|
1 | 1 | #include <linux/efi.h> |
2 | 2 | #include <linux/memblock.h> |
3 | 3 | #include <linux/acpi.h> |
| 4 | +#include <linux/of_address.h> |
4 | 5 | #include <linux/kmemleak.h> |
5 | 6 | #include <linux/kernel.h> |
6 | 7 |
|
@@ -718,3 +719,69 @@ void __init acpi_arch_init (void){ |
718 | 719 | int loongarch_have_legacy_bpi (void){ |
719 | 720 | return have_bpi; |
720 | 721 | } |
| 722 | + |
| 723 | +static int __init add_legacy_isa_io(struct fwnode_handle *fwnode, unsigned long isa_base) |
| 724 | +{ |
| 725 | + int ret = 0; |
| 726 | + unsigned long vaddr; |
| 727 | + struct logic_pio_hwaddr *range; |
| 728 | + range = kzalloc(sizeof(*range), GFP_ATOMIC); |
| 729 | + if (!range) |
| 730 | + return -ENOMEM; |
| 731 | + range->fwnode = fwnode; |
| 732 | + range->size = ISA_IOSIZE; |
| 733 | + range->hw_start = isa_base; |
| 734 | + range->flags = LOGIC_PIO_CPU_MMIO; |
| 735 | + ret = logic_pio_register_range(range); |
| 736 | + if (ret) { |
| 737 | + kfree(range); |
| 738 | + return ret; |
| 739 | + } |
| 740 | + if (range->io_start != 0) { |
| 741 | + logic_pio_unregister_range(range); |
| 742 | + kfree(range); |
| 743 | + return -EINVAL; |
| 744 | + } |
| 745 | + vaddr = (unsigned long)(PCI_IOBASE + range->io_start); |
| 746 | + ret = ioremap_page_range(vaddr, vaddr + range->size, range->hw_start, |
| 747 | + pgprot_device(PAGE_KERNEL)); |
| 748 | + return ret; |
| 749 | +} |
| 750 | +static struct fwnode_handle * __init parse_isa_base(u64 *cpu_addr) |
| 751 | +{ |
| 752 | + struct device_node *np; |
| 753 | + const __be32 *ranges = NULL; |
| 754 | + int len; |
| 755 | + struct device_node *node; |
| 756 | + for_each_node_by_name(np, "isa") { |
| 757 | + node = of_node_get(np); |
| 758 | + if (!node) |
| 759 | + break; |
| 760 | + ranges = of_get_property(node, "ranges", &len); |
| 761 | + if (!ranges || (ranges && len > 0)) |
| 762 | + break; |
| 763 | + } |
| 764 | + if (ranges) { |
| 765 | + ranges += 2; |
| 766 | + *cpu_addr = of_translate_address(np, ranges); |
| 767 | + return &np->fwnode; |
| 768 | + } |
| 769 | + return NULL; |
| 770 | +} |
| 771 | + |
| 772 | +#define ISA_PHY_IOBASE LOONGSON_LIO_BASE |
| 773 | +static int __init register_legacy_isa_io(void) |
| 774 | +{ |
| 775 | + struct fwnode_handle *fwnode; |
| 776 | + u64 cpu_addr; |
| 777 | + if (!acpi_disabled) { |
| 778 | + cpu_addr = ISA_PHY_IOBASE; |
| 779 | + fwnode = kzalloc(sizeof(*fwnode), GFP_ATOMIC); |
| 780 | + } else { |
| 781 | + fwnode = parse_isa_base(&cpu_addr); |
| 782 | + } |
| 783 | + if (fwnode) |
| 784 | + add_legacy_isa_io(fwnode, cpu_addr); |
| 785 | + return 0; |
| 786 | +} |
| 787 | +arch_initcall(register_legacy_isa_io); |
0 commit comments