[POWERPC] spufs: support new OF device tree format

The properties we used traditionally in the device tree are somewhat
nonstandard. This adds support for a more conventional format using
'interrupts' and 'reg' properties.

The interrupts are specified in three cells (class 0, 1 and 2) and
registered at the interrupt-parent.

The reg property contains either three or four register areas in the
order 'local-store', 'problem', 'priv2', and 'priv1', so the priv1 one
can be left out in case of hypervisor driven systems that access these
through hcalls.

Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>

authored by Arnd Bergmann and committed by Paul Mackerras 7650f2f2 e1dbff2b

+94 -5
+94 -5
arch/powerpc/platforms/cell/spu_base.c
··· 25 25 #include <linux/interrupt.h> 26 26 #include <linux/list.h> 27 27 #include <linux/module.h> 28 + #include <linux/pci.h> 28 29 #include <linux/poll.h> 29 30 #include <linux/ptrace.h> 30 31 #include <linux/slab.h> 31 32 #include <linux/wait.h> 32 33 34 + #include <asm/firmware.h> 33 35 #include <asm/io.h> 34 36 #include <asm/prom.h> 35 37 #include <linux/mutex.h> ··· 578 576 } 579 577 580 578 /* This function shall be abstracted for HV platforms */ 581 - static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) 579 + static int __init spu_map_interrupts_old(struct spu *spu, struct device_node *np) 582 580 { 583 581 unsigned int isrc; 584 582 const u32 *tmp; ··· 602 600 return spu->irqs[2] == NO_IRQ ? -EINVAL : 0; 603 601 } 604 602 605 - static int __init spu_map_device(struct spu *spu, struct device_node *node) 603 + static int __init spu_map_device_old(struct spu *spu, struct device_node *node) 606 604 { 607 605 const char *prop; 608 606 int ret; ··· 644 642 out_unmap: 645 643 spu_unmap(spu); 646 644 out: 645 + return ret; 646 + } 647 + 648 + static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) 649 + { 650 + struct of_irq oirq; 651 + int ret; 652 + int i; 653 + 654 + for (i=0; i < 3; i++) { 655 + ret = of_irq_map_one(np, i, &oirq); 656 + if (ret) 657 + goto err; 658 + 659 + ret = -EINVAL; 660 + spu->irqs[i] = irq_create_of_mapping(oirq.controller, 661 + oirq.specifier, oirq.size); 662 + if (spu->irqs[i] == NO_IRQ) 663 + goto err; 664 + } 665 + return 0; 666 + 667 + err: 668 + pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, spu->name); 669 + for (; i >= 0; i--) { 670 + if (spu->irqs[i] != NO_IRQ) 671 + irq_dispose_mapping(spu->irqs[i]); 672 + } 673 + return ret; 674 + } 675 + 676 + static int spu_map_resource(struct device_node *node, int nr, 677 + void __iomem** virt, unsigned long *phys) 678 + { 679 + struct resource resource = { }; 680 + int ret; 681 + 682 + ret = of_address_to_resource(node, 0, &resource); 683 + if (ret) 684 + goto out; 685 + 686 + if (phys) 687 + *phys = resource.start; 688 + *virt = ioremap(resource.start, resource.end - resource.start); 689 + if (!*virt) 690 + ret = -EINVAL; 691 + 692 + out: 693 + return ret; 694 + } 695 + 696 + static int __init spu_map_device(struct spu *spu, struct device_node *node) 697 + { 698 + int ret = -ENODEV; 699 + spu->name = get_property(node, "name", NULL); 700 + if (!spu->name) 701 + goto out; 702 + 703 + ret = spu_map_resource(node, 0, (void __iomem**)&spu->local_store, 704 + &spu->local_store_phys); 705 + if (ret) 706 + goto out; 707 + ret = spu_map_resource(node, 1, (void __iomem**)&spu->problem, 708 + &spu->problem_phys); 709 + if (ret) 710 + goto out_unmap; 711 + ret = spu_map_resource(node, 2, (void __iomem**)&spu->priv2, 712 + NULL); 713 + if (ret) 714 + goto out_unmap; 715 + 716 + if (!firmware_has_feature(FW_FEATURE_LPAR)) 717 + ret = spu_map_resource(node, 3, (void __iomem**)&spu->priv1, 718 + NULL); 719 + if (ret) 720 + goto out_unmap; 721 + return 0; 722 + 723 + out_unmap: 724 + spu_unmap(spu); 725 + out: 726 + pr_debug("failed to map spe %s: %d\n", spu->name, ret); 647 727 return ret; 648 728 } 649 729 ··· 782 698 goto out; 783 699 784 700 ret = spu_map_device(spu, spe); 701 + /* try old method */ 702 + if (ret) 703 + ret = spu_map_device_old(spu, spe); 785 704 if (ret) 786 705 goto out_free; 787 706 ··· 793 706 if (spu->nid == -1) 794 707 spu->nid = 0; 795 708 ret = spu_map_interrupts(spu, spe); 709 + if (ret) 710 + ret = spu_map_interrupts_old(spu, spe); 796 711 if (ret) 797 712 goto out_unmap; 798 713 spin_lock_init(&spu->register_lock); ··· 805 716 spu->number = number++; 806 717 ret = spu_request_irqs(spu); 807 718 if (ret) 808 - goto out_unmap; 719 + goto out_unlock; 809 720 810 721 ret = spu_create_sysdev(spu); 811 722 if (ret) ··· 821 732 822 733 out_free_irqs: 823 734 spu_free_irqs(spu); 824 - 825 - out_unmap: 735 + out_unlock: 826 736 mutex_unlock(&spu_mutex); 737 + out_unmap: 827 738 spu_unmap(spu); 828 739 out_free: 829 740 kfree(spu);