diff options
author | Liu Gang <Gang.Liu@freescale.com> | 2011-11-12 07:02:29 -0500 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2011-11-24 03:01:34 -0500 |
commit | abc3aeae3aaa5c319d02f12649e17ea5929999aa (patch) | |
tree | 1eb64b3c01ce6ae488c9f5f0460b602d654b5a2a | |
parent | 6ec4bedbf153a8ef71aeba99a40efef556b57798 (diff) |
fsl-rio: Add two ports and rapidio message units support
Usually, freescale rapidio endpoint can support one or two 1x or 4X
LP-Serial link interfaces, and rapidio message transactions can be
implemented by two message units. This adds the support of two
rapidio ports and initializes message unit 0 and message unit 1. And
these ports and message units can work simultaneously.
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jin Qing <b24347@freescale.com>
Signed-off-by: Liu Gang <Gang.Liu@freescale.com>
Acked-by: Alexandre Bounine <alexandre.bounine@idt.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.c | 391 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_rio.h | 75 | ||||
-rw-r--r-- | arch/powerpc/sysdev/fsl_rmu.c | 502 |
3 files changed, 545 insertions, 423 deletions
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 9484484c82c3..a4c4f4a932d8 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #define RIO_PORT1_IECSR 0x10130 | 45 | #define RIO_PORT1_IECSR 0x10130 |
46 | #define RIO_PORT2_IECSR 0x101B0 | 46 | #define RIO_PORT2_IECSR 0x101B0 |
47 | 47 | ||
48 | #define RIO_ATMU_REGS_OFFSET 0x10c00 | ||
49 | #define RIO_GCCSR 0x13c | 48 | #define RIO_GCCSR 0x13c |
50 | #define RIO_ESCSR 0x158 | 49 | #define RIO_ESCSR 0x158 |
51 | #define ESCSR_CLEAR 0x07120204 | 50 | #define ESCSR_CLEAR 0x07120204 |
@@ -74,6 +73,11 @@ | |||
74 | : "b" (addr), "i" (-EFAULT), "0" (err)) | 73 | : "b" (addr), "i" (-EFAULT), "0" (err)) |
75 | 74 | ||
76 | void __iomem *rio_regs_win; | 75 | void __iomem *rio_regs_win; |
76 | void __iomem *rmu_regs_win; | ||
77 | resource_size_t rio_law_start; | ||
78 | |||
79 | struct fsl_rio_dbell *dbell; | ||
80 | struct fsl_rio_pw *pw; | ||
77 | 81 | ||
78 | #ifdef CONFIG_E500 | 82 | #ifdef CONFIG_E500 |
79 | int fsl_rio_mcheck_exception(struct pt_regs *regs) | 83 | int fsl_rio_mcheck_exception(struct pt_regs *regs) |
@@ -120,7 +124,7 @@ static int fsl_local_config_read(struct rio_mport *mport, | |||
120 | { | 124 | { |
121 | struct rio_priv *priv = mport->priv; | 125 | struct rio_priv *priv = mport->priv; |
122 | pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index, | 126 | pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index, |
123 | offset); | 127 | offset); |
124 | *data = in_be32(priv->regs_win + offset); | 128 | *data = in_be32(priv->regs_win + offset); |
125 | 129 | ||
126 | return 0; | 130 | return 0; |
@@ -173,7 +177,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid, | |||
173 | pr_debug | 177 | pr_debug |
174 | ("fsl_rio_config_read:" | 178 | ("fsl_rio_config_read:" |
175 | " index %d destid %d hopcount %d offset %8.8x len %d\n", | 179 | " index %d destid %d hopcount %d offset %8.8x len %d\n", |
176 | index, destid, hopcount, offset, len); | 180 | index, destid, hopcount, offset, len); |
177 | 181 | ||
178 | /* 16MB maintenance window possible */ | 182 | /* 16MB maintenance window possible */ |
179 | /* allow only aligned access to maintenance registers */ | 183 | /* allow only aligned access to maintenance registers */ |
@@ -230,8 +234,8 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, | |||
230 | u8 *data; | 234 | u8 *data; |
231 | pr_debug | 235 | pr_debug |
232 | ("fsl_rio_config_write:" | 236 | ("fsl_rio_config_write:" |
233 | "index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", | 237 | " index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", |
234 | index, destid, hopcount, offset, len, val); | 238 | index, destid, hopcount, offset, len, val); |
235 | 239 | ||
236 | /* 16MB maintenance windows possible */ | 240 | /* 16MB maintenance windows possible */ |
237 | /* allow only aligned access to maintenance registers */ | 241 | /* allow only aligned access to maintenance registers */ |
@@ -260,7 +264,7 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, | |||
260 | return 0; | 264 | return 0; |
261 | } | 265 | } |
262 | 266 | ||
263 | void fsl_rio_port_error_handler(struct rio_mport *port, int offset) | 267 | void fsl_rio_port_error_handler(int offset) |
264 | { | 268 | { |
265 | /*XXX: Error recovery is not implemented, we just clear errors */ | 269 | /*XXX: Error recovery is not implemented, we just clear errors */ |
266 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); | 270 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); |
@@ -331,16 +335,21 @@ int fsl_rio_setup(struct platform_device *dev) | |||
331 | struct rio_mport *port; | 335 | struct rio_mport *port; |
332 | struct rio_priv *priv; | 336 | struct rio_priv *priv; |
333 | int rc = 0; | 337 | int rc = 0; |
334 | const u32 *dt_range, *cell; | 338 | const u32 *dt_range, *cell, *port_index; |
335 | struct resource regs; | 339 | u32 active_ports = 0; |
340 | struct resource regs, rmu_regs; | ||
341 | struct device_node *np, *rmu_node; | ||
336 | int rlen; | 342 | int rlen; |
337 | u32 ccsr; | 343 | u32 ccsr; |
338 | u64 law_start, law_size; | 344 | u64 range_start, range_size; |
339 | int paw, aw, sw; | 345 | int paw, aw, sw; |
346 | u32 i; | ||
347 | static int tmp; | ||
348 | struct device_node *rmu_np[MAX_MSG_UNIT_NUM] = {NULL}; | ||
340 | 349 | ||
341 | if (!dev->dev.of_node) { | 350 | if (!dev->dev.of_node) { |
342 | dev_err(&dev->dev, "Device OF-Node is NULL"); | 351 | dev_err(&dev->dev, "Device OF-Node is NULL"); |
343 | return -EFAULT; | 352 | return -ENODEV; |
344 | } | 353 | } |
345 | 354 | ||
346 | rc = of_address_to_resource(dev->dev.of_node, 0, ®s); | 355 | rc = of_address_to_resource(dev->dev.of_node, 0, ®s); |
@@ -353,34 +362,13 @@ int fsl_rio_setup(struct platform_device *dev) | |||
353 | dev->dev.of_node->full_name); | 362 | dev->dev.of_node->full_name); |
354 | dev_info(&dev->dev, "Regs: %pR\n", ®s); | 363 | dev_info(&dev->dev, "Regs: %pR\n", ®s); |
355 | 364 | ||
356 | dt_range = of_get_property(dev->dev.of_node, "ranges", &rlen); | 365 | rio_regs_win = ioremap(regs.start, resource_size(®s)); |
357 | if (!dt_range) { | 366 | if (!rio_regs_win) { |
358 | dev_err(&dev->dev, "Can't get %s property 'ranges'\n", | 367 | dev_err(&dev->dev, "Unable to map rio register window\n"); |
359 | dev->dev.of_node->full_name); | 368 | rc = -ENOMEM; |
360 | return -EFAULT; | 369 | goto err_rio_regs; |
361 | } | 370 | } |
362 | 371 | ||
363 | /* Get node address wide */ | ||
364 | cell = of_get_property(dev->dev.of_node, "#address-cells", NULL); | ||
365 | if (cell) | ||
366 | aw = *cell; | ||
367 | else | ||
368 | aw = of_n_addr_cells(dev->dev.of_node); | ||
369 | /* Get node size wide */ | ||
370 | cell = of_get_property(dev->dev.of_node, "#size-cells", NULL); | ||
371 | if (cell) | ||
372 | sw = *cell; | ||
373 | else | ||
374 | sw = of_n_size_cells(dev->dev.of_node); | ||
375 | /* Get parent address wide wide */ | ||
376 | paw = of_n_addr_cells(dev->dev.of_node); | ||
377 | |||
378 | law_start = of_read_number(dt_range + aw, paw); | ||
379 | law_size = of_read_number(dt_range + aw + paw, sw); | ||
380 | |||
381 | dev_info(&dev->dev, "LAW start 0x%016llx, size 0x%016llx.\n", | ||
382 | law_start, law_size); | ||
383 | |||
384 | ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL); | 372 | ops = kzalloc(sizeof(struct rio_ops), GFP_KERNEL); |
385 | if (!ops) { | 373 | if (!ops) { |
386 | rc = -ENOMEM; | 374 | rc = -ENOMEM; |
@@ -390,130 +378,267 @@ int fsl_rio_setup(struct platform_device *dev) | |||
390 | ops->lcwrite = fsl_local_config_write; | 378 | ops->lcwrite = fsl_local_config_write; |
391 | ops->cread = fsl_rio_config_read; | 379 | ops->cread = fsl_rio_config_read; |
392 | ops->cwrite = fsl_rio_config_write; | 380 | ops->cwrite = fsl_rio_config_write; |
381 | ops->dsend = fsl_rio_doorbell_send; | ||
393 | ops->pwenable = fsl_rio_pw_enable; | 382 | ops->pwenable = fsl_rio_pw_enable; |
394 | 383 | ops->open_outb_mbox = fsl_open_outb_mbox; | |
395 | port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); | 384 | ops->open_inb_mbox = fsl_open_inb_mbox; |
396 | if (!port) { | 385 | ops->close_outb_mbox = fsl_close_outb_mbox; |
386 | ops->close_inb_mbox = fsl_close_inb_mbox; | ||
387 | ops->add_outb_message = fsl_add_outb_message; | ||
388 | ops->add_inb_buffer = fsl_add_inb_buffer; | ||
389 | ops->get_inb_message = fsl_get_inb_message; | ||
390 | |||
391 | rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0); | ||
392 | if (!rmu_node) | ||
393 | goto err_rmu; | ||
394 | rc = of_address_to_resource(rmu_node, 0, &rmu_regs); | ||
395 | if (rc) { | ||
396 | dev_err(&dev->dev, "Can't get %s property 'reg'\n", | ||
397 | rmu_node->full_name); | ||
398 | goto err_rmu; | ||
399 | } | ||
400 | rmu_regs_win = ioremap(rmu_regs.start, resource_size(&rmu_regs)); | ||
401 | if (!rmu_regs_win) { | ||
402 | dev_err(&dev->dev, "Unable to map rmu register window\n"); | ||
397 | rc = -ENOMEM; | 403 | rc = -ENOMEM; |
398 | goto err_port; | 404 | goto err_rmu; |
405 | } | ||
406 | for_each_compatible_node(np, NULL, "fsl,srio-msg-unit") { | ||
407 | rmu_np[tmp] = np; | ||
408 | tmp++; | ||
399 | } | 409 | } |
400 | port->index = 0; | ||
401 | 410 | ||
402 | priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); | 411 | /*set up doobell node*/ |
403 | if (!priv) { | 412 | np = of_find_compatible_node(NULL, NULL, "fsl,srio-dbell-unit"); |
404 | printk(KERN_ERR "Can't alloc memory for 'priv'\n"); | 413 | if (!np) { |
414 | rc = -ENODEV; | ||
415 | goto err_dbell; | ||
416 | } | ||
417 | dbell = kzalloc(sizeof(struct fsl_rio_dbell), GFP_KERNEL); | ||
418 | if (!(dbell)) { | ||
419 | dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_dbell'\n"); | ||
405 | rc = -ENOMEM; | 420 | rc = -ENOMEM; |
406 | goto err_priv; | 421 | goto err_dbell; |
407 | } | 422 | } |
423 | dbell->dev = &dev->dev; | ||
424 | dbell->bellirq = irq_of_parse_and_map(np, 1); | ||
425 | dev_info(&dev->dev, "bellirq: %d\n", dbell->bellirq); | ||
408 | 426 | ||
409 | INIT_LIST_HEAD(&port->dbells); | 427 | aw = of_n_addr_cells(np); |
410 | port->iores.start = law_start; | 428 | dt_range = of_get_property(np, "reg", &rlen); |
411 | port->iores.end = law_start + law_size - 1; | 429 | if (!dt_range) { |
412 | port->iores.flags = IORESOURCE_MEM; | 430 | pr_err("%s: unable to find 'reg' property\n", |
413 | port->iores.name = "rio_io_win"; | 431 | np->full_name); |
414 | 432 | rc = -ENOMEM; | |
415 | if (request_resource(&iomem_resource, &port->iores) < 0) { | 433 | goto err_pw; |
416 | dev_err(&dev->dev, "RIO: Error requesting master port region" | 434 | } |
417 | " 0x%016llx-0x%016llx\n", | 435 | range_start = of_read_number(dt_range, aw); |
418 | (u64)port->iores.start, (u64)port->iores.end); | 436 | dbell->dbell_regs = (struct rio_dbell_regs *)(rmu_regs_win + |
419 | rc = -ENOMEM; | 437 | (u32)range_start); |
420 | goto err_res; | 438 | |
439 | /*set up port write node*/ | ||
440 | np = of_find_compatible_node(NULL, NULL, "fsl,srio-port-write-unit"); | ||
441 | if (!np) { | ||
442 | rc = -ENODEV; | ||
443 | goto err_pw; | ||
444 | } | ||
445 | pw = kzalloc(sizeof(struct fsl_rio_pw), GFP_KERNEL); | ||
446 | if (!(pw)) { | ||
447 | dev_err(&dev->dev, "Can't alloc memory for 'fsl_rio_pw'\n"); | ||
448 | rc = -ENOMEM; | ||
449 | goto err_pw; | ||
450 | } | ||
451 | pw->dev = &dev->dev; | ||
452 | pw->pwirq = irq_of_parse_and_map(np, 0); | ||
453 | dev_info(&dev->dev, "pwirq: %d\n", pw->pwirq); | ||
454 | aw = of_n_addr_cells(np); | ||
455 | dt_range = of_get_property(np, "reg", &rlen); | ||
456 | if (!dt_range) { | ||
457 | pr_err("%s: unable to find 'reg' property\n", | ||
458 | np->full_name); | ||
459 | rc = -ENOMEM; | ||
460 | goto err; | ||
421 | } | 461 | } |
462 | range_start = of_read_number(dt_range, aw); | ||
463 | pw->pw_regs = (struct rio_pw_regs *)(rmu_regs_win + (u32)range_start); | ||
464 | |||
465 | /*set up ports node*/ | ||
466 | for_each_child_of_node(dev->dev.of_node, np) { | ||
467 | port_index = of_get_property(np, "cell-index", NULL); | ||
468 | if (!port_index) { | ||
469 | dev_err(&dev->dev, "Can't get %s property 'cell-index'\n", | ||
470 | np->full_name); | ||
471 | continue; | ||
472 | } | ||
473 | |||
474 | dt_range = of_get_property(np, "ranges", &rlen); | ||
475 | if (!dt_range) { | ||
476 | dev_err(&dev->dev, "Can't get %s property 'ranges'\n", | ||
477 | np->full_name); | ||
478 | continue; | ||
479 | } | ||
422 | 480 | ||
423 | priv->pwirq = irq_of_parse_and_map(dev->dev.of_node, 0); | 481 | /* Get node address wide */ |
424 | dev_info(&dev->dev, "pwirq: %d\n", priv->pwirq); | 482 | cell = of_get_property(np, "#address-cells", NULL); |
425 | strcpy(port->name, "RIO0 mport"); | 483 | if (cell) |
426 | 484 | aw = *cell; | |
427 | priv->dev = &dev->dev; | 485 | else |
428 | 486 | aw = of_n_addr_cells(np); | |
429 | port->ops = ops; | 487 | /* Get node size wide */ |
430 | port->priv = priv; | 488 | cell = of_get_property(np, "#size-cells", NULL); |
431 | port->phys_efptr = 0x100; | 489 | if (cell) |
432 | 490 | sw = *cell; | |
433 | priv->regs_win = ioremap(regs.start, resource_size(®s)); | 491 | else |
434 | rio_regs_win = priv->regs_win; | 492 | sw = of_n_size_cells(np); |
435 | 493 | /* Get parent address wide wide */ | |
436 | /* Probe the master port phy type */ | 494 | paw = of_n_addr_cells(np); |
437 | ccsr = in_be32(priv->regs_win + RIO_CCSR); | 495 | range_start = of_read_number(dt_range + aw, paw); |
438 | port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL; | 496 | range_size = of_read_number(dt_range + aw + paw, sw); |
439 | dev_info(&dev->dev, "RapidIO PHY type: %s\n", | 497 | |
440 | (port->phy_type == RIO_PHY_PARALLEL) ? "parallel" : | 498 | dev_info(&dev->dev, "%s: LAW start 0x%016llx, size 0x%016llx.\n", |
441 | ((port->phy_type == RIO_PHY_SERIAL) ? "serial" : | 499 | np->full_name, range_start, range_size); |
442 | "unknown")); | 500 | |
443 | /* Checking the port training status */ | 501 | port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); |
444 | if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) { | 502 | if (!port) |
445 | dev_err(&dev->dev, "Port is not ready. " | 503 | continue; |
446 | "Try to restart connection...\n"); | 504 | |
447 | switch (port->phy_type) { | 505 | i = *port_index - 1; |
448 | case RIO_PHY_SERIAL: | 506 | port->index = (unsigned char)i; |
507 | |||
508 | priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); | ||
509 | if (!priv) { | ||
510 | dev_err(&dev->dev, "Can't alloc memory for 'priv'\n"); | ||
511 | kfree(port); | ||
512 | continue; | ||
513 | } | ||
514 | |||
515 | INIT_LIST_HEAD(&port->dbells); | ||
516 | port->iores.start = range_start; | ||
517 | port->iores.end = port->iores.start + range_size - 1; | ||
518 | port->iores.flags = IORESOURCE_MEM; | ||
519 | port->iores.name = "rio_io_win"; | ||
520 | |||
521 | if (request_resource(&iomem_resource, &port->iores) < 0) { | ||
522 | dev_err(&dev->dev, "RIO: Error requesting master port region" | ||
523 | " 0x%016llx-0x%016llx\n", | ||
524 | (u64)port->iores.start, (u64)port->iores.end); | ||
525 | kfree(priv); | ||
526 | kfree(port); | ||
527 | continue; | ||
528 | } | ||
529 | sprintf(port->name, "RIO mport %d", i); | ||
530 | |||
531 | priv->dev = &dev->dev; | ||
532 | port->ops = ops; | ||
533 | port->priv = priv; | ||
534 | port->phys_efptr = 0x100; | ||
535 | priv->regs_win = rio_regs_win; | ||
536 | |||
537 | /* Probe the master port phy type */ | ||
538 | ccsr = in_be32(priv->regs_win + RIO_CCSR + i*0x20); | ||
539 | port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL; | ||
540 | if (port->phy_type == RIO_PHY_PARALLEL) { | ||
541 | dev_err(&dev->dev, "RIO: Parallel PHY type, unsupported port type!\n"); | ||
542 | release_resource(&port->iores); | ||
543 | kfree(priv); | ||
544 | kfree(port); | ||
545 | continue; | ||
546 | } | ||
547 | dev_info(&dev->dev, "RapidIO PHY type: Serial\n"); | ||
548 | /* Checking the port training status */ | ||
549 | if (in_be32((priv->regs_win + RIO_ESCSR + i*0x20)) & 1) { | ||
550 | dev_err(&dev->dev, "Port %d is not ready. " | ||
551 | "Try to restart connection...\n", i); | ||
449 | /* Disable ports */ | 552 | /* Disable ports */ |
450 | out_be32(priv->regs_win + RIO_CCSR, 0); | 553 | out_be32(priv->regs_win |
554 | + RIO_CCSR + i*0x20, 0); | ||
451 | /* Set 1x lane */ | 555 | /* Set 1x lane */ |
452 | setbits32(priv->regs_win + RIO_CCSR, 0x02000000); | 556 | setbits32(priv->regs_win |
557 | + RIO_CCSR + i*0x20, 0x02000000); | ||
453 | /* Enable ports */ | 558 | /* Enable ports */ |
454 | setbits32(priv->regs_win + RIO_CCSR, 0x00600000); | 559 | setbits32(priv->regs_win |
455 | break; | 560 | + RIO_CCSR + i*0x20, 0x00600000); |
456 | case RIO_PHY_PARALLEL: | 561 | msleep(100); |
457 | /* Disable ports */ | 562 | if (in_be32((priv->regs_win |
458 | out_be32(priv->regs_win + RIO_CCSR, 0x22000000); | 563 | + RIO_ESCSR + i*0x20)) & 1) { |
459 | /* Enable ports */ | 564 | dev_err(&dev->dev, |
460 | out_be32(priv->regs_win + RIO_CCSR, 0x44000000); | 565 | "Port %d restart failed.\n", i); |
461 | break; | 566 | release_resource(&port->iores); |
567 | kfree(priv); | ||
568 | kfree(port); | ||
569 | continue; | ||
570 | } | ||
571 | dev_info(&dev->dev, "Port %d restart success!\n", i); | ||
462 | } | 572 | } |
463 | msleep(100); | 573 | fsl_rio_info(&dev->dev, ccsr); |
464 | if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) { | ||
465 | dev_err(&dev->dev, "Port restart failed.\n"); | ||
466 | rc = -ENOLINK; | ||
467 | goto err; | ||
468 | } | ||
469 | dev_info(&dev->dev, "Port restart success!\n"); | ||
470 | } | ||
471 | fsl_rio_info(&dev->dev, ccsr); | ||
472 | 574 | ||
473 | port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR)) | 575 | port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR)) |
474 | & RIO_PEF_CTLS) >> 4; | 576 | & RIO_PEF_CTLS) >> 4; |
475 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", | 577 | dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", |
476 | port->sys_size ? 65536 : 256); | 578 | port->sys_size ? 65536 : 256); |
579 | |||
580 | if (rio_register_mport(port)) { | ||
581 | release_resource(&port->iores); | ||
582 | kfree(priv); | ||
583 | kfree(port); | ||
584 | continue; | ||
585 | } | ||
586 | if (port->host_deviceid >= 0) | ||
587 | out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | | ||
588 | RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); | ||
589 | else | ||
590 | out_be32(priv->regs_win + RIO_GCCSR, | ||
591 | RIO_PORT_GEN_MASTER); | ||
477 | 592 | ||
478 | if (rio_register_mport(port)) | 593 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win |
479 | goto err; | 594 | + ((i == 0) ? RIO_ATMU_REGS_PORT1_OFFSET : |
595 | RIO_ATMU_REGS_PORT2_OFFSET)); | ||
596 | |||
597 | priv->maint_atmu_regs = priv->atmu_regs + 1; | ||
480 | 598 | ||
481 | if (port->host_deviceid >= 0) | 599 | /* Set to receive any dist ID for serial RapidIO controller. */ |
482 | out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST | | 600 | if (port->phy_type == RIO_PHY_SERIAL) |
483 | RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED); | 601 | out_be32((priv->regs_win |
484 | else | 602 | + RIO_ISR_AACR + i*0x80), RIO_ISR_AACR_AA); |
485 | out_be32(priv->regs_win + RIO_GCCSR, 0x00000000); | ||
486 | 603 | ||
487 | priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win | 604 | /* Configure maintenance transaction window */ |
488 | + RIO_ATMU_REGS_OFFSET); | 605 | out_be32(&priv->maint_atmu_regs->rowbar, |
489 | priv->maint_atmu_regs = priv->atmu_regs + 1; | 606 | port->iores.start >> 12); |
607 | out_be32(&priv->maint_atmu_regs->rowar, | ||
608 | 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1)); | ||
490 | 609 | ||
491 | /* Set to receive any dist ID for serial RapidIO controller. */ | 610 | priv->maint_win = ioremap(port->iores.start, |
492 | if (port->phy_type == RIO_PHY_SERIAL) | 611 | RIO_MAINT_WIN_SIZE); |
493 | out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA); | ||
494 | 612 | ||
495 | /* Configure maintenance transaction window */ | 613 | rio_law_start = range_start; |
496 | out_be32(&priv->maint_atmu_regs->rowbar, law_start >> 12); | ||
497 | out_be32(&priv->maint_atmu_regs->rowar, | ||
498 | 0x80077000 | (ilog2(RIO_MAINT_WIN_SIZE) - 1)); | ||
499 | 614 | ||
500 | priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE); | 615 | fsl_rio_setup_rmu(port, rmu_np[i]); |
501 | 616 | ||
502 | fsl_rio_setup_rmu(port, dev->dev.of_node); | 617 | dbell->mport[i] = port; |
618 | |||
619 | active_ports++; | ||
620 | } | ||
621 | |||
622 | if (!active_ports) { | ||
623 | rc = -ENOLINK; | ||
624 | goto err; | ||
625 | } | ||
503 | 626 | ||
504 | fsl_rio_port_write_init(port); | 627 | fsl_rio_doorbell_init(dbell); |
628 | fsl_rio_port_write_init(pw); | ||
505 | 629 | ||
506 | return 0; | 630 | return 0; |
507 | err: | 631 | err: |
508 | iounmap(priv->regs_win); | 632 | kfree(pw); |
509 | release_resource(&port->iores); | 633 | err_pw: |
510 | err_res: | 634 | kfree(dbell); |
511 | kfree(priv); | 635 | err_dbell: |
512 | err_priv: | 636 | iounmap(rmu_regs_win); |
513 | kfree(port); | 637 | err_rmu: |
514 | err_port: | ||
515 | kfree(ops); | 638 | kfree(ops); |
516 | err_ops: | 639 | err_ops: |
640 | iounmap(rio_regs_win); | ||
641 | err_rio_regs: | ||
517 | return rc; | 642 | return rc; |
518 | } | 643 | } |
519 | 644 | ||
@@ -529,7 +654,7 @@ static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev) | |||
529 | 654 | ||
530 | static const struct of_device_id fsl_of_rio_rpn_ids[] = { | 655 | static const struct of_device_id fsl_of_rio_rpn_ids[] = { |
531 | { | 656 | { |
532 | .compatible = "fsl,rapidio-delta", | 657 | .compatible = "fsl,srio", |
533 | }, | 658 | }, |
534 | {}, | 659 | {}, |
535 | }; | 660 | }; |
diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h index f888a1effd43..ae8e27405a0d 100644 --- a/arch/powerpc/sysdev/fsl_rio.h +++ b/arch/powerpc/sysdev/fsl_rio.h | |||
@@ -36,13 +36,36 @@ | |||
36 | #define RIO_MAINT_WIN_SIZE 0x400000 | 36 | #define RIO_MAINT_WIN_SIZE 0x400000 |
37 | #define RIO_LTLEDCSR 0x0608 | 37 | #define RIO_LTLEDCSR 0x0608 |
38 | 38 | ||
39 | #define DOORBELL_ROWAR_EN 0x80000000 | ||
40 | #define DOORBELL_ROWAR_TFLOWLV 0x08000000 /* highest priority level */ | ||
41 | #define DOORBELL_ROWAR_PCI 0x02000000 /* PCI window */ | ||
42 | #define DOORBELL_ROWAR_NREAD 0x00040000 /* NREAD */ | ||
43 | #define DOORBELL_ROWAR_MAINTRD 0x00070000 /* maintenance read */ | ||
44 | #define DOORBELL_ROWAR_RES 0x00002000 /* wrtpy: reserverd */ | ||
45 | #define DOORBELL_ROWAR_MAINTWD 0x00007000 | ||
46 | #define DOORBELL_ROWAR_SIZE 0x0000000b /* window size is 4k */ | ||
47 | |||
48 | #define RIO_ATMU_REGS_PORT1_OFFSET 0x10c00 | ||
49 | #define RIO_ATMU_REGS_PORT2_OFFSET 0x10e00 | ||
50 | #define RIO_S_DBELL_REGS_OFFSET 0x13400 | ||
51 | #define RIO_S_PW_REGS_OFFSET 0x134e0 | ||
52 | #define RIO_ATMU_REGS_DBELL_OFFSET 0x10C40 | ||
53 | |||
54 | #define MAX_MSG_UNIT_NUM 2 | ||
55 | #define MAX_PORT_NUM 4 | ||
56 | |||
39 | struct rio_atmu_regs { | 57 | struct rio_atmu_regs { |
40 | u32 rowtar; | 58 | u32 rowtar; |
41 | u32 rowtear; | 59 | u32 rowtear; |
42 | u32 rowbar; | 60 | u32 rowbar; |
43 | u32 pad2; | 61 | u32 pad1; |
44 | u32 rowar; | 62 | u32 rowar; |
45 | u32 pad3[3]; | 63 | u32 pad2[3]; |
64 | }; | ||
65 | |||
66 | struct rio_dbell_ring { | ||
67 | void *virt; | ||
68 | dma_addr_t phys; | ||
46 | }; | 69 | }; |
47 | 70 | ||
48 | struct rio_port_write_msg { | 71 | struct rio_port_write_msg { |
@@ -53,26 +76,60 @@ struct rio_port_write_msg { | |||
53 | u32 discard_count; | 76 | u32 discard_count; |
54 | }; | 77 | }; |
55 | 78 | ||
56 | struct rio_priv { | 79 | struct fsl_rio_dbell { |
80 | struct rio_mport *mport[MAX_PORT_NUM]; | ||
57 | struct device *dev; | 81 | struct device *dev; |
58 | void __iomem *regs_win; | 82 | struct rio_dbell_regs __iomem *dbell_regs; |
59 | struct rio_atmu_regs __iomem *atmu_regs; | 83 | struct rio_dbell_ring dbell_ring; |
60 | struct rio_atmu_regs __iomem *maint_atmu_regs; | 84 | int bellirq; |
61 | void __iomem *maint_win; | 85 | }; |
86 | |||
87 | struct fsl_rio_pw { | ||
88 | struct device *dev; | ||
89 | struct rio_pw_regs __iomem *pw_regs; | ||
62 | struct rio_port_write_msg port_write_msg; | 90 | struct rio_port_write_msg port_write_msg; |
63 | int pwirq; | 91 | int pwirq; |
64 | struct work_struct pw_work; | 92 | struct work_struct pw_work; |
65 | struct kfifo pw_fifo; | 93 | struct kfifo pw_fifo; |
66 | spinlock_t pw_fifo_lock; | 94 | spinlock_t pw_fifo_lock; |
95 | }; | ||
96 | |||
97 | struct rio_priv { | ||
98 | struct device *dev; | ||
99 | void __iomem *regs_win; | ||
100 | struct rio_atmu_regs __iomem *atmu_regs; | ||
101 | struct rio_atmu_regs __iomem *maint_atmu_regs; | ||
102 | void __iomem *maint_win; | ||
67 | void *rmm_handle; /* RapidIO message manager(unit) Handle */ | 103 | void *rmm_handle; /* RapidIO message manager(unit) Handle */ |
68 | }; | 104 | }; |
69 | 105 | ||
70 | extern void __iomem *rio_regs_win; | 106 | extern void __iomem *rio_regs_win; |
107 | extern void __iomem *rmu_regs_win; | ||
108 | |||
109 | extern resource_size_t rio_law_start; | ||
110 | |||
111 | extern struct fsl_rio_dbell *dbell; | ||
112 | extern struct fsl_rio_pw *pw; | ||
71 | 113 | ||
72 | extern int fsl_rio_setup_rmu(struct rio_mport *mport, | 114 | extern int fsl_rio_setup_rmu(struct rio_mport *mport, |
73 | struct device_node *node); | 115 | struct device_node *node); |
74 | extern int fsl_rio_port_write_init(struct rio_mport *mport); | 116 | extern int fsl_rio_port_write_init(struct fsl_rio_pw *pw); |
75 | extern int fsl_rio_pw_enable(struct rio_mport *mport, int enable); | 117 | extern int fsl_rio_pw_enable(struct rio_mport *mport, int enable); |
76 | extern void fsl_rio_port_error_handler(struct rio_mport *port, int offset); | 118 | extern void fsl_rio_port_error_handler(int offset); |
119 | extern int fsl_rio_doorbell_init(struct fsl_rio_dbell *dbell); | ||
120 | |||
121 | extern int fsl_rio_doorbell_send(struct rio_mport *mport, | ||
122 | int index, u16 destid, u16 data); | ||
123 | extern int fsl_add_outb_message(struct rio_mport *mport, | ||
124 | struct rio_dev *rdev, | ||
125 | int mbox, void *buffer, size_t len); | ||
126 | extern int fsl_open_outb_mbox(struct rio_mport *mport, | ||
127 | void *dev_id, int mbox, int entries); | ||
128 | extern void fsl_close_outb_mbox(struct rio_mport *mport, int mbox); | ||
129 | extern int fsl_open_inb_mbox(struct rio_mport *mport, | ||
130 | void *dev_id, int mbox, int entries); | ||
131 | extern void fsl_close_inb_mbox(struct rio_mport *mport, int mbox); | ||
132 | extern int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf); | ||
133 | extern void *fsl_get_inb_message(struct rio_mport *mport, int mbox); | ||
77 | 134 | ||
78 | #endif | 135 | #endif |
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c index 0a3e6cff1837..02445a51949d 100644 --- a/arch/powerpc/sysdev/fsl_rmu.c +++ b/arch/powerpc/sysdev/fsl_rmu.c | |||
@@ -36,8 +36,8 @@ | |||
36 | (((struct rio_priv *)(mport->priv))->rmm_handle) | 36 | (((struct rio_priv *)(mport->priv))->rmm_handle) |
37 | 37 | ||
38 | /* RapidIO definition irq, which read from OF-tree */ | 38 | /* RapidIO definition irq, which read from OF-tree */ |
39 | #define IRQ_RIO_PW(m) (((struct rio_priv *)(m->priv))->pwirq) | 39 | #define IRQ_RIO_PW(m) (((struct fsl_rio_pw *)(m))->pwirq) |
40 | #define IRQ_RIO_BELL(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->bellirq) | 40 | #define IRQ_RIO_BELL(m) (((struct fsl_rio_dbell *)(m))->bellirq) |
41 | #define IRQ_RIO_TX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->txirq) | 41 | #define IRQ_RIO_TX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->txirq) |
42 | #define IRQ_RIO_RX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->rxirq) | 42 | #define IRQ_RIO_RX(m) (((struct fsl_rmu *)(GET_RMM_HANDLE(m)))->rxirq) |
43 | 43 | ||
@@ -73,13 +73,10 @@ | |||
73 | #define LTLEECSR_ENABLE_ALL 0xFFC000FC | 73 | #define LTLEECSR_ENABLE_ALL 0xFFC000FC |
74 | #define RIO_LTLEECSR 0x060c | 74 | #define RIO_LTLEECSR 0x060c |
75 | 75 | ||
76 | #define RIO_IM0SR 0x13064 | 76 | #define RIO_IM0SR 0x64 |
77 | #define RIO_IM1SR 0x13164 | 77 | #define RIO_IM1SR 0x164 |
78 | #define RIO_OM0SR 0x13004 | 78 | #define RIO_OM0SR 0x4 |
79 | #define RIO_OM1SR 0x13104 | 79 | #define RIO_OM1SR 0x104 |
80 | |||
81 | #define RIO_P_MSG_REGS_OFFSET 0x11000 | ||
82 | #define RIO_S_MSG_REGS_OFFSET 0x13000 | ||
83 | 80 | ||
84 | #define RIO_DBELL_WIN_SIZE 0x1000 | 81 | #define RIO_DBELL_WIN_SIZE 0x1000 |
85 | 82 | ||
@@ -113,75 +110,60 @@ | |||
113 | #define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET)) | 110 | #define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET)) |
114 | 111 | ||
115 | struct rio_msg_regs { | 112 | struct rio_msg_regs { |
116 | u32 omr; /* 0xD_3000 - Outbound message 0 mode register */ | 113 | u32 omr; |
117 | u32 osr; /* 0xD_3004 - Outbound message 0 status register */ | 114 | u32 osr; |
118 | u32 pad1; | 115 | u32 pad1; |
119 | u32 odqdpar; /* 0xD_300C - Outbound message 0 descriptor queue | 116 | u32 odqdpar; |
120 | dequeue pointer address register */ | ||
121 | u32 pad2; | 117 | u32 pad2; |
122 | u32 osar; /* 0xD_3014 - Outbound message 0 source address | 118 | u32 osar; |
123 | register */ | 119 | u32 odpr; |
124 | u32 odpr; /* 0xD_3018 - Outbound message 0 destination port | 120 | u32 odatr; |
125 | register */ | 121 | u32 odcr; |
126 | u32 odatr; /* 0xD_301C - Outbound message 0 destination attributes | ||
127 | Register*/ | ||
128 | u32 odcr; /* 0xD_3020 - Outbound message 0 double-word count | ||
129 | register */ | ||
130 | u32 pad3; | 122 | u32 pad3; |
131 | u32 odqepar; /* 0xD_3028 - Outbound message 0 descriptor queue | 123 | u32 odqepar; |
132 | enqueue pointer address register */ | ||
133 | u32 pad4[13]; | 124 | u32 pad4[13]; |
134 | u32 imr; /* 0xD_3060 - Inbound message 0 mode register */ | 125 | u32 imr; |
135 | u32 isr; /* 0xD_3064 - Inbound message 0 status register */ | 126 | u32 isr; |
136 | u32 pad5; | 127 | u32 pad5; |
137 | u32 ifqdpar; /* 0xD_306C - Inbound message 0 frame queue dequeue | 128 | u32 ifqdpar; |
138 | pointer address register*/ | ||
139 | u32 pad6; | 129 | u32 pad6; |
140 | u32 ifqepar; /* 0xD_3074 - Inbound message 0 frame queue enqueue | 130 | u32 ifqepar; |
141 | pointer address register */ | 131 | }; |
142 | u32 pad7[226]; | 132 | |
143 | u32 odmr; /* 0xD_3400 - Outbound doorbell mode register */ | 133 | struct rio_dbell_regs { |
144 | u32 odsr; /* 0xD_3404 - Outbound doorbell status register */ | 134 | u32 odmr; |
145 | u32 res0[4]; | 135 | u32 odsr; |
146 | u32 oddpr; /* 0xD_3418 - Outbound doorbell destination port | 136 | u32 pad1[4]; |
147 | register */ | 137 | u32 oddpr; |
148 | u32 oddatr; /* 0xD_341c - Outbound doorbell destination attributes | 138 | u32 oddatr; |
149 | register */ | 139 | u32 pad2[3]; |
150 | u32 res1[3]; | 140 | u32 odretcr; |
151 | u32 odretcr; /* 0xD_342C - Outbound doorbell retry error threshold | 141 | u32 pad3[12]; |
152 | configuration register */ | 142 | u32 dmr; |
153 | u32 res2[12]; | 143 | u32 dsr; |
154 | u32 dmr; /* 0xD_3460 - Inbound doorbell mode register */ | 144 | u32 pad4; |
155 | u32 dsr; /* 0xD_3464 - Inbound doorbell status register */ | 145 | u32 dqdpar; |
156 | u32 pad8; | 146 | u32 pad5; |
157 | u32 dqdpar; /* 0xD_346C - Inbound doorbell queue dequeue Pointer | 147 | u32 dqepar; |
158 | address register */ | 148 | }; |
159 | u32 pad9; | 149 | |
160 | u32 dqepar; /* 0xD_3474 - Inbound doorbell Queue enqueue pointer | 150 | struct rio_pw_regs { |
161 | address register */ | 151 | u32 pwmr; |
162 | u32 pad10[26]; | 152 | u32 pwsr; |
163 | u32 pwmr; /* 0xD_34E0 - Inbound port-write mode register */ | 153 | u32 epwqbar; |
164 | u32 pwsr; /* 0xD_34E4 - Inbound port-write status register */ | 154 | u32 pwqbar; |
165 | u32 epwqbar; /* 0xD_34E8 - Extended Port-Write Queue Base Address | ||
166 | register */ | ||
167 | u32 pwqbar; /* 0xD_34EC - Inbound port-write queue base address | ||
168 | register */ | ||
169 | }; | 155 | }; |
170 | 156 | ||
157 | |||
171 | struct rio_tx_desc { | 158 | struct rio_tx_desc { |
172 | u32 res1; | 159 | u32 pad1; |
173 | u32 saddr; | 160 | u32 saddr; |
174 | u32 dport; | 161 | u32 dport; |
175 | u32 dattr; | 162 | u32 dattr; |
176 | u32 res2; | 163 | u32 pad2; |
177 | u32 res3; | 164 | u32 pad3; |
178 | u32 dwcnt; | 165 | u32 dwcnt; |
179 | u32 res4; | 166 | u32 pad4; |
180 | }; | ||
181 | |||
182 | struct rio_dbell_ring { | ||
183 | void *virt; | ||
184 | dma_addr_t phys; | ||
185 | }; | 167 | }; |
186 | 168 | ||
187 | struct rio_msg_tx_ring { | 169 | struct rio_msg_tx_ring { |
@@ -204,13 +186,9 @@ struct rio_msg_rx_ring { | |||
204 | }; | 186 | }; |
205 | 187 | ||
206 | struct fsl_rmu { | 188 | struct fsl_rmu { |
207 | struct rio_atmu_regs __iomem *dbell_atmu_regs; | ||
208 | void __iomem *dbell_win; | ||
209 | struct rio_msg_regs __iomem *msg_regs; | 189 | struct rio_msg_regs __iomem *msg_regs; |
210 | struct rio_dbell_ring dbell_ring; | ||
211 | struct rio_msg_tx_ring msg_tx_ring; | 190 | struct rio_msg_tx_ring msg_tx_ring; |
212 | struct rio_msg_rx_ring msg_rx_ring; | 191 | struct rio_msg_rx_ring msg_rx_ring; |
213 | int bellirq; | ||
214 | int txirq; | 192 | int txirq; |
215 | int rxirq; | 193 | int rxirq; |
216 | }; | 194 | }; |
@@ -247,9 +225,11 @@ fsl_rio_tx_handler(int irq, void *dev_instance) | |||
247 | if (osr & RIO_MSG_OSR_EOMI) { | 225 | if (osr & RIO_MSG_OSR_EOMI) { |
248 | u32 dqp = in_be32(&rmu->msg_regs->odqdpar); | 226 | u32 dqp = in_be32(&rmu->msg_regs->odqdpar); |
249 | int slot = (dqp - rmu->msg_tx_ring.phys) >> 5; | 227 | int slot = (dqp - rmu->msg_tx_ring.phys) >> 5; |
250 | port->outb_msg[0].mcback(port, rmu->msg_tx_ring.dev_id, -1, | 228 | if (port->outb_msg[0].mcback != NULL) { |
251 | slot); | 229 | port->outb_msg[0].mcback(port, rmu->msg_tx_ring.dev_id, |
252 | 230 | -1, | |
231 | slot); | ||
232 | } | ||
253 | /* Ack the end-of-message interrupt */ | 233 | /* Ack the end-of-message interrupt */ |
254 | out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_EOMI); | 234 | out_be32(&rmu->msg_regs->osr, RIO_MSG_OSR_EOMI); |
255 | } | 235 | } |
@@ -284,12 +264,14 @@ fsl_rio_rx_handler(int irq, void *dev_instance) | |||
284 | /* XXX Need to check/dispatch until queue empty */ | 264 | /* XXX Need to check/dispatch until queue empty */ |
285 | if (isr & RIO_MSG_ISR_DIQI) { | 265 | if (isr & RIO_MSG_ISR_DIQI) { |
286 | /* | 266 | /* |
287 | * We implement *only* mailbox 0, but can receive messages | 267 | * Can receive messages for any mailbox/letter to that |
288 | * for any mailbox/letter to that mailbox destination. So, | 268 | * mailbox destination. So, make the callback with an |
289 | * make the callback with an unknown/invalid mailbox number | 269 | * unknown/invalid mailbox number argument. |
290 | * argument. | 270 | */ |
291 | */ | 271 | if (port->inb_msg[0].mcback != NULL) |
292 | port->inb_msg[0].mcback(port, rmu->msg_rx_ring.dev_id, -1, -1); | 272 | port->inb_msg[0].mcback(port, rmu->msg_rx_ring.dev_id, |
273 | -1, | ||
274 | -1); | ||
293 | 275 | ||
294 | /* Ack the queueing interrupt */ | 276 | /* Ack the queueing interrupt */ |
295 | out_be32(&rmu->msg_regs->isr, RIO_MSG_ISR_DIQI); | 277 | out_be32(&rmu->msg_regs->isr, RIO_MSG_ISR_DIQI); |
@@ -311,27 +293,27 @@ static irqreturn_t | |||
311 | fsl_rio_dbell_handler(int irq, void *dev_instance) | 293 | fsl_rio_dbell_handler(int irq, void *dev_instance) |
312 | { | 294 | { |
313 | int dsr; | 295 | int dsr; |
314 | struct rio_mport *port = (struct rio_mport *)dev_instance; | 296 | struct fsl_rio_dbell *fsl_dbell = (struct fsl_rio_dbell *)dev_instance; |
315 | struct fsl_rmu *rmu = GET_RMM_HANDLE(port); | 297 | int i; |
316 | 298 | ||
317 | dsr = in_be32(&rmu->msg_regs->dsr); | 299 | dsr = in_be32(&fsl_dbell->dbell_regs->dsr); |
318 | 300 | ||
319 | if (dsr & DOORBELL_DSR_TE) { | 301 | if (dsr & DOORBELL_DSR_TE) { |
320 | pr_info("RIO: doorbell reception error\n"); | 302 | pr_info("RIO: doorbell reception error\n"); |
321 | out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_TE); | 303 | out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_TE); |
322 | goto out; | 304 | goto out; |
323 | } | 305 | } |
324 | 306 | ||
325 | if (dsr & DOORBELL_DSR_QFI) { | 307 | if (dsr & DOORBELL_DSR_QFI) { |
326 | pr_info("RIO: doorbell queue full\n"); | 308 | pr_info("RIO: doorbell queue full\n"); |
327 | out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_QFI); | 309 | out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_QFI); |
328 | } | 310 | } |
329 | 311 | ||
330 | /* XXX Need to check/dispatch until queue empty */ | 312 | /* XXX Need to check/dispatch until queue empty */ |
331 | if (dsr & DOORBELL_DSR_DIQI) { | 313 | if (dsr & DOORBELL_DSR_DIQI) { |
332 | u32 dmsg = | 314 | u32 dmsg = |
333 | (u32) rmu->dbell_ring.virt + | 315 | (u32) fsl_dbell->dbell_ring.virt + |
334 | (in_be32(&rmu->msg_regs->dqdpar) & 0xfff); | 316 | (in_be32(&fsl_dbell->dbell_regs->dqdpar) & 0xfff); |
335 | struct rio_dbell *dbell; | 317 | struct rio_dbell *dbell; |
336 | int found = 0; | 318 | int found = 0; |
337 | 319 | ||
@@ -340,48 +322,58 @@ fsl_rio_dbell_handler(int irq, void *dev_instance) | |||
340 | " sid %2.2x tid %2.2x info %4.4x\n", | 322 | " sid %2.2x tid %2.2x info %4.4x\n", |
341 | DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); | 323 | DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); |
342 | 324 | ||
343 | list_for_each_entry(dbell, &port->dbells, node) { | 325 | for (i = 0; i < MAX_PORT_NUM; i++) { |
344 | if ((dbell->res->start <= DBELL_INF(dmsg)) && | 326 | if (fsl_dbell->mport[i]) { |
345 | (dbell->res->end >= DBELL_INF(dmsg))) { | 327 | list_for_each_entry(dbell, |
346 | found = 1; | 328 | &fsl_dbell->mport[i]->dbells, node) { |
347 | break; | 329 | if ((dbell->res->start |
330 | <= DBELL_INF(dmsg)) | ||
331 | && (dbell->res->end | ||
332 | >= DBELL_INF(dmsg))) { | ||
333 | found = 1; | ||
334 | break; | ||
335 | } | ||
336 | } | ||
337 | if (found && dbell->dinb) { | ||
338 | dbell->dinb(fsl_dbell->mport[i], | ||
339 | dbell->dev_id, DBELL_SID(dmsg), | ||
340 | DBELL_TID(dmsg), | ||
341 | DBELL_INF(dmsg)); | ||
342 | break; | ||
343 | } | ||
348 | } | 344 | } |
349 | } | 345 | } |
350 | if (found) { | 346 | |
351 | dbell->dinb(port, dbell->dev_id, | 347 | if (!found) { |
352 | DBELL_SID(dmsg), | ||
353 | DBELL_TID(dmsg), DBELL_INF(dmsg)); | ||
354 | } else { | ||
355 | pr_debug | 348 | pr_debug |
356 | ("RIO: spurious doorbell," | 349 | ("RIO: spurious doorbell," |
357 | " sid %2.2x tid %2.2x info %4.4x\n", | 350 | " sid %2.2x tid %2.2x info %4.4x\n", |
358 | DBELL_SID(dmsg), DBELL_TID(dmsg), | 351 | DBELL_SID(dmsg), DBELL_TID(dmsg), |
359 | DBELL_INF(dmsg)); | 352 | DBELL_INF(dmsg)); |
360 | } | 353 | } |
361 | setbits32(&rmu->msg_regs->dmr, DOORBELL_DMR_DI); | 354 | setbits32(&fsl_dbell->dbell_regs->dmr, DOORBELL_DMR_DI); |
362 | out_be32(&rmu->msg_regs->dsr, DOORBELL_DSR_DIQI); | 355 | out_be32(&fsl_dbell->dbell_regs->dsr, DOORBELL_DSR_DIQI); |
363 | } | 356 | } |
364 | 357 | ||
365 | out: | 358 | out: |
366 | return IRQ_HANDLED; | 359 | return IRQ_HANDLED; |
367 | } | 360 | } |
368 | 361 | ||
369 | void msg_unit_error_handler(struct rio_mport *port) | 362 | void msg_unit_error_handler(void) |
370 | { | 363 | { |
371 | struct fsl_rmu *rmu = GET_RMM_HANDLE(port); | ||
372 | 364 | ||
373 | /*XXX: Error recovery is not implemented, we just clear errors */ | 365 | /*XXX: Error recovery is not implemented, we just clear errors */ |
374 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); | 366 | out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0); |
375 | 367 | ||
376 | out_be32((u32 *)(rio_regs_win + RIO_IM0SR), IMSR_CLEAR); | 368 | out_be32((u32 *)(rmu_regs_win + RIO_IM0SR), IMSR_CLEAR); |
377 | out_be32((u32 *)(rio_regs_win + RIO_IM1SR), IMSR_CLEAR); | 369 | out_be32((u32 *)(rmu_regs_win + RIO_IM1SR), IMSR_CLEAR); |
378 | out_be32((u32 *)(rio_regs_win + RIO_OM0SR), OMSR_CLEAR); | 370 | out_be32((u32 *)(rmu_regs_win + RIO_OM0SR), OMSR_CLEAR); |
379 | out_be32((u32 *)(rio_regs_win + RIO_OM1SR), OMSR_CLEAR); | 371 | out_be32((u32 *)(rmu_regs_win + RIO_OM1SR), OMSR_CLEAR); |
380 | 372 | ||
381 | out_be32(&rmu->msg_regs->odsr, ODSR_CLEAR); | 373 | out_be32(&dbell->dbell_regs->odsr, ODSR_CLEAR); |
382 | out_be32(&rmu->msg_regs->dsr, IDSR_CLEAR); | 374 | out_be32(&dbell->dbell_regs->dsr, IDSR_CLEAR); |
383 | 375 | ||
384 | out_be32(&rmu->msg_regs->pwsr, IPWSR_CLEAR); | 376 | out_be32(&pw->pw_regs->pwsr, IPWSR_CLEAR); |
385 | } | 377 | } |
386 | 378 | ||
387 | /** | 379 | /** |
@@ -396,18 +388,15 @@ static irqreturn_t | |||
396 | fsl_rio_port_write_handler(int irq, void *dev_instance) | 388 | fsl_rio_port_write_handler(int irq, void *dev_instance) |
397 | { | 389 | { |
398 | u32 ipwmr, ipwsr; | 390 | u32 ipwmr, ipwsr; |
399 | struct rio_mport *port = (struct rio_mport *)dev_instance; | 391 | struct fsl_rio_pw *pw = (struct fsl_rio_pw *)dev_instance; |
400 | struct rio_priv *priv = port->priv; | ||
401 | struct fsl_rmu *rmu; | ||
402 | u32 epwisr, tmp; | 392 | u32 epwisr, tmp; |
403 | 393 | ||
404 | rmu = GET_RMM_HANDLE(port); | 394 | epwisr = in_be32(rio_regs_win + RIO_EPWISR); |
405 | epwisr = in_be32(priv->regs_win + RIO_EPWISR); | ||
406 | if (!(epwisr & RIO_EPWISR_PW)) | 395 | if (!(epwisr & RIO_EPWISR_PW)) |
407 | goto pw_done; | 396 | goto pw_done; |
408 | 397 | ||
409 | ipwmr = in_be32(&rmu->msg_regs->pwmr); | 398 | ipwmr = in_be32(&pw->pw_regs->pwmr); |
410 | ipwsr = in_be32(&rmu->msg_regs->pwsr); | 399 | ipwsr = in_be32(&pw->pw_regs->pwsr); |
411 | 400 | ||
412 | #ifdef DEBUG_PW | 401 | #ifdef DEBUG_PW |
413 | pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); | 402 | pr_debug("PW Int->IPWMR: 0x%08x IPWSR: 0x%08x (", ipwmr, ipwsr); |
@@ -428,60 +417,60 @@ fsl_rio_port_write_handler(int irq, void *dev_instance) | |||
428 | /* Save PW message (if there is room in FIFO), | 417 | /* Save PW message (if there is room in FIFO), |
429 | * otherwise discard it. | 418 | * otherwise discard it. |
430 | */ | 419 | */ |
431 | if (kfifo_avail(&priv->pw_fifo) >= RIO_PW_MSG_SIZE) { | 420 | if (kfifo_avail(&pw->pw_fifo) >= RIO_PW_MSG_SIZE) { |
432 | priv->port_write_msg.msg_count++; | 421 | pw->port_write_msg.msg_count++; |
433 | kfifo_in(&priv->pw_fifo, priv->port_write_msg.virt, | 422 | kfifo_in(&pw->pw_fifo, pw->port_write_msg.virt, |
434 | RIO_PW_MSG_SIZE); | 423 | RIO_PW_MSG_SIZE); |
435 | } else { | 424 | } else { |
436 | priv->port_write_msg.discard_count++; | 425 | pw->port_write_msg.discard_count++; |
437 | pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", | 426 | pr_debug("RIO: ISR Discarded Port-Write Msg(s) (%d)\n", |
438 | priv->port_write_msg.discard_count); | 427 | pw->port_write_msg.discard_count); |
439 | } | 428 | } |
440 | /* Clear interrupt and issue Clear Queue command. This allows | 429 | /* Clear interrupt and issue Clear Queue command. This allows |
441 | * another port-write to be received. | 430 | * another port-write to be received. |
442 | */ | 431 | */ |
443 | out_be32(&rmu->msg_regs->pwsr, RIO_IPWSR_QFI); | 432 | out_be32(&pw->pw_regs->pwsr, RIO_IPWSR_QFI); |
444 | out_be32(&rmu->msg_regs->pwmr, ipwmr | RIO_IPWMR_CQ); | 433 | out_be32(&pw->pw_regs->pwmr, ipwmr | RIO_IPWMR_CQ); |
445 | 434 | ||
446 | schedule_work(&priv->pw_work); | 435 | schedule_work(&pw->pw_work); |
447 | } | 436 | } |
448 | 437 | ||
449 | if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { | 438 | if ((ipwmr & RIO_IPWMR_EIE) && (ipwsr & RIO_IPWSR_TE)) { |
450 | priv->port_write_msg.err_count++; | 439 | pw->port_write_msg.err_count++; |
451 | pr_debug("RIO: Port-Write Transaction Err (%d)\n", | 440 | pr_debug("RIO: Port-Write Transaction Err (%d)\n", |
452 | priv->port_write_msg.err_count); | 441 | pw->port_write_msg.err_count); |
453 | /* Clear Transaction Error: port-write controller should be | 442 | /* Clear Transaction Error: port-write controller should be |
454 | * disabled when clearing this error | 443 | * disabled when clearing this error |
455 | */ | 444 | */ |
456 | out_be32(&rmu->msg_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE); | 445 | out_be32(&pw->pw_regs->pwmr, ipwmr & ~RIO_IPWMR_PWE); |
457 | out_be32(&rmu->msg_regs->pwsr, RIO_IPWSR_TE); | 446 | out_be32(&pw->pw_regs->pwsr, RIO_IPWSR_TE); |
458 | out_be32(&rmu->msg_regs->pwmr, ipwmr); | 447 | out_be32(&pw->pw_regs->pwmr, ipwmr); |
459 | } | 448 | } |
460 | 449 | ||
461 | if (ipwsr & RIO_IPWSR_PWD) { | 450 | if (ipwsr & RIO_IPWSR_PWD) { |
462 | priv->port_write_msg.discard_count++; | 451 | pw->port_write_msg.discard_count++; |
463 | pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n", | 452 | pr_debug("RIO: Port Discarded Port-Write Msg(s) (%d)\n", |
464 | priv->port_write_msg.discard_count); | 453 | pw->port_write_msg.discard_count); |
465 | out_be32(&rmu->msg_regs->pwsr, RIO_IPWSR_PWD); | 454 | out_be32(&pw->pw_regs->pwsr, RIO_IPWSR_PWD); |
466 | } | 455 | } |
467 | 456 | ||
468 | pw_done: | 457 | pw_done: |
469 | if (epwisr & RIO_EPWISR_PINT1) { | 458 | if (epwisr & RIO_EPWISR_PINT1) { |
470 | tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); | 459 | tmp = in_be32(rio_regs_win + RIO_LTLEDCSR); |
471 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); | 460 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); |
472 | fsl_rio_port_error_handler(port, 0); | 461 | fsl_rio_port_error_handler(0); |
473 | } | 462 | } |
474 | 463 | ||
475 | if (epwisr & RIO_EPWISR_PINT2) { | 464 | if (epwisr & RIO_EPWISR_PINT2) { |
476 | tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); | 465 | tmp = in_be32(rio_regs_win + RIO_LTLEDCSR); |
477 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); | 466 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); |
478 | fsl_rio_port_error_handler(port, 1); | 467 | fsl_rio_port_error_handler(1); |
479 | } | 468 | } |
480 | 469 | ||
481 | if (epwisr & RIO_EPWISR_MU) { | 470 | if (epwisr & RIO_EPWISR_MU) { |
482 | tmp = in_be32(priv->regs_win + RIO_LTLEDCSR); | 471 | tmp = in_be32(rio_regs_win + RIO_LTLEDCSR); |
483 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); | 472 | pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp); |
484 | msg_unit_error_handler(port); | 473 | msg_unit_error_handler(); |
485 | } | 474 | } |
486 | 475 | ||
487 | return IRQ_HANDLED; | 476 | return IRQ_HANDLED; |
@@ -489,18 +478,15 @@ pw_done: | |||
489 | 478 | ||
490 | static void fsl_pw_dpc(struct work_struct *work) | 479 | static void fsl_pw_dpc(struct work_struct *work) |
491 | { | 480 | { |
492 | struct rio_priv *priv = container_of(work, struct rio_priv, pw_work); | 481 | struct fsl_rio_pw *pw = container_of(work, struct fsl_rio_pw, pw_work); |
493 | unsigned long flags; | ||
494 | u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; | 482 | u32 msg_buffer[RIO_PW_MSG_SIZE/sizeof(u32)]; |
495 | 483 | ||
496 | /* | 484 | /* |
497 | * Process port-write messages | 485 | * Process port-write messages |
498 | */ | 486 | */ |
499 | spin_lock_irqsave(&priv->pw_fifo_lock, flags); | 487 | while (kfifo_out_spinlocked(&pw->pw_fifo, (unsigned char *)msg_buffer, |
500 | while (kfifo_out(&priv->pw_fifo, (unsigned char *)msg_buffer, | 488 | RIO_PW_MSG_SIZE, &pw->pw_fifo_lock)) { |
501 | RIO_PW_MSG_SIZE)) { | ||
502 | /* Process one message */ | 489 | /* Process one message */ |
503 | spin_unlock_irqrestore(&priv->pw_fifo_lock, flags); | ||
504 | #ifdef DEBUG_PW | 490 | #ifdef DEBUG_PW |
505 | { | 491 | { |
506 | u32 i; | 492 | u32 i; |
@@ -517,31 +503,26 @@ static void fsl_pw_dpc(struct work_struct *work) | |||
517 | #endif | 503 | #endif |
518 | /* Pass the port-write message to RIO core for processing */ | 504 | /* Pass the port-write message to RIO core for processing */ |
519 | rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer); | 505 | rio_inb_pwrite_handler((union rio_pw_msg *)msg_buffer); |
520 | spin_lock_irqsave(&priv->pw_fifo_lock, flags); | ||
521 | } | 506 | } |
522 | spin_unlock_irqrestore(&priv->pw_fifo_lock, flags); | ||
523 | } | 507 | } |
524 | 508 | ||
525 | /** | 509 | /** |
526 | * fsl_rio_pw_enable - enable/disable port-write interface init | 510 | * fsl_rio_pw_enable - enable/disable port-write interface init |
527 | * @mport: Master port implementing the port write unit | 511 | * @mport: Master port implementing the port write unit |
528 | * @enable: 1=enable; 0=disable port-write message handling | 512 | * @enable: 1=enable; 0=disable port-write message handling |
529 | */ | 513 | */ |
530 | int fsl_rio_pw_enable(struct rio_mport *mport, int enable) | 514 | int fsl_rio_pw_enable(struct rio_mport *mport, int enable) |
531 | { | 515 | { |
532 | struct fsl_rmu *rmu; | ||
533 | u32 rval; | 516 | u32 rval; |
534 | 517 | ||
535 | rmu = GET_RMM_HANDLE(mport); | 518 | rval = in_be32(&pw->pw_regs->pwmr); |
536 | |||
537 | rval = in_be32(&rmu->msg_regs->pwmr); | ||
538 | 519 | ||
539 | if (enable) | 520 | if (enable) |
540 | rval |= RIO_IPWMR_PWE; | 521 | rval |= RIO_IPWMR_PWE; |
541 | else | 522 | else |
542 | rval &= ~RIO_IPWMR_PWE; | 523 | rval &= ~RIO_IPWMR_PWE; |
543 | 524 | ||
544 | out_be32(&rmu->msg_regs->pwmr, rval); | 525 | out_be32(&pw->pw_regs->pwmr, rval); |
545 | 526 | ||
546 | return 0; | 527 | return 0; |
547 | } | 528 | } |
@@ -555,51 +536,47 @@ int fsl_rio_pw_enable(struct rio_mport *mport, int enable) | |||
555 | * or %-ENOMEM on failure. | 536 | * or %-ENOMEM on failure. |
556 | */ | 537 | */ |
557 | 538 | ||
558 | int fsl_rio_port_write_init(struct rio_mport *mport) | 539 | int fsl_rio_port_write_init(struct fsl_rio_pw *pw) |
559 | { | 540 | { |
560 | struct rio_priv *priv = mport->priv; | ||
561 | struct fsl_rmu *rmu; | ||
562 | int rc = 0; | 541 | int rc = 0; |
563 | 542 | ||
564 | rmu = GET_RMM_HANDLE(mport); | ||
565 | |||
566 | /* Following configurations require a disabled port write controller */ | 543 | /* Following configurations require a disabled port write controller */ |
567 | out_be32(&rmu->msg_regs->pwmr, | 544 | out_be32(&pw->pw_regs->pwmr, |
568 | in_be32(&rmu->msg_regs->pwmr) & ~RIO_IPWMR_PWE); | 545 | in_be32(&pw->pw_regs->pwmr) & ~RIO_IPWMR_PWE); |
569 | 546 | ||
570 | /* Initialize port write */ | 547 | /* Initialize port write */ |
571 | priv->port_write_msg.virt = dma_alloc_coherent(priv->dev, | 548 | pw->port_write_msg.virt = dma_alloc_coherent(pw->dev, |
572 | RIO_PW_MSG_SIZE, | 549 | RIO_PW_MSG_SIZE, |
573 | &priv->port_write_msg.phys, GFP_KERNEL); | 550 | &pw->port_write_msg.phys, GFP_KERNEL); |
574 | if (!priv->port_write_msg.virt) { | 551 | if (!pw->port_write_msg.virt) { |
575 | pr_err("RIO: unable allocate port write queue\n"); | 552 | pr_err("RIO: unable allocate port write queue\n"); |
576 | return -ENOMEM; | 553 | return -ENOMEM; |
577 | } | 554 | } |
578 | 555 | ||
579 | priv->port_write_msg.err_count = 0; | 556 | pw->port_write_msg.err_count = 0; |
580 | priv->port_write_msg.discard_count = 0; | 557 | pw->port_write_msg.discard_count = 0; |
581 | 558 | ||
582 | /* Point dequeue/enqueue pointers at first entry */ | 559 | /* Point dequeue/enqueue pointers at first entry */ |
583 | out_be32(&rmu->msg_regs->epwqbar, 0); | 560 | out_be32(&pw->pw_regs->epwqbar, 0); |
584 | out_be32(&rmu->msg_regs->pwqbar, (u32) priv->port_write_msg.phys); | 561 | out_be32(&pw->pw_regs->pwqbar, (u32) pw->port_write_msg.phys); |
585 | 562 | ||
586 | pr_debug("EIPWQBAR: 0x%08x IPWQBAR: 0x%08x\n", | 563 | pr_debug("EIPWQBAR: 0x%08x IPWQBAR: 0x%08x\n", |
587 | in_be32(&rmu->msg_regs->epwqbar), | 564 | in_be32(&pw->pw_regs->epwqbar), |
588 | in_be32(&rmu->msg_regs->pwqbar)); | 565 | in_be32(&pw->pw_regs->pwqbar)); |
589 | 566 | ||
590 | /* Clear interrupt status IPWSR */ | 567 | /* Clear interrupt status IPWSR */ |
591 | out_be32(&rmu->msg_regs->pwsr, | 568 | out_be32(&pw->pw_regs->pwsr, |
592 | (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD)); | 569 | (RIO_IPWSR_TE | RIO_IPWSR_QFI | RIO_IPWSR_PWD)); |
593 | 570 | ||
594 | /* Configure port write contoller for snooping enable all reporting, | 571 | /* Configure port write contoller for snooping enable all reporting, |
595 | clear queue full */ | 572 | clear queue full */ |
596 | out_be32(&rmu->msg_regs->pwmr, | 573 | out_be32(&pw->pw_regs->pwmr, |
597 | RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ); | 574 | RIO_IPWMR_SEN | RIO_IPWMR_QFIE | RIO_IPWMR_EIE | RIO_IPWMR_CQ); |
598 | 575 | ||
599 | 576 | ||
600 | /* Hook up port-write handler */ | 577 | /* Hook up port-write handler */ |
601 | rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, | 578 | rc = request_irq(IRQ_RIO_PW(pw), fsl_rio_port_write_handler, |
602 | IRQF_SHARED, "port-write", (void *)mport); | 579 | IRQF_SHARED, "port-write", (void *)pw); |
603 | if (rc < 0) { | 580 | if (rc < 0) { |
604 | pr_err("MPC85xx RIO: unable to request inbound doorbell irq"); | 581 | pr_err("MPC85xx RIO: unable to request inbound doorbell irq"); |
605 | goto err_out; | 582 | goto err_out; |
@@ -607,26 +584,26 @@ int fsl_rio_port_write_init(struct rio_mport *mport) | |||
607 | /* Enable Error Interrupt */ | 584 | /* Enable Error Interrupt */ |
608 | out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL); | 585 | out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL); |
609 | 586 | ||
610 | INIT_WORK(&priv->pw_work, fsl_pw_dpc); | 587 | INIT_WORK(&pw->pw_work, fsl_pw_dpc); |
611 | spin_lock_init(&priv->pw_fifo_lock); | 588 | spin_lock_init(&pw->pw_fifo_lock); |
612 | if (kfifo_alloc(&priv->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) { | 589 | if (kfifo_alloc(&pw->pw_fifo, RIO_PW_MSG_SIZE * 32, GFP_KERNEL)) { |
613 | pr_err("FIFO allocation failed\n"); | 590 | pr_err("FIFO allocation failed\n"); |
614 | rc = -ENOMEM; | 591 | rc = -ENOMEM; |
615 | goto err_out_irq; | 592 | goto err_out_irq; |
616 | } | 593 | } |
617 | 594 | ||
618 | pr_debug("IPWMR: 0x%08x IPWSR: 0x%08x\n", | 595 | pr_debug("IPWMR: 0x%08x IPWSR: 0x%08x\n", |
619 | in_be32(&rmu->msg_regs->pwmr), | 596 | in_be32(&pw->pw_regs->pwmr), |
620 | in_be32(&rmu->msg_regs->pwsr)); | 597 | in_be32(&pw->pw_regs->pwsr)); |
621 | 598 | ||
622 | return rc; | 599 | return rc; |
623 | 600 | ||
624 | err_out_irq: | 601 | err_out_irq: |
625 | free_irq(IRQ_RIO_PW(mport), (void *)mport); | 602 | free_irq(IRQ_RIO_PW(pw), (void *)pw); |
626 | err_out: | 603 | err_out: |
627 | dma_free_coherent(priv->dev, RIO_PW_MSG_SIZE, | 604 | dma_free_coherent(pw->dev, RIO_PW_MSG_SIZE, |
628 | priv->port_write_msg.virt, | 605 | pw->port_write_msg.virt, |
629 | priv->port_write_msg.phys); | 606 | pw->port_write_msg.phys); |
630 | return rc; | 607 | return rc; |
631 | } | 608 | } |
632 | 609 | ||
@@ -640,29 +617,20 @@ err_out: | |||
640 | * Sends a MPC85xx doorbell message. Returns %0 on success or | 617 | * Sends a MPC85xx doorbell message. Returns %0 on success or |
641 | * %-EINVAL on failure. | 618 | * %-EINVAL on failure. |
642 | */ | 619 | */ |
643 | static int fsl_rio_doorbell_send(struct rio_mport *mport, | 620 | int fsl_rio_doorbell_send(struct rio_mport *mport, |
644 | int index, u16 destid, u16 data) | 621 | int index, u16 destid, u16 data) |
645 | { | 622 | { |
646 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); | ||
647 | |||
648 | pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", | 623 | pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", |
649 | index, destid, data); | 624 | index, destid, data); |
650 | switch (mport->phy_type) { | 625 | |
651 | case RIO_PHY_PARALLEL: | 626 | /* In the serial version silicons, such as MPC8548, MPC8641, |
652 | out_be32(&rmu->dbell_atmu_regs->rowtar, destid << 22); | 627 | * below operations is must be. |
653 | out_be16(rmu->dbell_win, data); | 628 | */ |
654 | break; | 629 | out_be32(&dbell->dbell_regs->odmr, 0x00000000); |
655 | case RIO_PHY_SERIAL: | 630 | out_be32(&dbell->dbell_regs->odretcr, 0x00000004); |
656 | /* In the serial version silicons, such as MPC8548, MPC8641, | 631 | out_be32(&dbell->dbell_regs->oddpr, destid << 16); |
657 | * below operations is must be. | 632 | out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data); |
658 | */ | 633 | out_be32(&dbell->dbell_regs->odmr, 0x00000001); |
659 | out_be32(&rmu->msg_regs->odmr, 0x00000000); | ||
660 | out_be32(&rmu->msg_regs->odretcr, 0x00000004); | ||
661 | out_be32(&rmu->msg_regs->oddpr, destid << 16); | ||
662 | out_be32(&rmu->msg_regs->oddatr, data); | ||
663 | out_be32(&rmu->msg_regs->odmr, 0x00000001); | ||
664 | break; | ||
665 | } | ||
666 | 634 | ||
667 | return 0; | 635 | return 0; |
668 | } | 636 | } |
@@ -678,7 +646,7 @@ static int fsl_rio_doorbell_send(struct rio_mport *mport, | |||
678 | * Adds the @buffer message to the MPC85xx outbound message queue. Returns | 646 | * Adds the @buffer message to the MPC85xx outbound message queue. Returns |
679 | * %0 on success or %-EINVAL on failure. | 647 | * %0 on success or %-EINVAL on failure. |
680 | */ | 648 | */ |
681 | static int | 649 | int |
682 | fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | 650 | fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, |
683 | void *buffer, size_t len) | 651 | void *buffer, size_t len) |
684 | { | 652 | { |
@@ -690,7 +658,6 @@ fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | |||
690 | 658 | ||
691 | pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \ | 659 | pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \ |
692 | "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len); | 660 | "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len); |
693 | |||
694 | if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { | 661 | if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) { |
695 | ret = -EINVAL; | 662 | ret = -EINVAL; |
696 | goto out; | 663 | goto out; |
@@ -703,22 +670,11 @@ fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, | |||
703 | memset(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot] | 670 | memset(rmu->msg_tx_ring.virt_buffer[rmu->msg_tx_ring.tx_slot] |
704 | + len, 0, RIO_MAX_MSG_SIZE - len); | 671 | + len, 0, RIO_MAX_MSG_SIZE - len); |
705 | 672 | ||
706 | switch (mport->phy_type) { | 673 | /* Set mbox field for message, and set destid */ |
707 | case RIO_PHY_PARALLEL: | 674 | desc->dport = (rdev->destid << 16) | (mbox & 0x3); |
708 | /* Set mbox field for message */ | 675 | |
709 | desc->dport = mbox & 0x3; | 676 | /* Enable EOMI interrupt and priority */ |
710 | 677 | desc->dattr = 0x28000000 | ((mport->index) << 20); | |
711 | /* Enable EOMI interrupt, set priority, and set destid */ | ||
712 | desc->dattr = 0x28000000 | (rdev->destid << 2); | ||
713 | break; | ||
714 | case RIO_PHY_SERIAL: | ||
715 | /* Set mbox field for message, and set destid */ | ||
716 | desc->dport = (rdev->destid << 16) | (mbox & 0x3); | ||
717 | |||
718 | /* Enable EOMI interrupt and priority */ | ||
719 | desc->dattr = 0x28000000; | ||
720 | break; | ||
721 | } | ||
722 | 678 | ||
723 | /* Set transfer size aligned to next power of 2 (in double words) */ | 679 | /* Set transfer size aligned to next power of 2 (in double words) */ |
724 | desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); | 680 | desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); |
@@ -750,7 +706,7 @@ out: | |||
750 | * and enables the outbound message unit. Returns %0 on success and | 706 | * and enables the outbound message unit. Returns %0 on success and |
751 | * %-EINVAL or %-ENOMEM on failure. | 707 | * %-EINVAL or %-ENOMEM on failure. |
752 | */ | 708 | */ |
753 | static int | 709 | int |
754 | fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) | 710 | fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) |
755 | { | 711 | { |
756 | int i, j, rc = 0; | 712 | int i, j, rc = 0; |
@@ -855,7 +811,7 @@ out_dma: | |||
855 | * Disables the outbound message unit, free all buffers, and | 811 | * Disables the outbound message unit, free all buffers, and |
856 | * frees the outbound message interrupt. | 812 | * frees the outbound message interrupt. |
857 | */ | 813 | */ |
858 | static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox) | 814 | void fsl_close_outb_mbox(struct rio_mport *mport, int mbox) |
859 | { | 815 | { |
860 | struct rio_priv *priv = mport->priv; | 816 | struct rio_priv *priv = mport->priv; |
861 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); | 817 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); |
@@ -883,7 +839,7 @@ static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox) | |||
883 | * and enables the inbound message unit. Returns %0 on success | 839 | * and enables the inbound message unit. Returns %0 on success |
884 | * and %-EINVAL or %-ENOMEM on failure. | 840 | * and %-EINVAL or %-ENOMEM on failure. |
885 | */ | 841 | */ |
886 | static int | 842 | int |
887 | fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) | 843 | fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) |
888 | { | 844 | { |
889 | int i, rc = 0; | 845 | int i, rc = 0; |
@@ -956,7 +912,7 @@ out: | |||
956 | * Disables the inbound message unit, free all buffers, and | 912 | * Disables the inbound message unit, free all buffers, and |
957 | * frees the inbound message interrupt. | 913 | * frees the inbound message interrupt. |
958 | */ | 914 | */ |
959 | static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox) | 915 | void fsl_close_inb_mbox(struct rio_mport *mport, int mbox) |
960 | { | 916 | { |
961 | struct rio_priv *priv = mport->priv; | 917 | struct rio_priv *priv = mport->priv; |
962 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); | 918 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); |
@@ -966,7 +922,7 @@ static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox) | |||
966 | 922 | ||
967 | /* Free ring */ | 923 | /* Free ring */ |
968 | dma_free_coherent(priv->dev, rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE, | 924 | dma_free_coherent(priv->dev, rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE, |
969 | rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys); | 925 | rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys); |
970 | 926 | ||
971 | /* Free interrupt */ | 927 | /* Free interrupt */ |
972 | free_irq(IRQ_RIO_RX(mport), (void *)mport); | 928 | free_irq(IRQ_RIO_RX(mport), (void *)mport); |
@@ -981,7 +937,7 @@ static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox) | |||
981 | * Adds the @buf buffer to the MPC85xx inbound message queue. Returns | 937 | * Adds the @buf buffer to the MPC85xx inbound message queue. Returns |
982 | * %0 on success or %-EINVAL on failure. | 938 | * %0 on success or %-EINVAL on failure. |
983 | */ | 939 | */ |
984 | static int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) | 940 | int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) |
985 | { | 941 | { |
986 | int rc = 0; | 942 | int rc = 0; |
987 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); | 943 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); |
@@ -1013,7 +969,7 @@ out: | |||
1013 | * Gets the next available inbound message from the inbound message queue. | 969 | * Gets the next available inbound message from the inbound message queue. |
1014 | * A pointer to the message is returned on success or NULL on failure. | 970 | * A pointer to the message is returned on success or NULL on failure. |
1015 | */ | 971 | */ |
1016 | static void *fsl_get_inb_message(struct rio_mport *mport, int mbox) | 972 | void *fsl_get_inb_message(struct rio_mport *mport, int mbox) |
1017 | { | 973 | { |
1018 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); | 974 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); |
1019 | u32 phys_buf, virt_buf; | 975 | u32 phys_buf, virt_buf; |
@@ -1058,53 +1014,39 @@ out2: | |||
1058 | * ring. Called from fsl_rio_setup(). Returns %0 on success | 1014 | * ring. Called from fsl_rio_setup(). Returns %0 on success |
1059 | * or %-ENOMEM on failure. | 1015 | * or %-ENOMEM on failure. |
1060 | */ | 1016 | */ |
1061 | static int fsl_rio_doorbell_init(struct rio_mport *mport) | 1017 | int fsl_rio_doorbell_init(struct fsl_rio_dbell *dbell) |
1062 | { | 1018 | { |
1063 | struct rio_priv *priv = mport->priv; | ||
1064 | struct fsl_rmu *rmu = GET_RMM_HANDLE(mport); | ||
1065 | int rc = 0; | 1019 | int rc = 0; |
1066 | 1020 | ||
1067 | /* Map outbound doorbell window immediately after maintenance window */ | ||
1068 | rmu->dbell_win = ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE, | ||
1069 | RIO_DBELL_WIN_SIZE); | ||
1070 | if (!rmu->dbell_win) { | ||
1071 | printk(KERN_ERR | ||
1072 | "RIO: unable to map outbound doorbell window\n"); | ||
1073 | rc = -ENOMEM; | ||
1074 | goto out; | ||
1075 | } | ||
1076 | |||
1077 | /* Initialize inbound doorbells */ | 1021 | /* Initialize inbound doorbells */ |
1078 | rmu->dbell_ring.virt = dma_alloc_coherent(priv->dev, 512 * | 1022 | dbell->dbell_ring.virt = dma_alloc_coherent(dbell->dev, 512 * |
1079 | DOORBELL_MESSAGE_SIZE, &rmu->dbell_ring.phys, GFP_KERNEL); | 1023 | DOORBELL_MESSAGE_SIZE, &dbell->dbell_ring.phys, GFP_KERNEL); |
1080 | if (!rmu->dbell_ring.virt) { | 1024 | if (!dbell->dbell_ring.virt) { |
1081 | printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n"); | 1025 | printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n"); |
1082 | rc = -ENOMEM; | 1026 | rc = -ENOMEM; |
1083 | iounmap(rmu->dbell_win); | ||
1084 | goto out; | 1027 | goto out; |
1085 | } | 1028 | } |
1086 | 1029 | ||
1087 | /* Point dequeue/enqueue pointers at first entry in ring */ | 1030 | /* Point dequeue/enqueue pointers at first entry in ring */ |
1088 | out_be32(&rmu->msg_regs->dqdpar, (u32) rmu->dbell_ring.phys); | 1031 | out_be32(&dbell->dbell_regs->dqdpar, (u32) dbell->dbell_ring.phys); |
1089 | out_be32(&rmu->msg_regs->dqepar, (u32) rmu->dbell_ring.phys); | 1032 | out_be32(&dbell->dbell_regs->dqepar, (u32) dbell->dbell_ring.phys); |
1090 | 1033 | ||
1091 | /* Clear interrupt status */ | 1034 | /* Clear interrupt status */ |
1092 | out_be32(&rmu->msg_regs->dsr, 0x00000091); | 1035 | out_be32(&dbell->dbell_regs->dsr, 0x00000091); |
1093 | 1036 | ||
1094 | /* Hook up doorbell handler */ | 1037 | /* Hook up doorbell handler */ |
1095 | rc = request_irq(IRQ_RIO_BELL(mport), fsl_rio_dbell_handler, 0, | 1038 | rc = request_irq(IRQ_RIO_BELL(dbell), fsl_rio_dbell_handler, 0, |
1096 | "dbell_rx", (void *)mport); | 1039 | "dbell_rx", (void *)dbell); |
1097 | if (rc < 0) { | 1040 | if (rc < 0) { |
1098 | iounmap(rmu->dbell_win); | 1041 | dma_free_coherent(dbell->dev, 512 * DOORBELL_MESSAGE_SIZE, |
1099 | dma_free_coherent(priv->dev, 512 * DOORBELL_MESSAGE_SIZE, | 1042 | dbell->dbell_ring.virt, dbell->dbell_ring.phys); |
1100 | rmu->dbell_ring.virt, rmu->dbell_ring.phys); | ||
1101 | printk(KERN_ERR | 1043 | printk(KERN_ERR |
1102 | "MPC85xx RIO: unable to request inbound doorbell irq"); | 1044 | "MPC85xx RIO: unable to request inbound doorbell irq"); |
1103 | goto out; | 1045 | goto out; |
1104 | } | 1046 | } |
1105 | 1047 | ||
1106 | /* Configure doorbells for snooping, 512 entries, and enable */ | 1048 | /* Configure doorbells for snooping, 512 entries, and enable */ |
1107 | out_be32(&rmu->msg_regs->dmr, 0x00108161); | 1049 | out_be32(&dbell->dbell_regs->dmr, 0x00108161); |
1108 | 1050 | ||
1109 | out: | 1051 | out: |
1110 | return rc; | 1052 | return rc; |
@@ -1114,50 +1056,48 @@ int fsl_rio_setup_rmu(struct rio_mport *mport, struct device_node *node) | |||
1114 | { | 1056 | { |
1115 | struct rio_priv *priv; | 1057 | struct rio_priv *priv; |
1116 | struct fsl_rmu *rmu; | 1058 | struct fsl_rmu *rmu; |
1117 | struct rio_ops *ops; | 1059 | u64 msg_start; |
1060 | const u32 *msg_addr; | ||
1061 | int mlen; | ||
1062 | int aw; | ||
1118 | 1063 | ||
1119 | if (!mport || !mport->priv || !node) | 1064 | if (!mport || !mport->priv) |
1120 | return -1; | 1065 | return -EINVAL; |
1066 | |||
1067 | priv = mport->priv; | ||
1068 | |||
1069 | if (!node) { | ||
1070 | dev_warn(priv->dev, "Can't get %s property 'fsl,rmu'\n", | ||
1071 | priv->dev->of_node->full_name); | ||
1072 | return -EINVAL; | ||
1073 | } | ||
1121 | 1074 | ||
1122 | rmu = kzalloc(sizeof(struct fsl_rmu), GFP_KERNEL); | 1075 | rmu = kzalloc(sizeof(struct fsl_rmu), GFP_KERNEL); |
1123 | if (!rmu) | 1076 | if (!rmu) |
1124 | return -ENOMEM; | 1077 | return -ENOMEM; |
1125 | 1078 | ||
1126 | priv = mport->priv; | 1079 | aw = of_n_addr_cells(node); |
1080 | msg_addr = of_get_property(node, "reg", &mlen); | ||
1081 | if (!msg_addr) { | ||
1082 | pr_err("%s: unable to find 'reg' property of message-unit\n", | ||
1083 | node->full_name); | ||
1084 | return -ENOMEM; | ||
1085 | } | ||
1086 | msg_start = of_read_number(msg_addr, aw); | ||
1087 | |||
1088 | rmu->msg_regs = (struct rio_msg_regs *) | ||
1089 | (rmu_regs_win + (u32)msg_start); | ||
1090 | |||
1091 | rmu->txirq = irq_of_parse_and_map(node, 0); | ||
1092 | rmu->rxirq = irq_of_parse_and_map(node, 1); | ||
1093 | printk(KERN_INFO "%s: txirq: %d, rxirq %d\n", | ||
1094 | node->full_name, rmu->txirq, rmu->rxirq); | ||
1095 | |||
1127 | priv->rmm_handle = rmu; | 1096 | priv->rmm_handle = rmu; |
1128 | rmu->dbell_atmu_regs = priv->atmu_regs + 2; | ||
1129 | rmu->msg_regs = (struct rio_msg_regs *)(priv->regs_win + | ||
1130 | ((mport->phy_type == RIO_PHY_SERIAL) ? | ||
1131 | RIO_S_MSG_REGS_OFFSET : RIO_P_MSG_REGS_OFFSET)); | ||
1132 | |||
1133 | rmu->bellirq = irq_of_parse_and_map(node, 2); | ||
1134 | rmu->txirq = irq_of_parse_and_map(node, 3); | ||
1135 | rmu->rxirq = irq_of_parse_and_map(node, 4); | ||
1136 | dev_info(priv->dev, "bellirq: %d, txirq: %d, rxirq %d\n", | ||
1137 | rmu->bellirq, rmu->txirq, rmu->rxirq); | ||
1138 | |||
1139 | ops = mport->ops; | ||
1140 | |||
1141 | ops->dsend = fsl_rio_doorbell_send; | ||
1142 | ops->open_outb_mbox = fsl_open_outb_mbox; | ||
1143 | ops->open_inb_mbox = fsl_open_inb_mbox; | ||
1144 | ops->close_outb_mbox = fsl_close_outb_mbox; | ||
1145 | ops->close_inb_mbox = fsl_close_inb_mbox; | ||
1146 | ops->add_outb_message = fsl_add_outb_message; | ||
1147 | ops->add_inb_buffer = fsl_add_inb_buffer; | ||
1148 | ops->get_inb_message = fsl_get_inb_message; | ||
1149 | 1097 | ||
1150 | rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); | 1098 | rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); |
1151 | rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0); | 1099 | rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 0); |
1152 | rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); | 1100 | rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); |
1153 | 1101 | ||
1154 | /* Configure outbound doorbell window */ | ||
1155 | out_be32(&rmu->dbell_atmu_regs->rowbar, | ||
1156 | (mport->iores.start + RIO_MAINT_WIN_SIZE) >> 12); | ||
1157 | /* 4k window size */ | ||
1158 | out_be32(&rmu->dbell_atmu_regs->rowar, 0x8004200b); | ||
1159 | |||
1160 | fsl_rio_doorbell_init(mport); | ||
1161 | |||
1162 | return 0; | 1102 | return 0; |
1163 | } | 1103 | } |