aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/busfreq_opp_5250.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-exynos/busfreq_opp_5250.c')
-rw-r--r--arch/arm/mach-exynos/busfreq_opp_5250.c892
1 files changed, 0 insertions, 892 deletions
diff --git a/arch/arm/mach-exynos/busfreq_opp_5250.c b/arch/arm/mach-exynos/busfreq_opp_5250.c
deleted file mode 100644
index bcedb46..0000000
--- a/arch/arm/mach-exynos/busfreq_opp_5250.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/* linux/arch/arm/mach-exynos/busfreq_opp_5250.c
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * EXYNOS5 - BUS clock frequency scaling support with OPP
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/regulator/consumer.h>
-#include <linux/sysfs.h>
-#include <linux/platform_device.h>
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/cpu.h>
-#include <linux/ktime.h>
-#include <linux/tick.h>
-#include <linux/kernel_stat.h>
-#include <linux/reboot.h>
-#include <linux/slab.h>
-#include <linux/opp.h>
-#include <linux/clk.h>
-#include <mach/busfreq_exynos5.h>
-
-#include <asm/mach-types.h>
-
-#include <mach/ppmu.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/gpio.h>
-#include <mach/regs-mem.h>
-#include <mach/dev.h>
-#include <mach/asv.h>
-#include <mach/regs-pmu-5250.h>
-
-#include <plat/map-s5p.h>
-#include <plat/gpio-cfg.h>
-#include <plat/cpu.h>
-#include <plat/clock.h>
-
-#undef BUSFREQ_PROFILE_DEBUG
-
-#define IDLE_THRESHOLD 4
-#define MIF_R1_THRESHOLD 20
-#define MIF_MAX_THRESHOLD 20
-#define INT_MAX_THRESHOLD 20
-#define INT_RIGHT0_THRESHOLD 25
-#define INT_VIDEOPLAY_LIMIT_FREQ 200000UL
-#define INT_RBB 6 /* +300mV */
-
-static struct device busfreq_for_int;
-
-/* To save/restore DREX2_PAUSE_CTRL register */
-static unsigned int drex2_pause_ctrl;
-
-static struct busfreq_table exynos5_busfreq_table_for800[] = {
- {LV_0, 800000, 1000000, 0, 0, 0},
- {LV_1, 400000, 1000000, 0, 0, 0},
- {LV_2, 160000, 1000000, 0, 0, 0},
-};
-
-static struct busfreq_table exynos5_busfreq_table_for667[] = {
- {LV_0, 667000, 1000000, 0, 0, 0},
- {LV_1, 334000, 1000000, 0, 0, 0},
- {LV_2, 111000, 1000000, 0, 0, 0},
-};
-
-static struct busfreq_table exynos5_busfreq_table_for533[] = {
- {LV_0, 533000, 1000000, 0, 0, 0},
- {LV_1, 267000, 1000000, 0, 0, 0},
- {LV_2, 107000, 1000000, 0, 0, 0},
-};
-
-static struct busfreq_table exynos5_busfreq_table_for400[] = {
- {LV_0, 400000, 1000000, 0, 0, 0},
- {LV_1, 267000, 1000000, 0, 0, 0},
- {LV_2, 100000, 1000000, 0, 0, 0},
-};
-#define ASV_GROUP 10
-static unsigned int asv_group_index;
-
-static unsigned int exynos5_mif_volt_for800[ASV_GROUP+1][LV_MIF_END] = {
- /* L0 L1 L2 */
- { 0, 0, 0}, /* ASV0 */
- {1200000, 1000000, 950000}, /* ASV1 */
- {1200000, 1000000, 900000}, /* ASV2 */
- {1200000, 1050000, 950000}, /* ASV3 */
- {1150000, 1000000, 900000}, /* ASV4 */
- {1150000, 1050000, 950000}, /* ASV5 */
- {1150000, 1050000, 950000}, /* ASV6 */
- {1100000, 1000000, 900000}, /* ASV7 */
- {1100000, 1000000, 900000}, /* ASV8 */
- {1100000, 1000000, 900000}, /* ASV9 */
- {1100000, 1000000, 900000}, /* ASV10 */
-};
-
-static unsigned int exynos5_mif_volt_for667[ASV_GROUP+1][LV_MIF_END] = {
- /* L0 L1 L2 */
- { 0, 0, 0}, /* ASV0 */
- {1100000, 1000000, 950000}, /* ASV1 */
- {1050000, 1000000, 950000}, /* ASV2 */
- {1050000, 1050000, 950000}, /* ASV3 */
- {1050000, 1000000, 950000}, /* ASV4 */
- {1050000, 1050000, 1000000}, /* ASV5 */
- {1050000, 1050000, 950000}, /* ASV6 */
- {1050000, 1000000, 900000}, /* ASV7 */
- {1050000, 1000000, 900000}, /* ASV8 */
- {1050000, 1000000, 900000}, /* ASV9 */
- {1050000, 1000000, 900000}, /* ASV10 */
-};
-
-static unsigned int exynos5_mif_volt_for533[ASV_GROUP+1][LV_MIF_END] = {
- /* L0 L1 L2 */
- { 0, 0, 0}, /* ASV0 */
- {1050000, 1000000, 950000}, /* ASV1 */
- {1000000, 950000, 950000}, /* ASV2 */
- {1050000, 1000000, 950000}, /* ASV3 */
- {1000000, 950000, 950000}, /* ASV4 */
- {1050000, 1000000, 1000000}, /* ASV5 */
- {1050000, 950000, 950000}, /* ASV6 */
- {1000000, 950000, 900000}, /* ASV7 */
- {1000000, 950000, 900000}, /* ASV8 */
- {1000000, 950000, 900000}, /* ASV9 */
- {1000000, 950000, 900000}, /* ASV10 */
-};
-
-static unsigned int exynos5_mif_volt_for400[ASV_GROUP+1][LV_MIF_END] = {
- /* L0 L1 L2 */
- { 0, 0, 0}, /* ASV0 */
- {1000000, 1000000, 950000}, /* ASV1 */
- {1000000, 950000, 900000}, /* ASV2 */
- {1050000, 1000000, 950000}, /* ASV3 */
- {1000000, 950000, 900000}, /* ASV4 */
- {1050000, 1000000, 950000}, /* ASV5 */
- {1050000, 950000, 950000}, /* ASV6 */
- {1000000, 950000, 900000}, /* ASV7 */
- {1000000, 950000, 900000}, /* ASV8 */
- {1000000, 950000, 900000}, /* ASV9 */
- {1000000, 950000, 900000}, /* ASV10 */
-};
-
-static struct busfreq_table *exynos5_busfreq_table_mif;
-
-static unsigned int (*exynos5_mif_volt)[LV_MIF_END];
-
-static struct busfreq_table exynos5_busfreq_table_int[] = {
- {LV_0, 267000, 1000000, 0, 0, 0},
- {LV_1, 200000, 1000000, 0, 0, 0},
- {LV_2, 160000, 1000000, 0, 0, 0},
- {LV_3, 133000, 1000000, 0, 0, 0},
-};
-
-static unsigned int exynos5_int_volt[ASV_GROUP+1][LV_INT_END] = {
- /* L0 L1 L2 L3 */
- { 0, 0, 0, 0}, /* ASV0 */
- {1025000, 987500, 975000, 950000}, /* ASV1 */
- {1012500, 975000, 962500, 937500}, /* ASV2 */
- {1012500, 987500, 975000, 950000}, /* ASV3 */
- {1000000, 975000, 962500, 937500}, /* ASV4 */
- {1012500, 987500, 975000, 950000}, /* ASV5 */
- {1000000, 975000, 962500, 937500}, /* ASV6 */
- { 987500, 962500, 950000, 925000}, /* ASV7 */
- { 975000, 950000, 937500, 912500}, /* ASV8 */
- { 962500, 937500, 925000, 900000}, /* ASV9 */
- { 962500, 937500, 925000, 900000}, /* ASV10 */
-};
-
-
-/* For CMU_LEX */
-static unsigned int clkdiv_lex[LV_INT_END][2] = {
- /*
- * Clock divider value for following
- * { DIVATCLK_LEX, DIVPCLK_LEX }
- */
-
- /* ATCLK_LEX L0 : 200MHz */
- {0, 1},
-
- /* ATCLK_LEX L1 : 166MHz */
- {0, 1},
-
- /* ATCLK_LEX L2 : 133MHz */
- {0, 1},
-
- /* ATCLK_LEX L3 : 114MHz */
- {0, 1},
-};
-
-/* For CMU_R0X */
-static unsigned int clkdiv_r0x[LV_INT_END][1] = {
- /*
- * Clock divider value for following
- * { DIVPCLK_R0X }
- */
-
- /* ACLK_PR0X L0 : 133MHz */
- {1},
-
- /* ACLK_DR0X L1 : 100MHz */
- {1},
-
- /* ACLK_PR0X L2 : 80MHz */
- {1},
-
- /* ACLK_PR0X L3 : 67MHz */
- {1},
-};
-
-/* For CMU_R1X */
-static unsigned int clkdiv_r1x[LV_INT_END][1] = {
- /*
- * Clock divider value for following
- * { DIVPCLK_R1X }
- */
-
- /* ACLK_PR1X L0 : 133MHz */
- {1},
-
- /* ACLK_DR1X L1 : 100MHz */
- {1},
-
- /* ACLK_PR1X L2 : 80MHz */
- {1},
-
- /* ACLK_PR1X L3 : 67MHz */
- {1},
-};
-
-/* For CMU_TOP */
-static unsigned int clkdiv_top[LV_INT_END][10] = {
- /*
- * Clock divider value for following
- * { DIVACLK400_ISP, DIVACLK400_IOP, DIVACLK266, DIVACLK_200, DIVACLK_66_PRE,
- DIVACLK_66, DIVACLK_333, DIVACLK_166, DIVACLK_300_DISP1, DIVACLK300_GSCL }
- */
-
- /* ACLK_400_ISP L0 : 400MHz */
- {1, 1, 2, 3, 1, 5, 0, 1, 2, 2},
-
- /* ACLK_400_ISP L1 : 267MHz */
- {2, 3, 3, 4, 1, 5, 1, 2, 2, 2},
-
- /* ACLK_400_ISP L2 : 200MHz */
- {3, 3, 4, 4, 1, 5, 2, 3, 2, 2},
-
- /* ACLK_400_ISP L3 : 160MHz */
- {4, 4, 5, 5, 1, 5, 2, 3, 5, 5},
-};
-
-/* For CMU_CDREX */
-static unsigned int clkdiv_cdrex_for800[LV_MIF_END][9] = {
- /*
- * Clock divider value for following
- * { DIVMCLK_DPHY, DIVMCLK_CDREX2, DIVACLK_CDREX, DIVMCLK_CDREX,
- DIVPCLK_CDREX, DIVC2C, DIVC2C_ACLK, DIVMCLK_EFPHY, DIVACLK_EFCON }
- */
-
- /* MCLK_CDREX L0: 800MHz */
- {0, 0, 1, 0, 5, 1, 1, 4, 1},
-
- /* MCLK_CDREX L1: 400MHz */
- {0, 1, 1, 1, 3, 2, 1, 5, 1},
-
- /* MCLK_CDREX L2: 100MHz */
- {0, 4, 1, 1, 7, 7, 1, 15, 1},
-};
-
-static unsigned int clkdiv_cdrex_for667[LV_MIF_END][9] = {
- /*
- * Clock divider value for following
- * { DIVMCLK_DPHY, DIVMCLK_CDREX2, DIVACLK_CDREX, DIVMCLK_CDREX,
- DIVPCLK_CDREX, DIVC2C, DIVC2C_ACLK, DIVMCLK_EFPHY, DIVACLK_EFCON }
- */
-
- /* MCLK_CDREX L0: 667MHz */
- {0, 0, 1, 0, 4, 1, 1, 4, 1},
-
- /* MCLK_CDREX L1: 334MHz */
- {0, 1, 1, 1, 4, 2, 1, 5, 1},
-
- /* MCLK_CDREX L2: 111MHz */
- {0, 5, 1, 4, 4, 5, 1, 8, 1},
-};
-
-static unsigned int clkdiv_cdrex_for533[LV_MIF_END][9] = {
- /*
- * Clock divider value for following
- * { DIVMCLK_DPHY, DIVMCLK_CDREX2, DIVACLK_CDREX, DIVMCLK_CDREX,
- DIVPCLK_CDREX, DIVC2C, DIVC2C_ACLK, DIVMCLK_EFPHY, DIVACLK_EFCON }
- */
-
- /* MCLK_CDREX L0: 533MHz */
- {0, 0, 1, 0, 3, 1, 1, 4, 1},
-
- /* MCLK_CDREX L1: 267MHz */
- {0, 1, 1, 1, 3, 2, 1, 5, 1},
-
- /* MCLK_CDREX L2: 107MHz */
- {0, 4, 1, 4, 3, 5, 1, 8, 1},
-};
-
-static unsigned int __maybe_unused clkdiv_cdrex_for400[LV_MIF_END][9] = {
- /*
- * Clock divider value for following
- * { DIVMCLK_DPHY, DIVMCLK_CDREX2, DIVACLK_CDREX, DIVMCLK_CDREX,
- DIVPCLK_CDREX, DIVC2C, DIVC2C_ACLK, DIVMCLK_EFPHY, DIVACLK_EFCON }
- */
-
- /* MCLK_CDREX L0: 400MHz */
- {1, 1, 1, 0, 5, 1, 1, 4, 1},
-
- /* MCLK_CDREX L1: 267MHz */
- {1, 2, 1, 2, 2, 2, 1, 5, 1},
-
- /* MCLK_CDREX L2: 100MHz */
- {1, 7, 1, 2, 7, 7, 1, 15, 1},
-};
-
-static unsigned int (*clkdiv_cdrex)[9];
-
-static void exynos5250_set_bus_volt(void)
-{
- unsigned int i;
-
- if (soc_is_exynos5250() && samsung_rev() < EXYNOS5250_REV_1_0)
- asv_group_index = 0;
- else
- asv_group_index = exynos_result_of_asv;
-
- if (asv_group_index == 0xff)
- asv_group_index = 0;
-
- printk(KERN_INFO "DVFS : VDD_INT Voltage table set with %d Group\n", asv_group_index);
- printk(KERN_INFO "DVFS : VDD_INT Voltage of L0 level is %d \n", exynos5_mif_volt[asv_group_index][0]);
-
- for (i = LV_0; i < LV_MIF_END; i++)
- exynos5_busfreq_table_mif[i].volt =
- exynos5_mif_volt[asv_group_index][i];
-
- for (i = LV_0; i < LV_INT_END; i++)
- exynos5_busfreq_table_int[i].volt =
- exynos5_int_volt[asv_group_index][i];
- return;
-}
-
-static void exynos5250_target_for_mif(struct busfreq_data *data, int div_index)
-{
- unsigned int tmp;
-
- /* Change Divider - CDREX */
- tmp = data->cdrex_divtable[div_index];
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_CDREX);
-
- if (samsung_rev() < EXYNOS5250_REV_1_0) {
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_CDREX);
- } while (tmp & 0x11111111);
- } else {
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_CDREX);
- } while (tmp & 0x11110011); \
- }
-
- if (samsung_rev() < EXYNOS5250_REV_1_0) {
- tmp = data->cdrex2_divtable[div_index];
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_CDREX2);
-
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_CDREX2);
- } while (tmp & 0x1);
- }
-}
-
-static void exynos5250_target_for_int(struct busfreq_data *data, int div_index)
-{
- unsigned int tmp;
- unsigned int tmp2;
-
- /* Change Divider - TOP */
- tmp = __raw_readl(EXYNOS5_CLKDIV_TOP0);
-
- tmp &= ~(EXYNOS5_CLKDIV_TOP0_ACLK266_MASK |
- EXYNOS5_CLKDIV_TOP0_ACLK200_MASK |
- EXYNOS5_CLKDIV_TOP0_ACLK66_MASK |
- EXYNOS5_CLKDIV_TOP0_ACLK333_MASK |
- EXYNOS5_CLKDIV_TOP0_ACLK166_MASK |
- EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_MASK);
-
- tmp |= ((clkdiv_top[div_index][2] << EXYNOS5_CLKDIV_TOP0_ACLK266_SHIFT) |
- (clkdiv_top[div_index][3] << EXYNOS5_CLKDIV_TOP0_ACLK200_SHIFT) |
- (clkdiv_top[div_index][5] << EXYNOS5_CLKDIV_TOP0_ACLK66_SHIFT) |
- (clkdiv_top[div_index][6] << EXYNOS5_CLKDIV_TOP0_ACLK333_SHIFT) |
- (clkdiv_top[div_index][7] << EXYNOS5_CLKDIV_TOP0_ACLK166_SHIFT) |
- (clkdiv_top[div_index][8] << EXYNOS5_CLKDIV_TOP0_ACLK300_DISP1_SHIFT));
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_TOP0);
-
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_TOP0);
- } while (tmp & 0x151101);
-
- tmp = __raw_readl(EXYNOS5_CLKDIV_TOP1);
-
- tmp &= ~(EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_MASK |
- EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_MASK |
- EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_MASK |
- EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_MASK);
-
- tmp |= ((clkdiv_top[div_index][0] << EXYNOS5_CLKDIV_TOP1_ACLK400_ISP_SHIFT) |
- (clkdiv_top[div_index][1] << EXYNOS5_CLKDIV_TOP1_ACLK400_IOP_SHIFT) |
- (clkdiv_top[div_index][4] << EXYNOS5_CLKDIV_TOP1_ACLK66_PRE_SHIFT) |
- (clkdiv_top[div_index][9] << EXYNOS5_CLKDIV_TOP1_ACLK300_GSCL_SHIFT));
-
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_TOP1);
-
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_TOP1);
- tmp2 = __raw_readl(EXYNOS5_CLKDIV_STAT_TOP0);
- } while ((tmp & 0x1110000) && (tmp2 & 0x80000));
-
- /* Change Divider - LEX */
- tmp = data->lex_divtable[div_index];
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_LEX);
-
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_LEX);
- } while (tmp & 0x110);
-
- /* Change Divider - R0X */
- tmp = __raw_readl(EXYNOS5_CLKDIV_R0X);
-
- tmp &= ~EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK;
-
- tmp |= (clkdiv_r0x[div_index][0] << EXYNOS5_CLKDIV_R0X_PCLK_R0X_SHIFT);
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_R0X);
-
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_R0X);
- } while (tmp & 0x10);
-
- /* Change Divider - R1X */
- tmp = data->r1x_divtable[div_index];
-
- __raw_writel(tmp, EXYNOS5_CLKDIV_R1X);
-
- do {
- tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_R1X);
- } while (tmp & 0x10);
-}
-
-static void exynos5250_target(struct busfreq_data *data, enum ppmu_type type,
- int index)
-{
- if (type == PPMU_MIF)
- exynos5250_target_for_mif(data, index);
- else
- exynos5250_target_for_int(data, index);
-}
-
-static int exynos5250_get_table_index(unsigned long freq, enum ppmu_type type)
-{
- int index;
-
- if (type == PPMU_MIF) {
- for (index = LV_0; index < LV_MIF_END; index++)
- if (freq == exynos5_busfreq_table_mif[index].mem_clk)
- return index;
- } else {
- for (index = LV_0; index < LV_INT_END; index++)
- if (freq == exynos5_busfreq_table_int[index].mem_clk)
- return index;
- }
- return -EINVAL;
-}
-
-static void exynos5250_suspend(void)
-{
- /* Nothing to do */
-}
-
-static void exynos5250_resume(void)
-{
- __raw_writel(drex2_pause_ctrl, EXYNOS5_DREX2_PAUSE);
-}
-
-static void exynos5250_monitor(struct busfreq_data *data,
- struct opp **mif_opp, struct opp **int_opp)
-{
- int i;
- unsigned int cpu_load_average = 0;
- unsigned int ddr_c_load_average = 0;
- unsigned int ddr_l_load_average = 0;
- unsigned int ddr_r1_load_average = 0;
- unsigned int right0_load_average = 0;
- unsigned int ddr_load_average;
- unsigned long cpufreq = 0;
- unsigned long freq_int_right0 = 0;
- unsigned long lockfreq[PPMU_TYPE_END];
- unsigned long freq[PPMU_TYPE_END];
- unsigned long cpu_load;
- unsigned long ddr_load=0;
- unsigned long ddr_load_int=0;
- unsigned long ddr_c_load;
- unsigned long ddr_r1_load;
- unsigned long ddr_l_load;
- unsigned long right0_load;
- struct opp *opp[PPMU_TYPE_END];
- unsigned long newfreq[PPMU_TYPE_END];
-
- ppmu_update(data->dev[PPMU_MIF], 3);
-
- /* Convert from base xxx to base maxfreq */
- cpu_load = div64_u64(ppmu_load[PPMU_CPU] * data->curr_freq[PPMU_MIF], data->max_freq[PPMU_MIF]);
- ddr_c_load = div64_u64(ppmu_load[PPMU_DDR_C] * data->curr_freq[PPMU_MIF], data->max_freq[PPMU_MIF]);
- ddr_r1_load = div64_u64(ppmu_load[PPMU_DDR_R1] * data->curr_freq[PPMU_MIF], data->max_freq[PPMU_MIF]);
- ddr_l_load = div64_u64(ppmu_load[PPMU_DDR_L] * data->curr_freq[PPMU_MIF], data->max_freq[PPMU_MIF]);
- right0_load = div64_u64(ppmu_load[PPMU_RIGHT0_BUS] * data->curr_freq[PPMU_INT], data->max_freq[PPMU_INT]);
-
- data->load_history[PPMU_CPU][data->index] = cpu_load;
- data->load_history[PPMU_DDR_C][data->index] = ddr_c_load;
- data->load_history[PPMU_DDR_R1][data->index] = ddr_r1_load;
- data->load_history[PPMU_DDR_L][data->index] = ddr_l_load;
- data->load_history[PPMU_RIGHT0_BUS][data->index++] = right0_load;
-
- if (data->index >= LOAD_HISTORY_SIZE)
- data->index = 0;
-
- for (i = 0; i < LOAD_HISTORY_SIZE; i++) {
- cpu_load_average += data->load_history[PPMU_CPU][i];
- ddr_c_load_average += data->load_history[PPMU_DDR_C][i];
- ddr_r1_load_average += data->load_history[PPMU_DDR_R1][i];
- ddr_l_load_average += data->load_history[PPMU_DDR_L][i];
- right0_load_average += data->load_history[PPMU_RIGHT0_BUS][i];
- }
-
- /* Calculate average Load */
- cpu_load_average /= LOAD_HISTORY_SIZE;
- ddr_c_load_average /= LOAD_HISTORY_SIZE;
- ddr_r1_load_average /= LOAD_HISTORY_SIZE;
- ddr_l_load_average /= LOAD_HISTORY_SIZE;
- right0_load_average /= LOAD_HISTORY_SIZE;
-
- if (ddr_c_load >= ddr_l_load) {
- ddr_load = ddr_c_load;
- ddr_load_average = ddr_c_load_average;
- } else {
- ddr_load = ddr_l_load;
- ddr_load_average = ddr_l_load_average;
- }
-
- ddr_load_int = ddr_load;
-
- //Calculate MIF/INT frequency level
- if (ddr_r1_load >= MIF_R1_THRESHOLD) {
- freq[PPMU_MIF] = data->max_freq[PPMU_MIF];
- if (right0_load >= INT_RIGHT0_THRESHOLD) {
- freq[PPMU_INT] = data->max_freq[PPMU_INT];
- goto go_max;
- } else {
- freq_int_right0 = div64_u64(data->max_freq[PPMU_INT] * right0_load, INT_RIGHT0_THRESHOLD);
- }
- } else {
- // Caculate next MIF frequency
- if (ddr_load >= MIF_MAX_THRESHOLD) {
- freq[PPMU_MIF] = data->max_freq[PPMU_MIF];
- } else if ( ddr_load < IDLE_THRESHOLD) {
- if (ddr_load_average < IDLE_THRESHOLD)
- freq[PPMU_MIF] = step_down(data, PPMU_MIF, 1);
- else
- freq[PPMU_MIF] = data->curr_freq[PPMU_MIF];
- } else {
- if (ddr_load < ddr_load_average) {
- ddr_load = ddr_load_average;
- if (ddr_load >= MIF_MAX_THRESHOLD)
- ddr_load = MIF_MAX_THRESHOLD;
- }
- freq[PPMU_MIF] = div64_u64(data->max_freq[PPMU_MIF] * ddr_load, MIF_MAX_THRESHOLD);
- }
-
- freq_int_right0 = div64_u64(data->max_freq[PPMU_INT] * right0_load, INT_RIGHT0_THRESHOLD);
- }
-
- // Caculate next INT frequency
- if (ddr_load_int >= INT_MAX_THRESHOLD) {
- freq[PPMU_INT] = data->max_freq[PPMU_INT];
- } else if ( ddr_load_int < IDLE_THRESHOLD) {
- if (ddr_load_average < IDLE_THRESHOLD)
- freq[PPMU_INT] = step_down(data, PPMU_INT, 1);
- else
- freq[PPMU_INT] = data->curr_freq[PPMU_INT];
- } else {
- if (ddr_load_int < ddr_load_average) {
- ddr_load_int = ddr_load_average;
- if (ddr_load_int >= INT_MAX_THRESHOLD)
- ddr_load_int = INT_MAX_THRESHOLD;
- }
- freq[PPMU_INT] = div64_u64(data->max_freq[PPMU_INT] * ddr_load_int, INT_MAX_THRESHOLD);
- }
-
- freq[PPMU_INT] = max(freq[PPMU_INT], freq_int_right0);
-
- if (freq[PPMU_INT] == data->max_freq[PPMU_INT])
- freq[PPMU_MIF] = data->max_freq[PPMU_MIF];
-
-go_max:
-#ifdef BUSFREQ_PROFILE_DEBUG
- printk(KERN_DEBUG "cpu[%ld] l[%ld] c[%ld] r1[%ld] rt[%ld] m_load[%ld] i_load[%ld]\n",
- cpu_load, ddr_l_load, ddr_c_load, ddr_r1_load, right0_load, ddr_load, ddr_load_int);
-#endif
- lockfreq[PPMU_MIF] = (dev_max_freq(data->dev[PPMU_MIF])/1000)*1000;
- lockfreq[PPMU_INT] = (dev_max_freq(data->dev[PPMU_MIF])%1000)*1000;
-#ifdef BUSFREQ_PROFILE_DEBUG
- printk(KERN_DEBUG "i_cf[%ld] m_cf[%ld] i_nf[%ld] m_nf[%ld] lock_Mfreq[%ld] lock_Ifreq[%ld]\n",
- data->curr_freq[PPMU_INT],data->curr_freq[PPMU_MIF],freq[PPMU_INT], freq[PPMU_MIF], lockfreq[PPMU_MIF], lockfreq[PPMU_INT]);
-#endif
- newfreq[PPMU_MIF] = max(lockfreq[PPMU_MIF], freq[PPMU_MIF]);
- newfreq[PPMU_INT] = max(lockfreq[PPMU_INT], freq[PPMU_INT]);
- opp[PPMU_MIF] = opp_find_freq_ceil(data->dev[PPMU_MIF], &newfreq[PPMU_MIF]);
- opp[PPMU_INT] = opp_find_freq_ceil(data->dev[PPMU_INT], &newfreq[PPMU_INT]);
-
- *mif_opp = opp[PPMU_MIF];
- *int_opp = opp[PPMU_INT];
-}
-
-static void busfreq_early_suspend(struct early_suspend *h)
-{
- unsigned long freq;
- struct busfreq_data *data = container_of(h, struct busfreq_data,
- busfreq_early_suspend_handler);
- freq = data->min_freq[PPMU_MIF] + data->min_freq[PPMU_INT] / 1000;
- //dev_lock(data->dev[PPMU_MIF], data->dev[PPMU_MIF], freq);
- dev_unlock(data->dev[PPMU_MIF], data->dev[PPMU_MIF]);
-}
-
-static void busfreq_late_resume(struct early_suspend *h)
-{
- struct busfreq_data *data = container_of(h, struct busfreq_data,
- busfreq_early_suspend_handler);
- /* Request min MIF/INT 300MHz */
- dev_lock(data->dev[PPMU_MIF], data->dev[PPMU_MIF], 300150);
-}
-
-int exynos5250_init(struct device *dev, struct busfreq_data *data)
-{
- unsigned int i, tmp;
- unsigned long maxfreq = ULONG_MAX;
- unsigned long minfreq = 0;
- unsigned long cdrexfreq;
- unsigned long lrbusfreq;
- struct clk *clk;
- int ret;
-
- /* Enable pause function for DREX2 DVFS */
- drex2_pause_ctrl = __raw_readl(EXYNOS5_DREX2_PAUSE);
- drex2_pause_ctrl |= DMC_PAUSE_ENABLE;
- __raw_writel(drex2_pause_ctrl, EXYNOS5_DREX2_PAUSE);
-
- clk = clk_get(NULL, "mclk_cdrex");
- if (IS_ERR(clk)) {
- dev_err(dev, "Fail to get mclk_cdrex clock");
- ret = PTR_ERR(clk);
- return ret;
- }
- cdrexfreq = clk_get_rate(clk) / 1000;
- clk_put(clk);
-
- clk = clk_get(NULL, "aclk_266");
- if (IS_ERR(clk)) {
- dev_err(dev, "Fail to get aclk_266 clock");
- ret = PTR_ERR(clk);
- return ret;
- }
- lrbusfreq = clk_get_rate(clk) / 1000;
- clk_put(clk);
-
- if (cdrexfreq == 800000) {
- clkdiv_cdrex = clkdiv_cdrex_for800;
- exynos5_busfreq_table_mif = exynos5_busfreq_table_for800;
- exynos5_mif_volt = exynos5_mif_volt_for800;
- } else if (cdrexfreq == 666857) {
- clkdiv_cdrex = clkdiv_cdrex_for667;
- exynos5_busfreq_table_mif = exynos5_busfreq_table_for667;
- exynos5_mif_volt = exynos5_mif_volt_for667;
- } else if (cdrexfreq == 533000) {
- clkdiv_cdrex = clkdiv_cdrex_for533;
- exynos5_busfreq_table_mif = exynos5_busfreq_table_for533;
- exynos5_mif_volt = exynos5_mif_volt_for533;
- } else if (cdrexfreq == 400000) {
- clkdiv_cdrex = clkdiv_cdrex_for400;
- exynos5_busfreq_table_mif = exynos5_busfreq_table_for400;
- exynos5_mif_volt = exynos5_mif_volt_for400;
- } else {
- dev_err(dev, "Don't support cdrex table\n");
- return -EINVAL;
- }
-
- tmp = __raw_readl(EXYNOS5_CLKDIV_LEX);
-
- for (i = LV_0; i < LV_INT_END; i++) {
- tmp &= ~(EXYNOS5_CLKDIV_LEX_ATCLK_LEX_MASK | EXYNOS5_CLKDIV_LEX_PCLK_LEX_MASK);
-
- tmp |= ((clkdiv_lex[i][0] << EXYNOS5_CLKDIV_LEX_ATCLK_LEX_SHIFT) |
- (clkdiv_lex[i][1] << EXYNOS5_CLKDIV_LEX_PCLK_LEX_SHIFT));
-
- data->lex_divtable[i] = tmp;
- }
-
- tmp = __raw_readl(EXYNOS5_CLKDIV_R0X);
-
- for (i = LV_0; i < LV_INT_END; i++) {
-
- tmp &= ~EXYNOS5_CLKDIV_R0X_PCLK_R0X_MASK;
-
- tmp |= (clkdiv_r0x[i][0] << EXYNOS5_CLKDIV_R0X_PCLK_R0X_SHIFT);
-
- data->r0x_divtable[i] = tmp;
- }
-
- tmp = __raw_readl(EXYNOS5_CLKDIV_R1X);
-
- for (i = LV_0; i < LV_INT_END; i++) {
- tmp &= ~EXYNOS5_CLKDIV_R1X_PCLK_R1X_MASK;
-
- tmp |= (clkdiv_r1x[i][0] << EXYNOS5_CLKDIV_R1X_PCLK_R1X_SHIFT);
-
- data->r1x_divtable[i] = tmp;
- }
-
- tmp = __raw_readl(EXYNOS5_CLKDIV_CDREX);
-
- if (samsung_rev() < EXYNOS5250_REV_1_0) {
- for (i = LV_0; i < LV_MIF_END; i++) {
- tmp &= ~(EXYNOS5_CLKDIV_CDREX_MCLK_DPHY_MASK |
- EXYNOS5_CLKDIV_CDREX_MCLK_CDREX2_MASK |
- EXYNOS5_CLKDIV_CDREX_ACLK_CDREX_MASK |
- EXYNOS5_CLKDIV_CDREX_MCLK_CDREX_MASK |
- EXYNOS5_CLKDIV_CDREX_PCLK_CDREX_MASK |
- EXYNOS5_CLKDIV_CDREX_ACLK_CLK400_MASK |
- EXYNOS5_CLKDIV_CDREX_ACLK_C2C200_MASK |
- EXYNOS5_CLKDIV_CDREX_ACLK_EFCON_MASK);
-
- tmp |= ((clkdiv_cdrex[i][0] << EXYNOS5_CLKDIV_CDREX_MCLK_DPHY_SHIFT) |
- (clkdiv_cdrex[i][1] << EXYNOS5_CLKDIV_CDREX_MCLK_CDREX2_SHIFT) |
- (clkdiv_cdrex[i][2] << EXYNOS5_CLKDIV_CDREX_ACLK_CDREX_SHIFT) |
- (clkdiv_cdrex[i][3] << EXYNOS5_CLKDIV_CDREX_MCLK_CDREX_SHIFT) |
- (clkdiv_cdrex[i][4] << EXYNOS5_CLKDIV_CDREX_PCLK_CDREX_SHIFT) |
- (clkdiv_cdrex[i][5] << EXYNOS5_CLKDIV_CDREX_ACLK_CLK400_SHIFT) |
- (clkdiv_cdrex[i][6] << EXYNOS5_CLKDIV_CDREX_ACLK_C2C200_SHIFT) |
- (clkdiv_cdrex[i][8] << EXYNOS5_CLKDIV_CDREX_ACLK_EFCON_SHIFT));
-
- data->cdrex_divtable[i] = tmp;
- }
- } else {
- for (i = LV_0; i < LV_MIF_END; i++) {
- tmp &= ~(EXYNOS5_CLKDIV_CDREX_MCLK_DPHY_MASK |
- EXYNOS5_CLKDIV_CDREX_MCLK_CDREX2_MASK |
- EXYNOS5_CLKDIV_CDREX_ACLK_CDREX_MASK |
- EXYNOS5_CLKDIV_CDREX_MCLK_CDREX_MASK |
- EXYNOS5_CLKDIV_CDREX_PCLK_CDREX_MASK |
- EXYNOS5_CLKDIV_CDREX_ACLK_EFCON_MASK);
-
- tmp |= ((clkdiv_cdrex[i][0] << EXYNOS5_CLKDIV_CDREX_MCLK_DPHY_SHIFT) |
- (clkdiv_cdrex[i][1] << EXYNOS5_CLKDIV_CDREX_MCLK_CDREX2_SHIFT) |
- (clkdiv_cdrex[i][2] << EXYNOS5_CLKDIV_CDREX_ACLK_CDREX_SHIFT) |
- (clkdiv_cdrex[i][3] << EXYNOS5_CLKDIV_CDREX_MCLK_CDREX_SHIFT) |
- (clkdiv_cdrex[i][4] << EXYNOS5_CLKDIV_CDREX_PCLK_CDREX_SHIFT) |
- (clkdiv_cdrex[i][8] << EXYNOS5_CLKDIV_CDREX_ACLK_EFCON_SHIFT));
-
- data->cdrex_divtable[i] = tmp;
- }
- }
-
- if (samsung_rev() < EXYNOS5250_REV_1_0) {
- tmp = __raw_readl(EXYNOS5_CLKDIV_CDREX2);
-
- for (i = LV_0; i < LV_MIF_END; i++) {
- tmp &= ~EXYNOS5_CLKDIV_CDREX2_MCLK_EFPHY_MASK;
-
- tmp |= clkdiv_cdrex[i][7] << EXYNOS5_CLKDIV_CDREX2_MCLK_EFPHY_SHIFT;
-
- data->cdrex2_divtable[i] = tmp;
-
- }
- }
-
- exynos5250_set_bus_volt();
-
- data->dev[PPMU_MIF] = dev;
- data->dev[PPMU_INT] = &busfreq_for_int;
-
- for (i = LV_0; i < LV_MIF_END; i++) {
- ret = opp_add(data->dev[PPMU_MIF], exynos5_busfreq_table_mif[i].mem_clk,
- exynos5_busfreq_table_mif[i].volt);
- if (ret) {
- dev_err(dev, "Fail to add opp entries.\n");
- return ret;
- }
- }
-
-#if defined(CONFIG_DP_60HZ_P11) || defined(CONFIG_DP_60HZ_P10)
- if (cdrexfreq == 666857) {
- opp_disable(data->dev[PPMU_MIF], 334000);
- opp_disable(data->dev[PPMU_MIF], 110000);
- } else if (cdrexfreq == 533000) {
- opp_disable(data->dev[PPMU_MIF], 267000);
- opp_disable(data->dev[PPMU_MIF], 107000);
- } else if (cdrexfreq == 400000) {
- opp_disable(data->dev[PPMU_MIF], 267000);
- opp_disable(data->dev[PPMU_MIF], 100000);
- }
-#endif
-
- for (i = LV_0; i < LV_INT_END; i++) {
- ret = opp_add(data->dev[PPMU_INT], exynos5_busfreq_table_int[i].mem_clk,
- exynos5_busfreq_table_int[i].volt);
- if (ret) {
- dev_err(dev, "Fail to add opp entries.\n");
- return ret;
- }
- }
-
- data->target = exynos5250_target;
- data->get_table_index = exynos5250_get_table_index;
- data->monitor = exynos5250_monitor;
- data->busfreq_suspend = exynos5250_suspend;
- data->busfreq_resume = exynos5250_resume;
- data->sampling_rate = usecs_to_jiffies(100000);
-
- data->table[PPMU_MIF] = exynos5_busfreq_table_mif;
- data->table[PPMU_INT] = exynos5_busfreq_table_int;
-
- /* Find max frequency for mif */
- data->max_freq[PPMU_MIF] =
- opp_get_freq(opp_find_freq_floor(data->dev[PPMU_MIF], &maxfreq));
- data->min_freq[PPMU_MIF] =
- opp_get_freq(opp_find_freq_ceil(data->dev[PPMU_MIF], &minfreq));
- data->curr_freq[PPMU_MIF] =
- opp_get_freq(opp_find_freq_ceil(data->dev[PPMU_MIF], &cdrexfreq));
- /* Find max frequency for int */
- maxfreq = ULONG_MAX;
- minfreq = 0;
- data->max_freq[PPMU_INT] =
- opp_get_freq(opp_find_freq_floor(data->dev[PPMU_INT], &maxfreq));
- data->min_freq[PPMU_INT] =
- opp_get_freq(opp_find_freq_ceil(data->dev[PPMU_INT], &minfreq));
- data->curr_freq[PPMU_INT] =
- opp_get_freq(opp_find_freq_ceil(data->dev[PPMU_INT], &lrbusfreq));
-
- data->vdd_reg[PPMU_INT] = regulator_get(NULL, "vdd_int");
- if (IS_ERR(data->vdd_reg[PPMU_INT])) {
- pr_err("failed to get resource %s\n", "vdd_int");
- return -ENODEV;
- }
-
- data->vdd_reg[PPMU_MIF] = regulator_get(NULL, "vdd_mif");
- if (IS_ERR(data->vdd_reg[PPMU_MIF])) {
- pr_err("failed to get resource %s\n", "vdd_mif");
- regulator_put(data->vdd_reg[PPMU_INT]);
- return -ENODEV;
- }
-
- data->busfreq_early_suspend_handler.suspend = &busfreq_early_suspend;
- data->busfreq_early_suspend_handler.resume = &busfreq_late_resume;
-
- data->busfreq_early_suspend_handler.suspend = &busfreq_early_suspend;
- data->busfreq_early_suspend_handler.resume = &busfreq_late_resume;
-
- /* Request min 300MHz for MIF and 150MHz for INT*/
- dev_lock(dev, dev, 300150);
-
- register_early_suspend(&data->busfreq_early_suspend_handler);
-
- tmp = __raw_readl(EXYNOS5_ABBG_INT_CONTROL);
- tmp &= ~(0x1f | (1 << 31) | (1 << 7));
- tmp |= ((8 + INT_RBB) | (1 << 31) | (1 << 7));
- __raw_writel(tmp, EXYNOS5_ABBG_INT_CONTROL);
-
- return 0;
-}