1/* 2 * linux/arch/arm/mach-sa1100/clock.c 3 */ 4#include <linux/module.h> 5#include <linux/kernel.h> 6#include <linux/list.h> 7#include <linux/errno.h> 8#include <linux/err.h> 9#include <linux/string.h> 10#include <linux/clk.h> 11#include <linux/spinlock.h> 12#include <linux/mutex.h> 13 14#include <asm/hardware.h> 15 16/* 17 * Very simple clock implementation - we only have one clock to 18 * deal with at the moment, so we only match using the "name". 19 */ 20struct clk { 21 struct list_head node; 22 unsigned long rate; 23 const char *name; 24 unsigned int enabled; 25 void (*enable)(void); 26 void (*disable)(void); 27}; 28 29static LIST_HEAD(clocks); 30static DEFINE_MUTEX(clocks_mutex); 31static DEFINE_SPINLOCK(clocks_lock); 32 33struct clk *clk_get(struct device *dev, const char *id) 34{ 35 struct clk *p, *clk = ERR_PTR(-ENOENT); 36 37 mutex_lock(&clocks_mutex); 38 list_for_each_entry(p, &clocks, node) { 39 if (strcmp(id, p->name) == 0) { 40 clk = p; 41 break; 42 } 43 } 44 mutex_unlock(&clocks_mutex); 45 46 return clk; 47} 48EXPORT_SYMBOL(clk_get); 49 50void clk_put(struct clk *clk) 51{ 52} 53EXPORT_SYMBOL(clk_put); 54 55int clk_enable(struct clk *clk) 56{ 57 unsigned long flags; 58 59 spin_lock_irqsave(&clocks_lock, flags); 60 if (clk->enabled++ == 0) 61 clk->enable(); 62 spin_unlock_irqrestore(&clocks_lock, flags); 63 return 0; 64} 65EXPORT_SYMBOL(clk_enable); 66 67void clk_disable(struct clk *clk) 68{ 69 unsigned long flags; 70 71 WARN_ON(clk->enabled == 0); 72 73 spin_lock_irqsave(&clocks_lock, flags); 74 if (--clk->enabled == 0) 75 clk->disable(); 76 spin_unlock_irqrestore(&clocks_lock, flags); 77} 78EXPORT_SYMBOL(clk_disable); 79 80unsigned long clk_get_rate(struct clk *clk) 81{ 82 return clk->rate; 83} 84EXPORT_SYMBOL(clk_get_rate); 85 86 87static void clk_gpio27_enable(void) 88{ 89 /* 90 * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: 91 * (SA-1110 Developer's Manual, section 9.1.2.1) 92 */ 93 GAFR |= GPIO_32_768kHz; 94 GPDR |= GPIO_32_768kHz; 95 TUCR = TUCR_3_6864MHz; 96} 97 98static void clk_gpio27_disable(void) 99{ 100 TUCR = 0; 101 GPDR &= ~GPIO_32_768kHz; 102 GAFR &= ~GPIO_32_768kHz; 103} 104 105static struct clk clk_gpio27 = { 106 .name = "GPIO27_CLK", 107 .rate = 3686400, 108 .enable = clk_gpio27_enable, 109 .disable = clk_gpio27_disable, 110}; 111 112int clk_register(struct clk *clk) 113{ 114 mutex_lock(&clocks_mutex); 115 list_add(&clk->node, &clocks); 116 mutex_unlock(&clocks_mutex); 117 return 0; 118} 119EXPORT_SYMBOL(clk_register); 120 121void clk_unregister(struct clk *clk) 122{ 123 mutex_lock(&clocks_mutex); 124 list_del(&clk->node); 125 mutex_unlock(&clocks_mutex); 126} 127EXPORT_SYMBOL(clk_unregister); 128 129static int __init clk_init(void) 130{ 131 clk_register(&clk_gpio27); 132 return 0; 133} 134arch_initcall(clk_init); 135