123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: [email protected] or [email protected]
- *
- * Copyright 2003 ICT CAS
- * Author: Michael Guo <[email protected]>
- *
- * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology
- * Author: Fuxin Zhang, [email protected]
- *
- * Copyright (C) 2009 Lemote Inc.
- * Author: Wu Zhangjin, [email protected]
- */
- #include <linux/dma-map-ops.h>
- #include <linux/export.h>
- #include <linux/pci_ids.h>
- #include <asm/bootinfo.h>
- #include <loongson.h>
- #include <boot_param.h>
- #include <builtin_dtbs.h>
- #include <workarounds.h>
- #define HOST_BRIDGE_CONFIG_ADDR ((void __iomem *)TO_UNCAC(0x1a000000))
- u32 cpu_clock_freq;
- EXPORT_SYMBOL(cpu_clock_freq);
- struct efi_memory_map_loongson *loongson_memmap;
- struct loongson_system_configuration loongson_sysconf;
- struct board_devices *eboard;
- struct interface_info *einter;
- struct loongson_special_attribute *especial;
- u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
- u64 loongson_chiptemp[MAX_PACKAGES];
- u64 loongson_freqctrl[MAX_PACKAGES];
- unsigned long long smp_group[4];
- const char *get_system_type(void)
- {
- return "Generic Loongson64 System";
- }
- void __init prom_dtb_init_env(void)
- {
- if ((fw_arg2 < CKSEG0 || fw_arg2 > CKSEG1)
- && (fw_arg2 < XKPHYS || fw_arg2 > XKSEG))
- loongson_fdt_blob = __dtb_loongson64_2core_2k1000_begin;
- else
- loongson_fdt_blob = (void *)fw_arg2;
- }
- void __init prom_lefi_init_env(void)
- {
- struct boot_params *boot_p;
- struct loongson_params *loongson_p;
- struct system_loongson *esys;
- struct efi_cpuinfo_loongson *ecpu;
- struct irq_source_routing_table *eirq_source;
- u32 id;
- u16 vendor;
- /* firmware arguments are initialized in head.S */
- boot_p = (struct boot_params *)fw_arg2;
- loongson_p = &(boot_p->efi.smbios.lp);
- esys = (struct system_loongson *)
- ((u64)loongson_p + loongson_p->system_offset);
- ecpu = (struct efi_cpuinfo_loongson *)
- ((u64)loongson_p + loongson_p->cpu_offset);
- eboard = (struct board_devices *)
- ((u64)loongson_p + loongson_p->boarddev_table_offset);
- einter = (struct interface_info *)
- ((u64)loongson_p + loongson_p->interface_offset);
- especial = (struct loongson_special_attribute *)
- ((u64)loongson_p + loongson_p->special_offset);
- eirq_source = (struct irq_source_routing_table *)
- ((u64)loongson_p + loongson_p->irq_offset);
- loongson_memmap = (struct efi_memory_map_loongson *)
- ((u64)loongson_p + loongson_p->memory_offset);
- cpu_clock_freq = ecpu->cpu_clock_freq;
- loongson_sysconf.cputype = ecpu->cputype;
- switch (ecpu->cputype) {
- case Legacy_3A:
- case Loongson_3A:
- loongson_sysconf.cores_per_node = 4;
- loongson_sysconf.cores_per_package = 4;
- smp_group[0] = 0x900000003ff01000;
- smp_group[1] = 0x900010003ff01000;
- smp_group[2] = 0x900020003ff01000;
- smp_group[3] = 0x900030003ff01000;
- loongson_chipcfg[0] = 0x900000001fe00180;
- loongson_chipcfg[1] = 0x900010001fe00180;
- loongson_chipcfg[2] = 0x900020001fe00180;
- loongson_chipcfg[3] = 0x900030001fe00180;
- loongson_chiptemp[0] = 0x900000001fe0019c;
- loongson_chiptemp[1] = 0x900010001fe0019c;
- loongson_chiptemp[2] = 0x900020001fe0019c;
- loongson_chiptemp[3] = 0x900030001fe0019c;
- loongson_freqctrl[0] = 0x900000001fe001d0;
- loongson_freqctrl[1] = 0x900010001fe001d0;
- loongson_freqctrl[2] = 0x900020001fe001d0;
- loongson_freqctrl[3] = 0x900030001fe001d0;
- loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
- break;
- case Legacy_3B:
- case Loongson_3B:
- loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
- loongson_sysconf.cores_per_package = 8;
- smp_group[0] = 0x900000003ff01000;
- smp_group[1] = 0x900010003ff05000;
- smp_group[2] = 0x900020003ff09000;
- smp_group[3] = 0x900030003ff0d000;
- loongson_chipcfg[0] = 0x900000001fe00180;
- loongson_chipcfg[1] = 0x900020001fe00180;
- loongson_chipcfg[2] = 0x900040001fe00180;
- loongson_chipcfg[3] = 0x900060001fe00180;
- loongson_chiptemp[0] = 0x900000001fe0019c;
- loongson_chiptemp[1] = 0x900020001fe0019c;
- loongson_chiptemp[2] = 0x900040001fe0019c;
- loongson_chiptemp[3] = 0x900060001fe0019c;
- loongson_freqctrl[0] = 0x900000001fe001d0;
- loongson_freqctrl[1] = 0x900020001fe001d0;
- loongson_freqctrl[2] = 0x900040001fe001d0;
- loongson_freqctrl[3] = 0x900060001fe001d0;
- loongson_sysconf.workarounds = WORKAROUND_CPUHOTPLUG;
- break;
- default:
- loongson_sysconf.cores_per_node = 1;
- loongson_sysconf.cores_per_package = 1;
- loongson_chipcfg[0] = 0x900000001fe00180;
- }
- loongson_sysconf.nr_cpus = ecpu->nr_cpus;
- loongson_sysconf.boot_cpu_id = ecpu->cpu_startup_core_id;
- loongson_sysconf.reserved_cpus_mask = ecpu->reserved_cores_mask;
- if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
- loongson_sysconf.nr_cpus = NR_CPUS;
- loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
- loongson_sysconf.cores_per_node - 1) /
- loongson_sysconf.cores_per_node;
- loongson_sysconf.dma_mask_bits = eirq_source->dma_mask_bits;
- if (loongson_sysconf.dma_mask_bits < 32 ||
- loongson_sysconf.dma_mask_bits > 64) {
- loongson_sysconf.dma_mask_bits = 32;
- dma_default_coherent = true;
- } else {
- dma_default_coherent = !eirq_source->dma_noncoherent;
- }
- pr_info("Firmware: Coherent DMA: %s\n", dma_default_coherent ? "on" : "off");
- loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
- loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
- loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend;
- loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios;
- pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
- loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
- loongson_sysconf.vgabios_addr);
- loongson_sysconf.workarounds |= esys->workarounds;
- pr_info("CpuClock = %u\n", cpu_clock_freq);
- /* Read the ID of PCI host bridge to detect bridge type */
- id = readl(HOST_BRIDGE_CONFIG_ADDR);
- vendor = id & 0xffff;
- switch (vendor) {
- case PCI_VENDOR_ID_LOONGSON:
- pr_info("The bridge chip is LS7A\n");
- loongson_sysconf.bridgetype = LS7A;
- loongson_sysconf.early_config = ls7a_early_config;
- break;
- case PCI_VENDOR_ID_AMD:
- case PCI_VENDOR_ID_ATI:
- pr_info("The bridge chip is RS780E or SR5690\n");
- loongson_sysconf.bridgetype = RS780E;
- loongson_sysconf.early_config = rs780e_early_config;
- break;
- default:
- pr_info("The bridge chip is VIRTUAL\n");
- loongson_sysconf.bridgetype = VIRTUAL;
- loongson_sysconf.early_config = virtual_early_config;
- loongson_fdt_blob = __dtb_loongson64v_4core_virtio_begin;
- break;
- }
- if ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64C) {
- switch (read_c0_prid() & PRID_REV_MASK) {
- case PRID_REV_LOONGSON3A_R1:
- case PRID_REV_LOONGSON3A_R2_0:
- case PRID_REV_LOONGSON3A_R2_1:
- case PRID_REV_LOONGSON3A_R3_0:
- case PRID_REV_LOONGSON3A_R3_1:
- switch (loongson_sysconf.bridgetype) {
- case LS7A:
- loongson_fdt_blob = __dtb_loongson64c_4core_ls7a_begin;
- break;
- case RS780E:
- loongson_fdt_blob = __dtb_loongson64c_4core_rs780e_begin;
- break;
- default:
- break;
- }
- break;
- case PRID_REV_LOONGSON3B_R1:
- case PRID_REV_LOONGSON3B_R2:
- if (loongson_sysconf.bridgetype == RS780E)
- loongson_fdt_blob = __dtb_loongson64c_8core_rs780e_begin;
- break;
- default:
- break;
- }
- } else if ((read_c0_prid() & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64G) {
- if (loongson_sysconf.bridgetype == LS7A)
- loongson_fdt_blob = __dtb_loongson64g_4core_ls7a_begin;
- }
- if (!loongson_fdt_blob)
- pr_err("Failed to determine built-in Loongson64 dtb\n");
- }
|