Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/*
  2 * Platform device setup for Marvell mv64360/mv64460 host bridges (Discovery)
  3 *
  4 * Author: Dale Farnsworth <dale@farnsworth.org>
  5 *
  6 * 2007 (c) MontaVista, Software, Inc.  This file is licensed under
  7 * the terms of the GNU General Public License version 2.  This program
  8 * is licensed "as is" without any warranty of any kind, whether express
  9 * or implied.
 10 */
 11
 12#include <linux/stddef.h>
 13#include <linux/kernel.h>
 14#include <linux/init.h>
 15#include <linux/console.h>
 16#include <linux/mv643xx.h>
 17#include <linux/platform_device.h>
 18#include <linux/of_platform.h>
 19#include <linux/of_net.h>
 20#include <linux/dma-mapping.h>
 21
 22#include <asm/prom.h>
 23
 24/* These functions provide the necessary setup for the mv64x60 drivers. */
 25
 26static struct of_device_id __initdata of_mv64x60_devices[] = {
 27	{ .compatible = "marvell,mv64306-devctrl", },
 28	{}
 29};
 30
 31/*
 32 * Create MPSC platform devices
 33 */
 34static int __init mv64x60_mpsc_register_shared_pdev(struct device_node *np)
 35{
 36	struct platform_device *pdev;
 37	struct resource r[2];
 38	struct mpsc_shared_pdata pdata;
 39	const phandle *ph;
 40	struct device_node *mpscrouting, *mpscintr;
 41	int err;
 42
 43	ph = of_get_property(np, "mpscrouting", NULL);
 44	mpscrouting = of_find_node_by_phandle(*ph);
 45	if (!mpscrouting)
 46		return -ENODEV;
 47
 48	err = of_address_to_resource(mpscrouting, 0, &r[0]);
 49	of_node_put(mpscrouting);
 50	if (err)
 51		return err;
 52
 53	ph = of_get_property(np, "mpscintr", NULL);
 54	mpscintr = of_find_node_by_phandle(*ph);
 55	if (!mpscintr)
 56		return -ENODEV;
 57
 58	err = of_address_to_resource(mpscintr, 0, &r[1]);
 59	of_node_put(mpscintr);
 60	if (err)
 61		return err;
 62
 63	memset(&pdata, 0, sizeof(pdata));
 64
 65	pdev = platform_device_alloc(MPSC_SHARED_NAME, 0);
 66	if (!pdev)
 67		return -ENOMEM;
 68
 69	err = platform_device_add_resources(pdev, r, 2);
 70	if (err)
 71		goto error;
 72
 73	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
 74	if (err)
 75		goto error;
 76
 77	err = platform_device_add(pdev);
 78	if (err)
 79		goto error;
 80
 81	return 0;
 82
 83error:
 84	platform_device_put(pdev);
 85	return err;
 86}
 87
 88
 89static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id)
 90{
 91	struct resource r[5];
 92	struct mpsc_pdata pdata;
 93	struct platform_device *pdev;
 94	const unsigned int *prop;
 95	const phandle *ph;
 96	struct device_node *sdma, *brg;
 97	int err;
 98	int port_number;
 99
100	/* only register the shared platform device the first time through */
101	if (id == 0 && (err = mv64x60_mpsc_register_shared_pdev(np)))
102		return err;
103
104	memset(r, 0, sizeof(r));
105
106	err = of_address_to_resource(np, 0, &r[0]);
107	if (err)
108		return err;
109
110	of_irq_to_resource(np, 0, &r[4]);
111
112	ph = of_get_property(np, "sdma", NULL);
113	sdma = of_find_node_by_phandle(*ph);
114	if (!sdma)
115		return -ENODEV;
116
117	of_irq_to_resource(sdma, 0, &r[3]);
118	err = of_address_to_resource(sdma, 0, &r[1]);
119	of_node_put(sdma);
120	if (err)
121		return err;
122
123	ph = of_get_property(np, "brg", NULL);
124	brg = of_find_node_by_phandle(*ph);
125	if (!brg)
126		return -ENODEV;
127
128	err = of_address_to_resource(brg, 0, &r[2]);
129	of_node_put(brg);
130	if (err)
131		return err;
132
133	prop = of_get_property(np, "cell-index", NULL);
134	if (!prop)
135		return -ENODEV;
136	port_number = *(int *)prop;
137
138	memset(&pdata, 0, sizeof(pdata));
139
140	pdata.cache_mgmt = 1; /* All current revs need this set */
141
142	pdata.max_idle = 40; /* default */
143	prop = of_get_property(np, "max_idle", NULL);
144	if (prop)
145		pdata.max_idle = *prop;
146
147	prop = of_get_property(brg, "current-speed", NULL);
148	if (prop)
149		pdata.default_baud = *prop;
150
151	/* Default is 8 bits, no parity, no flow control */
152	pdata.default_bits = 8;
153	pdata.default_parity = 'n';
154	pdata.default_flow = 'n';
155
156	prop = of_get_property(np, "chr_1", NULL);
157	if (prop)
158		pdata.chr_1_val = *prop;
159
160	prop = of_get_property(np, "chr_2", NULL);
161	if (prop)
162		pdata.chr_2_val = *prop;
163
164	prop = of_get_property(np, "chr_10", NULL);
165	if (prop)
166		pdata.chr_10_val = *prop;
167
168	prop = of_get_property(np, "mpcr", NULL);
169	if (prop)
170		pdata.mpcr_val = *prop;
171
172	prop = of_get_property(brg, "bcr", NULL);
173	if (prop)
174		pdata.bcr_val = *prop;
175
176	pdata.brg_can_tune = 1; /* All current revs need this set */
177
178	prop = of_get_property(brg, "clock-src", NULL);
179	if (prop)
180		pdata.brg_clk_src = *prop;
181
182	prop = of_get_property(brg, "clock-frequency", NULL);
183	if (prop)
184		pdata.brg_clk_freq = *prop;
185
186	pdev = platform_device_alloc(MPSC_CTLR_NAME, port_number);
187	if (!pdev)
188		return -ENOMEM;
189	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
190
191	err = platform_device_add_resources(pdev, r, 5);
192	if (err)
193		goto error;
194
195	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
196	if (err)
197		goto error;
198
199	err = platform_device_add(pdev);
200	if (err)
201		goto error;
202
203	return 0;
204
205error:
206	platform_device_put(pdev);
207	return err;
208}
209
210/*
211 * Create mv64x60_eth platform devices
212 */
213static struct platform_device * __init mv64x60_eth_register_shared_pdev(
214						struct device_node *np, int id)
215{
216	struct platform_device *pdev;
217	struct resource r[1];
218	int err;
219
220	err = of_address_to_resource(np, 0, &r[0]);
221	if (err)
222		return ERR_PTR(err);
223
224	pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id,
225					       r, 1);
226	return pdev;
227}
228
229static int __init mv64x60_eth_device_setup(struct device_node *np, int id,
230					   struct platform_device *shared_pdev)
231{
232	struct resource r[1];
233	struct mv643xx_eth_platform_data pdata;
234	struct platform_device *pdev;
235	struct device_node *phy;
236	const u8 *mac_addr;
237	const int *prop;
238	const phandle *ph;
239	int err;
240
241	memset(r, 0, sizeof(r));
242	of_irq_to_resource(np, 0, &r[0]);
243
244	memset(&pdata, 0, sizeof(pdata));
245
246	pdata.shared = shared_pdev;
247
248	prop = of_get_property(np, "reg", NULL);
249	if (!prop)
250		return -ENODEV;
251	pdata.port_number = *prop;
252
253	mac_addr = of_get_mac_address(np);
254	if (mac_addr)
255		memcpy(pdata.mac_addr, mac_addr, 6);
256
257	prop = of_get_property(np, "speed", NULL);
258	if (prop)
259		pdata.speed = *prop;
260
261	prop = of_get_property(np, "tx_queue_size", NULL);
262	if (prop)
263		pdata.tx_queue_size = *prop;
264
265	prop = of_get_property(np, "rx_queue_size", NULL);
266	if (prop)
267		pdata.rx_queue_size = *prop;
268
269	prop = of_get_property(np, "tx_sram_addr", NULL);
270	if (prop)
271		pdata.tx_sram_addr = *prop;
272
273	prop = of_get_property(np, "tx_sram_size", NULL);
274	if (prop)
275		pdata.tx_sram_size = *prop;
276
277	prop = of_get_property(np, "rx_sram_addr", NULL);
278	if (prop)
279		pdata.rx_sram_addr = *prop;
280
281	prop = of_get_property(np, "rx_sram_size", NULL);
282	if (prop)
283		pdata.rx_sram_size = *prop;
284
285	ph = of_get_property(np, "phy", NULL);
286	if (!ph)
287		return -ENODEV;
288
289	phy = of_find_node_by_phandle(*ph);
290	if (phy == NULL)
291		return -ENODEV;
292
293	prop = of_get_property(phy, "reg", NULL);
294	if (prop)
295		pdata.phy_addr = MV643XX_ETH_PHY_ADDR(*prop);
296
297	of_node_put(phy);
298
299	pdev = platform_device_alloc(MV643XX_ETH_NAME, id);
300	if (!pdev)
301		return -ENOMEM;
302
303	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
304	err = platform_device_add_resources(pdev, r, 1);
305	if (err)
306		goto error;
307
308	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
309	if (err)
310		goto error;
311
312	err = platform_device_add(pdev);
313	if (err)
314		goto error;
315
316	return 0;
317
318error:
319	platform_device_put(pdev);
320	return err;
321}
322
323/*
324 * Create mv64x60_i2c platform devices
325 */
326static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
327{
328	struct resource r[2];
329	struct platform_device *pdev;
330	struct mv64xxx_i2c_pdata pdata;
331	const unsigned int *prop;
332	int err;
333
334	memset(r, 0, sizeof(r));
335
336	err = of_address_to_resource(np, 0, &r[0]);
337	if (err)
338		return err;
339
340	of_irq_to_resource(np, 0, &r[1]);
341
342	memset(&pdata, 0, sizeof(pdata));
343
344	pdata.freq_m = 8;	/* default */
345	prop = of_get_property(np, "freq_m", NULL);
346	if (prop)
347		pdata.freq_m = *prop;
348
349	pdata.freq_n = 3;	/* default */
350	prop = of_get_property(np, "freq_n", NULL);
351	if (prop)
352		pdata.freq_n = *prop;
353
354	pdata.timeout = 1000;				/* default: 1 second */
355
356	pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id);
357	if (!pdev)
358		return -ENOMEM;
359
360	err = platform_device_add_resources(pdev, r, 2);
361	if (err)
362		goto error;
363
364	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
365	if (err)
366		goto error;
367
368	err = platform_device_add(pdev);
369	if (err)
370		goto error;
371
372	return 0;
373
374error:
375	platform_device_put(pdev);
376	return err;
377}
378
379/*
380 * Create mv64x60_wdt platform devices
381 */
382static int __init mv64x60_wdt_device_setup(struct device_node *np, int id)
383{
384	struct resource r;
385	struct platform_device *pdev;
386	struct mv64x60_wdt_pdata pdata;
387	const unsigned int *prop;
388	int err;
389
390	err = of_address_to_resource(np, 0, &r);
391	if (err)
392		return err;
393
394	memset(&pdata, 0, sizeof(pdata));
395
396	pdata.timeout = 10;			/* Default: 10 seconds */
397
398	np = of_get_parent(np);
399	if (!np)
400		return -ENODEV;
401
402	prop = of_get_property(np, "clock-frequency", NULL);
403	of_node_put(np);
404	if (!prop)
405		return -ENODEV;
406	pdata.bus_clk = *prop / 1000000; /* wdt driver wants freq in MHz */
407
408	pdev = platform_device_alloc(MV64x60_WDT_NAME, id);
409	if (!pdev)
410		return -ENOMEM;
411
412	err = platform_device_add_resources(pdev, &r, 1);
413	if (err)
414		goto error;
415
416	err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
417	if (err)
418		goto error;
419
420	err = platform_device_add(pdev);
421	if (err)
422		goto error;
423
424	return 0;
425
426error:
427	platform_device_put(pdev);
428	return err;
429}
430
431static int __init mv64x60_device_setup(void)
432{
433	struct device_node *np, *np2;
434	struct platform_device *pdev;
435	int id, id2;
436	int err;
437
438	id = 0;
439	for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
440		err = mv64x60_mpsc_device_setup(np, id++);
441		if (err)
442			printk(KERN_ERR "Failed to initialize MV64x60 "
443					"serial device %s: error %d.\n",
444					np->full_name, err);
445	}
446
447	id = 0;
448	id2 = 0;
449	for_each_compatible_node(np, NULL, "marvell,mv64360-eth-group") {
450		pdev = mv64x60_eth_register_shared_pdev(np, id++);
451		if (IS_ERR(pdev)) {
452			err = PTR_ERR(pdev);
453			printk(KERN_ERR "Failed to initialize MV64x60 "
454					"network block %s: error %d.\n",
455					np->full_name, err);
456			continue;
457		}
458		for_each_child_of_node(np, np2) {
459			if (!of_device_is_compatible(np2,
460					"marvell,mv64360-eth"))
461				continue;
462			err = mv64x60_eth_device_setup(np2, id2++, pdev);
463			if (err)
464				printk(KERN_ERR "Failed to initialize "
465						"MV64x60 network device %s: "
466						"error %d.\n",
467						np2->full_name, err);
468		}
469	}
470
471	id = 0;
472	for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") {
473		err = mv64x60_i2c_device_setup(np, id++);
474		if (err)
475			printk(KERN_ERR "Failed to initialize MV64x60 I2C "
476					"bus %s: error %d.\n",
477					np->full_name, err);
478	}
479
480	/* support up to one watchdog timer */
481	np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt");
482	if (np) {
483		if ((err = mv64x60_wdt_device_setup(np, id)))
484			printk(KERN_ERR "Failed to initialize MV64x60 "
485					"Watchdog %s: error %d.\n",
486					np->full_name, err);
487		of_node_put(np);
488	}
489
490	/* Now add every node that is on the device bus */
491	for_each_compatible_node(np, NULL, "marvell,mv64360")
492		of_platform_bus_probe(np, of_mv64x60_devices, NULL);
493
494	return 0;
495}
496arch_initcall(mv64x60_device_setup);
497
498static int __init mv64x60_add_mpsc_console(void)
499{
500	struct device_node *np = NULL;
501	const char *prop;
502
503	prop = of_get_property(of_chosen, "linux,stdout-path", NULL);
504	if (prop == NULL)
505		goto not_mpsc;
506
507	np = of_find_node_by_path(prop);
508	if (!np)
509		goto not_mpsc;
510
511	if (!of_device_is_compatible(np, "marvell,mv64360-mpsc"))
512		goto not_mpsc;
513
514	prop = of_get_property(np, "cell-index", NULL);
515	if (!prop)
516		goto not_mpsc;
517
518	add_preferred_console("ttyMM", *(int *)prop, NULL);
519
520not_mpsc:
521	return 0;
522}
523console_initcall(mv64x60_add_mpsc_console);