POWERPC: Add cpm2 stuff support to the fsl_soc.c
[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/fsl_devices.h>
26 #include <linux/fs_enet_pd.h>
27 #include <linux/fs_uart_pd.h>
28
29 #include <asm/system.h>
30 #include <asm/atomic.h>
31 #include <asm/io.h>
32 #include <asm/irq.h>
33 #include <asm/time.h>
34 #include <asm/prom.h>
35 #include <sysdev/fsl_soc.h>
36 #include <mm/mmu_decl.h>
37 #include <asm/cpm2.h>
38
39 static phys_addr_t immrbase = -1;
40
41 phys_addr_t get_immrbase(void)
42 {
43         struct device_node *soc;
44
45         if (immrbase != -1)
46                 return immrbase;
47
48         soc = of_find_node_by_type(NULL, "soc");
49         if (soc) {
50                 unsigned int size;
51                 const void *prop = get_property(soc, "reg", &size);
52
53                 if (prop)
54                         immrbase = of_translate_address(soc, prop);
55                 of_node_put(soc);
56         };
57
58         return immrbase;
59 }
60
61 EXPORT_SYMBOL(get_immrbase);
62
63 #ifdef CONFIG_CPM2
64
65 static u32 brgfreq = -1;
66
67 u32 get_brgfreq(void)
68 {
69         struct device_node *node;
70
71         if (brgfreq != -1)
72                 return brgfreq;
73
74         node = of_find_node_by_type(NULL, "cpm");
75         if (node) {
76                 unsigned int size;
77                 const unsigned int *prop = get_property(node, "brg-frequency",
78                                         &size);
79
80                 if (prop)
81                         brgfreq = *prop;
82                 of_node_put(node);
83         };
84
85         return brgfreq;
86 }
87
88 EXPORT_SYMBOL(get_brgfreq);
89
90 static u32 fs_baudrate = -1;
91
92 u32 get_baudrate(void)
93 {
94         struct device_node *node;
95
96         if (fs_baudrate != -1)
97                 return fs_baudrate;
98
99         node = of_find_node_by_type(NULL, "serial");
100         if (node) {
101                 unsigned int size;
102                 const unsigned int *prop = get_property(node, "current-speed",
103                                 &size);
104
105                 if (prop)
106                         fs_baudrate = *prop;
107                 of_node_put(node);
108         };
109
110         return fs_baudrate;
111 }
112
113 EXPORT_SYMBOL(get_baudrate);
114 #endif /* CONFIG_CPM2 */
115
116 static int __init gfar_mdio_of_init(void)
117 {
118         struct device_node *np;
119         unsigned int i;
120         struct platform_device *mdio_dev;
121         struct resource res;
122         int ret;
123
124         for (np = NULL, i = 0;
125              (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL;
126              i++) {
127                 int k;
128                 struct device_node *child = NULL;
129                 struct gianfar_mdio_data mdio_data;
130
131                 memset(&res, 0, sizeof(res));
132                 memset(&mdio_data, 0, sizeof(mdio_data));
133
134                 ret = of_address_to_resource(np, 0, &res);
135                 if (ret)
136                         goto err;
137
138                 mdio_dev =
139                     platform_device_register_simple("fsl-gianfar_mdio",
140                                                     res.start, &res, 1);
141                 if (IS_ERR(mdio_dev)) {
142                         ret = PTR_ERR(mdio_dev);
143                         goto err;
144                 }
145
146                 for (k = 0; k < 32; k++)
147                         mdio_data.irq[k] = -1;
148
149                 while ((child = of_get_next_child(np, child)) != NULL) {
150                         int irq = irq_of_parse_and_map(child, 0);
151                         if (irq != NO_IRQ) {
152                                 const u32 *id = get_property(child, "reg", NULL);
153                                 mdio_data.irq[*id] = irq;
154                         }
155                 }
156
157                 ret =
158                     platform_device_add_data(mdio_dev, &mdio_data,
159                                              sizeof(struct gianfar_mdio_data));
160                 if (ret)
161                         goto unreg;
162         }
163
164         return 0;
165
166 unreg:
167         platform_device_unregister(mdio_dev);
168 err:
169         return ret;
170 }
171
172 arch_initcall(gfar_mdio_of_init);
173
174 static const char *gfar_tx_intr = "tx";
175 static const char *gfar_rx_intr = "rx";
176 static const char *gfar_err_intr = "error";
177
178 static int __init gfar_of_init(void)
179 {
180         struct device_node *np;
181         unsigned int i;
182         struct platform_device *gfar_dev;
183         struct resource res;
184         int ret;
185
186         for (np = NULL, i = 0;
187              (np = of_find_compatible_node(np, "network", "gianfar")) != NULL;
188              i++) {
189                 struct resource r[4];
190                 struct device_node *phy, *mdio;
191                 struct gianfar_platform_data gfar_data;
192                 const unsigned int *id;
193                 const char *model;
194                 const void *mac_addr;
195                 const phandle *ph;
196                 int n_res = 2;
197
198                 memset(r, 0, sizeof(r));
199                 memset(&gfar_data, 0, sizeof(gfar_data));
200
201                 ret = of_address_to_resource(np, 0, &r[0]);
202                 if (ret)
203                         goto err;
204
205                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
206                 r[1].flags = IORESOURCE_IRQ;
207
208                 model = get_property(np, "model", NULL);
209
210                 /* If we aren't the FEC we have multiple interrupts */
211                 if (model && strcasecmp(model, "FEC")) {
212                         r[1].name = gfar_tx_intr;
213
214                         r[2].name = gfar_rx_intr;
215                         r[2].start = r[2].end = irq_of_parse_and_map(np, 1);
216                         r[2].flags = IORESOURCE_IRQ;
217
218                         r[3].name = gfar_err_intr;
219                         r[3].start = r[3].end = irq_of_parse_and_map(np, 2);
220                         r[3].flags = IORESOURCE_IRQ;
221
222                         n_res += 2;
223                 }
224
225                 gfar_dev =
226                     platform_device_register_simple("fsl-gianfar", i, &r[0],
227                                                     n_res);
228
229                 if (IS_ERR(gfar_dev)) {
230                         ret = PTR_ERR(gfar_dev);
231                         goto err;
232                 }
233
234                 mac_addr = get_property(np, "local-mac-address", NULL);
235                 if (mac_addr == NULL)
236                         mac_addr = get_property(np, "mac-address", NULL);
237                 if (mac_addr == NULL) {
238                         /* Obsolete */
239                         mac_addr = get_property(np, "address", NULL);
240                 }
241
242                 if (mac_addr)
243                         memcpy(gfar_data.mac_addr, mac_addr, 6);
244
245                 if (model && !strcasecmp(model, "TSEC"))
246                         gfar_data.device_flags =
247                             FSL_GIANFAR_DEV_HAS_GIGABIT |
248                             FSL_GIANFAR_DEV_HAS_COALESCE |
249                             FSL_GIANFAR_DEV_HAS_RMON |
250                             FSL_GIANFAR_DEV_HAS_MULTI_INTR;
251                 if (model && !strcasecmp(model, "eTSEC"))
252                         gfar_data.device_flags =
253                             FSL_GIANFAR_DEV_HAS_GIGABIT |
254                             FSL_GIANFAR_DEV_HAS_COALESCE |
255                             FSL_GIANFAR_DEV_HAS_RMON |
256                             FSL_GIANFAR_DEV_HAS_MULTI_INTR |
257                             FSL_GIANFAR_DEV_HAS_CSUM |
258                             FSL_GIANFAR_DEV_HAS_VLAN |
259                             FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
260
261                 ph = get_property(np, "phy-handle", NULL);
262                 phy = of_find_node_by_phandle(*ph);
263
264                 if (phy == NULL) {
265                         ret = -ENODEV;
266                         goto unreg;
267                 }
268
269                 mdio = of_get_parent(phy);
270
271                 id = get_property(phy, "reg", NULL);
272                 ret = of_address_to_resource(mdio, 0, &res);
273                 if (ret) {
274                         of_node_put(phy);
275                         of_node_put(mdio);
276                         goto unreg;
277                 }
278
279                 gfar_data.phy_id = *id;
280                 gfar_data.bus_id = res.start;
281
282                 of_node_put(phy);
283                 of_node_put(mdio);
284
285                 ret =
286                     platform_device_add_data(gfar_dev, &gfar_data,
287                                              sizeof(struct
288                                                     gianfar_platform_data));
289                 if (ret)
290                         goto unreg;
291         }
292
293         return 0;
294
295 unreg:
296         platform_device_unregister(gfar_dev);
297 err:
298         return ret;
299 }
300
301 arch_initcall(gfar_of_init);
302
303 static int __init fsl_i2c_of_init(void)
304 {
305         struct device_node *np;
306         unsigned int i;
307         struct platform_device *i2c_dev;
308         int ret;
309
310         for (np = NULL, i = 0;
311              (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL;
312              i++) {
313                 struct resource r[2];
314                 struct fsl_i2c_platform_data i2c_data;
315                 const unsigned char *flags = NULL;
316
317                 memset(&r, 0, sizeof(r));
318                 memset(&i2c_data, 0, sizeof(i2c_data));
319
320                 ret = of_address_to_resource(np, 0, &r[0]);
321                 if (ret)
322                         goto err;
323
324                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
325                 r[1].flags = IORESOURCE_IRQ;
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                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
461                 r[1].flags = IORESOURCE_IRQ;
462
463                 usb_dev_mph =
464                     platform_device_register_simple("fsl-ehci", i, r, 2);
465                 if (IS_ERR(usb_dev_mph)) {
466                         ret = PTR_ERR(usb_dev_mph);
467                         goto err;
468                 }
469
470                 usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
471                 usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
472
473                 usb_data.operating_mode = FSL_USB2_MPH_HOST;
474
475                 prop = get_property(np, "port0", NULL);
476                 if (prop)
477                         usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
478
479                 prop = get_property(np, "port1", NULL);
480                 if (prop)
481                         usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
482
483                 prop = get_property(np, "phy_type", NULL);
484                 usb_data.phy_mode = determine_usb_phy(prop);
485
486                 ret =
487                     platform_device_add_data(usb_dev_mph, &usb_data,
488                                              sizeof(struct
489                                                     fsl_usb2_platform_data));
490                 if (ret)
491                         goto unreg_mph;
492         }
493
494         for (np = NULL;
495              (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL;
496              i++) {
497                 struct resource r[2];
498                 struct fsl_usb2_platform_data usb_data;
499                 const unsigned char *prop = NULL;
500
501                 memset(&r, 0, sizeof(r));
502                 memset(&usb_data, 0, sizeof(usb_data));
503
504                 ret = of_address_to_resource(np, 0, &r[0]);
505                 if (ret)
506                         goto unreg_mph;
507
508                 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
509                 r[1].flags = IORESOURCE_IRQ;
510
511                 usb_dev_dr =
512                     platform_device_register_simple("fsl-ehci", i, r, 2);
513                 if (IS_ERR(usb_dev_dr)) {
514                         ret = PTR_ERR(usb_dev_dr);
515                         goto err;
516                 }
517
518                 usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL;
519                 usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask;
520
521                 usb_data.operating_mode = FSL_USB2_DR_HOST;
522
523                 prop = get_property(np, "phy_type", NULL);
524                 usb_data.phy_mode = determine_usb_phy(prop);
525
526                 ret =
527                     platform_device_add_data(usb_dev_dr, &usb_data,
528                                              sizeof(struct
529                                                     fsl_usb2_platform_data));
530                 if (ret)
531                         goto unreg_dr;
532         }
533         return 0;
534
535 unreg_dr:
536         if (usb_dev_dr)
537                 platform_device_unregister(usb_dev_dr);
538 unreg_mph:
539         if (usb_dev_mph)
540                 platform_device_unregister(usb_dev_mph);
541 err:
542         return ret;
543 }
544
545 arch_initcall(fsl_usb_of_init);
546
547 #ifdef CONFIG_CPM2
548
549 static const char fcc_regs[] = "fcc_regs";
550 static const char fcc_regs_c[] = "fcc_regs_c";
551 static const char fcc_pram[] = "fcc_pram";
552 static char bus_id[9][BUS_ID_SIZE];
553
554 static int __init fs_enet_of_init(void)
555 {
556         struct device_node *np;
557         unsigned int i;
558         struct platform_device *fs_enet_dev;
559         struct resource res;
560         int ret;
561
562         for (np = NULL, i = 0;
563              (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
564              i++) {
565                 struct resource r[4];
566                 struct device_node *phy, *mdio;
567                 struct fs_platform_info fs_enet_data;
568                 const unsigned int *id, *phy_addr;
569                 const void *mac_addr;
570                 const phandle *ph;
571                 const char *model;
572
573                 memset(r, 0, sizeof(r));
574                 memset(&fs_enet_data, 0, sizeof(fs_enet_data));
575
576                 ret = of_address_to_resource(np, 0, &r[0]);
577                 if (ret)
578                         goto err;
579                 r[0].name = fcc_regs;
580
581                 ret = of_address_to_resource(np, 1, &r[1]);
582                 if (ret)
583                         goto err;
584                 r[1].name = fcc_pram;
585
586                 ret = of_address_to_resource(np, 2, &r[2]);
587                 if (ret)
588                         goto err;
589                 r[2].name = fcc_regs_c;
590
591                 r[3].start = r[3].end = irq_of_parse_and_map(np, 0);
592                 r[3].flags = IORESOURCE_IRQ;
593
594                 fs_enet_dev =
595                     platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
596
597                 if (IS_ERR(fs_enet_dev)) {
598                         ret = PTR_ERR(fs_enet_dev);
599                         goto err;
600                 }
601
602                 model = get_property(np, "model", NULL);
603                 if (model == NULL) {
604                         ret = -ENODEV;
605                         goto unreg;
606                 }
607
608                 mac_addr = get_property(np, "mac-address", NULL);
609                 memcpy(fs_enet_data.macaddr, mac_addr, 6);
610
611                 ph = get_property(np, "phy-handle", NULL);
612                 phy = of_find_node_by_phandle(*ph);
613
614                 if (phy == NULL) {
615                         ret = -ENODEV;
616                         goto unreg;
617                 }
618
619                 phy_addr = get_property(phy, "reg", NULL);
620                 fs_enet_data.phy_addr = *phy_addr;
621
622                 id = get_property(np, "device-id", NULL);
623                 fs_enet_data.fs_no = *id;
624
625                 mdio = of_get_parent(phy);
626                 ret = of_address_to_resource(mdio, 0, &res);
627                 if (ret) {
628                         of_node_put(phy);
629                         of_node_put(mdio);
630                         goto unreg;
631                 }
632
633                 if (strstr(model, "FCC")) {
634                         int fcc_index = fs_get_fcc_index(*id);
635
636                         fs_enet_data.dpram_offset = (u32)cpm2_immr->im_dprambase;
637                         fs_enet_data.rx_ring = 32;
638                         fs_enet_data.tx_ring = 32;
639                         fs_enet_data.rx_copybreak = 240;
640                         fs_enet_data.use_napi = 0;
641                         fs_enet_data.napi_weight = 17;
642                         fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
643                         fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
644                         fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);
645
646                         snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
647                                                         (u32)res.start, fs_enet_data.phy_addr);
648                         fs_enet_data.bus_id = (char*)&bus_id[(*id)];
649                 }
650
651                 of_node_put(phy);
652                 of_node_put(mdio);
653
654                 ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
655                                              sizeof(struct
656                                                     fs_platform_info));
657                 if (ret)
658                         goto unreg;
659         }
660         return 0;
661
662 unreg:
663         platform_device_unregister(fs_enet_dev);
664 err:
665         return ret;
666 }
667
668 arch_initcall(fs_enet_of_init);
669
670 static const char scc_regs[] = "regs";
671 static const char scc_pram[] = "pram";
672
673 static int __init cpm_uart_of_init(void)
674 {
675         struct device_node *np;
676         unsigned int i;
677         struct platform_device *cpm_uart_dev;
678         int ret;
679
680         for (np = NULL, i = 0;
681              (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
682              i++) {
683                 struct resource r[3];
684                 struct fs_uart_platform_info cpm_uart_data;
685                 const int *id;
686
687                 memset(r, 0, sizeof(r));
688                 memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
689
690                 ret = of_address_to_resource(np, 0, &r[0]);
691                 if (ret)
692                         goto err;
693
694                 r[0].name = scc_regs;
695
696                 ret = of_address_to_resource(np, 1, &r[1]);
697                 if (ret)
698                         goto err;
699                 r[1].name = scc_pram;
700
701                 r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
702                 r[2].flags = IORESOURCE_IRQ;
703
704                 cpm_uart_dev =
705                     platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
706
707                 if (IS_ERR(cpm_uart_dev)) {
708                         ret = PTR_ERR(cpm_uart_dev);
709                         goto err;
710                 }
711
712                 id = get_property(np, "device-id", NULL);
713                 cpm_uart_data.fs_no = *id;
714                 cpm_uart_data.uart_clk = ppc_proc_freq;
715
716                 cpm_uart_data.tx_num_fifo = 4;
717                 cpm_uart_data.tx_buf_size = 32;
718                 cpm_uart_data.rx_num_fifo = 4;
719                 cpm_uart_data.rx_buf_size = 32;
720
721                 ret =
722                     platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
723                                              sizeof(struct
724                                                     fs_uart_platform_info));
725                 if (ret)
726                         goto unreg;
727         }
728
729         return 0;
730
731 unreg:
732         platform_device_unregister(cpm_uart_dev);
733 err:
734         return ret;
735 }
736
737 arch_initcall(cpm_uart_of_init);
738 #endif /* CONFIG_CPM2 */