3 Exports some additional hardware control to userspace.
4 Written by GraÅžvydas "notaz" Ignotas <notasas@gmail.com>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; version 2 of the License.
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/proc_fs.h>
14 #include <linux/uaccess.h>
15 #include <linux/delay.h>
16 #include <linux/clk.h>
19 #ifndef CONFIG_PROC_FS
20 #error need CONFIG_PROC_FS
23 #define PND_PROC_CPUMHZ "pandora/cpu_mhz_max"
27 * SYS_CLK is 26 MHz (see PRM_CLKSEL)
28 * ARM_FCLK = (SYS_CLK * M * 2) / ([N+1] * M2) / 2
29 * CM_CLKSEL1_PLL_MPU = N | (M << 8) | (M2 << 19)
31 static int get_fclk(void)
33 unsigned __iomem *base;
36 base = ioremap(0x48004000, 0x2000);
38 printk(KERN_ERR "get_fclk: can't ioremap\n");
45 if ((ret & ~0x7ff00) != 0x10000c) {
46 printk(KERN_ERR "get_fclk: unexpected CM_CLKSEL1_PLL_MPU: "
57 static void set_fclk(int val)
59 struct clk *pllclk, *fclk;
63 printk(KERN_ERR "set_fclk: value %d out of range\n", val);
68 pllclk = clk_get(NULL, "dpll1_ck");
70 printk(KERN_ERR "set_fclk: clk_get() failed: %li\n",
75 ret = clk_set_rate(pllclk, val * 1000000);
77 printk(KERN_ERR "set_fclk: clk_set_rate(dpll1_ck) "
78 "failed: %li\n", PTR_ERR(pllclk));
81 printk(KERN_INFO "dpll1_ck rate: %li\n", clk_get_rate(pllclk));
84 fclk = clk_get(NULL, "arm_fck");
85 if (!IS_ERR(pllclk)) {
86 printk(KERN_INFO "arm_fck rate: %li\n", clk_get_rate(fclk));
90 printk(KERN_INFO "PLL_MPU rate: %i\n", get_fclk() * 1000000);
93 static int cpu_clk_read(char *page, char **start, off_t off, int count,
99 p += sprintf(p, "%d\n", get_fclk());
101 len = (p - page) - off;
105 *eof = (len <= count) ? 1 : 0;
111 static int cpu_clk_write(struct file *file, const char __user *buffer,
112 unsigned long count, void *data)
118 count = strncpy_from_user(buff, buffer,
119 count < sizeof(buff) ? count : sizeof(buff) - 1);
122 ret = strict_strtoul(buff, 0, &val);
124 printk(KERN_ERR "error %i parsing %s\n", ret, buff);
133 /* ************************************************************************* */
135 static int pndctrl_init(void)
137 struct proc_dir_entry *pret;
140 pret = create_proc_entry(PND_PROC_CPUMHZ, S_IWUSR | S_IRUGO, NULL);
142 proc_mkdir("pandora", NULL);
143 pret = create_proc_entry(PND_PROC_CPUMHZ,
144 S_IWUSR | S_IRUGO, NULL);
146 printk(KERN_ERR "can't create proc entry\n");
151 pret->read_proc = cpu_clk_read;
152 pret->write_proc = cpu_clk_write;
154 printk(KERN_INFO "pndctrl loaded.\n");
160 static void pndctrl_cleanup(void)
162 remove_proc_entry(PND_PROC_CPUMHZ, NULL);
163 printk(KERN_INFO "pndctrl unloaded.\n");
167 module_init(pndctrl_init);
168 module_exit(pndctrl_cleanup);
170 MODULE_AUTHOR("Grazvydas Ignotas");
171 MODULE_LICENSE("GPL");
172 MODULE_DESCRIPTION("Pandora Additional hw control");