Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/sysdev/mv64x60_dev.c
10818 views
1
/*
2
* Platform device setup for Marvell mv64360/mv64460 host bridges (Discovery)
3
*
4
* Author: Dale Farnsworth <[email protected]>
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
26
static struct of_device_id __initdata of_mv64x60_devices[] = {
27
{ .compatible = "marvell,mv64306-devctrl", },
28
{}
29
};
30
31
/*
32
* Create MPSC platform devices
33
*/
34
static 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
83
error:
84
platform_device_put(pdev);
85
return err;
86
}
87
88
89
static 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
205
error:
206
platform_device_put(pdev);
207
return err;
208
}
209
210
/*
211
* Create mv64x60_eth platform devices
212
*/
213
static 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
229
static 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
318
error:
319
platform_device_put(pdev);
320
return err;
321
}
322
323
/*
324
* Create mv64x60_i2c platform devices
325
*/
326
static 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
374
error:
375
platform_device_put(pdev);
376
return err;
377
}
378
379
/*
380
* Create mv64x60_wdt platform devices
381
*/
382
static 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
426
error:
427
platform_device_put(pdev);
428
return err;
429
}
430
431
static 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
}
496
arch_initcall(mv64x60_device_setup);
497
498
static 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
520
not_mpsc:
521
return 0;
522
}
523
console_initcall(mv64x60_add_mpsc_console);
524
525