1 /***************************************************************************/ 2 3 /* 4 * clk.c -- general ColdFire CPU kernel clk handling 5 * 6 * Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com) 7 */ 8 9 /***************************************************************************/ 10 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/mutex.h> 15 #include <linux/clk.h> 16 #include <linux/io.h> 17 #include <linux/err.h> 18 #include <asm/coldfire.h> 19 #include <asm/mcfsim.h> 20 #include <asm/mcfclk.h> 21 22 static DEFINE_SPINLOCK(clk_lock); 23 24 #ifdef MCFPM_PPMCR0 25 /* 26 * For more advanced ColdFire parts that have clocks that can be enabled 27 * we supply enable/disable functions. These must properly define their 28 * clocks in their platform specific code. 29 */ 30 void __clk_init_enabled(struct clk *clk) 31 { 32 clk->enabled = 1; 33 clk->clk_ops->enable(clk); 34 } 35 36 void __clk_init_disabled(struct clk *clk) 37 { 38 clk->enabled = 0; 39 clk->clk_ops->disable(clk); 40 } 41 42 static void __clk_enable0(struct clk *clk) 43 { 44 __raw_writeb(clk->slot, MCFPM_PPMCR0); 45 } 46 47 static void __clk_disable0(struct clk *clk) 48 { 49 __raw_writeb(clk->slot, MCFPM_PPMSR0); 50 } 51 52 struct clk_ops clk_ops0 = { 53 .enable = __clk_enable0, 54 .disable = __clk_disable0, 55 }; 56 57 #ifdef MCFPM_PPMCR1 58 static void __clk_enable1(struct clk *clk) 59 { 60 __raw_writeb(clk->slot, MCFPM_PPMCR1); 61 } 62 63 static void __clk_disable1(struct clk *clk) 64 { 65 __raw_writeb(clk->slot, MCFPM_PPMSR1); 66 } 67 68 struct clk_ops clk_ops1 = { 69 .enable = __clk_enable1, 70 .disable = __clk_disable1, 71 }; 72 #endif /* MCFPM_PPMCR1 */ 73 #endif /* MCFPM_PPMCR0 */ 74 75 struct clk *clk_get(struct device *dev, const char *id) 76 { 77 const char *clk_name = dev ? dev_name(dev) : id ? id : NULL; 78 struct clk *clk; 79 unsigned i; 80 81 for (i = 0; (clk = mcf_clks[i]) != NULL; ++i) 82 if (!strcmp(clk->name, clk_name)) 83 return clk; 84 pr_warn("clk_get: didn't find clock %s\n", clk_name); 85 return ERR_PTR(-ENOENT); 86 } 87 EXPORT_SYMBOL(clk_get); 88 89 int clk_enable(struct clk *clk) 90 { 91 unsigned long flags; 92 spin_lock_irqsave(&clk_lock, flags); 93 if ((clk->enabled++ == 0) && clk->clk_ops) 94 clk->clk_ops->enable(clk); 95 spin_unlock_irqrestore(&clk_lock, flags); 96 97 return 0; 98 } 99 EXPORT_SYMBOL(clk_enable); 100 101 void clk_disable(struct clk *clk) 102 { 103 unsigned long flags; 104 105 if (!clk) 106 return; 107 108 spin_lock_irqsave(&clk_lock, flags); 109 if ((--clk->enabled == 0) && clk->clk_ops) 110 clk->clk_ops->disable(clk); 111 spin_unlock_irqrestore(&clk_lock, flags); 112 } 113 EXPORT_SYMBOL(clk_disable); 114 115 void clk_put(struct clk *clk) 116 { 117 if (clk->enabled != 0) 118 pr_warn("clk_put %s still enabled\n", clk->name); 119 } 120 EXPORT_SYMBOL(clk_put); 121 122 unsigned long clk_get_rate(struct clk *clk) 123 { 124 if (!clk) 125 return 0; 126 127 return clk->rate; 128 } 129 EXPORT_SYMBOL(clk_get_rate); 130 131 /***************************************************************************/ 132