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