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 | int clk_enable(struct clk *clk) |
77 | { |
78 | unsigned long flags; |
79 | |
80 | if (!clk) |
81 | return 0; |
82 | |
83 | spin_lock_irqsave(&clk_lock, flags); |
84 | if ((clk->enabled++ == 0) && clk->clk_ops) |
85 | clk->clk_ops->enable(clk); |
86 | spin_unlock_irqrestore(lock: &clk_lock, flags); |
87 | |
88 | return 0; |
89 | } |
90 | EXPORT_SYMBOL(clk_enable); |
91 | |
92 | void clk_disable(struct clk *clk) |
93 | { |
94 | unsigned long flags; |
95 | |
96 | if (!clk) |
97 | return; |
98 | |
99 | spin_lock_irqsave(&clk_lock, flags); |
100 | if ((--clk->enabled == 0) && clk->clk_ops) |
101 | clk->clk_ops->disable(clk); |
102 | spin_unlock_irqrestore(lock: &clk_lock, flags); |
103 | } |
104 | EXPORT_SYMBOL(clk_disable); |
105 | |
106 | unsigned long clk_get_rate(struct clk *clk) |
107 | { |
108 | if (!clk) |
109 | return 0; |
110 | |
111 | return clk->rate; |
112 | } |
113 | EXPORT_SYMBOL(clk_get_rate); |
114 | |
115 | /* dummy functions, should not be called */ |
116 | long clk_round_rate(struct clk *clk, unsigned long rate) |
117 | { |
118 | WARN_ON(clk); |
119 | return 0; |
120 | } |
121 | EXPORT_SYMBOL(clk_round_rate); |
122 | |
123 | int clk_set_rate(struct clk *clk, unsigned long rate) |
124 | { |
125 | WARN_ON(clk); |
126 | return 0; |
127 | } |
128 | EXPORT_SYMBOL(clk_set_rate); |
129 | |
130 | int clk_set_parent(struct clk *clk, struct clk *parent) |
131 | { |
132 | WARN_ON(clk); |
133 | return 0; |
134 | } |
135 | EXPORT_SYMBOL(clk_set_parent); |
136 | |
137 | struct clk *clk_get_parent(struct clk *clk) |
138 | { |
139 | WARN_ON(clk); |
140 | return NULL; |
141 | } |
142 | EXPORT_SYMBOL(clk_get_parent); |
143 | |
144 | /***************************************************************************/ |
145 | |