diff options
Diffstat (limited to 'arch/powerpc/kernel/setup_64.c')
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 190 |
1 files changed, 9 insertions, 181 deletions
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index e3fb78397dc6..0fc442ad1d26 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -459,6 +459,15 @@ void __init setup_system(void) | |||
459 | */ | 459 | */ |
460 | ppc_md.init_early(); | 460 | ppc_md.init_early(); |
461 | 461 | ||
462 | /* | ||
463 | * We can discover serial ports now since the above did setup the | ||
464 | * hash table management for us, thus ioremap works. We do that early | ||
465 | * so that further code can be debugged | ||
466 | */ | ||
467 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
468 | find_legacy_serial_ports(); | ||
469 | #endif | ||
470 | |||
462 | /* | 471 | /* |
463 | * "Finish" the device-tree, that is do the actual parsing of | 472 | * "Finish" the device-tree, that is do the actual parsing of |
464 | * some of the properties like the interrupt map | 473 | * some of the properties like the interrupt map |
@@ -657,187 +666,6 @@ void ppc64_terminate_msg(unsigned int src, const char *msg) | |||
657 | printk("[terminate]%04x %s\n", src, msg); | 666 | printk("[terminate]%04x %s\n", src, msg); |
658 | } | 667 | } |
659 | 668 | ||
660 | #ifndef CONFIG_PPC_ISERIES | ||
661 | /* | ||
662 | * This function can be used by platforms to "find" legacy serial ports. | ||
663 | * It works for "serial" nodes under an "isa" node, and will try to | ||
664 | * respect the "ibm,aix-loc" property if any. It works with up to 8 | ||
665 | * ports. | ||
666 | */ | ||
667 | |||
668 | #define MAX_LEGACY_SERIAL_PORTS 8 | ||
669 | static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1]; | ||
670 | static unsigned int old_serial_count; | ||
671 | |||
672 | void __init generic_find_legacy_serial_ports(u64 *physport, | ||
673 | unsigned int *default_speed) | ||
674 | { | ||
675 | struct device_node *np; | ||
676 | u32 *sizeprop; | ||
677 | |||
678 | struct isa_reg_property { | ||
679 | u32 space; | ||
680 | u32 address; | ||
681 | u32 size; | ||
682 | }; | ||
683 | struct pci_reg_property { | ||
684 | struct pci_address addr; | ||
685 | u32 size_hi; | ||
686 | u32 size_lo; | ||
687 | }; | ||
688 | |||
689 | DBG(" -> generic_find_legacy_serial_port()\n"); | ||
690 | |||
691 | *physport = 0; | ||
692 | if (default_speed) | ||
693 | *default_speed = 0; | ||
694 | |||
695 | np = of_find_node_by_path("/"); | ||
696 | if (!np) | ||
697 | return; | ||
698 | |||
699 | /* First fill our array */ | ||
700 | for (np = NULL; (np = of_find_node_by_type(np, "serial"));) { | ||
701 | struct device_node *isa, *pci; | ||
702 | struct isa_reg_property *reg; | ||
703 | unsigned long phys_size, addr_size, io_base; | ||
704 | u32 *rangesp; | ||
705 | u32 *interrupts, *clk, *spd; | ||
706 | char *typep; | ||
707 | int index, rlen, rentsize; | ||
708 | |||
709 | /* Ok, first check if it's under an "isa" parent */ | ||
710 | isa = of_get_parent(np); | ||
711 | if (!isa || strcmp(isa->name, "isa")) { | ||
712 | DBG("%s: no isa parent found\n", np->full_name); | ||
713 | continue; | ||
714 | } | ||
715 | |||
716 | /* Now look for an "ibm,aix-loc" property that gives us ordering | ||
717 | * if any... | ||
718 | */ | ||
719 | typep = (char *)get_property(np, "ibm,aix-loc", NULL); | ||
720 | |||
721 | /* Get the ISA port number */ | ||
722 | reg = (struct isa_reg_property *)get_property(np, "reg", NULL); | ||
723 | if (reg == NULL) | ||
724 | goto next_port; | ||
725 | /* We assume the interrupt number isn't translated ... */ | ||
726 | interrupts = (u32 *)get_property(np, "interrupts", NULL); | ||
727 | /* get clock freq. if present */ | ||
728 | clk = (u32 *)get_property(np, "clock-frequency", NULL); | ||
729 | /* get default speed if present */ | ||
730 | spd = (u32 *)get_property(np, "current-speed", NULL); | ||
731 | /* Default to locate at end of array */ | ||
732 | index = old_serial_count; /* end of the array by default */ | ||
733 | |||
734 | /* If we have a location index, then use it */ | ||
735 | if (typep && *typep == 'S') { | ||
736 | index = simple_strtol(typep+1, NULL, 0) - 1; | ||
737 | /* if index is out of range, use end of array instead */ | ||
738 | if (index >= MAX_LEGACY_SERIAL_PORTS) | ||
739 | index = old_serial_count; | ||
740 | /* if our index is still out of range, that mean that | ||
741 | * array is full, we could scan for a free slot but that | ||
742 | * make little sense to bother, just skip the port | ||
743 | */ | ||
744 | if (index >= MAX_LEGACY_SERIAL_PORTS) | ||
745 | goto next_port; | ||
746 | if (index >= old_serial_count) | ||
747 | old_serial_count = index + 1; | ||
748 | /* Check if there is a port who already claimed our slot */ | ||
749 | if (serial_ports[index].iobase != 0) { | ||
750 | /* if we still have some room, move it, else override */ | ||
751 | if (old_serial_count < MAX_LEGACY_SERIAL_PORTS) { | ||
752 | DBG("Moved legacy port %d -> %d\n", index, | ||
753 | old_serial_count); | ||
754 | serial_ports[old_serial_count++] = | ||
755 | serial_ports[index]; | ||
756 | } else { | ||
757 | DBG("Replacing legacy port %d\n", index); | ||
758 | } | ||
759 | } | ||
760 | } | ||
761 | if (index >= MAX_LEGACY_SERIAL_PORTS) | ||
762 | goto next_port; | ||
763 | if (index >= old_serial_count) | ||
764 | old_serial_count = index + 1; | ||
765 | |||
766 | /* Now fill the entry */ | ||
767 | memset(&serial_ports[index], 0, sizeof(struct plat_serial8250_port)); | ||
768 | serial_ports[index].uartclk = clk ? *clk : BASE_BAUD * 16; | ||
769 | serial_ports[index].iobase = reg->address; | ||
770 | serial_ports[index].irq = interrupts ? interrupts[0] : 0; | ||
771 | serial_ports[index].flags = ASYNC_BOOT_AUTOCONF; | ||
772 | |||
773 | DBG("Added legacy port, index: %d, port: %x, irq: %d, clk: %d\n", | ||
774 | index, | ||
775 | serial_ports[index].iobase, | ||
776 | serial_ports[index].irq, | ||
777 | serial_ports[index].uartclk); | ||
778 | |||
779 | /* Get phys address of IO reg for port 1 */ | ||
780 | if (index != 0) | ||
781 | goto next_port; | ||
782 | |||
783 | pci = of_get_parent(isa); | ||
784 | if (!pci) { | ||
785 | DBG("%s: no pci parent found\n", np->full_name); | ||
786 | goto next_port; | ||
787 | } | ||
788 | |||
789 | rangesp = (u32 *)get_property(pci, "ranges", &rlen); | ||
790 | if (rangesp == NULL) { | ||
791 | of_node_put(pci); | ||
792 | goto next_port; | ||
793 | } | ||
794 | rlen /= 4; | ||
795 | |||
796 | /* we need the #size-cells of the PCI bridge node itself */ | ||
797 | phys_size = 1; | ||
798 | sizeprop = (u32 *)get_property(pci, "#size-cells", NULL); | ||
799 | if (sizeprop != NULL) | ||
800 | phys_size = *sizeprop; | ||
801 | /* we need the parent #addr-cells */ | ||
802 | addr_size = prom_n_addr_cells(pci); | ||
803 | rentsize = 3 + addr_size + phys_size; | ||
804 | io_base = 0; | ||
805 | for (;rlen >= rentsize; rlen -= rentsize,rangesp += rentsize) { | ||
806 | if (((rangesp[0] >> 24) & 0x3) != 1) | ||
807 | continue; /* not IO space */ | ||
808 | io_base = rangesp[3]; | ||
809 | if (addr_size == 2) | ||
810 | io_base = (io_base << 32) | rangesp[4]; | ||
811 | } | ||
812 | if (io_base != 0) { | ||
813 | *physport = io_base + reg->address; | ||
814 | if (default_speed && spd) | ||
815 | *default_speed = *spd; | ||
816 | } | ||
817 | of_node_put(pci); | ||
818 | next_port: | ||
819 | of_node_put(isa); | ||
820 | } | ||
821 | |||
822 | DBG(" <- generic_find_legacy_serial_port()\n"); | ||
823 | } | ||
824 | |||
825 | static struct platform_device serial_device = { | ||
826 | .name = "serial8250", | ||
827 | .id = PLAT8250_DEV_PLATFORM, | ||
828 | .dev = { | ||
829 | .platform_data = serial_ports, | ||
830 | }, | ||
831 | }; | ||
832 | |||
833 | static int __init serial_dev_init(void) | ||
834 | { | ||
835 | return platform_device_register(&serial_device); | ||
836 | } | ||
837 | arch_initcall(serial_dev_init); | ||
838 | |||
839 | #endif /* CONFIG_PPC_ISERIES */ | ||
840 | |||
841 | int check_legacy_ioport(unsigned long base_port) | 669 | int check_legacy_ioport(unsigned long base_port) |
842 | { | 670 | { |
843 | if (ppc_md.check_legacy_ioport == NULL) | 671 | if (ppc_md.check_legacy_ioport == NULL) |