Merge branch 'master' of /home/sam/kernel/linux-2.6/
[pandora-kernel.git] / arch / powerpc / sysdev / fsl_soc.c
1 /*
2  * FSL SoC setup code
3  *
4  * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5  *
6  * This program is free software; you can redistribute  it and/or modify it
7  * under  the terms of  the GNU General  Public License as published by the
8  * Free Software Foundation;  either version 2 of the  License, or (at your
9  * option) any later version.
10  */
11
12 #include <linux/stddef.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/major.h>
17 #include <linux/delay.h>
18 #include <linux/irq.h>
19 #include <linux/module.h>
20 #include <linux/device.h>
21 #include <linux/platform_device.h>
22 #include <linux/fsl_devices.h>
23
24 #include <asm/system.h>
25 #include <asm/atomic.h>
26 #include <asm/io.h>
27 #include <asm/irq.h>
28 #include <asm/prom.h>
29 #include <sysdev/fsl_soc.h>
30 #include <mm/mmu_decl.h>
31
32 static phys_addr_t immrbase = -1;
33
34 phys_addr_t get_immrbase(void)
35 {
36         struct device_node *soc;
37
38         if (immrbase != -1)
39                 return immrbase;
40
41         soc = of_find_node_by_type(NULL, "soc");
42         if (soc) {
43                 unsigned int size;
44                 void *prop = get_property(soc, "reg", &size);
45                 immrbase = of_translate_address(soc, prop);
46                 of_node_put(soc);
47         };
48
49         return immrbase;
50 }
51
52 EXPORT_SYMBOL(get_immrbase);
53
54 static int __init gfar_mdio_of_init(void)
55 {
56         struct device_node *np;
57         unsigned int i;
58         struct platform_device *mdio_dev;
59         struct resource res;
60         int ret;
61
62         for (np = NULL, i = 0;
63              (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL;
64              i++) {
65                 int k;
66                 struct device_node *child = NULL;
67                 struct gianfar_mdio_data mdio_data;
68
69                 memset(&res, 0, sizeof(res));
70                 memset(&mdio_data, 0, sizeof(mdio_data));
71
72                 ret = of_address_to_resource(np, 0, &res);
73                 if (ret)
74                         goto err;
75
76                 mdio_dev =
77                     platform_device_register_simple("fsl-gianfar_mdio",
78                                                     res.start, &res, 1);
79                 if (IS_ERR(mdio_dev)) {
80                         ret = PTR_ERR(mdio_dev);
81                         goto err;
82                 }
83
84                 for (k = 0; k < 32; k++)
85                         mdio_data.irq[k] = -1;
86
87                 while ((child = of_get_next_child(np, child)) != NULL) {
88                         if (child->n_intrs) {
89                                 u32 *id =
90                                     (u32 *) get_property(child, "reg", NULL);
91                                 mdio_data.irq[*id] = child->intrs[0].line;
92                         }
93                 }
94
95                 ret =
96                     platform_device_add_data(mdio_dev, &mdio_data,
97                                              sizeof(struct gianfar_mdio_data));
98                 if (ret)
99                         goto unreg;
100         }
101
102         return 0;
103
104 unreg:
105         platform_device_unregister(mdio_dev);
106 err:
107         return ret;
108 }
109
110 arch_initcall(gfar_mdio_of_init);
111
112 static const char *gfar_tx_intr = "tx";
113 static const char *gfar_rx_intr = "rx";
114 static const char *gfar_err_intr = "error";
115
116 static int __init gfar_of_init(void)
117 {
118         struct device_node *np;
119         unsigned int i;
120         struct platform_device *gfar_dev;
121         struct resource res;
122         int ret;
123
124         for (np = NULL, i = 0;
125              (np = of_find_compatible_node(np, "network", "gianfar")) != NULL;
126              i++) {
127                 struct resource r[4];
128                 struct device_node *phy, *mdio;
129                 struct gianfar_platform_data gfar_data;
130                 unsigned int *id;
131                 char *model;
132                 void *mac_addr;
133                 phandle *ph;
134
135                 memset(r, 0, sizeof(r));
136                 memset(&gfar_data, 0, sizeof(gfar_data));
137
138                 ret = of_address_to_resource(np, 0, &r[0]);
139                 if (ret)
140                         goto err;
141
142                 r[1].start = np->intrs[0].line;
143                 r[1].end = np->intrs[0].line;
144                 r[1].flags = IORESOURCE_IRQ;
145
146                 model = get_property(np, "model", NULL);
147
148                 /* If we aren't the FEC we have multiple interrupts */
149                 if (model && strcasecmp(model, "FEC")) {
150                         r[1].name = gfar_tx_intr;
151
152                         r[2].name = gfar_rx_intr;
153                         r[2].start = np->intrs[1].line;
154                         r[2].end = np->intrs[1].line;
155                         r[2].flags = IORESOURCE_IRQ;
156
157                         r[3].name = gfar_err_intr;
158                         r[3].start = np->intrs[2].line;
159                         r[3].end = np->intrs[2].line;
160                         r[3].flags = IORESOURCE_IRQ;
161                 }
162
163                 gfar_dev =
164                     platform_device_register_simple("fsl-gianfar", i, &r[0],
165                                                     np->n_intrs + 1);
166
167                 if (IS_ERR(gfar_dev)) {
168                         ret = PTR_ERR(gfar_dev);
169                         goto err;
170                 }
171
172                 mac_addr = get_property(np, "address", NULL);
173                 memcpy(gfar_data.mac_addr, mac_addr, 6);
174
175                 if (model && !strcasecmp(model, "TSEC"))
176                         gfar_data.device_flags =
177                             FSL_GIANFAR_DEV_HAS_GIGABIT |
178                             FSL_GIANFAR_DEV_HAS_COALESCE |
179                             FSL_GIANFAR_DEV_HAS_RMON |
180                             FSL_GIANFAR_DEV_HAS_MULTI_INTR;
181                 if (model && !strcasecmp(model, "eTSEC"))
182                         gfar_data.device_flags =
183                             FSL_GIANFAR_DEV_HAS_GIGABIT |
184                             FSL_GIANFAR_DEV_HAS_COALESCE |
185                             FSL_GIANFAR_DEV_HAS_RMON |
186                             FSL_GIANFAR_DEV_HAS_MULTI_INTR |
187                             FSL_GIANFAR_DEV_HAS_CSUM |
188                             FSL_GIANFAR_DEV_HAS_VLAN |
189                             FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
190
191                 ph = (phandle *) get_property(np, "phy-handle", NULL);
192                 phy = of_find_node_by_phandle(*ph);
193
194                 if (phy == NULL) {
195                         ret = -ENODEV;
196                         goto unreg;
197                 }
198
199                 mdio = of_get_parent(phy);
200
201                 id = (u32 *) get_property(phy, "reg", NULL);
202                 ret = of_address_to_resource(mdio, 0, &res);
203                 if (ret) {
204                         of_node_put(phy);
205                         of_node_put(mdio);
206                         goto unreg;
207                 }
208
209                 gfar_data.phy_id = *id;
210                 gfar_data.bus_id = res.start;
211
212                 of_node_put(phy);
213                 of_node_put(mdio);
214
215                 ret =
216                     platform_device_add_data(gfar_dev, &gfar_data,
217                                              sizeof(struct
218                                                     gianfar_platform_data));
219                 if (ret)
220                         goto unreg;
221         }
222
223         return 0;
224
225 unreg:
226         platform_device_unregister(gfar_dev);
227 err:
228         return ret;
229 }
230
231 arch_initcall(gfar_of_init);
232
233 static int __init fsl_i2c_of_init(void)
234 {
235         struct device_node *np;
236         unsigned int i;
237         struct platform_device *i2c_dev;
238         int ret;
239
240         for (np = NULL, i = 0;
241              (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
242              i++) {
243                 struct resource r[2];
244                 struct fsl_i2c_platform_data i2c_data;
245                 unsigned char *flags = NULL;
246
247                 memset(&r, 0, sizeof(r));
248                 memset(&i2c_data, 0, sizeof(i2c_data));
249
250                 ret = of_address_to_resource(np, 0, &r[0]);
251                 if (ret)
252                         goto err;
253
254                 r[1].start = np->intrs[0].line;
255                 r[1].end = np->intrs[0].line;
256                 r[1].flags = IORESOURCE_IRQ;
257
258                 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
259                 if (IS_ERR(i2c_dev)) {
260                         ret = PTR_ERR(i2c_dev);
261                         goto err;
262                 }
263
264                 i2c_data.device_flags = 0;
265                 flags = get_property(np, "dfsrr", NULL);
266                 if (flags)
267                         i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
268
269                 flags = get_property(np, "fsl5200-clocking", NULL);
270                 if (flags)
271                         i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
272
273                 ret =
274                     platform_device_add_data(i2c_dev, &i2c_data,
275                                              sizeof(struct
276                                                     fsl_i2c_platform_data));
277                 if (ret)
278                         goto unreg;
279         }
280
281         return 0;
282
283 unreg:
284         platform_device_unregister(i2c_dev);
285 err:
286         return ret;
287 }
288
289 arch_initcall(fsl_i2c_of_init);
290
291 #ifdef CONFIG_PPC_83xx
292 static int __init mpc83xx_wdt_init(void)
293 {
294         struct resource r;
295         struct device_node *soc, *np;
296         struct platform_device *dev;
297         unsigned int *freq;
298         int ret;
299
300         np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
301
302         if (!np) {
303                 ret = -ENODEV;
304                 goto nodev;
305         }
306
307         soc = of_find_node_by_type(NULL, "soc");
308
309         if (!soc) {
310                 ret = -ENODEV;
311                 goto nosoc;
312         }
313
314         freq = (unsigned int *)get_property(soc, "bus-frequency", NULL);
315         if (!freq) {
316                 ret = -ENODEV;
317                 goto err;
318         }
319
320         memset(&r, 0, sizeof(r));
321
322         ret = of_address_to_resource(np, 0, &r);
323         if (ret)
324                 goto err;
325
326         dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
327         if (IS_ERR(dev)) {
328                 ret = PTR_ERR(dev);
329                 goto err;
330         }
331
332         ret = platform_device_add_data(dev, freq, sizeof(int));
333         if (ret)
334                 goto unreg;
335
336         of_node_put(soc);
337         of_node_put(np);
338
339         return 0;
340
341 unreg:
342         platform_device_unregister(dev);
343 err:
344         of_node_put(soc);
345 nosoc:
346         of_node_put(np);
347 nodev:
348         return ret;
349 }
350
351 arch_initcall(mpc83xx_wdt_init);
352 #endif
353
354 static enum fsl_usb2_phy_modes determine_usb_phy(char * phy_type)
355 {
356         if (!phy_type)
357                 return FSL_USB2_PHY_NONE;
358         if (!strcasecmp(phy_type, "ulpi"))
359                 return FSL_USB2_PHY_ULPI;
360         if (!strcasecmp(phy_type, "utmi"))
361                 return FSL_USB2_PHY_UTMI;
362         if (!strcasecmp(phy_type, "utmi_wide"))
363                 return FSL_USB2_PHY_UTMI_WIDE;
364         if (!strcasecmp(phy_type, "serial"))
365                 return FSL_USB2_PHY_SERIAL;
366
367         return FSL_USB2_PHY_NONE;
368 }
369
370 static int __init fsl_usb_of_init(void)
371 {
372         struct device_node *np;
373         unsigned int i;
374         struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL;
375         int ret;
376
377         for (np = NULL, i = 0;
378              (np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL;
379              i++) {
380                 struct resource r[2];
381                 struct fsl_usb2_platform_data usb_data;
382                 unsigned char *prop = NULL;
383
384                 memset(&r, 0, sizeof(r));
385                 memset(&usb_data, 0, sizeof(usb_data));
386
387                 ret = of_address_to_resource(np, 0, &r[0]);
388                 if (ret)
389                         goto err;
390
391                 r[1].start = np->intrs[0].line;
392                 r[1].end = np->intrs[0].line;
393                 r[1].flags = IORESOURCE_IRQ;
394
395                 usb_dev_mph =
396                     platform_device_register_simple("fsl-ehci", i, r, 2);
397                 if (IS_ERR(usb_dev_mph)) {
398                         ret = PTR_ERR(usb_dev_mph);
399                         goto err;
400                 }
401
402                 usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
403                 usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
404
405                 usb_data.operating_mode = FSL_USB2_MPH_HOST;
406
407                 prop = get_property(np, "port0", NULL);
408                 if (prop)
409                         usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
410
411                 prop = get_property(np, "port1", NULL);
412                 if (prop)
413                         usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
414
415                 prop = get_property(np, "phy_type", NULL);
416                 usb_data.phy_mode = determine_usb_phy(prop);
417
418                 ret =
419                     platform_device_add_data(usb_dev_mph, &usb_data,
420                                              sizeof(struct
421                                                     fsl_usb2_platform_data));
422                 if (ret)
423                         goto unreg_mph;
424         }
425
426         for (np = NULL;
427              (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL;
428              i++) {
429                 struct resource r[2];
430                 struct fsl_usb2_platform_data usb_data;
431                 unsigned char *prop = NULL;
432
433                 memset(&r, 0, sizeof(r));
434                 memset(&usb_data, 0, sizeof(usb_data));
435
436                 ret = of_address_to_resource(np, 0, &r[0]);
437                 if (ret)
438                         goto unreg_mph;
439
440                 r[1].start = np->intrs[0].line;
441                 r[1].end = np->intrs[0].line;
442                 r[1].flags = IORESOURCE_IRQ;
443
444                 usb_dev_dr =
445                     platform_device_register_simple("fsl-ehci", i, r, 2);
446                 if (IS_ERR(usb_dev_dr)) {
447                         ret = PTR_ERR(usb_dev_dr);
448                         goto err;
449                 }
450
451                 usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL;
452                 usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask;
453
454                 usb_data.operating_mode = FSL_USB2_DR_HOST;
455
456                 prop = get_property(np, "phy_type", NULL);
457                 usb_data.phy_mode = determine_usb_phy(prop);
458
459                 ret =
460                     platform_device_add_data(usb_dev_dr, &usb_data,
461                                              sizeof(struct
462                                                     fsl_usb2_platform_data));
463                 if (ret)
464                         goto unreg_dr;
465         }
466         return 0;
467
468 unreg_dr:
469         if (usb_dev_dr)
470                 platform_device_unregister(usb_dev_dr);
471 unreg_mph:
472         if (usb_dev_mph)
473                 platform_device_unregister(usb_dev_mph);
474 err:
475         return ret;
476 }
477
478 arch_initcall(fsl_usb_of_init);