2 * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
6 * The code contained herein is licensed under the GNU General Public
7 * License. You may obtain a copy of the GNU General Public License
8 * Version 2 or later at the following locations:
10 * http://www.opensource.org/licenses/gpl-license.html
11 * http://www.gnu.org/copyleft/gpl.html
15 * @file busfreq_ddr3.c
17 * @brief iMX6 DDR3 frequency change specific file.
21 #include <asm/cacheflush.h>
22 #include <asm/fncpy.h>
24 #include <asm/mach/map.h>
25 #include <asm/mach-types.h>
27 #include <linux/clk.h>
28 #include <linux/cpumask.h>
29 #include <linux/delay.h>
30 #include <linux/genalloc.h>
31 #include <linux/interrupt.h>
32 #include <linux/irqchip/arm-gic.h>
33 #include <linux/kernel.h>
34 #include <linux/mutex.h>
36 #include <linux/of_address.h>
37 #include <linux/of_device.h>
38 #include <linux/platform_device.h>
39 #include <linux/proc_fs.h>
40 #include <linux/sched.h>
41 #include <linux/smp.h>
46 static unsigned long (*iram_ddr_settings)[2];
47 static unsigned long (*normal_mmdc_settings)[2];
48 static unsigned long (*iram_iomux_settings)[2];
50 static void __iomem *mmdc_base;
51 static void __iomem *iomux_base;
52 static void __iomem *ccm_base;
53 static void __iomem *l2_base;
54 static void __iomem *gic_dist_base;
55 static u32 *irqs_used;
57 void (*mx6_change_ddr_freq)(u32 freq, void *ddr_settings,
58 bool dll_mode, void *iomux_offsets) = NULL;
60 extern unsigned int ddr_med_rate;
61 extern unsigned int ddr_normal_rate;
62 extern int low_bus_freq_mode;
63 extern int audio_bus_freq_mode;
64 extern void mx6_ddr3_freq_change(u32 freq, void *ddr_settings,
65 bool dll_mode, void *iomux_offsets);
67 static void *ddr_freq_change_iram_base;
68 static int ddr_settings_size;
69 static int iomux_settings_size;
70 static volatile unsigned int cpus_in_wfe;
71 static volatile bool wait_for_ddr_freq_update;
72 static int curr_ddr_rate;
74 #define MIN_DLL_ON_FREQ 333000000
75 #define MAX_DLL_OFF_FREQ 125000000
76 #define DDR_FREQ_CHANGE_SIZE 0x2000
78 unsigned long ddr3_dll_mx6q[][2] = {
88 unsigned long ddr3_calibration[][2] = {
99 unsigned long ddr3_dll_mx6dl[][2] = {
109 unsigned long iomux_offsets_mx6q[][2] = {
120 unsigned long iomux_offsets_mx6dl[][2] = {
131 unsigned long ddr3_400[][2] = {
134 {0x483c, 0x42570257},
135 {0x4840, 0x02400240},
137 {0x4848, 0x3A39333F},
142 int can_change_ddr_freq(void)
148 * each active core apart from the one changing
149 * the DDR frequency will execute this function.
150 * the rest of the cores have to remain in WFE
151 * state until the frequency is changed.
153 irqreturn_t wait_in_wfe_irq(int irq, void *dev_id)
155 u32 me = smp_processor_id();
157 *((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
159 while (wait_for_ddr_freq_update)
162 *((char *)(&cpus_in_wfe) + (u8)me) = 0;
167 /* change the DDR frequency. */
168 int update_ddr_freq(int ddr_rate)
172 bool dll_off = false;
173 unsigned int online_cpus = 0;
177 if (!can_change_ddr_freq())
180 if (ddr_rate == curr_ddr_rate)
183 printk(KERN_DEBUG "\nBus freq set to %d start...\n", ddr_rate);
185 if (low_bus_freq_mode || audio_bus_freq_mode)
188 iram_ddr_settings[0][0] = ddr_settings_size;
189 iram_iomux_settings[0][0] = iomux_settings_size;
190 if (ddr_rate == ddr_med_rate && cpu_is_imx6q()) {
191 for (i = 0; i < ARRAY_SIZE(ddr3_dll_mx6q); i++) {
192 iram_ddr_settings[i + 1][0] =
193 normal_mmdc_settings[i][0];
194 iram_ddr_settings[i + 1][1] =
195 normal_mmdc_settings[i][1];
197 for (j = 0, i = ARRAY_SIZE(ddr3_dll_mx6q);
198 i < iram_ddr_settings[0][0]; j++, i++) {
199 iram_ddr_settings[i + 1][0] =
201 iram_ddr_settings[i + 1][1] =
204 } else if (ddr_rate == ddr_normal_rate) {
205 for (i = 0; i < iram_ddr_settings[0][0]; i++) {
206 iram_ddr_settings[i + 1][0] =
207 normal_mmdc_settings[i][0];
208 iram_ddr_settings[i + 1][1] =
209 normal_mmdc_settings[i][1];
213 /* ensure that all Cores are in WFE. */
216 me = smp_processor_id();
218 *((char *)(&cpus_in_wfe) + (u8)me) = 0xff;
219 wait_for_ddr_freq_update = true;
220 for_each_online_cpu(cpu) {
221 *((char *)(&online_cpus) + (u8)cpu) = 0xff;
223 /* set the interrupt to be pending in the GIC. */
224 reg = 1 << (irqs_used[cpu] % 32);
225 writel_relaxed(reg, gic_dist_base + GIC_DIST_PENDING_SET
226 + (irqs_used[cpu] / 32) * 4);
229 while (cpus_in_wfe != online_cpus)
232 /* Now we can change the DDR frequency. */
233 mx6_change_ddr_freq(ddr_rate, iram_ddr_settings,
234 dll_off, iram_iomux_settings);
236 curr_ddr_rate = ddr_rate;
238 /* DDR frequency change is done . */
239 wait_for_ddr_freq_update = false;
241 /* wake up all the cores. */
244 *((char *)(&cpus_in_wfe) + (u8)me) = 0;
248 printk(KERN_DEBUG "Bus freq set to %d done!\n", ddr_rate);
253 int init_mmdc_settings(struct platform_device *busfreq_pdev)
255 struct device *dev = &busfreq_pdev->dev;
256 struct platform_device *ocram_dev;
257 unsigned int iram_paddr;
260 struct device_node *node;
261 struct gen_pool *iram_pool;
264 node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc-combine");
266 printk(KERN_ERR "failed to find imx6q-mmdc device tree data!\n");
269 mmdc_base = of_iomap(node, 0);
270 WARN(!mmdc_base, "unable to map mmdc registers\n");
274 node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-iomuxc");
276 node = of_find_compatible_node(NULL, NULL,
277 "fsl,imx6dl-iomuxc");
279 printk(KERN_ERR "failed to find imx6q-iomux device tree data!\n");
282 iomux_base = of_iomap(node, 0);
283 WARN(!iomux_base, "unable to map iomux registers\n");
285 node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm");
287 printk(KERN_ERR "failed to find imx6q-ccm device tree data!\n");
290 ccm_base = of_iomap(node, 0);
291 WARN(!mmdc_base, "unable to map mmdc registers\n");
293 node = of_find_compatible_node(NULL, NULL, "arm,pl310-cache");
295 printk(KERN_ERR "failed to find imx6q-pl310-cache device tree data!\n");
298 l2_base = of_iomap(node, 0);
299 WARN(!mmdc_base, "unable to map mmdc registers\n");
302 node = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
304 printk(KERN_ERR "failed to find imx6q-a9-gic device tree data!\n");
307 gic_dist_base = of_iomap(node, 0);
308 WARN(!gic_dist_base, "unable to map gic dist registers\n");
311 ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6q) +
312 ARRAY_SIZE(ddr3_calibration);
314 ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6dl) +
315 ARRAY_SIZE(ddr3_calibration);
317 normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL);
318 if (cpu_is_imx6q()) {
319 memcpy(normal_mmdc_settings, ddr3_dll_mx6q,
320 sizeof(ddr3_dll_mx6q));
321 memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6q)),
322 ddr3_calibration, sizeof(ddr3_calibration));
324 if (cpu_is_imx6dl()) {
325 memcpy(normal_mmdc_settings, ddr3_dll_mx6dl,
326 sizeof(ddr3_dll_mx6dl));
327 memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6dl)),
328 ddr3_calibration, sizeof(ddr3_calibration));
330 /* store the original DDR settings at boot. */
331 for (i = 0; i < ddr_settings_size; i++) {
333 * writes via command mode register cannot be read back.
334 * hence hardcode them in the initial static array.
335 * this may require modification on a per customer basis.
337 if (normal_mmdc_settings[i][0] != 0x1C)
338 normal_mmdc_settings[i][1] =
339 readl_relaxed(mmdc_base
340 + normal_mmdc_settings[i][0]);
343 irqs_used = devm_kzalloc(dev, sizeof(u32) * num_present_cpus(),
346 for_each_present_cpu(cpu) {
350 * set up a reserved interrupt to get all
351 * the active cores into a WFE state
352 * before changing the DDR frequency.
354 irq = platform_get_irq(busfreq_pdev, cpu);
355 err = request_irq(irq, wait_in_wfe_irq,
356 IRQF_PERCPU, "mmdc_1", NULL);
359 "Busfreq:request_irq failed %d, err = %d\n",
363 err = irq_set_affinity(irq, cpumask_of(cpu));
366 "Busfreq: Cannot set irq affinity irq=%d,\n",
370 irqs_used[cpu] = irq;
374 node = of_find_compatible_node(NULL, NULL, "mmio-sram");
376 dev_err(dev, "%s: failed to find ocram node\n",
381 ocram_dev = of_find_device_by_node(node);
383 dev_err(dev, "failed to find ocram device!\n");
387 iram_pool = dev_get_gen_pool(&ocram_dev->dev);
389 dev_err(dev, "iram pool unavailable!\n");
393 iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q);
394 iram_addr = (void *)gen_pool_alloc(iram_pool,
395 (iomux_settings_size * 8) + 8);
396 iram_iomux_settings = iram_addr;
397 if (!iram_iomux_settings) {
398 dev_err(dev, "unable to alloc iram for IOMUX settings!\n");
403 * Allocate extra space to store the number of entries in the
404 * ddr_settings plus 4 extra regsiter information that needs
405 * to be passed to the frequency change code.
406 * sizeof(iram_ddr_settings) = sizeof(ddr_settings) +
407 * entries in ddr_settings + 16.
408 * The last 4 enties store the addresses of the registers:
414 iram_addr = (void *)gen_pool_alloc(iram_pool,
415 (ddr_settings_size * 8) + 8 + 32);
416 iram_ddr_settings = iram_addr;
417 if (!iram_ddr_settings) {
418 dev_err(dev, "unable to alloc iram for ddr settings!\n");
422 i = ddr_settings_size + 1;
423 iram_ddr_settings[i][0] = (unsigned long)mmdc_base;
424 iram_ddr_settings[i+1][0] = (unsigned long)ccm_base;
425 iram_ddr_settings[i+2][0] = (unsigned long)iomux_base;
426 iram_ddr_settings[i+3][0] = (unsigned long)l2_base;
428 if (cpu_is_imx6q()) {
429 /* store the IOMUX settings at boot. */
430 for (i = 0; i < iomux_settings_size; i++) {
431 iomux_offsets_mx6q[i][1] =
432 readl_relaxed(iomux_base +
433 iomux_offsets_mx6q[i][0]);
434 iram_iomux_settings[i+1][0] = iomux_offsets_mx6q[i][0];
435 iram_iomux_settings[i+1][1] = iomux_offsets_mx6q[i][1];
439 if (cpu_is_imx6dl()) {
440 for (i = 0; i < iomux_settings_size; i++) {
441 iomux_offsets_mx6dl[i][1] =
442 readl_relaxed(iomux_base +
443 iomux_offsets_mx6dl[i][0]);
444 iram_iomux_settings[i+1][0] = iomux_offsets_mx6dl[i][0];
445 iram_iomux_settings[i+1][1] = iomux_offsets_mx6dl[i][1];
449 ddr_freq_change_iram_base = (void *)gen_pool_alloc(iram_pool,
450 DDR_FREQ_CHANGE_SIZE);
451 if (!ddr_freq_change_iram_base) {
452 dev_err(dev, "Cannot alloc iram for ddr freq change code!\n");
456 iram_paddr = gen_pool_virt_to_phys(iram_pool,
457 (unsigned long)ddr_freq_change_iram_base);
459 * need to remap the area here since we want
460 * the memory region to be executable.
462 ddr_freq_change_iram_base = __arm_ioremap(iram_paddr,
463 DDR_FREQ_CHANGE_SIZE,
464 MT_MEMORY_RWX_NONCACHED);
465 mx6_change_ddr_freq = (void *)fncpy(ddr_freq_change_iram_base,
466 &mx6_ddr3_freq_change, DDR_FREQ_CHANGE_SIZE);
468 curr_ddr_rate = ddr_normal_rate;