1
2
3
4
5
6
7
8
9
10
11
12
13#undef DEBUG
14
15#include <linux/gpio.h>
16#include <linux/kernel.h>
17#include <linux/spinlock.h>
18#include <linux/of_platform.h>
19#include <linux/of_gpio.h>
20#include <linux/export.h>
21#include <asm/io.h>
22#include <asm/prom.h>
23#include <asm/mpc52xx.h>
24
25
26static const struct of_device_id mpc52xx_xlb_ids[] __initconst = {
27 { .compatible = "fsl,mpc5200-xlb", },
28 { .compatible = "mpc5200-xlb", },
29 {}
30};
31static const struct of_device_id mpc52xx_bus_ids[] __initconst = {
32 { .compatible = "fsl,mpc5200-immr", },
33 { .compatible = "fsl,mpc5200b-immr", },
34 { .compatible = "simple-bus", },
35
36
37 { .compatible = "fsl,lpb", },
38 { .type = "builtin", .compatible = "mpc5200", },
39 { .type = "soc", .compatible = "mpc5200", },
40 {}
41};
42
43
44
45
46
47
48
49static DEFINE_SPINLOCK(mpc52xx_lock);
50static struct mpc52xx_gpt __iomem *mpc52xx_wdt;
51static struct mpc52xx_cdm __iomem *mpc52xx_cdm;
52
53
54
55
56void __init
57mpc5200_setup_xlb_arbiter(void)
58{
59 struct device_node *np;
60 struct mpc52xx_xlb __iomem *xlb;
61
62 np = of_find_matching_node(NULL, mpc52xx_xlb_ids);
63 xlb = of_iomap(np, 0);
64 of_node_put(np);
65 if (!xlb) {
66 printk(KERN_ERR __FILE__ ": "
67 "Error mapping XLB in mpc52xx_setup_cpu(). "
68 "Expect some abnormal behavior\n");
69 return;
70 }
71
72
73 out_be32(&xlb->master_pri_enable, 0xff);
74 out_be32(&xlb->master_priority, 0x11111111);
75
76
77
78
79
80
81
82 if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
83 out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
84
85 iounmap(xlb);
86}
87
88
89
90
91
92static DEFINE_SPINLOCK(gpio_lock);
93struct mpc52xx_gpio __iomem *simple_gpio;
94struct mpc52xx_gpio_wkup __iomem *wkup_gpio;
95
96
97
98
99
100
101void __init mpc52xx_declare_of_platform_devices(void)
102{
103
104 if (of_platform_populate(NULL, mpc52xx_bus_ids, NULL, NULL))
105 pr_err(__FILE__ ": Error while populating devices from DT\n");
106}
107
108
109
110
111static const struct of_device_id mpc52xx_gpt_ids[] __initconst = {
112 { .compatible = "fsl,mpc5200-gpt", },
113 { .compatible = "mpc5200-gpt", },
114 {}
115};
116static const struct of_device_id mpc52xx_cdm_ids[] __initconst = {
117 { .compatible = "fsl,mpc5200-cdm", },
118 { .compatible = "mpc5200-cdm", },
119 {}
120};
121static const struct of_device_id mpc52xx_gpio_simple[] __initconst = {
122 { .compatible = "fsl,mpc5200-gpio", },
123 {}
124};
125static const struct of_device_id mpc52xx_gpio_wkup[] __initconst = {
126 { .compatible = "fsl,mpc5200-gpio-wkup", },
127 {}
128};
129
130
131
132
133
134void __init
135mpc52xx_map_common_devices(void)
136{
137 struct device_node *np;
138
139
140
141
142
143 for_each_matching_node(np, mpc52xx_gpt_ids) {
144 if (of_get_property(np, "fsl,has-wdt", NULL) ||
145 of_get_property(np, "has-wdt", NULL)) {
146 mpc52xx_wdt = of_iomap(np, 0);
147 of_node_put(np);
148 break;
149 }
150 }
151
152
153 np = of_find_matching_node(NULL, mpc52xx_cdm_ids);
154 mpc52xx_cdm = of_iomap(np, 0);
155 of_node_put(np);
156
157
158 np = of_find_matching_node(NULL, mpc52xx_gpio_simple);
159 simple_gpio = of_iomap(np, 0);
160 of_node_put(np);
161
162
163 np = of_find_matching_node(NULL, mpc52xx_gpio_wkup);
164 wkup_gpio = of_iomap(np, 0);
165 of_node_put(np);
166}
167
168
169
170
171
172
173
174int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv)
175{
176 unsigned long flags;
177 u16 __iomem *reg;
178 u32 val;
179 u32 mask;
180 u32 mclken_div;
181
182 if (!mpc52xx_cdm)
183 return -ENODEV;
184
185 mclken_div = 0x8000 | (clkdiv & 0x1FF);
186 switch (psc_id) {
187 case 1: reg = &mpc52xx_cdm->mclken_div_psc1; mask = 0x20; break;
188 case 2: reg = &mpc52xx_cdm->mclken_div_psc2; mask = 0x40; break;
189 case 3: reg = &mpc52xx_cdm->mclken_div_psc3; mask = 0x80; break;
190 case 6: reg = &mpc52xx_cdm->mclken_div_psc6; mask = 0x10; break;
191 default:
192 return -ENODEV;
193 }
194
195
196 spin_lock_irqsave(&mpc52xx_lock, flags);
197 out_be16(reg, mclken_div);
198 val = in_be32(&mpc52xx_cdm->clk_enables);
199 out_be32(&mpc52xx_cdm->clk_enables, val | mask);
200 spin_unlock_irqrestore(&mpc52xx_lock, flags);
201
202 return 0;
203}
204EXPORT_SYMBOL(mpc52xx_set_psc_clkdiv);
205
206
207
208
209
210
211
212
213
214unsigned int mpc52xx_get_xtal_freq(struct device_node *node)
215{
216 u32 val;
217 unsigned int freq;
218
219 if (!mpc52xx_cdm)
220 return 0;
221
222 freq = mpc5xxx_get_bus_frequency(node);
223 if (!freq)
224 return 0;
225
226 if (in_8(&mpc52xx_cdm->ipb_clk_sel) & 0x1)
227 freq *= 2;
228
229 val = in_be32(&mpc52xx_cdm->rstcfg);
230 if (val & (1 << 5))
231 freq *= 8;
232 else
233 freq *= 4;
234 if (val & (1 << 6))
235 freq /= 12;
236 else
237 freq /= 16;
238
239 return freq;
240}
241EXPORT_SYMBOL(mpc52xx_get_xtal_freq);
242
243
244
245
246void __noreturn mpc52xx_restart(char *cmd)
247{
248 local_irq_disable();
249
250
251
252 if (mpc52xx_wdt) {
253 out_be32(&mpc52xx_wdt->mode, 0x00000000);
254 out_be32(&mpc52xx_wdt->count, 0x000000ff);
255 out_be32(&mpc52xx_wdt->mode, 0x00009004);
256 } else
257 printk(KERN_ERR __FILE__ ": "
258 "mpc52xx_restart: Can't access wdt. "
259 "Restart impossible, system halted.\n");
260
261 while (1);
262}
263
264#define PSC1_RESET 0x1
265#define PSC1_SYNC 0x4
266#define PSC1_SDATA_OUT 0x1
267#define PSC2_RESET 0x2
268#define PSC2_SYNC (0x4<<4)
269#define PSC2_SDATA_OUT (0x1<<4)
270#define MPC52xx_GPIO_PSC1_MASK 0x7
271#define MPC52xx_GPIO_PSC2_MASK (0x7<<4)
272
273
274
275
276
277
278int mpc5200_psc_ac97_gpio_reset(int psc_number)
279{
280 unsigned long flags;
281 u32 gpio;
282 u32 mux;
283 int out;
284 int reset;
285 int sync;
286
287 if ((!simple_gpio) || (!wkup_gpio))
288 return -ENODEV;
289
290 switch (psc_number) {
291 case 0:
292 reset = PSC1_RESET;
293 sync = PSC1_SYNC;
294 out = PSC1_SDATA_OUT;
295 gpio = MPC52xx_GPIO_PSC1_MASK;
296 break;
297 case 1:
298 reset = PSC2_RESET;
299 sync = PSC2_SYNC;
300 out = PSC2_SDATA_OUT;
301 gpio = MPC52xx_GPIO_PSC2_MASK;
302 break;
303 default:
304 pr_err(__FILE__ ": Unable to determine PSC, no ac97 "
305 "cold-reset will be performed\n");
306 return -ENODEV;
307 }
308
309 spin_lock_irqsave(&gpio_lock, flags);
310
311
312 mux = in_be32(&simple_gpio->port_config);
313 out_be32(&simple_gpio->port_config, mux & (~gpio));
314
315
316 setbits8(&wkup_gpio->wkup_gpioe, reset);
317 setbits32(&simple_gpio->simple_gpioe, sync | out);
318
319 setbits8(&wkup_gpio->wkup_ddr, reset);
320 setbits32(&simple_gpio->simple_ddr, sync | out);
321
322
323 clrbits32(&simple_gpio->simple_dvo, sync | out);
324 clrbits8(&wkup_gpio->wkup_dvo, reset);
325
326
327 udelay(1);
328
329
330 setbits8(&wkup_gpio->wkup_dvo, reset);
331
332
333
334 __delay(7);
335
336
337 out_be32(&simple_gpio->port_config, mux);
338
339 spin_unlock_irqrestore(&gpio_lock, flags);
340
341 return 0;
342}
343EXPORT_SYMBOL(mpc5200_psc_ac97_gpio_reset);
344