aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/memory/of_memory.c
diff options
context:
space:
mode:
authorAneesh V <aneesh@ti.com>2012-08-17 04:35:15 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-04 19:14:31 -0400
commite6b42eb6a66c188642aeb447312938c6f6ebee86 (patch)
tree0deb9e5d95c2668041034fdfd701c60123bb78e2 /drivers/memory/of_memory.c
parent6f1cbd4a25c58323b57f1374e827c363b44683cb (diff)
memory: emif: add device tree support to emif driver
Device tree support for the EMIF driver. LPDDR2 generic timings extraction from device is managed using couple of helper functions which can be used by other memory controller drivers. Reviewed-by: Benoit Cousson <b-cousson@ti.com> Reviewed-by: Grant Likely <grant.likely@secretlab.ca> Tested-by: Lokesh Vutla <lokeshvutla@ti.com> Signed-off-by: Aneesh V <aneesh@ti.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/memory/of_memory.c')
-rw-r--r--drivers/memory/of_memory.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c
new file mode 100644
index 000000000000..60074351f17e
--- /dev/null
+++ b/drivers/memory/of_memory.c
@@ -0,0 +1,153 @@
1/*
2 * OpenFirmware helpers for memory drivers
3 *
4 * Copyright (C) 2012 Texas Instruments, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/device.h>
13#include <linux/platform_device.h>
14#include <linux/list.h>
15#include <linux/of.h>
16#include <linux/gfp.h>
17#include <memory/jedec_ddr.h>
18#include <linux/export.h>
19
20/**
21 * of_get_min_tck() - extract min timing values for ddr
22 * @np: pointer to ddr device tree node
23 * @device: device requesting for min timing values
24 *
25 * Populates the lpddr2_min_tck structure by extracting data
26 * from device tree node. Returns a pointer to the populated
27 * structure. If any error in populating the structure, returns
28 * default min timings provided by JEDEC.
29 */
30const struct lpddr2_min_tck *of_get_min_tck(struct device_node *np,
31 struct device *dev)
32{
33 int ret = 0;
34 struct lpddr2_min_tck *min;
35
36 min = devm_kzalloc(dev, sizeof(*min), GFP_KERNEL);
37 if (!min)
38 goto default_min_tck;
39
40 ret |= of_property_read_u32(np, "tRPab-min-tck", &min->tRPab);
41 ret |= of_property_read_u32(np, "tRCD-min-tck", &min->tRCD);
42 ret |= of_property_read_u32(np, "tWR-min-tck", &min->tWR);
43 ret |= of_property_read_u32(np, "tRASmin-min-tck", &min->tRASmin);
44 ret |= of_property_read_u32(np, "tRRD-min-tck", &min->tRRD);
45 ret |= of_property_read_u32(np, "tWTR-min-tck", &min->tWTR);
46 ret |= of_property_read_u32(np, "tXP-min-tck", &min->tXP);
47 ret |= of_property_read_u32(np, "tRTP-min-tck", &min->tRTP);
48 ret |= of_property_read_u32(np, "tCKE-min-tck", &min->tCKE);
49 ret |= of_property_read_u32(np, "tCKESR-min-tck", &min->tCKESR);
50 ret |= of_property_read_u32(np, "tFAW-min-tck", &min->tFAW);
51
52 if (ret) {
53 devm_kfree(dev, min);
54 goto default_min_tck;
55 }
56
57 return min;
58
59default_min_tck:
60 dev_warn(dev, "%s: using default min-tck values\n", __func__);
61 return &lpddr2_jedec_min_tck;
62}
63EXPORT_SYMBOL(of_get_min_tck);
64
65static int of_do_get_timings(struct device_node *np,
66 struct lpddr2_timings *tim)
67{
68 int ret;
69
70 ret = of_property_read_u32(np, "max-freq", &tim->max_freq);
71 ret |= of_property_read_u32(np, "min-freq", &tim->min_freq);
72 ret |= of_property_read_u32(np, "tRPab", &tim->tRPab);
73 ret |= of_property_read_u32(np, "tRCD", &tim->tRCD);
74 ret |= of_property_read_u32(np, "tWR", &tim->tWR);
75 ret |= of_property_read_u32(np, "tRAS-min", &tim->tRAS_min);
76 ret |= of_property_read_u32(np, "tRRD", &tim->tRRD);
77 ret |= of_property_read_u32(np, "tWTR", &tim->tWTR);
78 ret |= of_property_read_u32(np, "tXP", &tim->tXP);
79 ret |= of_property_read_u32(np, "tRTP", &tim->tRTP);
80 ret |= of_property_read_u32(np, "tCKESR", &tim->tCKESR);
81 ret |= of_property_read_u32(np, "tDQSCK-max", &tim->tDQSCK_max);
82 ret |= of_property_read_u32(np, "tFAW", &tim->tFAW);
83 ret |= of_property_read_u32(np, "tZQCS", &tim->tZQCS);
84 ret |= of_property_read_u32(np, "tZQCL", &tim->tZQCL);
85 ret |= of_property_read_u32(np, "tZQinit", &tim->tZQinit);
86 ret |= of_property_read_u32(np, "tRAS-max-ns", &tim->tRAS_max_ns);
87 ret |= of_property_read_u32(np, "tDQSCK-max-derated",
88 &tim->tDQSCK_max_derated);
89
90 return ret;
91}
92
93/**
94 * of_get_ddr_timings() - extracts the ddr timings and updates no of
95 * frequencies available.
96 * @np_ddr: Pointer to ddr device tree node
97 * @dev: Device requesting for ddr timings
98 * @device_type: Type of ddr(LPDDR2 S2/S4)
99 * @nr_frequencies: No of frequencies available for ddr
100 * (updated by this function)
101 *
102 * Populates lpddr2_timings structure by extracting data from device
103 * tree node. Returns pointer to populated structure. If any error
104 * while populating, returns default timings provided by JEDEC.
105 */
106const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
107 struct device *dev, u32 device_type, u32 *nr_frequencies)
108{
109 struct lpddr2_timings *timings = NULL;
110 u32 arr_sz = 0, i = 0;
111 struct device_node *np_tim;
112 char *tim_compat;
113
114 switch (device_type) {
115 case DDR_TYPE_LPDDR2_S2:
116 case DDR_TYPE_LPDDR2_S4:
117 tim_compat = "jedec,lpddr2-timings";
118 break;
119 default:
120 dev_warn(dev, "%s: un-supported memory type\n", __func__);
121 }
122
123 for_each_child_of_node(np_ddr, np_tim)
124 if (of_device_is_compatible(np_tim, tim_compat))
125 arr_sz++;
126
127 if (arr_sz)
128 timings = devm_kzalloc(dev, sizeof(*timings) * arr_sz,
129 GFP_KERNEL);
130
131 if (!timings)
132 goto default_timings;
133
134 for_each_child_of_node(np_ddr, np_tim) {
135 if (of_device_is_compatible(np_tim, tim_compat)) {
136 if (of_do_get_timings(np_tim, &timings[i])) {
137 devm_kfree(dev, timings);
138 goto default_timings;
139 }
140 i++;
141 }
142 }
143
144 *nr_frequencies = arr_sz;
145
146 return timings;
147
148default_timings:
149 dev_warn(dev, "%s: using default timings\n", __func__);
150 *nr_frequencies = ARRAY_SIZE(lpddr2_jedec_timings);
151 return lpddr2_jedec_timings;
152}
153EXPORT_SYMBOL(of_get_ddr_timings);