blob: 6e9202b957962ec95fbad2469a0ef8c8557c5d95 [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>
Dave Gerlachd712b362021-05-11 10:22:11 -05009#include <clk.h>
Dave Gerlach296c83a2022-03-17 12:03:43 -050010#include <div64.h>
Dave Gerlachd712b362021-05-11 10:22:11 -050011#include <dm.h>
12#include <dm/device_compat.h>
Dave Gerlach296c83a2022-03-17 12:03:43 -050013#include <fdt_support.h>
Dave Gerlachd712b362021-05-11 10:22:11 -050014#include <ram.h>
15#include <hang.h>
16#include <log.h>
17#include <asm/io.h>
18#include <power-domain.h>
19#include <wait_bit.h>
Lokesh Vutladd01c632021-05-11 10:22:13 -050020#include <power/regulator.h>
Dave Gerlachd712b362021-05-11 10:22:11 -050021
22#include "lpddr4_obj_if.h"
23#include "lpddr4_if.h"
24#include "lpddr4_structs_if.h"
25#include "lpddr4_ctl_regs.h"
26
27#define SRAM_MAX 512
28
29#define CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS 0x80
30#define CTRLMMR_DDR4_FSP_CLKCHNG_ACK_OFFS 0xc0
31
Dominic Rath6feaf592022-04-06 11:56:47 +020032#define DDRSS_V2A_CTL_REG 0x0020
Wolfgang Denk62fb2b42021-09-27 17:42:39 +020033#define DDRSS_ECC_CTRL_REG 0x0120
Dave Gerlach2c861a92021-05-11 10:22:12 -050034
Dave Gerlach296c83a2022-03-17 12:03:43 -050035#define DDRSS_ECC_CTRL_REG_ECC_EN BIT(0)
36#define DDRSS_ECC_CTRL_REG_RMW_EN BIT(1)
37#define DDRSS_ECC_CTRL_REG_ECC_CK BIT(2)
38#define DDRSS_ECC_CTRL_REG_WR_ALLOC BIT(4)
39
40#define DDRSS_ECC_R0_STR_ADDR_REG 0x0130
41#define DDRSS_ECC_R0_END_ADDR_REG 0x0134
42#define DDRSS_ECC_R1_STR_ADDR_REG 0x0138
43#define DDRSS_ECC_R1_END_ADDR_REG 0x013c
44#define DDRSS_ECC_R2_STR_ADDR_REG 0x0140
45#define DDRSS_ECC_R2_END_ADDR_REG 0x0144
46#define DDRSS_ECC_1B_ERR_CNT_REG 0x0150
47
Aswath Govindrajub232cb42022-01-25 20:56:29 +053048#define SINGLE_DDR_SUBSYSTEM 0x1
49#define MULTI_DDR_SUBSYSTEM 0x2
50
Aswath Govindraju6324bc72022-01-25 20:56:30 +053051#define MULTI_DDR_CFG0 0x00114100
52#define MULTI_DDR_CFG1 0x00114104
53#define DDR_CFG_LOAD 0x00114110
54
55enum intrlv_gran {
56 GRAN_128B,
57 GRAN_512B,
58 GRAN_2KB,
59 GRAN_4KB,
60 GRAN_16KB,
61 GRAN_32KB,
62 GRAN_512KB,
63 GRAN_1GB,
64 GRAN_1_5GB,
65 GRAN_2GB,
66 GRAN_3GB,
67 GRAN_4GB,
68 GRAN_6GB,
69 GRAN_8GB,
70 GRAN_16GB
71};
72
73enum intrlv_size {
74 SIZE_0,
75 SIZE_128MB,
76 SIZE_256MB,
77 SIZE_512MB,
78 SIZE_1GB,
79 SIZE_2GB,
80 SIZE_3GB,
81 SIZE_4GB,
82 SIZE_6GB,
83 SIZE_8GB,
84 SIZE_12GB,
85 SIZE_16GB,
86 SIZE_32GB
87};
88
89struct k3_ddrss_data {
90 u32 flags;
91};
92
93enum ecc_enable {
94 DISABLE_ALL = 0,
95 ENABLE_0,
96 ENABLE_1,
97 ENABLE_ALL
98};
99
100enum emif_config {
101 INTERLEAVE_ALL = 0,
102 SEPR0,
103 SEPR1
104};
105
106enum emif_active {
107 EMIF_0 = 1,
108 EMIF_1,
109 EMIF_ALL
110};
111
112struct k3_msmc {
113 enum intrlv_gran gran;
114 enum intrlv_size size;
115 enum ecc_enable enable;
116 enum emif_config config;
117 enum emif_active active;
118};
119
Dave Gerlach296c83a2022-03-17 12:03:43 -0500120#define K3_DDRSS_MAX_ECC_REGIONS 3
121
122struct k3_ddrss_ecc_region {
123 u32 start;
124 u32 range;
125};
126
Dave Gerlachd712b362021-05-11 10:22:11 -0500127struct k3_ddrss_desc {
128 struct udevice *dev;
129 void __iomem *ddrss_ss_cfg;
130 void __iomem *ddrss_ctrl_mmr;
Dave Gerlachfd199dd2022-03-17 12:03:42 -0500131 void __iomem *ddrss_ctl_cfg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500132 struct power_domain ddrcfg_pwrdmn;
133 struct power_domain ddrdata_pwrdmn;
134 struct clk ddr_clk;
135 struct clk osc_clk;
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500136 u32 ddr_freq0;
Dave Gerlachd712b362021-05-11 10:22:11 -0500137 u32 ddr_freq1;
138 u32 ddr_freq2;
139 u32 ddr_fhs_cnt;
Bryan Brattlof2905a462023-07-17 17:15:26 -0500140 u32 dram_class;
Lokesh Vutladd01c632021-05-11 10:22:13 -0500141 struct udevice *vtt_supply;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530142 u32 instance;
143 lpddr4_obj *driverdt;
144 lpddr4_config config;
145 lpddr4_privatedata pd;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500146 struct k3_ddrss_ecc_region ecc_regions[K3_DDRSS_MAX_ECC_REGIONS];
147 u64 ecc_reserved_space;
148 bool ti_ecc_enabled;
Dave Gerlachd712b362021-05-11 10:22:11 -0500149};
150
Dave Gerlachd712b362021-05-11 10:22:11 -0500151struct reginitdata {
152 u32 ctl_regs[LPDDR4_INTR_CTL_REG_COUNT];
153 u16 ctl_regs_offs[LPDDR4_INTR_CTL_REG_COUNT];
154 u32 pi_regs[LPDDR4_INTR_PHY_INDEP_REG_COUNT];
155 u16 pi_regs_offs[LPDDR4_INTR_PHY_INDEP_REG_COUNT];
156 u32 phy_regs[LPDDR4_INTR_PHY_REG_COUNT];
157 u16 phy_regs_offs[LPDDR4_INTR_PHY_REG_COUNT];
158};
159
160#define TH_MACRO_EXP(fld, str) (fld##str)
161
162#define TH_FLD_MASK(fld) TH_MACRO_EXP(fld, _MASK)
163#define TH_FLD_SHIFT(fld) TH_MACRO_EXP(fld, _SHIFT)
164#define TH_FLD_WIDTH(fld) TH_MACRO_EXP(fld, _WIDTH)
165#define TH_FLD_WOCLR(fld) TH_MACRO_EXP(fld, _WOCLR)
166#define TH_FLD_WOSET(fld) TH_MACRO_EXP(fld, _WOSET)
167
168#define str(s) #s
169#define xstr(s) str(s)
170
171#define CTL_SHIFT 11
172#define PHY_SHIFT 11
173#define PI_SHIFT 10
174
175#define DENALI_CTL_0_DRAM_CLASS_DDR4 0xA
176#define DENALI_CTL_0_DRAM_CLASS_LPDDR4 0xB
177
178#define TH_OFFSET_FROM_REG(REG, SHIFT, offset) do {\
179 char *i, *pstr = xstr(REG); offset = 0;\
180 for (i = &pstr[SHIFT]; *i != '\0'; ++i) {\
181 offset = offset * 10 + (*i - '0'); } \
182 } while (0)
183
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530184static u32 k3_lpddr4_read_ddr_type(const lpddr4_privatedata *pd)
Dave Gerlachd712b362021-05-11 10:22:11 -0500185{
186 u32 status = 0U;
187 u32 offset = 0U;
188 u32 regval = 0U;
189 u32 dram_class = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530190 struct k3_ddrss_desc *ddrss = (struct k3_ddrss_desc *)pd->ddr_instance;
Dave Gerlachd712b362021-05-11 10:22:11 -0500191
192 TH_OFFSET_FROM_REG(LPDDR4__DRAM_CLASS__REG, CTL_SHIFT, offset);
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530193 status = ddrss->driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
Dave Gerlachd712b362021-05-11 10:22:11 -0500194 if (status > 0U) {
195 printf("%s: Failed to read DRAM_CLASS\n", __func__);
196 hang();
197 }
198
199 dram_class = ((regval & TH_FLD_MASK(LPDDR4__DRAM_CLASS__FLD)) >>
200 TH_FLD_SHIFT(LPDDR4__DRAM_CLASS__FLD));
201 return dram_class;
202}
203
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530204static void k3_lpddr4_freq_update(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500205{
206 unsigned int req_type, counter;
207
208 for (counter = 0; counter < ddrss->ddr_fhs_cnt; counter++) {
209 if (wait_for_bit_le32(ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530210 CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS + ddrss->instance * 0x10, 0x80,
Dave Gerlachd712b362021-05-11 10:22:11 -0500211 true, 10000, false)) {
212 printf("Timeout during frequency handshake\n");
213 hang();
214 }
215
216 req_type = readl(ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530217 CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS + ddrss->instance * 0x10) & 0x03;
Dave Gerlachd712b362021-05-11 10:22:11 -0500218
Dave Gerlachd712b362021-05-11 10:22:11 -0500219 if (req_type == 1)
220 clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq1);
221 else if (req_type == 2)
222 clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq2);
223 else if (req_type == 0)
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500224 clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq0);
Dave Gerlachd712b362021-05-11 10:22:11 -0500225 else
226 printf("%s: Invalid freq request type\n", __func__);
227
228 writel(0x1, ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530229 CTRLMMR_DDR4_FSP_CLKCHNG_ACK_OFFS + ddrss->instance * 0x10);
Dave Gerlachd712b362021-05-11 10:22:11 -0500230 if (wait_for_bit_le32(ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530231 CTRLMMR_DDR4_FSP_CLKCHNG_REQ_OFFS + ddrss->instance * 0x10, 0x80,
Dave Gerlachd712b362021-05-11 10:22:11 -0500232 false, 10, false)) {
233 printf("Timeout during frequency handshake\n");
234 hang();
235 }
236 writel(0x0, ddrss->ddrss_ctrl_mmr +
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530237 CTRLMMR_DDR4_FSP_CLKCHNG_ACK_OFFS + ddrss->instance * 0x10);
Dave Gerlachd712b362021-05-11 10:22:11 -0500238 }
239}
240
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530241static void k3_lpddr4_ack_freq_upd_req(const lpddr4_privatedata *pd)
Dave Gerlachd712b362021-05-11 10:22:11 -0500242{
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530243 struct k3_ddrss_desc *ddrss = (struct k3_ddrss_desc *)pd->ddr_instance;
Dave Gerlachd712b362021-05-11 10:22:11 -0500244
Bryan Brattlof2905a462023-07-17 17:15:26 -0500245 switch (ddrss->dram_class) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500246 case DENALI_CTL_0_DRAM_CLASS_DDR4:
247 break;
248 case DENALI_CTL_0_DRAM_CLASS_LPDDR4:
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530249 k3_lpddr4_freq_update(ddrss);
Dave Gerlachd712b362021-05-11 10:22:11 -0500250 break;
251 default:
252 printf("Unrecognized dram_class cannot update frequency!\n");
253 }
254}
255
256static int k3_ddrss_init_freq(struct k3_ddrss_desc *ddrss)
257{
Dave Gerlachd712b362021-05-11 10:22:11 -0500258 int ret;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530259 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500260
Bryan Brattlof2905a462023-07-17 17:15:26 -0500261 ddrss->dram_class = k3_lpddr4_read_ddr_type(pd);
Dave Gerlachd712b362021-05-11 10:22:11 -0500262
Bryan Brattlof2905a462023-07-17 17:15:26 -0500263 switch (ddrss->dram_class) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500264 case DENALI_CTL_0_DRAM_CLASS_DDR4:
265 /* Set to ddr_freq1 from DT for DDR4 */
266 ret = clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq1);
267 break;
268 case DENALI_CTL_0_DRAM_CLASS_LPDDR4:
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500269 ret = clk_set_rate(&ddrss->ddr_clk, ddrss->ddr_freq0);
Dave Gerlachd712b362021-05-11 10:22:11 -0500270 break;
271 default:
272 ret = -EINVAL;
273 printf("Unrecognized dram_class cannot init frequency!\n");
274 }
275
276 if (ret < 0)
277 dev_err(ddrss->dev, "ddr clk init failed: %d\n", ret);
278 else
279 ret = 0;
280
281 return ret;
282}
283
284static void k3_lpddr4_info_handler(const lpddr4_privatedata *pd,
285 lpddr4_infotype infotype)
286{
287 if (infotype == LPDDR4_DRV_SOC_PLL_UPDATE)
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530288 k3_lpddr4_ack_freq_upd_req(pd);
Dave Gerlachd712b362021-05-11 10:22:11 -0500289}
290
291static int k3_ddrss_power_on(struct k3_ddrss_desc *ddrss)
292{
293 int ret;
294
295 debug("%s(ddrss=%p)\n", __func__, ddrss);
296
297 ret = power_domain_on(&ddrss->ddrcfg_pwrdmn);
298 if (ret) {
299 dev_err(ddrss->dev, "power_domain_on() failed: %d\n", ret);
300 return ret;
301 }
302
303 ret = power_domain_on(&ddrss->ddrdata_pwrdmn);
304 if (ret) {
305 dev_err(ddrss->dev, "power_domain_on() failed: %d\n", ret);
306 return ret;
307 }
308
Lokesh Vutladd01c632021-05-11 10:22:13 -0500309 ret = device_get_supply_regulator(ddrss->dev, "vtt-supply",
310 &ddrss->vtt_supply);
311 if (ret) {
312 dev_dbg(ddrss->dev, "vtt-supply not found.\n");
313 } else {
314 ret = regulator_set_value(ddrss->vtt_supply, 3300000);
315 if (ret)
316 return ret;
317 dev_dbg(ddrss->dev, "VTT regulator enabled, volt = %d\n",
318 regulator_get_value(ddrss->vtt_supply));
319 }
320
Dave Gerlachd712b362021-05-11 10:22:11 -0500321 return 0;
322}
323
324static int k3_ddrss_ofdata_to_priv(struct udevice *dev)
325{
326 struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530327 struct k3_ddrss_data *ddrss_data = (struct k3_ddrss_data *)dev_get_driver_data(dev);
Matthias Schiffer47331932023-09-27 15:33:34 +0200328 void *reg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500329 int ret;
330
331 debug("%s(dev=%p)\n", __func__, dev);
332
Matthias Schiffer47331932023-09-27 15:33:34 +0200333 reg = dev_read_addr_name_ptr(dev, "cfg");
334 if (!reg) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500335 dev_err(dev, "No reg property for DDRSS wrapper logic\n");
336 return -EINVAL;
337 }
Matthias Schiffer47331932023-09-27 15:33:34 +0200338 ddrss->ddrss_ctl_cfg = reg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500339
Matthias Schiffer47331932023-09-27 15:33:34 +0200340 reg = dev_read_addr_name_ptr(dev, "ctrl_mmr_lp4");
341 if (!reg) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500342 dev_err(dev, "No reg property for CTRL MMR\n");
343 return -EINVAL;
344 }
Matthias Schiffer47331932023-09-27 15:33:34 +0200345 ddrss->ddrss_ctrl_mmr = reg;
Dave Gerlachd712b362021-05-11 10:22:11 -0500346
Matthias Schiffer47331932023-09-27 15:33:34 +0200347 reg = dev_read_addr_name_ptr(dev, "ss_cfg");
348 if (!reg)
Dave Gerlach296c83a2022-03-17 12:03:43 -0500349 dev_dbg(dev, "No reg property for SS Config region, but this is optional so continuing.\n");
Matthias Schiffer47331932023-09-27 15:33:34 +0200350 ddrss->ddrss_ss_cfg = reg;
Dave Gerlach296c83a2022-03-17 12:03:43 -0500351
Dave Gerlachd712b362021-05-11 10:22:11 -0500352 ret = power_domain_get_by_index(dev, &ddrss->ddrcfg_pwrdmn, 0);
353 if (ret) {
354 dev_err(dev, "power_domain_get() failed: %d\n", ret);
355 return ret;
356 }
357
358 ret = power_domain_get_by_index(dev, &ddrss->ddrdata_pwrdmn, 1);
359 if (ret) {
360 dev_err(dev, "power_domain_get() failed: %d\n", ret);
361 return ret;
362 }
363
364 ret = clk_get_by_index(dev, 0, &ddrss->ddr_clk);
365 if (ret)
366 dev_err(dev, "clk get failed%d\n", ret);
367
368 ret = clk_get_by_index(dev, 1, &ddrss->osc_clk);
369 if (ret)
370 dev_err(dev, "clk get failed for osc clk %d\n", ret);
371
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530372 /* Reading instance number for multi ddr subystems */
373 if (ddrss_data->flags & MULTI_DDR_SUBSYSTEM) {
374 ret = dev_read_u32(dev, "instance", &ddrss->instance);
375 if (ret) {
376 dev_err(dev, "missing instance property");
377 return -EINVAL;
378 }
379 } else {
380 ddrss->instance = 0;
381 }
382
Dave Gerlachff4e82b2022-04-08 16:46:50 -0500383 ret = dev_read_u32(dev, "ti,ddr-freq0", &ddrss->ddr_freq0);
384 if (ret) {
385 ddrss->ddr_freq0 = clk_get_rate(&ddrss->osc_clk);
386 dev_dbg(dev,
387 "ddr freq0 not populated, using bypass frequency.\n");
388 }
389
Dave Gerlachd712b362021-05-11 10:22:11 -0500390 ret = dev_read_u32(dev, "ti,ddr-freq1", &ddrss->ddr_freq1);
391 if (ret)
392 dev_err(dev, "ddr freq1 not populated %d\n", ret);
393
394 ret = dev_read_u32(dev, "ti,ddr-freq2", &ddrss->ddr_freq2);
395 if (ret)
396 dev_err(dev, "ddr freq2 not populated %d\n", ret);
397
398 ret = dev_read_u32(dev, "ti,ddr-fhs-cnt", &ddrss->ddr_fhs_cnt);
399 if (ret)
400 dev_err(dev, "ddr fhs cnt not populated %d\n", ret);
401
Dave Gerlach296c83a2022-03-17 12:03:43 -0500402 ddrss->ti_ecc_enabled = dev_read_bool(dev, "ti,ecc-enable");
403
Dave Gerlachd712b362021-05-11 10:22:11 -0500404 return ret;
405}
406
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530407void k3_lpddr4_probe(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500408{
409 u32 status = 0U;
410 u16 configsize = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530411 lpddr4_config *config = &ddrss->config;
Dave Gerlachd712b362021-05-11 10:22:11 -0500412
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530413 status = ddrss->driverdt->probe(config, &configsize);
Dave Gerlachd712b362021-05-11 10:22:11 -0500414
415 if ((status != 0) || (configsize != sizeof(lpddr4_privatedata))
416 || (configsize > SRAM_MAX)) {
417 printf("%s: FAIL\n", __func__);
418 hang();
419 } else {
420 debug("%s: PASS\n", __func__);
421 }
422}
423
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530424void k3_lpddr4_init(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500425{
426 u32 status = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530427 lpddr4_config *config = &ddrss->config;
428 lpddr4_obj *driverdt = ddrss->driverdt;
429 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500430
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530431 if ((sizeof(*pd) != sizeof(lpddr4_privatedata)) || (sizeof(*pd) > SRAM_MAX)) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500432 printf("%s: FAIL\n", __func__);
433 hang();
434 }
435
Dave Gerlachfd199dd2022-03-17 12:03:42 -0500436 config->ctlbase = (struct lpddr4_ctlregs_s *)ddrss->ddrss_ctl_cfg;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530437 config->infohandler = (lpddr4_infocallback) k3_lpddr4_info_handler;
Dave Gerlachd712b362021-05-11 10:22:11 -0500438
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530439 status = driverdt->init(pd, config);
440
441 /* linking ddr instance to lpddr4 */
442 pd->ddr_instance = (void *)ddrss;
Dave Gerlachd712b362021-05-11 10:22:11 -0500443
444 if ((status > 0U) ||
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530445 (pd->ctlbase != (struct lpddr4_ctlregs_s *)config->ctlbase) ||
446 (pd->ctlinterrupthandler != config->ctlinterrupthandler) ||
447 (pd->phyindepinterrupthandler != config->phyindepinterrupthandler)) {
Dave Gerlachd712b362021-05-11 10:22:11 -0500448 printf("%s: FAIL\n", __func__);
449 hang();
450 } else {
451 debug("%s: PASS\n", __func__);
452 }
453}
454
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530455void populate_data_array_from_dt(struct k3_ddrss_desc *ddrss,
456 struct reginitdata *reginit_data)
Dave Gerlachd712b362021-05-11 10:22:11 -0500457{
458 int ret, i;
459
460 ret = dev_read_u32_array(ddrss->dev, "ti,ctl-data",
461 (u32 *)reginit_data->ctl_regs,
462 LPDDR4_INTR_CTL_REG_COUNT);
463 if (ret)
464 printf("Error reading ctrl data %d\n", ret);
465
466 for (i = 0; i < LPDDR4_INTR_CTL_REG_COUNT; i++)
467 reginit_data->ctl_regs_offs[i] = i;
468
469 ret = dev_read_u32_array(ddrss->dev, "ti,pi-data",
470 (u32 *)reginit_data->pi_regs,
471 LPDDR4_INTR_PHY_INDEP_REG_COUNT);
472 if (ret)
473 printf("Error reading PI data\n");
474
475 for (i = 0; i < LPDDR4_INTR_PHY_INDEP_REG_COUNT; i++)
476 reginit_data->pi_regs_offs[i] = i;
477
478 ret = dev_read_u32_array(ddrss->dev, "ti,phy-data",
479 (u32 *)reginit_data->phy_regs,
480 LPDDR4_INTR_PHY_REG_COUNT);
481 if (ret)
482 printf("Error reading PHY data %d\n", ret);
483
484 for (i = 0; i < LPDDR4_INTR_PHY_REG_COUNT; i++)
485 reginit_data->phy_regs_offs[i] = i;
486}
487
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530488void k3_lpddr4_hardware_reg_init(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500489{
490 u32 status = 0U;
491 struct reginitdata reginitdata;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530492 lpddr4_obj *driverdt = ddrss->driverdt;
493 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500494
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530495 populate_data_array_from_dt(ddrss, &reginitdata);
Dave Gerlachd712b362021-05-11 10:22:11 -0500496
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530497 status = driverdt->writectlconfig(pd, reginitdata.ctl_regs,
Dave Gerlachd712b362021-05-11 10:22:11 -0500498 reginitdata.ctl_regs_offs,
499 LPDDR4_INTR_CTL_REG_COUNT);
500 if (!status)
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530501 status = driverdt->writephyindepconfig(pd, reginitdata.pi_regs,
Dave Gerlachd712b362021-05-11 10:22:11 -0500502 reginitdata.pi_regs_offs,
503 LPDDR4_INTR_PHY_INDEP_REG_COUNT);
504 if (!status)
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530505 status = driverdt->writephyconfig(pd, reginitdata.phy_regs,
Dave Gerlachd712b362021-05-11 10:22:11 -0500506 reginitdata.phy_regs_offs,
507 LPDDR4_INTR_PHY_REG_COUNT);
508 if (status) {
509 printf("%s: FAIL\n", __func__);
510 hang();
511 }
512}
513
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530514void k3_lpddr4_start(struct k3_ddrss_desc *ddrss)
Dave Gerlachd712b362021-05-11 10:22:11 -0500515{
516 u32 status = 0U;
517 u32 regval = 0U;
518 u32 offset = 0U;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530519 lpddr4_obj *driverdt = ddrss->driverdt;
520 lpddr4_privatedata *pd = &ddrss->pd;
Dave Gerlachd712b362021-05-11 10:22:11 -0500521
522 TH_OFFSET_FROM_REG(LPDDR4__START__REG, CTL_SHIFT, offset);
523
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530524 status = driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
Dave Gerlachd712b362021-05-11 10:22:11 -0500525 if ((status > 0U) || ((regval & TH_FLD_MASK(LPDDR4__START__FLD)) != 0U)) {
526 printf("%s: Pre start FAIL\n", __func__);
527 hang();
528 }
529
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530530 status = driverdt->start(pd);
Dave Gerlachd712b362021-05-11 10:22:11 -0500531 if (status > 0U) {
532 printf("%s: FAIL\n", __func__);
533 hang();
534 }
535
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530536 status = driverdt->readreg(pd, LPDDR4_CTL_REGS, offset, &regval);
Dave Gerlachd712b362021-05-11 10:22:11 -0500537 if ((status > 0U) || ((regval & TH_FLD_MASK(LPDDR4__START__FLD)) != 1U)) {
538 printf("%s: Post start FAIL\n", __func__);
539 hang();
540 } else {
541 debug("%s: Post start PASS\n", __func__);
542 }
543}
544
Dave Gerlach296c83a2022-03-17 12:03:43 -0500545static void k3_ddrss_set_ecc_range_r0(u32 base, u32 start_address, u32 size)
546{
547 writel((start_address) >> 16, base + DDRSS_ECC_R0_STR_ADDR_REG);
548 writel((start_address + size - 1) >> 16, base + DDRSS_ECC_R0_END_ADDR_REG);
549}
550
551static void k3_ddrss_preload_ecc_mem_region(u32 *addr, u32 size, u32 word)
552{
553 int i;
554
555 printf("ECC is enabled, priming DDR which will take several seconds.\n");
556
557 for (i = 0; i < (size / 4); i++)
558 addr[i] = word;
559}
560
561static void k3_ddrss_lpddr4_ecc_calc_reserved_mem(struct k3_ddrss_desc *ddrss)
562{
563 fdtdec_setup_mem_size_base_lowest();
564
565 ddrss->ecc_reserved_space = gd->ram_size;
566 do_div(ddrss->ecc_reserved_space, 9);
567
568 /* Round to clean number */
569 ddrss->ecc_reserved_space = 1ull << (fls(ddrss->ecc_reserved_space));
570}
571
572static void k3_ddrss_lpddr4_ecc_init(struct k3_ddrss_desc *ddrss)
573{
574 u32 ecc_region_start = ddrss->ecc_regions[0].start;
575 u32 ecc_range = ddrss->ecc_regions[0].range;
576 u32 base = (u32)ddrss->ddrss_ss_cfg;
577 u32 val;
578
579 /* Only Program region 0 which covers full ddr space */
580 k3_ddrss_set_ecc_range_r0(base, ecc_region_start - gd->ram_base, ecc_range);
581
582 /* Enable ECC, RMW, WR_ALLOC */
583 writel(DDRSS_ECC_CTRL_REG_ECC_EN | DDRSS_ECC_CTRL_REG_RMW_EN |
584 DDRSS_ECC_CTRL_REG_WR_ALLOC, base + DDRSS_ECC_CTRL_REG);
585
586 /* Preload ECC Mem region with 0's */
587 k3_ddrss_preload_ecc_mem_region((u32 *)ecc_region_start, ecc_range,
588 0x00000000);
589
590 /* Clear Error Count Register */
591 writel(0x1, base + DDRSS_ECC_1B_ERR_CNT_REG);
592
593 /* Enable ECC Check */
594 val = readl(base + DDRSS_ECC_CTRL_REG);
595 val |= DDRSS_ECC_CTRL_REG_ECC_CK;
596 writel(val, base + DDRSS_ECC_CTRL_REG);
597}
598
Dave Gerlachd712b362021-05-11 10:22:11 -0500599static int k3_ddrss_probe(struct udevice *dev)
600{
601 int ret;
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530602 struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
Dave Gerlachd712b362021-05-11 10:22:11 -0500603
604 debug("%s(dev=%p)\n", __func__, dev);
605
606 ret = k3_ddrss_ofdata_to_priv(dev);
607 if (ret)
608 return ret;
609
610 ddrss->dev = dev;
611 ret = k3_ddrss_power_on(ddrss);
612 if (ret)
613 return ret;
614
Dave Gerlach2c861a92021-05-11 10:22:12 -0500615#ifdef CONFIG_K3_AM64_DDRSS
Dominic Rath6feaf592022-04-06 11:56:47 +0200616 /* AM64x supports only up to 2 GB SDRAM */
617 writel(0x000001EF, ddrss->ddrss_ss_cfg + DDRSS_V2A_CTL_REG);
Dave Gerlach2c861a92021-05-11 10:22:12 -0500618 writel(0x0, ddrss->ddrss_ss_cfg + DDRSS_ECC_CTRL_REG);
619#endif
620
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530621 ddrss->driverdt = lpddr4_getinstance();
622
623 k3_lpddr4_probe(ddrss);
624 k3_lpddr4_init(ddrss);
625 k3_lpddr4_hardware_reg_init(ddrss);
Dave Gerlachd712b362021-05-11 10:22:11 -0500626
627 ret = k3_ddrss_init_freq(ddrss);
628 if (ret)
629 return ret;
630
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530631 k3_lpddr4_start(ddrss);
Dave Gerlachd712b362021-05-11 10:22:11 -0500632
Dave Gerlach296c83a2022-03-17 12:03:43 -0500633 if (ddrss->ti_ecc_enabled) {
634 if (!ddrss->ddrss_ss_cfg) {
635 printf("%s: ss_cfg is required if ecc is enabled but not provided.",
636 __func__);
637 return -EINVAL;
638 }
639
640 k3_ddrss_lpddr4_ecc_calc_reserved_mem(ddrss);
641
642 /* Always configure one region that covers full DDR space */
643 ddrss->ecc_regions[0].start = gd->ram_base;
644 ddrss->ecc_regions[0].range = gd->ram_size - ddrss->ecc_reserved_space;
645 k3_ddrss_lpddr4_ecc_init(ddrss);
646 }
647
Dave Gerlachd712b362021-05-11 10:22:11 -0500648 return ret;
649}
650
Dave Gerlach296c83a2022-03-17 12:03:43 -0500651int k3_ddrss_ddr_fdt_fixup(struct udevice *dev, void *blob, struct bd_info *bd)
652{
653 struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
654 u64 start[CONFIG_NR_DRAM_BANKS];
655 u64 size[CONFIG_NR_DRAM_BANKS];
656 int bank;
657
658 if (ddrss->ecc_reserved_space == 0)
659 return 0;
660
661 for (bank = CONFIG_NR_DRAM_BANKS - 1; bank >= 0; bank--) {
662 if (ddrss->ecc_reserved_space > bd->bi_dram[bank].size) {
663 ddrss->ecc_reserved_space -= bd->bi_dram[bank].size;
664 bd->bi_dram[bank].size = 0;
665 } else {
666 bd->bi_dram[bank].size -= ddrss->ecc_reserved_space;
667 break;
668 }
669 }
670
671 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
672 start[bank] = bd->bi_dram[bank].start;
673 size[bank] = bd->bi_dram[bank].size;
674 }
675
676 return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
677}
678
Dave Gerlachd712b362021-05-11 10:22:11 -0500679static int k3_ddrss_get_info(struct udevice *dev, struct ram_info *info)
680{
681 return 0;
682}
683
684static struct ram_ops k3_ddrss_ops = {
685 .get_info = k3_ddrss_get_info,
686};
687
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530688static const struct k3_ddrss_data k3_data = {
689 .flags = SINGLE_DDR_SUBSYSTEM,
690};
691
692static const struct k3_ddrss_data j721s2_data = {
693 .flags = MULTI_DDR_SUBSYSTEM,
694};
695
Dave Gerlachd712b362021-05-11 10:22:11 -0500696static const struct udevice_id k3_ddrss_ids[] = {
Bryan Brattlofdebb0452022-11-03 19:13:53 -0500697 {.compatible = "ti,am62a-ddrss", .data = (ulong)&k3_data, },
Aswath Govindrajub232cb42022-01-25 20:56:29 +0530698 {.compatible = "ti,am64-ddrss", .data = (ulong)&k3_data, },
699 {.compatible = "ti,j721e-ddrss", .data = (ulong)&k3_data, },
700 {.compatible = "ti,j721s2-ddrss", .data = (ulong)&j721s2_data, },
Dave Gerlachd712b362021-05-11 10:22:11 -0500701 {}
702};
703
704U_BOOT_DRIVER(k3_ddrss) = {
705 .name = "k3_ddrss",
706 .id = UCLASS_RAM,
707 .of_match = k3_ddrss_ids,
708 .ops = &k3_ddrss_ops,
709 .probe = k3_ddrss_probe,
710 .priv_auto = sizeof(struct k3_ddrss_desc),
711};
Aswath Govindraju6324bc72022-01-25 20:56:30 +0530712
713static int k3_msmc_set_config(struct k3_msmc *msmc)
714{
715 u32 ddr_cfg0 = 0;
716 u32 ddr_cfg1 = 0;
717
718 ddr_cfg0 |= msmc->gran << 24;
719 ddr_cfg0 |= msmc->size << 16;
720 /* heartbeat_per, bit[4:0] setting to 3 is advisable */
721 ddr_cfg0 |= 3;
722
723 /* Program MULTI_DDR_CFG0 */
724 writel(ddr_cfg0, MULTI_DDR_CFG0);
725
726 ddr_cfg1 |= msmc->enable << 16;
727 ddr_cfg1 |= msmc->config << 8;
728 ddr_cfg1 |= msmc->active;
729
730 /* Program MULTI_DDR_CFG1 */
731 writel(ddr_cfg1, MULTI_DDR_CFG1);
732
733 /* Program DDR_CFG_LOAD */
734 writel(0x60000000, DDR_CFG_LOAD);
735
736 return 0;
737}
738
739static int k3_msmc_probe(struct udevice *dev)
740{
741 struct k3_msmc *msmc = dev_get_priv(dev);
742 int ret = 0;
743
744 /* Read the granular size from DT */
745 ret = dev_read_u32(dev, "intrlv-gran", &msmc->gran);
746 if (ret) {
747 dev_err(dev, "missing intrlv-gran property");
748 return -EINVAL;
749 }
750
751 /* Read the interleave region from DT */
752 ret = dev_read_u32(dev, "intrlv-size", &msmc->size);
753 if (ret) {
754 dev_err(dev, "missing intrlv-size property");
755 return -EINVAL;
756 }
757
758 /* Read ECC enable config */
759 ret = dev_read_u32(dev, "ecc-enable", &msmc->enable);
760 if (ret) {
761 dev_err(dev, "missing ecc-enable property");
762 return -EINVAL;
763 }
764
765 /* Read EMIF configuration */
766 ret = dev_read_u32(dev, "emif-config", &msmc->config);
767 if (ret) {
768 dev_err(dev, "missing emif-config property");
769 return -EINVAL;
770 }
771
772 /* Read EMIF active */
773 ret = dev_read_u32(dev, "emif-active", &msmc->active);
774 if (ret) {
775 dev_err(dev, "missing emif-active property");
776 return -EINVAL;
777 }
778
779 ret = k3_msmc_set_config(msmc);
780 if (ret) {
781 dev_err(dev, "error setting msmc config");
782 return -EINVAL;
783 }
784
785 return 0;
786}
787
788static const struct udevice_id k3_msmc_ids[] = {
789 { .compatible = "ti,j721s2-msmc"},
790 {}
791};
792
793U_BOOT_DRIVER(k3_msmc) = {
794 .name = "k3_msmc",
795 .of_match = k3_msmc_ids,
796 .id = UCLASS_MISC,
797 .probe = k3_msmc_probe,
798 .priv_auto = sizeof(struct k3_msmc),
799 .flags = DM_FLAG_DEFAULT_PD_CTRL_OFF,
800};