Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mv64x60_dev.c
Go to the documentation of this file.
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 
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];
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 
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 
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 
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);