1
2
3
4
5
6
7
8
9
10
11
12
13#undef DEBUG
14
15#include <linux/kernel.h>
16#include <linux/spinlock.h>
17#include <linux/of_platform.h>
18#include <asm/io.h>
19#include <asm/prom.h>
20#include <asm/mpc52xx.h>
21
22
23static struct of_device_id mpc52xx_xlb_ids[] __initdata = {
24 { .compatible = "fsl,mpc5200-xlb", },
25 { .compatible = "mpc5200-xlb", },
26 {}
27};
28static struct of_device_id mpc52xx_bus_ids[] __initdata = {
29 { .compatible = "fsl,mpc5200-immr", },
30 { .compatible = "fsl,mpc5200b-immr", },
31 { .compatible = "fsl,lpb", },
32
33
34 { .type = "builtin", .compatible = "mpc5200", },
35 { .type = "soc", .compatible = "mpc5200", },
36 {}
37};
38
39
40
41
42
43
44
45static spinlock_t mpc52xx_lock = SPIN_LOCK_UNLOCKED;
46static struct mpc52xx_gpt __iomem *mpc52xx_wdt;
47static struct mpc52xx_cdm __iomem *mpc52xx_cdm;
48
49
50
51
52
53
54
55unsigned int
56mpc52xx_find_ipb_freq(struct device_node *node)
57{
58 struct device_node *np;
59 const unsigned int *p_ipb_freq = NULL;
60
61 of_node_get(node);
62 while (node) {
63 p_ipb_freq = of_get_property(node, "bus-frequency", NULL);
64 if (p_ipb_freq)
65 break;
66
67 np = of_get_parent(node);
68 of_node_put(node);
69 node = np;
70 }
71 if (node)
72 of_node_put(node);
73
74 return p_ipb_freq ? *p_ipb_freq : 0;
75}
76EXPORT_SYMBOL(mpc52xx_find_ipb_freq);
77
78
79
80
81
82void __init
83mpc5200_setup_xlb_arbiter(void)
84{
85 struct device_node *np;
86 struct mpc52xx_xlb __iomem *xlb;
87
88 np = of_find_matching_node(NULL, mpc52xx_xlb_ids);
89 xlb = of_iomap(np, 0);
90 of_node_put(np);
91 if (!xlb) {
92 printk(KERN_ERR __FILE__ ": "
93 "Error mapping XLB in mpc52xx_setup_cpu(). "
94 "Expect some abnormal behavior\n");
95 return;
96 }
97
98
99 out_be32(&xlb->master_pri_enable, 0xff);
100 out_be32(&xlb->master_priority, 0x11111111);
101
102
103
104
105
106
107
108 if ((mfspr(SPRN_SVR) & MPC5200_SVR_MASK) == MPC5200_SVR)
109 out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS);
110
111 iounmap(xlb);
112}
113
114
115
116
117
118
119void __init
120mpc52xx_declare_of_platform_devices(void)
121{
122
123 if (of_platform_bus_probe(NULL, mpc52xx_bus_ids, NULL))
124 printk(KERN_ERR __FILE__ ": "
125 "Error while probing of_platform bus\n");
126}
127
128
129
130
131static struct of_device_id mpc52xx_gpt_ids[] __initdata = {
132 { .compatible = "fsl,mpc5200-gpt", },
133 { .compatible = "mpc5200-gpt", },
134 {}
135};
136static struct of_device_id mpc52xx_cdm_ids[] __initdata = {
137 { .compatible = "fsl,mpc5200-cdm", },
138 { .compatible = "mpc5200-cdm", },
139 {}
140};
141
142
143
144
145void __init
146mpc52xx_map_common_devices(void)
147{
148 struct device_node *np;
149
150
151
152
153
154 for_each_matching_node(np, mpc52xx_gpt_ids) {
155 if (of_get_property(np, "fsl,has-wdt", NULL) ||
156 of_get_property(np, "has-wdt", NULL)) {
157 mpc52xx_wdt = of_iomap(np, 0);
158 of_node_put(np);
159 break;
160 }
161 }
162
163
164 np = of_find_matching_node(NULL, mpc52xx_cdm_ids);
165 mpc52xx_cdm = of_iomap(np, 0);
166 of_node_put(np);
167}
168
169
170
171
172
173
174
175int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv)
176{
177 unsigned long flags;
178 u16 __iomem *reg;
179 u32 val;
180 u32 mask;
181 u32 mclken_div;
182
183 if (!mpc52xx_cdm)
184 return -ENODEV;
185
186 mclken_div = 0x8000 | (clkdiv & 0x1FF);
187 switch (psc_id) {
188 case 1: reg = &mpc52xx_cdm->mclken_div_psc1; mask = 0x20; break;
189 case 2: reg = &mpc52xx_cdm->mclken_div_psc2; mask = 0x40; break;
190 case 3: reg = &mpc52xx_cdm->mclken_div_psc3; mask = 0x80; break;
191 case 6: reg = &mpc52xx_cdm->mclken_div_psc6; mask = 0x10; break;
192 default:
193 return -ENODEV;
194 }
195
196
197 spin_lock_irqsave(&mpc52xx_lock, flags);
198 out_be16(reg, mclken_div);
199 val = in_be32(&mpc52xx_cdm->clk_enables);
200 out_be32(&mpc52xx_cdm->clk_enables, val | mask);
201 spin_unlock_irqrestore(&mpc52xx_lock, flags);
202
203 return 0;
204}
205EXPORT_SYMBOL(mpc52xx_set_psc_clkdiv);
206
207
208
209
210void
211mpc52xx_restart(char *cmd)
212{
213 local_irq_disable();
214
215
216
217 if (mpc52xx_wdt) {
218 out_be32(&mpc52xx_wdt->mode, 0x00000000);
219 out_be32(&mpc52xx_wdt->count, 0x000000ff);
220 out_be32(&mpc52xx_wdt->mode, 0x00009004);
221 } else
222 printk(KERN_ERR __FILE__ ": "
223 "mpc52xx_restart: Can't access wdt. "
224 "Restart impossible, system halted.\n");
225
226 while (1);
227}
228