cpufreq: s3c24xx: split out registers
[linux-2.6-microblaze.git] / drivers / cpufreq / s3c2410-cpufreq.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2006-2008 Simtec Electronics
4  *      http://armlinux.simtec.co.uk/
5  *      Ben Dooks <ben@simtec.co.uk>
6  *
7  * S3C2410 CPU Frequency scaling
8 */
9
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/interrupt.h>
13 #include <linux/ioport.h>
14 #include <linux/cpufreq.h>
15 #include <linux/device.h>
16 #include <linux/clk.h>
17 #include <linux/err.h>
18 #include <linux/io.h>
19
20 #include <asm/mach/arch.h>
21 #include <asm/mach/map.h>
22
23 #include <plat/cpu.h>
24 #include <plat/cpu-freq-core.h>
25
26 #include <mach/map.h>
27
28 #define S3C2410_CLKREG(x) ((x) + S3C24XX_VA_CLKPWR)
29
30 #define S3C2410_CLKDIVN     S3C2410_CLKREG(0x14)
31
32 #define S3C2410_CLKDIVN_PDIVN        (1<<0)
33 #define S3C2410_CLKDIVN_HDIVN        (1<<1)
34
35 /* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */
36
37 static void s3c2410_cpufreq_setdivs(struct s3c_cpufreq_config *cfg)
38 {
39         u32 clkdiv = 0;
40
41         if (cfg->divs.h_divisor == 2)
42                 clkdiv |= S3C2410_CLKDIVN_HDIVN;
43
44         if (cfg->divs.p_divisor != cfg->divs.h_divisor)
45                 clkdiv |= S3C2410_CLKDIVN_PDIVN;
46
47         __raw_writel(clkdiv, S3C2410_CLKDIVN);
48 }
49
50 static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
51 {
52         unsigned long hclk, fclk, pclk;
53         unsigned int hdiv, pdiv;
54         unsigned long hclk_max;
55
56         fclk = cfg->freq.fclk;
57         hclk_max = cfg->max.hclk;
58
59         cfg->freq.armclk = fclk;
60
61         s3c_freq_dbg("%s: fclk is %lu, max hclk %lu\n",
62                       __func__, fclk, hclk_max);
63
64         hdiv = (fclk > cfg->max.hclk) ? 2 : 1;
65         hclk = fclk / hdiv;
66
67         if (hclk > cfg->max.hclk) {
68                 s3c_freq_dbg("%s: hclk too big\n", __func__);
69                 return -EINVAL;
70         }
71
72         pdiv = (hclk > cfg->max.pclk) ? 2 : 1;
73         pclk = hclk / pdiv;
74
75         if (pclk > cfg->max.pclk) {
76                 s3c_freq_dbg("%s: pclk too big\n", __func__);
77                 return -EINVAL;
78         }
79
80         pdiv *= hdiv;
81
82         /* record the result */
83         cfg->divs.p_divisor = pdiv;
84         cfg->divs.h_divisor = hdiv;
85
86         return 0;
87 }
88
89 static struct s3c_cpufreq_info s3c2410_cpufreq_info = {
90         .max            = {
91                 .fclk   = 200000000,
92                 .hclk   = 100000000,
93                 .pclk   =  50000000,
94         },
95
96         /* transition latency is about 5ms worst-case, so
97          * set 10ms to be sure */
98         .latency        = 10000000,
99
100         .locktime_m     = 150,
101         .locktime_u     = 150,
102         .locktime_bits  = 12,
103
104         .need_pll       = 1,
105
106         .name           = "s3c2410",
107         .calc_iotiming  = s3c2410_iotiming_calc,
108         .set_iotiming   = s3c2410_iotiming_set,
109         .get_iotiming   = s3c2410_iotiming_get,
110
111         .set_fvco       = s3c2410_set_fvco,
112         .set_refresh    = s3c2410_cpufreq_setrefresh,
113         .set_divs       = s3c2410_cpufreq_setdivs,
114         .calc_divs      = s3c2410_cpufreq_calcdivs,
115
116         .debug_io_show  = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs),
117 };
118
119 static int s3c2410_cpufreq_add(struct device *dev,
120                                struct subsys_interface *sif)
121 {
122         return s3c_cpufreq_register(&s3c2410_cpufreq_info);
123 }
124
125 static struct subsys_interface s3c2410_cpufreq_interface = {
126         .name           = "s3c2410_cpufreq",
127         .subsys         = &s3c2410_subsys,
128         .add_dev        = s3c2410_cpufreq_add,
129 };
130
131 static int __init s3c2410_cpufreq_init(void)
132 {
133         return subsys_interface_register(&s3c2410_cpufreq_interface);
134 }
135 arch_initcall(s3c2410_cpufreq_init);
136
137 static int s3c2410a_cpufreq_add(struct device *dev,
138                                 struct subsys_interface *sif)
139 {
140         /* alter the maximum freq settings for S3C2410A. If a board knows
141          * it only has a maximum of 200, then it should register its own
142          * limits. */
143
144         s3c2410_cpufreq_info.max.fclk = 266000000;
145         s3c2410_cpufreq_info.max.hclk = 133000000;
146         s3c2410_cpufreq_info.max.pclk =  66500000;
147         s3c2410_cpufreq_info.name = "s3c2410a";
148
149         return s3c2410_cpufreq_add(dev, sif);
150 }
151
152 static struct subsys_interface s3c2410a_cpufreq_interface = {
153         .name           = "s3c2410a_cpufreq",
154         .subsys         = &s3c2410a_subsys,
155         .add_dev        = s3c2410a_cpufreq_add,
156 };
157
158 static int __init s3c2410a_cpufreq_init(void)
159 {
160         return subsys_interface_register(&s3c2410a_cpufreq_interface);
161 }
162 arch_initcall(s3c2410a_cpufreq_init);