diff options
Diffstat (limited to 'arch/mips/loongson64')
-rw-r--r-- | arch/mips/loongson64/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/loongson64/boardinfo.c | 48 | ||||
-rw-r--r-- | arch/mips/loongson64/env.c | 10 | ||||
-rw-r--r-- | arch/mips/loongson64/numa.c | 27 | ||||
-rw-r--r-- | arch/mips/loongson64/smp.c | 126 |
5 files changed, 165 insertions, 47 deletions
diff --git a/arch/mips/loongson64/Makefile b/arch/mips/loongson64/Makefile index 39c06f52b08f..cc76944b1a9d 100644 --- a/arch/mips/loongson64/Makefile +++ b/arch/mips/loongson64/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_RS780_HPET) += hpet.o obj-$(CONFIG_SUSPEND) += pm.o obj-$(CONFIG_PCI_QUIRKS) += vbios_quirk.o obj-$(CONFIG_CPU_LOONGSON3_CPUCFG_EMULATION) += cpucfg-emul.o +obj-$(CONFIG_SYSFS) += boardinfo.o diff --git a/arch/mips/loongson64/boardinfo.c b/arch/mips/loongson64/boardinfo.c new file mode 100644 index 000000000000..280989c5a137 --- /dev/null +++ b/arch/mips/loongson64/boardinfo.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/kobject.h> +#include <boot_param.h> + +static ssize_t boardinfo_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + char board_manufacturer[64] = {0}; + char *tmp_board_manufacturer = board_manufacturer; + char bios_vendor[64] = {0}; + char *tmp_bios_vendor = bios_vendor; + + strcpy(board_manufacturer, eboard->name); + strcpy(bios_vendor, einter->description); + + return sprintf(buf, + "Board Info\n" + "Manufacturer\t\t: %s\n" + "Board Name\t\t: %s\n" + "Family\t\t\t: LOONGSON3\n\n" + "BIOS Info\n" + "Vendor\t\t\t: %s\n" + "Version\t\t\t: %s\n" + "ROM Size\t\t: %d KB\n" + "Release Date\t\t: %s\n", + strsep(&tmp_board_manufacturer, "-"), + eboard->name, + strsep(&tmp_bios_vendor, "-"), + einter->description, + einter->size, + especial->special_name); +} +static struct kobj_attribute boardinfo_attr = __ATTR(boardinfo, 0444, + boardinfo_show, NULL); + +static int __init boardinfo_init(void) +{ + struct kobject *lefi_kobj; + + lefi_kobj = kobject_create_and_add("lefi", firmware_kobj); + if (!lefi_kobj) { + pr_err("lefi: Firmware registration failed.\n"); + return -ENOMEM; + } + + return sysfs_create_file(lefi_kobj, &boardinfo_attr.attr); +} +late_initcall(boardinfo_init); diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c index 134cb8e9efc2..51a5d050a94c 100644 --- a/arch/mips/loongson64/env.c +++ b/arch/mips/loongson64/env.c @@ -28,6 +28,10 @@ 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]; @@ -57,6 +61,12 @@ void __init prom_init_env(void) ((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 *) diff --git a/arch/mips/loongson64/numa.c b/arch/mips/loongson64/numa.c index cf9459f79f9b..c6f0c48384f8 100644 --- a/arch/mips/loongson64/numa.c +++ b/arch/mips/loongson64/numa.c @@ -35,23 +35,6 @@ EXPORT_SYMBOL(__node_data); cpumask_t __node_cpumask[MAX_NUMNODES]; EXPORT_SYMBOL(__node_cpumask); -static void enable_lpa(void) -{ - unsigned long value; - - value = __read_32bit_c0_register($16, 3); - value |= 0x00000080; - __write_32bit_c0_register($16, 3, value); - value = __read_32bit_c0_register($16, 3); - pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value); - - value = __read_32bit_c0_register($5, 1); - value |= 0x20000000; - __write_32bit_c0_register($5, 1, value); - value = __read_32bit_c0_register($5, 1); - pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value); -} - static void cpu_node_probe(void) { int i; @@ -168,6 +151,9 @@ static void __init node_mem_init(unsigned int node) NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; if (node == 0) { + /* kernel start address */ + unsigned long kernel_start_pfn = PFN_DOWN(__pa_symbol(&_text)); + /* kernel end address */ unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end)); @@ -175,8 +161,8 @@ static void __init node_mem_init(unsigned int node) max_low_pfn = end_pfn; /* Reserve the kernel text/data/bss */ - memblock_reserve(start_pfn << PAGE_SHIFT, - ((kernel_end_pfn - start_pfn) << PAGE_SHIFT)); + memblock_reserve(kernel_start_pfn << PAGE_SHIFT, + ((kernel_end_pfn - kernel_start_pfn) << PAGE_SHIFT)); /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */ if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) @@ -243,7 +229,8 @@ EXPORT_SYMBOL(pcibus_to_node); void __init prom_init_numa_memory(void) { - enable_lpa(); + pr_info("CP0_Config3: CP0 16.3 (0x%x)\n", read_c0_config3()); + pr_info("CP0_PageGrain: CP0 5.1 (0x%x)\n", read_c0_pagegrain()); prom_meminit(); } EXPORT_SYMBOL(prom_init_numa_memory); diff --git a/arch/mips/loongson64/smp.c b/arch/mips/loongson64/smp.c index e744e1bee49e..b8c1fc3158fd 100644 --- a/arch/mips/loongson64/smp.c +++ b/arch/mips/loongson64/smp.c @@ -53,6 +53,29 @@ static uint32_t core0_c0count[NR_CPUS]; u32 (*ipi_read_clear)(int cpu); void (*ipi_write_action)(int cpu, u32 action); +void (*ipi_write_enable)(int cpu); +void (*ipi_clear_buf)(int cpu); +void (*ipi_write_buf)(int cpu, struct task_struct *idle); + +/* send mail via Mail_Send register for 3A4000+ CPU */ +static void csr_mail_send(uint64_t data, int cpu, int mailbox) +{ + uint64_t val; + + /* send high 32 bits */ + val = CSR_MAIL_SEND_BLOCK; + val |= (CSR_MAIL_SEND_BOX_HIGH(mailbox) << CSR_MAIL_SEND_BOX_SHIFT); + val |= (cpu << CSR_MAIL_SEND_CPU_SHIFT); + val |= (data & CSR_MAIL_SEND_H32_MASK); + csr_writeq(val, LOONGSON_CSR_MAIL_SEND); + + /* send low 32 bits */ + val = CSR_MAIL_SEND_BLOCK; + val |= (CSR_MAIL_SEND_BOX_LOW(mailbox) << CSR_MAIL_SEND_BOX_SHIFT); + val |= (cpu << CSR_MAIL_SEND_CPU_SHIFT); + val |= (data << CSR_MAIL_SEND_BUF_SHIFT); + csr_writeq(val, LOONGSON_CSR_MAIL_SEND); +}; static u32 csr_ipi_read_clear(int cpu) { @@ -79,6 +102,35 @@ static void csr_ipi_write_action(int cpu, u32 action) } } +static void csr_ipi_write_enable(int cpu) +{ + csr_writel(0xffffffff, LOONGSON_CSR_IPI_EN); +} + +static void csr_ipi_clear_buf(int cpu) +{ + csr_writeq(0, LOONGSON_CSR_MAIL_BUF0); +} + +static void csr_ipi_write_buf(int cpu, struct task_struct *idle) +{ + unsigned long startargs[4]; + + /* startargs[] are initial PC, SP and GP for secondary CPU */ + startargs[0] = (unsigned long)&smp_bootstrap; + startargs[1] = (unsigned long)__KSTK_TOS(idle); + startargs[2] = (unsigned long)task_thread_info(idle); + startargs[3] = 0; + + pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n", + cpu, startargs[0], startargs[1], startargs[2]); + + csr_mail_send(startargs[3], cpu_logical_map(cpu), 3); + csr_mail_send(startargs[2], cpu_logical_map(cpu), 2); + csr_mail_send(startargs[1], cpu_logical_map(cpu), 1); + csr_mail_send(startargs[0], cpu_logical_map(cpu), 0); +} + static u32 legacy_ipi_read_clear(int cpu) { u32 action; @@ -96,14 +148,53 @@ static void legacy_ipi_write_action(int cpu, u32 action) loongson3_ipi_write32((u32)action, ipi_set0_regs[cpu]); } +static void legacy_ipi_write_enable(int cpu) +{ + loongson3_ipi_write32(0xffffffff, ipi_en0_regs[cpu_logical_map(cpu)]); +} + +static void legacy_ipi_clear_buf(int cpu) +{ + loongson3_ipi_write64(0, ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0); +} + +static void legacy_ipi_write_buf(int cpu, struct task_struct *idle) +{ + unsigned long startargs[4]; + + /* startargs[] are initial PC, SP and GP for secondary CPU */ + startargs[0] = (unsigned long)&smp_bootstrap; + startargs[1] = (unsigned long)__KSTK_TOS(idle); + startargs[2] = (unsigned long)task_thread_info(idle); + startargs[3] = 0; + + pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n", + cpu, startargs[0], startargs[1], startargs[2]); + + loongson3_ipi_write64(startargs[3], + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x18); + loongson3_ipi_write64(startargs[2], + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x10); + loongson3_ipi_write64(startargs[1], + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x8); + loongson3_ipi_write64(startargs[0], + ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0); +} + static void csr_ipi_probe(void) { if (cpu_has_csr() && csr_readl(LOONGSON_CSR_FEATURES) & LOONGSON_CSRF_IPI) { ipi_read_clear = csr_ipi_read_clear; ipi_write_action = csr_ipi_write_action; + ipi_write_enable = csr_ipi_write_enable; + ipi_clear_buf = csr_ipi_clear_buf; + ipi_write_buf = csr_ipi_write_buf; } else { ipi_read_clear = legacy_ipi_read_clear; ipi_write_action = legacy_ipi_write_action; + ipi_write_enable = legacy_ipi_write_enable; + ipi_clear_buf = legacy_ipi_clear_buf; + ipi_write_buf = legacy_ipi_write_buf; } } @@ -347,9 +438,7 @@ static void loongson3_init_secondary(void) /* Set interrupt mask, but don't enable */ change_c0_status(ST0_IM, imask); - - for (i = 0; i < num_possible_cpus(); i++) - loongson3_ipi_write32(0xffffffff, ipi_en0_regs[cpu_logical_map(i)]); + ipi_write_enable(cpu); per_cpu(cpu_state, cpu) = CPU_ONLINE; cpu_set_core(&cpu_data[cpu], @@ -381,8 +470,8 @@ static void loongson3_smp_finish(void) write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ); local_irq_enable(); - loongson3_ipi_write64(0, - ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0); + ipi_clear_buf(cpu); + pr_info("CPU#%d finished, CP0_ST=%x\n", smp_processor_id(), read_c0_status()); } @@ -420,6 +509,8 @@ static void __init loongson3_smp_setup(void) ipi_status0_regs_init(); ipi_en0_regs_init(); ipi_mailbox_buf_init(); + ipi_write_enable(0); + cpu_set_core(&cpu_data[0], cpu_logical_map(0) % loongson_sysconf.cores_per_package); cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package; @@ -439,27 +530,10 @@ static void __init loongson3_prepare_cpus(unsigned int max_cpus) */ static int loongson3_boot_secondary(int cpu, struct task_struct *idle) { - unsigned long startargs[4]; - pr_info("Booting CPU#%d...\n", cpu); - /* startargs[] are initial PC, SP and GP for secondary CPU */ - startargs[0] = (unsigned long)&smp_bootstrap; - startargs[1] = (unsigned long)__KSTK_TOS(idle); - startargs[2] = (unsigned long)task_thread_info(idle); - startargs[3] = 0; + ipi_write_buf(cpu, idle); - pr_debug("CPU#%d, func_pc=%lx, sp=%lx, gp=%lx\n", - cpu, startargs[0], startargs[1], startargs[2]); - - loongson3_ipi_write64(startargs[3], - ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x18); - loongson3_ipi_write64(startargs[2], - ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x10); - loongson3_ipi_write64(startargs[1], - ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x8); - loongson3_ipi_write64(startargs[0], - ipi_mailbox_buf[cpu_logical_map(cpu)] + 0x0); return 0; } @@ -470,9 +544,6 @@ static int loongson3_cpu_disable(void) unsigned long flags; unsigned int cpu = smp_processor_id(); - if (cpu == 0) - return -EBUSY; - set_cpu_online(cpu, false); calculate_cpu_foreign_map(); local_irq_save(flags); @@ -690,9 +761,10 @@ static void loongson3_type3_play_dead(int *state_addr) "1: li %[count], 0x100 \n" /* wait for init loop */ "2: bnez %[count], 2b \n" /* limit mailbox access */ " addiu %[count], -1 \n" - " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */ + " lw %[initfunc], 0x20(%[base]) \n" /* check lower 32-bit as jump indicator */ " beqz %[initfunc], 1b \n" " nop \n" + " ld %[initfunc], 0x20(%[base]) \n" /* get PC (whole 64-bit) via mailbox */ " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */ " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */ " ld $a1, 0x38(%[base]) \n" |