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