Skip to content

Commit aaa5e4f

Browse files
committed
deepin: LoongArch: legacyboot: BPI: workaround old firmware with ISA
deepin inclusion category: other Restore BPI logic to workaround with some buggy DSDT table with ISA IO. Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
1 parent c645628 commit aaa5e4f

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

arch/loongarch/kernel/legacy_boot.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <linux/efi.h>
22
#include <linux/memblock.h>
33
#include <linux/acpi.h>
4+
#include <linux/of_address.h>
45
#include <linux/kmemleak.h>
56
#include <linux/kernel.h>
67

@@ -718,3 +719,69 @@ void __init acpi_arch_init (void){
718719
int loongarch_have_legacy_bpi (void){
719720
return have_bpi;
720721
}
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

Comments
 (0)