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