Merge ../linus
[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  * 2006 (c) MontaVista Software, Inc.
7  * Vitaly Bordug <vbordug@ru.mvista.com>
8  *
9  * This program is free software; you can redistribute  it and/or modify it
10  * under  the terms of  the GNU General  Public License as published by the
11  * Free Software Foundation;  either version 2 of the  License, or (at your
12  * option) any later version.
13  */
14
15 #include <linux/stddef.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/errno.h>
19 #include <linux/major.h>
20 #include <linux/delay.h>
21 #include <linux/irq.h>
22 #include <linux/module.h>
23 #include <linux/device.h>
24 #include <linux/platform_device.h>
25 #include <linux/phy.h>
26 #include <linux/fsl_devices.h>
27 #include <linux/fs_enet_pd.h>
28 #include <linux/fs_uart_pd.h>
29
30 #include <asm/system.h>
31 #include <asm/atomic.h>
32 #include <asm/io.h>
33 #include <asm/irq.h>
34 #include <asm/time.h>
35 #include <asm/prom.h>
36 #include <sysdev/fsl_soc.h>
37 #include <mm/mmu_decl.h>
38 #include <asm/cpm2.h>
39
40 extern void init_fcc_ioports(struct fs_platform_info*);
41 extern void init_scc_ioports(struct fs_uart_platform_info*);
42 static phys_addr_t immrbase = -1;
43
44 phys_addr_t get_immrbase(void)
45 {
46         struct device_node *soc;
47
48         if (immrbase != -1)
49                 return immrbase;
50
51         soc = of_find_node_by_type(NULL, "soc");
52         if (soc) {
53                 unsigned int size;
54                 const void *prop = get_property(soc, "reg", &size);
55
56                 if (prop)
57                         immrbase = of_translate_address(soc, prop);
58                 of_node_put(soc);
59         };
60
61         return immrbase;
62 }
63
64 EXPORT_SYMBOL(get_immrbase);
65
66 #ifdef CONFIG_CPM2
67
68 static u32 brgfreq = -1;
69
70 u32 get_brgfreq(void)
71 {
72         struct device_node *node;
73
74         if (brgfreq != -1)
75                 return brgfreq;
76
77         node = of_find_node_by_type(NULL, "cpm");
78         if (node) {
79                 unsigned int size;
80                 const unsigned int *prop = get_property(node, "brg-frequency",
81                                         &size);
82
83                 if (prop)
84                         brgfreq = *prop;
85                 of_node_put(node);
86         };
87
88         return brgfreq;
89 }
90
91 EXPORT_SYMBOL(get_brgfreq);
92
93 static u32 fs_baudrate = -1;
94
95 u32 get_baudrate(void)
96 {
97         struct device_node *node;
98
99         if (fs_baudrate != -1)
100                 return fs_baudrate;
101
102         node = of_find_node_by_type(NULL, "serial");
103         if (node) {
104                 unsigned int size;
105                 const unsigned int *prop = get_property(node, "current-speed",
106                                 &size);
107
108                 if (prop)
109                         fs_baudrate = *prop;
110                 of_node_put(node);
111         };
112
113         return fs_baudrate;
114 }
115
116 EXPORT_SYMBOL(get_baudrate);
117 #endif /* CONFIG_CPM2 */
118
119 static int __init gfar_mdio_of_init(void)
120 {
121         struct device_node *np;
122         unsigned int i;
123         struct platform_device *mdio_dev;
124         struct resource res;
125         int ret;
126
127         for (np = NULL, i = 0;
128              (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL;
129              i++) {
130                 int k;
131                 struct device_node *child = NULL;
132                 struct gianfar_mdio_data mdio_data;
133
134                 memset(&res, 0, sizeof(res));
135                 memset(&mdio_data, 0, sizeof(mdio_data));
136
137                 ret = of_address_to_resource(np, 0, &res);
138                 if (ret)
139                         goto err;
140
141                 mdio_dev =
142                     platform_device_register_simple("fsl-gianfar_mdio",
143                                                     res.start, &res, 1);
144                 if (IS_ERR(mdio_dev)) {
145                         ret = PTR_ERR(mdio_dev);
146                         goto err;
147                 }
148
149                 for (k = 0; k < 32; k++)
150                         mdio_data.irq[k] = PHY_POLL;
151
152                 while ((child = of_get_next_child(np, child)) != NULL) {
153                         int irq = irq_of_parse_and_map(child, 0);
154                         if (irq != NO_IRQ) {
155                                 const u32 *id = get_property(child, "reg", NULL);
156                                 mdio_data.irq[*id] = irq;
157                         }
158                 }
159
160                 ret =
161                     platform_device_add_data(mdio_dev, &mdio_data,
162                                              sizeof(struct gianfar_mdio_data));
163                 if (ret)
164                         goto unreg;
165         }
166
167         return 0;
168
169 unreg:
170         platform_device_unregister(mdio_dev);
171 err:
172         return ret;
173 }
174
175 arch_initcall(gfar_mdio_of_init);
176
177 static const char *gfar_tx_intr = "tx";
178 static const char *gfar_rx_intr = "rx";
179 static const char *gfar_err_intr = "error";
180
181
182 static int __init gfar_of_init(void)
183 {
184         struct device_node *np;
185         unsigned int i;
186         struct platform_device *gfar_dev;
187         struct resource res;
188         int ret;
189
190         for (np = NULL, i = 0;
191              (np = of_find_compatible_node(np, "network", "gianfar")) != NULL;
192              i++) {
193                 struct resource r[4];
194                 struct device_node *phy, *mdio;
195                 struct gianfar_platform_data gfar_data;
196                 const unsigned int *id;
197                 const char *model;
198                 const void *mac_addr;
199                 const phandle *ph;
200                 int n_res = 2;
201
202                 memset(r, 0, sizeof(r));
203                 memset(&gfar_data, 0, sizeof(gfar_data));
204
205                 ret = of_address_to_resource(np, 0, &r[0]);
206                 if (ret)
207                         goto err;
208
209                 of_irq_to_resource(np, 0, &r[1]);
210
211                 model = get_property(np, "model", NULL);
212
213                 /* If we aren't the FEC we have multiple interrupts */
214                 if (model && strcasecmp(model, "FEC")) {
215                         r[1].name = gfar_tx_intr;
216
217                         r[2].name = gfar_rx_intr;
218                         of_irq_to_resource(np, 1, &r[2]);
219
220                         r[3].name = gfar_err_intr;
221                         of_irq_to_resource(np, 2, &r[3]);
222
223                         n_res += 2;
224                 }
225
226                 gfar_dev =
227                     platform_device_register_simple("fsl-gianfar", i, &r[0],
228                                                     n_res);
229
230                 if (IS_ERR(gfar_dev)) {
231                         ret = PTR_ERR(gfar_dev);
232                         goto err;
233                 }
234
235                 mac_addr = get_property(np, "local-mac-address", NULL);
236                 if (mac_addr == NULL)
237                         mac_addr = get_property(np, "mac-address", NULL);
238                 if (mac_addr == NULL) {
239                         /* Obsolete */
240                         mac_addr = get_property(np, "address", NULL);
241                 }
242
243                 if (mac_addr)
244                         memcpy(gfar_data.mac_addr, mac_addr, 6);
245
246                 if (model && !strcasecmp(model, "TSEC"))
247                         gfar_data.device_flags =
248                             FSL_GIANFAR_DEV_HAS_GIGABIT |
249                             FSL_GIANFAR_DEV_HAS_COALESCE |
250                             FSL_GIANFAR_DEV_HAS_RMON |
251                             FSL_GIANFAR_DEV_HAS_MULTI_INTR;
252                 if (model && !strcasecmp(model, "eTSEC"))
253                         gfar_data.device_flags =
254                             FSL_GIANFAR_DEV_HAS_GIGABIT |
255                             FSL_GIANFAR_DEV_HAS_COALESCE |
256                             FSL_GIANFAR_DEV_HAS_RMON |
257                             FSL_GIANFAR_DEV_HAS_MULTI_INTR |
258                             FSL_GIANFAR_DEV_HAS_CSUM |
259                             FSL_GIANFAR_DEV_HAS_VLAN |
260                             FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
261
262                 ph = get_property(np, "phy-handle", NULL);
263                 phy = of_find_node_by_phandle(*ph);
264
265                 if (phy == NULL) {
266                         ret = -ENODEV;
267                         goto unreg;
268                 }
269
270                 mdio = of_get_parent(phy);
271
272                 id = get_property(phy, "reg", NULL);
273                 ret = of_address_to_resource(mdio, 0, &res);
274                 if (ret) {
275                         of_node_put(phy);
276                         of_node_put(mdio);
277                         goto unreg;
278                 }
279
280                 gfar_data.phy_id = *id;
281                 gfar_data.bus_id = res.start;
282
283                 of_node_put(phy);
284                 of_node_put(mdio);
285
286                 ret =
287                     platform_device_add_data(gfar_dev, &gfar_data,
288                                              sizeof(struct
289                                                     gianfar_platform_data));
290                 if (ret)
291                         goto unreg;
292         }
293
294         return 0;
295
296 unreg:
297         platform_device_unregister(gfar_dev);
298 err:
299         return ret;
300 }
301
302 arch_initcall(gfar_of_init);
303
304 static int __init fsl_i2c_of_init(void)
305 {
306         struct device_node *np;
307         unsigned int i;
308         struct platform_device *i2c_dev;
309         int ret;
310
311         for (np = NULL, i = 0;
312              (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
313              i++) {
314                 struct resource r[2];
315                 struct fsl_i2c_platform_data i2c_data;
316                 const unsigned char *flags = NULL;
317
318                 memset(&r, 0, sizeof(r));
319                 memset(&i2c_data, 0, sizeof(i2c_data));
320
321                 ret = of_address_to_resource(np, 0, &r[0]);
322                 if (ret)
323                         goto err;
324
325                 of_irq_to_resource(np, 0, &r[1]);
326
327                 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
328                 if (IS_ERR(i2c_dev)) {
329                         ret = PTR_ERR(i2c_dev);
330                         goto err;
331                 }
332
333                 i2c_data.device_flags = 0;
334                 flags = get_property(np, "dfsrr", NULL);
335                 if (flags)
336                         i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
337
338                 flags = get_property(np, "fsl5200-clocking", NULL);
339                 if (flags)
340                         i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
341
342                 ret =
343                     platform_device_add_data(i2c_dev, &i2c_data,
344                                              sizeof(struct
345                                                     fsl_i2c_platform_data));
346                 if (ret)
347                         goto unreg;
348         }
349
350         return 0;
351
352 unreg:
353         platform_device_unregister(i2c_dev);
354 err:
355         return ret;
356 }
357
358 arch_initcall(fsl_i2c_of_init);
359
360 #ifdef CONFIG_PPC_83xx
361 static int __init mpc83xx_wdt_init(void)
362 {
363         struct resource r;
364         struct device_node *soc, *np;
365         struct platform_device *dev;
366         const unsigned int *freq;
367         int ret;
368
369         np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
370
371         if (!np) {
372                 ret = -ENODEV;
373                 goto nodev;
374         }
375
376         soc = of_find_node_by_type(NULL, "soc");
377
378         if (!soc) {
379                 ret = -ENODEV;
380                 goto nosoc;
381         }
382
383         freq = get_property(soc, "bus-frequency", NULL);
384         if (!freq) {
385                 ret = -ENODEV;
386                 goto err;
387         }
388
389         memset(&r, 0, sizeof(r));
390
391         ret = of_address_to_resource(np, 0, &r);
392         if (ret)
393                 goto err;
394
395         dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
396         if (IS_ERR(dev)) {
397                 ret = PTR_ERR(dev);
398                 goto err;
399         }
400
401         ret = platform_device_add_data(dev, freq, sizeof(int));
402         if (ret)
403                 goto unreg;
404
405         of_node_put(soc);
406         of_node_put(np);
407
408         return 0;
409
410 unreg:
411         platform_device_unregister(dev);
412 err:
413         of_node_put(soc);
414 nosoc:
415         of_node_put(np);
416 nodev:
417         return ret;
418 }
419
420 arch_initcall(mpc83xx_wdt_init);
421 #endif
422
423 static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
424 {
425         if (!phy_type)
426                 return FSL_USB2_PHY_NONE;
427         if (!strcasecmp(phy_type, "ulpi"))
428                 return FSL_USB2_PHY_ULPI;
429         if (!strcasecmp(phy_type, "utmi"))
430                 return FSL_USB2_PHY_UTMI;
431         if (!strcasecmp(phy_type, "utmi_wide"))
432                 return FSL_USB2_PHY_UTMI_WIDE;
433         if (!strcasecmp(phy_type, "serial"))
434                 return FSL_USB2_PHY_SERIAL;
435
436         return FSL_USB2_PHY_NONE;
437 }
438
439 static int __init fsl_usb_of_init(void)
440 {
441         struct device_node *np;
442         unsigned int i;
443         struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL;
444         int ret;
445
446         for (np = NULL, i = 0;
447              (np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL;
448              i++) {
449                 struct resource r[2];
450                 struct fsl_usb2_platform_data usb_data;
451                 const unsigned char *prop = NULL;
452
453                 memset(&r, 0, sizeof(r));
454                 memset(&usb_data, 0, sizeof(usb_data));
455
456                 ret = of_address_to_resource(np, 0, &r[0]);
457                 if (ret)
458                         goto err;
459
460                 of_irq_to_resource(np, 0, &r[1]);
461
462                 usb_dev_mph =
463                     platform_device_register_simple("fsl-ehci", i, r, 2);
464                 if (IS_ERR(usb_dev_mph)) {
465                         ret = PTR_ERR(usb_dev_mph);
466                         goto err;
467                 }
468
469                 usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
470                 usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
471
472                 usb_data.operating_mode = FSL_USB2_MPH_HOST;
473
474                 prop = get_property(np, "port0", NULL);
475                 if (prop)
476                         usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
477
478                 prop = get_property(np, "port1", NULL);
479                 if (prop)
480                         usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
481
482                 prop = get_property(np, "phy_type", NULL);
483                 usb_data.phy_mode = determine_usb_phy(prop);
484
485                 ret =
486                     platform_device_add_data(usb_dev_mph, &usb_data,
487                                              sizeof(struct
488                                                     fsl_usb2_platform_data));
489                 if (ret)
490                         goto unreg_mph;
491         }
492
493         for (np = NULL;
494              (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL;
495              i++) {
496                 struct resource r[2];
497                 struct fsl_usb2_platform_data usb_data;
498                 const unsigned char *prop = NULL;
499
500                 memset(&r, 0, sizeof(r));
501                 memset(&usb_data, 0, sizeof(usb_data));
502
503                 ret = of_address_to_resource(np, 0, &r[0]);
504                 if (ret)
505                         goto unreg_mph;
506
507                 of_irq_to_resource(np, 0, &r[1]);
508
509                 usb_dev_dr =
510                     platform_device_register_simple("fsl-ehci", i, r, 2);
511                 if (IS_ERR(usb_dev_dr)) {
512                         ret = PTR_ERR(usb_dev_dr);
513                         goto err;
514                 }
515
516                 usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL;
517                 usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask;
518
519                 usb_data.operating_mode = FSL_USB2_DR_HOST;
520
521                 prop = get_property(np, "phy_type", NULL);
522                 usb_data.phy_mode = determine_usb_phy(prop);
523
524                 ret =
525                     platform_device_add_data(usb_dev_dr, &usb_data,
526                                              sizeof(struct
527                                                     fsl_usb2_platform_data));
528                 if (ret)
529                         goto unreg_dr;
530         }
531         return 0;
532
533 unreg_dr:
534         if (usb_dev_dr)
535                 platform_device_unregister(usb_dev_dr);
536 unreg_mph:
537         if (usb_dev_mph)
538                 platform_device_unregister(usb_dev_mph);
539 err:
540         return ret;
541 }
542
543 arch_initcall(fsl_usb_of_init);
544
545 #ifdef CONFIG_CPM2
546
547 static const char fcc_regs[] = "fcc_regs";
548 static const char fcc_regs_c[] = "fcc_regs_c";
549 static const char fcc_pram[] = "fcc_pram";
550 static char bus_id[9][BUS_ID_SIZE];
551
552 static int __init fs_enet_of_init(void)
553 {
554         struct device_node *np;
555         unsigned int i;
556         struct platform_device *fs_enet_dev;
557         struct resource res;
558         int ret;
559
560         for (np = NULL, i = 0;
561              (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
562              i++) {
563                 struct resource r[4];
564                 struct device_node *phy, *mdio;
565                 struct fs_platform_info fs_enet_data;
566                 const unsigned int *id, *phy_addr, *phy_irq;
567                 const void *mac_addr;
568                 const phandle *ph;
569                 const char *model;
570
571                 memset(r, 0, sizeof(r));
572                 memset(&fs_enet_data, 0, sizeof(fs_enet_data));
573
574                 ret = of_address_to_resource(np, 0, &r[0]);
575                 if (ret)
576                         goto err;
577                 r[0].name = fcc_regs;
578
579                 ret = of_address_to_resource(np, 1, &r[1]);
580                 if (ret)
581                         goto err;
582                 r[1].name = fcc_pram;
583
584                 ret = of_address_to_resource(np, 2, &r[2]);
585                 if (ret)
586                         goto err;
587                 r[2].name = fcc_regs_c;
588                 fs_enet_data.fcc_regs_c = r[2].start;
589
590                 of_irq_to_resource(np, 0, &r[3]);
591
592                 fs_enet_dev =
593                     platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
594
595                 if (IS_ERR(fs_enet_dev)) {
596                         ret = PTR_ERR(fs_enet_dev);
597                         goto err;
598                 }
599
600                 model = get_property(np, "model", NULL);
601                 if (model == NULL) {
602                         ret = -ENODEV;
603                         goto unreg;
604                 }
605
606                 mac_addr = get_property(np, "mac-address", NULL);
607                 memcpy(fs_enet_data.macaddr, mac_addr, 6);
608
609                 ph = get_property(np, "phy-handle", NULL);
610                 phy = of_find_node_by_phandle(*ph);
611
612                 if (phy == NULL) {
613                         ret = -ENODEV;
614                         goto unreg;
615                 }
616
617                 phy_addr = get_property(phy, "reg", NULL);
618                 fs_enet_data.phy_addr = *phy_addr;
619
620                 phy_irq = get_property(phy, "interrupts", NULL);
621
622                 id = get_property(np, "device-id", NULL);
623                 fs_enet_data.fs_no = *id;
624                 strcpy(fs_enet_data.fs_type, model);
625
626                 mdio = of_get_parent(phy);
627                 ret = of_address_to_resource(mdio, 0, &res);
628                 if (ret) {
629                         of_node_put(phy);
630                         of_node_put(mdio);
631                         goto unreg;
632                 }
633
634                 fs_enet_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
635                 fs_enet_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
636
637                 if (strstr(model, "FCC")) {
638                         int fcc_index = *id - 1;
639                         const unsigned char *mdio_bb_prop;
640
641                         fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
642                         fs_enet_data.rx_ring = 32;
643                         fs_enet_data.tx_ring = 32;
644                         fs_enet_data.rx_copybreak = 240;
645                         fs_enet_data.use_napi = 0;
646                         fs_enet_data.napi_weight = 17;
647                         fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
648                         fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
649                         fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);
650
651                         snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
652                                                         (u32)res.start, fs_enet_data.phy_addr);
653                         fs_enet_data.bus_id = (char*)&bus_id[(*id)];
654                         fs_enet_data.init_ioports = init_fcc_ioports;
655
656                         mdio_bb_prop = get_property(phy, "bitbang", NULL);
657                         if (mdio_bb_prop) {
658                                 struct platform_device *fs_enet_mdio_bb_dev;
659                                 struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;
660
661                                 fs_enet_mdio_bb_dev =
662                                         platform_device_register_simple("fsl-bb-mdio",
663                                                         i, NULL, 0);
664                                 memset(&fs_enet_mdio_bb_data, 0,
665                                                 sizeof(struct fs_mii_bb_platform_info));
666                                 fs_enet_mdio_bb_data.mdio_dat.bit =
667                                         mdio_bb_prop[0];
668                                 fs_enet_mdio_bb_data.mdio_dir.bit =
669                                         mdio_bb_prop[1];
670                                 fs_enet_mdio_bb_data.mdc_dat.bit =
671                                         mdio_bb_prop[2];
672                                 fs_enet_mdio_bb_data.mdio_port =
673                                         mdio_bb_prop[3];
674                                 fs_enet_mdio_bb_data.mdc_port =
675                                         mdio_bb_prop[4];
676                                 fs_enet_mdio_bb_data.delay =
677                                         mdio_bb_prop[5];
678
679                                 fs_enet_mdio_bb_data.irq[0] = phy_irq[0];
680                                 fs_enet_mdio_bb_data.irq[1] = -1;
681                                 fs_enet_mdio_bb_data.irq[2] = -1;
682                                 fs_enet_mdio_bb_data.irq[3] = phy_irq[0];
683                                 fs_enet_mdio_bb_data.irq[31] = -1;
684
685                                 fs_enet_mdio_bb_data.mdio_dat.offset =
686                                         (u32)&cpm2_immr->im_ioport.iop_pdatc;
687                                 fs_enet_mdio_bb_data.mdio_dir.offset =
688                                         (u32)&cpm2_immr->im_ioport.iop_pdirc;
689                                 fs_enet_mdio_bb_data.mdc_dat.offset =
690                                         (u32)&cpm2_immr->im_ioport.iop_pdatc;
691
692                                 ret = platform_device_add_data(
693                                                 fs_enet_mdio_bb_dev,
694                                                 &fs_enet_mdio_bb_data,
695                                                 sizeof(struct fs_mii_bb_platform_info));
696                                 if (ret)
697                                         goto unreg;
698                         }
699                         
700                         of_node_put(phy);
701                         of_node_put(mdio);
702
703                         ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
704                                                      sizeof(struct
705                                                             fs_platform_info));
706                         if (ret)
707                                 goto unreg;
708                 }
709         }
710         return 0;
711
712 unreg:
713         platform_device_unregister(fs_enet_dev);
714 err:
715         return ret;
716 }
717
718 arch_initcall(fs_enet_of_init);
719
720 static const char scc_regs[] = "regs";
721 static const char scc_pram[] = "pram";
722
723 static int __init cpm_uart_of_init(void)
724 {
725         struct device_node *np;
726         unsigned int i;
727         struct platform_device *cpm_uart_dev;
728         int ret;
729
730         for (np = NULL, i = 0;
731              (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
732              i++) {
733                 struct resource r[3];
734                 struct fs_uart_platform_info cpm_uart_data;
735                 const int *id;
736                 const char *model;
737
738                 memset(r, 0, sizeof(r));
739                 memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
740
741                 ret = of_address_to_resource(np, 0, &r[0]);
742                 if (ret)
743                         goto err;
744
745                 r[0].name = scc_regs;
746
747                 ret = of_address_to_resource(np, 1, &r[1]);
748                 if (ret)
749                         goto err;
750                 r[1].name = scc_pram;
751
752                 of_irq_to_resource(np, 0, &r[2]);
753
754                 cpm_uart_dev =
755                     platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
756
757                 if (IS_ERR(cpm_uart_dev)) {
758                         ret = PTR_ERR(cpm_uart_dev);
759                         goto err;
760                 }
761
762                 id = get_property(np, "device-id", NULL);
763                 cpm_uart_data.fs_no = *id;
764
765                 model = (char*)get_property(np, "model", NULL);
766                 strcpy(cpm_uart_data.fs_type, model);
767
768                 cpm_uart_data.uart_clk = ppc_proc_freq;
769
770                 cpm_uart_data.tx_num_fifo = 4;
771                 cpm_uart_data.tx_buf_size = 32;
772                 cpm_uart_data.rx_num_fifo = 4;
773                 cpm_uart_data.rx_buf_size = 32;
774                 cpm_uart_data.clk_rx = *((u32 *) get_property(np, "rx-clock", NULL));
775                 cpm_uart_data.clk_tx = *((u32 *) get_property(np, "tx-clock", NULL));
776
777                 ret =
778                     platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
779                                              sizeof(struct
780                                                     fs_uart_platform_info));
781                 if (ret)
782                         goto unreg;
783         }
784
785         return 0;
786
787 unreg:
788         platform_device_unregister(cpm_uart_dev);
789 err:
790         return ret;
791 }
792
793 arch_initcall(cpm_uart_of_init);
794 #endif /* CONFIG_CPM2 */