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