blob: 474cb8e22f64603451dae9777ac24614cec1e69f [file] [log] [blame]
Kumar Galaeed32002006-01-13 11:19:13 -06001/*
2 * FSL SoC setup code
3 *
4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5 *
Vitaly Bordugfba43662006-09-21 17:26:34 +04006 * 2006 (c) MontaVista Software, Inc.
7 * Vitaly Bordug <vbordug@ru.mvista.com>
8 *
Kumar Galaeed32002006-01-13 11:19:13 -06009 * 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
Kumar Galaeed32002006-01-13 11:19:13 -060015#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>
Kumar Gala0af666f2007-08-17 08:23:06 -050025#include <linux/of_platform.h>
Andy Fleminga9b14972006-10-19 19:52:26 -050026#include <linux/phy.h>
Vitaly Borduga21e2822007-12-07 01:51:31 +030027#include <linux/phy_fixed.h>
Anton Vorontsov26f6cb92007-08-23 15:35:56 +040028#include <linux/spi/spi.h>
Kumar Galaeed32002006-01-13 11:19:13 -060029#include <linux/fsl_devices.h>
Vitaly Bordugfba43662006-09-21 17:26:34 +040030#include <linux/fs_enet_pd.h>
31#include <linux/fs_uart_pd.h>
Kumar Galaeed32002006-01-13 11:19:13 -060032
33#include <asm/system.h>
34#include <asm/atomic.h>
35#include <asm/io.h>
36#include <asm/irq.h>
Vitaly Bordugfba43662006-09-21 17:26:34 +040037#include <asm/time.h>
Kumar Galaeed32002006-01-13 11:19:13 -060038#include <asm/prom.h>
39#include <sysdev/fsl_soc.h>
40#include <mm/mmu_decl.h>
Vitaly Bordugfba43662006-09-21 17:26:34 +040041#include <asm/cpm2.h>
Kumar Galaeed32002006-01-13 11:19:13 -060042
Vitaly Bordugd3465c92006-09-21 22:38:05 +040043extern void init_fcc_ioports(struct fs_platform_info*);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +030044extern void init_fec_ioports(struct fs_platform_info*);
45extern void init_smc_ioports(struct fs_uart_platform_info*);
Kumar Galaeed32002006-01-13 11:19:13 -060046static phys_addr_t immrbase = -1;
47
48phys_addr_t get_immrbase(void)
49{
50 struct device_node *soc;
51
52 if (immrbase != -1)
53 return immrbase;
54
55 soc = of_find_node_by_type(NULL, "soc");
Kumar Gala2fb07d72006-01-23 16:58:04 -060056 if (soc) {
Scott Woodf9234732007-08-20 11:38:12 -050057 int size;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +100058 const void *prop = of_get_property(soc, "reg", &size);
Vitaly Bordugfba43662006-09-21 17:26:34 +040059
60 if (prop)
61 immrbase = of_translate_address(soc, prop);
Kumar Galaeed32002006-01-13 11:19:13 -060062 of_node_put(soc);
Scott Woodf9234732007-08-20 11:38:12 -050063 }
Kumar Galaeed32002006-01-13 11:19:13 -060064
65 return immrbase;
66}
Kumar Gala2fb07d72006-01-23 16:58:04 -060067
Kumar Galaeed32002006-01-13 11:19:13 -060068EXPORT_SYMBOL(get_immrbase);
69
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +030070#if defined(CONFIG_CPM2) || defined(CONFIG_8xx)
Vitaly Bordugfba43662006-09-21 17:26:34 +040071
72static u32 brgfreq = -1;
73
74u32 get_brgfreq(void)
75{
76 struct device_node *node;
Scott Wood6d817aa2007-08-29 15:08:40 -050077 const unsigned int *prop;
78 int size;
Vitaly Bordugfba43662006-09-21 17:26:34 +040079
80 if (brgfreq != -1)
81 return brgfreq;
82
Scott Wood6d817aa2007-08-29 15:08:40 -050083 node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");
Vitaly Bordugfba43662006-09-21 17:26:34 +040084 if (node) {
Scott Wood6d817aa2007-08-29 15:08:40 -050085 prop = of_get_property(node, "clock-frequency", &size);
86 if (prop && size == 4)
87 brgfreq = *prop;
Vitaly Bordugfba43662006-09-21 17:26:34 +040088
Scott Wood6d817aa2007-08-29 15:08:40 -050089 of_node_put(node);
90 return brgfreq;
91 }
92
93 /* Legacy device binding -- will go away when no users are left. */
94 node = of_find_node_by_type(NULL, "cpm");
95 if (node) {
96 prop = of_get_property(node, "brg-frequency", &size);
Scott Woodf9234732007-08-20 11:38:12 -050097 if (prop && size == 4)
Vitaly Bordugfba43662006-09-21 17:26:34 +040098 brgfreq = *prop;
Scott Woodf9234732007-08-20 11:38:12 -050099
Vitaly Bordugfba43662006-09-21 17:26:34 +0400100 of_node_put(node);
Scott Woodf9234732007-08-20 11:38:12 -0500101 }
Vitaly Bordugfba43662006-09-21 17:26:34 +0400102
103 return brgfreq;
104}
105
106EXPORT_SYMBOL(get_brgfreq);
107
108static u32 fs_baudrate = -1;
109
110u32 get_baudrate(void)
111{
112 struct device_node *node;
113
114 if (fs_baudrate != -1)
115 return fs_baudrate;
116
117 node = of_find_node_by_type(NULL, "serial");
118 if (node) {
Scott Woodf9234732007-08-20 11:38:12 -0500119 int size;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000120 const unsigned int *prop = of_get_property(node,
121 "current-speed", &size);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400122
123 if (prop)
124 fs_baudrate = *prop;
125 of_node_put(node);
Scott Woodf9234732007-08-20 11:38:12 -0500126 }
Vitaly Bordugfba43662006-09-21 17:26:34 +0400127
128 return fs_baudrate;
129}
130
131EXPORT_SYMBOL(get_baudrate);
132#endif /* CONFIG_CPM2 */
133
Vitaly Borduga21e2822007-12-07 01:51:31 +0300134#ifdef CONFIG_FIXED_PHY
135static int __init of_add_fixed_phys(void)
136{
137 int ret;
138 struct device_node *np;
139 u32 *fixed_link;
140 struct fixed_phy_status status = {};
141
142 for_each_node_by_name(np, "ethernet") {
143 fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
144 if (!fixed_link)
145 continue;
146
147 status.link = 1;
148 status.duplex = fixed_link[1];
149 status.speed = fixed_link[2];
150 status.pause = fixed_link[3];
151 status.asym_pause = fixed_link[4];
152
153 ret = fixed_phy_add(PHY_POLL, fixed_link[0], &status);
154 if (ret) {
155 of_node_put(np);
156 return ret;
157 }
158 }
159
160 return 0;
161}
162arch_initcall(of_add_fixed_phys);
163#endif /* CONFIG_FIXED_PHY */
164
Kumar Gala2fb07d72006-01-23 16:58:04 -0600165static int __init gfar_mdio_of_init(void)
Kumar Galaeed32002006-01-13 11:19:13 -0600166{
Kumar Galae77b28e2007-12-12 00:28:35 -0600167 struct device_node *np = NULL;
Kumar Gala2fb07d72006-01-23 16:58:04 -0600168 struct platform_device *mdio_dev;
Kumar Galaeed32002006-01-13 11:19:13 -0600169 struct resource res;
170 int ret;
171
Kumar Galae77b28e2007-12-12 00:28:35 -0600172 np = of_find_compatible_node(np, NULL, "fsl,gianfar-mdio");
173
174 /* try the deprecated version */
175 if (!np)
176 np = of_find_compatible_node(np, "mdio", "gianfar");
177
178 if (np) {
Kumar Galaeed32002006-01-13 11:19:13 -0600179 int k;
180 struct device_node *child = NULL;
181 struct gianfar_mdio_data mdio_data;
182
183 memset(&res, 0, sizeof(res));
184 memset(&mdio_data, 0, sizeof(mdio_data));
185
186 ret = of_address_to_resource(np, 0, &res);
187 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600188 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600189
Kumar Gala2fb07d72006-01-23 16:58:04 -0600190 mdio_dev =
191 platform_device_register_simple("fsl-gianfar_mdio",
192 res.start, &res, 1);
Kumar Galaeed32002006-01-13 11:19:13 -0600193 if (IS_ERR(mdio_dev)) {
194 ret = PTR_ERR(mdio_dev);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600195 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600196 }
197
198 for (k = 0; k < 32; k++)
Andy Fleminga9b14972006-10-19 19:52:26 -0500199 mdio_data.irq[k] = PHY_POLL;
Kumar Galaeed32002006-01-13 11:19:13 -0600200
201 while ((child = of_get_next_child(np, child)) != NULL) {
Vitaly Bordugfba43662006-09-21 17:26:34 +0400202 int irq = irq_of_parse_and_map(child, 0);
203 if (irq != NO_IRQ) {
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000204 const u32 *id = of_get_property(child,
205 "reg", NULL);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400206 mdio_data.irq[*id] = irq;
207 }
Kumar Galaeed32002006-01-13 11:19:13 -0600208 }
209
Kumar Gala2fb07d72006-01-23 16:58:04 -0600210 ret =
211 platform_device_add_data(mdio_dev, &mdio_data,
212 sizeof(struct gianfar_mdio_data));
Kumar Galaeed32002006-01-13 11:19:13 -0600213 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600214 goto unreg;
Kumar Galaeed32002006-01-13 11:19:13 -0600215 }
216
Kumar Galae77b28e2007-12-12 00:28:35 -0600217 of_node_put(np);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600218 return 0;
219
220unreg:
221 platform_device_unregister(mdio_dev);
222err:
Kumar Galae77b28e2007-12-12 00:28:35 -0600223 of_node_put(np);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600224 return ret;
225}
226
227arch_initcall(gfar_mdio_of_init);
228
229static const char *gfar_tx_intr = "tx";
230static const char *gfar_rx_intr = "rx";
231static const char *gfar_err_intr = "error";
232
233static int __init gfar_of_init(void)
234{
235 struct device_node *np;
236 unsigned int i;
237 struct platform_device *gfar_dev;
238 struct resource res;
239 int ret;
240
241 for (np = NULL, i = 0;
242 (np = of_find_compatible_node(np, "network", "gianfar")) != NULL;
243 i++) {
Kumar Galaeed32002006-01-13 11:19:13 -0600244 struct resource r[4];
245 struct device_node *phy, *mdio;
246 struct gianfar_platform_data gfar_data;
Jeremy Kerra7f67bd2006-07-12 15:35:54 +1000247 const unsigned int *id;
248 const char *model;
Andy Fleming7132ab72007-07-11 11:43:07 -0500249 const char *ctype;
Jeremy Kerra7f67bd2006-07-12 15:35:54 +1000250 const void *mac_addr;
251 const phandle *ph;
Vitaly Bordugfba43662006-09-21 17:26:34 +0400252 int n_res = 2;
Kumar Galaeed32002006-01-13 11:19:13 -0600253
254 memset(r, 0, sizeof(r));
255 memset(&gfar_data, 0, sizeof(gfar_data));
256
257 ret = of_address_to_resource(np, 0, &r[0]);
258 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600259 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600260
Andy Fleminga9b14972006-10-19 19:52:26 -0500261 of_irq_to_resource(np, 0, &r[1]);
Kumar Galaeed32002006-01-13 11:19:13 -0600262
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000263 model = of_get_property(np, "model", NULL);
Kumar Galaeed32002006-01-13 11:19:13 -0600264
265 /* If we aren't the FEC we have multiple interrupts */
266 if (model && strcasecmp(model, "FEC")) {
267 r[1].name = gfar_tx_intr;
268
269 r[2].name = gfar_rx_intr;
Andy Fleminga9b14972006-10-19 19:52:26 -0500270 of_irq_to_resource(np, 1, &r[2]);
Kumar Galaeed32002006-01-13 11:19:13 -0600271
272 r[3].name = gfar_err_intr;
Andy Fleminga9b14972006-10-19 19:52:26 -0500273 of_irq_to_resource(np, 2, &r[3]);
Jon Loeliger919fede2006-07-31 15:35:41 -0500274
275 n_res += 2;
Kumar Galaeed32002006-01-13 11:19:13 -0600276 }
277
Kumar Gala2fb07d72006-01-23 16:58:04 -0600278 gfar_dev =
279 platform_device_register_simple("fsl-gianfar", i, &r[0],
Vitaly Bordugfba43662006-09-21 17:26:34 +0400280 n_res);
Kumar Galaeed32002006-01-13 11:19:13 -0600281
282 if (IS_ERR(gfar_dev)) {
283 ret = PTR_ERR(gfar_dev);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600284 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600285 }
286
Timur Tabi29cfe6f2007-02-16 12:01:29 -0600287 mac_addr = of_get_mac_address(np);
Jon Loeligerf5831652006-08-17 08:42:35 -0500288 if (mac_addr)
289 memcpy(gfar_data.mac_addr, mac_addr, 6);
Kumar Galaeed32002006-01-13 11:19:13 -0600290
291 if (model && !strcasecmp(model, "TSEC"))
292 gfar_data.device_flags =
Kumar Gala2fb07d72006-01-23 16:58:04 -0600293 FSL_GIANFAR_DEV_HAS_GIGABIT |
294 FSL_GIANFAR_DEV_HAS_COALESCE |
295 FSL_GIANFAR_DEV_HAS_RMON |
296 FSL_GIANFAR_DEV_HAS_MULTI_INTR;
Kumar Galaeed32002006-01-13 11:19:13 -0600297 if (model && !strcasecmp(model, "eTSEC"))
298 gfar_data.device_flags =
Kumar Gala2fb07d72006-01-23 16:58:04 -0600299 FSL_GIANFAR_DEV_HAS_GIGABIT |
300 FSL_GIANFAR_DEV_HAS_COALESCE |
301 FSL_GIANFAR_DEV_HAS_RMON |
302 FSL_GIANFAR_DEV_HAS_MULTI_INTR |
303 FSL_GIANFAR_DEV_HAS_CSUM |
304 FSL_GIANFAR_DEV_HAS_VLAN |
305 FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
Kumar Galaeed32002006-01-13 11:19:13 -0600306
Andy Fleming7132ab72007-07-11 11:43:07 -0500307 ctype = of_get_property(np, "phy-connection-type", NULL);
308
309 /* We only care about rgmii-id. The rest are autodetected */
310 if (ctype && !strcmp(ctype, "rgmii-id"))
311 gfar_data.interface = PHY_INTERFACE_MODE_RGMII_ID;
312 else
313 gfar_data.interface = PHY_INTERFACE_MODE_MII;
314
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000315 ph = of_get_property(np, "phy-handle", NULL);
Vitaly Borduga21e2822007-12-07 01:51:31 +0300316 if (ph == NULL) {
317 u32 *fixed_link;
Kumar Galaeed32002006-01-13 11:19:13 -0600318
Vitaly Borduga21e2822007-12-07 01:51:31 +0300319 fixed_link = (u32 *)of_get_property(np, "fixed-link",
320 NULL);
321 if (!fixed_link) {
322 ret = -ENODEV;
323 goto unreg;
324 }
Kumar Galaeed32002006-01-13 11:19:13 -0600325
Vitaly Borduga21e2822007-12-07 01:51:31 +0300326 gfar_data.bus_id = 0;
327 gfar_data.phy_id = fixed_link[0];
328 } else {
329 phy = of_find_node_by_phandle(*ph);
Kumar Galaeed32002006-01-13 11:19:13 -0600330
Vitaly Borduga21e2822007-12-07 01:51:31 +0300331 if (phy == NULL) {
332 ret = -ENODEV;
333 goto unreg;
334 }
335
336 mdio = of_get_parent(phy);
337
338 id = of_get_property(phy, "reg", NULL);
339 ret = of_address_to_resource(mdio, 0, &res);
340 if (ret) {
341 of_node_put(phy);
342 of_node_put(mdio);
343 goto unreg;
344 }
345
346 gfar_data.phy_id = *id;
347 gfar_data.bus_id = res.start;
348
Kumar Galaeed32002006-01-13 11:19:13 -0600349 of_node_put(phy);
350 of_node_put(mdio);
Kumar Galaeed32002006-01-13 11:19:13 -0600351 }
352
Kumar Gala2fb07d72006-01-23 16:58:04 -0600353 ret =
354 platform_device_add_data(gfar_dev, &gfar_data,
355 sizeof(struct
356 gianfar_platform_data));
Kumar Galaeed32002006-01-13 11:19:13 -0600357 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600358 goto unreg;
Kumar Galaeed32002006-01-13 11:19:13 -0600359 }
360
361 return 0;
362
Kumar Gala2fb07d72006-01-23 16:58:04 -0600363unreg:
Kumar Galaeed32002006-01-13 11:19:13 -0600364 platform_device_unregister(gfar_dev);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600365err:
Kumar Galaeed32002006-01-13 11:19:13 -0600366 return ret;
367}
Kumar Gala2fb07d72006-01-23 16:58:04 -0600368
Kumar Galaeed32002006-01-13 11:19:13 -0600369arch_initcall(gfar_of_init);
370
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000371#ifdef CONFIG_I2C_BOARDINFO
372#include <linux/i2c.h>
373struct i2c_driver_device {
374 char *of_device;
375 char *i2c_driver;
376 char *i2c_type;
377};
378
379static struct i2c_driver_device i2c_devices[] __initdata = {
380 {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},
381 {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
382 {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",},
383 {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
Peter Korsgaard0438c282007-09-20 12:42:13 +0200384 {"dallas,ds1307", "rtc-ds1307", "ds1307",},
385 {"dallas,ds1337", "rtc-ds1307", "ds1337",},
386 {"dallas,ds1338", "rtc-ds1307", "ds1338",},
387 {"dallas,ds1339", "rtc-ds1307", "ds1339",},
388 {"dallas,ds1340", "rtc-ds1307", "ds1340",},
389 {"stm,m41t00", "rtc-ds1307", "m41t00"},
Anton Vorontsovc0e4eb22007-10-02 17:47:43 +0400390 {"dallas,ds1374", "rtc-ds1374", "rtc-ds1374",},
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000391};
392
Guennadi Liakhovetskie78bb5d2007-08-16 05:15:03 +1000393static int __init of_find_i2c_driver(struct device_node *node,
394 struct i2c_board_info *info)
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000395{
396 int i;
397
398 for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
399 if (!of_device_is_compatible(node, i2c_devices[i].of_device))
400 continue;
Guennadi Liakhovetskie78bb5d2007-08-16 05:15:03 +1000401 if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
402 KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
403 strlcpy(info->type, i2c_devices[i].i2c_type,
404 I2C_NAME_SIZE) >= I2C_NAME_SIZE)
405 return -ENOMEM;
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000406 return 0;
407 }
408 return -ENODEV;
409}
410
Guennadi Liakhovetskie78bb5d2007-08-16 05:15:03 +1000411static void __init of_register_i2c_devices(struct device_node *adap_node,
412 int bus_num)
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000413{
414 struct device_node *node = NULL;
415
416 while ((node = of_get_next_child(adap_node, node))) {
Anton Vorontsovda1bb3a2007-10-02 17:47:40 +0400417 struct i2c_board_info info = {};
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000418 const u32 *addr;
419 int len;
420
421 addr = of_get_property(node, "reg", &len);
422 if (!addr || len < sizeof(int) || *addr > (1 << 10) - 1) {
Peter Korsgaard210805e2007-09-20 12:42:12 +0200423 printk(KERN_WARNING "fsl_soc.c: invalid i2c device entry\n");
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000424 continue;
425 }
426
427 info.irq = irq_of_parse_and_map(node, 0);
428 if (info.irq == NO_IRQ)
429 info.irq = -1;
430
431 if (of_find_i2c_driver(node, &info) < 0)
432 continue;
433
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000434 info.addr = *addr;
435
436 i2c_register_board_info(bus_num, &info, 1);
437 }
438}
439
Kumar Galaeed32002006-01-13 11:19:13 -0600440static int __init fsl_i2c_of_init(void)
441{
442 struct device_node *np;
Kumar Galaec9686c2007-12-11 23:17:24 -0600443 unsigned int i = 0;
Kumar Galaeed32002006-01-13 11:19:13 -0600444 struct platform_device *i2c_dev;
445 int ret;
446
Kumar Galaec9686c2007-12-11 23:17:24 -0600447 for_each_compatible_node(np, NULL, "fsl-i2c") {
Kumar Galaeed32002006-01-13 11:19:13 -0600448 struct resource r[2];
449 struct fsl_i2c_platform_data i2c_data;
Jeremy Kerra7f67bd2006-07-12 15:35:54 +1000450 const unsigned char *flags = NULL;
Kumar Galaeed32002006-01-13 11:19:13 -0600451
452 memset(&r, 0, sizeof(r));
453 memset(&i2c_data, 0, sizeof(i2c_data));
454
455 ret = of_address_to_resource(np, 0, &r[0]);
456 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600457 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600458
Andy Fleminga9b14972006-10-19 19:52:26 -0500459 of_irq_to_resource(np, 0, &r[1]);
Kumar Galaeed32002006-01-13 11:19:13 -0600460
461 i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2);
462 if (IS_ERR(i2c_dev)) {
463 ret = PTR_ERR(i2c_dev);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600464 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600465 }
466
467 i2c_data.device_flags = 0;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000468 flags = of_get_property(np, "dfsrr", NULL);
Kumar Galaeed32002006-01-13 11:19:13 -0600469 if (flags)
470 i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR;
471
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000472 flags = of_get_property(np, "fsl5200-clocking", NULL);
Kumar Galaeed32002006-01-13 11:19:13 -0600473 if (flags)
474 i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200;
475
Kumar Gala2fb07d72006-01-23 16:58:04 -0600476 ret =
477 platform_device_add_data(i2c_dev, &i2c_data,
478 sizeof(struct
479 fsl_i2c_platform_data));
Kumar Galaeed32002006-01-13 11:19:13 -0600480 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600481 goto unreg;
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000482
Kumar Galaec9686c2007-12-11 23:17:24 -0600483 of_register_i2c_devices(np, i++);
Kumar Galaeed32002006-01-13 11:19:13 -0600484 }
485
486 return 0;
487
Kumar Gala2fb07d72006-01-23 16:58:04 -0600488unreg:
Kumar Galaeed32002006-01-13 11:19:13 -0600489 platform_device_unregister(i2c_dev);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600490err:
Kumar Galaeed32002006-01-13 11:19:13 -0600491 return ret;
492}
Kumar Gala2fb07d72006-01-23 16:58:04 -0600493
Kumar Galaeed32002006-01-13 11:19:13 -0600494arch_initcall(fsl_i2c_of_init);
Guennadi Liakhovetskid13ae862007-07-21 06:26:15 +1000495#endif
Kumar Galaeed32002006-01-13 11:19:13 -0600496
497#ifdef CONFIG_PPC_83xx
498static int __init mpc83xx_wdt_init(void)
499{
500 struct resource r;
501 struct device_node *soc, *np;
502 struct platform_device *dev;
Jeremy Kerra7f67bd2006-07-12 15:35:54 +1000503 const unsigned int *freq;
Kumar Galaeed32002006-01-13 11:19:13 -0600504 int ret;
505
506 np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt");
507
508 if (!np) {
509 ret = -ENODEV;
Kumar Gala2fb07d72006-01-23 16:58:04 -0600510 goto nodev;
Kumar Galaeed32002006-01-13 11:19:13 -0600511 }
512
513 soc = of_find_node_by_type(NULL, "soc");
514
515 if (!soc) {
516 ret = -ENODEV;
Kumar Gala2fb07d72006-01-23 16:58:04 -0600517 goto nosoc;
Kumar Galaeed32002006-01-13 11:19:13 -0600518 }
519
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000520 freq = of_get_property(soc, "bus-frequency", NULL);
Kumar Galaeed32002006-01-13 11:19:13 -0600521 if (!freq) {
522 ret = -ENODEV;
Kumar Gala2fb07d72006-01-23 16:58:04 -0600523 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600524 }
525
526 memset(&r, 0, sizeof(r));
527
528 ret = of_address_to_resource(np, 0, &r);
529 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600530 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600531
532 dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1);
533 if (IS_ERR(dev)) {
534 ret = PTR_ERR(dev);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600535 goto err;
Kumar Galaeed32002006-01-13 11:19:13 -0600536 }
537
538 ret = platform_device_add_data(dev, freq, sizeof(int));
539 if (ret)
Kumar Gala2fb07d72006-01-23 16:58:04 -0600540 goto unreg;
Kumar Galaeed32002006-01-13 11:19:13 -0600541
542 of_node_put(soc);
543 of_node_put(np);
544
545 return 0;
546
Kumar Gala2fb07d72006-01-23 16:58:04 -0600547unreg:
Kumar Galaeed32002006-01-13 11:19:13 -0600548 platform_device_unregister(dev);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600549err:
Kumar Galaeed32002006-01-13 11:19:13 -0600550 of_node_put(soc);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600551nosoc:
Kumar Galaeed32002006-01-13 11:19:13 -0600552 of_node_put(np);
Kumar Gala2fb07d72006-01-23 16:58:04 -0600553nodev:
Kumar Galaeed32002006-01-13 11:19:13 -0600554 return ret;
555}
Kumar Gala2fb07d72006-01-23 16:58:04 -0600556
Kumar Galaeed32002006-01-13 11:19:13 -0600557arch_initcall(mpc83xx_wdt_init);
558#endif
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600559
Jeremy Kerra7f67bd2006-07-12 15:35:54 +1000560static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600561{
562 if (!phy_type)
563 return FSL_USB2_PHY_NONE;
564 if (!strcasecmp(phy_type, "ulpi"))
565 return FSL_USB2_PHY_ULPI;
566 if (!strcasecmp(phy_type, "utmi"))
567 return FSL_USB2_PHY_UTMI;
568 if (!strcasecmp(phy_type, "utmi_wide"))
569 return FSL_USB2_PHY_UTMI_WIDE;
570 if (!strcasecmp(phy_type, "serial"))
571 return FSL_USB2_PHY_SERIAL;
572
573 return FSL_USB2_PHY_NONE;
574}
575
576static int __init fsl_usb_of_init(void)
577{
578 struct device_node *np;
Li Yang866b6dd2008-01-08 15:18:46 +0800579 unsigned int i = 0;
Li Yang97c5a202007-02-07 13:49:24 +0800580 struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
581 *usb_dev_dr_client = NULL;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600582 int ret;
583
Li Yang866b6dd2008-01-08 15:18:46 +0800584 for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600585 struct resource r[2];
586 struct fsl_usb2_platform_data usb_data;
Jeremy Kerra7f67bd2006-07-12 15:35:54 +1000587 const unsigned char *prop = NULL;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600588
589 memset(&r, 0, sizeof(r));
590 memset(&usb_data, 0, sizeof(usb_data));
591
592 ret = of_address_to_resource(np, 0, &r[0]);
593 if (ret)
594 goto err;
595
Andy Fleminga9b14972006-10-19 19:52:26 -0500596 of_irq_to_resource(np, 0, &r[1]);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600597
Kumar Gala01cced22006-04-11 10:07:16 -0500598 usb_dev_mph =
599 platform_device_register_simple("fsl-ehci", i, r, 2);
600 if (IS_ERR(usb_dev_mph)) {
601 ret = PTR_ERR(usb_dev_mph);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600602 goto err;
603 }
604
Kumar Gala01cced22006-04-11 10:07:16 -0500605 usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
606 usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600607
608 usb_data.operating_mode = FSL_USB2_MPH_HOST;
609
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000610 prop = of_get_property(np, "port0", NULL);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600611 if (prop)
612 usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;
613
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000614 prop = of_get_property(np, "port1", NULL);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600615 if (prop)
616 usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;
617
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000618 prop = of_get_property(np, "phy_type", NULL);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600619 usb_data.phy_mode = determine_usb_phy(prop);
620
621 ret =
Kumar Gala01cced22006-04-11 10:07:16 -0500622 platform_device_add_data(usb_dev_mph, &usb_data,
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600623 sizeof(struct
624 fsl_usb2_platform_data));
625 if (ret)
Kumar Gala01cced22006-04-11 10:07:16 -0500626 goto unreg_mph;
Li Yang866b6dd2008-01-08 15:18:46 +0800627 i++;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600628 }
629
Li Yang866b6dd2008-01-08 15:18:46 +0800630 for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600631 struct resource r[2];
632 struct fsl_usb2_platform_data usb_data;
Jeremy Kerra7f67bd2006-07-12 15:35:54 +1000633 const unsigned char *prop = NULL;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600634
635 memset(&r, 0, sizeof(r));
636 memset(&usb_data, 0, sizeof(usb_data));
637
638 ret = of_address_to_resource(np, 0, &r[0]);
639 if (ret)
Kumar Gala01cced22006-04-11 10:07:16 -0500640 goto unreg_mph;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600641
Andy Fleminga9b14972006-10-19 19:52:26 -0500642 of_irq_to_resource(np, 0, &r[1]);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600643
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000644 prop = of_get_property(np, "dr_mode", NULL);
Li Yang97c5a202007-02-07 13:49:24 +0800645
646 if (!prop || !strcmp(prop, "host")) {
647 usb_data.operating_mode = FSL_USB2_DR_HOST;
648 usb_dev_dr_host = platform_device_register_simple(
649 "fsl-ehci", i, r, 2);
650 if (IS_ERR(usb_dev_dr_host)) {
651 ret = PTR_ERR(usb_dev_dr_host);
652 goto err;
653 }
654 } else if (prop && !strcmp(prop, "peripheral")) {
655 usb_data.operating_mode = FSL_USB2_DR_DEVICE;
656 usb_dev_dr_client = platform_device_register_simple(
657 "fsl-usb2-udc", i, r, 2);
658 if (IS_ERR(usb_dev_dr_client)) {
659 ret = PTR_ERR(usb_dev_dr_client);
660 goto err;
661 }
662 } else if (prop && !strcmp(prop, "otg")) {
663 usb_data.operating_mode = FSL_USB2_DR_OTG;
664 usb_dev_dr_host = platform_device_register_simple(
665 "fsl-ehci", i, r, 2);
666 if (IS_ERR(usb_dev_dr_host)) {
667 ret = PTR_ERR(usb_dev_dr_host);
668 goto err;
669 }
670 usb_dev_dr_client = platform_device_register_simple(
671 "fsl-usb2-udc", i, r, 2);
672 if (IS_ERR(usb_dev_dr_client)) {
673 ret = PTR_ERR(usb_dev_dr_client);
674 goto err;
675 }
676 } else {
677 ret = -EINVAL;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600678 goto err;
679 }
680
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000681 prop = of_get_property(np, "phy_type", NULL);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600682 usb_data.phy_mode = determine_usb_phy(prop);
683
Li Yang97c5a202007-02-07 13:49:24 +0800684 if (usb_dev_dr_host) {
685 usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
686 usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
687 dev.coherent_dma_mask;
688 if ((ret = platform_device_add_data(usb_dev_dr_host,
689 &usb_data, sizeof(struct
690 fsl_usb2_platform_data))))
691 goto unreg_dr;
692 }
693 if (usb_dev_dr_client) {
694 usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
695 usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
696 dev.coherent_dma_mask;
697 if ((ret = platform_device_add_data(usb_dev_dr_client,
698 &usb_data, sizeof(struct
699 fsl_usb2_platform_data))))
700 goto unreg_dr;
701 }
Li Yang866b6dd2008-01-08 15:18:46 +0800702 i++;
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600703 }
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600704 return 0;
705
Kumar Gala01cced22006-04-11 10:07:16 -0500706unreg_dr:
Li Yang97c5a202007-02-07 13:49:24 +0800707 if (usb_dev_dr_host)
708 platform_device_unregister(usb_dev_dr_host);
709 if (usb_dev_dr_client)
710 platform_device_unregister(usb_dev_dr_client);
Kumar Gala01cced22006-04-11 10:07:16 -0500711unreg_mph:
712 if (usb_dev_mph)
713 platform_device_unregister(usb_dev_mph);
Kumar Gala4b10cfd2006-02-02 12:31:00 -0600714err:
715 return ret;
716}
717
Kumar Gala01cced22006-04-11 10:07:16 -0500718arch_initcall(fsl_usb_of_init);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400719
Scott Woode631ae32007-09-14 13:04:54 -0500720#ifndef CONFIG_PPC_CPM_NEW_BINDING
Vitaly Bordugfba43662006-09-21 17:26:34 +0400721#ifdef CONFIG_CPM2
722
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +0300723extern void init_scc_ioports(struct fs_uart_platform_info*);
724
Vitaly Bordugfba43662006-09-21 17:26:34 +0400725static const char fcc_regs[] = "fcc_regs";
726static const char fcc_regs_c[] = "fcc_regs_c";
727static const char fcc_pram[] = "fcc_pram";
728static char bus_id[9][BUS_ID_SIZE];
729
730static int __init fs_enet_of_init(void)
731{
732 struct device_node *np;
733 unsigned int i;
734 struct platform_device *fs_enet_dev;
735 struct resource res;
736 int ret;
737
738 for (np = NULL, i = 0;
739 (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
740 i++) {
741 struct resource r[4];
742 struct device_node *phy, *mdio;
743 struct fs_platform_info fs_enet_data;
Olof Johansson2b00b252006-10-05 21:16:48 -0500744 const unsigned int *id, *phy_addr, *phy_irq;
Vitaly Bordugfba43662006-09-21 17:26:34 +0400745 const void *mac_addr;
746 const phandle *ph;
747 const char *model;
748
749 memset(r, 0, sizeof(r));
750 memset(&fs_enet_data, 0, sizeof(fs_enet_data));
751
752 ret = of_address_to_resource(np, 0, &r[0]);
753 if (ret)
754 goto err;
755 r[0].name = fcc_regs;
756
757 ret = of_address_to_resource(np, 1, &r[1]);
758 if (ret)
759 goto err;
760 r[1].name = fcc_pram;
761
762 ret = of_address_to_resource(np, 2, &r[2]);
763 if (ret)
764 goto err;
765 r[2].name = fcc_regs_c;
Vitaly Borduged943c12006-10-02 22:41:50 +0400766 fs_enet_data.fcc_regs_c = r[2].start;
Vitaly Bordugfba43662006-09-21 17:26:34 +0400767
Andy Fleminga9b14972006-10-19 19:52:26 -0500768 of_irq_to_resource(np, 0, &r[3]);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400769
770 fs_enet_dev =
771 platform_device_register_simple("fsl-cpm-fcc", i, &r[0], 4);
772
773 if (IS_ERR(fs_enet_dev)) {
774 ret = PTR_ERR(fs_enet_dev);
775 goto err;
776 }
777
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000778 model = of_get_property(np, "model", NULL);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400779 if (model == NULL) {
780 ret = -ENODEV;
781 goto unreg;
782 }
783
Timur Tabi29cfe6f2007-02-16 12:01:29 -0600784 mac_addr = of_get_mac_address(np);
785 if (mac_addr)
786 memcpy(fs_enet_data.macaddr, mac_addr, 6);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400787
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000788 ph = of_get_property(np, "phy-handle", NULL);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400789 phy = of_find_node_by_phandle(*ph);
790
791 if (phy == NULL) {
792 ret = -ENODEV;
793 goto unreg;
794 }
795
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000796 phy_addr = of_get_property(phy, "reg", NULL);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400797 fs_enet_data.phy_addr = *phy_addr;
798
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000799 phy_irq = of_get_property(phy, "interrupts", NULL);
Vitaly Borduged943c12006-10-02 22:41:50 +0400800
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000801 id = of_get_property(np, "device-id", NULL);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400802 fs_enet_data.fs_no = *id;
Vitaly Bordug611a15a2006-09-21 22:38:05 +0400803 strcpy(fs_enet_data.fs_type, model);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400804
805 mdio = of_get_parent(phy);
806 ret = of_address_to_resource(mdio, 0, &res);
807 if (ret) {
808 of_node_put(phy);
809 of_node_put(mdio);
810 goto unreg;
811 }
812
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000813 fs_enet_data.clk_rx = *((u32 *)of_get_property(np,
814 "rx-clock", NULL));
815 fs_enet_data.clk_tx = *((u32 *)of_get_property(np,
816 "tx-clock", NULL));
Vitaly Bordugd3465c92006-09-21 22:38:05 +0400817
Vitaly Bordugfba43662006-09-21 17:26:34 +0400818 if (strstr(model, "FCC")) {
Vitaly Bordug611a15a2006-09-21 22:38:05 +0400819 int fcc_index = *id - 1;
Olof Johansson2b00b252006-10-05 21:16:48 -0500820 const unsigned char *mdio_bb_prop;
Vitaly Bordugfba43662006-09-21 17:26:34 +0400821
Vitaly Bordugfc8e50e2006-09-21 22:37:58 +0400822 fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400823 fs_enet_data.rx_ring = 32;
824 fs_enet_data.tx_ring = 32;
825 fs_enet_data.rx_copybreak = 240;
826 fs_enet_data.use_napi = 0;
827 fs_enet_data.napi_weight = 17;
828 fs_enet_data.mem_offset = FCC_MEM_OFFSET(fcc_index);
829 fs_enet_data.cp_page = CPM_CR_FCC_PAGE(fcc_index);
830 fs_enet_data.cp_block = CPM_CR_FCC_SBLOCK(fcc_index);
831
832 snprintf((char*)&bus_id[(*id)], BUS_ID_SIZE, "%x:%02x",
833 (u32)res.start, fs_enet_data.phy_addr);
834 fs_enet_data.bus_id = (char*)&bus_id[(*id)];
Vitaly Bordugd3465c92006-09-21 22:38:05 +0400835 fs_enet_data.init_ioports = init_fcc_ioports;
Vitaly Bordugfba43662006-09-21 17:26:34 +0400836
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000837 mdio_bb_prop = of_get_property(phy, "bitbang", NULL);
Vitaly Borduged943c12006-10-02 22:41:50 +0400838 if (mdio_bb_prop) {
839 struct platform_device *fs_enet_mdio_bb_dev;
840 struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;
Vitaly Bordugfba43662006-09-21 17:26:34 +0400841
Vitaly Borduged943c12006-10-02 22:41:50 +0400842 fs_enet_mdio_bb_dev =
843 platform_device_register_simple("fsl-bb-mdio",
844 i, NULL, 0);
845 memset(&fs_enet_mdio_bb_data, 0,
846 sizeof(struct fs_mii_bb_platform_info));
847 fs_enet_mdio_bb_data.mdio_dat.bit =
848 mdio_bb_prop[0];
849 fs_enet_mdio_bb_data.mdio_dir.bit =
850 mdio_bb_prop[1];
851 fs_enet_mdio_bb_data.mdc_dat.bit =
852 mdio_bb_prop[2];
853 fs_enet_mdio_bb_data.mdio_port =
854 mdio_bb_prop[3];
855 fs_enet_mdio_bb_data.mdc_port =
856 mdio_bb_prop[4];
857 fs_enet_mdio_bb_data.delay =
858 mdio_bb_prop[5];
859
860 fs_enet_mdio_bb_data.irq[0] = phy_irq[0];
861 fs_enet_mdio_bb_data.irq[1] = -1;
862 fs_enet_mdio_bb_data.irq[2] = -1;
863 fs_enet_mdio_bb_data.irq[3] = phy_irq[0];
864 fs_enet_mdio_bb_data.irq[31] = -1;
865
866 fs_enet_mdio_bb_data.mdio_dat.offset =
867 (u32)&cpm2_immr->im_ioport.iop_pdatc;
868 fs_enet_mdio_bb_data.mdio_dir.offset =
869 (u32)&cpm2_immr->im_ioport.iop_pdirc;
870 fs_enet_mdio_bb_data.mdc_dat.offset =
871 (u32)&cpm2_immr->im_ioport.iop_pdatc;
872
873 ret = platform_device_add_data(
874 fs_enet_mdio_bb_dev,
875 &fs_enet_mdio_bb_data,
876 sizeof(struct fs_mii_bb_platform_info));
877 if (ret)
878 goto unreg;
879 }
Li Yang97c5a202007-02-07 13:49:24 +0800880
Vitaly Borduged943c12006-10-02 22:41:50 +0400881 of_node_put(phy);
882 of_node_put(mdio);
883
884 ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
885 sizeof(struct
886 fs_platform_info));
Olof Johansson2b00b252006-10-05 21:16:48 -0500887 if (ret)
888 goto unreg;
889 }
Vitaly Bordugfba43662006-09-21 17:26:34 +0400890 }
891 return 0;
892
893unreg:
894 platform_device_unregister(fs_enet_dev);
895err:
896 return ret;
897}
898
899arch_initcall(fs_enet_of_init);
900
901static const char scc_regs[] = "regs";
902static const char scc_pram[] = "pram";
903
904static int __init cpm_uart_of_init(void)
905{
906 struct device_node *np;
907 unsigned int i;
908 struct platform_device *cpm_uart_dev;
909 int ret;
910
911 for (np = NULL, i = 0;
912 (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
913 i++) {
914 struct resource r[3];
915 struct fs_uart_platform_info cpm_uart_data;
916 const int *id;
Vitaly Bordug611a15a2006-09-21 22:38:05 +0400917 const char *model;
Vitaly Bordugfba43662006-09-21 17:26:34 +0400918
919 memset(r, 0, sizeof(r));
920 memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
921
922 ret = of_address_to_resource(np, 0, &r[0]);
923 if (ret)
924 goto err;
925
926 r[0].name = scc_regs;
927
928 ret = of_address_to_resource(np, 1, &r[1]);
929 if (ret)
930 goto err;
931 r[1].name = scc_pram;
932
Andy Fleminga9b14972006-10-19 19:52:26 -0500933 of_irq_to_resource(np, 0, &r[2]);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400934
935 cpm_uart_dev =
936 platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3);
937
938 if (IS_ERR(cpm_uart_dev)) {
939 ret = PTR_ERR(cpm_uart_dev);
940 goto err;
941 }
942
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000943 id = of_get_property(np, "device-id", NULL);
Vitaly Bordugfba43662006-09-21 17:26:34 +0400944 cpm_uart_data.fs_no = *id;
Vitaly Bordug611a15a2006-09-21 22:38:05 +0400945
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000946 model = of_get_property(np, "model", NULL);
Vitaly Bordug611a15a2006-09-21 22:38:05 +0400947 strcpy(cpm_uart_data.fs_type, model);
948
Vitaly Bordugfba43662006-09-21 17:26:34 +0400949 cpm_uart_data.uart_clk = ppc_proc_freq;
950
951 cpm_uart_data.tx_num_fifo = 4;
952 cpm_uart_data.tx_buf_size = 32;
953 cpm_uart_data.rx_num_fifo = 4;
954 cpm_uart_data.rx_buf_size = 32;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000955 cpm_uart_data.clk_rx = *((u32 *)of_get_property(np,
956 "rx-clock", NULL));
957 cpm_uart_data.clk_tx = *((u32 *)of_get_property(np,
958 "tx-clock", NULL));
Vitaly Bordugfba43662006-09-21 17:26:34 +0400959
960 ret =
961 platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
962 sizeof(struct
963 fs_uart_platform_info));
964 if (ret)
965 goto unreg;
966 }
967
968 return 0;
969
970unreg:
971 platform_device_unregister(cpm_uart_dev);
972err:
973 return ret;
974}
975
976arch_initcall(cpm_uart_of_init);
977#endif /* CONFIG_CPM2 */
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +0300978
979#ifdef CONFIG_8xx
980
981extern void init_scc_ioports(struct fs_platform_info*);
Stephen Rothwelle2eb6392007-04-03 22:26:41 +1000982extern int platform_device_skip(const char *model, int id);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +0300983
984static int __init fs_enet_mdio_of_init(void)
985{
986 struct device_node *np;
987 unsigned int i;
988 struct platform_device *mdio_dev;
989 struct resource res;
990 int ret;
991
992 for (np = NULL, i = 0;
993 (np = of_find_compatible_node(np, "mdio", "fs_enet")) != NULL;
994 i++) {
995 struct fs_mii_fec_platform_info mdio_data;
996
997 memset(&res, 0, sizeof(res));
998 memset(&mdio_data, 0, sizeof(mdio_data));
999
1000 ret = of_address_to_resource(np, 0, &res);
1001 if (ret)
1002 goto err;
1003
1004 mdio_dev =
1005 platform_device_register_simple("fsl-cpm-fec-mdio",
1006 res.start, &res, 1);
1007 if (IS_ERR(mdio_dev)) {
1008 ret = PTR_ERR(mdio_dev);
1009 goto err;
1010 }
1011
1012 mdio_data.mii_speed = ((((ppc_proc_freq + 4999999) / 2500000) / 2) & 0x3F) << 1;
1013
1014 ret =
1015 platform_device_add_data(mdio_dev, &mdio_data,
1016 sizeof(struct fs_mii_fec_platform_info));
1017 if (ret)
1018 goto unreg;
1019 }
1020 return 0;
1021
1022unreg:
1023 platform_device_unregister(mdio_dev);
1024err:
1025 return ret;
1026}
1027
1028arch_initcall(fs_enet_mdio_of_init);
1029
1030static const char *enet_regs = "regs";
1031static const char *enet_pram = "pram";
1032static const char *enet_irq = "interrupt";
1033static char bus_id[9][BUS_ID_SIZE];
1034
1035static int __init fs_enet_of_init(void)
1036{
1037 struct device_node *np;
1038 unsigned int i;
1039 struct platform_device *fs_enet_dev = NULL;
1040 struct resource res;
1041 int ret;
1042
1043 for (np = NULL, i = 0;
1044 (np = of_find_compatible_node(np, "network", "fs_enet")) != NULL;
1045 i++) {
1046 struct resource r[4];
1047 struct device_node *phy = NULL, *mdio = NULL;
1048 struct fs_platform_info fs_enet_data;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001049 const unsigned int *id;
1050 const unsigned int *phy_addr;
Scott Woodb7a69122007-05-09 03:15:34 +10001051 const void *mac_addr;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001052 const phandle *ph;
1053 const char *model;
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001054
1055 memset(r, 0, sizeof(r));
1056 memset(&fs_enet_data, 0, sizeof(fs_enet_data));
1057
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001058 model = of_get_property(np, "model", NULL);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001059 if (model == NULL) {
1060 ret = -ENODEV;
1061 goto unreg;
1062 }
1063
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001064 id = of_get_property(np, "device-id", NULL);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001065 fs_enet_data.fs_no = *id;
1066
1067 if (platform_device_skip(model, *id))
1068 continue;
1069
1070 ret = of_address_to_resource(np, 0, &r[0]);
1071 if (ret)
1072 goto err;
1073 r[0].name = enet_regs;
1074
Timur Tabi29cfe6f2007-02-16 12:01:29 -06001075 mac_addr = of_get_mac_address(np);
1076 if (mac_addr)
1077 memcpy(fs_enet_data.macaddr, mac_addr, 6);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001078
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001079 ph = of_get_property(np, "phy-handle", NULL);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001080 if (ph != NULL)
1081 phy = of_find_node_by_phandle(*ph);
1082
1083 if (phy != NULL) {
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001084 phy_addr = of_get_property(phy, "reg", NULL);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001085 fs_enet_data.phy_addr = *phy_addr;
1086 fs_enet_data.has_phy = 1;
1087
1088 mdio = of_get_parent(phy);
1089 ret = of_address_to_resource(mdio, 0, &res);
1090 if (ret) {
1091 of_node_put(phy);
1092 of_node_put(mdio);
1093 goto unreg;
1094 }
1095 }
1096
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001097 model = of_get_property(np, "model", NULL);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001098 strcpy(fs_enet_data.fs_type, model);
1099
1100 if (strstr(model, "FEC")) {
1101 r[1].start = r[1].end = irq_of_parse_and_map(np, 0);
1102 r[1].flags = IORESOURCE_IRQ;
1103 r[1].name = enet_irq;
1104
1105 fs_enet_dev =
1106 platform_device_register_simple("fsl-cpm-fec", i, &r[0], 2);
1107
1108 if (IS_ERR(fs_enet_dev)) {
1109 ret = PTR_ERR(fs_enet_dev);
1110 goto err;
1111 }
1112
1113 fs_enet_data.rx_ring = 128;
1114 fs_enet_data.tx_ring = 16;
1115 fs_enet_data.rx_copybreak = 240;
1116 fs_enet_data.use_napi = 1;
1117 fs_enet_data.napi_weight = 17;
1118
1119 snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%x:%02x",
1120 (u32)res.start, fs_enet_data.phy_addr);
1121 fs_enet_data.bus_id = (char*)&bus_id[i];
1122 fs_enet_data.init_ioports = init_fec_ioports;
1123 }
1124 if (strstr(model, "SCC")) {
1125 ret = of_address_to_resource(np, 1, &r[1]);
1126 if (ret)
1127 goto err;
1128 r[1].name = enet_pram;
1129
1130 r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
1131 r[2].flags = IORESOURCE_IRQ;
1132 r[2].name = enet_irq;
1133
1134 fs_enet_dev =
1135 platform_device_register_simple("fsl-cpm-scc", i, &r[0], 3);
1136
1137 if (IS_ERR(fs_enet_dev)) {
1138 ret = PTR_ERR(fs_enet_dev);
1139 goto err;
1140 }
1141
1142 fs_enet_data.rx_ring = 64;
1143 fs_enet_data.tx_ring = 8;
1144 fs_enet_data.rx_copybreak = 240;
1145 fs_enet_data.use_napi = 1;
1146 fs_enet_data.napi_weight = 17;
1147
1148 snprintf((char*)&bus_id[i], BUS_ID_SIZE, "%s", "fixed@10:1");
1149 fs_enet_data.bus_id = (char*)&bus_id[i];
1150 fs_enet_data.init_ioports = init_scc_ioports;
1151 }
1152
1153 of_node_put(phy);
1154 of_node_put(mdio);
1155
1156 ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
1157 sizeof(struct
1158 fs_platform_info));
1159 if (ret)
1160 goto unreg;
1161 }
1162 return 0;
1163
1164unreg:
1165 platform_device_unregister(fs_enet_dev);
1166err:
1167 return ret;
1168}
1169
1170arch_initcall(fs_enet_of_init);
1171
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001172static int __init fsl_pcmcia_of_init(void)
1173{
Cyrill Gorcunov26cb7d82007-11-30 06:44:36 +11001174 struct device_node *np;
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001175 /*
1176 * Register all the devices which type is "pcmcia"
1177 */
Cyrill Gorcunov26cb7d82007-11-30 06:44:36 +11001178 for_each_compatible_node(np, "pcmcia", "fsl,pq-pcmcia")
1179 of_platform_device_create(np, "m8xx-pcmcia", NULL);
Vitaly Bordug80128ff2007-07-09 11:37:35 -07001180 return 0;
1181}
1182
1183arch_initcall(fsl_pcmcia_of_init);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001184
1185static const char *smc_regs = "regs";
1186static const char *smc_pram = "pram";
1187
1188static int __init cpm_smc_uart_of_init(void)
1189{
1190 struct device_node *np;
1191 unsigned int i;
1192 struct platform_device *cpm_uart_dev;
1193 int ret;
1194
1195 for (np = NULL, i = 0;
1196 (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL;
1197 i++) {
1198 struct resource r[3];
1199 struct fs_uart_platform_info cpm_uart_data;
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001200 const int *id;
1201 const char *model;
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001202
1203 memset(r, 0, sizeof(r));
1204 memset(&cpm_uart_data, 0, sizeof(cpm_uart_data));
1205
1206 ret = of_address_to_resource(np, 0, &r[0]);
1207 if (ret)
1208 goto err;
1209
1210 r[0].name = smc_regs;
1211
1212 ret = of_address_to_resource(np, 1, &r[1]);
1213 if (ret)
1214 goto err;
1215 r[1].name = smc_pram;
1216
1217 r[2].start = r[2].end = irq_of_parse_and_map(np, 0);
1218 r[2].flags = IORESOURCE_IRQ;
1219
1220 cpm_uart_dev =
1221 platform_device_register_simple("fsl-cpm-smc:uart", i, &r[0], 3);
1222
1223 if (IS_ERR(cpm_uart_dev)) {
1224 ret = PTR_ERR(cpm_uart_dev);
1225 goto err;
1226 }
1227
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001228 model = of_get_property(np, "model", NULL);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001229 strcpy(cpm_uart_data.fs_type, model);
1230
Stephen Rothwelle2eb6392007-04-03 22:26:41 +10001231 id = of_get_property(np, "device-id", NULL);
Vitaly Bordug88bdc6f2007-01-24 22:41:15 +03001232 cpm_uart_data.fs_no = *id;
1233 cpm_uart_data.uart_clk = ppc_proc_freq;
1234
1235 cpm_uart_data.tx_num_fifo = 4;
1236 cpm_uart_data.tx_buf_size = 32;
1237 cpm_uart_data.rx_num_fifo = 4;
1238 cpm_uart_data.rx_buf_size = 32;
1239
1240 ret =
1241 platform_device_add_data(cpm_uart_dev, &cpm_uart_data,
1242 sizeof(struct
1243 fs_uart_platform_info));
1244 if (ret)
1245 goto unreg;
1246 }
1247
1248 return 0;
1249
1250unreg:
1251 platform_device_unregister(cpm_uart_dev);
1252err:
1253 return ret;
1254}
1255
1256arch_initcall(cpm_smc_uart_of_init);
1257
1258#endif /* CONFIG_8xx */
Scott Woode631ae32007-09-14 13:04:54 -05001259#endif /* CONFIG_PPC_CPM_NEW_BINDING */
Anton Vorontsov26f6cb92007-08-23 15:35:56 +04001260
1261int __init fsl_spi_init(struct spi_board_info *board_infos,
1262 unsigned int num_board_infos,
1263 void (*activate_cs)(u8 cs, u8 polarity),
1264 void (*deactivate_cs)(u8 cs, u8 polarity))
1265{
1266 struct device_node *np;
1267 unsigned int i;
1268 const u32 *sysclk;
1269
Peter Korsgaard082ea862007-10-06 22:06:40 +02001270 /* SPI controller is either clocked from QE or SoC clock */
Anton Vorontsov26f6cb92007-08-23 15:35:56 +04001271 np = of_find_node_by_type(NULL, "qe");
1272 if (!np)
Peter Korsgaard082ea862007-10-06 22:06:40 +02001273 np = of_find_node_by_type(NULL, "soc");
1274
1275 if (!np)
Anton Vorontsov26f6cb92007-08-23 15:35:56 +04001276 return -ENODEV;
1277
1278 sysclk = of_get_property(np, "bus-frequency", NULL);
1279 if (!sysclk)
1280 return -ENODEV;
1281
1282 for (np = NULL, i = 1;
1283 (np = of_find_compatible_node(np, "spi", "fsl_spi")) != NULL;
1284 i++) {
1285 int ret = 0;
1286 unsigned int j;
1287 const void *prop;
1288 struct resource res[2];
1289 struct platform_device *pdev;
1290 struct fsl_spi_platform_data pdata = {
1291 .activate_cs = activate_cs,
1292 .deactivate_cs = deactivate_cs,
1293 };
1294
1295 memset(res, 0, sizeof(res));
1296
1297 pdata.sysclk = *sysclk;
1298
1299 prop = of_get_property(np, "reg", NULL);
1300 if (!prop)
1301 goto err;
1302 pdata.bus_num = *(u32 *)prop;
1303
1304 prop = of_get_property(np, "mode", NULL);
1305 if (prop && !strcmp(prop, "cpu-qe"))
1306 pdata.qe_mode = 1;
1307
1308 for (j = 0; j < num_board_infos; j++) {
1309 if (board_infos[j].bus_num == pdata.bus_num)
1310 pdata.max_chipselect++;
1311 }
1312
1313 if (!pdata.max_chipselect)
1314 goto err;
1315
1316 ret = of_address_to_resource(np, 0, &res[0]);
1317 if (ret)
1318 goto err;
1319
1320 ret = of_irq_to_resource(np, 0, &res[1]);
1321 if (ret == NO_IRQ)
1322 goto err;
1323
1324 pdev = platform_device_alloc("mpc83xx_spi", i);
1325 if (!pdev)
1326 goto err;
1327
1328 ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
1329 if (ret)
1330 goto unreg;
1331
1332 ret = platform_device_add_resources(pdev, res,
1333 ARRAY_SIZE(res));
1334 if (ret)
1335 goto unreg;
1336
1337 ret = platform_device_register(pdev);
1338 if (ret)
1339 goto unreg;
1340
1341 continue;
1342unreg:
1343 platform_device_del(pdev);
1344err:
1345 continue;
1346 }
1347
1348 return spi_register_board_info(board_infos, num_board_infos);
1349}
Kumar Galae1c15752007-10-04 01:04:57 -05001350
1351#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
1352static __be32 __iomem *rstcr;
1353
1354static int __init setup_rstcr(void)
1355{
1356 struct device_node *np;
1357 np = of_find_node_by_name(NULL, "global-utilities");
1358 if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
1359 const u32 *prop = of_get_property(np, "reg", NULL);
1360 if (prop) {
1361 /* map reset control register
1362 * 0xE00B0 is offset of reset control register
1363 */
1364 rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
1365 if (!rstcr)
1366 printk (KERN_EMERG "Error: reset control "
1367 "register not mapped!\n");
1368 }
1369 } else
1370 printk (KERN_INFO "rstcr compatible register does not exist!\n");
1371 if (np)
1372 of_node_put(np);
1373 return 0;
1374}
1375
1376arch_initcall(setup_rstcr);
1377
1378void fsl_rstcr_restart(char *cmd)
1379{
1380 local_irq_disable();
1381 if (rstcr)
1382 /* set reset control register */
1383 out_be32(rstcr, 0x2); /* HRESET_REQ */
1384
1385 while (1) ;
1386}
1387#endif