Merge git://git.infradead.org/~dwmw2/hdroneline
[linux-2.6] / 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                 const 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                         const u32 *id = get_property(child, "reg", NULL);
89                         mdio_data.irq[*id] = irq_of_parse_and_map(child, 0);
90                 }
91
92                 ret =
93                     platform_device_add_data(mdio_dev, &mdio_data,
94                                              sizeof(struct gianfar_mdio_data));
95                 if (ret)
96                         goto unreg;
97         }
98
99         return 0;
100
101 unreg:
102         platform_device_unregister(mdio_dev);
103 err:
104         return ret;
105 }
106
107 arch_initcall(gfar_mdio_of_init);
108
109 static const char *gfar_tx_intr = "tx";
110 static const char *gfar_rx_intr = "rx";
111 static const char *gfar_err_intr = "error";
112
113 static int __init gfar_of_init(void)
114 {
115         struct device_node *np;
116         unsigned int i;
117         struct platform_device *gfar_dev;
118         struct resource res;
119         int ret;
120
121         for (np = NULL, i = 0;
122              (np = of_find_compatible_node(np, "network", "gianfar")) != NULL;
123              i++) {
124                 struct resource r[4];
125                 struct device_node *phy, *mdio;
126                 struct gianfar_platform_data gfar_data;
127                 const unsigned int *id;
128                 const char *model;
129                 const void *mac_addr;
130                 const phandle *ph;
131                 int n_res = 1;
132
133                 memset(r, 0, sizeof(r));
134                 memset(&gfar_data, 0, sizeof(gfar_data));
135
136                 ret = of_address_to_resource(np, 0, &r[0]);
137                 if (ret)
138                         goto err;
139
140                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
141                 r[1].flags = IORESOURCE_IRQ;
142
143                 model = get_property(np, "model", NULL);
144
145                 /* If we aren't the FEC we have multiple interrupts */
146                 if (model && strcasecmp(model, "FEC")) {
147                         r[1].name = gfar_tx_intr;
148
149                         r[2].name = gfar_rx_intr;
150                         r[2].start = r[2].end = irq_of_parse_and_map(np, 1);
151                         r[2].flags = IORESOURCE_IRQ;
152
153                         r[3].name = gfar_err_intr;
154                         r[3].start = r[3].end = irq_of_parse_and_map(np, 2);
155                         r[3].flags = IORESOURCE_IRQ;
156
157                         n_res += 2;
158                 }
159
160                 gfar_dev =
161                     platform_device_register_simple("fsl-gianfar", i, &r[0],
162                                                     n_res + 1);
163
164                 if (IS_ERR(gfar_dev)) {
165                         ret = PTR_ERR(gfar_dev);
166                         goto err;
167                 }
168
169                 mac_addr = get_property(np, "local-mac-address", NULL);
170                 if (mac_addr == NULL)
171                         mac_addr = get_property(np, "mac-address", NULL);
172                 if (mac_addr == NULL) {
173                         /* Obsolete */
174                         mac_addr = get_property(np, "address", NULL);
175                 }
176
177                 if (mac_addr)
178                         memcpy(gfar_data.mac_addr, mac_addr, 6);
179
180                 if (model && !strcasecmp(model, "TSEC"))
181                         gfar_data.device_flags =
182                             FSL_GIANFAR_DEV_HAS_GIGABIT |
183                             FSL_GIANFAR_DEV_HAS_COALESCE |
184                             FSL_GIANFAR_DEV_HAS_RMON |
185                             FSL_GIANFAR_DEV_HAS_MULTI_INTR;
186                 if (model && !strcasecmp(model, "eTSEC"))
187                         gfar_data.device_flags =
188                             FSL_GIANFAR_DEV_HAS_GIGABIT |
189                             FSL_GIANFAR_DEV_HAS_COALESCE |
190                             FSL_GIANFAR_DEV_HAS_RMON |
191                             FSL_GIANFAR_DEV_HAS_MULTI_INTR |
192                             FSL_GIANFAR_DEV_HAS_CSUM |
193                             FSL_GIANFAR_DEV_HAS_VLAN |
194                             FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
195
196                 ph = get_property(np, "phy-handle", NULL);
197                 phy = of_find_node_by_phandle(*ph);
198
199                 if (phy == NULL) {
200                         ret = -ENODEV;
201                         goto unreg;
202                 }
203
204                 mdio = of_get_parent(phy);
205
206                 id = get_property(phy, "reg", NULL);
207                 ret = of_address_to_resource(mdio, 0, &res);
208                 if (ret) {
209                         of_node_put(phy);
210                         of_node_put(mdio);
211                         goto unreg;
212                 }
213
214                 gfar_data.phy_id = *id;
215                 gfar_data.bus_id = res.start;
216
217                 of_node_put(phy);
218                 of_node_put(mdio);
219
220                 ret =
221                     platform_device_add_data(gfar_dev, &gfar_data,
222                                              sizeof(struct
223                                                     gianfar_platform_data));
224                 if (ret)
225                         goto unreg;
226         }
227
228         return 0;
229
230 unreg:
231         platform_device_unregister(gfar_dev);
232 err:
233         return ret;
234 }
235
236 arch_initcall(gfar_of_init);
237
238 static int __init fsl_i2c_of_init(void)
239 {
240         struct device_node *np;
241         unsigned int i;
242         struct platform_device *i2c_dev;
243         int ret;
244
245         for (np = NULL, i = 0;
246              (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
247              i++) {
248                 struct resource r[2];
249                 struct fsl_i2c_platform_data i2c_data;
250                 const unsigned char *flags = NULL;
251
252                 memset(&r, 0, sizeof(r));
253                 memset(&i2c_data, 0, sizeof(i2c_data));
254
255                 ret = of_address_to_resource(np, 0, &r[0]);
256                 if (ret)
257                         goto err;
258
259                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
260                 r[1].flags = IORESOURCE_IRQ;
261
262                 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
263                 if (IS_ERR(i2c_dev)) {
264                         ret = PTR_ERR(i2c_dev);
265                         goto err;
266                 }
267
268                 i2c_data.device_flags = 0;
269                 flags = get_property(np, "dfsrr", NULL);
270                 if (flags)
271                         i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
272
273                 flags = get_property(np, "fsl5200-clocking", NULL);
274                 if (flags)
275                         i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
276
277                 ret =
278                     platform_device_add_data(i2c_dev, &i2c_data,
279                                              sizeof(struct
280                                                     fsl_i2c_platform_data));
281                 if (ret)
282                         goto unreg;
283         }
284
285         return 0;
286
287 unreg:
288         platform_device_unregister(i2c_dev);
289 err:
290         return ret;
291 }
292
293 arch_initcall(fsl_i2c_of_init);
294
295 #ifdef CONFIG_PPC_83xx
296 static int __init mpc83xx_wdt_init(void)
297 {
298         struct resource r;
299         struct device_node *soc, *np;
300         struct platform_device *dev;
301         const unsigned int *freq;
302         int ret;
303
304         np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
305
306         if (!np) {
307                 ret = -ENODEV;
308                 goto nodev;
309         }
310
311         soc = of_find_node_by_type(NULL, "soc");
312
313         if (!soc) {
314                 ret = -ENODEV;
315                 goto nosoc;
316         }
317
318         freq = get_property(soc, "bus-frequency", NULL);
319         if (!freq) {
320                 ret = -ENODEV;
321                 goto err;
322         }
323
324         memset(&r, 0, sizeof(r));
325
326         ret = of_address_to_resource(np, 0, &r);
327         if (ret)
328                 goto err;
329
330         dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
331         if (IS_ERR(dev)) {
332                 ret = PTR_ERR(dev);
333                 goto err;
334         }
335
336         ret = platform_device_add_data(dev, freq, sizeof(int));
337         if (ret)
338                 goto unreg;
339
340         of_node_put(soc);
341         of_node_put(np);
342
343         return 0;
344
345 unreg:
346         platform_device_unregister(dev);
347 err:
348         of_node_put(soc);
349 nosoc:
350         of_node_put(np);
351 nodev:
352         return ret;
353 }
354
355 arch_initcall(mpc83xx_wdt_init);
356 #endif
357
358 static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
359 {
360         if (!phy_type)
361                 return FSL_USB2_PHY_NONE;
362         if (!strcasecmp(phy_type, "ulpi"))
363                 return FSL_USB2_PHY_ULPI;
364         if (!strcasecmp(phy_type, "utmi"))
365                 return FSL_USB2_PHY_UTMI;
366         if (!strcasecmp(phy_type, "utmi_wide"))
367                 return FSL_USB2_PHY_UTMI_WIDE;
368         if (!strcasecmp(phy_type, "serial"))
369                 return FSL_USB2_PHY_SERIAL;
370
371         return FSL_USB2_PHY_NONE;
372 }
373
374 static int __init fsl_usb_of_init(void)
375 {
376         struct device_node *np;
377         unsigned int i;
378         struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL;
379         int ret;
380
381         for (np = NULL, i = 0;
382              (np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL;
383              i++) {
384                 struct resource r[2];
385                 struct fsl_usb2_platform_data usb_data;
386                 const unsigned char *prop = NULL;
387
388                 memset(&r, 0, sizeof(r));
389                 memset(&usb_data, 0, sizeof(usb_data));
390
391                 ret = of_address_to_resource(np, 0, &r[0]);
392                 if (ret)
393                         goto err;
394
395                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
396                 r[1].flags = IORESOURCE_IRQ;
397
398                 usb_dev_mph =
399                     platform_device_register_simple("fsl-ehci", i, r, 2);
400                 if (IS_ERR(usb_dev_mph)) {
401                         ret = PTR_ERR(usb_dev_mph);
402                         goto err;
403                 }
404
405                 usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
406                 usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
407
408                 usb_data.operating_mode = FSL_USB2_MPH_HOST;
409
410                 prop = get_property(np, "port0", NULL);
411                 if (prop)
412                         usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
413
414                 prop = get_property(np, "port1", NULL);
415                 if (prop)
416                         usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
417
418                 prop = get_property(np, "phy_type", NULL);
419                 usb_data.phy_mode = determine_usb_phy(prop);
420
421                 ret =
422                     platform_device_add_data(usb_dev_mph, &usb_data,
423                                              sizeof(struct
424                                                     fsl_usb2_platform_data));
425                 if (ret)
426                         goto unreg_mph;
427         }
428
429         for (np = NULL;
430              (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL;
431              i++) {
432                 struct resource r[2];
433                 struct fsl_usb2_platform_data usb_data;
434                 const unsigned char *prop = NULL;
435
436                 memset(&r, 0, sizeof(r));
437                 memset(&usb_data, 0, sizeof(usb_data));
438
439                 ret = of_address_to_resource(np, 0, &r[0]);
440                 if (ret)
441                         goto unreg_mph;
442
443                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
444                 r[1].flags = IORESOURCE_IRQ;
445
446                 usb_dev_dr =
447                     platform_device_register_simple("fsl-ehci", i, r, 2);
448                 if (IS_ERR(usb_dev_dr)) {
449                         ret = PTR_ERR(usb_dev_dr);
450                         goto err;
451                 }
452
453                 usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL;
454                 usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask;
455
456                 usb_data.operating_mode = FSL_USB2_DR_HOST;
457
458                 prop = get_property(np, "phy_type", NULL);
459                 usb_data.phy_mode = determine_usb_phy(prop);
460
461                 ret =
462                     platform_device_add_data(usb_dev_dr, &usb_data,
463                                              sizeof(struct
464                                                     fsl_usb2_platform_data));
465                 if (ret)
466                         goto unreg_dr;
467         }
468         return 0;
469
470 unreg_dr:
471         if (usb_dev_dr)
472                 platform_device_unregister(usb_dev_dr);
473 unreg_mph:
474         if (usb_dev_mph)
475                 platform_device_unregister(usb_dev_mph);
476 err:
477         return ret;
478 }
479
480 arch_initcall(fsl_usb_of_init);