aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Baatz <gmbnomis@gmail.com>2012-07-06 14:42:38 -0400
committerAndrew Lunn <andrew@lunn.ch>2012-07-25 10:51:10 -0400
commitb5409430ffaef1ed282d20cab868ee692df6dbff (patch)
treec71c5551df6d229dd5a7b64e8a6c876a3d97f726
parentf479db44d2e3d4a969897e1f5e331e5ed4ac4968 (diff)
ARM: Kirkwood: Fix PHY disable clk problems
Commit 98d9986 (ARM: Kirkwood: Replace clock gating) and the fix 5fb2ce (ARM: Kirkwood: clk_register_gate_fn: add fn assignment) introduced a custom variant of clock gating which allows to define a function to be called before gating the clock off. This is used to disable the SATA and PCIe PHYs if the respective clocks are unused after initialization. However, of these two drivers, the SATA driver may be compiled as a module. The driver re-enables the clocks at module init but the PHYs stay disabled. Since the custom clock gating disabled the PHYs when gating the clock off, it should also re-enable them when enabling the clock gate. This is done by adding a second function that may be used to enable the PHYs. Signed-off-by: Simon Baatz <gmbnomis@gmail.com> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
-rw-r--r--arch/arm/mach-kirkwood/common.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 3de2d6df58e1..c9201539ffbd 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -67,6 +67,14 @@ void __init kirkwood_map_io(void)
67 * CLK tree 67 * CLK tree
68 ****************************************************************************/ 68 ****************************************************************************/
69 69
70static void enable_sata0(void)
71{
72 /* Enable PLL and IVREF */
73 writel(readl(SATA0_PHY_MODE_2) | 0xf, SATA0_PHY_MODE_2);
74 /* Enable PHY */
75 writel(readl(SATA0_IF_CTRL) & ~0x200, SATA0_IF_CTRL);
76}
77
70static void disable_sata0(void) 78static void disable_sata0(void)
71{ 79{
72 /* Disable PLL and IVREF */ 80 /* Disable PLL and IVREF */
@@ -75,6 +83,14 @@ static void disable_sata0(void)
75 writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL); 83 writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
76} 84}
77 85
86static void enable_sata1(void)
87{
88 /* Enable PLL and IVREF */
89 writel(readl(SATA1_PHY_MODE_2) | 0xf, SATA1_PHY_MODE_2);
90 /* Enable PHY */
91 writel(readl(SATA1_IF_CTRL) & ~0x200, SATA1_IF_CTRL);
92}
93
78static void disable_sata1(void) 94static void disable_sata1(void)
79{ 95{
80 /* Disable PLL and IVREF */ 96 /* Disable PLL and IVREF */
@@ -107,23 +123,38 @@ static void disable_pcie1(void)
107 } 123 }
108} 124}
109 125
110/* An extended version of the gated clk. This calls fn() before 126/* An extended version of the gated clk. This calls fn_en()/fn_dis
111 * disabling the clock. We use this to turn off PHYs etc. */ 127 * before enabling/disabling the clock. We use this to turn on/off
128 * PHYs etc. */
112struct clk_gate_fn { 129struct clk_gate_fn {
113 struct clk_gate gate; 130 struct clk_gate gate;
114 void (*fn)(void); 131 void (*fn_en)(void);
132 void (*fn_dis)(void);
115}; 133};
116 134
117#define to_clk_gate_fn(_gate) container_of(_gate, struct clk_gate_fn, gate) 135#define to_clk_gate_fn(_gate) container_of(_gate, struct clk_gate_fn, gate)
118#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) 136#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
119 137
138static int clk_gate_fn_enable(struct clk_hw *hw)
139{
140 struct clk_gate *gate = to_clk_gate(hw);
141 struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
142 int ret;
143
144 ret = clk_gate_ops.enable(hw);
145 if (!ret && gate_fn->fn_en)
146 gate_fn->fn_en();
147
148 return ret;
149}
150
120static void clk_gate_fn_disable(struct clk_hw *hw) 151static void clk_gate_fn_disable(struct clk_hw *hw)
121{ 152{
122 struct clk_gate *gate = to_clk_gate(hw); 153 struct clk_gate *gate = to_clk_gate(hw);
123 struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate); 154 struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
124 155
125 if (gate_fn->fn) 156 if (gate_fn->fn_dis)
126 gate_fn->fn(); 157 gate_fn->fn_dis();
127 158
128 clk_gate_ops.disable(hw); 159 clk_gate_ops.disable(hw);
129} 160}
@@ -135,7 +166,7 @@ static struct clk __init *clk_register_gate_fn(struct device *dev,
135 const char *parent_name, unsigned long flags, 166 const char *parent_name, unsigned long flags,
136 void __iomem *reg, u8 bit_idx, 167 void __iomem *reg, u8 bit_idx,
137 u8 clk_gate_flags, spinlock_t *lock, 168 u8 clk_gate_flags, spinlock_t *lock,
138 void (*fn)(void)) 169 void (*fn_en)(void), void (*fn_dis)(void))
139{ 170{
140 struct clk_gate_fn *gate_fn; 171 struct clk_gate_fn *gate_fn;
141 struct clk *clk; 172 struct clk *clk;
@@ -159,11 +190,14 @@ static struct clk __init *clk_register_gate_fn(struct device *dev,
159 gate_fn->gate.flags = clk_gate_flags; 190 gate_fn->gate.flags = clk_gate_flags;
160 gate_fn->gate.lock = lock; 191 gate_fn->gate.lock = lock;
161 gate_fn->gate.hw.init = &init; 192 gate_fn->gate.hw.init = &init;
162 gate_fn->fn = fn; 193 gate_fn->fn_en = fn_en;
194 gate_fn->fn_dis = fn_dis;
163 195
164 /* ops is the gate ops, but with our disable function */ 196 /* ops is the gate ops, but with our enable/disable functions */
165 if (clk_gate_fn_ops.disable != clk_gate_fn_disable) { 197 if (clk_gate_fn_ops.enable != clk_gate_fn_enable ||
198 clk_gate_fn_ops.disable != clk_gate_fn_disable) {
166 clk_gate_fn_ops = clk_gate_ops; 199 clk_gate_fn_ops = clk_gate_ops;
200 clk_gate_fn_ops.enable = clk_gate_fn_enable;
167 clk_gate_fn_ops.disable = clk_gate_fn_disable; 201 clk_gate_fn_ops.disable = clk_gate_fn_disable;
168 } 202 }
169 203
@@ -187,11 +221,12 @@ static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
187 221
188static struct clk __init *kirkwood_register_gate_fn(const char *name, 222static struct clk __init *kirkwood_register_gate_fn(const char *name,
189 u8 bit_idx, 223 u8 bit_idx,
190 void (*fn)(void)) 224 void (*fn_en)(void),
225 void (*fn_dis)(void))
191{ 226{
192 return clk_register_gate_fn(NULL, name, "tclk", 0, 227 return clk_register_gate_fn(NULL, name, "tclk", 0,
193 (void __iomem *)CLOCK_GATING_CTRL, 228 (void __iomem *)CLOCK_GATING_CTRL,
194 bit_idx, 0, &gating_lock, fn); 229 bit_idx, 0, &gating_lock, fn_en, fn_dis);
195} 230}
196 231
197static struct clk *ge0, *ge1; 232static struct clk *ge0, *ge1;
@@ -208,18 +243,18 @@ void __init kirkwood_clk_init(void)
208 ge0 = kirkwood_register_gate("ge0", CGC_BIT_GE0); 243 ge0 = kirkwood_register_gate("ge0", CGC_BIT_GE0);
209 ge1 = kirkwood_register_gate("ge1", CGC_BIT_GE1); 244 ge1 = kirkwood_register_gate("ge1", CGC_BIT_GE1);
210 sata0 = kirkwood_register_gate_fn("sata0", CGC_BIT_SATA0, 245 sata0 = kirkwood_register_gate_fn("sata0", CGC_BIT_SATA0,
211 disable_sata0); 246 enable_sata0, disable_sata0);
212 sata1 = kirkwood_register_gate_fn("sata1", CGC_BIT_SATA1, 247 sata1 = kirkwood_register_gate_fn("sata1", CGC_BIT_SATA1,
213 disable_sata1); 248 enable_sata1, disable_sata1);
214 usb0 = kirkwood_register_gate("usb0", CGC_BIT_USB0); 249 usb0 = kirkwood_register_gate("usb0", CGC_BIT_USB0);
215 sdio = kirkwood_register_gate("sdio", CGC_BIT_SDIO); 250 sdio = kirkwood_register_gate("sdio", CGC_BIT_SDIO);
216 crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO); 251 crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO);
217 xor0 = kirkwood_register_gate("xor0", CGC_BIT_XOR0); 252 xor0 = kirkwood_register_gate("xor0", CGC_BIT_XOR0);
218 xor1 = kirkwood_register_gate("xor1", CGC_BIT_XOR1); 253 xor1 = kirkwood_register_gate("xor1", CGC_BIT_XOR1);
219 pex0 = kirkwood_register_gate_fn("pex0", CGC_BIT_PEX0, 254 pex0 = kirkwood_register_gate_fn("pex0", CGC_BIT_PEX0,
220 disable_pcie0); 255 NULL, disable_pcie0);
221 pex1 = kirkwood_register_gate_fn("pex1", CGC_BIT_PEX1, 256 pex1 = kirkwood_register_gate_fn("pex1", CGC_BIT_PEX1,
222 disable_pcie1); 257 NULL, disable_pcie1);
223 audio = kirkwood_register_gate("audio", CGC_BIT_AUDIO); 258 audio = kirkwood_register_gate("audio", CGC_BIT_AUDIO);
224 kirkwood_register_gate("tdm", CGC_BIT_TDM); 259 kirkwood_register_gate("tdm", CGC_BIT_TDM);
225 kirkwood_register_gate("tsu", CGC_BIT_TSU); 260 kirkwood_register_gate("tsu", CGC_BIT_TSU);