diff options
-rw-r--r-- | Documentation/memory-devices/ti-emif.txt | 57 | ||||
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/memory/Kconfig | 22 | ||||
-rw-r--r-- | drivers/memory/Makefile | 5 | ||||
-rw-r--r-- | drivers/memory/emif.c | 289 | ||||
-rw-r--r-- | drivers/memory/emif.h | 7 | ||||
-rw-r--r-- | include/linux/platform_data/emif_plat.h | 128 |
8 files changed, 511 insertions, 0 deletions
diff --git a/Documentation/memory-devices/ti-emif.txt b/Documentation/memory-devices/ti-emif.txt new file mode 100644 index 000000000000..f4ad9a7d0f4b --- /dev/null +++ b/Documentation/memory-devices/ti-emif.txt | |||
@@ -0,0 +1,57 @@ | |||
1 | TI EMIF SDRAM Controller Driver: | ||
2 | |||
3 | Author | ||
4 | ======== | ||
5 | Aneesh V <aneesh@ti.com> | ||
6 | |||
7 | Location | ||
8 | ============ | ||
9 | driver/memory/emif.c | ||
10 | |||
11 | Supported SoCs: | ||
12 | =================== | ||
13 | TI OMAP44xx | ||
14 | TI OMAP54xx | ||
15 | |||
16 | Menuconfig option: | ||
17 | ========================== | ||
18 | Device Drivers | ||
19 | Memory devices | ||
20 | Texas Instruments EMIF driver | ||
21 | |||
22 | Description | ||
23 | =========== | ||
24 | This driver is for the EMIF module available in Texas Instruments | ||
25 | SoCs. EMIF is an SDRAM controller that, based on its revision, | ||
26 | supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. | ||
27 | This driver takes care of only LPDDR2 memories presently. The | ||
28 | functions of the driver includes re-configuring AC timing | ||
29 | parameters and other settings during frequency, voltage and | ||
30 | temperature changes | ||
31 | |||
32 | Platform Data (see include/linux/platform_data/emif_plat.h): | ||
33 | ===================================================================== | ||
34 | DDR device details and other board dependent and SoC dependent | ||
35 | information can be passed through platform data (struct emif_platform_data) | ||
36 | - DDR device details: 'struct ddr_device_info' | ||
37 | - Device AC timings: 'struct lpddr2_timings' and 'struct lpddr2_min_tck' | ||
38 | - Custom configurations: customizable policy options through | ||
39 | 'struct emif_custom_configs' | ||
40 | - IP revision | ||
41 | - PHY type | ||
42 | |||
43 | Interface to the external world: | ||
44 | ================================ | ||
45 | EMIF driver registers notifiers for voltage and frequency changes | ||
46 | affecting EMIF and takes appropriate actions when these are invoked. | ||
47 | - freq_pre_notify_handling() | ||
48 | - freq_post_notify_handling() | ||
49 | - volt_notify_handling() | ||
50 | |||
51 | Debugfs | ||
52 | ======== | ||
53 | The driver creates two debugfs entries per device. | ||
54 | - regcache_dump : dump of register values calculated and saved for all | ||
55 | frequencies used so far. | ||
56 | - mr4 : last polled value of MR4 register in the LPDDR2 device. MR4 | ||
57 | indicates the current temperature level of the device. | ||
diff --git a/drivers/Kconfig b/drivers/Kconfig index 0233ad979b7d..63b81826cb55 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -142,4 +142,6 @@ source "drivers/devfreq/Kconfig" | |||
142 | 142 | ||
143 | source "drivers/extcon/Kconfig" | 143 | source "drivers/extcon/Kconfig" |
144 | 144 | ||
145 | source "drivers/memory/Kconfig" | ||
146 | |||
145 | endmenu | 147 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index c41dfa92cd79..265b506a15be 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -135,3 +135,4 @@ obj-$(CONFIG_HYPERV) += hv/ | |||
135 | 135 | ||
136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ | 136 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ |
137 | obj-$(CONFIG_EXTCON) += extcon/ | 137 | obj-$(CONFIG_EXTCON) += extcon/ |
138 | obj-$(CONFIG_MEMORY) += memory/ | ||
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig new file mode 100644 index 000000000000..b08327cca0e5 --- /dev/null +++ b/drivers/memory/Kconfig | |||
@@ -0,0 +1,22 @@ | |||
1 | # | ||
2 | # Memory devices | ||
3 | # | ||
4 | |||
5 | menuconfig MEMORY | ||
6 | bool "Memory Controller drivers" | ||
7 | |||
8 | if MEMORY | ||
9 | |||
10 | config TI_EMIF | ||
11 | tristate "Texas Instruments EMIF driver" | ||
12 | select DDR | ||
13 | help | ||
14 | This driver is for the EMIF module available in Texas Instruments | ||
15 | SoCs. EMIF is an SDRAM controller that, based on its revision, | ||
16 | supports one or more of DDR2, DDR3, and LPDDR2 SDRAM protocols. | ||
17 | This driver takes care of only LPDDR2 memories presently. The | ||
18 | functions of the driver includes re-configuring AC timing | ||
19 | parameters and other settings during frequency, voltage and | ||
20 | temperature changes | ||
21 | |||
22 | endif | ||
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile new file mode 100644 index 000000000000..e27f80b28859 --- /dev/null +++ b/drivers/memory/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for memory devices | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_TI_EMIF) += emif.o | ||
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c new file mode 100644 index 000000000000..7486d7ef0826 --- /dev/null +++ b/drivers/memory/emif.c | |||
@@ -0,0 +1,289 @@ | |||
1 | /* | ||
2 | * EMIF driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Aneesh V <aneesh@ti.com> | ||
7 | * Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/reboot.h> | ||
15 | #include <linux/platform_data/emif_plat.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <memory/jedec_ddr.h> | ||
25 | #include "emif.h" | ||
26 | |||
27 | /** | ||
28 | * struct emif_data - Per device static data for driver's use | ||
29 | * @duplicate: Whether the DDR devices attached to this EMIF | ||
30 | * instance are exactly same as that on EMIF1. In | ||
31 | * this case we can save some memory and processing | ||
32 | * @temperature_level: Maximum temperature of LPDDR2 devices attached | ||
33 | * to this EMIF - read from MR4 register. If there | ||
34 | * are two devices attached to this EMIF, this | ||
35 | * value is the maximum of the two temperature | ||
36 | * levels. | ||
37 | * @node: node in the device list | ||
38 | * @base: base address of memory-mapped IO registers. | ||
39 | * @dev: device pointer. | ||
40 | * @plat_data: Pointer to saved platform data. | ||
41 | */ | ||
42 | struct emif_data { | ||
43 | u8 duplicate; | ||
44 | u8 temperature_level; | ||
45 | struct list_head node; | ||
46 | void __iomem *base; | ||
47 | struct device *dev; | ||
48 | struct emif_platform_data *plat_data; | ||
49 | }; | ||
50 | |||
51 | static struct emif_data *emif1; | ||
52 | static LIST_HEAD(device_list); | ||
53 | |||
54 | static void get_default_timings(struct emif_data *emif) | ||
55 | { | ||
56 | struct emif_platform_data *pd = emif->plat_data; | ||
57 | |||
58 | pd->timings = lpddr2_jedec_timings; | ||
59 | pd->timings_arr_size = ARRAY_SIZE(lpddr2_jedec_timings); | ||
60 | |||
61 | dev_warn(emif->dev, "%s: using default timings\n", __func__); | ||
62 | } | ||
63 | |||
64 | static int is_dev_data_valid(u32 type, u32 density, u32 io_width, u32 phy_type, | ||
65 | u32 ip_rev, struct device *dev) | ||
66 | { | ||
67 | int valid; | ||
68 | |||
69 | valid = (type == DDR_TYPE_LPDDR2_S4 || | ||
70 | type == DDR_TYPE_LPDDR2_S2) | ||
71 | && (density >= DDR_DENSITY_64Mb | ||
72 | && density <= DDR_DENSITY_8Gb) | ||
73 | && (io_width >= DDR_IO_WIDTH_8 | ||
74 | && io_width <= DDR_IO_WIDTH_32); | ||
75 | |||
76 | /* Combinations of EMIF and PHY revisions that we support today */ | ||
77 | switch (ip_rev) { | ||
78 | case EMIF_4D: | ||
79 | valid = valid && (phy_type == EMIF_PHY_TYPE_ATTILAPHY); | ||
80 | break; | ||
81 | case EMIF_4D5: | ||
82 | valid = valid && (phy_type == EMIF_PHY_TYPE_INTELLIPHY); | ||
83 | break; | ||
84 | default: | ||
85 | valid = 0; | ||
86 | } | ||
87 | |||
88 | if (!valid) | ||
89 | dev_err(dev, "%s: invalid DDR details\n", __func__); | ||
90 | return valid; | ||
91 | } | ||
92 | |||
93 | static int is_custom_config_valid(struct emif_custom_configs *cust_cfgs, | ||
94 | struct device *dev) | ||
95 | { | ||
96 | int valid = 1; | ||
97 | |||
98 | if ((cust_cfgs->mask & EMIF_CUSTOM_CONFIG_LPMODE) && | ||
99 | (cust_cfgs->lpmode != EMIF_LP_MODE_DISABLE)) | ||
100 | valid = cust_cfgs->lpmode_freq_threshold && | ||
101 | cust_cfgs->lpmode_timeout_performance && | ||
102 | cust_cfgs->lpmode_timeout_power; | ||
103 | |||
104 | if (cust_cfgs->mask & EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL) | ||
105 | valid = valid && cust_cfgs->temp_alert_poll_interval_ms; | ||
106 | |||
107 | if (!valid) | ||
108 | dev_warn(dev, "%s: invalid custom configs\n", __func__); | ||
109 | |||
110 | return valid; | ||
111 | } | ||
112 | |||
113 | static struct emif_data *__init_or_module get_device_details( | ||
114 | struct platform_device *pdev) | ||
115 | { | ||
116 | u32 size; | ||
117 | struct emif_data *emif = NULL; | ||
118 | struct ddr_device_info *dev_info; | ||
119 | struct emif_custom_configs *cust_cfgs; | ||
120 | struct emif_platform_data *pd; | ||
121 | struct device *dev; | ||
122 | void *temp; | ||
123 | |||
124 | pd = pdev->dev.platform_data; | ||
125 | dev = &pdev->dev; | ||
126 | |||
127 | if (!(pd && pd->device_info && is_dev_data_valid(pd->device_info->type, | ||
128 | pd->device_info->density, pd->device_info->io_width, | ||
129 | pd->phy_type, pd->ip_rev, dev))) { | ||
130 | dev_err(dev, "%s: invalid device data\n", __func__); | ||
131 | goto error; | ||
132 | } | ||
133 | |||
134 | emif = devm_kzalloc(dev, sizeof(*emif), GFP_KERNEL); | ||
135 | temp = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); | ||
136 | dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL); | ||
137 | |||
138 | if (!emif || !pd || !dev_info) { | ||
139 | dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__); | ||
140 | goto error; | ||
141 | } | ||
142 | |||
143 | memcpy(temp, pd, sizeof(*pd)); | ||
144 | pd = temp; | ||
145 | memcpy(dev_info, pd->device_info, sizeof(*dev_info)); | ||
146 | |||
147 | pd->device_info = dev_info; | ||
148 | emif->plat_data = pd; | ||
149 | emif->dev = dev; | ||
150 | emif->temperature_level = SDRAM_TEMP_NOMINAL; | ||
151 | |||
152 | /* | ||
153 | * For EMIF instances other than EMIF1 see if the devices connected | ||
154 | * are exactly same as on EMIF1(which is typically the case). If so, | ||
155 | * mark it as a duplicate of EMIF1 and skip copying timings data. | ||
156 | * This will save some memory and some computation later. | ||
157 | */ | ||
158 | emif->duplicate = emif1 && (memcmp(dev_info, | ||
159 | emif1->plat_data->device_info, | ||
160 | sizeof(struct ddr_device_info)) == 0); | ||
161 | |||
162 | if (emif->duplicate) { | ||
163 | pd->timings = NULL; | ||
164 | pd->min_tck = NULL; | ||
165 | goto out; | ||
166 | } else if (emif1) { | ||
167 | dev_warn(emif->dev, "%s: Non-symmetric DDR geometry\n", | ||
168 | __func__); | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Copy custom configs - ignore allocation error, if any, as | ||
173 | * custom_configs is not very critical | ||
174 | */ | ||
175 | cust_cfgs = pd->custom_configs; | ||
176 | if (cust_cfgs && is_custom_config_valid(cust_cfgs, dev)) { | ||
177 | temp = devm_kzalloc(dev, sizeof(*cust_cfgs), GFP_KERNEL); | ||
178 | if (temp) | ||
179 | memcpy(temp, cust_cfgs, sizeof(*cust_cfgs)); | ||
180 | else | ||
181 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
182 | __LINE__); | ||
183 | pd->custom_configs = temp; | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Copy timings and min-tck values from platform data. If it is not | ||
188 | * available or if memory allocation fails, use JEDEC defaults | ||
189 | */ | ||
190 | size = sizeof(struct lpddr2_timings) * pd->timings_arr_size; | ||
191 | if (pd->timings) { | ||
192 | temp = devm_kzalloc(dev, size, GFP_KERNEL); | ||
193 | if (temp) { | ||
194 | memcpy(temp, pd->timings, sizeof(*pd->timings)); | ||
195 | pd->timings = temp; | ||
196 | } else { | ||
197 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
198 | __LINE__); | ||
199 | get_default_timings(emif); | ||
200 | } | ||
201 | } else { | ||
202 | get_default_timings(emif); | ||
203 | } | ||
204 | |||
205 | if (pd->min_tck) { | ||
206 | temp = devm_kzalloc(dev, sizeof(*pd->min_tck), GFP_KERNEL); | ||
207 | if (temp) { | ||
208 | memcpy(temp, pd->min_tck, sizeof(*pd->min_tck)); | ||
209 | pd->min_tck = temp; | ||
210 | } else { | ||
211 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | ||
212 | __LINE__); | ||
213 | pd->min_tck = &lpddr2_jedec_min_tck; | ||
214 | } | ||
215 | } else { | ||
216 | pd->min_tck = &lpddr2_jedec_min_tck; | ||
217 | } | ||
218 | |||
219 | out: | ||
220 | return emif; | ||
221 | |||
222 | error: | ||
223 | return NULL; | ||
224 | } | ||
225 | |||
226 | static int __init_or_module emif_probe(struct platform_device *pdev) | ||
227 | { | ||
228 | struct emif_data *emif; | ||
229 | struct resource *res; | ||
230 | |||
231 | emif = get_device_details(pdev); | ||
232 | if (!emif) { | ||
233 | pr_err("%s: error getting device data\n", __func__); | ||
234 | goto error; | ||
235 | } | ||
236 | |||
237 | if (!emif1) | ||
238 | emif1 = emif; | ||
239 | |||
240 | list_add(&emif->node, &device_list); | ||
241 | |||
242 | /* Save pointers to each other in emif and device structures */ | ||
243 | emif->dev = &pdev->dev; | ||
244 | platform_set_drvdata(pdev, emif); | ||
245 | |||
246 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
247 | if (!res) { | ||
248 | dev_err(emif->dev, "%s: error getting memory resource\n", | ||
249 | __func__); | ||
250 | goto error; | ||
251 | } | ||
252 | |||
253 | emif->base = devm_request_and_ioremap(emif->dev, res); | ||
254 | if (!emif->base) { | ||
255 | dev_err(emif->dev, "%s: devm_request_and_ioremap() failed\n", | ||
256 | __func__); | ||
257 | goto error; | ||
258 | } | ||
259 | |||
260 | dev_info(&pdev->dev, "%s: device configured with addr = %p\n", | ||
261 | __func__, emif->base); | ||
262 | |||
263 | return 0; | ||
264 | error: | ||
265 | return -ENODEV; | ||
266 | } | ||
267 | |||
268 | static struct platform_driver emif_driver = { | ||
269 | .driver = { | ||
270 | .name = "emif", | ||
271 | }, | ||
272 | }; | ||
273 | |||
274 | static int __init_or_module emif_register(void) | ||
275 | { | ||
276 | return platform_driver_probe(&emif_driver, emif_probe); | ||
277 | } | ||
278 | |||
279 | static void __exit emif_unregister(void) | ||
280 | { | ||
281 | platform_driver_unregister(&emif_driver); | ||
282 | } | ||
283 | |||
284 | module_init(emif_register); | ||
285 | module_exit(emif_unregister); | ||
286 | MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver"); | ||
287 | MODULE_LICENSE("GPL"); | ||
288 | MODULE_ALIAS("platform:emif"); | ||
289 | MODULE_AUTHOR("Texas Instruments Inc"); | ||
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h index 44b97dfe95b4..692b2a864e7b 100644 --- a/drivers/memory/emif.h +++ b/drivers/memory/emif.h | |||
@@ -12,6 +12,13 @@ | |||
12 | #ifndef __EMIF_H | 12 | #ifndef __EMIF_H |
13 | #define __EMIF_H | 13 | #define __EMIF_H |
14 | 14 | ||
15 | /* | ||
16 | * Maximum number of different frequencies supported by EMIF driver | ||
17 | * Determines the number of entries in the pointer array for register | ||
18 | * cache | ||
19 | */ | ||
20 | #define EMIF_MAX_NUM_FREQUENCIES 6 | ||
21 | |||
15 | /* Registers offset */ | 22 | /* Registers offset */ |
16 | #define EMIF_MODULE_ID_AND_REVISION 0x0000 | 23 | #define EMIF_MODULE_ID_AND_REVISION 0x0000 |
17 | #define EMIF_STATUS 0x0004 | 24 | #define EMIF_STATUS 0x0004 |
diff --git a/include/linux/platform_data/emif_plat.h b/include/linux/platform_data/emif_plat.h new file mode 100644 index 000000000000..03378ca84061 --- /dev/null +++ b/include/linux/platform_data/emif_plat.h | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * Definitions for TI EMIF device platform data | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments, Inc. | ||
5 | * | ||
6 | * Aneesh V <aneesh@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef __EMIF_PLAT_H | ||
13 | #define __EMIF_PLAT_H | ||
14 | |||
15 | /* Low power modes - EMIF_PWR_MGMT_CTRL */ | ||
16 | #define EMIF_LP_MODE_DISABLE 0 | ||
17 | #define EMIF_LP_MODE_CLOCK_STOP 1 | ||
18 | #define EMIF_LP_MODE_SELF_REFRESH 2 | ||
19 | #define EMIF_LP_MODE_PWR_DN 4 | ||
20 | |||
21 | /* Hardware capabilities */ | ||
22 | #define EMIF_HW_CAPS_LL_INTERFACE 0x00000001 | ||
23 | |||
24 | /* | ||
25 | * EMIF IP Revisions | ||
26 | * EMIF4D - Used in OMAP4 | ||
27 | * EMIF4D5 - Used in OMAP5 | ||
28 | */ | ||
29 | #define EMIF_4D 1 | ||
30 | #define EMIF_4D5 2 | ||
31 | |||
32 | /* | ||
33 | * PHY types | ||
34 | * ATTILAPHY - Used in OMAP4 | ||
35 | * INTELLIPHY - Used in OMAP5 | ||
36 | */ | ||
37 | #define EMIF_PHY_TYPE_ATTILAPHY 1 | ||
38 | #define EMIF_PHY_TYPE_INTELLIPHY 2 | ||
39 | |||
40 | /* Custom config requests */ | ||
41 | #define EMIF_CUSTOM_CONFIG_LPMODE 0x00000001 | ||
42 | #define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL 0x00000002 | ||
43 | |||
44 | #ifndef __ASSEMBLY__ | ||
45 | /** | ||
46 | * struct ddr_device_info - All information about the DDR device except AC | ||
47 | * timing parameters | ||
48 | * @type: Device type (LPDDR2-S4, LPDDR2-S2 etc) | ||
49 | * @density: Device density | ||
50 | * @io_width: Bus width | ||
51 | * @cs1_used: Whether there is a DDR device attached to the second | ||
52 | * chip-select(CS1) of this EMIF instance | ||
53 | * @cal_resistors_per_cs: Whether there is one calibration resistor per | ||
54 | * chip-select or whether it's a single one for both | ||
55 | * @manufacturer: Manufacturer name string | ||
56 | */ | ||
57 | struct ddr_device_info { | ||
58 | u32 type; | ||
59 | u32 density; | ||
60 | u32 io_width; | ||
61 | u32 cs1_used; | ||
62 | u32 cal_resistors_per_cs; | ||
63 | char manufacturer[10]; | ||
64 | }; | ||
65 | |||
66 | /** | ||
67 | * struct emif_custom_configs - Custom configuration parameters/policies | ||
68 | * passed from the platform layer | ||
69 | * @mask: Mask to indicate which configs are requested | ||
70 | * @lpmode: LPMODE to be used in PWR_MGMT_CTRL register | ||
71 | * @lpmode_timeout_performance: Timeout before LPMODE entry when higher | ||
72 | * performance is desired at the cost of power (typically | ||
73 | * at higher OPPs) | ||
74 | * @lpmode_timeout_power: Timeout before LPMODE entry when better power | ||
75 | * savings is desired and performance is not important | ||
76 | * (typically at lower loads indicated by lower OPPs) | ||
77 | * @lpmode_freq_threshold: The DDR frequency threshold to identify between | ||
78 | * the above two cases: | ||
79 | * timeout = (freq >= lpmode_freq_threshold) ? | ||
80 | * lpmode_timeout_performance : | ||
81 | * lpmode_timeout_power; | ||
82 | * @temp_alert_poll_interval_ms: LPDDR2 MR4 polling interval at nominal | ||
83 | * temperature(in milliseconds). When temperature is high | ||
84 | * polling is done 4 times as frequently. | ||
85 | */ | ||
86 | struct emif_custom_configs { | ||
87 | u32 mask; | ||
88 | u32 lpmode; | ||
89 | u32 lpmode_timeout_performance; | ||
90 | u32 lpmode_timeout_power; | ||
91 | u32 lpmode_freq_threshold; | ||
92 | u32 temp_alert_poll_interval_ms; | ||
93 | }; | ||
94 | |||
95 | /** | ||
96 | * struct emif_platform_data - Platform data passed on EMIF platform | ||
97 | * device creation. Used by the driver. | ||
98 | * @hw_caps: Hw capabilities of the EMIF IP in the respective SoC | ||
99 | * @device_info: Device info structure containing information such | ||
100 | * as type, bus width, density etc | ||
101 | * @timings: Timings information from device datasheet passed | ||
102 | * as an array of 'struct lpddr2_timings'. Can be NULL | ||
103 | * if if default timings are ok | ||
104 | * @timings_arr_size: Size of the timings array. Depends on the number | ||
105 | * of different frequencies for which timings data | ||
106 | * is provided | ||
107 | * @min_tck: Minimum value of some timing parameters in terms | ||
108 | * of number of cycles. Can be NULL if default values | ||
109 | * are ok | ||
110 | * @custom_configs: Custom configurations requested by SoC or board | ||
111 | * code and the data for them. Can be NULL if default | ||
112 | * configurations done by the driver are ok. See | ||
113 | * documentation for 'struct emif_custom_configs' for | ||
114 | * more details | ||
115 | */ | ||
116 | struct emif_platform_data { | ||
117 | u32 hw_caps; | ||
118 | struct ddr_device_info *device_info; | ||
119 | const struct lpddr2_timings *timings; | ||
120 | u32 timings_arr_size; | ||
121 | const struct lpddr2_min_tck *min_tck; | ||
122 | struct emif_custom_configs *custom_configs; | ||
123 | u32 ip_rev; | ||
124 | u32 phy_type; | ||
125 | }; | ||
126 | #endif /* __ASSEMBLY__ */ | ||
127 | |||
128 | #endif /* __LINUX_EMIF_H */ | ||