2 * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
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.
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.
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.
22 * @brief A common API for the Freescale Semiconductor i.MXC CPUfreq module
23 * and DVFS CORE module.
25 * The APIs are for setting bus frequency to low or high.
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>
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
61 DEFINE_SPINLOCK(ddr_freq_lock);
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;
69 struct regulator *pll_regulator;
71 struct regulator *lp_regulator;
72 int low_bus_freq_mode;
73 int high_bus_freq_mode;
74 int med_bus_freq_mode;
76 int bus_freq_scaling_initialized;
79 static struct device *busfreq_dev;
80 static int busfreq_suspended;
82 /* True if bus_frequency is scaled not using DVFS-PER */
83 int bus_freq_scaling_is_active;
89 struct workqueue_struct *voltage_wq;
90 struct completion voltage_change_cmpl;
92 int low_freq_bus_used(void);
93 void set_ddr_freq(int ddr_freq);
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);
101 struct mutex bus_freq_mutex;
103 struct timeval start_time;
104 struct timeval end_time;
106 int set_low_bus_freq(void)
111 int set_high_bus_freq(int high_bus_freq)
116 void exit_lpapm_mode_mx6q(int high_bus_freq)
122 void set_ddr_freq(int ddr_rate)
127 int low_freq_bus_used(void)
129 if ((lp_high_freq == 0)
130 && (lp_med_freq == 0))
140 static ssize_t bus_freq_scaling_enable_show(struct device *dev,
141 struct device_attribute *attr, char *buf)
143 if (bus_freq_scaling_is_active)
144 return sprintf(buf, "Bus frequency scaling is enabled\n");
146 return sprintf(buf, "Bus frequency scaling is disabled\n");
149 static ssize_t bus_freq_scaling_enable_store(struct device *dev,
150 struct device_attribute *attr,
151 const char *buf, size_t size)
156 static int busfreq_suspend(struct platform_device *pdev, pm_message_t message)
158 if (low_bus_freq_mode)
159 set_high_bus_freq(1);
160 busfreq_suspended = 1;
164 static int busfreq_resume(struct platform_device *pdev)
166 busfreq_suspended = 0;
170 static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show,
171 bus_freq_scaling_enable_store);
174 * This is the probe routine for the bus frequency driver.
176 * @param pdev The platform device structure
178 * @return The function returns 0 on success
181 static int __devinit busfreq_probe(struct platform_device *pdev)
186 static struct platform_driver busfreq_driver = {
188 .name = "imx_busfreq",
190 .probe = busfreq_probe,
191 .suspend = busfreq_suspend,
192 .resume = busfreq_resume,
196 * Initialise the busfreq_driver.
198 * @return The function always returns 0.
201 static int __init busfreq_init(void)
203 if (platform_driver_register(&busfreq_driver) != 0) {
204 printk(KERN_ERR "busfreq_driver register failed\n");
208 printk(KERN_INFO "Bus freq driver module loaded\n");
212 static void __exit busfreq_cleanup(void)
214 sysfs_remove_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
216 /* Unregister the device structure */
217 platform_driver_unregister(&busfreq_driver);
218 bus_freq_scaling_initialized = 0;
221 module_init(busfreq_init);
222 module_exit(busfreq_cleanup);
224 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
225 MODULE_DESCRIPTION("BusFreq driver");
226 MODULE_LICENSE("GPL");