Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ARM] 4430/1: davinci: clock control support

Support clock control driver for TI DaVinci SoC

Signed-off-by: Vladimir Barinov <vbarinov@ru.mvista.com>
Signed-off-by: Kevin Hilman <khilman@mvista.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Vladimir Barinov and committed by
Russell King
3e062b07 7dcca30a

+387 -1
+1 -1
arch/arm/mach-davinci/Makefile
··· 4 4 # 5 5 6 6 # Common objects 7 - obj-y := time.o irq.o serial.o io.o id.o psc.o 7 + obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o 8 8 9 9 # Board specific 10 10 obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o
+2
arch/arm/mach-davinci/board-evm.c
··· 32 32 void __init davinci_psc_init(void); 33 33 void __init davinci_irq_init(void); 34 34 void __init davinci_map_common_io(void); 35 + void __init davinci_init_common_hw(void); 35 36 36 37 /* NOR Flash base address set to CS0 by default */ 37 38 #define NOR_FLASH_PHYS 0x02000000 ··· 117 116 118 117 static __init void davinci_evm_irq_init(void) 119 118 { 119 + davinci_init_common_hw(); 120 120 davinci_irq_init(); 121 121 } 122 122
+323
arch/arm/mach-davinci/clock.c
··· 1 + /* 2 + * TI DaVinci clock config file 3 + * 4 + * Copyright (C) 2006 Texas Instruments. 5 + * 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; either version 2 of the License, or 9 + * (at your option) any later version. 10 + */ 11 + 12 + #include <linux/module.h> 13 + #include <linux/kernel.h> 14 + #include <linux/init.h> 15 + #include <linux/errno.h> 16 + #include <linux/err.h> 17 + #include <linux/mutex.h> 18 + #include <linux/platform_device.h> 19 + 20 + #include <asm/hardware.h> 21 + #include <asm/io.h> 22 + 23 + #include <asm/arch/psc.h> 24 + #include "clock.h" 25 + 26 + /* PLL/Reset register offsets */ 27 + #define PLLM 0x110 28 + 29 + static LIST_HEAD(clocks); 30 + static DEFINE_MUTEX(clocks_mutex); 31 + static DEFINE_SPINLOCK(clockfw_lock); 32 + 33 + static unsigned int commonrate; 34 + static unsigned int armrate; 35 + static unsigned int fixedrate = 27000000; /* 27 MHZ */ 36 + 37 + extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable); 38 + 39 + /* 40 + * Returns a clock. Note that we first try to use device id on the bus 41 + * and clock name. If this fails, we try to use clock name only. 42 + */ 43 + struct clk *clk_get(struct device *dev, const char *id) 44 + { 45 + struct clk *p, *clk = ERR_PTR(-ENOENT); 46 + int idno; 47 + 48 + if (dev == NULL || dev->bus != &platform_bus_type) 49 + idno = -1; 50 + else 51 + idno = to_platform_device(dev)->id; 52 + 53 + mutex_lock(&clocks_mutex); 54 + 55 + list_for_each_entry(p, &clocks, node) { 56 + if (p->id == idno && 57 + strcmp(id, p->name) == 0 && try_module_get(p->owner)) { 58 + clk = p; 59 + goto found; 60 + } 61 + } 62 + 63 + list_for_each_entry(p, &clocks, node) { 64 + if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { 65 + clk = p; 66 + break; 67 + } 68 + } 69 + 70 + found: 71 + mutex_unlock(&clocks_mutex); 72 + 73 + return clk; 74 + } 75 + EXPORT_SYMBOL(clk_get); 76 + 77 + void clk_put(struct clk *clk) 78 + { 79 + if (clk && !IS_ERR(clk)) 80 + module_put(clk->owner); 81 + } 82 + EXPORT_SYMBOL(clk_put); 83 + 84 + static int __clk_enable(struct clk *clk) 85 + { 86 + if (clk->flags & ALWAYS_ENABLED) 87 + return 0; 88 + 89 + davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1); 90 + return 0; 91 + } 92 + 93 + static void __clk_disable(struct clk *clk) 94 + { 95 + if (clk->usecount) 96 + return; 97 + 98 + davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0); 99 + } 100 + 101 + int clk_enable(struct clk *clk) 102 + { 103 + unsigned long flags; 104 + int ret = 0; 105 + 106 + if (clk == NULL || IS_ERR(clk)) 107 + return -EINVAL; 108 + 109 + if (clk->usecount++ == 0) { 110 + spin_lock_irqsave(&clockfw_lock, flags); 111 + ret = __clk_enable(clk); 112 + spin_unlock_irqrestore(&clockfw_lock, flags); 113 + } 114 + 115 + return ret; 116 + } 117 + EXPORT_SYMBOL(clk_enable); 118 + 119 + void clk_disable(struct clk *clk) 120 + { 121 + unsigned long flags; 122 + 123 + if (clk == NULL || IS_ERR(clk)) 124 + return; 125 + 126 + if (clk->usecount > 0 && !(--clk->usecount)) { 127 + spin_lock_irqsave(&clockfw_lock, flags); 128 + __clk_disable(clk); 129 + spin_unlock_irqrestore(&clockfw_lock, flags); 130 + } 131 + } 132 + EXPORT_SYMBOL(clk_disable); 133 + 134 + unsigned long clk_get_rate(struct clk *clk) 135 + { 136 + if (clk == NULL || IS_ERR(clk)) 137 + return -EINVAL; 138 + 139 + return *(clk->rate); 140 + } 141 + EXPORT_SYMBOL(clk_get_rate); 142 + 143 + long clk_round_rate(struct clk *clk, unsigned long rate) 144 + { 145 + if (clk == NULL || IS_ERR(clk)) 146 + return -EINVAL; 147 + 148 + return *(clk->rate); 149 + } 150 + EXPORT_SYMBOL(clk_round_rate); 151 + 152 + int clk_set_rate(struct clk *clk, unsigned long rate) 153 + { 154 + if (clk == NULL || IS_ERR(clk)) 155 + return -EINVAL; 156 + 157 + /* changing the clk rate is not supported */ 158 + return -EINVAL; 159 + } 160 + EXPORT_SYMBOL(clk_set_rate); 161 + 162 + int clk_register(struct clk *clk) 163 + { 164 + if (clk == NULL || IS_ERR(clk)) 165 + return -EINVAL; 166 + 167 + mutex_lock(&clocks_mutex); 168 + list_add(&clk->node, &clocks); 169 + mutex_unlock(&clocks_mutex); 170 + 171 + return 0; 172 + } 173 + EXPORT_SYMBOL(clk_register); 174 + 175 + void clk_unregister(struct clk *clk) 176 + { 177 + if (clk == NULL || IS_ERR(clk)) 178 + return; 179 + 180 + mutex_lock(&clocks_mutex); 181 + list_del(&clk->node); 182 + mutex_unlock(&clocks_mutex); 183 + } 184 + EXPORT_SYMBOL(clk_unregister); 185 + 186 + static struct clk davinci_clks[] = { 187 + { 188 + .name = "ARMCLK", 189 + .rate = &armrate, 190 + .lpsc = -1, 191 + .flags = ALWAYS_ENABLED, 192 + }, 193 + { 194 + .name = "UART", 195 + .rate = &fixedrate, 196 + .lpsc = DAVINCI_LPSC_UART0, 197 + }, 198 + { 199 + .name = "EMACCLK", 200 + .rate = &commonrate, 201 + .lpsc = DAVINCI_LPSC_EMAC_WRAPPER, 202 + }, 203 + { 204 + .name = "I2CCLK", 205 + .rate = &fixedrate, 206 + .lpsc = DAVINCI_LPSC_I2C, 207 + }, 208 + { 209 + .name = "IDECLK", 210 + .rate = &commonrate, 211 + .lpsc = DAVINCI_LPSC_ATA, 212 + }, 213 + { 214 + .name = "McBSPCLK", 215 + .rate = &commonrate, 216 + .lpsc = DAVINCI_LPSC_McBSP, 217 + }, 218 + { 219 + .name = "MMCSDCLK", 220 + .rate = &commonrate, 221 + .lpsc = DAVINCI_LPSC_MMC_SD, 222 + }, 223 + { 224 + .name = "SPICLK", 225 + .rate = &commonrate, 226 + .lpsc = DAVINCI_LPSC_SPI, 227 + }, 228 + { 229 + .name = "gpio", 230 + .rate = &commonrate, 231 + .lpsc = DAVINCI_LPSC_GPIO, 232 + }, 233 + { 234 + .name = "AEMIFCLK", 235 + .rate = &commonrate, 236 + .lpsc = DAVINCI_LPSC_AEMIF, 237 + .usecount = 1, 238 + } 239 + }; 240 + 241 + int __init davinci_clk_init(void) 242 + { 243 + struct clk *clkp; 244 + int count = 0; 245 + u32 pll_mult; 246 + 247 + pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM); 248 + commonrate = ((pll_mult + 1) * 27000000) / 6; 249 + armrate = ((pll_mult + 1) * 27000000) / 2; 250 + 251 + for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks); 252 + count++, clkp++) { 253 + clk_register(clkp); 254 + 255 + /* Turn on clocks that have been enabled in the 256 + * table above */ 257 + if (clkp->usecount) 258 + clk_enable(clkp); 259 + } 260 + 261 + return 0; 262 + } 263 + 264 + #ifdef CONFIG_PROC_FS 265 + #include <linux/proc_fs.h> 266 + #include <linux/seq_file.h> 267 + 268 + static void *davinci_ck_start(struct seq_file *m, loff_t *pos) 269 + { 270 + return *pos < 1 ? (void *)1 : NULL; 271 + } 272 + 273 + static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos) 274 + { 275 + ++*pos; 276 + return NULL; 277 + } 278 + 279 + static void davinci_ck_stop(struct seq_file *m, void *v) 280 + { 281 + } 282 + 283 + static int davinci_ck_show(struct seq_file *m, void *v) 284 + { 285 + struct clk *cp; 286 + 287 + list_for_each_entry(cp, &clocks, node) 288 + seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount); 289 + 290 + return 0; 291 + } 292 + 293 + static struct seq_operations davinci_ck_op = { 294 + .start = davinci_ck_start, 295 + .next = davinci_ck_next, 296 + .stop = davinci_ck_stop, 297 + .show = davinci_ck_show 298 + }; 299 + 300 + static int davinci_ck_open(struct inode *inode, struct file *file) 301 + { 302 + return seq_open(file, &davinci_ck_op); 303 + } 304 + 305 + static struct file_operations proc_davinci_ck_operations = { 306 + .open = davinci_ck_open, 307 + .read = seq_read, 308 + .llseek = seq_lseek, 309 + .release = seq_release, 310 + }; 311 + 312 + static int __init davinci_ck_proc_init(void) 313 + { 314 + struct proc_dir_entry *entry; 315 + 316 + entry = create_proc_entry("davinci_clocks", 0, NULL); 317 + if (entry) 318 + entry->proc_fops = &proc_davinci_ck_operations; 319 + return 0; 320 + 321 + } 322 + __initcall(davinci_ck_proc_init); 323 + #endif /* CONFIG_DEBUG_PROC_FS */
+33
arch/arm/mach-davinci/clock.h
··· 1 + /* 2 + * TI DaVinci clock definitions 3 + * 4 + * Copyright (C) 2006 Texas Instruments. 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #ifndef __ARCH_ARM_DAVINCI_CLOCK_H 12 + #define __ARCH_ARM_DAVINCI_CLOCK_H 13 + 14 + struct clk { 15 + struct list_head node; 16 + struct module *owner; 17 + const char *name; 18 + unsigned int *rate; 19 + int id; 20 + __s8 usecount; 21 + __u8 flags; 22 + __u8 lpsc; 23 + }; 24 + 25 + /* Clock flags */ 26 + #define RATE_CKCTL 1 27 + #define RATE_FIXED 2 28 + #define RATE_PROPAGATES 4 29 + #define VIRTUAL_CLOCK 8 30 + #define ALWAYS_ENABLED 16 31 + #define ENABLE_REG_32BIT 32 32 + 33 + #endif
+6
arch/arm/mach-davinci/io.c
··· 17 17 #include <asm/memory.h> 18 18 19 19 #include <asm/mach/map.h> 20 + #include <asm/arch/clock.h> 20 21 21 22 extern void davinci_check_revision(void); 22 23 ··· 49 48 * IO space mapping must be initialized before we can do that. 50 49 */ 51 50 davinci_check_revision(); 51 + } 52 + 53 + void __init davinci_init_common_hw(void) 54 + { 55 + davinci_clk_init(); 52 56 }
+22
include/asm-arm/arch-davinci/clock.h
··· 1 + /* 2 + * include/asm-arm/arch-davinci/clock.h 3 + * 4 + * Clock control driver for DaVinci - header file 5 + * 6 + * Authors: Vladimir Barinov <source@mvista.com> 7 + * 8 + * 2007 (c) MontaVista Software, Inc. This file is licensed under 9 + * the terms of the GNU General Public License version 2. This program 10 + * is licensed "as is" without any warranty of any kind, whether express 11 + * or implied. 12 + */ 13 + #ifndef __ASM_ARCH_DAVINCI_CLOCK_H 14 + #define __ASM_ARCH_DAVINCI_CLOCK_H 15 + 16 + struct clk; 17 + 18 + extern int clk_register(struct clk *clk); 19 + extern void clk_unregister(struct clk *clk); 20 + extern int davinci_clk_init(void); 21 + 22 + #endif