1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * OpenFirmware helpers for memory drivers
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2012 Texas Instruments, Inc.
6*4882a593Smuzhiyun * Copyright (C) 2019 Samsung Electronics Co., Ltd.
7*4882a593Smuzhiyun * Copyright (C) 2020 Krzysztof Kozlowski <krzk@kernel.org>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/of.h>
12*4882a593Smuzhiyun #include <linux/gfp.h>
13*4882a593Smuzhiyun #include <linux/export.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include "jedec_ddr.h"
16*4882a593Smuzhiyun #include "of_memory.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /**
19*4882a593Smuzhiyun * of_get_min_tck() - extract min timing values for ddr
20*4882a593Smuzhiyun * @np: pointer to ddr device tree node
21*4882a593Smuzhiyun * @dev: device requesting for min timing values
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * Populates the lpddr2_min_tck structure by extracting data
24*4882a593Smuzhiyun * from device tree node. Returns a pointer to the populated
25*4882a593Smuzhiyun * structure. If any error in populating the structure, returns
26*4882a593Smuzhiyun * default min timings provided by JEDEC.
27*4882a593Smuzhiyun */
of_get_min_tck(struct device_node * np,struct device * dev)28*4882a593Smuzhiyun const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
29*4882a593Smuzhiyun struct device *dev)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun int ret = 0;
32*4882a593Smuzhiyun struct lpddr2_min_tck *min;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun min = devm_kzalloc(dev, sizeof(*min), GFP_KERNEL);
35*4882a593Smuzhiyun if (!min)
36*4882a593Smuzhiyun goto default_min_tck;
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
39*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
40*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
41*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin);
42*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
43*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
44*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
45*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
46*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
47*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
48*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun if (ret) {
51*4882a593Smuzhiyun devm_kfree(dev, min);
52*4882a593Smuzhiyun goto default_min_tck;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun return min;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun default_min_tck:
58*4882a593Smuzhiyun dev_warn(dev, "Using default min-tck values\n");
59*4882a593Smuzhiyun return &lpddr2_jedec_min_tck;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun EXPORT_SYMBOL(of_get_min_tck);
62*4882a593Smuzhiyun
of_do_get_timings(struct device_node * np,struct lpddr2_timings * tim)63*4882a593Smuzhiyun static int of_do_get_timings(struct device_node *np,
64*4882a593Smuzhiyun struct lpddr2_timings *tim)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun int ret;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
69*4882a593Smuzhiyun ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
70*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
71*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
72*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWR", &tim->tWR);
73*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min);
74*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
75*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
76*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tXP", &tim->tXP);
77*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
78*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
79*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max);
80*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
81*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS);
82*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL);
83*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
84*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
85*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tDQSCK-max-derated",
86*4882a593Smuzhiyun &tim->tDQSCK_max_derated);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun return ret;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun /**
92*4882a593Smuzhiyun * of_get_ddr_timings() - extracts the ddr timings and updates no of
93*4882a593Smuzhiyun * frequencies available.
94*4882a593Smuzhiyun * @np_ddr: Pointer to ddr device tree node
95*4882a593Smuzhiyun * @dev: Device requesting for ddr timings
96*4882a593Smuzhiyun * @device_type: Type of ddr(LPDDR2 S2/S4)
97*4882a593Smuzhiyun * @nr_frequencies: No of frequencies available for ddr
98*4882a593Smuzhiyun * (updated by this function)
99*4882a593Smuzhiyun *
100*4882a593Smuzhiyun * Populates lpddr2_timings structure by extracting data from device
101*4882a593Smuzhiyun * tree node. Returns pointer to populated structure. If any error
102*4882a593Smuzhiyun * while populating, returns default timings provided by JEDEC.
103*4882a593Smuzhiyun */
of_get_ddr_timings(struct device_node * np_ddr,struct device * dev,u32 device_type,u32 * nr_frequencies)104*4882a593Smuzhiyun const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
105*4882a593Smuzhiyun struct device *dev,
106*4882a593Smuzhiyun u32 device_type,
107*4882a593Smuzhiyun u32 *nr_frequencies)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct lpddr2_timings *timings = NULL;
110*4882a593Smuzhiyun u32 arr_sz = 0, i = 0;
111*4882a593Smuzhiyun struct device_node *np_tim;
112*4882a593Smuzhiyun char *tim_compat = NULL;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun switch (device_type) {
115*4882a593Smuzhiyun case DDR_TYPE_LPDDR2_S2:
116*4882a593Smuzhiyun case DDR_TYPE_LPDDR2_S4:
117*4882a593Smuzhiyun tim_compat = "jedec,lpddr2-timings";
118*4882a593Smuzhiyun break;
119*4882a593Smuzhiyun default:
120*4882a593Smuzhiyun dev_warn(dev, "Unsupported memory type\n");
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun for_each_child_of_node(np_ddr, np_tim)
124*4882a593Smuzhiyun if (of_device_is_compatible(np_tim, tim_compat))
125*4882a593Smuzhiyun arr_sz++;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (arr_sz)
128*4882a593Smuzhiyun timings = devm_kcalloc(dev, arr_sz, sizeof(*timings),
129*4882a593Smuzhiyun GFP_KERNEL);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (!timings)
132*4882a593Smuzhiyun goto default_timings;
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun for_each_child_of_node(np_ddr, np_tim) {
135*4882a593Smuzhiyun if (of_device_is_compatible(np_tim, tim_compat)) {
136*4882a593Smuzhiyun if (of_do_get_timings(np_tim, &timings[i])) {
137*4882a593Smuzhiyun of_node_put(np_tim);
138*4882a593Smuzhiyun devm_kfree(dev, timings);
139*4882a593Smuzhiyun goto default_timings;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun i++;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun *nr_frequencies = arr_sz;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun return timings;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun default_timings:
150*4882a593Smuzhiyun dev_warn(dev, "Using default memory timings\n");
151*4882a593Smuzhiyun *nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings);
152*4882a593Smuzhiyun return lpddr2_jedec_timings;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun EXPORT_SYMBOL(of_get_ddr_timings);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /**
157*4882a593Smuzhiyun * of_lpddr3_get_min_tck() - extract min timing values for lpddr3
158*4882a593Smuzhiyun * @np: pointer to ddr device tree node
159*4882a593Smuzhiyun * @dev: device requesting for min timing values
160*4882a593Smuzhiyun *
161*4882a593Smuzhiyun * Populates the lpddr3_min_tck structure by extracting data
162*4882a593Smuzhiyun * from device tree node. Returns a pointer to the populated
163*4882a593Smuzhiyun * structure. If any error in populating the structure, returns NULL.
164*4882a593Smuzhiyun */
of_lpddr3_get_min_tck(struct device_node * np,struct device * dev)165*4882a593Smuzhiyun const struct lpddr3_min_tck *of_lpddr3_get_min_tck(struct device_node *np,
166*4882a593Smuzhiyun struct device *dev)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun int ret = 0;
169*4882a593Smuzhiyun struct lpddr3_min_tck *min;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun min = devm_kzalloc(dev, sizeof(*min), GFP_KERNEL);
172*4882a593Smuzhiyun if (!min)
173*4882a593Smuzhiyun goto default_min_tck;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRFC-min-tck", &min->tRFC);
176*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
177*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
178*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRPpb-min-tck", &min->tRPpb);
179*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
180*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRC-min-tck", &min->tRC);
181*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRAS-min-tck", &min->tRAS);
182*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
183*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
184*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
185*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tW2W-C2C-min-tck", &min->tW2W_C2C);
186*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tR2R-C2C-min-tck", &min->tR2R_C2C);
187*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWL-min-tck", &min->tWL);
188*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tDQSCK-min-tck", &min->tDQSCK);
189*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRL-min-tck", &min->tRL);
190*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
191*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tXSR-min-tck", &min->tXSR);
192*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
193*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
194*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
195*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tMRD-min-tck", &min->tMRD);
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (ret) {
198*4882a593Smuzhiyun dev_warn(dev, "Errors while parsing min-tck values\n");
199*4882a593Smuzhiyun devm_kfree(dev, min);
200*4882a593Smuzhiyun goto default_min_tck;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun return min;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun default_min_tck:
206*4882a593Smuzhiyun dev_warn(dev, "Using default min-tck values\n");
207*4882a593Smuzhiyun return NULL;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun EXPORT_SYMBOL(of_lpddr3_get_min_tck);
210*4882a593Smuzhiyun
of_lpddr3_do_get_timings(struct device_node * np,struct lpddr3_timings * tim)211*4882a593Smuzhiyun static int of_lpddr3_do_get_timings(struct device_node *np,
212*4882a593Smuzhiyun struct lpddr3_timings *tim)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun int ret;
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun /* The 'reg' param required since DT has changed, used as 'max-freq' */
217*4882a593Smuzhiyun ret = of_property_read_u32(np, "reg", &tim->max_freq);
218*4882a593Smuzhiyun ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
219*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRFC", &tim->tRFC);
220*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
221*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
222*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRPpb", &tim->tRPpb);
223*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
224*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRC", &tim->tRC);
225*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRAS", &tim->tRAS);
226*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
227*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tWR", &tim->tWR);
228*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
229*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tW2W-C2C", &tim->tW2W_C2C);
230*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tR2R-C2C", &tim->tR2R_C2C);
231*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
232*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tXSR", &tim->tXSR);
233*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tXP", &tim->tXP);
234*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tCKE", &tim->tCKE);
235*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
236*4882a593Smuzhiyun ret |= of_property_read_u32(np, "tMRD", &tim->tMRD);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return ret;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun /**
242*4882a593Smuzhiyun * of_lpddr3_get_ddr_timings() - extracts the lpddr3 timings and updates no of
243*4882a593Smuzhiyun * frequencies available.
244*4882a593Smuzhiyun * @np_ddr: Pointer to ddr device tree node
245*4882a593Smuzhiyun * @dev: Device requesting for ddr timings
246*4882a593Smuzhiyun * @device_type: Type of ddr
247*4882a593Smuzhiyun * @nr_frequencies: No of frequencies available for ddr
248*4882a593Smuzhiyun * (updated by this function)
249*4882a593Smuzhiyun *
250*4882a593Smuzhiyun * Populates lpddr3_timings structure by extracting data from device
251*4882a593Smuzhiyun * tree node. Returns pointer to populated structure. If any error
252*4882a593Smuzhiyun * while populating, returns NULL.
253*4882a593Smuzhiyun */
254*4882a593Smuzhiyun const struct lpddr3_timings
of_lpddr3_get_ddr_timings(struct device_node * np_ddr,struct device * dev,u32 device_type,u32 * nr_frequencies)255*4882a593Smuzhiyun *of_lpddr3_get_ddr_timings(struct device_node *np_ddr, struct device *dev,
256*4882a593Smuzhiyun u32 device_type, u32 *nr_frequencies)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun struct lpddr3_timings *timings = NULL;
259*4882a593Smuzhiyun u32 arr_sz = 0, i = 0;
260*4882a593Smuzhiyun struct device_node *np_tim;
261*4882a593Smuzhiyun char *tim_compat = NULL;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun switch (device_type) {
264*4882a593Smuzhiyun case DDR_TYPE_LPDDR3:
265*4882a593Smuzhiyun tim_compat = "jedec,lpddr3-timings";
266*4882a593Smuzhiyun break;
267*4882a593Smuzhiyun default:
268*4882a593Smuzhiyun dev_warn(dev, "Unsupported memory type\n");
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun for_each_child_of_node(np_ddr, np_tim)
272*4882a593Smuzhiyun if (of_device_is_compatible(np_tim, tim_compat))
273*4882a593Smuzhiyun arr_sz++;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun if (arr_sz)
276*4882a593Smuzhiyun timings = devm_kcalloc(dev, arr_sz, sizeof(*timings),
277*4882a593Smuzhiyun GFP_KERNEL);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun if (!timings)
280*4882a593Smuzhiyun goto default_timings;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun for_each_child_of_node(np_ddr, np_tim) {
283*4882a593Smuzhiyun if (of_device_is_compatible(np_tim, tim_compat)) {
284*4882a593Smuzhiyun if (of_lpddr3_do_get_timings(np_tim, &timings[i])) {
285*4882a593Smuzhiyun devm_kfree(dev, timings);
286*4882a593Smuzhiyun of_node_put(np_tim);
287*4882a593Smuzhiyun goto default_timings;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun i++;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun *nr_frequencies = arr_sz;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun return timings;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun default_timings:
298*4882a593Smuzhiyun dev_warn(dev, "Failed to get timings\n");
299*4882a593Smuzhiyun *nr_frequencies = 0;
300*4882a593Smuzhiyun return NULL;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun EXPORT_SYMBOL(of_lpddr3_get_ddr_timings);
303