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