1 /* linux/arch/arm/mach-s5pv310/asv.c
3 * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com/
6 * S5PV310 - ASV(Adaptive Supply Voltage) Test driver
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.
13 #include <linux/init.h>
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/err.h>
17 #include <linux/clk.h>
21 #include <mach/regs-iem.h>
22 #include <mach/regs-pmu.h>
23 #include <mach/regs-clock.h>
25 #include <asm/mach-types.h>
29 int exynos4_asv_group;
31 static int __init iem_clock_init(void)
35 struct clk *clk_parent;
37 /* PWI clock setting */
38 clk_copy = clk_get(NULL, "sclk_pwi");
39 if (IS_ERR(clk_copy)) {
40 printk(KERN_ERR"ASV : SCLK_PWI clock get error\n");
43 clk_parent = clk_get(NULL, "xusbxti");
44 if (IS_ERR(clk_parent)) {
45 printk(KERN_ERR"ASV : MOUT_APLL clock get error\n");
48 clk_set_parent(clk_copy, clk_parent);
52 clk_set_rate(clk_copy, 4800000);
56 /* HPM clock setting */
57 clk_copy = clk_get(NULL, "dout_copy");
58 if (IS_ERR(clk_copy)) {
59 printk(KERN_ERR"ASV : DOUT_COPY clock get error\n");
62 clk_parent = clk_get(NULL, "mout_mpll");
63 if (IS_ERR(clk_parent)) {
64 printk(KERN_ERR"ASV : MOUT_APLL clock get error\n");
67 clk_set_parent(clk_copy, clk_parent);
72 clk_set_rate(clk_copy, (400 * 1000 * 1000));
76 clk_hpm = clk_get(NULL, "sclk_hpm");
80 clk_set_rate(clk_hpm, (200 * 1000 * 1000));
87 void __init iem_clock_set(void)
89 /* APLL_CON0 level register */
90 __raw_writel(0x80FA0601, S5P_APLL_CON0L8);
91 __raw_writel(0x80C80601, S5P_APLL_CON0L7);
92 __raw_writel(0x80C80602, S5P_APLL_CON0L6);
93 __raw_writel(0x80C80604, S5P_APLL_CON0L5);
94 __raw_writel(0x80C80601, S5P_APLL_CON0L4);
95 __raw_writel(0x80C80601, S5P_APLL_CON0L3);
96 __raw_writel(0x80C80601, S5P_APLL_CON0L2);
97 __raw_writel(0x80C80601, S5P_APLL_CON0L1);
99 /* IEM Divider register */
100 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L8);
101 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L7);
102 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L6);
103 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L5);
104 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L4);
105 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L3);
106 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L2);
107 __raw_writel(0x00500000, S5P_CLKDIV_IEM_L1);
110 #define IDS_OFFSET 24
111 #define IDS_MASK 0xFF
113 #define IDS_LEVEL_MAX_0 4
114 #define IDS_LEVEL_MAX_1 8
115 #define IDS_LEVEL_MAX_2 12
116 #define IDS_LEVEL_MAX_3 17
117 #define IDS_LEVEL_MAX_4 27
118 #define IDS_LEVEL_MAX_5 45
119 #define IDS_LEVEL_MAX_6 55
121 #define HPM_LEVEL_MAX_0 8
122 #define HPM_LEVEL_MAX_1 11
123 #define HPM_LEVEL_MAX_2 14
124 #define HPM_LEVEL_MAX_3 18
125 #define HPM_LEVEL_MAX_4 21
126 #define HPM_LEVEL_MAX_5 23
127 #define HPM_LEVEL_MAX_6 25
129 #define ASV_MAX_GROUP 8
136 static int __init s5pv310_find_group(unsigned int value, enum find_asv grp)
140 if (grp == HPM_GROUP) {
141 if (value <= HPM_LEVEL_MAX_0)
143 else if (value <= HPM_LEVEL_MAX_1)
145 else if (value <= HPM_LEVEL_MAX_2)
147 else if (value <= HPM_LEVEL_MAX_3)
149 else if (value <= HPM_LEVEL_MAX_4)
151 else if (value <= HPM_LEVEL_MAX_5)
156 if (value <= IDS_LEVEL_MAX_0)
158 else if (value <= IDS_LEVEL_MAX_1)
160 else if (value <= IDS_LEVEL_MAX_2)
162 else if (value <= IDS_LEVEL_MAX_3)
164 else if (value <= IDS_LEVEL_MAX_4)
166 else if (value <= IDS_LEVEL_MAX_5)
175 static int __init s5pv310_asv_init(void)
178 unsigned long hpm_delay = 0;
180 unsigned int ids_arm;
181 unsigned int result_group = 0;
182 static void __iomem * iem_base;
183 struct clk *clk = clk_get(NULL, "chipid");
185 if (IS_ERR_OR_NULL(clk))
190 if(machine_is_smdkv310())
193 tmp = __raw_readl(S5P_VA_CHIPID + 0x4);
200 ids_arm = ((tmp >> IDS_OFFSET) & IDS_MASK);
202 iem_base = ioremap(S5PV310_PA_IEM, (128 * 1024));
204 if (iem_base == NULL) {
205 printk(KERN_ERR "faile to ioremap\n");
209 if (iem_clock_init()) {
210 printk(KERN_ERR "ASV driver clock_init fail\n");
214 tmp = __raw_readl(iem_base + S5PV310_APC_CONTROL);
216 __raw_writel(tmp, (iem_base + S5PV310_APC_CONTROL));
221 tmp = __raw_readl(iem_base + S5PV310_IECDPCCR);
223 __raw_writel(tmp, (iem_base + S5PV310_IECDPCCR));
226 for ( i=0 ; i < LOOP_CNT ; i++ ){
227 tmp = __raw_readb(iem_base + S5PV310_APC_DBG_DLYCODE);
231 hpm_delay /= LOOP_CNT;
233 result_group = s5pv310_find_group(hpm_delay, HPM_GROUP);
235 if (result_group > s5pv310_find_group(ids_arm,IDS_GROUP))
236 result_group = s5pv310_find_group(ids_arm,IDS_GROUP);
238 exynos4_asv_group = result_group;
240 printk(KERN_INFO "ASV Group for This Exynos4210 is %d\n",result_group);
245 exynos4_asv_group = 0;
246 printk(KERN_INFO "ASV Group for This Exynos4210 is %d\n",result_group);
251 core_initcall(s5pv310_asv_init);