blob: e4f9891bee2059f998b9402b9e9b87a8b002f36f [file] [log] [blame]
Dave Gerlachd712b362021-05-11 10:22:11 -05001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Texas Instruments' K3 DDRSS driver
4 *
Nishanth Menoneaa39c62023-11-01 15:56:03 -05005 * Copyright (C) 2020-2021 Texas Instruments Incorporated - https://www.ti.com/
Dave Gerlachd712b362021-05-11 10:22:11 -05006 */
7
Dave Gerlach296c83a2022-03-17 12:03:43 -05008#include <config.h>
Georgi Vlaev1e6702e2025-01-06 14:37:01 +05309#include <time.h>
Dave Gerlachd712b362021-05-11 10:22:11 -050010#include <clk.h>
Dave Gerlach296c83a2022-03-17 12:03:43 -050011#include <div64.h>
Dave Gerlachd712b362021-05-11 10:22:11 -050012#include <dm.h>
13#include <dm/device_compat.h>
Dave Gerlach296c83a2022-03-17 12:03:43 -050014#include <fdt_support.h>
Dave Gerlachd712b362021-05-11 10:22:11 -050015#include <ram.h>
16#include <hang.h>
17#include <log.h>
18#include <asm/io.h>
19#include <power-domain.h>
20#include <wait_bit.h>
Lokesh Vutladd01c632021-05-11 10:22:13 -050021#include <power/regulator.h>
Dave Gerlachd712b362021-05-11 10:22:11 -050022
23#include "lpddr4_obj_if.h"
24#include "lpddr4_if.h"
25#include "lpddr4_structs_if.h"
26#include "lpddr4_ctl_regs.h"
27
28#define SRAM_MAX 512
29
30#define CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS 0x80
31#define CTRLMMR_DDR4_FSP_CLKCHNG_ACK_OFFS 0xc0
32
Dominic Rath6feaf592022-04-06 11:56:47 +020033#define DDRSS_V2A_CTL_REG 0x0020
Wolfgang Denk62fb2b42021-09-27 17:42:39 +020034#define DDRSS_ECC_CTRL_REG 0x0120
Dave Gerlach2c861a92021-05-11 10:22:12 -050035
Dave Gerlach296c83a2022-03-17 12:03:43 -050036#define DDRSS_ECC_CTRL_REG_ECC_EN BIT(0)
37#define DDRSS_ECC_CTRL_REG_RMW_EN BIT(1)
38#define DDRSS_ECC_CTRL_REG_ECC_CK BIT(2)
39#define DDRSS_ECC_CTRL_REG_WR_ALLOC BIT(4)
40
41#define DDRSS_ECC_R0_STR_ADDR_REG 0x0130
42#define DDRSS_ECC_R0_END_ADDR_REG 0x0134
43#define DDRSS_ECC_R1_STR_ADDR_REG 0x0138
44#define DDRSS_ECC_R1_END_ADDR_REG 0x013c
45#define DDRSS_ECC_R2_STR_ADDR_REG 0x0140
46#define DDRSS_ECC_R2_END_ADDR_REG 0x0144
47#define DDRSS_ECC_1B_ERR_CNT_REG 0x0150
Santhosh Kumar Kf0297ba2025-01-06 14:37:04 +053048#define DDRSS_V2A_INT_SET_REG 0x00a8
49
50#define DDRSS_V2A_INT_SET_REG_ECC1BERR_EN BIT(3)
51#define DDRSS_V2A_INT_SET_REG_ECC2BERR_EN BIT(4)
52#define DDRSS_V2A_INT_SET_REG_ECCM1BERR_EN BIT(5)
Dave Gerlach296c83a2022-03-17 12:03:43 -050053
Aswath Govindrajub232cb42022-01-25 20:56:29 +053054#define SINGLE_DDR_SUBSYSTEM 0x1
55#define MULTI_DDR_SUBSYSTEM 0x2
56
Aswath Govindraju6324bc72022-01-25 20:56:30 +053057#define MULTI_DDR_CFG0 0x00114100
58#define MULTI_DDR_CFG1 0x00114104
59#define DDR_CFG_LOAD 0x00114110
60
61enum intrlv_gran {
62 GRAN_128B,
63 GRAN_512B,
64 GRAN_2KB,
65 GRAN_4KB,
66 GRAN_16KB,
67 GRAN_32KB,
68 GRAN_512KB,
69 GRAN_1GB,
70 GRAN_1_5GB,
71 GRAN_2GB,
72 GRAN_3GB,
73 GRAN_4GB,
74 GRAN_6GB,
75 GRAN_8GB,
76 GRAN_16GB
77};
78
79enum intrlv_size {
80 SIZE_0,
81 SIZE_128MB,
82 SIZE_256MB,
83 SIZE_512MB,
84 SIZE_1GB,
85 SIZE_2GB,
86 SIZE_3GB,
87 SIZE_4GB,
88 SIZE_6GB,
89 SIZE_8GB,
90 SIZE_12GB,
91 SIZE_16GB,
92 SIZE_32GB
93};
94
95struct k3_ddrss_data {
96 u32 flags;
97};
98
99enum ecc_enable {
100 DISABLE_ALL = 0,
101 ENABLE_0,
102 ENABLE_1,
103 ENABLE_ALL
104};
105
106enum emif_config {
107 INTERLEAVE_ALL = 0,
108 SEPR0,
109 SEPR1
110};
111
112enum emif_active {
113 EMIF_0 = 1,
114 EMIF_1,
115 EMIF_ALL
116};
117
118struct k3_msmc {
119 enum intrlv_gran gran;
120 enum intrlv_size size;
121 enum ecc_enable enable;
122 enum emif_config config;
123 enum emif_active active;
124};
125
Dave Gerlach296c83a2022-03-17 12:03:43 -0500126#define K3_DDRSS_MAX_ECC_REGIONS 3
127
128struct k3_ddrss_ecc_region {
Santhosh Kumar K3f735f72025-01-06 14:37:03 +0530129 u64 start;
130 u64 range;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500131};
132
Dave Gerlachd712b362021-05-11 10:22:11 -0500133struct k3_ddrss_desc {
134 struct udevice *dev;
135 void __iomem *ddrss_ss_cfg;
136 void __iomem *ddrss_ctrl_mmr;
Dave Gerlachfd199dd2022-03-17 12:03:42 -0500137 void __iomem *ddrss_ctl_cfg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500138 struct power_domain ddrcfg_pwrdmn;
139 struct power_domain ddrdata_pwrdmn;
140 struct clk ddr_clk;
141 struct clk osc_clk;
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500142 u32 ddr_freq0;
Dave Gerlachd712b362021-05-11 10:22:11 -0500143 u32 ddr_freq1;
144 u32 ddr_freq2;
145 u32 ddr_fhs_cnt;
Bryan Brattlof2905a462023-07-17 17:15:26 -0500146 u32 dram_class;
Lokesh Vutladd01c632021-05-11 10:22:13 -0500147 struct udevice *vtt_supply;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530148 u32 instance;
149 lpddr4_obj *driverdt;
150 lpddr4_config config;
151 lpddr4_privatedata pd;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500152 struct k3_ddrss_ecc_region ecc_regions[K3_DDRSS_MAX_ECC_REGIONS];
153 u64 ecc_reserved_space;
154 bool ti_ecc_enabled;
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530155 u64 ddr_bank_base[CONFIG_NR_DRAM_BANKS];
156 u64 ddr_bank_size[CONFIG_NR_DRAM_BANKS];
157 u64 ddr_ram_size;
Dave Gerlachd712b362021-05-11 10:22:11 -0500158};
159
Dave Gerlachd712b362021-05-11 10:22:11 -0500160struct reginitdata {
161 u32 ctl_regs[LPDDR4_INTR_CTL_REG_COUNT];
162 u16 ctl_regs_offs[LPDDR4_INTR_CTL_REG_COUNT];
163 u32 pi_regs[LPDDR4_INTR_PHY_INDEP_REG_COUNT];
164 u16 pi_regs_offs[LPDDR4_INTR_PHY_INDEP_REG_COUNT];
165 u32 phy_regs[LPDDR4_INTR_PHY_REG_COUNT];
166 u16 phy_regs_offs[LPDDR4_INTR_PHY_REG_COUNT];
167};
168
169#define TH_MACRO_EXP(fld, str) (fld##str)
170
171#define TH_FLD_MASK(fld) TH_MACRO_EXP(fld, _MASK)
172#define TH_FLD_SHIFT(fld) TH_MACRO_EXP(fld, _SHIFT)
173#define TH_FLD_WIDTH(fld) TH_MACRO_EXP(fld, _WIDTH)
174#define TH_FLD_WOCLR(fld) TH_MACRO_EXP(fld, _WOCLR)
175#define TH_FLD_WOSET(fld) TH_MACRO_EXP(fld, _WOSET)
176
177#define str(s) #s
178#define xstr(s) str(s)
179
180#define CTL_SHIFT 11
181#define PHY_SHIFT 11
182#define PI_SHIFT 10
183
184#define DENALI_CTL_0_DRAM_CLASS_DDR4 0xA
185#define DENALI_CTL_0_DRAM_CLASS_LPDDR4 0xB
186
187#define TH_OFFSET_FROM_REG(REG, SHIFT, offset) do {\
188 char *i, *pstr = xstr(REG); offset = 0;\
189 for (i = &pstr[SHIFT]; *i != '\0'; ++i) {\
190 offset = offset * 10 + (*i - '0'); } \
191 } while (0)
192
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530193static u32 k3_lpddr4_read_ddr_type(const lpddr4_privatedata *pd)
Dave Gerlachd712b362021-05-11 10:22:11 -0500194{
195 u32 status = 0U;
196 u32 offset = 0U;
197 u32 regval = 0U;
198 u32 dram_class = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530199 struct k3_ddrss_desc *ddrss = (struct k3_ddrss_desc *)pd->ddr_instance;
Dave Gerlachd712b362021-05-11 10:22:11 -0500200
201 TH_OFFSET_FROM_REG(LPDDR4__DRAM_CLASS__REG, CTL_SHIFT, offset);
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530202 status = ddrss->driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
Dave Gerlachd712b362021-05-11 10:22:11 -0500203 if (status > 0U) {
204 printf("%s: Failed to read DRAM_CLASS\n", __func__);
205 hang();
206 }
207
208 dram_class = ((regval & TH_FLD_MASK(LPDDR4__DRAM_CLASS__FLD)) >>
209 TH_FLD_SHIFT(LPDDR4__DRAM_CLASS__FLD));
210 return dram_class;
211}
212
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530213static void k3_lpddr4_freq_update(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500214{
215 unsigned int req_type, counter;
216
217 for (counter = 0; counter < ddrss->ddr_fhs_cnt; counter++) {
218 if (wait_for_bit_le32(ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530219 CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS + ddrss->instance * 0x10, 0x80,
Dave Gerlachd712b362021-05-11 10:22:11 -0500220 true, 10000, false)) {
221 printf("Timeout during frequency handshake\n");
222 hang();
223 }
224
225 req_type = readl(ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530226 CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS + ddrss->instance * 0x10) & 0x03;
Dave Gerlachd712b362021-05-11 10:22:11 -0500227
Dave Gerlachd712b362021-05-11 10:22:11 -0500228 if (req_type == 1)
229 clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq1);
230 else if (req_type == 2)
231 clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq2);
232 else if (req_type == 0)
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500233 clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq0);
Dave Gerlachd712b362021-05-11 10:22:11 -0500234 else
235 printf("%s: Invalid freq request type\n", __func__);
236
237 writel(0x1, ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530238 CTRLMMR_DDR4_FSP_CLKCHNG_ACK_OFFS + ddrss->instance * 0x10);
Dave Gerlachd712b362021-05-11 10:22:11 -0500239 if (wait_for_bit_le32(ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530240 CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS + ddrss->instance * 0x10, 0x80,
Dave Gerlachd712b362021-05-11 10:22:11 -0500241 false, 10, false)) {
242 printf("Timeout during frequency handshake\n");
243 hang();
244 }
245 writel(0x0, ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530246 CTRLMMR_DDR4_FSP_CLKCHNG_ACK_OFFS + ddrss->instance * 0x10);
Dave Gerlachd712b362021-05-11 10:22:11 -0500247 }
248}
249
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530250static void k3_lpddr4_ack_freq_upd_req(const lpddr4_privatedata *pd)
Dave Gerlachd712b362021-05-11 10:22:11 -0500251{
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530252 struct k3_ddrss_desc *ddrss = (struct k3_ddrss_desc *)pd->ddr_instance;
Dave Gerlachd712b362021-05-11 10:22:11 -0500253
Bryan Brattlof2905a462023-07-17 17:15:26 -0500254 switch (ddrss->dram_class) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500255 case DENALI_CTL_0_DRAM_CLASS_DDR4:
256 break;
257 case DENALI_CTL_0_DRAM_CLASS_LPDDR4:
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530258 k3_lpddr4_freq_update(ddrss);
Dave Gerlachd712b362021-05-11 10:22:11 -0500259 break;
260 default:
261 printf("Unrecognized dram_class cannot update frequency!\n");
262 }
263}
264
265static int k3_ddrss_init_freq(struct k3_ddrss_desc *ddrss)
266{
Dave Gerlachd712b362021-05-11 10:22:11 -0500267 int ret;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530268 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500269
Bryan Brattlof2905a462023-07-17 17:15:26 -0500270 ddrss->dram_class = k3_lpddr4_read_ddr_type(pd);
Dave Gerlachd712b362021-05-11 10:22:11 -0500271
Bryan Brattlof2905a462023-07-17 17:15:26 -0500272 switch (ddrss->dram_class) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500273 case DENALI_CTL_0_DRAM_CLASS_DDR4:
274 /* Set to ddr_freq1 from DT for DDR4 */
275 ret = clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq1);
276 break;
277 case DENALI_CTL_0_DRAM_CLASS_LPDDR4:
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500278 ret = clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq0);
Dave Gerlachd712b362021-05-11 10:22:11 -0500279 break;
280 default:
281 ret = -EINVAL;
282 printf("Unrecognized dram_class cannot init frequency!\n");
283 }
284
285 if (ret < 0)
286 dev_err(ddrss->dev, "ddr clk init failed: %d\n", ret);
287 else
288 ret = 0;
289
290 return ret;
291}
292
293static void k3_lpddr4_info_handler(const lpddr4_privatedata *pd,
294 lpddr4_infotype infotype)
295{
296 if (infotype == LPDDR4_DRV_SOC_PLL_UPDATE)
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530297 k3_lpddr4_ack_freq_upd_req(pd);
Dave Gerlachd712b362021-05-11 10:22:11 -0500298}
299
300static int k3_ddrss_power_on(struct k3_ddrss_desc *ddrss)
301{
302 int ret;
303
304 debug("%s(ddrss=%p)\n", __func__, ddrss);
305
306 ret = power_domain_on(&ddrss->ddrcfg_pwrdmn);
307 if (ret) {
308 dev_err(ddrss->dev, "power_domain_on() failed: %d\n", ret);
309 return ret;
310 }
311
312 ret = power_domain_on(&ddrss->ddrdata_pwrdmn);
313 if (ret) {
314 dev_err(ddrss->dev, "power_domain_on() failed: %d\n", ret);
315 return ret;
316 }
317
Lokesh Vutladd01c632021-05-11 10:22:13 -0500318 ret = device_get_supply_regulator(ddrss->dev, "vtt-supply",
319 &ddrss->vtt_supply);
320 if (ret) {
321 dev_dbg(ddrss->dev, "vtt-supply not found.\n");
322 } else {
323 ret = regulator_set_value(ddrss->vtt_supply, 3300000);
324 if (ret)
325 return ret;
326 dev_dbg(ddrss->dev, "VTT regulator enabled, volt = %d\n",
327 regulator_get_value(ddrss->vtt_supply));
328 }
329
Dave Gerlachd712b362021-05-11 10:22:11 -0500330 return 0;
331}
332
333static int k3_ddrss_ofdata_to_priv(struct udevice *dev)
334{
335 struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530336 struct k3_ddrss_data *ddrss_data = (struct k3_ddrss_data *)dev_get_driver_data(dev);
Matthias Schiffer47331932023-09-27 15:33:34 +0200337 void *reg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500338 int ret;
339
340 debug("%s(dev=%p)\n", __func__, dev);
341
Matthias Schiffer47331932023-09-27 15:33:34 +0200342 reg = dev_read_addr_name_ptr(dev, "cfg");
343 if (!reg) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500344 dev_err(dev, "No reg property for DDRSS wrapper logic\n");
345 return -EINVAL;
346 }
Matthias Schiffer47331932023-09-27 15:33:34 +0200347 ddrss->ddrss_ctl_cfg = reg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500348
Matthias Schiffer47331932023-09-27 15:33:34 +0200349 reg = dev_read_addr_name_ptr(dev, "ctrl_mmr_lp4");
350 if (!reg) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500351 dev_err(dev, "No reg property for CTRL MMR\n");
352 return -EINVAL;
353 }
Matthias Schiffer47331932023-09-27 15:33:34 +0200354 ddrss->ddrss_ctrl_mmr = reg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500355
Matthias Schiffer47331932023-09-27 15:33:34 +0200356 reg = dev_read_addr_name_ptr(dev, "ss_cfg");
357 if (!reg)
Dave Gerlach296c83a2022-03-17 12:03:43 -0500358 dev_dbg(dev, "No reg property for SS Config region, but this is optional so continuing.\n");
Matthias Schiffer47331932023-09-27 15:33:34 +0200359 ddrss->ddrss_ss_cfg = reg;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500360
Dave Gerlachd712b362021-05-11 10:22:11 -0500361 ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0);
362 if (ret) {
363 dev_err(dev, "power_domain_get() failed: %d\n", ret);
364 return ret;
365 }
366
367 ret = power_domain_get_by_index(dev, &ddrss->ddrdata_pwrdmn, 1);
368 if (ret) {
369 dev_err(dev, "power_domain_get() failed: %d\n", ret);
370 return ret;
371 }
372
373 ret = clk_get_by_index(dev, 0, &ddrss->ddr_clk);
374 if (ret)
375 dev_err(dev, "clk get failed%d\n", ret);
376
377 ret = clk_get_by_index(dev, 1, &ddrss->osc_clk);
378 if (ret)
379 dev_err(dev, "clk get failed for osc clk %d\n", ret);
380
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530381 /* Reading instance number for multi ddr subystems */
382 if (ddrss_data->flags & MULTI_DDR_SUBSYSTEM) {
383 ret = dev_read_u32(dev, "instance", &ddrss->instance);
384 if (ret) {
385 dev_err(dev, "missing instance property");
386 return -EINVAL;
387 }
388 } else {
389 ddrss->instance = 0;
390 }
391
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500392 ret = dev_read_u32(dev, "ti,ddr-freq0", &ddrss->ddr_freq0);
393 if (ret) {
394 ddrss->ddr_freq0 = clk_get_rate(&ddrss->osc_clk);
395 dev_dbg(dev,
396 "ddr freq0 not populated, using bypass frequency.\n");
397 }
398
Dave Gerlachd712b362021-05-11 10:22:11 -0500399 ret = dev_read_u32(dev, "ti,ddr-freq1", &ddrss->ddr_freq1);
400 if (ret)
401 dev_err(dev, "ddr freq1 not populated %d\n", ret);
402
403 ret = dev_read_u32(dev, "ti,ddr-freq2", &ddrss->ddr_freq2);
404 if (ret)
405 dev_err(dev, "ddr freq2 not populated %d\n", ret);
406
407 ret = dev_read_u32(dev, "ti,ddr-fhs-cnt", &ddrss->ddr_fhs_cnt);
408 if (ret)
409 dev_err(dev, "ddr fhs cnt not populated %d\n", ret);
410
Dave Gerlach296c83a2022-03-17 12:03:43 -0500411 ddrss->ti_ecc_enabled = dev_read_bool(dev, "ti,ecc-enable");
412
Dave Gerlachd712b362021-05-11 10:22:11 -0500413 return ret;
414}
415
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530416void k3_lpddr4_probe(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500417{
418 u32 status = 0U;
419 u16 configsize = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530420 lpddr4_config *config = &ddrss->config;
Dave Gerlachd712b362021-05-11 10:22:11 -0500421
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530422 status = ddrss->driverdt->probe(config, &configsize);
Dave Gerlachd712b362021-05-11 10:22:11 -0500423
424 if ((status != 0) || (configsize != sizeof(lpddr4_privatedata))
425 || (configsize > SRAM_MAX)) {
426 printf("%s: FAIL\n", __func__);
427 hang();
428 } else {
429 debug("%s: PASS\n", __func__);
430 }
431}
432
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530433void k3_lpddr4_init(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500434{
435 u32 status = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530436 lpddr4_config *config = &ddrss->config;
437 lpddr4_obj *driverdt = ddrss->driverdt;
438 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500439
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530440 if ((sizeof(*pd) != sizeof(lpddr4_privatedata)) || (sizeof(*pd) > SRAM_MAX)) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500441 printf("%s: FAIL\n", __func__);
442 hang();
443 }
444
Dave Gerlachfd199dd2022-03-17 12:03:42 -0500445 config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ctl_cfg;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530446 config->infohandler = (lpddr4_infocallback) k3_lpddr4_info_handler;
Dave Gerlachd712b362021-05-11 10:22:11 -0500447
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530448 status = driverdt->init(pd, config);
449
450 /* linking ddr instance to lpddr4 */
451 pd->ddr_instance = (void *)ddrss;
Dave Gerlachd712b362021-05-11 10:22:11 -0500452
453 if ((status > 0U) ||
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530454 (pd->ctlbase != (struct lpddr4_ctlregs_s *)config->ctlbase) ||
455 (pd->ctlinterrupthandler != config->ctlinterrupthandler) ||
456 (pd->phyindepinterrupthandler != config->phyindepinterrupthandler)) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500457 printf("%s: FAIL\n", __func__);
458 hang();
459 } else {
460 debug("%s: PASS\n", __func__);
461 }
462}
463
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530464void populate_data_array_from_dt(struct k3_ddrss_desc *ddrss,
465 struct reginitdata *reginit_data)
Dave Gerlachd712b362021-05-11 10:22:11 -0500466{
467 int ret, i;
468
469 ret = dev_read_u32_array(ddrss->dev, "ti,ctl-data",
470 (u32 *)reginit_data->ctl_regs,
471 LPDDR4_INTR_CTL_REG_COUNT);
472 if (ret)
473 printf("Error reading ctrl data %d\n", ret);
474
475 for (i = 0; i < LPDDR4_INTR_CTL_REG_COUNT; i++)
476 reginit_data->ctl_regs_offs[i] = i;
477
478 ret = dev_read_u32_array(ddrss->dev, "ti,pi-data",
479 (u32 *)reginit_data->pi_regs,
480 LPDDR4_INTR_PHY_INDEP_REG_COUNT);
481 if (ret)
482 printf("Error reading PI data\n");
483
484 for (i = 0; i < LPDDR4_INTR_PHY_INDEP_REG_COUNT; i++)
485 reginit_data->pi_regs_offs[i] = i;
486
487 ret = dev_read_u32_array(ddrss->dev, "ti,phy-data",
488 (u32 *)reginit_data->phy_regs,
489 LPDDR4_INTR_PHY_REG_COUNT);
490 if (ret)
491 printf("Error reading PHY data %d\n", ret);
492
493 for (i = 0; i < LPDDR4_INTR_PHY_REG_COUNT; i++)
494 reginit_data->phy_regs_offs[i] = i;
495}
496
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530497void k3_lpddr4_hardware_reg_init(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500498{
499 u32 status = 0U;
500 struct reginitdata reginitdata;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530501 lpddr4_obj *driverdt = ddrss->driverdt;
502 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500503
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530504 populate_data_array_from_dt(ddrss, &reginitdata);
Dave Gerlachd712b362021-05-11 10:22:11 -0500505
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530506 status = driverdt->writectlconfig(pd, reginitdata.ctl_regs,
Dave Gerlachd712b362021-05-11 10:22:11 -0500507 reginitdata.ctl_regs_offs,
508 LPDDR4_INTR_CTL_REG_COUNT);
509 if (!status)
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530510 status = driverdt->writephyindepconfig(pd, reginitdata.pi_regs,
Dave Gerlachd712b362021-05-11 10:22:11 -0500511 reginitdata.pi_regs_offs,
512 LPDDR4_INTR_PHY_INDEP_REG_COUNT);
513 if (!status)
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530514 status = driverdt->writephyconfig(pd, reginitdata.phy_regs,
Dave Gerlachd712b362021-05-11 10:22:11 -0500515 reginitdata.phy_regs_offs,
516 LPDDR4_INTR_PHY_REG_COUNT);
517 if (status) {
518 printf("%s: FAIL\n", __func__);
519 hang();
520 }
521}
522
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530523void k3_lpddr4_start(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500524{
525 u32 status = 0U;
526 u32 regval = 0U;
527 u32 offset = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530528 lpddr4_obj *driverdt = ddrss->driverdt;
529 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500530
531 TH_OFFSET_FROM_REG(LPDDR4__START__REG, CTL_SHIFT, offset);
532
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530533 status = driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
Dave Gerlachd712b362021-05-11 10:22:11 -0500534 if ((status > 0U) || ((regval & TH_FLD_MASK(LPDDR4__START__FLD)) != 0U)) {
535 printf("%s: Pre start FAIL\n", __func__);
536 hang();
537 }
538
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530539 status = driverdt->start(pd);
Dave Gerlachd712b362021-05-11 10:22:11 -0500540 if (status > 0U) {
541 printf("%s: FAIL\n", __func__);
542 hang();
543 }
544
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530545 status = driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
Dave Gerlachd712b362021-05-11 10:22:11 -0500546 if ((status > 0U) || ((regval & TH_FLD_MASK(LPDDR4__START__FLD)) != 1U)) {
547 printf("%s: Post start FAIL\n", __func__);
548 hang();
549 } else {
550 debug("%s: Post start PASS\n", __func__);
551 }
552}
553
Santhosh Kumar K3f735f72025-01-06 14:37:03 +0530554static void k3_ddrss_set_ecc_range_r0(u32 base, u64 start_address, u64 size)
Dave Gerlach296c83a2022-03-17 12:03:43 -0500555{
556 writel((start_address) >> 16, base + DDRSS_ECC_R0_STR_ADDR_REG);
557 writel((start_address + size - 1) >> 16, base + DDRSS_ECC_R0_END_ADDR_REG);
558}
559
Georgi Vlaev1e6702e2025-01-06 14:37:01 +0530560#define BIST_MODE_MEM_INIT 4
561#define BIST_MEM_INIT_TIMEOUT 10000 /* 1msec loops per block = 10s */
562static void k3_lpddr4_bist_init_mem_region(struct k3_ddrss_desc *ddrss,
563 u64 addr, u64 size,
564 u32 pattern)
Dave Gerlach296c83a2022-03-17 12:03:43 -0500565{
Georgi Vlaev1e6702e2025-01-06 14:37:01 +0530566 lpddr4_obj *driverdt = ddrss->driverdt;
567 lpddr4_privatedata *pd = &ddrss->pd;
568 u32 status, offset, regval;
569 bool int_status;
570 int i = 0;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500571
Georgi Vlaev1e6702e2025-01-06 14:37:01 +0530572 /* Set BIST_START_ADDR_0 [31:0] */
573 regval = (u32)(addr & TH_FLD_MASK(LPDDR4__BIST_START_ADDRESS_0__FLD));
574 TH_OFFSET_FROM_REG(LPDDR4__BIST_START_ADDRESS_0__REG, CTL_SHIFT, offset);
575 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, regval);
576
577 /* Set BIST_START_ADDR_1 [32 or 34:32] */
578 regval = (u32)(addr >> TH_FLD_WIDTH(LPDDR4__BIST_START_ADDRESS_0__FLD));
579 regval &= TH_FLD_MASK(LPDDR4__BIST_START_ADDRESS_1__FLD);
580 TH_OFFSET_FROM_REG(LPDDR4__BIST_START_ADDRESS_1__REG, CTL_SHIFT, offset);
581 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, regval);
Dave Gerlach296c83a2022-03-17 12:03:43 -0500582
Georgi Vlaev1e6702e2025-01-06 14:37:01 +0530583 /* Set ADDR_SPACE = log2(size) */
584 regval = (u32)(ilog2(size) << TH_FLD_SHIFT(LPDDR4__ADDR_SPACE__FLD));
585 TH_OFFSET_FROM_REG(LPDDR4__ADDR_SPACE__REG, CTL_SHIFT, offset);
586 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, regval);
587
588 /* Enable the BIST data check. On 32bit lpddr4 (e.g J7) this shares a
589 * register with ADDR_SPACE and BIST_GO.
590 */
591 TH_OFFSET_FROM_REG(LPDDR4__BIST_DATA_CHECK__REG, CTL_SHIFT, offset);
592 driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
593 regval |= TH_FLD_MASK(LPDDR4__BIST_DATA_CHECK__FLD);
594 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, regval);
595 /* Clear the address check bit */
596 TH_OFFSET_FROM_REG(LPDDR4__BIST_ADDR_CHECK__REG, CTL_SHIFT, offset);
597 driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
598 regval &= ~TH_FLD_MASK(LPDDR4__BIST_ADDR_CHECK__FLD);
599 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, regval);
600
601 /* Set BIST_TEST_MODE[2:0] to memory initialize (4) */
602 regval = BIST_MODE_MEM_INIT;
603 TH_OFFSET_FROM_REG(LPDDR4__BIST_TEST_MODE__REG, CTL_SHIFT, offset);
604 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, regval);
605
606 /* Set BIST_DATA_PATTERN[31:0] */
607 TH_OFFSET_FROM_REG(LPDDR4__BIST_DATA_PATTERN_0__REG, CTL_SHIFT, offset);
608 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, pattern);
609
610 /* Set BIST_DATA_PATTERN[63:32] */
611 TH_OFFSET_FROM_REG(LPDDR4__BIST_DATA_PATTERN_1__REG, CTL_SHIFT, offset);
612 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, pattern);
613
614 udelay(1000);
615
616 /* Enable the programmed BIST operation - BIST_GO = 1 */
617 TH_OFFSET_FROM_REG(LPDDR4__BIST_GO__REG, CTL_SHIFT, offset);
618 driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
619 regval |= TH_FLD_MASK(LPDDR4__BIST_GO__FLD);
620 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, regval);
621
622 /* Wait for the BIST_DONE interrupt */
623 while (i < BIST_MEM_INIT_TIMEOUT) {
624 status = driverdt->checkctlinterrupt(pd, LPDDR4_INTR_BIST_DONE,
625 &int_status);
626 if (!status & int_status) {
627 /* Clear LPDDR4_INTR_BIST_DONE */
628 driverdt->ackctlinterrupt(pd, LPDDR4_INTR_BIST_DONE);
629 break;
630 }
631 udelay(1000);
632 i++;
633 }
634
635 /* Before continuing we have to stop BIST - BIST_GO = 0 */
636 TH_OFFSET_FROM_REG(LPDDR4__BIST_GO__REG, CTL_SHIFT, offset);
637 driverdt->writereg(pd, LPDDR4_CTL_REGS, offset, 0);
638
639 /* Timeout hit while priming the memory. We can't continue,
640 * since the memory is not fully initialized and we most
641 * likely get an uncorrectable error exception while booting.
642 */
643 if (i == BIST_MEM_INIT_TIMEOUT) {
644 printf("ERROR: Timeout while priming the memory.\n");
645 hang();
646 }
647}
648
649static void k3_ddrss_lpddr4_preload_full_mem(struct k3_ddrss_desc *ddrss,
650 u64 total_size, u32 pattern)
651{
652 u32 done, max_size2;
653
654 /* Get the max size (log2) supported in this config (16/32 lpddr4)
655 * from the start_addess width - 16bit: 8G, 32bit: 32G
656 */
657 max_size2 = TH_FLD_WIDTH(LPDDR4__BIST_START_ADDRESS_0__FLD) +
658 TH_FLD_WIDTH(LPDDR4__BIST_START_ADDRESS_1__FLD) + 1;
659
660 /* ECC is enabled in dt but we can't preload the memory if
661 * the memory configuration is recognized and supported.
662 */
663 if (!total_size || total_size > (1ull << max_size2) ||
664 total_size & (total_size - 1)) {
665 printf("ECC: the memory configuration is not supported\n");
666 hang();
667 }
668 printf("ECC is enabled, priming DDR which will take several seconds.\n");
669 done = get_timer(0);
670 k3_lpddr4_bist_init_mem_region(ddrss, 0, total_size, pattern);
671 printf("ECC: priming DDR completed in %lu msec\n", get_timer(done));
Dave Gerlach296c83a2022-03-17 12:03:43 -0500672}
673
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530674static void k3_ddrss_ddr_bank_base_size_calc(struct k3_ddrss_desc *ddrss)
675{
676 int bank, na, ns, len, parent;
677 const fdt32_t *ptr, *end;
678
679 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
680 ddrss->ddr_bank_base[bank] = 0;
681 ddrss->ddr_bank_size[bank] = 0;
682 }
683
684 ofnode mem = ofnode_null();
685
686 do {
687 mem = ofnode_by_prop_value(mem, "device_type", "memory", 7);
688 } while (!ofnode_is_enabled(mem));
689
690 const void *fdt = ofnode_to_fdt(mem);
691 int node = ofnode_to_offset(mem);
692 const char *property = "reg";
693
694 parent = fdt_parent_offset(fdt, node);
695 na = fdt_address_cells(fdt, parent);
696 ns = fdt_size_cells(fdt, parent);
697 ptr = fdt_getprop(fdt, node, property, &len);
698 end = ptr + len / sizeof(*ptr);
699
700 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
701 if (ptr + na + ns <= end) {
702 if (CONFIG_IS_ENABLED(OF_TRANSLATE))
703 ddrss->ddr_bank_base[bank] = fdt_translate_address(fdt, node, ptr);
704 else
705 ddrss->ddr_bank_base[bank] = fdtdec_get_number(ptr, na);
706
707 ddrss->ddr_bank_size[bank] = fdtdec_get_number(&ptr[na], ns);
708 }
709
710 ptr += na + ns;
711 }
712
713 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++)
714 ddrss->ddr_ram_size += ddrss->ddr_bank_size[bank];
715}
716
Dave Gerlach296c83a2022-03-17 12:03:43 -0500717static void k3_ddrss_lpddr4_ecc_calc_reserved_mem(struct k3_ddrss_desc *ddrss)
718{
719 fdtdec_setup_mem_size_base_lowest();
720
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530721 ddrss->ecc_reserved_space = ddrss->ddr_ram_size;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500722 do_div(ddrss->ecc_reserved_space, 9);
723
724 /* Round to clean number */
725 ddrss->ecc_reserved_space = 1ull << (fls(ddrss->ecc_reserved_space));
726}
727
728static void k3_ddrss_lpddr4_ecc_init(struct k3_ddrss_desc *ddrss)
729{
Santhosh Kumar K3f735f72025-01-06 14:37:03 +0530730 u64 ecc_region_start = ddrss->ecc_regions[0].start;
731 u64 ecc_range = ddrss->ecc_regions[0].range;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500732 u32 base = (u32)ddrss->ddrss_ss_cfg;
733 u32 val;
734
735 /* Only Program region 0 which covers full ddr space */
Santhosh Kumar K3f735f72025-01-06 14:37:03 +0530736 k3_ddrss_set_ecc_range_r0(base, ecc_region_start - ddrss->ddr_bank_base[0], ecc_range);
Dave Gerlach296c83a2022-03-17 12:03:43 -0500737
738 /* Enable ECC, RMW, WR_ALLOC */
739 writel(DDRSS_ECC_CTRL_REG_ECC_EN | DDRSS_ECC_CTRL_REG_RMW_EN |
740 DDRSS_ECC_CTRL_REG_WR_ALLOC, base + DDRSS_ECC_CTRL_REG);
741
Georgi Vlaev1e6702e2025-01-06 14:37:01 +0530742 /* Preload the full memory with 0's using the BIST engine of
743 * the LPDDR4 controller.
744 */
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530745 k3_ddrss_lpddr4_preload_full_mem(ddrss, ddrss->ddr_ram_size, 0);
Dave Gerlach296c83a2022-03-17 12:03:43 -0500746
747 /* Clear Error Count Register */
748 writel(0x1, base + DDRSS_ECC_1B_ERR_CNT_REG);
749
Santhosh Kumar Kf0297ba2025-01-06 14:37:04 +0530750 writel(DDRSS_V2A_INT_SET_REG_ECC1BERR_EN | DDRSS_V2A_INT_SET_REG_ECC2BERR_EN |
751 DDRSS_V2A_INT_SET_REG_ECCM1BERR_EN, base + DDRSS_V2A_INT_SET_REG);
752
Dave Gerlach296c83a2022-03-17 12:03:43 -0500753 /* Enable ECC Check */
754 val = readl(base + DDRSS_ECC_CTRL_REG);
755 val |= DDRSS_ECC_CTRL_REG_ECC_CK;
756 writel(val, base + DDRSS_ECC_CTRL_REG);
757}
758
Dave Gerlachd712b362021-05-11 10:22:11 -0500759static int k3_ddrss_probe(struct udevice *dev)
760{
761 int ret;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530762 struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
Dave Gerlachd712b362021-05-11 10:22:11 -0500763
764 debug("%s(dev=%p)\n", __func__, dev);
765
766 ret = k3_ddrss_ofdata_to_priv(dev);
767 if (ret)
768 return ret;
769
770 ddrss->dev = dev;
771 ret = k3_ddrss_power_on(ddrss);
772 if (ret)
773 return ret;
774
Dave Gerlach2c861a92021-05-11 10:22:12 -0500775#ifdef CONFIG_K3_AM64_DDRSS
Dominic Rath6feaf592022-04-06 11:56:47 +0200776 /* AM64x supports only up to 2 GB SDRAM */
777 writel(0x000001EF, ddrss->ddrss_ss_cfg + DDRSS_V2A_CTL_REG);
Dave Gerlach2c861a92021-05-11 10:22:12 -0500778 writel(0x0, ddrss->ddrss_ss_cfg + DDRSS_ECC_CTRL_REG);
779#endif
780
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530781 ddrss->driverdt = lpddr4_getinstance();
782
783 k3_lpddr4_probe(ddrss);
784 k3_lpddr4_init(ddrss);
785 k3_lpddr4_hardware_reg_init(ddrss);
Dave Gerlachd712b362021-05-11 10:22:11 -0500786
787 ret = k3_ddrss_init_freq(ddrss);
788 if (ret)
789 return ret;
790
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530791 k3_lpddr4_start(ddrss);
Dave Gerlachd712b362021-05-11 10:22:11 -0500792
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530793 k3_ddrss_ddr_bank_base_size_calc(ddrss);
794
Dave Gerlach296c83a2022-03-17 12:03:43 -0500795 if (ddrss->ti_ecc_enabled) {
796 if (!ddrss->ddrss_ss_cfg) {
797 printf("%s: ss_cfg is required if ecc is enabled but not provided.",
798 __func__);
799 return -EINVAL;
800 }
801
802 k3_ddrss_lpddr4_ecc_calc_reserved_mem(ddrss);
803
804 /* Always configure one region that covers full DDR space */
Santhosh Kumar K3f735f72025-01-06 14:37:03 +0530805 ddrss->ecc_regions[0].start = ddrss->ddr_bank_base[0];
806 ddrss->ecc_regions[0].range = ddrss->ddr_ram_size - ddrss->ecc_reserved_space;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500807 k3_ddrss_lpddr4_ecc_init(ddrss);
808 }
809
Dave Gerlachd712b362021-05-11 10:22:11 -0500810 return ret;
811}
812
Dave Gerlach296c83a2022-03-17 12:03:43 -0500813int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd)
814{
Dave Gerlach296c83a2022-03-17 12:03:43 -0500815 int bank;
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530816 struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
Dave Gerlach296c83a2022-03-17 12:03:43 -0500817
818 if (ddrss->ecc_reserved_space == 0)
819 return 0;
820
821 for (bank = CONFIG_NR_DRAM_BANKS - 1; bank >= 0; bank--) {
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530822 if (ddrss->ecc_reserved_space > ddrss->ddr_bank_size[bank]) {
823 ddrss->ecc_reserved_space -= ddrss->ddr_bank_size[bank];
824 ddrss->ddr_bank_size[bank] = 0;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500825 } else {
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530826 ddrss->ddr_bank_size[bank] -= ddrss->ecc_reserved_space;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500827 break;
828 }
829 }
830
Santhosh Kumar K51c52fb2025-01-06 14:37:02 +0530831 return fdt_fixup_memory_banks(blob, ddrss->ddr_bank_base,
832 ddrss->ddr_bank_size, CONFIG_NR_DRAM_BANKS);
Dave Gerlach296c83a2022-03-17 12:03:43 -0500833}
834
Dave Gerlachd712b362021-05-11 10:22:11 -0500835static int k3_ddrss_get_info(struct udevice *dev, struct ram_info *info)
836{
837 return 0;
838}
839
840static struct ram_ops k3_ddrss_ops = {
841 .get_info = k3_ddrss_get_info,
842};
843
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530844static const struct k3_ddrss_data k3_data = {
845 .flags = SINGLE_DDR_SUBSYSTEM,
846};
847
848static const struct k3_ddrss_data j721s2_data = {
849 .flags = MULTI_DDR_SUBSYSTEM,
850};
851
Dave Gerlachd712b362021-05-11 10:22:11 -0500852static const struct udevice_id k3_ddrss_ids[] = {
Bryan Brattlofdebb0452022-11-03 19:13:53 -0500853 {.compatible = "ti,am62a-ddrss", .data = (ulong)&k3_data, },
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530854 {.compatible = "ti,am64-ddrss", .data = (ulong)&k3_data, },
855 {.compatible = "ti,j721e-ddrss", .data = (ulong)&k3_data, },
856 {.compatible = "ti,j721s2-ddrss", .data = (ulong)&j721s2_data, },
Dave Gerlachd712b362021-05-11 10:22:11 -0500857 {}
858};
859
860U_BOOT_DRIVER(k3_ddrss) = {
861 .name = "k3_ddrss",
862 .id = UCLASS_RAM,
863 .of_match = k3_ddrss_ids,
864 .ops = &k3_ddrss_ops,
865 .probe = k3_ddrss_probe,
866 .priv_auto = sizeof(struct k3_ddrss_desc),
867};
Aswath Govindraju6324bc72022-01-25 20:56:30 +0530868
869static int k3_msmc_set_config(struct k3_msmc *msmc)
870{
871 u32 ddr_cfg0 = 0;
872 u32 ddr_cfg1 = 0;
873
874 ddr_cfg0 |= msmc->gran << 24;
875 ddr_cfg0 |= msmc->size << 16;
876 /* heartbeat_per, bit[4:0] setting to 3 is advisable */
877 ddr_cfg0 |= 3;
878
879 /* Program MULTI_DDR_CFG0 */
880 writel(ddr_cfg0, MULTI_DDR_CFG0);
881
882 ddr_cfg1 |= msmc->enable << 16;
883 ddr_cfg1 |= msmc->config << 8;
884 ddr_cfg1 |= msmc->active;
885
886 /* Program MULTI_DDR_CFG1 */
887 writel(ddr_cfg1, MULTI_DDR_CFG1);
888
889 /* Program DDR_CFG_LOAD */
890 writel(0x60000000, DDR_CFG_LOAD);
891
892 return 0;
893}
894
895static int k3_msmc_probe(struct udevice *dev)
896{
897 struct k3_msmc *msmc = dev_get_priv(dev);
898 int ret = 0;
899
900 /* Read the granular size from DT */
901 ret = dev_read_u32(dev, "intrlv-gran", &msmc->gran);
902 if (ret) {
903 dev_err(dev, "missing intrlv-gran property");
904 return -EINVAL;
905 }
906
907 /* Read the interleave region from DT */
908 ret = dev_read_u32(dev, "intrlv-size", &msmc->size);
909 if (ret) {
910 dev_err(dev, "missing intrlv-size property");
911 return -EINVAL;
912 }
913
914 /* Read ECC enable config */
915 ret = dev_read_u32(dev, "ecc-enable", &msmc->enable);
916 if (ret) {
917 dev_err(dev, "missing ecc-enable property");
918 return -EINVAL;
919 }
920
921 /* Read EMIF configuration */
922 ret = dev_read_u32(dev, "emif-config", &msmc->config);
923 if (ret) {
924 dev_err(dev, "missing emif-config property");
925 return -EINVAL;
926 }
927
928 /* Read EMIF active */
929 ret = dev_read_u32(dev, "emif-active", &msmc->active);
930 if (ret) {
931 dev_err(dev, "missing emif-active property");
932 return -EINVAL;
933 }
934
935 ret = k3_msmc_set_config(msmc);
936 if (ret) {
937 dev_err(dev, "error setting msmc config");
938 return -EINVAL;
939 }
940
941 return 0;
942}
943
944static const struct udevice_id k3_msmc_ids[] = {
945 { .compatible = "ti,j721s2-msmc"},
946 {}
947};
948
949U_BOOT_DRIVER(k3_msmc) = {
950 .name = "k3_msmc",
951 .of_match = k3_msmc_ids,
952 .id = UCLASS_MISC,
953 .probe = k3_msmc_probe,
954 .priv_auto = sizeof(struct k3_msmc),
955 .flags = DM_FLAG_DEFAULT_PD_CTRL_OFF,
956};