]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-mx6/bus_freq.c
ENGR00139280: MX6: Add CPUFREQ support
[karo-tx-linux.git] / arch / arm / mach-mx6 / bus_freq.c
1 /*
2  * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 /*!
20  * @file bus_freq.c
21  *
22  * @brief A common API for the Freescale Semiconductor i.MXC CPUfreq module
23  * and DVFS CORE module.
24  *
25  * The APIs are for setting bus frequency to low or high.
26  *
27  * @ingroup PM
28  */
29 #include <asm/io.h>
30 #include <linux/sched.h>
31 #include <linux/proc_fs.h>
32 #include <linux/clk.h>
33 #include <linux/delay.h>
34 #include <linux/platform_device.h>
35 #include <linux/regulator/consumer.h>
36 #include <linux/mutex.h>
37 #include <mach/iram.h>
38 #include <mach/hardware.h>
39 #include <mach/clock.h>
40 #include <mach/mxc_dvfs.h>
41 #include <mach/sdram_autogating.h>
42 #include <asm/mach/map.h>
43 #include <asm/mach-types.h>
44 #include <asm/cacheflush.h>
45 #include <asm/tlb.h>
46
47 #define LP_LOW_VOLTAGE          1050000
48 #define LP_NORMAL_VOLTAGE               1250000
49 #define LP_APM_CLK                      24000000
50 #define NAND_LP_APM_CLK                 12000000
51 #define AXI_A_NORMAL_CLK                166250000
52 #define AXI_A_CLK_NORMAL_DIV            4
53 #define AXI_B_CLK_NORMAL_DIV            5
54 #define AHB_CLK_NORMAL_DIV              AXI_B_CLK_NORMAL_DIV
55 #define EMI_SLOW_CLK_NORMAL_DIV         AXI_B_CLK_NORMAL_DIV
56 #define NFC_CLK_NORMAL_DIV              4
57 #define SPIN_DELAY      1000000 /* in nanoseconds */
58 #define DDR_TYPE_DDR3           0x0
59 #define DDR_TYPE_DDR2           0x1
60
61 DEFINE_SPINLOCK(ddr_freq_lock);
62
63 unsigned long lp_normal_rate;
64 unsigned long lp_med_rate;
65 unsigned long ddr_normal_rate;
66 unsigned long ddr_med_rate;
67 unsigned long ddr_low_rate;
68
69 struct regulator *pll_regulator;
70
71 struct regulator *lp_regulator;
72 int low_bus_freq_mode;
73 int high_bus_freq_mode;
74 int med_bus_freq_mode;
75
76 int bus_freq_scaling_initialized;
77 char *lp_reg_id;
78
79 static struct device *busfreq_dev;
80 static int busfreq_suspended;
81
82 /* True if bus_frequency is scaled not using DVFS-PER */
83 int bus_freq_scaling_is_active;
84
85 int cpu_op_nr;
86 int lp_high_freq;
87 int lp_med_freq;
88
89 struct workqueue_struct *voltage_wq;
90 struct completion voltage_change_cmpl;
91
92 int low_freq_bus_used(void);
93 void set_ddr_freq(int ddr_freq);
94
95 extern struct cpu_op *(*get_cpu_op)(int *op);
96 extern void __iomem *ccm_base;
97 extern void __iomem *databahn_base;
98 extern int update_ddr_freq(int ddr_rate);
99
100
101 struct mutex bus_freq_mutex;
102
103 struct timeval start_time;
104 struct timeval end_time;
105
106 int set_low_bus_freq(void)
107 {
108         return 0;
109 }
110
111 int set_high_bus_freq(int high_bus_freq)
112 {
113         return 0;
114 }
115
116 void exit_lpapm_mode_mx6q(int high_bus_freq)
117 {
118
119 }
120
121
122 void set_ddr_freq(int ddr_rate)
123 {
124
125 }
126
127 int low_freq_bus_used(void)
128 {
129         if ((lp_high_freq == 0)
130             && (lp_med_freq == 0))
131                 return 1;
132         else
133                 return 0;
134 }
135
136 void setup_pll(void)
137 {
138 }
139
140 static ssize_t bus_freq_scaling_enable_show(struct device *dev,
141                                 struct device_attribute *attr, char *buf)
142 {
143         if (bus_freq_scaling_is_active)
144                 return sprintf(buf, "Bus frequency scaling is enabled\n");
145         else
146                 return sprintf(buf, "Bus frequency scaling is disabled\n");
147 }
148
149 static ssize_t bus_freq_scaling_enable_store(struct device *dev,
150                                  struct device_attribute *attr,
151                                  const char *buf, size_t size)
152 {
153         return size;
154 }
155
156 static int busfreq_suspend(struct platform_device *pdev, pm_message_t message)
157 {
158         if (low_bus_freq_mode)
159                 set_high_bus_freq(1);
160         busfreq_suspended = 1;
161         return 0;
162 }
163
164 static int busfreq_resume(struct platform_device *pdev)
165 {
166         busfreq_suspended = 0;
167         return  0;
168 }
169
170 static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
171                         bus_freq_scaling_enable_store);
172
173 /*!
174  * This is the probe routine for the bus frequency driver.
175  *
176  * @param   pdev   The platform device structure
177  *
178  * @return         The function returns 0 on success
179  *
180  */
181 static int __devinit busfreq_probe(struct platform_device *pdev)
182 {
183         return 0;
184 }
185
186 static struct platform_driver busfreq_driver = {
187         .driver = {
188                    .name = "imx_busfreq",
189                 },
190         .probe = busfreq_probe,
191         .suspend = busfreq_suspend,
192         .resume = busfreq_resume,
193 };
194
195 /*!
196  * Initialise the busfreq_driver.
197  *
198  * @return  The function always returns 0.
199  */
200
201 static int __init busfreq_init(void)
202 {
203         if (platform_driver_register(&busfreq_driver) != 0) {
204                 printk(KERN_ERR "busfreq_driver register failed\n");
205                 return -ENODEV;
206         }
207
208         printk(KERN_INFO "Bus freq driver module loaded\n");
209         return 0;
210 }
211
212 static void __exit busfreq_cleanup(void)
213 {
214         sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
215
216         /* Unregister the device structure */
217         platform_driver_unregister(&busfreq_driver);
218         bus_freq_scaling_initialized = 0;
219 }
220
221 module_init(busfreq_init);
222 module_exit(busfreq_cleanup);
223
224 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
225 MODULE_DESCRIPTION("BusFreq driver");
226 MODULE_LICENSE("GPL");