blob: ac83c9a107b8d14ff6daf7c8c747fbf1e5db279b [file] [log] [blame]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001/*
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002 * Copyright (c) 2015-2020, Renesas Electronics Corporation.
Marek Vasut6ad74c32019-08-08 16:34:22 +02003 * All rights reserved.
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <stdint.h>
9#include <string.h>
10#include <stdio.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
12#include <common/debug.h>
13#include <lib/mmio.h>
14
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020015#include "ddr_regdef.h"
16#include "init_dram_tbl_h3.h"
17#include "init_dram_tbl_m3.h"
18#include "init_dram_tbl_h3ver2.h"
19#include "init_dram_tbl_m3n.h"
20#include "boot_init_dram_regdef.h"
21#include "boot_init_dram.h"
22#include "dram_sub_func.h"
23#include "micro_delay.h"
Marek Vasutd97f6ee2019-08-06 18:58:38 +020024#include "rcar_def.h"
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020025
26#define DDR_BACKUPMODE
27#define FATAL_MSG(x) NOTICE(x)
28
Marek Vasut6a131772019-08-07 19:56:09 +020029/* variables */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020030#ifdef RCAR_DDR_FIXED_LSI_TYPE
31#ifndef RCAR_AUTO
32#define RCAR_AUTO 99
Marek Vasut38dc7562019-08-07 19:17:42 +020033#define RCAR_H3 0
34#define RCAR_M3 1
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020035#define RCAR_M3N 2
Marek Vasut38dc7562019-08-07 19:17:42 +020036#define RCAR_E3 3 /* NON */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020037#define RCAR_H3N 4
38
39#define RCAR_CUT_10 0
40#define RCAR_CUT_11 1
41#define RCAR_CUT_20 10
42#define RCAR_CUT_30 20
43#endif
44#ifndef RCAR_LSI
45#define RCAR_LSI RCAR_AUTO
46#endif
Marek Vasut38dc7562019-08-07 19:17:42 +020047
Marek Vasut80784f92019-08-07 19:02:26 +020048#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +020049static uint32_t prr_product;
50static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020051#else
Marek Vasut80784f92019-08-07 19:02:26 +020052#if (RCAR_LSI == RCAR_H3)
Marek Vasut38dc7562019-08-07 19:17:42 +020053static const uint32_t prr_product = PRR_PRODUCT_H3;
Marek Vasut80784f92019-08-07 19:02:26 +020054#elif(RCAR_LSI == RCAR_M3)
Marek Vasut38dc7562019-08-07 19:17:42 +020055static const uint32_t prr_product = PRR_PRODUCT_M3;
Marek Vasut80784f92019-08-07 19:02:26 +020056#elif(RCAR_LSI == RCAR_M3N)
Marek Vasut38dc7562019-08-07 19:17:42 +020057static const uint32_t prr_product = PRR_PRODUCT_M3N;
Marek Vasut80784f92019-08-07 19:02:26 +020058#elif(RCAR_LSI == RCAR_H3N)
Marek Vasut38dc7562019-08-07 19:17:42 +020059static const uint32_t prr_product = PRR_PRODUCT_H3;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020060#endif /* RCAR_LSI */
61
62#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +020063static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020064#else /* RCAR_LSI_CUT */
Marek Vasut80784f92019-08-07 19:02:26 +020065#if (RCAR_LSI_CUT == RCAR_CUT_10)
Marek Vasut38dc7562019-08-07 19:17:42 +020066static const uint32_t prr_cut = PRR_PRODUCT_10;
Marek Vasut80784f92019-08-07 19:02:26 +020067#elif(RCAR_LSI_CUT == RCAR_CUT_11)
Marek Vasut38dc7562019-08-07 19:17:42 +020068static const uint32_t prr_cut = PRR_PRODUCT_11;
Marek Vasut80784f92019-08-07 19:02:26 +020069#elif(RCAR_LSI_CUT == RCAR_CUT_20)
Marek Vasut38dc7562019-08-07 19:17:42 +020070static const uint32_t prr_cut = PRR_PRODUCT_20;
Marek Vasut80784f92019-08-07 19:02:26 +020071#elif(RCAR_LSI_CUT == RCAR_CUT_30)
Marek Vasut38dc7562019-08-07 19:17:42 +020072static const uint32_t prr_cut = PRR_PRODUCT_30;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020073#endif /* RCAR_LSI_CUT */
74#endif /* RCAR_LSI_CUT */
75#endif /* RCAR_AUTO_NON */
76#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +020077static uint32_t prr_product;
78static uint32_t prr_cut;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020079#endif /* RCAR_DDR_FIXED_LSI_TYPE */
80
Marek Vasut38dc7562019-08-07 19:17:42 +020081static const uint32_t *p_ddr_regdef_tbl;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020082static uint32_t brd_clk;
83static uint32_t brd_clkdiv;
84static uint32_t brd_clkdiva;
85static uint32_t ddr_mbps;
86static uint32_t ddr_mbpsdiv;
87static uint32_t ddr_tccd;
Marek Vasut6c245a52018-12-12 18:06:39 +010088static uint32_t ddr_phycaslice;
Marek Vasut38dc7562019-08-07 19:17:42 +020089static const struct _boardcnf *board_cnf;
Chiaki Fujii59263ee2019-05-17 10:45:02 +090090static uint32_t ddr_phyvalid;
91static uint32_t ddr_density[DRAM_CH_CNT][CS_CNT];
Marek Vasut6a131772019-08-07 19:56:09 +020092static uint32_t ch_have_this_cs[CS_CNT] __aligned(64);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +090093static uint32_t rdqdm_dly[DRAM_CH_CNT][CSAB_CNT][SLICE_CNT * 2][9];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020094static uint32_t max_density;
95static uint32_t ddr0800_mul;
96static uint32_t ddr_mul;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +020097static uint32_t DDR_PHY_SLICE_REGSET_OFS;
98static uint32_t DDR_PHY_ADR_V_REGSET_OFS;
99static uint32_t DDR_PHY_ADR_I_REGSET_OFS;
100static uint32_t DDR_PHY_ADR_G_REGSET_OFS;
101static uint32_t DDR_PI_REGSET_OFS;
102static uint32_t DDR_PHY_SLICE_REGSET_SIZE;
103static uint32_t DDR_PHY_ADR_V_REGSET_SIZE;
104static uint32_t DDR_PHY_ADR_I_REGSET_SIZE;
105static uint32_t DDR_PHY_ADR_G_REGSET_SIZE;
106static uint32_t DDR_PI_REGSET_SIZE;
107static uint32_t DDR_PHY_SLICE_REGSET_NUM;
108static uint32_t DDR_PHY_ADR_V_REGSET_NUM;
109static uint32_t DDR_PHY_ADR_I_REGSET_NUM;
110static uint32_t DDR_PHY_ADR_G_REGSET_NUM;
111static uint32_t DDR_PI_REGSET_NUM;
112static uint32_t DDR_PHY_ADR_I_NUM;
113#define DDR_PHY_REGSET_MAX 128
114#define DDR_PI_REGSET_MAX 320
115static uint32_t _cnf_DDR_PHY_SLICE_REGSET[DDR_PHY_REGSET_MAX];
116static uint32_t _cnf_DDR_PHY_ADR_V_REGSET[DDR_PHY_REGSET_MAX];
117static uint32_t _cnf_DDR_PHY_ADR_I_REGSET[DDR_PHY_REGSET_MAX];
118static uint32_t _cnf_DDR_PHY_ADR_G_REGSET[DDR_PHY_REGSET_MAX];
119static uint32_t _cnf_DDR_PI_REGSET[DDR_PI_REGSET_MAX];
Marek Vasut38dc7562019-08-07 19:17:42 +0200120static uint32_t pll3_mode;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200121static uint32_t loop_max;
122#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +0200123uint32_t ddr_backup;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200124/* #define DDR_BACKUPMODE_HALF //for Half channel(ch0,1 only) */
125#endif
126
127#ifdef ddr_qos_init_setting /* only for non qos_init */
128#define OPERATING_FREQ (400U) /* Mhz */
129#define BASE_SUB_SLOT_NUM (0x6U)
130#define SUB_SLOT_CYCLE (0x7EU) /* 126 */
Marek Vasut6a131772019-08-07 19:56:09 +0200131#define QOSWT_WTSET0_CYCLE \
132 ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / \
133 OPERATING_FREQ) /* unit:ns */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200134
135uint32_t get_refperiod(void)
136{
137 return QOSWT_WTSET0_CYCLE;
138}
139#else /* ddr_qos_init_setting // only for non qos_init */
140extern uint32_t get_refperiod(void);
141#endif /* ddr_qos_init_setting // only for non qos_init */
142
143#define _reg_PHY_RX_CAL_X_NUM 11
144static const uint32_t _reg_PHY_RX_CAL_X[_reg_PHY_RX_CAL_X_NUM] = {
145 _reg_PHY_RX_CAL_DQ0,
146 _reg_PHY_RX_CAL_DQ1,
147 _reg_PHY_RX_CAL_DQ2,
148 _reg_PHY_RX_CAL_DQ3,
149 _reg_PHY_RX_CAL_DQ4,
150 _reg_PHY_RX_CAL_DQ5,
151 _reg_PHY_RX_CAL_DQ6,
152 _reg_PHY_RX_CAL_DQ7,
153 _reg_PHY_RX_CAL_DM,
154 _reg_PHY_RX_CAL_DQS,
155 _reg_PHY_RX_CAL_FDBK
156};
157
158#define _reg_PHY_CLK_WRX_SLAVE_DELAY_NUM 10
Marek Vasut6ad74c32019-08-08 16:34:22 +0200159static const uint32_t _reg_PHY_CLK_WRX_SLAVE_DELAY
160 [_reg_PHY_CLK_WRX_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200161 _reg_PHY_CLK_WRDQ0_SLAVE_DELAY,
162 _reg_PHY_CLK_WRDQ1_SLAVE_DELAY,
163 _reg_PHY_CLK_WRDQ2_SLAVE_DELAY,
164 _reg_PHY_CLK_WRDQ3_SLAVE_DELAY,
165 _reg_PHY_CLK_WRDQ4_SLAVE_DELAY,
166 _reg_PHY_CLK_WRDQ5_SLAVE_DELAY,
167 _reg_PHY_CLK_WRDQ6_SLAVE_DELAY,
168 _reg_PHY_CLK_WRDQ7_SLAVE_DELAY,
169 _reg_PHY_CLK_WRDM_SLAVE_DELAY,
170 _reg_PHY_CLK_WRDQS_SLAVE_DELAY
171};
172
173#define _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM 9
Marek Vasut6ad74c32019-08-08 16:34:22 +0200174static const uint32_t _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY
175 [_reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200176 _reg_PHY_RDDQS_DQ0_FALL_SLAVE_DELAY,
177 _reg_PHY_RDDQS_DQ1_FALL_SLAVE_DELAY,
178 _reg_PHY_RDDQS_DQ2_FALL_SLAVE_DELAY,
179 _reg_PHY_RDDQS_DQ3_FALL_SLAVE_DELAY,
180 _reg_PHY_RDDQS_DQ4_FALL_SLAVE_DELAY,
181 _reg_PHY_RDDQS_DQ5_FALL_SLAVE_DELAY,
182 _reg_PHY_RDDQS_DQ6_FALL_SLAVE_DELAY,
183 _reg_PHY_RDDQS_DQ7_FALL_SLAVE_DELAY,
184 _reg_PHY_RDDQS_DM_FALL_SLAVE_DELAY
185};
186
187#define _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM 9
Marek Vasut6ad74c32019-08-08 16:34:22 +0200188static const uint32_t _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
189 [_reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200190 _reg_PHY_RDDQS_DQ0_RISE_SLAVE_DELAY,
191 _reg_PHY_RDDQS_DQ1_RISE_SLAVE_DELAY,
192 _reg_PHY_RDDQS_DQ2_RISE_SLAVE_DELAY,
193 _reg_PHY_RDDQS_DQ3_RISE_SLAVE_DELAY,
194 _reg_PHY_RDDQS_DQ4_RISE_SLAVE_DELAY,
195 _reg_PHY_RDDQS_DQ5_RISE_SLAVE_DELAY,
196 _reg_PHY_RDDQS_DQ6_RISE_SLAVE_DELAY,
197 _reg_PHY_RDDQS_DQ7_RISE_SLAVE_DELAY,
198 _reg_PHY_RDDQS_DM_RISE_SLAVE_DELAY
199};
200
201#define _reg_PHY_PAD_TERM_X_NUM 8
202static const uint32_t _reg_PHY_PAD_TERM_X[_reg_PHY_PAD_TERM_X_NUM] = {
203 _reg_PHY_PAD_FDBK_TERM,
204 _reg_PHY_PAD_DATA_TERM,
205 _reg_PHY_PAD_DQS_TERM,
206 _reg_PHY_PAD_ADDR_TERM,
207 _reg_PHY_PAD_CLK_TERM,
208 _reg_PHY_PAD_CKE_TERM,
209 _reg_PHY_PAD_RST_TERM,
210 _reg_PHY_PAD_CS_TERM
211};
212
213#define _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM 10
Marek Vasut6ad74c32019-08-08 16:34:22 +0200214static const uint32_t _reg_PHY_CLK_CACS_SLAVE_DELAY_X
215 [_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200216 _reg_PHY_ADR0_CLK_WR_SLAVE_DELAY,
217 _reg_PHY_ADR1_CLK_WR_SLAVE_DELAY,
218 _reg_PHY_ADR2_CLK_WR_SLAVE_DELAY,
219 _reg_PHY_ADR3_CLK_WR_SLAVE_DELAY,
220 _reg_PHY_ADR4_CLK_WR_SLAVE_DELAY,
221 _reg_PHY_ADR5_CLK_WR_SLAVE_DELAY,
222
223 _reg_PHY_GRP_SLAVE_DELAY_0,
224 _reg_PHY_GRP_SLAVE_DELAY_1,
225 _reg_PHY_GRP_SLAVE_DELAY_2,
226 _reg_PHY_GRP_SLAVE_DELAY_3
227};
228
Marek Vasut6a131772019-08-07 19:56:09 +0200229/* Prototypes */
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900230static inline uint32_t vch_nxt(uint32_t pos);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200231static void cpg_write_32(uint32_t a, uint32_t v);
232static void pll3_control(uint32_t high);
233static inline void dsb_sev(void);
234static void wait_dbcmd(void);
235static void send_dbcmd(uint32_t cmd);
236static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd);
237static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata);
238static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata);
239static inline uint32_t ddr_regdef(uint32_t _regdef);
240static inline uint32_t ddr_regdef_adr(uint32_t _regdef);
241static inline uint32_t ddr_regdef_lsb(uint32_t _regdef);
242static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef,
243 uint32_t val);
244static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef);
245static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val);
246static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val);
247static void ddr_setval_ach(uint32_t regdef, uint32_t val);
248static void ddr_setval_ach_as(uint32_t regdef, uint32_t val);
249static uint32_t ddr_getval(uint32_t ch, uint32_t regdef);
Marek Vasut80784f92019-08-07 19:02:26 +0200250static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p);
251static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p);
252static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size);
253static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val);
254static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200255static uint32_t ddrphy_regif_chk(void);
Marek Vasut80784f92019-08-07 19:02:26 +0200256static inline void ddrphy_regif_idle(void);
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +0100257static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200258 uint16_t cyc);
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +0100259static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv,
260 uint16_t *_js2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200261static int16_t _f_scale_adj(int16_t ps);
262static void ddrtbl_load(void);
263static void ddr_config_sub(void);
Marek Vasut80784f92019-08-07 19:02:26 +0200264static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200265static void ddr_config_sub_h3v1x(void);
266static void ddr_config(void);
267static void dbsc_regset(void);
268static void dbsc_regset_post(void);
269static uint32_t dfi_init_start(void);
270static void change_lpddr4_en(uint32_t mode);
271static uint32_t set_term_code(void);
Marek Vasut6c245a52018-12-12 18:06:39 +0100272static void ddr_register_set(void);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200273static inline uint32_t wait_freqchgreq(uint32_t assert);
274static inline void set_freqchgack(uint32_t assert);
275static inline void set_dfifrequency(uint32_t freq);
276static uint32_t pll3_freq(uint32_t on);
277static void update_dly(void);
278static uint32_t pi_training_go(void);
279static uint32_t init_ddr(void);
280static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200281static uint32_t wdqdm_man1(void);
282static uint32_t wdqdm_man(void);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200283static uint32_t rdqdm_man1(void);
284static uint32_t rdqdm_man(void);
285
286static int32_t _find_change(uint64_t val, uint32_t dir);
287static uint32_t _rx_offset_cal_updn(uint32_t code);
288static uint32_t rx_offset_cal(void);
289static uint32_t rx_offset_cal_hw(void);
290static void adjust_rddqs_latency(void);
291static void adjust_wpath_latency(void);
292
Marek Vasut38dc7562019-08-07 19:17:42 +0200293struct ddrt_data {
Marek Vasut6a131772019-08-07 19:56:09 +0200294 int32_t init_temp; /* Initial Temperature (do) */
295 uint32_t init_cal[4]; /* Initial io-code (4 is for H3) */
296 uint32_t tcomp_cal[4]; /* Temp. compensated io-code (4 is for H3) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200297};
Marek Vasut80784f92019-08-07 19:02:26 +0200298
Marek Vasut38dc7562019-08-07 19:17:42 +0200299static struct ddrt_data tcal;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200300
301static void pvtcode_update(void);
302static void pvtcode_update2(void);
303static void ddr_padcal_tcompensate_getinit(uint32_t override);
304
Marek Vasut6a131772019-08-07 19:56:09 +0200305/* load board configuration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200306#include "boot_init_dram_config.c"
307
Marek Vasut6c245a52018-12-12 18:06:39 +0100308#ifndef DDR_FAST_INIT
309static uint32_t rdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
310static uint32_t rdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
311static uint32_t rdqdm_nw[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9];
312static uint32_t rdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
313static uint32_t rdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2];
314static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn);
315static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn);
316
317static uint32_t wdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
318static uint32_t wdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
319static uint32_t wdqdm_dly[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9];
320static uint32_t wdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
321static uint32_t wdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT];
322static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn);
323static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn);
324#endif/* DDR_FAST_INIT */
325
Marek Vasut6a131772019-08-07 19:56:09 +0200326/* macro for channel selection loop */
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900327static inline uint32_t vch_nxt(uint32_t pos)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200328{
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900329 uint32_t posn;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200330
331 for (posn = pos; posn < DRAM_CH_CNT; posn++) {
332 if (ddr_phyvalid & (1U << posn))
333 break;
334 }
335 return posn;
336}
337
338#define foreach_vch(ch) \
Marek Vasut80784f92019-08-07 19:02:26 +0200339for (ch = vch_nxt(0); ch < DRAM_CH_CNT; ch = vch_nxt(ch + 1))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200340
341#define foreach_ech(ch) \
Marek Vasut80784f92019-08-07 19:02:26 +0200342for (ch = 0; ch < DRAM_CH_CNT; ch++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200343
Marek Vasut6a131772019-08-07 19:56:09 +0200344/* Printing functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200345#define MSG_LF(...)
346
Marek Vasut6a131772019-08-07 19:56:09 +0200347/* clock settings, reset control */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200348static void cpg_write_32(uint32_t a, uint32_t v)
349{
350 mmio_write_32(CPG_CPGWPR, ~v);
351 mmio_write_32(a, v);
352}
353
354static void pll3_control(uint32_t high)
355{
Marek Vasut38dc7562019-08-07 19:17:42 +0200356 uint32_t data_l, data_div, data_mul, tmp_div;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200357
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200358 if (high) {
Marek Vasut38dc7562019-08-07 19:17:42 +0200359 tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) /
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900360 (brd_clk * ddr_mul) / 2;
Chiaki Fujiifd1ec702019-07-08 23:44:56 +0900361 data_mul = ((ddr_mul * tmp_div) - 1) << 24;
Marek Vasut38dc7562019-08-07 19:17:42 +0200362 pll3_mode = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200363 loop_max = 2;
364 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +0200365 tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) /
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900366 (brd_clk * ddr0800_mul) / 2;
Chiaki Fujiifd1ec702019-07-08 23:44:56 +0900367 data_mul = ((ddr0800_mul * tmp_div) - 1) << 24;
Marek Vasut38dc7562019-08-07 19:17:42 +0200368 pll3_mode = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200369 loop_max = 8;
370 }
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900371
Marek Vasut38dc7562019-08-07 19:17:42 +0200372 switch (tmp_div) {
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900373 case 1:
Marek Vasut38dc7562019-08-07 19:17:42 +0200374 data_div = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900375 break;
376 case 2:
377 case 3:
378 case 4:
Marek Vasut38dc7562019-08-07 19:17:42 +0200379 data_div = tmp_div;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900380 break;
381 default:
Marek Vasut38dc7562019-08-07 19:17:42 +0200382 data_div = 6;
383 data_mul = (data_mul * tmp_div) / 3;
Chiaki Fujii59263ee2019-05-17 10:45:02 +0900384 break;
Marek Vasut6c245a52018-12-12 18:06:39 +0100385 }
Marek Vasut38dc7562019-08-07 19:17:42 +0200386 data_mul = data_mul | (brd_clkdiva << 7);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200387
Marek Vasut6c245a52018-12-12 18:06:39 +0100388 /* PLL3 disable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200389 data_l = mmio_read_32(CPG_PLLECR) & ~CPG_PLLECR_PLL3E_BIT;
390 cpg_write_32(CPG_PLLECR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200391 dsb_sev();
392
Marek Vasut38dc7562019-08-07 19:17:42 +0200393 if ((prr_product == PRR_PRODUCT_M3) ||
394 ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_20))) {
Marek Vasut6c245a52018-12-12 18:06:39 +0100395 /* PLL3 DIV resetting(Lowest value:3) */
Marek Vasut38dc7562019-08-07 19:17:42 +0200396 data_l = 0x00030003 | (0xFF80FF80 & mmio_read_32(CPG_FRQCRD));
397 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100398 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200399
Marek Vasut6c245a52018-12-12 18:06:39 +0100400 /* zb3 clk stop */
Marek Vasut38dc7562019-08-07 19:17:42 +0200401 data_l = CPG_ZB3CKCR_ZB3ST_BIT | mmio_read_32(CPG_ZB3CKCR);
402 cpg_write_32(CPG_ZB3CKCR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100403 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200404
Marek Vasut6c245a52018-12-12 18:06:39 +0100405 /* PLL3 enable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200406 data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR);
407 cpg_write_32(CPG_PLLECR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100408 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200409
Marek Vasut6c245a52018-12-12 18:06:39 +0100410 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200411 data_l = mmio_read_32(CPG_PLLECR);
412 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100413 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200414
Marek Vasut6c245a52018-12-12 18:06:39 +0100415 /* PLL3 DIV resetting (Highest value:0) */
Marek Vasut38dc7562019-08-07 19:17:42 +0200416 data_l = (0xFF80FF80 & mmio_read_32(CPG_FRQCRD));
417 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100418 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200419
Marek Vasut6c245a52018-12-12 18:06:39 +0100420 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200421 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
422 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100423 dsb_sev();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200424
Marek Vasut6c245a52018-12-12 18:06:39 +0100425 /* PLL3 multiplie set */
Marek Vasut38dc7562019-08-07 19:17:42 +0200426 cpg_write_32(CPG_PLL3CR, data_mul);
Marek Vasut6c245a52018-12-12 18:06:39 +0100427 dsb_sev();
428
429 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200430 data_l = mmio_read_32(CPG_PLLECR);
431 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100432 dsb_sev();
433
434 /* PLL3 DIV resetting(Target value) */
Marek Vasut6a131772019-08-07 19:56:09 +0200435 data_l = (data_div << 16) | data_div |
436 (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80);
Marek Vasut38dc7562019-08-07 19:17:42 +0200437 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100438 dsb_sev();
439
440 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200441 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
442 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100443 dsb_sev();
444
445 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200446 data_l = mmio_read_32(CPG_PLLECR);
447 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100448 dsb_sev();
449
450 /* zb3 clk start */
Marek Vasut38dc7562019-08-07 19:17:42 +0200451 data_l = (~CPG_ZB3CKCR_ZB3ST_BIT) & mmio_read_32(CPG_ZB3CKCR);
452 cpg_write_32(CPG_ZB3CKCR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100453 dsb_sev();
454
455 } else { /* H3Ver.3.0/M3N/V3H */
456
457 /* PLL3 multiplie set */
Marek Vasut38dc7562019-08-07 19:17:42 +0200458 cpg_write_32(CPG_PLL3CR, data_mul);
Marek Vasut6c245a52018-12-12 18:06:39 +0100459 dsb_sev();
460
461 /* PLL3 DIV set(Target value) */
Marek Vasut6a131772019-08-07 19:56:09 +0200462 data_l = (data_div << 16) | data_div |
463 (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80);
Marek Vasut38dc7562019-08-07 19:17:42 +0200464 cpg_write_32(CPG_FRQCRD, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100465
466 /* DIV SET KICK */
Marek Vasut38dc7562019-08-07 19:17:42 +0200467 data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB);
468 cpg_write_32(CPG_FRQCRB, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100469 dsb_sev();
470
471 /* PLL3 enable */
Marek Vasut38dc7562019-08-07 19:17:42 +0200472 data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR);
473 cpg_write_32(CPG_PLLECR, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +0100474 dsb_sev();
475
476 do {
Marek Vasut38dc7562019-08-07 19:17:42 +0200477 data_l = mmio_read_32(CPG_PLLECR);
478 } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0);
Marek Vasut6c245a52018-12-12 18:06:39 +0100479 dsb_sev();
480 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200481}
482
Marek Vasut6a131772019-08-07 19:56:09 +0200483/* barrier */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200484static inline void dsb_sev(void)
485{
486 __asm__ __volatile__("dsb sy");
487}
488
Marek Vasut6a131772019-08-07 19:56:09 +0200489/* DDR memory register access */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200490static void wait_dbcmd(void)
491{
Marek Vasut38dc7562019-08-07 19:17:42 +0200492 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200493 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +0200494 data_l = mmio_read_32(DBSC_DBCMD);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200495 dsb_sev();
496 while (1) {
497 /* wait DBCMD 1=busy, 0=ready */
Marek Vasut38dc7562019-08-07 19:17:42 +0200498 data_l = mmio_read_32(DBSC_DBWAIT);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200499 dsb_sev();
Marek Vasut38dc7562019-08-07 19:17:42 +0200500 if ((data_l & 0x00000001) == 0x00)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200501 break;
502 }
503}
504
505static void send_dbcmd(uint32_t cmd)
506{
507 /* dummy read */
508 wait_dbcmd();
509 mmio_write_32(DBSC_DBCMD, cmd);
510 dsb_sev();
511}
512
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900513static void dbwait_loop(uint32_t wait_loop)
514{
515 uint32_t i;
516
517 for (i = 0; i < wait_loop; i++)
518 wait_dbcmd();
519}
520
Marek Vasut6a131772019-08-07 19:56:09 +0200521/* DDRPHY register access (raw) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200522static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd)
523{
524 uint32_t val;
525 uint32_t loop;
526
527 val = 0;
Marek Vasut6a131772019-08-07 19:56:09 +0200528 if ((prr_product != PRR_PRODUCT_M3N) &&
529 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200530 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
531 dsb_sev();
532
533 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
534 dsb_sev();
535 }
536 dsb_sev();
537
538 for (loop = 0; loop < loop_max; loop++) {
539 val = mmio_read_32(DBSC_DBPDRGD(phyno));
540 dsb_sev();
541 }
542 (void)val;
543 } else {
544 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00004000);
545 dsb_sev();
546 while (mmio_read_32(DBSC_DBPDRGA(phyno)) !=
547 (regadd | 0x0000C000)) {
548 dsb_sev();
549 };
550 val = mmio_read_32(DBSC_DBPDRGA(phyno));
551 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
552 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
553 dsb_sev();
554 };
555 dsb_sev();
556
557 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
558 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
559 dsb_sev();
560 };
561
562 dsb_sev();
563 val = mmio_read_32(DBSC_DBPDRGD(phyno));
564 dsb_sev();
565 (void)val;
566 }
567 return val;
568}
569
570static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata)
571{
572 uint32_t val;
573 uint32_t loop;
574
Marek Vasut6a131772019-08-07 19:56:09 +0200575 if ((prr_product != PRR_PRODUCT_M3N) &&
576 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200577 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
578 dsb_sev();
579 for (loop = 0; loop < loop_max; loop++) {
580 val = mmio_read_32(DBSC_DBPDRGA(phyno));
581 dsb_sev();
582 }
583 mmio_write_32(DBSC_DBPDRGD(phyno), regdata);
584 dsb_sev();
585
586 for (loop = 0; loop < loop_max; loop++) {
587 val = mmio_read_32(DBSC_DBPDRGD(phyno));
588 dsb_sev();
589 }
590 } else {
591 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
592 dsb_sev();
593
594 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
595 dsb_sev();
596 };
597 dsb_sev();
598
599 mmio_write_32(DBSC_DBPDRGD(phyno), regdata);
600 dsb_sev();
601
602 while (mmio_read_32(DBSC_DBPDRGA(phyno)) !=
603 (regadd | 0x00008000)) {
604 dsb_sev();
605 };
606 mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000);
607
608 while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) {
609 dsb_sev();
610 };
611 dsb_sev();
612
613 mmio_write_32(DBSC_DBPDRGA(phyno), regadd);
614 }
615 (void)val;
616}
617
618static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata)
619{
620 uint32_t ch;
621 uint32_t val;
622 uint32_t loop;
623
Marek Vasut6a131772019-08-07 19:56:09 +0200624 if ((prr_product != PRR_PRODUCT_M3N) &&
625 (prr_product != PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200626 foreach_vch(ch) {
627 mmio_write_32(DBSC_DBPDRGA(ch), regadd);
628 dsb_sev();
629 }
630
631 foreach_vch(ch) {
632 mmio_write_32(DBSC_DBPDRGD(ch), regdata);
633 dsb_sev();
634 }
635
636 for (loop = 0; loop < loop_max; loop++) {
637 val = mmio_read_32(DBSC_DBPDRGD(0));
638 dsb_sev();
639 }
640 (void)val;
641 } else {
642 foreach_vch(ch) {
643 reg_ddrphy_write(ch, regadd, regdata);
644 dsb_sev();
645 }
646 }
647}
648
Marek Vasut80784f92019-08-07 19:02:26 +0200649static inline void ddrphy_regif_idle(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200650{
651 uint32_t val;
652
653 val = reg_ddrphy_read(0, ddr_regdef_adr(_reg_PI_INT_STATUS));
654 dsb_sev();
655 (void)val;
656}
657
Marek Vasut6a131772019-08-07 19:56:09 +0200658/* DDRPHY register access (field modify) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200659static inline uint32_t ddr_regdef(uint32_t _regdef)
660{
Marek Vasut38dc7562019-08-07 19:17:42 +0200661 return p_ddr_regdef_tbl[_regdef];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200662}
663
664static inline uint32_t ddr_regdef_adr(uint32_t _regdef)
665{
Marek Vasut38dc7562019-08-07 19:17:42 +0200666 return DDR_REGDEF_ADR(p_ddr_regdef_tbl[_regdef]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200667}
668
669static inline uint32_t ddr_regdef_lsb(uint32_t _regdef)
670{
Marek Vasut38dc7562019-08-07 19:17:42 +0200671 return DDR_REGDEF_LSB(p_ddr_regdef_tbl[_regdef]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200672}
673
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200674static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef,
675 uint32_t val)
676{
677 uint32_t adr;
678 uint32_t lsb;
679 uint32_t len;
680 uint32_t msk;
681 uint32_t tmp;
682 uint32_t regdef;
683
684 regdef = ddr_regdef(_regdef);
685 adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice;
686 len = DDR_REGDEF_LEN(regdef);
687 lsb = DDR_REGDEF_LSB(regdef);
688 if (len == 0x20)
689 msk = 0xffffffff;
690 else
691 msk = ((1U << len) - 1) << lsb;
692
693 tmp = reg_ddrphy_read(ch, adr);
694 tmp = (tmp & (~msk)) | ((val << lsb) & msk);
695 reg_ddrphy_write(ch, adr, tmp);
696}
697
698static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef)
699{
700 uint32_t adr;
701 uint32_t lsb;
702 uint32_t len;
703 uint32_t msk;
704 uint32_t tmp;
705 uint32_t regdef;
706
707 regdef = ddr_regdef(_regdef);
708 adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice;
709 len = DDR_REGDEF_LEN(regdef);
710 lsb = DDR_REGDEF_LSB(regdef);
711 if (len == 0x20)
712 msk = 0xffffffff;
713 else
714 msk = ((1U << len) - 1);
715
716 tmp = reg_ddrphy_read(ch, adr);
717 tmp = (tmp >> lsb) & msk;
718
719 return tmp;
720}
721
722static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val)
723{
724 ddr_setval_s(ch, 0, regdef, val);
725}
726
727static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val)
728{
729 uint32_t ch;
730
731 foreach_vch(ch)
732 ddr_setval_s(ch, slice, regdef, val);
733}
734
735static void ddr_setval_ach(uint32_t regdef, uint32_t val)
736{
737 ddr_setval_ach_s(0, regdef, val);
738}
739
740static void ddr_setval_ach_as(uint32_t regdef, uint32_t val)
741{
742 uint32_t slice;
743
744 for (slice = 0; slice < SLICE_CNT; slice++)
745 ddr_setval_ach_s(slice, regdef, val);
746}
747
748static uint32_t ddr_getval(uint32_t ch, uint32_t regdef)
749{
750 return ddr_getval_s(ch, 0, regdef);
751}
752
Marek Vasut80784f92019-08-07 19:02:26 +0200753static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200754{
755 uint32_t ch;
756
757 foreach_vch(ch)
758 p[ch] = ddr_getval_s(ch, 0, regdef);
759 return p[0];
760}
761
Marek Vasut80784f92019-08-07 19:02:26 +0200762static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200763{
764 uint32_t ch, slice;
765 uint32_t *pp;
766
767 pp = p;
768 foreach_vch(ch)
Marek Vasut6ad74c32019-08-08 16:34:22 +0200769 for (slice = 0; slice < SLICE_CNT; slice++)
770 *pp++ = ddr_getval_s(ch, slice, regdef);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200771 return p[0];
772}
773
Marek Vasut6a131772019-08-07 19:56:09 +0200774/* handling functions for setteing ddrphy value table */
Marek Vasut80784f92019-08-07 19:02:26 +0200775static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200776{
777 uint32_t i;
778
779 for (i = 0; i < size; i++) {
780 to[i] = from[i];
781 }
782}
783
Marek Vasut80784f92019-08-07 19:02:26 +0200784static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200785{
786 uint32_t adr;
787 uint32_t lsb;
788 uint32_t len;
789 uint32_t msk;
790 uint32_t tmp;
791 uint32_t adrmsk;
792 uint32_t regdef;
793
794 regdef = ddr_regdef(_regdef);
795 adr = DDR_REGDEF_ADR(regdef);
796 len = DDR_REGDEF_LEN(regdef);
797 lsb = DDR_REGDEF_LSB(regdef);
798 if (len == 0x20)
799 msk = 0xffffffff;
800 else
801 msk = ((1U << len) - 1) << lsb;
802
803 if (adr < 0x400) {
804 adrmsk = 0xff;
805 } else {
806 adrmsk = 0x7f;
807 }
808
809 tmp = tbl[adr & adrmsk];
810 tmp = (tmp & (~msk)) | ((val << lsb) & msk);
811 tbl[adr & adrmsk] = tmp;
812}
813
Marek Vasut80784f92019-08-07 19:02:26 +0200814static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200815{
816 uint32_t adr;
817 uint32_t lsb;
818 uint32_t len;
819 uint32_t msk;
820 uint32_t tmp;
821 uint32_t adrmsk;
822 uint32_t regdef;
823
824 regdef = ddr_regdef(_regdef);
825 adr = DDR_REGDEF_ADR(regdef);
826 len = DDR_REGDEF_LEN(regdef);
827 lsb = DDR_REGDEF_LSB(regdef);
828 if (len == 0x20)
829 msk = 0xffffffff;
830 else
831 msk = ((1U << len) - 1);
832
833 if (adr < 0x400) {
834 adrmsk = 0xff;
835 } else {
836 adrmsk = 0x7f;
837 }
838
839 tmp = tbl[adr & adrmsk];
840 tmp = (tmp >> lsb) & msk;
841
842 return tmp;
843}
844
Marek Vasut6a131772019-08-07 19:56:09 +0200845/* DDRPHY register access handling */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200846static uint32_t ddrphy_regif_chk(void)
847{
848 uint32_t tmp_ach[DRAM_CH_CNT];
849 uint32_t ch;
850 uint32_t err;
851 uint32_t PI_VERSION_CODE;
852
Marek Vasut6a131772019-08-07 19:56:09 +0200853 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
854 (prr_product == PRR_PRODUCT_M3)) {
855 PI_VERSION_CODE = 0x2041; /* H3 Ver.1.x/M3-W */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200856 } else {
Marek Vasut6a131772019-08-07 19:56:09 +0200857 PI_VERSION_CODE = 0x2040; /* H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200858 }
859
Marek Vasut80784f92019-08-07 19:02:26 +0200860 ddr_getval_ach(_reg_PI_VERSION, (uint32_t *)tmp_ach);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200861 err = 0;
862 foreach_vch(ch) {
Marek Vasut80784f92019-08-07 19:02:26 +0200863 if (tmp_ach[ch] != PI_VERSION_CODE)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200864 err = 1;
865 }
866 return err;
867}
868
Marek Vasut6a131772019-08-07 19:56:09 +0200869/* functions and parameters for timing setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200870struct _jedec_spec1 {
871 uint16_t fx3;
Marek Vasut38dc7562019-08-07 19:17:42 +0200872 uint8_t rlwodbi;
873 uint8_t rlwdbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200874 uint8_t WL;
Marek Vasut38dc7562019-08-07 19:17:42 +0200875 uint8_t nwr;
876 uint8_t nrtp;
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900877 uint8_t odtlon;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200878 uint8_t MR1;
879 uint8_t MR2;
880};
Marek Vasut80784f92019-08-07 19:02:26 +0200881
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200882#define JS1_USABLEC_SPEC_LO 2
883#define JS1_USABLEC_SPEC_HI 5
884#define JS1_FREQ_TBL_NUM 8
Marek Vasut80784f92019-08-07 19:02:26 +0200885#define JS1_MR1(f) (0x04 | ((f) << 4))
886#define JS1_MR2(f) (0x00 | ((f) << 3) | (f))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200887const struct _jedec_spec1 js1[JS1_FREQ_TBL_NUM] = {
Marek Vasut6ad74c32019-08-08 16:34:22 +0200888 /* 533.333Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900889 { 800, 6, 6, 4, 6, 8, 0, JS1_MR1(0), JS1_MR2(0) | 0x40 },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200890 /* 1066.666Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900891 { 1600, 10, 12, 8, 10, 8, 0, JS1_MR1(1), JS1_MR2(1) | 0x40 },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200892 /* 1600.000Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900893 { 2400, 14, 16, 12, 16, 8, 6, JS1_MR1(2), JS1_MR2(2) | 0x40 },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200894 /* 2133.333Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900895 { 3200, 20, 22, 10, 20, 8, 4, JS1_MR1(3), JS1_MR2(3) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200896 /* 2666.666Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900897 { 4000, 24, 28, 12, 24, 10, 4, JS1_MR1(4), JS1_MR2(4) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200898 /* 3200.000Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900899 { 4800, 28, 32, 14, 30, 12, 6, JS1_MR1(5), JS1_MR2(5) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200900 /* 3733.333Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900901 { 5600, 32, 36, 16, 34, 14, 6, JS1_MR1(6), JS1_MR2(6) },
Marek Vasut6ad74c32019-08-08 16:34:22 +0200902 /* 4266.666Mbps */
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900903 { 6400, 36, 40, 18, 40, 16, 8, JS1_MR1(7), JS1_MR2(7) }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200904};
905
906struct _jedec_spec2 {
907 uint16_t ps;
908 uint16_t cyc;
909};
910
Marek Vasut38dc7562019-08-07 19:17:42 +0200911#define js2_tsr 0
912#define js2_txp 1
913#define js2_trtp 2
914#define js2_trcd 3
915#define js2_trppb 4
916#define js2_trpab 5
917#define js2_tras 6
918#define js2_twr 7
919#define js2_twtr 8
920#define js2_trrd 9
921#define js2_tppd 10
922#define js2_tfaw 11
923#define js2_tdqsck 12
924#define js2_tckehcmd 13
925#define js2_tckelcmd 14
926#define js2_tckelpd 15
927#define js2_tmrr 16
928#define js2_tmrw 17
929#define js2_tmrd 18
930#define js2_tzqcalns 19
931#define js2_tzqlat 20
932#define js2_tiedly 21
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900933#define js2_tODTon_min 22
934#define JS2_TBLCNT 23
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200935
Marek Vasut38dc7562019-08-07 19:17:42 +0200936#define js2_trcpb (JS2_TBLCNT)
937#define js2_trcab (JS2_TBLCNT + 1)
938#define js2_trfcab (JS2_TBLCNT + 2)
Marek Vasut80784f92019-08-07 19:02:26 +0200939#define JS2_CNT (JS2_TBLCNT + 3)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200940
941#ifndef JS2_DERATE
942#define JS2_DERATE 0
943#endif
944const struct _jedec_spec2 jedec_spec2[2][JS2_TBLCNT] = {
945 {
946/*tSR */ {15000, 3},
947/*tXP */ {7500, 3},
948/*tRTP */ {7500, 8},
949/*tRCD */ {18000, 4},
950/*tRPpb */ {18000, 3},
951/*tRPab */ {21000, 3},
952/*tRAS */ {42000, 3},
953/*tWR */ {18000, 4},
954/*tWTR */ {10000, 8},
955/*tRRD */ {10000, 4},
956/*tPPD */ {0, 0},
957/*tFAW */ {40000, 0},
958/*tDQSCK*/ {3500, 0},
959/*tCKEHCMD*/ {7500, 3},
960/*tCKELCMD*/ {7500, 3},
961/*tCKELPD*/ {7500, 3},
962/*tMRR*/ {0, 8},
963/*tMRW*/ {10000, 10},
964/*tMRD*/ {14000, 10},
965/*tZQCALns*/ {1000 * 10, 0},
966/*tZQLAT*/ {30000, 10},
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900967/*tIEdly*/ {12500, 0},
968/*tODTon_min*/ {1500, 0}
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200969 }, {
970/*tSR */ {15000, 3},
971/*tXP */ {7500, 3},
972/*tRTP */ {7500, 8},
973/*tRCD */ {19875, 4},
974/*tRPpb */ {19875, 3},
975/*tRPab */ {22875, 3},
976/*tRAS */ {43875, 3},
977/*tWR */ {18000, 4},
978/*tWTR */ {10000, 8},
979/*tRRD */ {11875, 4},
980/*tPPD */ {0, 0},
981/*tFAW */ {40000, 0},
982/*tDQSCK*/ {3600, 0},
983/*tCKEHCMD*/ {7500, 3},
984/*tCKELCMD*/ {7500, 3},
985/*tCKELPD*/ {7500, 3},
986/*tMRR*/ {0, 8},
987/*tMRW*/ {10000, 10},
988/*tMRD*/ {14000, 10},
989/*tZQCALns*/ {1000 * 10, 0},
990/*tZQLAT*/ {30000, 10},
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +0900991/*tIEdly*/ {12500, 0},
992/*tODTon_min*/ {1500, 0}
Marek Vasut80784f92019-08-07 19:02:26 +0200993 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200994};
995
Marek Vasut38dc7562019-08-07 19:17:42 +0200996const uint16_t jedec_spec2_trfc_ab[7] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200997/* 4Gb, 6Gb, 8Gb,12Gb, 16Gb, 24Gb(non), 32Gb(non) */
Marek Vasut6c245a52018-12-12 18:06:39 +0100998 130, 180, 180, 280, 280, 560, 560
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +0200999};
1000
1001static uint32_t js1_ind;
1002static uint16_t js2[JS2_CNT];
1003static uint8_t RL;
1004static uint8_t WL;
1005
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001006static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001007 uint16_t cyc)
1008{
1009 uint32_t tmp;
1010 uint32_t div;
1011
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001012 tmp = (((uint32_t)(ps) + 9) / 10) * _ddr_mbps;
1013 div = tmp / (200000 * _ddr_mbpsdiv);
1014 if (tmp != (div * 200000 * _ddr_mbpsdiv))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001015 div = div + 1;
1016
1017 if (div > cyc)
Marek Vasut80784f92019-08-07 19:02:26 +02001018 return (uint16_t)div;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001019 return cyc;
1020}
1021
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001022static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv,
1023 uint16_t *_js2)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001024{
1025 int i;
1026
1027 for (i = 0; i < JS2_TBLCNT; i++) {
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001028 _js2[i] = _f_scale(_ddr_mbps, _ddr_mbpsdiv,
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001029 1UL * jedec_spec2[JS2_DERATE][i].ps,
1030 jedec_spec2[JS2_DERATE][i].cyc);
1031 }
1032
Justin Chadwell7d0e3ba2019-09-17 15:21:50 +01001033 _js2[js2_trcpb] = _js2[js2_tras] + _js2[js2_trppb];
1034 _js2[js2_trcab] = _js2[js2_tras] + _js2[js2_trpab];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001035}
1036
1037/* scaler for DELAY value */
1038static int16_t _f_scale_adj(int16_t ps)
1039{
1040 int32_t tmp;
1041 /*
Marek Vasut6a131772019-08-07 19:56:09 +02001042 * tmp = (int32_t)512 * ps * ddr_mbps /2 / ddr_mbpsdiv / 1000 / 1000;
1043 * = ps * ddr_mbps /2 / ddr_mbpsdiv *512 / 8 / 8 / 125 / 125
1044 * = ps * ddr_mbps / ddr_mbpsdiv *4 / 125 / 125
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001045 */
1046 tmp =
Marek Vasut80784f92019-08-07 19:02:26 +02001047 (int32_t)4 * (int32_t)ps * (int32_t)ddr_mbps /
1048 (int32_t)ddr_mbpsdiv;
1049 tmp = (int32_t)tmp / (int32_t)15625;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001050
Marek Vasut80784f92019-08-07 19:02:26 +02001051 return (int16_t)tmp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001052}
1053
Marek Vasut38dc7562019-08-07 19:17:42 +02001054static const uint32_t reg_pi_mr1_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001055 {
1056 _reg_PI_MR1_DATA_F0_0,
1057 _reg_PI_MR1_DATA_F0_1,
1058 _reg_PI_MR1_DATA_F0_2,
1059 _reg_PI_MR1_DATA_F0_3},
1060 {
1061 _reg_PI_MR1_DATA_F1_0,
1062 _reg_PI_MR1_DATA_F1_1,
1063 _reg_PI_MR1_DATA_F1_2,
1064 _reg_PI_MR1_DATA_F1_3}
1065};
1066
Marek Vasut38dc7562019-08-07 19:17:42 +02001067static const uint32_t reg_pi_mr2_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001068 {
1069 _reg_PI_MR2_DATA_F0_0,
1070 _reg_PI_MR2_DATA_F0_1,
1071 _reg_PI_MR2_DATA_F0_2,
1072 _reg_PI_MR2_DATA_F0_3},
1073 {
1074 _reg_PI_MR2_DATA_F1_0,
1075 _reg_PI_MR2_DATA_F1_1,
1076 _reg_PI_MR2_DATA_F1_2,
1077 _reg_PI_MR2_DATA_F1_3}
1078};
1079
Marek Vasut38dc7562019-08-07 19:17:42 +02001080static const uint32_t reg_pi_mr3_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001081 {
1082 _reg_PI_MR3_DATA_F0_0,
1083 _reg_PI_MR3_DATA_F0_1,
1084 _reg_PI_MR3_DATA_F0_2,
1085 _reg_PI_MR3_DATA_F0_3},
1086 {
1087 _reg_PI_MR3_DATA_F1_0,
1088 _reg_PI_MR3_DATA_F1_1,
1089 _reg_PI_MR3_DATA_F1_2,
1090 _reg_PI_MR3_DATA_F1_3}
1091};
1092
Marek Vasut38dc7562019-08-07 19:17:42 +02001093const uint32_t reg_pi_mr11_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001094 {
1095 _reg_PI_MR11_DATA_F0_0,
1096 _reg_PI_MR11_DATA_F0_1,
1097 _reg_PI_MR11_DATA_F0_2,
1098 _reg_PI_MR11_DATA_F0_3},
1099 {
1100 _reg_PI_MR11_DATA_F1_0,
1101 _reg_PI_MR11_DATA_F1_1,
1102 _reg_PI_MR11_DATA_F1_2,
1103 _reg_PI_MR11_DATA_F1_3}
1104};
1105
Marek Vasut38dc7562019-08-07 19:17:42 +02001106const uint32_t reg_pi_mr12_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001107 {
1108 _reg_PI_MR12_DATA_F0_0,
1109 _reg_PI_MR12_DATA_F0_1,
1110 _reg_PI_MR12_DATA_F0_2,
1111 _reg_PI_MR12_DATA_F0_3},
1112 {
1113 _reg_PI_MR12_DATA_F1_0,
1114 _reg_PI_MR12_DATA_F1_1,
1115 _reg_PI_MR12_DATA_F1_2,
1116 _reg_PI_MR12_DATA_F1_3}
1117};
1118
Marek Vasut38dc7562019-08-07 19:17:42 +02001119const uint32_t reg_pi_mr14_data_fx_csx[2][CSAB_CNT] = {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001120 {
1121 _reg_PI_MR14_DATA_F0_0,
1122 _reg_PI_MR14_DATA_F0_1,
1123 _reg_PI_MR14_DATA_F0_2,
1124 _reg_PI_MR14_DATA_F0_3},
1125 {
1126 _reg_PI_MR14_DATA_F1_0,
1127 _reg_PI_MR14_DATA_F1_1,
1128 _reg_PI_MR14_DATA_F1_2,
1129 _reg_PI_MR14_DATA_F1_3}
1130};
1131
Marek Vasut6a131772019-08-07 19:56:09 +02001132/*
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001133 * regif pll w/a ( REGIF H3 Ver.2.0 or later/M3-N/V3H WA )
Marek Vasut6a131772019-08-07 19:56:09 +02001134 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001135static void regif_pll_wa(void)
1136{
1137 uint32_t ch;
1138
Marek Vasut38dc7562019-08-07 19:17:42 +02001139 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001140 // PLL setting for PHY : H3 Ver.1.x
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001141 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT),
1142 (0x0064U <<
1143 ddr_regdef_lsb(_reg_PHY_PLL_WAIT)));
1144 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL),
1145 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1146 _reg_PHY_PLL_CTRL));
1147
1148 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL),
1149 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1150 _reg_PHY_LP4_BOOT_PLL_CTRL));
1151
1152 } else {
1153 /* PLL setting for PHY : M3-W/M3-N/V3H/H3 Ver.2.0 or later */
1154 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT),
1155 (0x5064U <<
1156 ddr_regdef_lsb(_reg_PHY_PLL_WAIT)));
1157
1158 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL),
1159 (ddrtbl_getval
1160 (_cnf_DDR_PHY_ADR_G_REGSET,
1161 _reg_PHY_PLL_CTRL_TOP) << 16) |
1162 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1163 _reg_PHY_PLL_CTRL));
1164 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL_CA),
1165 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1166 _reg_PHY_PLL_CTRL_CA));
1167
1168 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL),
1169 (ddrtbl_getval
1170 (_cnf_DDR_PHY_ADR_G_REGSET,
1171 _reg_PHY_LP4_BOOT_PLL_CTRL_CA) << 16) |
1172 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
1173 _reg_PHY_LP4_BOOT_PLL_CTRL));
1174 reg_ddrphy_write_a(ddr_regdef_adr
1175 (_reg_PHY_LP4_BOOT_TOP_PLL_CTRL),
1176 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
Marek Vasut6a131772019-08-07 19:56:09 +02001177 _reg_PHY_LP4_BOOT_TOP_PLL_CTRL
1178 ));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001179 }
1180
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001181 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LPDDR3_CS),
Marek Vasut6a131772019-08-07 19:56:09 +02001182 _cnf_DDR_PHY_ADR_G_REGSET
1183 [ddr_regdef_adr(_reg_PHY_LPDDR3_CS) -
1184 DDR_PHY_ADR_G_REGSET_OFS]);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001185
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001186 /* protect register interface */
1187 ddrphy_regif_idle();
1188 pll3_control(0);
1189
Marek Vasut38dc7562019-08-07 19:17:42 +02001190 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001191 /* non */
1192 } else {
1193 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_DLL_RST_EN),
1194 (0x01U <<
1195 ddr_regdef_lsb(_reg_PHY_DLL_RST_EN)));
1196 ddrphy_regif_idle();
1197 }
1198
Marek Vasut6a131772019-08-07 19:56:09 +02001199 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001200 /* dbdficnt0:
1201 * dfi_dram_clk_disable=1
1202 * dfi_frequency = 0
1203 * freq_ratio = 01 (2:1)
1204 * init_start =0
1205 */
1206 foreach_vch(ch)
1207 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
1208 dsb_sev();
1209
1210 /* dbdficnt0:
1211 * dfi_dram_clk_disable=1
1212 * dfi_frequency = 0
1213 * freq_ratio = 01 (2:1)
1214 * init_start =1
1215 */
1216 foreach_vch(ch)
1217 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
1218 dsb_sev();
1219
1220 foreach_ech(ch)
Marek Vasut6a131772019-08-07 19:56:09 +02001221 if ((board_cnf->phyvalid) & BIT(ch))
1222 while ((mmio_read_32(DBSC_PLL_LOCK(ch)) & 0x1f) != 0x1f)
1223 ;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001224 dsb_sev();
1225}
1226
Marek Vasut6a131772019-08-07 19:56:09 +02001227/* load table data into DDR registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001228static void ddrtbl_load(void)
1229{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001230 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001231 uint32_t slice;
1232 uint32_t csab;
1233 uint32_t adr;
Marek Vasut38dc7562019-08-07 19:17:42 +02001234 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001235 uint32_t tmp[3];
1236 uint16_t dataS;
1237
Marek Vasut6a131772019-08-07 19:56:09 +02001238 /* TIMING REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001239 /* search jedec_spec1 index */
1240 for (i = JS1_USABLEC_SPEC_LO; i < JS1_FREQ_TBL_NUM - 1; i++) {
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001241 if (js1[i].fx3 * 2U * ddr_mbpsdiv >= ddr_mbps * 3U)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001242 break;
1243 }
Marek Vasut80784f92019-08-07 19:02:26 +02001244 if (i > JS1_USABLEC_SPEC_HI)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001245 js1_ind = JS1_USABLEC_SPEC_HI;
1246 else
1247 js1_ind = i;
1248
Marek Vasut38dc7562019-08-07 19:17:42 +02001249 if (board_cnf->dbi_en)
1250 RL = js1[js1_ind].rlwdbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001251 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001252 RL = js1[js1_ind].rlwodbi;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001253
1254 WL = js1[js1_ind].WL;
1255
1256 /* calculate jedec_spec2 */
1257 _f_scale_js2(ddr_mbps, ddr_mbpsdiv, js2);
1258
Marek Vasut6a131772019-08-07 19:56:09 +02001259 /* PREPARE TBL */
Marek Vasut38dc7562019-08-07 19:17:42 +02001260 if (prr_product == PRR_PRODUCT_H3) {
1261 if (prr_cut <= PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001262 /* H3 Ver.1.x */
1263 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1264 DDR_PHY_SLICE_REGSET_H3,
1265 DDR_PHY_SLICE_REGSET_NUM_H3);
1266 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1267 DDR_PHY_ADR_V_REGSET_H3,
1268 DDR_PHY_ADR_V_REGSET_NUM_H3);
1269 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1270 DDR_PHY_ADR_I_REGSET_H3,
1271 DDR_PHY_ADR_I_REGSET_NUM_H3);
1272 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1273 DDR_PHY_ADR_G_REGSET_H3,
1274 DDR_PHY_ADR_G_REGSET_NUM_H3);
1275 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3,
1276 DDR_PI_REGSET_NUM_H3);
1277
1278 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_H3;
1279 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_H3;
1280 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_H3;
1281 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_H3;
1282 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3;
1283 DDR_PHY_SLICE_REGSET_SIZE =
1284 DDR_PHY_SLICE_REGSET_SIZE_H3;
1285 DDR_PHY_ADR_V_REGSET_SIZE =
1286 DDR_PHY_ADR_V_REGSET_SIZE_H3;
1287 DDR_PHY_ADR_I_REGSET_SIZE =
1288 DDR_PHY_ADR_I_REGSET_SIZE_H3;
1289 DDR_PHY_ADR_G_REGSET_SIZE =
1290 DDR_PHY_ADR_G_REGSET_SIZE_H3;
1291 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3;
1292 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_H3;
1293 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_H3;
1294 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_H3;
1295 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_H3;
1296 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3;
1297
1298 DDR_PHY_ADR_I_NUM = 1;
1299 } else {
1300 /* H3 Ver.2.0 or later */
1301 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1302 DDR_PHY_SLICE_REGSET_H3VER2,
1303 DDR_PHY_SLICE_REGSET_NUM_H3VER2);
1304 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1305 DDR_PHY_ADR_V_REGSET_H3VER2,
1306 DDR_PHY_ADR_V_REGSET_NUM_H3VER2);
1307 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1308 DDR_PHY_ADR_G_REGSET_H3VER2,
1309 DDR_PHY_ADR_G_REGSET_NUM_H3VER2);
1310 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3VER2,
1311 DDR_PI_REGSET_NUM_H3VER2);
1312
1313 DDR_PHY_SLICE_REGSET_OFS =
1314 DDR_PHY_SLICE_REGSET_OFS_H3VER2;
1315 DDR_PHY_ADR_V_REGSET_OFS =
1316 DDR_PHY_ADR_V_REGSET_OFS_H3VER2;
1317 DDR_PHY_ADR_G_REGSET_OFS =
1318 DDR_PHY_ADR_G_REGSET_OFS_H3VER2;
1319 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3VER2;
1320 DDR_PHY_SLICE_REGSET_SIZE =
1321 DDR_PHY_SLICE_REGSET_SIZE_H3VER2;
1322 DDR_PHY_ADR_V_REGSET_SIZE =
1323 DDR_PHY_ADR_V_REGSET_SIZE_H3VER2;
1324 DDR_PHY_ADR_G_REGSET_SIZE =
1325 DDR_PHY_ADR_G_REGSET_SIZE_H3VER2;
1326 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3VER2;
1327 DDR_PHY_SLICE_REGSET_NUM =
1328 DDR_PHY_SLICE_REGSET_NUM_H3VER2;
1329 DDR_PHY_ADR_V_REGSET_NUM =
1330 DDR_PHY_ADR_V_REGSET_NUM_H3VER2;
1331 DDR_PHY_ADR_G_REGSET_NUM =
1332 DDR_PHY_ADR_G_REGSET_NUM_H3VER2;
1333 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3VER2;
1334
1335 DDR_PHY_ADR_I_NUM = 0;
1336 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001337 } else if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001338 /* M3-W */
1339 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1340 DDR_PHY_SLICE_REGSET_M3, DDR_PHY_SLICE_REGSET_NUM_M3);
1341 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET,
1342 DDR_PHY_ADR_V_REGSET_M3, DDR_PHY_ADR_V_REGSET_NUM_M3);
1343 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET,
1344 DDR_PHY_ADR_I_REGSET_M3, DDR_PHY_ADR_I_REGSET_NUM_M3);
1345 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET,
1346 DDR_PHY_ADR_G_REGSET_M3, DDR_PHY_ADR_G_REGSET_NUM_M3);
1347 _tblcopy(_cnf_DDR_PI_REGSET,
1348 DDR_PI_REGSET_M3, DDR_PI_REGSET_NUM_M3);
1349
1350 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3;
1351 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3;
1352 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3;
1353 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3;
1354 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3;
1355 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3;
1356 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3;
1357 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3;
1358 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3;
1359 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3;
1360 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3;
1361 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3;
1362 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3;
1363 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3;
1364 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3;
1365
1366 DDR_PHY_ADR_I_NUM = 2;
1367 } else {
1368 /* M3-N/V3H */
1369 _tblcopy(_cnf_DDR_PHY_SLICE_REGSET,
1370 DDR_PHY_SLICE_REGSET_M3N,
1371 DDR_PHY_SLICE_REGSET_NUM_M3N);
1372 _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, DDR_PHY_ADR_V_REGSET_M3N,
1373 DDR_PHY_ADR_V_REGSET_NUM_M3N);
1374 _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, DDR_PHY_ADR_I_REGSET_M3N,
1375 DDR_PHY_ADR_I_REGSET_NUM_M3N);
1376 _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, DDR_PHY_ADR_G_REGSET_M3N,
1377 DDR_PHY_ADR_G_REGSET_NUM_M3N);
1378 _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_M3N,
1379 DDR_PI_REGSET_NUM_M3N);
1380
1381 DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3N;
1382 DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3N;
1383 DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3N;
1384 DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3N;
1385 DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3N;
1386 DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3N;
1387 DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3N;
1388 DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3N;
1389 DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3N;
1390 DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3N;
1391 DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3N;
1392 DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3N;
1393 DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3N;
1394 DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3N;
1395 DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3N;
1396
1397 DDR_PHY_ADR_I_NUM = 2;
1398 }
1399
Marek Vasut6a131772019-08-07 19:56:09 +02001400 /* PLL CODE CHANGE */
Marek Vasut38dc7562019-08-07 19:17:42 +02001401 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001402 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, _reg_PHY_PLL_CTRL,
1403 0x1142);
1404 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1405 _reg_PHY_LP4_BOOT_PLL_CTRL, 0x1142);
1406 }
1407
Marek Vasut6a131772019-08-07 19:56:09 +02001408 /* on fly gate adjust */
Marek Vasut38dc7562019-08-07 19:17:42 +02001409 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001410 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1411 _reg_ON_FLY_GATE_ADJUST_EN, 0x00);
1412 }
1413
Marek Vasut6a131772019-08-07 19:56:09 +02001414 /* Adjust PI parameters */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001415#ifdef _def_LPDDR4_ODT
Marek Vasut6c245a52018-12-12 18:06:39 +01001416 for (i = 0; i < 2; i++) {
1417 for (csab = 0; csab < CSAB_CNT; csab++) {
1418 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001419 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001420 _def_LPDDR4_ODT);
1421 }
1422 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001423#endif /* _def_LPDDR4_ODT */
1424
1425#ifdef _def_LPDDR4_VREFCA
Marek Vasut6c245a52018-12-12 18:06:39 +01001426 for (i = 0; i < 2; i++) {
1427 for (csab = 0; csab < CSAB_CNT; csab++) {
1428 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001429 reg_pi_mr12_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001430 _def_LPDDR4_VREFCA);
1431 }
1432 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001433#endif /* _def_LPDDR4_VREFCA */
Marek Vasut6a131772019-08-07 19:56:09 +02001434 if ((prr_product == PRR_PRODUCT_M3N) ||
1435 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001436 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 7000, 0) + 7U;
1437 if (js2[js2_tiedly] > (RL))
1438 js2[js2_tiedly] = RL;
Marek Vasut6a131772019-08-07 19:56:09 +02001439 } else if ((prr_product == PRR_PRODUCT_H3) &&
1440 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001441 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 9000, 0) + 4U;
Marek Vasut6a131772019-08-07 19:56:09 +02001442 } else if ((prr_product == PRR_PRODUCT_H3) &&
1443 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001444 js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 10000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001445 }
1446
Marek Vasut6a131772019-08-07 19:56:09 +02001447 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
1448 (prr_product == PRR_PRODUCT_M3N) ||
1449 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001450 if ((js2[js2_tiedly]) >= 0x1e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001451 dataS = 0x1e;
1452 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001453 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001454 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001455 if ((js2[js2_tiedly]) >= 0x0e)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001456 dataS = 0x0e;
1457 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001458 dataS = js2[js2_tiedly];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001459 }
1460
1461 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_DLY, dataS);
1462 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_TSEL_DLY,
1463 (dataS - 2));
Marek Vasut6a131772019-08-07 19:56:09 +02001464 if ((prr_product == PRR_PRODUCT_M3N) ||
1465 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001466 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001467 _reg_PHY_RDDATA_EN_OE_DLY, dataS - 2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001468 }
1469 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS);
1470
1471 if (ddrtbl_getval
1472 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001473 data_l = WL - 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001474 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001475 data_l = WL;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001476 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001477 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1, data_l - 2);
1478 ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001479
Marek Vasut38dc7562019-08-07 19:17:42 +02001480 if (board_cnf->dbi_en) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001481 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1482 0x01);
1483 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1484 _reg_PHY_WDQLVL_DATADM_MASK, 0x000);
1485 } else {
1486 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE,
1487 0x00);
1488 ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET,
1489 _reg_PHY_WDQLVL_DATADM_MASK, 0x100);
1490 }
1491
1492 tmp[0] = js1[js1_ind].MR1;
1493 tmp[1] = js1[js1_ind].MR2;
Marek Vasut38dc7562019-08-07 19:17:42 +02001494 data_l = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_MR3_DATA_F1_0);
1495 if (board_cnf->dbi_en)
1496 tmp[2] = data_l | 0xc0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001497 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001498 tmp[2] = data_l & (~0xc0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001499
1500 for (i = 0; i < 2; i++) {
1501 for (csab = 0; csab < CSAB_CNT; csab++) {
1502 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001503 reg_pi_mr1_data_fx_csx[i][csab], tmp[0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001504 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001505 reg_pi_mr2_data_fx_csx[i][csab], tmp[1]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001506 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001507 reg_pi_mr3_data_fx_csx[i][csab], tmp[2]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001508 }
1509 }
1510
Marek Vasut6a131772019-08-07 19:56:09 +02001511 /* DDRPHY INT START */
Marek Vasut38dc7562019-08-07 19:17:42 +02001512 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001513 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001514 } else {
1515 regif_pll_wa();
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09001516 dbwait_loop(5);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001517 }
1518
Marek Vasut6a131772019-08-07 19:56:09 +02001519 /* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001520 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001521 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001522 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x01);
1523
Marek Vasut6a131772019-08-07 19:56:09 +02001524 /* SET DATA SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001525 for (slice = 0; slice < SLICE_CNT; slice++) {
1526 adr =
1527 DDR_PHY_SLICE_REGSET_OFS +
1528 DDR_PHY_SLICE_REGSET_SIZE * slice;
1529 for (i = 0; i < DDR_PHY_SLICE_REGSET_NUM; i++) {
1530 reg_ddrphy_write_a(adr + i,
1531 _cnf_DDR_PHY_SLICE_REGSET[i]);
1532 }
1533 }
1534
Marek Vasut6a131772019-08-07 19:56:09 +02001535 /* SET ADR SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001536 adr = DDR_PHY_ADR_V_REGSET_OFS;
1537 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1538 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_V_REGSET[i]);
1539 }
1540
Marek Vasut6a131772019-08-07 19:56:09 +02001541 if (((prr_product == PRR_PRODUCT_M3) ||
1542 (prr_product == PRR_PRODUCT_M3N)) &&
Marek Vasut38dc7562019-08-07 19:17:42 +02001543 ((0x00ffffff & (uint32_t)((board_cnf->ch[0].ca_swap) >> 40))
Marek Vasut6c245a52018-12-12 18:06:39 +01001544 != 0x00)) {
1545 adr = DDR_PHY_ADR_I_REGSET_OFS + DDR_PHY_ADR_I_REGSET_SIZE;
1546 for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) {
1547 reg_ddrphy_write_a(adr + i,
1548 _cnf_DDR_PHY_ADR_V_REGSET[i]);
1549 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02001550 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1551 _reg_PHY_ADR_DISABLE, 0x02);
Marek Vasut6c245a52018-12-12 18:06:39 +01001552 DDR_PHY_ADR_I_NUM -= 1;
1553 ddr_phycaslice = 1;
1554
1555#ifndef _def_LPDDR4_ODT
1556 for (i = 0; i < 2; i++) {
1557 for (csab = 0; csab < CSAB_CNT; csab++) {
1558 ddrtbl_setval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02001559 reg_pi_mr11_data_fx_csx[i][csab],
Marek Vasut6c245a52018-12-12 18:06:39 +01001560 0x66);
1561 }
1562 }
1563#endif/* _def_LPDDR4_ODT */
1564 } else {
1565 ddr_phycaslice = 0;
1566 }
1567
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001568 if (DDR_PHY_ADR_I_NUM > 0) {
1569 for (slice = 0; slice < DDR_PHY_ADR_I_NUM; slice++) {
1570 adr =
1571 DDR_PHY_ADR_I_REGSET_OFS +
1572 DDR_PHY_ADR_I_REGSET_SIZE * slice;
1573 for (i = 0; i < DDR_PHY_ADR_I_REGSET_NUM; i++) {
1574 reg_ddrphy_write_a(adr + i,
1575 _cnf_DDR_PHY_ADR_I_REGSET
1576 [i]);
1577 }
1578 }
1579 }
1580
Marek Vasut6a131772019-08-07 19:56:09 +02001581 /* SET ADRCTRL SLICE TABLE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001582 adr = DDR_PHY_ADR_G_REGSET_OFS;
1583 for (i = 0; i < DDR_PHY_ADR_G_REGSET_NUM; i++) {
1584 reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_G_REGSET[i]);
1585 }
1586
Marek Vasut6a131772019-08-07 19:56:09 +02001587 /* SET PI REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001588 adr = DDR_PI_REGSET_OFS;
1589 for (i = 0; i < DDR_PI_REGSET_NUM; i++) {
1590 reg_ddrphy_write_a(adr + i, _cnf_DDR_PI_REGSET[i]);
1591 }
1592}
1593
Marek Vasut6a131772019-08-07 19:56:09 +02001594/* CONFIGURE DDR REGISTERS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001595static void ddr_config_sub(void)
1596{
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001597 uint32_t i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001598 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001599 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001600 uint32_t tmp;
1601 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001602 const uint32_t _par_CALVL_DEVICE_MAP = 1;
Marek Vasut80784f92019-08-07 19:02:26 +02001603
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001604 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001605 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001606 for (slice = 0; slice < SLICE_CNT; slice++) {
1607 high_byte[slice] =
Marek Vasut38dc7562019-08-07 19:17:42 +02001608 (board_cnf->ch[ch].dqs_swap >> (4 * slice)) % 2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001609 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001610 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001611 ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001612 board_cnf->ch[ch].dm_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001613 if (high_byte[slice]) {
1614 /* HIGHER 16 BYTE */
1615 ddr_setval_s(ch, slice,
1616 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1617 0x00);
1618 } else {
1619 /* LOWER 16 BYTE */
1620 ddr_setval_s(ch, slice,
1621 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1622 0x01);
1623 }
1624 }
1625
Marek Vasut6a131772019-08-07 19:56:09 +02001626 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001627 data_l = (0x00ffffff & (uint32_t)(board_cnf->ch[ch].ca_swap)) |
Marek Vasut6c245a52018-12-12 18:06:39 +01001628 0x00888888;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001629
1630 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001631 if (prr_product == PRR_PRODUCT_M3) {
1632 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001633 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0,
1634 0x00000000);
Marek Vasut38dc7562019-08-07 19:17:42 +02001635 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001636 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1,
1637 0x00000000);
1638 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP,
1639 _par_CALVL_DEVICE_MAP);
1640 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001641 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001642 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1, 0x00000000);
1643 ddr_setval(ch, _reg_PHY_CALVL_DEVICE_MAP,
1644 _par_CALVL_DEVICE_MAP);
1645 }
1646
1647 /* --- ADR_ADDR_SEL --- */
Marek Vasut6a131772019-08-07 19:56:09 +02001648 if ((prr_product == PRR_PRODUCT_H3) &&
1649 (prr_cut > PRR_PRODUCT_11)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001650 data_l = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001651 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02001652 data_l = 0;
1653 tmp = board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001654 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001655 data_l |= ((tmp & 0x0f) << (i * 5));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001656 tmp = tmp >> 4;
1657 }
1658 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001659 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001660 if (ddr_phycaslice == 1) {
1661 /* ----------- adr slice2 swap ----------- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001662 tmp = (uint32_t)((board_cnf->ch[ch].ca_swap) >> 40);
1663 data_l = (tmp & 0x00ffffff) | 0x00888888;
Marek Vasut6c245a52018-12-12 18:06:39 +01001664
1665 /* --- ADR_CALVL_SWIZZLE --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001666 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001667 ddr_setval_s(ch, 2,
1668 _reg_PHY_ADR_CALVL_SWIZZLE0_0,
1669 data_l);
1670 ddr_setval_s(ch, 2,
1671 _reg_PHY_ADR_CALVL_SWIZZLE1_0,
Marek Vasut6c245a52018-12-12 18:06:39 +01001672 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001673 ddr_setval_s(ch, 2,
1674 _reg_PHY_ADR_CALVL_SWIZZLE0_1,
1675 data_l);
1676 ddr_setval_s(ch, 2,
1677 _reg_PHY_ADR_CALVL_SWIZZLE1_1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001678 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001679 ddr_setval_s(ch, 2,
1680 _reg_PHY_ADR_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001681 _par_CALVL_DEVICE_MAP);
1682 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001683 ddr_setval_s(ch, 2,
1684 _reg_PHY_ADR_CALVL_SWIZZLE0,
1685 data_l);
1686 ddr_setval_s(ch, 2,
1687 _reg_PHY_ADR_CALVL_SWIZZLE1,
Marek Vasut6c245a52018-12-12 18:06:39 +01001688 0x00000000);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001689 ddr_setval_s(ch, 2,
1690 _reg_PHY_CALVL_DEVICE_MAP,
Marek Vasut6c245a52018-12-12 18:06:39 +01001691 _par_CALVL_DEVICE_MAP);
1692 }
1693
1694 /* --- ADR_ADDR_SEL --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001695 data_l = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01001696 for (i = 0; i < 6; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001697 data_l |= ((tmp & 0x0f) << (i * 5));
Marek Vasut6c245a52018-12-12 18:06:39 +01001698 tmp = tmp >> 4;
1699 }
1700
Marek Vasut38dc7562019-08-07 19:17:42 +02001701 ddr_setval_s(ch, 2, _reg_PHY_ADR_ADDR_SEL, data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01001702 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001703
Marek Vasut6a131772019-08-07 19:56:09 +02001704 /* BOARD SETTINGS (BYTE_ORDER_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001705 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001706 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001707 data_l = 0;
1708 tmp = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001709 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001710 data_l |= ((tmp & 0x03) << (i * 2));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001711 tmp = tmp >> 4;
1712 }
1713 } else {
1714 /* --- DATA_BYTE_SWAP --- */
Marek Vasut38dc7562019-08-07 19:17:42 +02001715 data_l = board_cnf->ch[ch].dqs_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001716 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_EN, 0x01);
1717 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE0,
Marek Vasut38dc7562019-08-07 19:17:42 +02001718 (data_l) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001719 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE1,
Marek Vasut38dc7562019-08-07 19:17:42 +02001720 (data_l >> 4 * 1) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001721 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE2,
Marek Vasut38dc7562019-08-07 19:17:42 +02001722 (data_l >> 4 * 2) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001723 ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE3,
Marek Vasut38dc7562019-08-07 19:17:42 +02001724 (data_l >> 4 * 3) & 0x0f);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001725
1726 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH, 0x00);
1727 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001728 ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001729 }
1730}
1731
Marek Vasut80784f92019-08-07 19:02:26 +02001732static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001733{
1734 uint32_t slice;
1735 uint32_t tmp;
1736 uint32_t tgt;
Marek Vasut80784f92019-08-07 19:02:26 +02001737
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001738 if (ddr_csn / 2) {
1739 tgt = 3;
1740 } else {
1741 tgt = 1;
1742 }
1743
1744 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001745 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001746 if (tgt == tmp)
1747 break;
1748 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001749 tmp = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001750 if (slice % 2)
1751 tmp |= 0x00888888;
1752 *p_swz = tmp;
1753}
1754
1755static void ddr_config_sub_h3v1x(void)
1756{
1757 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001758 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001759 uint32_t tmp;
1760 uint8_t high_byte[SLICE_CNT];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001761 uint32_t ca_swizzle;
1762 uint32_t ca;
1763 uint32_t csmap;
1764 uint32_t o_inv;
1765 uint32_t inv;
1766 uint32_t bit_soc;
1767 uint32_t bit_mem;
1768 uint32_t j;
1769
1770 const uint8_t o_mr15 = 0x55;
1771 const uint8_t o_mr20 = 0x55;
1772 const uint16_t o_mr32_mr40 = 0x5a3c;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001773
1774 foreach_vch(ch) {
Marek Vasut6a131772019-08-07 19:56:09 +02001775 /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001776 csmap = 0;
1777 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001778 tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) &
1779 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001780 high_byte[slice] = tmp % 2;
1781 if (tmp == 1 && (slice >= 2))
1782 csmap |= 0x05;
1783 if (tmp == 3 && (slice >= 2))
1784 csmap |= 0x50;
1785 ddr_setval_s(ch, slice, _reg_PHY_DQ_SWIZZLING,
Marek Vasut38dc7562019-08-07 19:17:42 +02001786 board_cnf->ch[ch].dq_swap[slice]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001787 if (high_byte[slice]) {
1788 /* HIGHER 16 BYTE */
1789 ddr_setval_s(ch, slice,
1790 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1791 0x00);
1792 } else {
1793 /* LOWER 16 BYTE */
1794 ddr_setval_s(ch, slice,
1795 _reg_PHY_CALVL_VREF_DRIVING_SLICE,
1796 0x01);
1797 }
1798 }
Marek Vasut6a131772019-08-07 19:56:09 +02001799 /* BOARD SETTINGS (CA,ADDR_SEL) */
Marek Vasut38dc7562019-08-07 19:17:42 +02001800 ca = 0x00FFFFFF & board_cnf->ch[ch].ca_swap;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001801 ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, ca);
1802 ddr_setval(ch, _reg_PHY_CALVL_CS_MAP, csmap);
1803
1804 get_ca_swizzle(ch, 0, &ca_swizzle);
1805
1806 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, ca_swizzle);
1807 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, 0x00000000);
1808 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, 0x00000000);
1809 ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, 0x00000000);
1810 ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, 0x01);
1811
1812 for (slice = 0; slice < SLICE_CNT; slice++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001813 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_NUM,
1814 0x01);
1815 ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_START,
1816 0x08);
1817
1818 if (high_byte[slice])
1819 o_inv = o_mr20;
1820 else
1821 o_inv = o_mr15;
1822
Marek Vasut38dc7562019-08-07 19:17:42 +02001823 tmp = board_cnf->ch[ch].dq_swap[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001824 inv = 0;
1825 j = 0;
1826 for (bit_soc = 0; bit_soc < 8; bit_soc++) {
1827 bit_mem = (tmp >> (4 * bit_soc)) & 0x0f;
1828 j |= (1U << bit_mem);
1829 if (o_inv & (1U << bit_mem))
1830 inv |= (1U << bit_soc);
1831 }
Marek Vasut38dc7562019-08-07 19:17:42 +02001832 data_l = o_mr32_mr40;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001833 if (!high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001834 data_l |= (inv << 24);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001835 if (high_byte[slice])
Marek Vasut38dc7562019-08-07 19:17:42 +02001836 data_l |= (inv << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001837 ddr_setval_s(ch, slice, _reg_PHY_LP4_RDLVL_PATT8,
Marek Vasut38dc7562019-08-07 19:17:42 +02001838 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001839 }
1840 }
1841}
1842
1843static void ddr_config(void)
1844{
1845 int32_t i;
1846 uint32_t ch, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02001847 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001848 uint32_t tmp;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001849 int8_t _adj;
1850 int16_t adj;
1851 uint32_t dq;
1852 union {
1853 uint32_t ui32[4];
1854 uint8_t ui8[16];
1855 } patt;
1856 uint16_t patm;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001857
Marek Vasut6a131772019-08-07 19:56:09 +02001858 /* configure ddrphy registers */
Marek Vasut38dc7562019-08-07 19:17:42 +02001859 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001860 ddr_config_sub_h3v1x();
Marek Vasut6ad74c32019-08-08 16:34:22 +02001861 } else { /* H3 Ver.2.0 or later/M3-N/V3H is same as M3-W */
1862 ddr_config_sub();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001863 }
1864
Marek Vasut6a131772019-08-07 19:56:09 +02001865 /* WDQ_USER_PATT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001866 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001867 for (slice = 0; slice < SLICE_CNT; slice++) {
1868 patm = 0;
1869 for (i = 0; i < 16; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001870 tmp = board_cnf->ch[ch].wdqlvl_patt[i];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001871 patt.ui8[i] = tmp & 0xff;
1872 if (tmp & 0x100)
1873 patm |= (1U << i);
1874 }
1875 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT0,
1876 patt.ui32[0]);
1877 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT1,
1878 patt.ui32[1]);
1879 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT2,
1880 patt.ui32[2]);
1881 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT3,
1882 patt.ui32[3]);
1883 ddr_setval_s(ch, slice, _reg_PHY_USER_PATT4, patm);
1884 }
1885 }
1886
Marek Vasut6a131772019-08-07 19:56:09 +02001887 /* CACS DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001888 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Marek Vasut6ad74c32019-08-08 16:34:22 +02001889 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
1890 0x00U);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001891 foreach_vch(ch) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02001892 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001893 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001894 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
1895 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001896 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001897 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001898 ddr_regdef_adr
1899 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1900 _cnf_DDR_PHY_ADR_V_REGSET
1901 [ddr_regdef_adr
1902 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001903 DDR_PHY_ADR_V_REGSET_OFS]);
1904 }
1905
1906 for (i = (_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4);
1907 i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02001908 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001909 ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET,
1910 _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001911 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001912 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001913 ddr_regdef_adr
1914 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]),
1915 _cnf_DDR_PHY_ADR_G_REGSET
1916 [ddr_regdef_adr
1917 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001918 DDR_PHY_ADR_G_REGSET_OFS]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001919 }
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001920
Marek Vasut6c245a52018-12-12 18:06:39 +01001921 if (ddr_phycaslice == 1) {
1922 for (i = 0; i < 6; i++) {
Marek Vasut6a131772019-08-07 19:56:09 +02001923 adj = _f_scale_adj
1924 (board_cnf->ch[ch].cacs_adj
1925 [i +
1926 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001927 ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET,
Marek Vasut6ad74c32019-08-08 16:34:22 +02001928 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
1929 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001930 data_l + adj);
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001931 reg_ddrphy_write(ch,
Marek Vasut6a131772019-08-07 19:56:09 +02001932 ddr_regdef_adr
1933 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) +
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001934 0x0100,
Marek Vasut6a131772019-08-07 19:56:09 +02001935 _cnf_DDR_PHY_ADR_V_REGSET
1936 [ddr_regdef_adr
1937 (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) -
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001938 DDR_PHY_ADR_V_REGSET_OFS]);
Marek Vasut6c245a52018-12-12 18:06:39 +01001939 }
1940 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001941 }
Chiaki Fujii61aa8032019-03-01 20:28:55 +09001942
Chiaki Fujii59263ee2019-05-17 10:45:02 +09001943 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
Marek Vasut6ad74c32019-08-08 16:34:22 +02001944 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001945
Marek Vasut6a131772019-08-07 19:56:09 +02001946 /* WDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001947 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001948 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001949 for (slice = 0; slice < SLICE_CNT; slice++) {
1950 for (i = 0; i <= 8; i++) {
1951 dq = slice * 8 + i;
1952 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001953 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001954 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001955 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001956 adj = _f_scale_adj(_adj);
1957 ddr_setval_s(ch, slice,
1958 _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02001959 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001960 }
1961 }
1962 }
1963
Marek Vasut6a131772019-08-07 19:56:09 +02001964 /* RDQDM DLY */
Marek Vasut38dc7562019-08-07 19:17:42 +02001965 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001966 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001967 for (slice = 0; slice < SLICE_CNT; slice++) {
1968 for (i = 0; i <= 8; i++) {
1969 dq = slice * 8 + i;
1970 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02001971 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001972 else
Marek Vasut38dc7562019-08-07 19:17:42 +02001973 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001974 adj = _f_scale_adj(_adj);
1975 ddr_setval_s(ch, slice,
1976 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001977 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001978 ddr_setval_s(ch, slice,
1979 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
Marek Vasut38dc7562019-08-07 19:17:42 +02001980 [i], data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001981 }
1982 }
1983 }
1984}
1985
Marek Vasut6a131772019-08-07 19:56:09 +02001986/* DBSC register setting functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001987static void dbsc_regset_pre(void)
1988{
1989 uint32_t ch, csab;
Marek Vasut38dc7562019-08-07 19:17:42 +02001990 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001991
Marek Vasut6a131772019-08-07 19:56:09 +02001992 /* PRIMARY SETTINGS */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02001993 /* LPDDR4, BL=16, DFI interface */
1994 mmio_write_32(DBSC_DBKIND, 0x0000000a);
1995 mmio_write_32(DBSC_DBBL, 0x00000002);
1996 mmio_write_32(DBSC_DBPHYCONF0, 0x00000001);
1997
1998 /* FREQRATIO=2 */
1999 mmio_write_32(DBSC_DBSYSCONF1, 0x00000002);
2000
2001 /* Chanel map (H3 Ver.1.x) */
Marek Vasut38dc7562019-08-07 19:17:42 +02002002 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002003 mmio_write_32(DBSC_DBSCHCNT1, 0x00001010);
2004
2005 /* DRAM SIZE REGISTER:
2006 * set all ranks as density=0(4Gb) for PHY initialization
2007 */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002008 foreach_vch(ch) {
2009 for (csab = 0; csab < 4; csab++) {
2010 mmio_write_32(DBSC_DBMEMCONF(ch, csab),
2011 DBMEMCONF_REGD(0));
2012 }
2013 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002014
Marek Vasut38dc7562019-08-07 19:17:42 +02002015 if (prr_product == PRR_PRODUCT_M3) {
2016 data_l = 0xe4e4e4e4;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002017 foreach_ech(ch) {
2018 if ((ddr_phyvalid & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02002019 data_l = (data_l & (~(0x000000FF << (ch * 8))))
2020 | (((board_cnf->ch[ch].dqs_swap & 0x0003)
2021 | ((board_cnf->ch[ch].dqs_swap & 0x0030)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002022 >> 2)
Marek Vasut38dc7562019-08-07 19:17:42 +02002023 | ((board_cnf->ch[ch].dqs_swap & 0x0300)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002024 >> 4)
Marek Vasut38dc7562019-08-07 19:17:42 +02002025 | ((board_cnf->ch[ch].dqs_swap & 0x3000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002026 >> 6)) << (ch * 8));
2027 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002028 mmio_write_32(DBSC_DBBSWAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002029 }
2030}
2031
2032static void dbsc_regset(void)
2033{
2034 int32_t i;
2035 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002036 uint32_t data_l;
2037 uint32_t data_l2;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002038 uint32_t tmp[4];
2039
2040 /* RFC */
Marek Vasut6a131772019-08-07 19:56:09 +02002041 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_20) &&
2042 (max_density == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002043 js2[js2_trfcab] =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002044 _f_scale(ddr_mbps, ddr_mbpsdiv,
Marek Vasut38dc7562019-08-07 19:17:42 +02002045 1UL * jedec_spec2_trfc_ab[1] * 1000, 0);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002046 } else {
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[max_density] *
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002050 1000, 0);
2051 }
2052
2053 /* DBTR0.CL : RL */
2054 mmio_write_32(DBSC_DBTR(0), RL);
2055
2056 /* DBTR1.CWL : WL */
2057 mmio_write_32(DBSC_DBTR(1), WL);
2058
2059 /* DBTR2.AL : 0 */
2060 mmio_write_32(DBSC_DBTR(2), 0);
2061
2062 /* DBTR3.TRCD: tRCD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002063 mmio_write_32(DBSC_DBTR(3), js2[js2_trcd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002064
2065 /* DBTR4.TRPA,TRP: tRPab,tRPpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002066 mmio_write_32(DBSC_DBTR(4), (js2[js2_trpab] << 16) | js2[js2_trppb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002067
2068 /* DBTR5.TRC : use tRCpb */
Marek Vasut38dc7562019-08-07 19:17:42 +02002069 mmio_write_32(DBSC_DBTR(5), js2[js2_trcpb]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002070
2071 /* DBTR6.TRAS : tRAS */
Marek Vasut38dc7562019-08-07 19:17:42 +02002072 mmio_write_32(DBSC_DBTR(6), js2[js2_tras]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002073
2074 /* DBTR7.TRRD : tRRD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002075 mmio_write_32(DBSC_DBTR(7), (js2[js2_trrd] << 16) | js2[js2_trrd]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002076
2077 /* DBTR8.TFAW : tFAW */
Marek Vasut38dc7562019-08-07 19:17:42 +02002078 mmio_write_32(DBSC_DBTR(8), js2[js2_tfaw]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002079
2080 /* DBTR9.TRDPR : tRTP */
Marek Vasut38dc7562019-08-07 19:17:42 +02002081 mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002082
Chiaki Fujii82e9c412019-12-26 12:57:40 +09002083 /* DBTR10.TWR : nWR */
2084 mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002085
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002086 /*
2087 * DBTR11.TRDWR : RL + BL / 2 + Rounddown(tRPST) + PHY_ODTLoff -
2088 * odtlon + tDQSCK - tODTon,min +
2089 * PCB delay (out+in) + tPHY_ODToff
2090 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002091 mmio_write_32(DBSC_DBTR(11),
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002092 RL + (16 / 2) + 1 + 2 - js1[js1_ind].odtlon +
2093 js2[js2_tdqsck] - js2[js2_tODTon_min] +
2094 _f_scale(ddr_mbps, ddr_mbpsdiv, 1300, 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002095
2096 /* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002097 data_l = WL + 1 + (16 / 2) + js2[js2_twtr];
2098 mmio_write_32(DBSC_DBTR(12), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002099
Marek Vasut6c245a52018-12-12 18:06:39 +01002100 /* DBTR13.TRFCAB : tRFCab */
Marek Vasut38dc7562019-08-07 19:17:42 +02002101 mmio_write_32(DBSC_DBTR(13), (js2[js2_trfcab]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002102
2103 /* DBTR14.TCKEHDLL,tCKEH : tCKEHCMD,tCKEHCMD */
2104 mmio_write_32(DBSC_DBTR(14),
Marek Vasut38dc7562019-08-07 19:17:42 +02002105 (js2[js2_tckehcmd] << 16) | (js2[js2_tckehcmd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002106
2107 /* DBTR15.TCKESR,TCKEL : tSR,tCKELPD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002108 mmio_write_32(DBSC_DBTR(15), (js2[js2_tsr] << 16) | (js2[js2_tckelpd]));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002109
2110 /* DBTR16 */
2111 /* WDQL : tphy_wrlat + tphy_wrdata */
2112 tmp[0] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1);
Marek Vasut3af20052019-02-25 14:57:08 +01002113 /* DQENLTNCY : tphy_wrlat = WL-2 : PHY_WRITE_PATH_LAT_ADD == 0
2114 * tphy_wrlat = WL-3 : PHY_WRITE_PATH_LAT_ADD != 0
2115 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002116 tmp[1] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1);
2117 /* DQL : tphy_rdlat + trdata_en */
2118 /* it is not important for dbsc */
2119 tmp[2] = RL + 16;
2120 /* DQIENLTNCY : trdata_en */
2121 tmp[3] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1) - 1;
2122 mmio_write_32(DBSC_DBTR(16),
2123 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2124
2125 /* DBTR24 */
2126 /* WRCSLAT = WRLAT -5 */
2127 tmp[0] -= 5;
2128 /* WRCSGAP = 5 */
2129 tmp[1] = 5;
2130 /* RDCSLAT = RDLAT_ADJ +2 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002131 if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6c245a52018-12-12 18:06:39 +01002132 tmp[2] = tmp[3];
2133 } else {
2134 tmp[2] = tmp[3] + 2;
2135 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002136 /* RDCSGAP = 6 */
Marek Vasut38dc7562019-08-07 19:17:42 +02002137 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002138 tmp[3] = 4;
2139 } else {
2140 tmp[3] = 6;
2141 }
2142 mmio_write_32(DBSC_DBTR(24),
2143 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2144
2145 /* DBTR17.TMODRD,TMOD,TRDMR: tMRR,tMRD,(0) */
2146 mmio_write_32(DBSC_DBTR(17),
Marek Vasut38dc7562019-08-07 19:17:42 +02002147 (js2[js2_tmrr] << 24) | (js2[js2_tmrd] << 16));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002148
2149 /* DBTR18.RODTL, RODTA, WODTL, WODTA : do not use in LPDDR4 */
2150 mmio_write_32(DBSC_DBTR(18), 0);
2151
2152 /* DBTR19.TZQCL, TZQCS : do not use in LPDDR4 */
2153 mmio_write_32(DBSC_DBTR(19), 0);
2154
2155 /* DBTR20.TXSDLL, TXS : tRFCab+tCKEHCMD */
Marek Vasut38dc7562019-08-07 19:17:42 +02002156 data_l = js2[js2_trfcab] + js2[js2_tckehcmd];
2157 mmio_write_32(DBSC_DBTR(20), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002158
2159 /* DBTR21.TCCD */
2160 /* DBTR23.TCCD */
2161 /* H3 Ver.1.0 cannot use TBTR23 feature */
2162 if (ddr_tccd == 8 &&
Marek Vasut38dc7562019-08-07 19:17:42 +02002163 !((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_10))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002164 ) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002165 data_l = 8;
2166 mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002167 mmio_write_32(DBSC_DBTR(23), 0x00000002);
2168 } else if (ddr_tccd <= 11) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002169 data_l = 11;
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), 0x00000000);
2172 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002173 data_l = ddr_tccd;
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 }
2177
2178 /* DBTR22.ZQLAT : */
Marek Vasut38dc7562019-08-07 19:17:42 +02002179 data_l = js2[js2_tzqcalns] * 100; /* 1000 * 1000 ps */
2180 data_l = (data_l << 16) | (js2[js2_tzqlat] + 24 + 20);
2181 mmio_write_32(DBSC_DBTR(22), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002182
2183 /* DBTR25 : do not use in LPDDR4 */
2184 mmio_write_32(DBSC_DBTR(25), 0);
2185
2186 /* DBRNK : */
2187 /*
2188 * DBSC_DBRNK2 rkrr
2189 * DBSC_DBRNK3 rkrw
2190 * DBSC_DBRNK4 rkwr
2191 * DBSC_DBRNK5 rkww
2192 */
2193#define _par_DBRNK_VAL (0x7007)
2194
2195 for (i = 0; i < 4; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002196 data_l = (_par_DBRNK_VAL >> (i * 4)) & 0x0f;
Marek Vasut6a131772019-08-07 19:56:09 +02002197 if ((prr_product == PRR_PRODUCT_H3) &&
2198 (prr_cut > PRR_PRODUCT_11) && (i == 0)) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002199 data_l += 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002200 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002201 data_l2 = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002202 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002203 data_l2 = data_l2 | (data_l << (4 * ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002204 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002205 mmio_write_32(DBSC_DBRNK(2 + i), data_l2);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002206 }
2207 mmio_write_32(DBSC_DBADJ0, 0x00000000);
2208
Marek Vasut6a131772019-08-07 19:56:09 +02002209 /* timing registers for Scheduler */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002210 /* SCFCTST0 */
2211 /* SCFCTST0 ACT-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002212 tmp[3] = 1UL * js2[js2_trcpb] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002213 /* SCFCTST0 RDA-ACT */
2214 tmp[2] =
Marek Vasut38dc7562019-08-07 19:17:42 +02002215 1UL * ((16 / 2) + js2[js2_trtp] - 8 +
2216 js2[js2_trppb]) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002217 /* SCFCTST0 WRA-ACT */
2218 tmp[1] =
2219 1UL * (WL + 1 + (16 / 2) +
Marek Vasut38dc7562019-08-07 19:17:42 +02002220 js1[js1_ind].nwr) * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002221 /* SCFCTST0 PRE-ACT */
Marek Vasut38dc7562019-08-07 19:17:42 +02002222 tmp[0] = 1UL * js2[js2_trppb];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002223 mmio_write_32(DBSC_SCFCTST0,
2224 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2225
2226 /* SCFCTST1 */
2227 /* SCFCTST1 RD-WR */
2228 tmp[3] =
2229 1UL * (mmio_read_32(DBSC_DBTR(11)) & 0xff) * 800 * ddr_mbpsdiv /
2230 ddr_mbps;
2231 /* SCFCTST1 WR-RD */
2232 tmp[2] =
2233 1UL * (mmio_read_32(DBSC_DBTR(12)) & 0xff) * 800 * ddr_mbpsdiv /
2234 ddr_mbps;
2235 /* SCFCTST1 ACT-RD/WR */
Marek Vasut38dc7562019-08-07 19:17:42 +02002236 tmp[1] = 1UL * js2[js2_trcd] * 800 * ddr_mbpsdiv / ddr_mbps;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002237 /* SCFCTST1 ASYNCOFS */
2238 tmp[0] = 12;
2239 mmio_write_32(DBSC_SCFCTST1,
2240 (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]);
2241
2242 /* DBSCHRW1 */
2243 /* DBSCHRW1 SCTRFCAB */
Marek Vasut38dc7562019-08-07 19:17:42 +02002244 tmp[0] = 1UL * js2[js2_trfcab] * 800 * ddr_mbpsdiv / ddr_mbps;
2245 data_l = (((mmio_read_32(DBSC_DBTR(16)) & 0x00FF0000) >> 16)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002246 + (mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
2247 + (0x28 * 2)) * 400 * 2 * ddr_mbpsdiv / ddr_mbps + 7;
Marek Vasut38dc7562019-08-07 19:17:42 +02002248 if (tmp[0] < data_l)
2249 tmp[0] = data_l;
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002250
Marek Vasut38dc7562019-08-07 19:17:42 +02002251 if ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30)) {
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002252 mmio_write_32(DBSC_DBSCHRW1, tmp[0]
2253 + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
Marek Vasut6ad74c32019-08-08 16:34:22 +02002254 * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) /
2255 ddr_mbps - 3);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002256 } else {
2257 mmio_write_32(DBSC_DBSCHRW1, tmp[0]
2258 + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF)
Marek Vasut6ad74c32019-08-08 16:34:22 +02002259 * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) /
2260 ddr_mbps);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002261 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002262
Marek Vasut6a131772019-08-07 19:56:09 +02002263 /* QOS and CAM */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002264#ifdef ddr_qos_init_setting /* only for non qos_init */
2265 /*wbkwait(0004), wbkmdhi(4,2),wbkmdlo(1,8) */
2266 mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218);
2267 /*0(fillunit),8(dirtymax),4(dirtymin) */
2268 mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4);
2269 /*stop_tolerance */
2270 mmio_write_32(DBSC_DBSCHRW0, 0x22421111);
2271 /*rd-wr/wr-rd toggle priority */
2272 mmio_write_32(DBSC_SCFCTST2, 0x012F1123);
2273 mmio_write_32(DBSC_DBSCHSZ0, 0x00000001);
2274 mmio_write_32(DBSC_DBSCHCNT0, 0x000F0037);
2275
2276 /* QoS Settings */
2277 mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00U);
2278 mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00U);
2279 mmio_write_32(DBSC_DBSCHQOS02, 0x00000000U);
2280 mmio_write_32(DBSC_DBSCHQOS03, 0x00000000U);
2281 mmio_write_32(DBSC_DBSCHQOS40, 0x00000300U);
2282 mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0U);
2283 mmio_write_32(DBSC_DBSCHQOS42, 0x00000200U);
2284 mmio_write_32(DBSC_DBSCHQOS43, 0x00000100U);
2285 mmio_write_32(DBSC_DBSCHQOS90, 0x00000100U);
2286 mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0U);
2287 mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0U);
2288 mmio_write_32(DBSC_DBSCHQOS93, 0x00000040U);
2289 mmio_write_32(DBSC_DBSCHQOS120, 0x00000040U);
2290 mmio_write_32(DBSC_DBSCHQOS121, 0x00000030U);
2291 mmio_write_32(DBSC_DBSCHQOS122, 0x00000020U);
2292 mmio_write_32(DBSC_DBSCHQOS123, 0x00000010U);
2293 mmio_write_32(DBSC_DBSCHQOS130, 0x00000100U);
2294 mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0U);
2295 mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0U);
2296 mmio_write_32(DBSC_DBSCHQOS133, 0x00000040U);
2297 mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0U);
2298 mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0U);
2299 mmio_write_32(DBSC_DBSCHQOS142, 0x00000080U);
2300 mmio_write_32(DBSC_DBSCHQOS143, 0x00000040U);
2301 mmio_write_32(DBSC_DBSCHQOS150, 0x00000040U);
2302 mmio_write_32(DBSC_DBSCHQOS151, 0x00000030U);
2303 mmio_write_32(DBSC_DBSCHQOS152, 0x00000020U);
2304 mmio_write_32(DBSC_DBSCHQOS153, 0x00000010U);
2305
2306 mmio_write_32(QOSCTRL_RAEN, 0x00000001U);
2307#endif /* ddr_qos_init_setting */
2308 /* H3 Ver.1.1 need to set monitor function */
Marek Vasut38dc7562019-08-07 19:17:42 +02002309 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002310 mmio_write_32(DBSC_DBMONCONF4, 0x00700000);
2311 }
2312
Marek Vasut38dc7562019-08-07 19:17:42 +02002313 if (prr_product == PRR_PRODUCT_H3) {
2314 if (prr_cut == PRR_PRODUCT_10) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002315 /* resrdis, simple mode, sc off */
2316 mmio_write_32(DBSC_DBBCAMDIS, 0x00000007);
Marek Vasut38dc7562019-08-07 19:17:42 +02002317 } else if (prr_cut == PRR_PRODUCT_11) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002318 /* resrdis, simple mode */
2319 mmio_write_32(DBSC_DBBCAMDIS, 0x00000005);
Marek Vasut38dc7562019-08-07 19:17:42 +02002320 } else if (prr_cut < PRR_PRODUCT_30) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002321 /* H3 Ver.2.0 */
2322 /* resrdis */
2323 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2324 } else { /* H3 Ver.3.0(include H3N) */
2325 /* exprespque */
2326 mmio_write_32(DBSC_DBBCAMDIS, 0x00000010);
2327 }
2328 } else { /* M3-W/M3-N/V3H */
2329 /* resrdis */
2330 mmio_write_32(DBSC_DBBCAMDIS, 0x00000001);
2331 }
2332}
2333
2334static void dbsc_regset_post(void)
2335{
2336 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02002337 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002338 uint32_t slice, rdlat_max, rdlat_min;
2339
2340 rdlat_max = 0;
2341 rdlat_min = 0xffff;
2342 foreach_vch(ch) {
2343 for (cs = 0; cs < CS_CNT; cs++) {
2344 if ((ch_have_this_cs[cs] & (1U << ch)) != 0) {
2345 for (slice = 0; slice < SLICE_CNT; slice++) {
2346 ddr_setval_s(ch, slice,
2347 _reg_PHY_PER_CS_TRAINING_INDEX,
2348 cs);
Marek Vasut6ad74c32019-08-08 16:34:22 +02002349 data_l = ddr_getval_s(ch, slice,
2350 _reg_PHY_RDDQS_LATENCY_ADJUST);
Marek Vasut38dc7562019-08-07 19:17:42 +02002351 if (data_l > rdlat_max)
2352 rdlat_max = data_l;
2353 if (data_l < rdlat_min)
2354 rdlat_min = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002355 }
2356 }
2357 }
2358 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002359 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) {
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002360#if RCAR_DRAM_SPLIT == 2
2361 if (board_cnf->phyvalid == 0x05) {
2362 mmio_write_32(DBSC_DBTR(24),
2363 (rdlat_max << 24) + (rdlat_min << 16) +
2364 mmio_read_32(DBSC_DBTR(24)));
2365 } else {
2366 mmio_write_32(DBSC_DBTR(24),
2367 ((rdlat_max * 2 - rdlat_min + 4) << 24) +
2368 ((rdlat_min + 2) << 16) +
2369 mmio_read_32(DBSC_DBTR(24)));
2370 }
2371#else /*RCAR_DRAM_SPLIT == 2 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002372 mmio_write_32(DBSC_DBTR(24),
2373 ((rdlat_max * 2 - rdlat_min + 4) << 24) +
2374 ((rdlat_min + 2) << 16) +
2375 mmio_read_32(DBSC_DBTR(24)));
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09002376#endif /*RCAR_DRAM_SPLIT == 2 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002377 } else {
2378 mmio_write_32(DBSC_DBTR(24),
2379 ((rdlat_max + 2) << 24) +
2380 ((rdlat_max + 2) << 16) +
2381 mmio_read_32(DBSC_DBTR(24)));
2382 }
2383
2384 /* set ddr density information */
2385 foreach_ech(ch) {
2386 for (cs = 0; cs < CS_CNT; cs++) {
2387 if (ddr_density[ch][cs] == 0xff) {
2388 mmio_write_32(DBSC_DBMEMCONF(ch, cs), 0x00);
2389 } else {
2390 mmio_write_32(DBSC_DBMEMCONF(ch, cs),
2391 DBMEMCONF_REGD(ddr_density[ch]
2392 [cs]));
2393 }
2394 }
2395 mmio_write_32(DBSC_DBMEMCONF(ch, 2), 0x00000000);
2396 mmio_write_32(DBSC_DBMEMCONF(ch, 3), 0x00000000);
2397 }
2398
2399 mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010);
2400
2401 /*set DBI */
Marek Vasut38dc7562019-08-07 19:17:42 +02002402 if (board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002403 mmio_write_32(DBSC_DBDBICNT, 0x00000003);
2404
2405 /* H3 Ver.2.0 or later/M3-N/V3H DBI wa */
Marek Vasut6a131772019-08-07 19:56:09 +02002406 if ((((prr_product == PRR_PRODUCT_H3) &&
2407 (prr_cut > PRR_PRODUCT_11)) ||
2408 (prr_product == PRR_PRODUCT_M3N) ||
2409 (prr_product == PRR_PRODUCT_V3H)) &&
2410 board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002411 reg_ddrphy_write_a(0x00001010, 0x01000000);
2412
2413 /*set REFCYCLE */
Marek Vasut38dc7562019-08-07 19:17:42 +02002414 data_l = (get_refperiod()) * ddr_mbps / 2000 / ddr_mbpsdiv;
2415 mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002416 mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS);
Chiaki Fujii61aa8032019-03-01 20:28:55 +09002417
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002418#if RCAR_REWT_TRAINING != 0
2419 /* Periodic-WriteDQ Training seeting */
Marek Vasut6a131772019-08-07 19:56:09 +02002420 if (((prr_product == PRR_PRODUCT_H3) &&
2421 (prr_cut <= PRR_PRODUCT_11)) ||
2422 ((prr_product == PRR_PRODUCT_M3) &&
2423 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002424 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2425 } else {
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002426 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002427 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000);
2428
2429 ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04);
2430 ddr_setval_ach_as(_reg_PHY_WDQLVL_QTR_DLY_STEP, 0x0F);
2431 ddr_setval_ach_as(_reg_PHY_WDQLVL_DLY_STEP, 0x50);
2432 ddr_setval_ach_as(_reg_PHY_WDQLVL_DQDM_SLV_DLY_START, 0x0300);
2433
2434 ddr_setval_ach(_reg_PI_WDQLVL_CS_MAP,
2435 ddrtbl_getval(_cnf_DDR_PI_REGSET,
2436 _reg_PI_WDQLVL_CS_MAP));
2437 ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f);
2438 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002439 ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01);
2440 ddr_setval_ach(_reg_PI_TREF_F0, 0x0000);
2441 ddr_setval_ach(_reg_PI_TREF_F1, 0x0000);
2442 ddr_setval_ach(_reg_PI_TREF_F2, 0x0000);
2443
Marek Vasut38dc7562019-08-07 19:17:42 +02002444 if (prr_product == PRR_PRODUCT_M3) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002445 ddr_setval_ach(_reg_PI_WDQLVL_EN, 0x02);
2446 } else {
2447 ddr_setval_ach(_reg_PI_WDQLVL_EN_F1, 0x02);
2448 }
2449 ddr_setval_ach(_reg_PI_WDQLVL_PERIODIC, 0x01);
2450
2451 /* DFI_PHYMSTR_ACK , WTmode setting */
Marek Vasut6ad74c32019-08-08 16:34:22 +02002452 /* DFI_PHYMSTR_ACK: WTmode =b'01 */
2453 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002454 }
2455#endif /* RCAR_REWT_TRAINING */
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002456 /* periodic dram zqcal enable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002457 mmio_write_32(DBSC_DBCALCNF, 0x01000010);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002458
2459 /* periodic phy ctrl update enable */
Marek Vasut6a131772019-08-07 19:56:09 +02002460 if (((prr_product == PRR_PRODUCT_H3) &&
2461 (prr_cut <= PRR_PRODUCT_11)) ||
2462 ((prr_product == PRR_PRODUCT_M3) &&
2463 (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002464 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
2465 } else {
2466#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02002467 if ((prr_product == PRR_PRODUCT_H3) &&
2468 (board_cnf->phyvalid == 0x05))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002469 mmio_write_32(DBSC_DBDFICUPDCNF, 0x2a240001);
2470 else
2471 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2472#else /* RCAR_DRAM_SPLIT == 2 */
2473 mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001);
2474#endif /* RCAR_DRAM_SPLIT == 2 */
2475 }
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002476
2477#ifdef DDR_BACKUPMODE
2478 /* SRX */
2479 if (ddr_backup == DRAM_BOOT_STATUS_WARM) {
2480#ifdef DDR_BACKUPMODE_HALF /* for Half channel(ch0, 1 only) */
2481 NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n");
2482 send_dbcmd(0x0A040001);
2483 if (Prr_Product == PRR_PRODUCT_H3)
2484 send_dbcmd(0x0A140001);
2485#else /* DDR_BACKUPMODE_HALF */ /* for All channels */
2486 send_dbcmd(0x0A840001);
2487#endif /* DDR_BACKUPMODE_HALF */
2488 }
2489#endif /* DDR_BACKUPMODE */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002490
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002491 /* set Auto Refresh */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002492 mmio_write_32(DBSC_DBRFEN, 0x00000001);
Chiaki Fujiiaea02862019-09-18 13:10:00 +09002493
2494#if RCAR_REWT_TRAINING != 0
2495 /* Periodic WriteDQ Traning */
2496 if (((prr_product == PRR_PRODUCT_H3) &&
2497 (prr_cut <= PRR_PRODUCT_11)) ||
2498 ((prr_product == PRR_PRODUCT_M3) &&
2499 (prr_cut == PRR_PRODUCT_10))) {
2500 /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */
2501 } else {
2502 /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */
2503 ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100);
2504 }
2505#endif /* RCAR_REWT_TRAINING */
2506
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002507 /* dram access enable */
2508 mmio_write_32(DBSC_DBACEN, 0x00000001);
2509
Marek Vasut6ad74c32019-08-08 16:34:22 +02002510 MSG_LF(__func__ "(done)");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002511}
2512
Marek Vasut6a131772019-08-07 19:56:09 +02002513/* DFI_INIT_START */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002514static uint32_t dfi_init_start(void)
2515{
2516 uint32_t ch;
2517 uint32_t phytrainingok;
2518 uint32_t retry;
Marek Vasut38dc7562019-08-07 19:17:42 +02002519 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002520 const uint32_t RETRY_MAX = 0x10000;
2521
Marek Vasut38dc7562019-08-07 19:17:42 +02002522 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002523 /* PLL3 Disable */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002524 /* protect register interface */
2525 ddrphy_regif_idle();
2526
2527 pll3_control(0);
2528
Marek Vasut6a131772019-08-07 19:56:09 +02002529 /* init start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002530 /* dbdficnt0:
2531 * dfi_dram_clk_disable=1
2532 * dfi_frequency = 0
2533 * freq_ratio = 01 (2:1)
2534 * init_start =0
2535 */
2536 foreach_vch(ch)
2537 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10);
2538 dsb_sev();
2539
2540 /* dbdficnt0:
2541 * dfi_dram_clk_disable=1
2542 * dfi_frequency = 0
2543 * freq_ratio = 01 (2:1)
2544 * init_start =1
2545 */
2546 foreach_vch(ch)
2547 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11);
2548 dsb_sev();
2549
2550 } else {
2551 ddr_setval_ach_as(_reg_PHY_DLL_RST_EN, 0x02);
2552 dsb_sev();
2553 ddrphy_regif_idle();
2554 }
2555
2556 /* dll_rst negate */
2557 foreach_vch(ch)
2558 mmio_write_32(DBSC_DBPDCNT3(ch), 0x0000CF01);
2559 dsb_sev();
2560
Marek Vasut6a131772019-08-07 19:56:09 +02002561 /* wait init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002562 phytrainingok = 0;
2563 retry = 0;
2564 while (retry++ < RETRY_MAX) {
2565 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002566 data_l = mmio_read_32(DBSC_DBDFISTAT(ch));
2567 if (data_l & 0x00000001)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002568 phytrainingok |= (1U << ch);
2569 }
2570 dsb_sev();
2571 if (phytrainingok == ddr_phyvalid)
2572 break;
2573 if (retry % 256 == 0)
2574 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
2575 }
2576
Marek Vasut6a131772019-08-07 19:56:09 +02002577 /* all ch ok? */
2578 if ((phytrainingok & ddr_phyvalid) != ddr_phyvalid)
2579 return 0xff;
2580
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002581 /* dbdficnt0:
2582 * dfi_dram_clk_disable=0
2583 * dfi_frequency = 0
2584 * freq_ratio = 01 (2:1)
2585 * init_start =0
2586 */
2587 foreach_vch(ch)
2588 mmio_write_32(DBSC_DBDFICNT(ch), 0x00000010);
2589 dsb_sev();
2590
2591 return 0;
2592}
2593
Marek Vasut6a131772019-08-07 19:56:09 +02002594/* drivablity setting : CMOS MODE ON/OFF */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002595static void change_lpddr4_en(uint32_t mode)
2596{
2597 uint32_t ch;
2598 uint32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002599 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002600 const uint32_t _reg_PHY_PAD_DRIVE_X[3] = {
2601 _reg_PHY_PAD_ADDR_DRIVE,
2602 _reg_PHY_PAD_CLK_DRIVE,
2603 _reg_PHY_PAD_CS_DRIVE
2604 };
2605
Marek Vasut6c245a52018-12-12 18:06:39 +01002606 foreach_vch(ch) {
2607 for (i = 0; i < 3; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002608 data_l = ddr_getval(ch, _reg_PHY_PAD_DRIVE_X[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002609 if (mode) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002610 data_l |= (1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002611 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02002612 data_l &= ~(1U << 14);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002613 }
Marek Vasut38dc7562019-08-07 19:17:42 +02002614 ddr_setval(ch, _reg_PHY_PAD_DRIVE_X[i], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002615 }
2616 }
2617}
2618
Marek Vasut6a131772019-08-07 19:56:09 +02002619/* drivablity setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002620static uint32_t set_term_code(void)
2621{
2622 int32_t i;
2623 uint32_t ch, index;
Marek Vasut38dc7562019-08-07 19:17:42 +02002624 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002625 uint32_t chip_id[2];
2626 uint32_t term_code;
2627 uint32_t override;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002628 uint32_t pvtr;
2629 uint32_t pvtp;
2630 uint32_t pvtn;
Marek Vasut80784f92019-08-07 19:02:26 +02002631
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002632 term_code = ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2633 _reg_PHY_PAD_DATA_TERM);
2634 override = 0;
2635 for (i = 0; i < 2; i++)
2636 chip_id[i] = mmio_read_32(LIFEC_CHIPID(i));
2637
2638 index = 0;
2639 while (1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002640 if (termcode_by_sample[index][0] == 0xffffffff) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002641 break;
2642 }
Marek Vasut6a131772019-08-07 19:56:09 +02002643 if ((termcode_by_sample[index][0] == chip_id[0]) &&
2644 (termcode_by_sample[index][1] == chip_id[1])) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002645 term_code = termcode_by_sample[index][2];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002646 override = 1;
2647 break;
2648 }
2649 index++;
2650 }
2651
2652 if (override) {
2653 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002654 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002655 ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET,
2656 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002657 data_l = (data_l & 0xfffe0000) | term_code;
2658 ddr_setval_ach(_reg_PHY_PAD_TERM_X[index], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002659 }
Marek Vasut6a131772019-08-07 19:56:09 +02002660 } else if ((prr_product == PRR_PRODUCT_M3) &&
2661 (prr_cut == PRR_PRODUCT_10)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002662 /* non */
2663 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002664 ddr_setval_ach(_reg_PHY_PAD_TERM_X[0],
2665 (ddrtbl_getval
2666 (_cnf_DDR_PHY_ADR_G_REGSET,
2667 _reg_PHY_PAD_TERM_X[0]) & 0xFFFE0000));
2668 ddr_setval_ach(_reg_PHY_CAL_CLEAR_0, 0x01);
2669 ddr_setval_ach(_reg_PHY_CAL_START_0, 0x01);
2670 foreach_vch(ch) {
2671 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002672 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002673 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002674 } while (!(data_l & 0x00800000));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002675 }
Marek Vasut6a131772019-08-07 19:56:09 +02002676 if ((prr_product == PRR_PRODUCT_H3) &&
2677 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002678 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002679 data_l = ddr_getval(ch, _reg_PHY_PAD_TERM_X[0]);
2680 pvtr = (data_l >> 12) & 0x1f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002681 pvtr += 8;
2682 if (pvtr > 0x1f)
2683 pvtr = 0x1f;
Marek Vasut38dc7562019-08-07 19:17:42 +02002684 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002685 ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0);
Marek Vasut38dc7562019-08-07 19:17:42 +02002686 pvtn = (data_l >> 6) & 0x03f;
2687 pvtp = (data_l >> 0) & 0x03f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002688
2689 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2690 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002691 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002692 ddrtbl_getval
2693 (_cnf_DDR_PHY_ADR_G_REGSET,
2694 _reg_PHY_PAD_TERM_X[index]);
Marek Vasut38dc7562019-08-07 19:17:42 +02002695 data_l = (data_l & 0xfffe0000)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002696 | (pvtr << 12)
2697 | (pvtn << 6)
2698 | (pvtp);
2699 ddr_setval(ch,
2700 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002701 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002702 }
2703 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02002704 } else {
2705 /* M3-W Ver.1.1 or later/H3 Ver.2.0 or later/M3-N/V3H */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002706 foreach_vch(ch) {
2707 for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM;
2708 index++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002709 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002710 ddr_getval(ch,
2711 _reg_PHY_PAD_TERM_X
2712 [index]);
2713 ddr_setval(ch,
2714 _reg_PHY_PAD_TERM_X[index],
Marek Vasut38dc7562019-08-07 19:17:42 +02002715 (data_l & 0xFFFE0FFF) |
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002716 0x00015000);
2717 }
2718 }
2719 }
2720 }
Marek Vasut6a131772019-08-07 19:56:09 +02002721
Marek Vasut38dc7562019-08-07 19:17:42 +02002722 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6a131772019-08-07 19:56:09 +02002723 /* non */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002724 } else {
2725 ddr_padcal_tcompensate_getinit(override);
2726 }
Marek Vasut6a131772019-08-07 19:56:09 +02002727
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002728 return 0;
2729}
2730
Marek Vasut6a131772019-08-07 19:56:09 +02002731/* DDR mode register setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01002732static void ddr_register_set(void)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002733{
2734 int32_t fspwp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002735 uint32_t tmp;
2736
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002737 for (fspwp = 1; fspwp >= 0; fspwp--) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002738 /*MR13, fspwp */
2739 send_dbcmd(0x0e840d08 | ((2 - fspwp) << 6));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002740
2741 tmp =
2742 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002743 reg_pi_mr1_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002744 send_dbcmd(0x0e840100 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002745
2746 tmp =
2747 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002748 reg_pi_mr2_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002749 send_dbcmd(0x0e840200 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002750
2751 tmp =
2752 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002753 reg_pi_mr3_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002754 send_dbcmd(0x0e840300 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002755
2756 tmp =
2757 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002758 reg_pi_mr11_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002759 send_dbcmd(0x0e840b00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002760
2761 tmp =
2762 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002763 reg_pi_mr12_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002764 send_dbcmd(0x0e840c00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002765
2766 tmp =
2767 ddrtbl_getval(_cnf_DDR_PI_REGSET,
Marek Vasut38dc7562019-08-07 19:17:42 +02002768 reg_pi_mr14_data_fx_csx[fspwp][0]);
Marek Vasut6c245a52018-12-12 18:06:39 +01002769 send_dbcmd(0x0e840e00 | tmp);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002770 /* MR22 */
Marek Vasut6c245a52018-12-12 18:06:39 +01002771 send_dbcmd(0x0e841616);
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002772
2773 /* ZQCAL start */
2774 send_dbcmd(0x0d84004F);
2775
2776 /* ZQLAT */
2777 send_dbcmd(0x0d840051);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002778 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09002779
2780 /* MR13, fspwp */
2781 send_dbcmd(0x0e840d08);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002782}
2783
Marek Vasut6a131772019-08-07 19:56:09 +02002784/* Training handshake functions */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002785static inline uint32_t wait_freqchgreq(uint32_t assert)
2786{
Marek Vasut38dc7562019-08-07 19:17:42 +02002787 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002788 uint32_t count;
2789 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002790
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002791 count = 100000;
2792
2793 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut38dc7562019-08-07 19:17:42 +02002794 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002795 return 0;
2796 }
2797
2798 if (assert) {
2799 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002800 data_l = 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002801 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002802 data_l &= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002803 }
2804 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002805 } while (((data_l & 0x01) != 0x01) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002806 } else {
2807 do {
Marek Vasut38dc7562019-08-07 19:17:42 +02002808 data_l = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002809 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02002810 data_l |= mmio_read_32(DBSC_DBPDSTAT(ch));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002811 }
2812 count = count - 1;
Marek Vasut38dc7562019-08-07 19:17:42 +02002813 } while (((data_l & 0x01) != 0x00) & (count != 0));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002814 }
2815
2816 return (count == 0);
2817}
2818
2819static inline void set_freqchgack(uint32_t assert)
2820{
2821 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02002822 uint32_t data_l;
Marek Vasut80784f92019-08-07 19:02:26 +02002823
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002824 if (assert)
Marek Vasut38dc7562019-08-07 19:17:42 +02002825 data_l = 0x0CF20000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002826 else
Marek Vasut38dc7562019-08-07 19:17:42 +02002827 data_l = 0x00000000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002828
2829 foreach_vch(ch)
Marek Vasut38dc7562019-08-07 19:17:42 +02002830 mmio_write_32(DBSC_DBPDCNT2(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002831}
2832
2833static inline void set_dfifrequency(uint32_t freq)
2834{
2835 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02002836
Marek Vasut38dc7562019-08-07 19:17:42 +02002837 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002838 foreach_vch(ch)
2839 mmio_clrsetbits_32(DBSC_DBPDCNT1(ch), 0x1fU, freq);
2840 } else {
2841 foreach_vch(ch) {
2842 mmio_clrsetbits_32(DBSC_DBDFICNT(ch), 0x1fU << 24,
2843 (freq << 24));
2844 }
2845 }
2846 dsb_sev();
2847}
2848
2849static uint32_t pll3_freq(uint32_t on)
2850{
2851 uint32_t timeout;
2852
2853 timeout = wait_freqchgreq(1);
2854
2855 if (timeout) {
Marek Vasut6a131772019-08-07 19:56:09 +02002856 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002857 }
2858
2859 pll3_control(on);
2860 set_dfifrequency(on);
2861
2862 set_freqchgack(1);
2863 timeout = wait_freqchgreq(0);
2864 set_freqchgack(0);
2865
2866 if (timeout) {
Marek Vasut56519892019-01-21 23:11:33 +01002867 FATAL_MSG("BL2: Time out[2]\n");
Marek Vasut6a131772019-08-07 19:56:09 +02002868 return 1;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002869 }
Marek Vasut6a131772019-08-07 19:56:09 +02002870 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002871}
2872
Marek Vasut6a131772019-08-07 19:56:09 +02002873/* update dly */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002874static void update_dly(void)
2875{
2876 ddr_setval_ach(_reg_SC_PHY_MANUAL_UPDATE, 0x01);
2877 ddr_setval_ach(_reg_PHY_ADRCTL_MANUAL_UPDATE, 0x01);
2878}
2879
Marek Vasut6a131772019-08-07 19:56:09 +02002880/* training by pi */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002881static uint32_t pi_training_go(void)
2882{
2883 uint32_t flag;
Marek Vasut38dc7562019-08-07 19:17:42 +02002884 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002885 uint32_t retry;
2886 const uint32_t RETRY_MAX = 4096 * 16;
2887 uint32_t ch;
2888
2889 uint32_t mst_ch;
2890 uint32_t cur_frq;
2891 uint32_t complete;
2892 uint32_t frqchg_req;
2893
Marek Vasut6a131772019-08-07 19:56:09 +02002894 /* pi_start */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002895 ddr_setval_ach(_reg_PI_START, 0x01);
2896 foreach_vch(ch)
2897 ddr_getval(ch, _reg_PI_INT_STATUS);
2898
2899 /* set dfi_phymstr_ack = 1 */
2900 mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000001);
2901 dsb_sev();
2902
Marek Vasut6a131772019-08-07 19:56:09 +02002903 /* wait pi_int_status[0] */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002904 mst_ch = 0;
2905 flag = 0;
2906 complete = 0;
2907 cur_frq = 0;
2908 retry = RETRY_MAX;
2909 do {
2910 frqchg_req = mmio_read_32(DBSC_DBPDSTAT(mst_ch)) & 0x01;
2911
2912 /* H3 Ver.1.x cannot see frqchg_req */
Marek Vasut6a131772019-08-07 19:56:09 +02002913 if ((prr_product == PRR_PRODUCT_H3) &&
2914 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002915 if ((retry % 4096) == 1) {
2916 frqchg_req = 1;
2917 } else {
2918 frqchg_req = 0;
2919 }
2920 }
2921
2922 if (frqchg_req) {
2923 if (cur_frq) {
2924 /* Low frequency */
2925 flag = pll3_freq(0);
2926 cur_frq = 0;
2927 } else {
2928 /* High frequency */
2929 flag = pll3_freq(1);
2930 cur_frq = 1;
2931 }
2932 if (flag)
2933 break;
2934 } else {
2935 if (cur_frq) {
2936 foreach_vch(ch) {
2937 if (complete & (1U << ch))
2938 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02002939 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002940 ddr_getval(ch, _reg_PI_INT_STATUS);
Marek Vasut38dc7562019-08-07 19:17:42 +02002941 if (data_l & 0x01) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002942 complete |= (1U << ch);
2943 }
2944 }
2945 if (complete == ddr_phyvalid)
2946 break;
2947 }
2948 }
2949 } while (--retry);
2950 foreach_vch(ch) {
2951 /* dummy read */
Marek Vasut38dc7562019-08-07 19:17:42 +02002952 data_l = ddr_getval_s(ch, 0, _reg_PHY_CAL_RESULT2_OBS_0);
2953 data_l = ddr_getval(ch, _reg_PI_INT_STATUS);
2954 ddr_setval(ch, _reg_PI_INT_ACK, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002955 }
2956 if (ddrphy_regif_chk()) {
Marek Vasut6a131772019-08-07 19:56:09 +02002957 return 0xfd;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002958 }
2959 return complete;
2960}
2961
Marek Vasut6a131772019-08-07 19:56:09 +02002962/* Initialize DDR */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002963static uint32_t init_ddr(void)
2964{
2965 int32_t i;
Marek Vasut38dc7562019-08-07 19:17:42 +02002966 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002967 uint32_t phytrainingok;
Marek Vasut6c245a52018-12-12 18:06:39 +01002968 uint32_t ch, slice;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002969 uint32_t err;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09002970 int16_t adj;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002971
Marek Vasut6ad74c32019-08-08 16:34:22 +02002972 MSG_LF(__func__ ":0\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002973
2974#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02002975 rcar_dram_get_boot_status(&ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002976#endif
2977
Marek Vasut6a131772019-08-07 19:56:09 +02002978 /* unlock phy */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002979 /* Unlock DDRPHY register(AGAIN) */
2980 foreach_vch(ch)
2981 mmio_write_32(DBSC_DBPDLK(ch), 0x0000A55A);
2982 dsb_sev();
2983
Marek Vasut6a131772019-08-07 19:56:09 +02002984 if ((((prr_product == PRR_PRODUCT_H3) &&
2985 (prr_cut > PRR_PRODUCT_11)) ||
2986 (prr_product == PRR_PRODUCT_M3N) ||
2987 (prr_product == PRR_PRODUCT_V3H)) && board_cnf->dbi_en)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002988 reg_ddrphy_write_a(0x00001010, 0x01000001);
2989 else
2990 reg_ddrphy_write_a(0x00001010, 0x00000001);
Marek Vasut6a131772019-08-07 19:56:09 +02002991 /* DBSC register pre-setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002992 dbsc_regset_pre();
2993
Marek Vasut6a131772019-08-07 19:56:09 +02002994 /* load ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002995
2996 ddrtbl_load();
2997
Marek Vasut6a131772019-08-07 19:56:09 +02002998 /* configure ddrphy registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02002999 ddr_config();
3000
Marek Vasut6a131772019-08-07 19:56:09 +02003001 /* dfi_reset assert */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003002 foreach_vch(ch)
3003 mmio_write_32(DBSC_DBPDCNT0(ch), 0x01);
3004 dsb_sev();
3005
Marek Vasut6a131772019-08-07 19:56:09 +02003006 /* dbsc register set */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003007 dbsc_regset();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003008 MSG_LF(__func__ ":1\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003009
Marek Vasut6a131772019-08-07 19:56:09 +02003010 /* dfi_reset negate */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003011 foreach_vch(ch)
3012 mmio_write_32(DBSC_DBPDCNT0(ch), 0x00);
3013 dsb_sev();
3014
Marek Vasut6a131772019-08-07 19:56:09 +02003015 /* dfi_init_start (start ddrphy) */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003016 err = dfi_init_start();
3017 if (err) {
3018 return INITDRAM_ERR_I;
3019 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003020 MSG_LF(__func__ ":2\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003021
Marek Vasut6a131772019-08-07 19:56:09 +02003022 /* ddr backupmode end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003023#ifdef DDR_BACKUPMODE
Marek Vasut38dc7562019-08-07 19:17:42 +02003024 if (ddr_backup) {
Marek Vasut56519892019-01-21 23:11:33 +01003025 NOTICE("BL2: [WARM_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003026 } else {
Marek Vasut56519892019-01-21 23:11:33 +01003027 NOTICE("BL2: [COLD_BOOT]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003028 }
Marek Vasut38dc7562019-08-07 19:17:42 +02003029 err = rcar_dram_update_boot_status(ddr_backup);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003030 if (err) {
Marek Vasut56519892019-01-21 23:11:33 +01003031 NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003032 return INITDRAM_ERR_I;
3033 }
3034#endif
Marek Vasut6ad74c32019-08-08 16:34:22 +02003035 MSG_LF(__func__ ":3\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003036
Marek Vasut6a131772019-08-07 19:56:09 +02003037 /* override term code after dfi_init_complete */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003038 err = set_term_code();
3039 if (err) {
3040 return INITDRAM_ERR_I;
3041 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003042 MSG_LF(__func__ ":4\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003043
Marek Vasut6a131772019-08-07 19:56:09 +02003044 /* rx offset calibration */
3045 if ((prr_cut > PRR_PRODUCT_11) || (prr_product == PRR_PRODUCT_M3N) ||
3046 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003047 err = rx_offset_cal_hw();
3048 } else {
3049 err = rx_offset_cal();
3050 }
3051 if (err)
Marek Vasut6a131772019-08-07 19:56:09 +02003052 return INITDRAM_ERR_O;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003053 MSG_LF(__func__ ":5\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003054
Chiaki Fujiiaea02862019-09-18 13:10:00 +09003055 /* Dummy PDE */
3056 send_dbcmd(0x08840000);
3057
Marek Vasut6c245a52018-12-12 18:06:39 +01003058 /* PDX */
3059 send_dbcmd(0x08840001);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003060
Marek Vasut6a131772019-08-07 19:56:09 +02003061 /* check register i/f is alive */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003062 err = ddrphy_regif_chk();
3063 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003064 return INITDRAM_ERR_O;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003065 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003066 MSG_LF(__func__ ":6\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003067
Marek Vasut6a131772019-08-07 19:56:09 +02003068 /* phy initialize end */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003069
Marek Vasut6a131772019-08-07 19:56:09 +02003070 /* setup DDR mode registers */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003071 /* CMOS MODE */
3072 change_lpddr4_en(0);
3073
Marek Vasut6c245a52018-12-12 18:06:39 +01003074 /* MRS */
3075 ddr_register_set();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003076
Marek Vasut6a131772019-08-07 19:56:09 +02003077 /* Thermal sensor setting */
Marek Vasut6c245a52018-12-12 18:06:39 +01003078 /* THCTR Bit6: PONM=0 , Bit0: THSST=1 */
Marek Vasut38dc7562019-08-07 19:17:42 +02003079 data_l = (mmio_read_32(THS1_THCTR) & 0xFFFFFFBF) | 0x00000001;
3080 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003081
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003082 /* LPDDR4 MODE */
3083 change_lpddr4_en(1);
3084
Marek Vasut6ad74c32019-08-08 16:34:22 +02003085 MSG_LF(__func__ ":7\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003086
Marek Vasut6a131772019-08-07 19:56:09 +02003087 /* mask CS_MAP if RANKx is not found */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003088 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003089 data_l = ddr_getval(ch, _reg_PI_CS_MAP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003090 if (!(ch_have_this_cs[1] & (1U << ch)))
Marek Vasut38dc7562019-08-07 19:17:42 +02003091 data_l = data_l & 0x05;
3092 ddr_setval(ch, _reg_PI_CS_MAP, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003093 }
3094
Marek Vasut6a131772019-08-07 19:56:09 +02003095 /* exec pi_training */
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003096 reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN),
3097 BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN)));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003098 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003099
Marek Vasut38dc7562019-08-07 19:17:42 +02003100 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003101 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_EN, 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003102 } else {
3103 foreach_vch(ch) {
3104 for (slice = 0; slice < SLICE_CNT; slice++) {
3105 ddr_setval_s(ch, slice,
3106 _reg_PHY_PER_CS_TRAINING_EN,
3107 ((ch_have_this_cs[1]) >> ch)
3108 & 0x01);
3109 }
3110 }
3111 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003112
3113 phytrainingok = pi_training_go();
3114
3115 if (ddr_phyvalid != (phytrainingok & ddr_phyvalid)) {
Marek Vasut6a131772019-08-07 19:56:09 +02003116 return INITDRAM_ERR_T | phytrainingok;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003117 }
3118
Marek Vasut6ad74c32019-08-08 16:34:22 +02003119 MSG_LF(__func__ ":8\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003120
Marek Vasut6a131772019-08-07 19:56:09 +02003121 /* CACS DLY ADJUST */
Marek Vasut38dc7562019-08-07 19:17:42 +02003122 data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003123 foreach_vch(ch) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003124 for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003125 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003126 ddr_setval(ch, _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003127 data_l + adj);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003128 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003129
3130 if (ddr_phycaslice == 1) {
3131 for (i = 0; i < 6; i++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003132 adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj
3133 [i +
3134 _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]);
3135 ddr_setval_s(ch, 2,
3136 _reg_PHY_CLK_CACS_SLAVE_DELAY_X
3137 [i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003138 data_l + adj
Marek Vasut6c245a52018-12-12 18:06:39 +01003139 );
3140 }
3141 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003142 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003143
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003144 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003145 MSG_LF(__func__ ":9\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003146
Marek Vasut6a131772019-08-07 19:56:09 +02003147 /* H3 fix rd latency to avoid bug in elasitic buffer */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003148 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003149 adjust_rddqs_latency();
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003150
Marek Vasut6a131772019-08-07 19:56:09 +02003151 /* Adjust Write path latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003152 if (ddrtbl_getval
3153 (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD))
3154 adjust_wpath_latency();
3155
Marek Vasut6a131772019-08-07 19:56:09 +02003156 /* RDQLVL Training */
Marek Vasut6ad74c32019-08-08 16:34:22 +02003157 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003158 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x01);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003159
3160 err = rdqdm_man();
Marek Vasut6c245a52018-12-12 18:06:39 +01003161
Marek Vasut6ad74c32019-08-08 16:34:22 +02003162 if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE))
Marek Vasut6c245a52018-12-12 18:06:39 +01003163 ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x00);
Marek Vasut6c245a52018-12-12 18:06:39 +01003164
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003165 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003166 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003167 }
3168 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003169 MSG_LF(__func__ ":10\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003170
Marek Vasut6a131772019-08-07 19:56:09 +02003171 /* WDQLVL Training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003172 err = wdqdm_man();
3173 if (err) {
Marek Vasut6a131772019-08-07 19:56:09 +02003174 return INITDRAM_ERR_T;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003175 }
3176 update_dly();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003177 MSG_LF(__func__ ":11\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003178
Marek Vasut6a131772019-08-07 19:56:09 +02003179 /* training complete, setup DBSC */
3180 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3181 (prr_product == PRR_PRODUCT_M3N) ||
3182 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003183 ddr_setval_ach_as(_reg_PHY_DFI40_POLARITY, 0x00);
3184 ddr_setval_ach(_reg_PI_DFI40_POLARITY, 0x00);
3185 }
3186
3187 dbsc_regset_post();
Marek Vasut6ad74c32019-08-08 16:34:22 +02003188 MSG_LF(__func__ ":12\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003189
3190 return phytrainingok;
3191}
3192
Marek Vasut6a131772019-08-07 19:56:09 +02003193/* SW LEVELING COMMON */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003194static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick)
3195{
3196 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02003197 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003198 uint32_t retry;
3199 uint32_t waiting;
3200 uint32_t err;
3201
3202 const uint32_t RETRY_MAX = 0x1000;
3203
3204 err = 0;
3205 /* set EXIT -> OP_DONE is cleared */
3206 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3207
3208 /* kick */
3209 foreach_vch(ch) {
3210 if (ch_have_this_cs[ddr_csn % 2] & (1U << ch)) {
3211 ddr_setval(ch, reg_cs, ddr_csn);
3212 ddr_setval(ch, reg_kick, 0x01);
3213 }
3214 }
3215 foreach_vch(ch) {
3216 /*PREPARE ADDR REGISTER (for SWLVL_OP_DONE) */
3217 ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3218 }
3219 waiting = ch_have_this_cs[ddr_csn % 2];
3220 dsb_sev();
3221 retry = RETRY_MAX;
3222 do {
3223 foreach_vch(ch) {
3224 if (!(waiting & (1U << ch)))
3225 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02003226 data_l = ddr_getval(ch, _reg_PI_SWLVL_OP_DONE);
3227 if (data_l & 0x01)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003228 waiting &= ~(1U << ch);
3229 }
3230 retry--;
3231 } while (waiting && (retry > 0));
3232 if (retry == 0) {
3233 err = 1;
3234 }
3235
3236 dsb_sev();
3237 /* set EXIT -> OP_DONE is cleared */
3238 ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01);
3239 dsb_sev();
3240
3241 return err;
3242}
3243
Marek Vasut6a131772019-08-07 19:56:09 +02003244/* WDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003245#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003246static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3247{
3248 int32_t i, k;
3249 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003250 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003251
Marek Vasut6a131772019-08-07 19:56:09 +02003252 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003253 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003254 data_l = board_cnf->dqdm_dly_w;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003255 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003256 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003257 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3258 continue;
3259
3260 for (i = 0; i <= 8; i++) {
3261 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch))
3262 wdqdm_dly[ch][cs][slice][i] =
3263 wdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3264 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003265 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003266 wdqdm_le[ch][cs][slice][i] = 0;
3267 wdqdm_te[ch][cs][slice][i] = 0;
3268 }
3269 wdqdm_st[ch][cs][slice] = 0;
3270 wdqdm_win[ch][cs][slice] = 0;
3271 }
3272}
3273
3274static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3275{
3276 int32_t i, k;
3277 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003278 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003279 uint32_t err;
3280 const uint32_t _par_WDQLVL_RETRY_THRES = 0x7c0;
3281
3282 int32_t min_win;
3283 int32_t win;
3284 int8_t _adj;
3285 int16_t adj;
3286 uint32_t dq;
3287
Marek Vasut6a131772019-08-07 19:56:09 +02003288 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003289 err = 0;
3290 for (slice = 0; slice < SLICE_CNT; slice += 1) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003291 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003292 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3293 continue;
3294
3295 cs = ddr_csn % 2;
3296 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003297 for (i = 0; i < 9; i++) {
3298 dq = slice * 8 + i;
3299 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003300 _adj = board_cnf->ch[ch].dm_adj_w[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003301 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003302 _adj = board_cnf->ch[ch].dq_adj_w[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003303 adj = _f_scale_adj(_adj);
3304
Marek Vasut38dc7562019-08-07 19:17:42 +02003305 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003306 ddr_getval_s(ch, slice,
3307 _reg_PHY_CLK_WRX_SLAVE_DELAY[i]) + adj;
3308 ddr_setval_s(ch, slice, _reg_PHY_CLK_WRX_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003309 data_l);
3310 wdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003311 }
3312 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, 0x00);
Marek Vasut38dc7562019-08-07 19:17:42 +02003313 data_l = ddr_getval_s(ch, slice, _reg_PHY_WDQLVL_STATUS_OBS);
3314 wdqdm_st[ch][cs][slice] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003315 min_win = INT_LEAST32_MAX;
3316 for (i = 0; i <= 8; i++) {
3317 ddr_setval_s(ch, slice, _reg_PHY_WDQLVL_DQDM_OBS_SELECT,
3318 i);
3319
Marek Vasut38dc7562019-08-07 19:17:42 +02003320 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003321 ddr_getval_s(ch, slice,
3322 _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003323 wdqdm_te[ch][cs][slice][i] = data_l;
3324 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003325 ddr_getval_s(ch, slice,
3326 _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003327 wdqdm_le[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003328 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003329 (int32_t)wdqdm_te[ch][cs][slice][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003330 wdqdm_le[ch][cs][slice][i];
3331 if (min_win > win)
3332 min_win = win;
Marek Vasut38dc7562019-08-07 19:17:42 +02003333 if (data_l >= _par_WDQLVL_RETRY_THRES)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003334 err = 2;
3335 }
3336 wdqdm_win[ch][cs][slice] = min_win;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003337 if ((prr_product == PRR_PRODUCT_H3) &&
3338 (prr_cut <= PRR_PRODUCT_11)) {
3339 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3340 0x01);
Marek Vasut6c245a52018-12-12 18:06:39 +01003341 } else {
3342 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN,
3343 ((ch_have_this_cs[1]) >> ch) & 0x01);
3344 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003345 }
3346 return err;
3347}
Marek Vasut6c245a52018-12-12 18:06:39 +01003348#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003349
3350static void wdqdm_cp(uint32_t ddr_csn, uint32_t restore)
3351{
3352 uint32_t i;
3353 uint32_t ch, slice;
3354 uint32_t tgt_cs, src_cs;
3355 uint32_t tmp_r;
3356
Marek Vasut6a131772019-08-07 19:56:09 +02003357 /* copy of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003358 foreach_vch(ch) {
3359 for (tgt_cs = 0; tgt_cs < CS_CNT; tgt_cs++) {
3360 for (slice = 0; slice < SLICE_CNT; slice++) {
3361 ddr_setval_s(ch, slice,
3362 _reg_PHY_PER_CS_TRAINING_INDEX,
3363 tgt_cs);
3364 src_cs = ddr_csn % 2;
3365 if (!(ch_have_this_cs[1] & (1U << ch)))
3366 src_cs = 0;
3367 for (i = 0; i <= 4; i += 4) {
3368 if (restore)
3369 tmp_r =
3370 rdqdm_dly[ch][tgt_cs][slice]
3371 [i];
3372 else
3373 tmp_r =
3374 rdqdm_dly[ch][src_cs][slice]
3375 [i];
3376
3377 ddr_setval_s(ch, slice,
3378 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY
3379 [i], tmp_r);
3380 }
3381 }
3382 }
3383 }
3384}
3385
3386static uint32_t wdqdm_man1(void)
3387{
3388 int32_t k;
3389 uint32_t ch, cs, slice;
3390 uint32_t ddr_csn;
Marek Vasut38dc7562019-08-07 19:17:42 +02003391 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003392 uint32_t err;
Marek Vasut6c245a52018-12-12 18:06:39 +01003393 uint32_t high_dq[DRAM_CH_CNT];
3394 uint32_t mr14_csab0_bak[DRAM_CH_CNT];
3395#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003396 uint32_t err_flg;
Marek Vasut6c245a52018-12-12 18:06:39 +01003397#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003398
Marek Vasut6a131772019-08-07 19:56:09 +02003399 /* manual execution of training */
Marek Vasut38dc7562019-08-07 19:17:42 +02003400 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003401 foreach_vch(ch) {
3402 high_dq[ch] = 0;
3403 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003404 k = (board_cnf->ch[ch].dqs_swap >>
3405 (4 * slice)) & 0x0f;
Marek Vasut6c245a52018-12-12 18:06:39 +01003406 if (k >= 2)
3407 high_dq[ch] |= (1U << slice);
3408 }
3409 ddr_setval(ch, _reg_PI_16BIT_DRAM_CONNECT, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003410 }
3411 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003412 err = 0;
3413 /* CLEAR PREV RESULT */
3414 for (cs = 0; cs < CS_CNT; cs++) {
3415 ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_INDEX, cs);
Marek Vasut6a131772019-08-07 19:56:09 +02003416 if (((prr_product == PRR_PRODUCT_H3) &&
3417 (prr_cut > PRR_PRODUCT_11)) ||
3418 (prr_product == PRR_PRODUCT_M3N) ||
3419 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003420 ddr_setval_ach_as(_reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS,
3421 0x01);
3422 } else {
3423 ddr_setval_ach_as(_reg_PHY_WDQLVL_CLR_PREV_RESULTS,
3424 0x01);
3425 }
3426 }
3427 ddrphy_regif_idle();
3428
Marek Vasut6c245a52018-12-12 18:06:39 +01003429#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003430 err_flg = 0;
Marek Vasut6c245a52018-12-12 18:06:39 +01003431#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003432 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Marek Vasut6a131772019-08-07 19:56:09 +02003433 if ((prr_product == PRR_PRODUCT_H3) &&
3434 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003435 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003436 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3437 data_l &= ~(0x00ffU << 16);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003438
3439 if (ddr_csn >= 2)
3440 k = (high_dq[ch] ^ 0x0f);
3441 else
3442 k = high_dq[ch];
Marek Vasut38dc7562019-08-07 19:17:42 +02003443 data_l |= (k << 16);
3444 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003445 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, k);
3446 }
3447 }
Marek Vasut6a131772019-08-07 19:56:09 +02003448 if (((prr_product == PRR_PRODUCT_H3) &&
3449 (prr_cut <= PRR_PRODUCT_11)) ||
3450 ((prr_product == PRR_PRODUCT_M3) &&
3451 (prr_cut == PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003452 wdqdm_cp(ddr_csn, 0);
3453 }
3454
3455 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003456 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003457 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003458 reg_pi_mr14_data_fx_csx[1][ddr_csn]);
3459 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003460 }
3461
3462 /* KICK WDQLVL */
3463 err = swlvl1(ddr_csn, _reg_PI_WDQLVL_CS, _reg_PI_WDQLVL_REQ);
3464 if (err)
3465 goto err_exit;
3466
3467 if (ddr_csn == 0)
3468 foreach_vch(ch) {
3469 mr14_csab0_bak[ch] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003470 ddr_getval(ch, reg_pi_mr14_data_fx_csx[1][0]);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003471 } else
3472 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003473 ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0],
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003474 mr14_csab0_bak[ch]);
3475 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003476#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003477 foreach_vch(ch) {
3478 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3479 wdqdm_clr1(ch, ddr_csn);
3480 continue;
3481 }
3482 err = wdqdm_ana1(ch, ddr_csn);
3483 if (err)
3484 err_flg |= (1U << (ddr_csn * 4 + ch));
3485 ddrphy_regif_idle();
3486 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003487#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003488 }
3489err_exit:
Marek Vasut6c245a52018-12-12 18:06:39 +01003490#ifndef DDR_FAST_INIT
3491 err |= err_flg;
3492#endif/* DDR_FAST_INIT */
Marek Vasut38dc7562019-08-07 19:17:42 +02003493 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003494 ddr_setval_ach(_reg_PI_16BIT_DRAM_CONNECT, 0x01);
3495 foreach_vch(ch) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003496 data_l = mmio_read_32(DBSC_DBDFICNT(ch));
3497 data_l &= ~(0x00ffU << 16);
3498 mmio_write_32(DBSC_DBDFICNT(ch), data_l);
Marek Vasut6c245a52018-12-12 18:06:39 +01003499 ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, 0x00);
3500 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003501 }
Marek Vasut6a131772019-08-07 19:56:09 +02003502 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003503}
3504
3505static uint32_t wdqdm_man(void)
3506{
3507 uint32_t err, retry_cnt;
3508 const uint32_t retry_max = 0x10;
Chiaki Fujii8c2f32d2019-12-06 19:33:34 +09003509 uint32_t datal, ch, ddr_csn, mr14_bkup[4][4];
3510
3511 datal = RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2 + 19;
3512 if ((mmio_read_32(DBSC_DBTR(11)) & 0xFF) > datal)
3513 datal = mmio_read_32(DBSC_DBTR(11)) & 0xFF;
3514 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW, datal);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003515
Marek Vasut6a131772019-08-07 19:56:09 +02003516 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) ||
3517 (prr_product == PRR_PRODUCT_M3N) ||
3518 (prr_product == PRR_PRODUCT_V3H)) {
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003519 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F0,
3520 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003521 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F1,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003522 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003523 } else {
3524 ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR,
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003525 (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003526 }
Chiaki Fujiifd1ec702019-07-08 23:44:56 +09003527 ddr_setval_ach(_reg_PI_TRFC_F0, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
3528 ddr_setval_ach(_reg_PI_TRFC_F1, mmio_read_32(DBSC_DBTR(13)) & 0x1FF);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003529
3530 retry_cnt = 0;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003531 err = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003532 do {
Marek Vasut6a131772019-08-07 19:56:09 +02003533 if ((prr_product == PRR_PRODUCT_H3) &&
3534 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003535 err = wdqdm_man1();
3536 } else {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003537 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x01);
3538 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3539 0x01);
Marek Vasut6a131772019-08-07 19:56:09 +02003540 if ((prr_product == PRR_PRODUCT_M3N) ||
3541 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003542 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3543 0x0C);
3544 } else {
3545 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x0C);
3546 }
3547 dsb_sev();
3548 err = wdqdm_man1();
3549 foreach_vch(ch) {
3550 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3551 mr14_bkup[ch][ddr_csn] =
3552 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003553 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003554 [1][ddr_csn]);
3555 dsb_sev();
3556 }
3557 }
3558
Marek Vasut6a131772019-08-07 19:56:09 +02003559 if ((prr_product == PRR_PRODUCT_M3N) ||
3560 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003561 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3562 0x04);
3563 } else {
3564 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x04);
3565 }
3566 pvtcode_update();
3567 err = wdqdm_man1();
3568 foreach_vch(ch) {
3569 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
3570 mr14_bkup[ch][ddr_csn] =
3571 (mr14_bkup[ch][ddr_csn] +
3572 ddr_getval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003573 reg_pi_mr14_data_fx_csx
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003574 [1][ddr_csn])) / 2;
3575 ddr_setval(ch,
Marek Vasut38dc7562019-08-07 19:17:42 +02003576 reg_pi_mr14_data_fx_csx[1]
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003577 [ddr_csn],
3578 mr14_bkup[ch][ddr_csn]);
3579 }
3580 }
3581
3582 ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE,
3583 0x00);
Marek Vasut6a131772019-08-07 19:56:09 +02003584 if ((prr_product == PRR_PRODUCT_M3N) ||
3585 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003586 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1,
3587 0x00);
3588 ddr_setval_ach
3589 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1,
3590 0x00);
3591 ddr_setval_ach
3592 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1,
3593 0x00);
3594 } else {
3595 ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x00);
3596 ddr_setval_ach
3597 (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT,
3598 0x00);
3599 ddr_setval_ach
3600 (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT,
3601 0x00);
3602 }
3603 ddr_setval_ach(_reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE,
3604 0x00);
3605
3606 pvtcode_update2();
3607 err = wdqdm_man1();
3608 ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00);
3609 }
3610 } while (err && (++retry_cnt < retry_max));
3611
Marek Vasut6a131772019-08-07 19:56:09 +02003612 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
3613 ((prr_product == PRR_PRODUCT_M3) && (prr_cut <= PRR_PRODUCT_10))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003614 wdqdm_cp(0, 1);
3615 }
3616
3617 return (retry_cnt >= retry_max);
3618}
3619
Marek Vasut6a131772019-08-07 19:56:09 +02003620/* RDQ TRAINING */
Marek Vasut6c245a52018-12-12 18:06:39 +01003621#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003622static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn)
3623{
3624 int32_t i, k;
3625 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003626 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003627
Marek Vasut6a131772019-08-07 19:56:09 +02003628 /* clr of training results buffer */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003629 cs = ddr_csn % 2;
Marek Vasut38dc7562019-08-07 19:17:42 +02003630 data_l = board_cnf->dqdm_dly_r;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003631 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003632 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003633 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3634 continue;
3635
3636 for (i = 0; i <= 8; i++) {
3637 if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) {
3638 rdqdm_dly[ch][cs][slice][i] =
3639 rdqdm_dly[ch][CS_CNT - 1 - cs][slice][i];
3640 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3641 rdqdm_dly[ch][CS_CNT - 1 - cs][slice +
3642 SLICE_CNT]
3643 [i];
3644 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02003645 rdqdm_dly[ch][cs][slice][i] = data_l;
Marek Vasut6ad74c32019-08-08 16:34:22 +02003646 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] =
3647 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003648 }
3649 rdqdm_le[ch][cs][slice][i] = 0;
3650 rdqdm_le[ch][cs][slice + SLICE_CNT][i] = 0;
3651 rdqdm_te[ch][cs][slice][i] = 0;
3652 rdqdm_te[ch][cs][slice + SLICE_CNT][i] = 0;
3653 rdqdm_nw[ch][cs][slice][i] = 0;
3654 rdqdm_nw[ch][cs][slice + SLICE_CNT][i] = 0;
3655 }
3656 rdqdm_st[ch][cs][slice] = 0;
3657 rdqdm_win[ch][cs][slice] = 0;
3658 }
3659}
3660
3661static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn)
3662{
3663 int32_t i, k;
3664 uint32_t cs, slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003665 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003666 uint32_t err;
3667 int8_t _adj;
3668 int16_t adj;
3669 uint32_t dq;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003670 int32_t min_win;
3671 int32_t win;
3672 uint32_t rdq_status_obs_select;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003673
Marek Vasut6a131772019-08-07 19:56:09 +02003674 /* analysis of training results */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003675 err = 0;
3676 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003677 k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003678 if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2)))
3679 continue;
3680
3681 cs = ddr_csn % 2;
3682 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs);
3683 ddrphy_regif_idle();
3684
3685 ddr_getval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX);
3686 ddrphy_regif_idle();
3687
3688 for (i = 0; i <= 8; i++) {
3689 dq = slice * 8 + i;
3690 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003691 _adj = board_cnf->ch[ch].dm_adj_r[slice];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003692 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003693 _adj = board_cnf->ch[ch].dq_adj_r[dq];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003694
3695 adj = _f_scale_adj(_adj);
3696
Marek Vasut38dc7562019-08-07 19:17:42 +02003697 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003698 ddr_getval_s(ch, slice,
3699 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) +
3700 adj;
3701 ddr_setval_s(ch, slice,
3702 _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003703 data_l);
3704 rdqdm_dly[ch][cs][slice][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003705
Marek Vasut38dc7562019-08-07 19:17:42 +02003706 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003707 ddr_getval_s(ch, slice,
3708 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) +
3709 adj;
3710 ddr_setval_s(ch, slice,
3711 _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i],
Marek Vasut38dc7562019-08-07 19:17:42 +02003712 data_l);
3713 rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003714 }
3715 min_win = INT_LEAST32_MAX;
3716 for (i = 0; i <= 8; i++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02003717 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003718 ddr_getval_s(ch, slice, _reg_PHY_RDLVL_STATUS_OBS);
Marek Vasut38dc7562019-08-07 19:17:42 +02003719 rdqdm_st[ch][cs][slice] = data_l;
3720 rdqdm_st[ch][cs][slice + SLICE_CNT] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003721 /* k : rise/fall */
3722 for (k = 0; k < 2; k++) {
3723 if (i == 8) {
3724 rdq_status_obs_select = 16 + 8 * k;
3725 } else {
3726 rdq_status_obs_select = i + k * 8;
3727 }
3728 ddr_setval_s(ch, slice,
3729 _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT,
3730 rdq_status_obs_select);
3731
Marek Vasut38dc7562019-08-07 19:17:42 +02003732 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003733 ddr_getval_s(ch, slice,
3734 _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS);
3735 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003736 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003737
Marek Vasut38dc7562019-08-07 19:17:42 +02003738 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003739 ddr_getval_s(ch, slice,
3740 _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS);
3741 rdqdm_te[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003742 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003743
Marek Vasut38dc7562019-08-07 19:17:42 +02003744 data_l =
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003745 ddr_getval_s(ch, slice,
3746 _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS);
3747 rdqdm_nw[ch][cs][slice + SLICE_CNT * k][i] =
Marek Vasut38dc7562019-08-07 19:17:42 +02003748 data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003749
3750 win =
Marek Vasut80784f92019-08-07 19:02:26 +02003751 (int32_t)rdqdm_te[ch][cs][slice +
Marek Vasut6ad74c32019-08-08 16:34:22 +02003752 SLICE_CNT *
3753 k][i] -
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003754 rdqdm_le[ch][cs][slice + SLICE_CNT * k][i];
3755 if (i != 8) {
3756 if (min_win > win)
3757 min_win = win;
3758 }
3759 }
3760 }
3761 rdqdm_win[ch][cs][slice] = min_win;
3762 if (min_win <= 0) {
3763 err = 2;
3764 }
3765 }
Marek Vasut6a131772019-08-07 19:56:09 +02003766 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003767}
Marek Vasut6c245a52018-12-12 18:06:39 +01003768#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003769
3770static uint32_t rdqdm_man1(void)
3771{
3772 uint32_t ch;
3773 uint32_t ddr_csn;
Marek Vasut6c245a52018-12-12 18:06:39 +01003774#ifdef DDR_FAST_INIT
3775 uint32_t slice;
Marek Vasut38dc7562019-08-07 19:17:42 +02003776 uint32_t i, adj, data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003777#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003778 uint32_t err;
3779
Marek Vasut6a131772019-08-07 19:56:09 +02003780 /* manual execution of training */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003781 err = 0;
3782
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003783 for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003784 /* KICK RDQLVL */
3785 err = swlvl1(ddr_csn, _reg_PI_RDLVL_CS, _reg_PI_RDLVL_REQ);
3786 if (err)
3787 goto err_exit;
Marek Vasut6c245a52018-12-12 18:06:39 +01003788#ifndef DDR_FAST_INIT
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003789 foreach_vch(ch) {
3790 if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) {
3791 rdqdm_clr1(ch, ddr_csn);
3792 ddrphy_regif_idle();
3793 continue;
3794 }
3795 err = rdqdm_ana1(ch, ddr_csn);
3796 ddrphy_regif_idle();
3797 if (err)
3798 goto err_exit;
3799 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003800#else/* DDR_FAST_INIT */
3801 foreach_vch(ch) {
3802 if (ch_have_this_cs[ddr_csn] & (1U << ch)) {
3803 for (slice = 0; slice < SLICE_CNT; slice++) {
3804 if (ddr_getval_s(ch, slice,
Marek Vasut80784f92019-08-07 19:02:26 +02003805 _reg_PHY_RDLVL_STATUS_OBS) !=
Marek Vasut6c245a52018-12-12 18:06:39 +01003806 0x0D00FFFF) {
3807 err = (1U << ch) |
3808 (0x10U << slice);
3809 goto err_exit;
3810 }
3811 }
3812 }
Marek Vasut6a131772019-08-07 19:56:09 +02003813 if (((prr_product == PRR_PRODUCT_H3) &&
3814 (prr_cut <= PRR_PRODUCT_11)) ||
3815 ((prr_product == PRR_PRODUCT_M3) &&
3816 (prr_cut <= PRR_PRODUCT_10))) {
Marek Vasut6c245a52018-12-12 18:06:39 +01003817 for (slice = 0; slice < SLICE_CNT; slice++) {
3818 for (i = 0; i <= 8; i++) {
3819 if (i == 8)
Marek Vasut38dc7562019-08-07 19:17:42 +02003820 adj = _f_scale_adj(board_cnf->ch[ch].dm_adj_r[slice]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003821 else
Marek Vasut38dc7562019-08-07 19:17:42 +02003822 adj = _f_scale_adj(board_cnf->ch[ch].dq_adj_r[slice * 8 + i]);
Marek Vasut6c245a52018-12-12 18:06:39 +01003823 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, ddr_csn);
Marek Vasut38dc7562019-08-07 19:17:42 +02003824 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + adj;
3825 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], data_l);
3826 rdqdm_dly[ch][ddr_csn][slice][i] = data_l;
3827 rdqdm_dly[ch][ddr_csn | 1][slice][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003828
Marek Vasut38dc7562019-08-07 19:17:42 +02003829 data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + adj;
3830 ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], data_l);
3831 rdqdm_dly[ch][ddr_csn][slice + SLICE_CNT][i] = data_l;
3832 rdqdm_dly[ch][ddr_csn | 1][slice + SLICE_CNT][i] = data_l;
Marek Vasut6c245a52018-12-12 18:06:39 +01003833 }
3834 }
3835 }
3836 }
3837 ddrphy_regif_idle();
3838
3839#endif/* DDR_FAST_INIT */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003840 }
Marek Vasut6c245a52018-12-12 18:06:39 +01003841
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003842err_exit:
Marek Vasut6a131772019-08-07 19:56:09 +02003843 return err;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003844}
3845
3846static uint32_t rdqdm_man(void)
3847{
3848 uint32_t err, retry_cnt;
3849 const uint32_t retry_max = 0x01;
3850
3851 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3852 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3853 _reg_PHY_DQ_TSEL_ENABLE));
3854 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3855 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3856 _reg_PHY_DQS_TSEL_ENABLE));
3857 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3858 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3859 _reg_PHY_DQ_TSEL_SELECT));
3860 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3861 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3862 _reg_PHY_DQS_TSEL_SELECT));
3863
3864 retry_cnt = 0;
3865 do {
3866 err = rdqdm_man1();
3867 ddrphy_regif_idle();
3868 } while (err && (++retry_cnt < retry_max));
3869 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE,
3870 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3871 _reg_PHY_DQ_TSEL_ENABLE));
3872 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE,
3873 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3874 _reg_PHY_DQS_TSEL_ENABLE));
3875 ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT,
3876 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3877 _reg_PHY_DQ_TSEL_SELECT));
3878 ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT,
3879 ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET,
3880 _reg_PHY_DQS_TSEL_SELECT));
3881
3882 return (retry_cnt >= retry_max);
3883}
3884
Marek Vasut6a131772019-08-07 19:56:09 +02003885/* rx offset calibration */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003886static int32_t _find_change(uint64_t val, uint32_t dir)
3887{
3888 int32_t i;
3889 uint32_t startval;
3890 uint32_t curval;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003891 const int32_t VAL_END = 0x3f;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003892
3893 if (dir == 0) {
3894 startval = (val & 0x01);
3895 for (i = 1; i <= VAL_END; i++) {
3896 curval = (val >> i) & 0x01;
3897 if (curval != startval)
Marek Vasut6a131772019-08-07 19:56:09 +02003898 return i;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003899 }
Marek Vasut6a131772019-08-07 19:56:09 +02003900 return VAL_END;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003901 }
Marek Vasut6ad74c32019-08-08 16:34:22 +02003902
3903 startval = (val >> dir) & 0x01;
3904 for (i = dir - 1; i >= 0; i--) {
3905 curval = (val >> i) & 0x01;
3906 if (curval != startval)
3907 return i;
3908 }
3909 return 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003910}
3911
3912static uint32_t _rx_offset_cal_updn(uint32_t code)
3913{
3914 const uint32_t CODE_MAX = 0x40;
3915 uint32_t tmp;
3916
Marek Vasut38dc7562019-08-07 19:17:42 +02003917 if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003918 if (code == 0)
3919 tmp = (1U << 6) | (CODE_MAX - 1);
3920 else if (code <= 0x20)
3921 tmp =
3922 ((CODE_MAX - 1 -
3923 (0x20 - code) * 2) << 6) | (CODE_MAX - 1);
3924 else
3925 tmp =
3926 ((CODE_MAX - 1) << 6) | (CODE_MAX - 1 -
3927 (code - 0x20) * 2);
3928 } else {
3929 if (code == 0)
3930 tmp = (1U << 6) | (CODE_MAX - 1);
3931 else
3932 tmp = (code << 6) | (CODE_MAX - code);
3933 }
3934 return tmp;
3935}
3936
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003937static uint32_t rx_offset_cal(void)
3938{
3939 uint32_t index;
3940 uint32_t code;
3941 const uint32_t CODE_MAX = 0x40;
3942 const uint32_t CODE_STEP = 2;
3943 uint32_t ch, slice;
3944 uint32_t tmp;
3945 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
3946 uint64_t val[DRAM_CH_CNT][SLICE_CNT][_reg_PHY_RX_CAL_X_NUM];
Chiaki Fujii59263ee2019-05-17 10:45:02 +09003947 uint64_t tmpval;
3948 int32_t lsb, msb;
Marek Vasut6c245a52018-12-12 18:06:39 +01003949
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003950 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x01);
3951 foreach_vch(ch) {
3952 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003953 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003954 val[ch][slice][index] = 0;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003955 }
3956 }
3957
3958 for (code = 0; code < CODE_MAX / CODE_STEP; code++) {
3959 tmp = _rx_offset_cal_updn(code * CODE_STEP);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003960 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) {
3961 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[index], tmp);
3962 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003963 dsb_sev();
Marek Vasut80784f92019-08-07 19:02:26 +02003964 ddr_getval_ach_as(_reg_PHY_RX_CAL_OBS, (uint32_t *)tmp_ach_as);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003965
3966 foreach_vch(ch) {
3967 for (slice = 0; slice < SLICE_CNT; slice++) {
3968 tmp = tmp_ach_as[ch][slice];
3969 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3970 index++) {
3971 if (tmp & (1U << index)) {
3972 val[ch][slice][index] |=
3973 (1ULL << code);
3974 } else {
3975 val[ch][slice][index] &=
3976 ~(1ULL << code);
3977 }
3978 }
3979 }
3980 }
3981 }
3982 foreach_vch(ch) {
3983 for (slice = 0; slice < SLICE_CNT; slice++) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02003984 for (index = 0; index < _reg_PHY_RX_CAL_X_NUM;
3985 index++) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02003986 tmpval = val[ch][slice][index];
3987 lsb = _find_change(tmpval, 0);
3988 msb =
3989 _find_change(tmpval,
3990 (CODE_MAX / CODE_STEP) - 1);
3991 tmp = (lsb + msb) >> 1;
3992
3993 tmp = _rx_offset_cal_updn(tmp * CODE_STEP);
3994 ddr_setval_s(ch, slice,
3995 _reg_PHY_RX_CAL_X[index], tmp);
3996 }
3997 }
3998 }
3999 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004000
4001 return 0;
4002}
4003
4004static uint32_t rx_offset_cal_hw(void)
4005{
4006 uint32_t ch, slice;
4007 uint32_t retry;
4008 uint32_t complete;
4009 uint32_t tmp;
4010 uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT];
4011
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004012 ddr_setval_ach_as(_reg_PHY_RX_CAL_X[9], 0x00);
4013 ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00);
4014 ddr_setval_ach_as(_reg_PHY_RX_CAL_SAMPLE_WAIT, 0x0f);
4015
4016 retry = 0;
4017 while (retry < 4096) {
4018 if ((retry & 0xff) == 0) {
4019 ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01);
4020 }
4021 foreach_vch(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004022 for (slice = 0; slice < SLICE_CNT; slice++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004023 tmp_ach_as[ch][slice] =
4024 ddr_getval_s(ch, slice, _reg_PHY_RX_CAL_X[9]);
4025
4026 complete = 1;
4027 foreach_vch(ch) {
4028 for (slice = 0; slice < SLICE_CNT; slice++) {
4029 tmp = tmp_ach_as[ch][slice];
4030 tmp = (tmp & 0x3f) + ((tmp >> 6) & 0x3f);
Marek Vasut6a131772019-08-07 19:56:09 +02004031 if (((prr_product == PRR_PRODUCT_H3) &&
4032 (prr_cut > PRR_PRODUCT_11)) ||
4033 (prr_product == PRR_PRODUCT_M3N) ||
4034 (prr_product == PRR_PRODUCT_V3H)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004035 if (tmp != 0x3E)
4036 complete = 0;
4037 } else {
4038 if (tmp != 0x40)
4039 complete = 0;
4040 }
4041 }
4042 }
4043 if (complete)
4044 break;
4045
4046 retry++;
4047 }
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004048
4049 return (complete == 0);
4050}
4051
Marek Vasut6a131772019-08-07 19:56:09 +02004052/* adjust rddqs latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004053static void adjust_rddqs_latency(void)
4054{
4055 uint32_t ch, slice;
4056 uint32_t dly;
4057 uint32_t maxlatx2;
4058 uint32_t tmp;
4059 uint32_t rdlat_adjx2[SLICE_CNT];
Marek Vasut80784f92019-08-07 19:02:26 +02004060
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004061 foreach_vch(ch) {
4062 maxlatx2 = 0;
4063 for (slice = 0; slice < SLICE_CNT; slice++) {
4064 ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX,
4065 0x00);
4066
4067 dly =
4068 ddr_getval_s(ch, slice,
4069 _reg_PHY_RDDQS_GATE_SLAVE_DELAY);
4070 tmp =
4071 ddr_getval_s(ch, slice,
4072 _reg_PHY_RDDQS_LATENCY_ADJUST);
4073 /* note gate_slave_delay[9] is always 0 */
4074 tmp = (tmp << 1) + (dly >> 8);
4075 rdlat_adjx2[slice] = tmp;
4076 if (maxlatx2 < tmp)
4077 maxlatx2 = tmp;
4078 }
4079 maxlatx2 = ((maxlatx2 + 1) >> 1) << 1;
4080 for (slice = 0; slice < SLICE_CNT; slice++) {
4081 tmp = maxlatx2 - rdlat_adjx2[slice];
4082 tmp = (tmp >> 1);
4083 if (tmp) {
4084 ddr_setval_s(ch, slice, _reg_PHY_RPTR_UPDATE,
4085 ddr_getval_s(ch, slice,
4086 _reg_PHY_RPTR_UPDATE)
4087 + 1);
4088 }
4089 }
4090 }
4091}
4092
Marek Vasut6a131772019-08-07 19:56:09 +02004093/* adjust wpath latency */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004094static void adjust_wpath_latency(void)
4095{
4096 uint32_t ch, cs, slice;
4097 uint32_t dly;
4098 uint32_t wpath_add;
4099 const uint32_t _par_EARLY_THRESHOLD_VAL = 0x180;
4100
4101 foreach_vch(ch) {
4102 for (slice = 0; slice < SLICE_CNT; slice += 1) {
4103 for (cs = 0; cs < CS_CNT; cs++) {
4104 ddr_setval_s(ch, slice,
4105 _reg_PHY_PER_CS_TRAINING_INDEX,
4106 cs);
4107 ddr_getval_s(ch, slice,
4108 _reg_PHY_PER_CS_TRAINING_INDEX);
4109 dly =
4110 ddr_getval_s(ch, slice,
4111 _reg_PHY_CLK_WRDQS_SLAVE_DELAY);
4112 if (dly <= _par_EARLY_THRESHOLD_VAL)
4113 continue;
4114
4115 wpath_add =
4116 ddr_getval_s(ch, slice,
4117 _reg_PHY_WRITE_PATH_LAT_ADD);
4118 ddr_setval_s(ch, slice,
4119 _reg_PHY_WRITE_PATH_LAT_ADD,
4120 wpath_add - 1);
4121 }
4122 }
4123 }
4124}
4125
Marek Vasut6a131772019-08-07 19:56:09 +02004126/* DDR Initialize entry */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004127int32_t rcar_dram_init(void)
4128{
4129 uint32_t ch, cs;
Marek Vasut38dc7562019-08-07 19:17:42 +02004130 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004131 uint32_t bus_mbps, bus_mbpsdiv;
4132 uint32_t tmp_tccd;
4133 uint32_t failcount;
Marek Vasut38dc7562019-08-07 19:17:42 +02004134 uint32_t cnf_boardtype;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004135
Marek Vasut6a131772019-08-07 19:56:09 +02004136 /* Thermal sensor setting */
Marek Vasut38dc7562019-08-07 19:17:42 +02004137 data_l = mmio_read_32(CPG_MSTPSR5);
4138 if (data_l & BIT(22)) { /* case THS/TSC Standby */
Marek Vasut6a131772019-08-07 19:56:09 +02004139 data_l &= ~BIT(22);
Marek Vasut38dc7562019-08-07 19:17:42 +02004140 cpg_write_32(CPG_SMSTPCR5, data_l);
Marek Vasut6a131772019-08-07 19:56:09 +02004141 while (mmio_read_32(CPG_MSTPSR5) & BIT(22))
4142 ; /* wait bit=0 */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004143 }
4144
4145 /* THCTR Bit6: PONM=0 , Bit0: THSST=0 */
Marek Vasut38dc7562019-08-07 19:17:42 +02004146 data_l = mmio_read_32(THS1_THCTR) & 0xFFFFFFBE;
4147 mmio_write_32(THS1_THCTR, data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004148
Marek Vasut6a131772019-08-07 19:56:09 +02004149 /* Judge product and cut */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004150#ifdef RCAR_DDR_FIXED_LSI_TYPE
Marek Vasut80784f92019-08-07 19:02:26 +02004151#if (RCAR_LSI == RCAR_AUTO)
Marek Vasut38dc7562019-08-07 19:17:42 +02004152 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4153 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004154#else /* RCAR_LSI */
4155#ifndef RCAR_LSI_CUT
Marek Vasut38dc7562019-08-07 19:17:42 +02004156 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004157#endif /* RCAR_LSI_CUT */
4158#endif /* RCAR_LSI */
4159#else /* RCAR_DDR_FIXED_LSI_TYPE */
Marek Vasut38dc7562019-08-07 19:17:42 +02004160 prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK;
4161 prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004162#endif /* RCAR_DDR_FIXED_LSI_TYPE */
4163
Marek Vasut38dc7562019-08-07 19:17:42 +02004164 if (prr_product == PRR_PRODUCT_H3) {
4165 if (prr_cut <= PRR_PRODUCT_11) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004166 p_ddr_regdef_tbl =
4167 (const uint32_t *)&DDR_REGDEF_TBL[0][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004168 } else {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004169 p_ddr_regdef_tbl =
4170 (const uint32_t *)&DDR_REGDEF_TBL[2][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004171 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004172 } else if (prr_product == PRR_PRODUCT_M3) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004173 p_ddr_regdef_tbl =
4174 (const uint32_t *)&DDR_REGDEF_TBL[1][0];
Marek Vasut6a131772019-08-07 19:56:09 +02004175 } else if ((prr_product == PRR_PRODUCT_M3N) ||
4176 (prr_product == PRR_PRODUCT_V3H)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004177 p_ddr_regdef_tbl =
4178 (const uint32_t *)&DDR_REGDEF_TBL[3][0];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004179 } else {
Marek Vasut6c245a52018-12-12 18:06:39 +01004180 FATAL_MSG("BL2: DDR:Unknown Product\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004181 return 0xff;
4182 }
4183
Marek Vasut6a131772019-08-07 19:56:09 +02004184 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4185 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004186 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4187 } else {
4188 mmio_write_32(DBSC_DBSYSCNT0, 0x00001234);
4189 }
4190
Marek Vasut6a131772019-08-07 19:56:09 +02004191 /* Judge board type */
Marek Vasut38dc7562019-08-07 19:17:42 +02004192 cnf_boardtype = boardcnf_get_brd_type();
4193 if (cnf_boardtype >= BOARDNUM) {
Marek Vasut6c245a52018-12-12 18:06:39 +01004194 FATAL_MSG("BL2: DDR:Unknown Board\n");
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004195 return 0xff;
4196 }
Marek Vasut38dc7562019-08-07 19:17:42 +02004197 board_cnf = (const struct _boardcnf *)&boardcnfs[cnf_boardtype];
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004198
4199/* RCAR_DRAM_SPLIT_2CH (2U) */
4200#if RCAR_DRAM_SPLIT == 2
Marek Vasut6a131772019-08-07 19:56:09 +02004201 /* H3(Test for future H3-N): Swap ch2 and ch1 for 2ch-split */
Marek Vasut38dc7562019-08-07 19:17:42 +02004202 if ((prr_product == PRR_PRODUCT_H3) && (board_cnf->phyvalid == 0x05)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004203 mmio_write_32(DBSC_DBMEMSWAPCONF0, 0x00000006);
4204 ddr_phyvalid = 0x03;
4205 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004206 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004207 }
4208#else /* RCAR_DRAM_SPLIT_2CH */
Marek Vasut38dc7562019-08-07 19:17:42 +02004209 ddr_phyvalid = board_cnf->phyvalid;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004210#endif /* RCAR_DRAM_SPLIT_2CH */
4211
4212 max_density = 0;
4213
4214 for (cs = 0; cs < CS_CNT; cs++) {
4215 ch_have_this_cs[cs] = 0;
4216 }
4217
4218 foreach_ech(ch)
Marek Vasut80784f92019-08-07 19:02:26 +02004219 for (cs = 0; cs < CS_CNT; cs++)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004220 ddr_density[ch][cs] = 0xff;
4221
4222 foreach_vch(ch) {
4223 for (cs = 0; cs < CS_CNT; cs++) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004224 data_l = board_cnf->ch[ch].ddr_density[cs];
4225 ddr_density[ch][cs] = data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004226
Marek Vasut38dc7562019-08-07 19:17:42 +02004227 if (data_l == 0xff)
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004228 continue;
Marek Vasut38dc7562019-08-07 19:17:42 +02004229 if (data_l > max_density)
4230 max_density = data_l;
Marek Vasut6a131772019-08-07 19:56:09 +02004231 if ((cs == 1) && (prr_product == PRR_PRODUCT_H3) &&
4232 (prr_cut <= PRR_PRODUCT_11))
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004233 continue;
4234 ch_have_this_cs[cs] |= (1U << ch);
4235 }
4236 }
4237
Marek Vasut6a131772019-08-07 19:56:09 +02004238 /* Judge board clock frequency (in MHz) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004239 boardcnf_get_brd_clk(cnf_boardtype, &brd_clk, &brd_clkdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004240 if ((brd_clk / brd_clkdiv) > 25) {
4241 brd_clkdiva = 1;
4242 } else {
4243 brd_clkdiva = 0;
4244 }
4245
Marek Vasut6a131772019-08-07 19:56:09 +02004246 /* Judge ddr operating frequency clock(in Mbps) */
Marek Vasut38dc7562019-08-07 19:17:42 +02004247 boardcnf_get_ddr_mbps(cnf_boardtype, &ddr_mbps, &ddr_mbpsdiv);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004248
4249 ddr0800_mul = CLK_DIV(800, 2, brd_clk, brd_clkdiv * (brd_clkdiva + 1));
4250
Marek Vasut80784f92019-08-07 19:02:26 +02004251 ddr_mul = CLK_DIV(ddr_mbps, ddr_mbpsdiv * 2, brd_clk,
4252 brd_clkdiv * (brd_clkdiva + 1));
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004253
Marek Vasut6a131772019-08-07 19:56:09 +02004254 /* Adjust tccd */
Marek Vasut38dc7562019-08-07 19:17:42 +02004255 data_l = (0x00006000 & mmio_read_32(RST_MODEMR)) >> 13;
Chiaki Fujii59263ee2019-05-17 10:45:02 +09004256 bus_mbps = 0;
4257 bus_mbpsdiv = 0;
Marek Vasut38dc7562019-08-07 19:17:42 +02004258 switch (data_l) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004259 case 0:
4260 bus_mbps = brd_clk * 0x60 * 2;
4261 bus_mbpsdiv = brd_clkdiv * 1;
4262 break;
4263 case 1:
4264 bus_mbps = brd_clk * 0x50 * 2;
4265 bus_mbpsdiv = brd_clkdiv * 1;
4266 break;
4267 case 2:
4268 bus_mbps = brd_clk * 0x40 * 2;
4269 bus_mbpsdiv = brd_clkdiv * 1;
4270 break;
4271 case 3:
4272 bus_mbps = brd_clk * 0x60 * 2;
4273 bus_mbpsdiv = brd_clkdiv * 2;
4274 break;
4275 default:
4276 bus_mbps = brd_clk * 0x60 * 2;
4277 bus_mbpsdiv = brd_clkdiv * 2;
4278 break;
4279 }
4280 tmp_tccd = CLK_DIV(ddr_mbps * 8, ddr_mbpsdiv, bus_mbps, bus_mbpsdiv);
4281 if (8 * ddr_mbps * bus_mbpsdiv != tmp_tccd * bus_mbps * ddr_mbpsdiv)
4282 tmp_tccd = tmp_tccd + 1;
4283
4284 if (tmp_tccd < 8)
4285 ddr_tccd = 8;
4286 else
4287 ddr_tccd = tmp_tccd;
4288
Marek Vasut6c245a52018-12-12 18:06:39 +01004289 NOTICE("BL2: DDR%d(%s)\n", ddr_mbps / ddr_mbpsdiv, RCAR_DDR_VERSION);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004290
4291 MSG_LF("Start\n");
4292
Marek Vasut6a131772019-08-07 19:56:09 +02004293 /* PLL Setting */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004294 pll3_control(1);
4295
Marek Vasut6a131772019-08-07 19:56:09 +02004296 /* initialize DDR */
Marek Vasut38dc7562019-08-07 19:17:42 +02004297 data_l = init_ddr();
4298 if (data_l == ddr_phyvalid) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004299 failcount = 0;
4300 } else {
4301 failcount = 1;
4302 }
4303
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004304 foreach_vch(ch)
4305 mmio_write_32(DBSC_DBPDLK(ch), 0x00000000);
Marek Vasut6a131772019-08-07 19:56:09 +02004306 if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) ||
4307 ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004308 /* non : H3 Ver.1.x/M3-W Ver.1.x not support */
4309 } else {
4310 mmio_write_32(DBSC_DBSYSCNT0, 0x00000000);
4311 }
4312
4313 if (failcount == 0) {
4314 return INITDRAM_OK;
4315 } else {
4316 return INITDRAM_NG;
4317 }
4318}
4319
4320void pvtcode_update(void)
4321{
4322 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004323 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004324 uint32_t pvtp[4], pvtn[4], pvtp_init, pvtn_init;
4325 int32_t pvtp_tmp, pvtn_tmp;
4326
4327 foreach_vch(ch) {
4328 pvtn_init = (tcal.tcomp_cal[ch] & 0xFC0) >> 6;
4329 pvtp_init = (tcal.tcomp_cal[ch] & 0x03F) >> 0;
4330
4331 if (8912 * pvtp_init > 44230) {
4332 pvtp_tmp = (5000 + 8912 * pvtp_init - 44230) / 10000;
4333 } else {
4334 pvtp_tmp =
4335 -((-(5000 + 8912 * pvtp_init - 44230)) / 10000);
4336 }
4337 pvtn_tmp = (5000 + 5776 * pvtn_init + 30280) / 10000;
4338
4339 pvtn[ch] = pvtn_tmp + pvtn_init;
4340 pvtp[ch] = pvtp_tmp + pvtp_init;
4341
4342 if (pvtn[ch] > 63) {
4343 pvtn[ch] = 63;
4344 pvtp[ch] =
4345 (pvtp_tmp) * (63 - 6 * pvtn_tmp -
4346 pvtn_init) / (pvtn_tmp) +
4347 6 * pvtp_tmp + pvtp_init;
4348 }
Marek Vasut6a131772019-08-07 19:56:09 +02004349 if ((prr_product == PRR_PRODUCT_H3) &&
4350 (prr_cut <= PRR_PRODUCT_11)) {
Marek Vasut6ad74c32019-08-08 16:34:22 +02004351 data_l = pvtp[ch] | (pvtn[ch] << 6) |
4352 (tcal.tcomp_cal[ch] & 0xfffff000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004353 reg_ddrphy_write(ch,
4354 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004355 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004356 reg_ddrphy_write(ch,
4357 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004358 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004359 reg_ddrphy_write(ch,
4360 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004361 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004362 reg_ddrphy_write(ch,
4363 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004364 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004365 reg_ddrphy_write(ch,
4366 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004367 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004368 } else {
Marek Vasut38dc7562019-08-07 19:17:42 +02004369 data_l = pvtp[ch] | (pvtn[ch] << 6) | 0x00015000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004370 reg_ddrphy_write(ch,
4371 ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004372 data_l | 0x00020000);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004373 reg_ddrphy_write(ch,
4374 ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004375 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004376 reg_ddrphy_write(ch,
4377 ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004378 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004379 reg_ddrphy_write(ch,
4380 ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004381 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004382 reg_ddrphy_write(ch,
4383 ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
Marek Vasut38dc7562019-08-07 19:17:42 +02004384 data_l);
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004385 }
4386 }
4387}
4388
4389void pvtcode_update2(void)
4390{
4391 uint32_t ch;
Marek Vasut80784f92019-08-07 19:02:26 +02004392
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004393 foreach_vch(ch) {
4394 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM),
4395 tcal.init_cal[ch] | 0x00020000);
4396 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM),
4397 tcal.init_cal[ch]);
4398 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM),
4399 tcal.init_cal[ch]);
4400 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM),
4401 tcal.init_cal[ch]);
4402 reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_CS_TERM),
4403 tcal.init_cal[ch]);
4404 }
4405}
4406
4407void ddr_padcal_tcompensate_getinit(uint32_t override)
4408{
4409 uint32_t ch;
Marek Vasut38dc7562019-08-07 19:17:42 +02004410 uint32_t data_l;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004411 uint32_t pvtp, pvtn;
4412
4413 tcal.init_temp = 0;
4414 for (ch = 0; ch < 4; ch++) {
4415 tcal.init_cal[ch] = 0;
4416 tcal.tcomp_cal[ch] = 0;
4417 }
4418
4419 foreach_vch(ch) {
4420 tcal.init_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4421 tcal.tcomp_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]);
4422 }
4423
4424 if (!override) {
Marek Vasut38dc7562019-08-07 19:17:42 +02004425 data_l = mmio_read_32(THS1_TEMP);
4426 if (data_l < 2800) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004427 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004428 (143 * (int32_t)data_l - 359000) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004429 } else {
4430 tcal.init_temp =
Marek Vasut38dc7562019-08-07 19:17:42 +02004431 (121 * (int32_t)data_l - 296300) / 1000;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004432 }
4433
4434 foreach_vch(ch) {
4435 pvtp = (tcal.init_cal[ch] >> 0) & 0x000003F;
4436 pvtn = (tcal.init_cal[ch] >> 6) & 0x000003F;
Marek Vasut80784f92019-08-07 19:02:26 +02004437 if ((int32_t)pvtp >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004438 ((tcal.init_temp * 29 - 3625) / 1000))
4439 pvtp =
Marek Vasut80784f92019-08-07 19:02:26 +02004440 (int32_t)pvtp +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004441 ((3625 - tcal.init_temp * 29) / 1000);
4442 else
4443 pvtp = 0;
4444
Marek Vasut80784f92019-08-07 19:02:26 +02004445 if ((int32_t)pvtn >
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004446 ((tcal.init_temp * 54 - 6750) / 1000))
4447 pvtn =
Marek Vasut80784f92019-08-07 19:02:26 +02004448 (int32_t)pvtn +
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004449 ((6750 - tcal.init_temp * 54) / 1000);
4450 else
4451 pvtn = 0;
4452
Marek Vasut6a131772019-08-07 19:56:09 +02004453 if ((prr_product == PRR_PRODUCT_H3) &&
4454 (prr_cut <= PRR_PRODUCT_11)) {
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004455 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004456 (tcal.init_cal[ch] & 0xfffff000) |
4457 (pvtn << 6) |
4458 pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004459 } else {
4460 tcal.init_cal[ch] =
Marek Vasut6ad74c32019-08-08 16:34:22 +02004461 0x00015000 | (pvtn << 6) | pvtp;
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004462 }
4463 }
4464 tcal.init_temp = 125;
4465 }
4466}
4467
4468#ifndef ddr_qos_init_setting
Marek Vasut6ad74c32019-08-08 16:34:22 +02004469/* For QoS init */
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004470uint8_t get_boardcnf_phyvalid(void)
4471{
Jorge Ramirez-Ortiz47503d22018-09-23 09:36:52 +02004472 return ddr_phyvalid;
4473}
4474#endif /* ddr_qos_init_setting */