int update_ddr_freq(int ddr_rate) { int i; unsigned int reg; if (!can_change_ddr_freq()) return -1; local_flush_tlb_all(); flush_cache_all(); iram_ddr_settings[0][0] = ddr_settings_size; if (ddr_rate == LP_APM_CLK) { if (mx50_ddr_type == MX50_LPDDR2) { for (i = 0; i < iram_ddr_settings[0][0]; i++) { iram_ddr_settings[i + 1][0] = lpddr2_24[i][0]; iram_ddr_settings[i + 1][1] = lpddr2_24[i][1]; } } else { for (i = 0; i < iram_ddr_settings[0][0]; i++) { iram_ddr_settings[i + 1][0] = mddr_24[i][0]; iram_ddr_settings[i + 1][1] = mddr_24[i][1]; } } } else { if (mx50_ddr_type == MX50_DDR2) { if (ddr_rate == ddr_low_rate) { for (i = 0; i < iram_ddr_settings[0][0]; i++) { iram_ddr_settings[i + 1][0] = ddr2_133[i][0]; iram_ddr_settings[i + 1][1] = ddr2_133[i][1]; } } if (ddr_rate == ddr_med_rate) { for (i = 0; i < iram_ddr_settings[0][0]; i++) { iram_ddr_settings[i + 1][0] = ddr2_160[i][0]; iram_ddr_settings[i + 1][1] = ddr2_160[i][1]; } } else { for (i = 0; i < iram_ddr_settings[0][0]; i++) { iram_ddr_settings[i + 1][0] = normal_databahn_settings[i][0]; iram_ddr_settings[i + 1][1] = normal_databahn_settings[i][1]; } } } else { for (i = 0; i < iram_ddr_settings[0][0]; i++) { iram_ddr_settings[i + 1][0] = normal_databahn_settings[i][0]; iram_ddr_settings[i + 1][1] = normal_databahn_settings[i][1]; } if (ddr_rate == ddr_med_rate) { /*Change the tref setting */ for (i = 0; i < iram_ddr_settings[0][0]; i++) { if (iram_ddr_settings[i + 1][0] == 0x40) { if (mx50_ddr_type == MX50_LPDDR2) /* LPDDR2 133MHz. */ iram_ddr_settings[i + 1][1] = 0x00050180; else /* mDDR 133MHz. */ iram_ddr_settings[i + 1][1] = 0x00050208; break; } } } } } /* Disable all masters from accessing the DDR, leave masters * on port 0 and 1 enabled. */ reg = __raw_readl(qosc_base + HW_QOS_DISABLE); reg |= QoS_DISABLE_MASTERS; __raw_writel(reg, qosc_base + HW_QOS_DISABLE_SET); udelay(100); /* Set the DDR to default freq. */ change_ddr_freq(ccm_base, databahn_base, ddr_rate, iram_ddr_settings); /* Enable all masters to access the DDR. */ __raw_writel(reg, qosc_base + HW_QOS_DISABLE_CLR); return 0; }
/* change the DDR frequency. */ int update_ddr_freq(int ddr_rate) { int i, j; unsigned int reg; bool dll_off = false; unsigned int online_cpus = 0; int cpu = 0; int me; if (!can_change_ddr_freq()) return -1; if (ddr_rate == curr_ddr_rate) return 0; printk(KERN_DEBUG "\nBus freq set to %d start...\n", ddr_rate); if (low_bus_freq_mode || audio_bus_freq_mode) dll_off = true; iram_ddr_settings[0][0] = ddr_settings_size; iram_iomux_settings[0][0] = iomux_settings_size; if (ddr_rate == ddr_med_rate && cpu_is_imx6q()) { for (i = 0; i < ARRAY_SIZE(ddr3_dll_mx6q); i++) { iram_ddr_settings[i + 1][0] = normal_mmdc_settings[i][0]; iram_ddr_settings[i + 1][1] = normal_mmdc_settings[i][1]; } for (j = 0, i = ARRAY_SIZE(ddr3_dll_mx6q); i < iram_ddr_settings[0][0]; j++, i++) { iram_ddr_settings[i + 1][0] = ddr3_400[j][0]; iram_ddr_settings[i + 1][1] = ddr3_400[j][1]; } } else if (ddr_rate == ddr_normal_rate) { for (i = 0; i < iram_ddr_settings[0][0]; i++) { iram_ddr_settings[i + 1][0] = normal_mmdc_settings[i][0]; iram_ddr_settings[i + 1][1] = normal_mmdc_settings[i][1]; } } /* ensure that all Cores are in WFE. */ local_irq_disable(); me = smp_processor_id(); *((char *)(&cpus_in_wfe) + (u8)me) = 0xff; wait_for_ddr_freq_update = true; for_each_online_cpu(cpu) { *((char *)(&online_cpus) + (u8)cpu) = 0xff; if (cpu != me) { /* set the interrupt to be pending in the GIC. */ reg = 1 << (irqs_used[cpu] % 32); writel_relaxed(reg, gic_dist_base + GIC_DIST_PENDING_SET + (irqs_used[cpu] / 32) * 4); } } while (cpus_in_wfe != online_cpus) udelay(5); /* Now we can change the DDR frequency. */ mx6_change_ddr_freq(ddr_rate, iram_ddr_settings, dll_off, iram_iomux_settings); curr_ddr_rate = ddr_rate; /* DDR frequency change is done . */ wait_for_ddr_freq_update = false; /* wake up all the cores. */ sev(); *((char *)(&cpus_in_wfe) + (u8)me) = 0; local_irq_enable(); printk(KERN_DEBUG "Bus freq set to %d done!\n", ddr_rate); return 0; }