diff options
Diffstat (limited to 'arch/mips/cavium-octeon/setup.c')
| -rw-r--r-- | arch/mips/cavium-octeon/setup.c | 479 |
1 files changed, 298 insertions, 181 deletions
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 48b08eb9d9e4..1ad2602a0383 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c @@ -8,6 +8,7 @@ * written by Ralf Baechle <ralf@linux-mips.org> */ #include <linux/compiler.h> +#include <linux/vmalloc.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/console.h> @@ -15,6 +16,7 @@ #include <linux/export.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/memblock.h> #include <linux/serial.h> #include <linux/smp.h> #include <linux/types.h> @@ -35,26 +37,49 @@ #include <asm/mipsregs.h> #include <asm/bootinfo.h> #include <asm/sections.h> +#include <asm/fw/fw.h> +#include <asm/setup.h> +#include <asm/prom.h> #include <asm/time.h> #include <asm/octeon/octeon.h> #include <asm/octeon/pci-octeon.h> -#include <asm/octeon/cvmx-mio-defs.h> +#include <asm/octeon/cvmx-rst-defs.h> -extern struct plat_smp_ops octeon_smp_ops; +/* + * TRUE for devices having registers with little-endian byte + * order, FALSE for registers with native-endian byte order. + * PCI mandates little-endian, USB and SATA are configuraable, + * but we chose little-endian for these. + */ +const bool octeon_should_swizzle_table[256] = { + [0x00] = true, /* bootbus/CF */ + [0x1b] = true, /* PCI mmio window */ + [0x1c] = true, /* PCI mmio window */ + [0x1d] = true, /* PCI mmio window */ + [0x1e] = true, /* PCI mmio window */ + [0x68] = true, /* OCTEON III USB */ + [0x69] = true, /* OCTEON III USB */ + [0x6c] = true, /* OCTEON III SATA */ + [0x6f] = true, /* OCTEON II USB */ +}; +EXPORT_SYMBOL(octeon_should_swizzle_table); #ifdef CONFIG_PCI extern void pci_console_init(const char *arg); #endif -static unsigned long long MAX_MEMORY = 512ull << 20; +static unsigned long long max_memory = ULLONG_MAX; +static unsigned long long reserve_low_mem; + +DEFINE_SEMAPHORE(octeon_bootbus_sem, 1); +EXPORT_SYMBOL(octeon_bootbus_sem); -struct octeon_boot_descriptor *octeon_boot_desc_ptr; +static struct octeon_boot_descriptor *octeon_boot_desc_ptr; struct cvmx_bootinfo *octeon_bootinfo; EXPORT_SYMBOL(octeon_bootinfo); -static unsigned long long RESERVE_LOW_MEM = 0ull; #ifdef CONFIG_KEXEC #ifdef CONFIG_SMP /* @@ -74,7 +99,7 @@ static void octeon_kexec_smp_down(void *ignored) " sync \n" " synci ($0) \n"); - relocated_kexec_smp_wait(NULL); + kexec_reboot(); } #endif @@ -104,18 +129,18 @@ static void kexec_bootmem_init(uint64_t mem_size, uint32_t low_reserved_bytes) bootmem_desc->major_version = CVMX_BOOTMEM_DESC_MAJ_VER; bootmem_desc->minor_version = CVMX_BOOTMEM_DESC_MIN_VER; - addr = (OCTEON_DDR0_BASE + RESERVE_LOW_MEM + low_reserved_bytes); + addr = (OCTEON_DDR0_BASE + reserve_low_mem + low_reserved_bytes); bootmem_desc->head_addr = 0; if (mem_size <= OCTEON_DDR0_SIZE) { __cvmx_bootmem_phy_free(addr, - mem_size - RESERVE_LOW_MEM - + mem_size - reserve_low_mem - low_reserved_bytes, 0); return; } __cvmx_bootmem_phy_free(addr, - OCTEON_DDR0_SIZE - RESERVE_LOW_MEM - + OCTEON_DDR0_SIZE - reserve_low_mem - low_reserved_bytes, 0); mem_size -= OCTEON_DDR0_SIZE; @@ -246,12 +271,21 @@ static void octeon_crash_shutdown(struct pt_regs *regs) default_machine_crash_shutdown(regs); } +#ifdef CONFIG_SMP +void octeon_crash_smp_send_stop(void) +{ + int cpu; + + /* disable watchdogs */ + for_each_online_cpu(cpu) + cvmx_write_csr(CVMX_CIU_WDOGX(cpu_logical_map(cpu)), 0); +} +#endif + #endif /* CONFIG_KEXEC */ -#ifdef CONFIG_CAVIUM_RESERVE32 uint64_t octeon_reserve32_memory; EXPORT_SYMBOL(octeon_reserve32_memory); -#endif #ifdef CONFIG_KEXEC /* crashkernel cmdline parameter is parsed _after_ memory setup @@ -262,12 +296,12 @@ static uint64_t crashk_size, crashk_base; static int octeon_uart; extern asmlinkage void handle_int(void); -extern asmlinkage void plat_irq_dispatch(void); /** - * Return non zero if we are currently running in the Octeon simulator + * octeon_is_simulation - Return non-zero if we are currently running + * in the Octeon simulator * - * Returns + * Return: non-0 if running in the Octeon simulator, 0 otherwise */ int octeon_is_simulation(void) { @@ -276,10 +310,10 @@ int octeon_is_simulation(void) EXPORT_SYMBOL(octeon_is_simulation); /** - * Return true if Octeon is in PCI Host mode. This means + * octeon_is_pci_host - Return true if Octeon is in PCI Host mode. This means * Linux can control the PCI bus. * - * Returns Non zero if Octeon in host mode. + * Return: Non-zero if Octeon is in host mode. */ int octeon_is_pci_host(void) { @@ -291,9 +325,9 @@ int octeon_is_pci_host(void) } /** - * Get the clock rate of Octeon + * octeon_get_clock_rate - Get the clock rate of Octeon * - * Returns Clock rate in HZ + * Return: Clock rate in HZ */ uint64_t octeon_get_clock_rate(void) { @@ -313,17 +347,17 @@ EXPORT_SYMBOL(octeon_get_io_clock_rate); /** - * Write to the LCD display connected to the bootbus. This display - * exists on most Cavium evaluation boards. If it doesn't exist, then - * this function doesn't do anything. - * + * octeon_write_lcd - Write to the LCD display connected to the bootbus. * @s: String to write + * + * This display exists on most Cavium evaluation boards. If it doesn't exist, + * then this function doesn't do anything. */ -void octeon_write_lcd(const char *s) +static void octeon_write_lcd(const char *s) { if (octeon_bootinfo->led_display_base_addr) { void __iomem *lcd_address = - ioremap_nocache(octeon_bootinfo->led_display_base_addr, + ioremap(octeon_bootinfo->led_display_base_addr, 8); int i; for (i = 0; i < 8; i++, s++) { @@ -337,26 +371,20 @@ void octeon_write_lcd(const char *s) } /** - * Return the console uart passed by the bootloader + * octeon_get_boot_uart - Return the console uart passed by the bootloader * - * Returns uart (0 or 1) + * Return: uart number (0 or 1) */ -int octeon_get_boot_uart(void) +static int octeon_get_boot_uart(void) { - int uart; -#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL - uart = 1; -#else - uart = (octeon_boot_desc_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) ? + return (octeon_boot_desc_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) ? 1 : 0; -#endif - return uart; } /** - * Get the coremask Linux was booted on. + * octeon_get_boot_coremask - Get the coremask Linux was booted on. * - * Returns Core mask + * Return: Core mask */ int octeon_get_boot_coremask(void) { @@ -364,7 +392,7 @@ int octeon_get_boot_coremask(void) } /** - * Check the hardware BIST results for a CPU + * octeon_check_cpu_bist - Check the hardware BIST results for a CPU */ void octeon_check_cpu_bist(void) { @@ -395,7 +423,7 @@ void octeon_check_cpu_bist(void) } /** - * Reboot Octeon + * octeon_restart - Reboot Octeon * * @command: Command to pass to the bootloader. Currently ignored. */ @@ -412,12 +440,15 @@ static void octeon_restart(char *command) mb(); while (1) - cvmx_write_csr(CVMX_CIU_SOFT_RST, 1); + if (OCTEON_IS_OCTEON3()) + cvmx_write_csr(CVMX_RST_SOFT_RST, 1); + else + cvmx_write_csr(CVMX_CIU_SOFT_RST, 1); } /** - * Permanently stop a core. + * octeon_kill_core - Permanently stop a core. * * @arg: Ignored. */ @@ -437,7 +468,7 @@ static void octeon_kill_core(void *arg) /** - * Halt the system + * octeon_halt - Halt the system */ static void octeon_halt(void) { @@ -457,18 +488,36 @@ static void octeon_halt(void) octeon_kill_core(NULL); } +static char __read_mostly octeon_system_type[80]; + +static void __init init_octeon_system_type(void) +{ + char const *board_type; + + board_type = cvmx_board_type_to_string(octeon_bootinfo->board_type); + if (board_type == NULL) { + struct device_node *root; + int ret; + + root = of_find_node_by_path("/"); + ret = of_property_read_string(root, "model", &board_type); + of_node_put(root); + if (ret) + board_type = "Unsupported Board"; + } + + snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", + board_type, octeon_model_get_string(read_c0_prid())); +} + /** - * Return a string representing the system type + * octeon_board_type_string - Return a string representing the system type * - * Returns + * Return: system type string */ const char *octeon_board_type_string(void) { - static char name[80]; - sprintf(name, "%s (%s)", - cvmx_board_type_to_string(octeon_bootinfo->board_type), - octeon_model_get_string(read_c0_prid())); - return name; + return octeon_system_type; } const char *get_system_type(void) @@ -477,13 +526,11 @@ const char *get_system_type(void) void octeon_user_io_init(void) { union octeon_cvmemctl cvmmemctl; - union cvmx_iob_fau_timeout fau_timeout; - union cvmx_pow_nw_tim nm_tim; /* Get the current settings for CP0_CVMMEMCTL_REG */ cvmmemctl.u64 = read_c0_cvmmemctl(); /* R/W If set, marked write-buffer entries time out the same - * as as other entries; if clear, marked write-buffer entries + * as other entries; if clear, marked write-buffer entries * use the maximum timeout. */ cvmmemctl.s.dismarkwblongto = 1; /* R/W If set, a merged store does not clear the write-buffer @@ -571,35 +618,43 @@ void octeon_user_io_init(void) /* R/W If set, CVMSEG is available for loads/stores in user * mode. */ cvmmemctl.s.cvmsegenau = 0; - /* R/W Size of local memory in cache blocks, 54 (6912 bytes) - * is max legal value. */ - cvmmemctl.s.lmemsz = CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE; write_c0_cvmmemctl(cvmmemctl.u64); + /* Setup of CVMSEG is done in kernel-entry-init.h */ if (smp_processor_id() == 0) pr_notice("CVMSEG size: %d cache lines (%d bytes)\n", CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE, CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128); - /* Set a default for the hardware timeouts */ - fau_timeout.u64 = 0; - fau_timeout.s.tout_val = 0xfff; - /* Disable tagwait FAU timeout */ - fau_timeout.s.tout_enb = 0; - cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64); + if (octeon_has_feature(OCTEON_FEATURE_FAU)) { + union cvmx_iob_fau_timeout fau_timeout; - nm_tim.u64 = 0; - /* 4096 cycles */ - nm_tim.s.nw_tim = 3; - cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64); + /* Set a default for the hardware timeouts */ + fau_timeout.u64 = 0; + fau_timeout.s.tout_val = 0xfff; + /* Disable tagwait FAU timeout */ + fau_timeout.s.tout_enb = 0; + cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_timeout.u64); + } + + if ((!OCTEON_IS_MODEL(OCTEON_CN68XX) && + !OCTEON_IS_MODEL(OCTEON_CN7XXX)) || + OCTEON_IS_MODEL(OCTEON_CN70XX)) { + union cvmx_pow_nw_tim nm_tim; + + nm_tim.u64 = 0; + /* 4096 cycles */ + nm_tim.s.nw_tim = 3; + cvmx_write_csr(CVMX_POW_NW_TIM, nm_tim.u64); + } write_octeon_c0_icacheerr(0); write_c0_derraddr1(0); } /** - * Early entry point for arch setup + * prom_init - Early entry point for arch setup */ void __init prom_init(void) { @@ -607,10 +662,8 @@ void __init prom_init(void) const char *arg; char *p; int i; + u64 t; int argc; -#ifdef CONFIG_CAVIUM_RESERVE32 - int64_t addr = -1; -#endif /* * The bootloader passes a pointer to the boot descriptor in * $a3, this is available as fw_arg3. @@ -623,9 +676,22 @@ void __init prom_init(void) sysinfo = cvmx_sysinfo_get(); memset(sysinfo, 0, sizeof(*sysinfo)); sysinfo->system_dram_size = octeon_bootinfo->dram_size << 20; - sysinfo->phy_mem_desc_ptr = - cvmx_phys_to_ptr(octeon_bootinfo->phy_mem_desc_addr); - sysinfo->core_mask = octeon_bootinfo->core_mask; + sysinfo->phy_mem_desc_addr = (u64)phys_to_virt(octeon_bootinfo->phy_mem_desc_addr); + + if ((octeon_bootinfo->major_version > 1) || + (octeon_bootinfo->major_version == 1 && + octeon_bootinfo->minor_version >= 4)) + cvmx_coremask_copy(&sysinfo->core_mask, + &octeon_bootinfo->ext_core_mask); + else + cvmx_coremask_set64(&sysinfo->core_mask, + octeon_bootinfo->core_mask); + + /* Some broken u-boot pass garbage in upper bits, clear them out */ + if (!OCTEON_IS_MODEL(OCTEON_CN78XX)) + for (i = 512; i < 1024; i++) + cvmx_coremask_clear_core(&sysinfo->core_mask, i); + sysinfo->exception_base_addr = octeon_bootinfo->exception_base_addr; sysinfo->cpu_clock_hz = octeon_bootinfo->eclock_hz; sysinfo->dram_data_rate_hz = octeon_bootinfo->dclock_hz * 2; @@ -646,15 +712,56 @@ void __init prom_init(void) sysinfo->dfa_ref_clock_hz = octeon_bootinfo->dfa_ref_clock_hz; sysinfo->bootloader_config_flags = octeon_bootinfo->config_flags; - if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { + if (OCTEON_IS_OCTEON2()) { /* I/O clock runs at a different rate than the CPU. */ union cvmx_mio_rst_boot rst_boot; rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); octeon_io_clock_rate = 50000000 * rst_boot.s.pnr_mul; + } else if (OCTEON_IS_OCTEON3()) { + /* I/O clock runs at a different rate than the CPU. */ + union cvmx_rst_boot rst_boot; + rst_boot.u64 = cvmx_read_csr(CVMX_RST_BOOT); + octeon_io_clock_rate = 50000000 * rst_boot.s.pnr_mul; } else { octeon_io_clock_rate = sysinfo->cpu_clock_hz; } + t = read_c0_cvmctl(); + if ((t & (1ull << 27)) == 0) { + /* + * Setup the multiplier save/restore code if + * CvmCtl[NOMUL] clear. + */ + void *save; + void *save_end; + void *restore; + void *restore_end; + int save_len; + int restore_len; + int save_max = (char *)octeon_mult_save_end - + (char *)octeon_mult_save; + int restore_max = (char *)octeon_mult_restore_end - + (char *)octeon_mult_restore; + if (current_cpu_data.cputype == CPU_CAVIUM_OCTEON3) { + save = octeon_mult_save3; + save_end = octeon_mult_save3_end; + restore = octeon_mult_restore3; + restore_end = octeon_mult_restore3_end; + } else { + save = octeon_mult_save2; + save_end = octeon_mult_save2_end; + restore = octeon_mult_restore2; + restore_end = octeon_mult_restore2_end; + } + save_len = (char *)save_end - (char *)save; + restore_len = (char *)restore_end - (char *)restore; + if (!WARN_ON(save_len > save_max || + restore_len > restore_max)) { + memcpy(octeon_mult_save, save, save_len); + memcpy(octeon_mult_restore, restore, restore_len); + } + } + /* * Only enable the LED controller if we're running on a CN38XX, CN58XX, * or CN56XX. The CN30XX and CN31XX don't have an LED controller. @@ -671,7 +778,7 @@ void __init prom_init(void) cvmx_write_csr(CVMX_LED_UDD_DATX(1), 0); cvmx_write_csr(CVMX_LED_EN, 1); } -#ifdef CONFIG_CAVIUM_RESERVE32 + /* * We need to temporarily allocate all memory in the reserve32 * region. This makes sure the kernel doesn't allocate this @@ -682,14 +789,16 @@ void __init prom_init(void) * Allocate memory for RESERVED32 aligned on 2MB boundary. This * is in case we later use hugetlb entries with it. */ - addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20, - 0, 0, 2 << 20, - "CAVIUM_RESERVE32", 0); - if (addr < 0) - pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n"); - else - octeon_reserve32_memory = addr; -#endif + if (CONFIG_CAVIUM_RESERVE32) { + int64_t addr = + cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20, + 0, 0, 2 << 20, + "CAVIUM_RESERVE32", 0); + if (addr < 0) + pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n"); + else + octeon_reserve32_memory = addr; + } #ifdef CONFIG_CAVIUM_OCTEON_LOCK_L2 if (cvmx_read_csr(CVMX_L2D_FUS3) & (3ull << 34)) { @@ -728,24 +837,13 @@ void __init prom_init(void) octeon_write_lcd("Linux"); #endif -#ifdef CONFIG_CAVIUM_GDB - /* - * When debugging the linux kernel, force the cores to enter - * the debug exception handler to break in. - */ - if (octeon_get_boot_debug_flag()) { - cvmx_write_csr(CVMX_CIU_DINT, 1 << cvmx_get_core_num()); - cvmx_read_csr(CVMX_CIU_DINT); - } -#endif - octeon_setup_delays(); /* * BIST should always be enabled when doing a soft reset. L2 * Cache locking for instance is not cleared unless BIST is * enabled. Unfortunately due to a chip errata G-200 for - * Cn38XX and CN31XX, BIST msut be disabled on these parts. + * Cn38XX and CN31XX, BIST must be disabled on these parts. */ if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2) || OCTEON_IS_MODEL(OCTEON_CN31XX)) @@ -755,15 +853,15 @@ void __init prom_init(void) /* Default to 64MB in the simulator to speed things up */ if (octeon_is_simulation()) - MAX_MEMORY = 64ull << 20; + max_memory = 64ull << 20; arg = strstr(arcs_cmdline, "mem="); if (arg) { - MAX_MEMORY = memparse(arg + 4, &p); - if (MAX_MEMORY == 0) - MAX_MEMORY = 32ull << 30; + max_memory = memparse(arg + 4, &p); + if (max_memory == 0) + max_memory = 32ull << 30; if (*p == '@') - RESERVE_LOW_MEM = memparse(p + 1, &p); + reserve_low_mem = memparse(p + 1, &p); } arcs_cmdline[0] = 0; @@ -773,17 +871,11 @@ void __init prom_init(void) cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]); if ((strncmp(arg, "MEM=", 4) == 0) || (strncmp(arg, "mem=", 4) == 0)) { - MAX_MEMORY = memparse(arg + 4, &p); - if (MAX_MEMORY == 0) - MAX_MEMORY = 32ull << 30; + max_memory = memparse(arg + 4, &p); + if (max_memory == 0) + max_memory = 32ull << 30; if (*p == '@') - RESERVE_LOW_MEM = memparse(p + 1, &p); - } else if (strcmp(arg, "ecc_verbose") == 0) { -#ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC - __cvmx_interrupt_ecc_report_single_bit_errors = 1; - pr_notice("Reporting of single bit ECC errors is " - "turned on\n"); -#endif + reserve_low_mem = memparse(p + 1, &p); #ifdef CONFIG_KEXEC } else if (strncmp(arg, "crashkernel=", 12) == 0) { crashk_size = memparse(arg+12, &p); @@ -805,23 +897,10 @@ void __init prom_init(void) } if (strstr(arcs_cmdline, "console=") == NULL) { -#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL - strcat(arcs_cmdline, " console=ttyS0,115200"); -#else if (octeon_uart == 1) strcat(arcs_cmdline, " console=ttyS1,115200"); else strcat(arcs_cmdline, " console=ttyS0,115200"); -#endif - } - - if (octeon_is_simulation()) { - /* - * The simulator uses a mtdram device pre filled with - * the filesystem. Also specify the calibration delay - * to avoid calculating it every time. - */ - strcat(arcs_cmdline, " rw root=1f00 slram=root,0x40000000,+1073741824"); } mips_hpt_frequency = octeon_get_clock_rate(); @@ -835,10 +914,13 @@ void __init prom_init(void) _machine_kexec_shutdown = octeon_shutdown; _machine_crash_shutdown = octeon_crash_shutdown; _machine_kexec_prepare = octeon_kexec_prepare; +#ifdef CONFIG_SMP + _crash_smp_send_stop = octeon_crash_smp_send_stop; +#endif #endif octeon_user_io_init(); - register_smp_ops(&octeon_smp_ops); + octeon_setup_smp(); } /* Exclude a single page from the regions obtained in plat_mem_setup. */ @@ -847,7 +929,7 @@ static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) { if (addr > *mem && addr < *mem + *size) { u64 inc = addr - *mem; - add_memory_region(*mem, inc, BOOT_MEM_RAM); + memblock_add(*mem, inc); *mem += inc; *size -= inc; } @@ -859,6 +941,29 @@ static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) } #endif /* CONFIG_CRASH_DUMP */ +void __init fw_init_cmdline(void) +{ + int i; + + octeon_boot_desc_ptr = (struct octeon_boot_descriptor *)fw_arg3; + for (i = 0; i < octeon_boot_desc_ptr->argc; i++) { + const char *arg = + cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]); + if (strlen(arcs_cmdline) + strlen(arg) + 1 < + sizeof(arcs_cmdline) - 1) { + strcat(arcs_cmdline, " "); + strcat(arcs_cmdline, arg); + } + } +} + +void __init *plat_get_fdt(void) +{ + octeon_bootinfo = + cvmx_phys_to_ptr(octeon_boot_desc_ptr->cvmx_desc_vaddr); + return phys_to_virt(octeon_bootinfo->fdt_addr); +} + void __init plat_mem_setup(void) { uint64_t mem_alloc_size; @@ -866,8 +971,6 @@ void __init plat_mem_setup(void) uint64_t crashk_end; #ifndef CONFIG_CRASH_DUMP int64_t memory; - uint64_t kernel_start; - uint64_t kernel_size; #endif total = 0; @@ -881,30 +984,28 @@ void __init plat_mem_setup(void) * to consistently work. */ mem_alloc_size = 4 << 20; - if (mem_alloc_size > MAX_MEMORY) - mem_alloc_size = MAX_MEMORY; + if (mem_alloc_size > max_memory) + mem_alloc_size = max_memory; /* Crashkernel ignores bootmem list. It relies on mem=X@Y option */ #ifdef CONFIG_CRASH_DUMP - add_memory_region(RESERVE_LOW_MEM, MAX_MEMORY, BOOT_MEM_RAM); - total += MAX_MEMORY; + memblock_add(reserve_low_mem, max_memory); + total += max_memory; #else #ifdef CONFIG_KEXEC if (crashk_size > 0) { - add_memory_region(crashk_base, crashk_size, BOOT_MEM_RAM); + memblock_add(crashk_base, crashk_size); crashk_end = crashk_base + crashk_size; } #endif /* - * When allocating memory, we want incrementing addresses from - * bootmem_alloc so the code in add_memory_region can merge - * regions next to each other. + * When allocating memory, we want incrementing addresses, + * which is handled by memblock */ cvmx_bootmem_lock(); - while ((boot_mem_map.nr_map < BOOT_MEM_MAP_MAX) - && (total < MAX_MEMORY)) { + while (total < max_memory) { memory = cvmx_bootmem_phy_alloc(mem_alloc_size, - __pa_symbol(&__init_end), -1, + __pa_symbol(&_end), -1, 0x100000, CVMX_BOOTMEM_FLAG_NO_LOCKING); if (memory >= 0) { @@ -934,13 +1035,9 @@ void __init plat_mem_setup(void) */ if (memory < crashk_base && end > crashk_end) { /* region is fully in */ - add_memory_region(memory, - crashk_base - memory, - BOOT_MEM_RAM); + memblock_add(memory, crashk_base - memory); total += crashk_base - memory; - add_memory_region(crashk_end, - end - crashk_end, - BOOT_MEM_RAM); + memblock_add(crashk_end, end - crashk_end); total += end - crashk_end; continue; } @@ -968,7 +1065,7 @@ void __init plat_mem_setup(void) */ mem_alloc_size -= end - crashk_base; #endif - add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM); + memblock_add(memory, mem_alloc_size); total += mem_alloc_size; /* Recovering mem_alloc_size */ mem_alloc_size = 4 << 20; @@ -977,16 +1074,8 @@ void __init plat_mem_setup(void) } } cvmx_bootmem_unlock(); - /* Add the memory region for the kernel. */ - kernel_start = (unsigned long) _text; - kernel_size = _end - _text; - - /* Adjust for physical offset. */ - kernel_start &= ~0xffffffff80000000ULL; - add_memory_region(kernel_start, kernel_size, BOOT_MEM_RAM); #endif /* CONFIG_CRASH_DUMP */ -#ifdef CONFIG_CAVIUM_RESERVE32 /* * Now that we've allocated the kernel memory it is safe to * free the reserved region. We free it here so that builtin @@ -994,18 +1083,17 @@ void __init plat_mem_setup(void) */ if (octeon_reserve32_memory) cvmx_bootmem_free_named("CAVIUM_RESERVE32"); -#endif /* CONFIG_CAVIUM_RESERVE32 */ if (total == 0) panic("Unable to allocate memory from " - "cvmx_bootmem_phy_alloc\n"); + "cvmx_bootmem_phy_alloc"); } /* * Emit one character to the boot UART. Exported for use by the * watchdog timer. */ -int prom_putchar(char c) +void prom_putchar(char c) { uint64_t lsrval; @@ -1016,13 +1104,12 @@ int prom_putchar(char c) /* Write the byte */ cvmx_write_csr(CVMX_MIO_UARTX_THR(octeon_uart), c & 0xffull); - return 1; } EXPORT_SYMBOL(prom_putchar); -void prom_free_prom_memory(void) +void __init prom_free_prom_memory(void) { - if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) { + if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) { /* Check for presence of Core-14449 fix. */ u32 insn; u32 *foo; @@ -1044,52 +1131,55 @@ void prom_free_prom_memory(void) panic("No PREF instruction at Core-14449 probe point."); if (((insn >> 16) & 0x1f) != 28) - panic("Core-14449 WAR not in place (%04x).\n" - "Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).", insn); + panic("OCTEON II DCache prefetch workaround not in place (%04x).\n" + "Please build kernel with proper options (CONFIG_CAVIUM_CN63XXP1).", + insn); } } -int octeon_prune_device_tree(void); +void __init octeon_fill_mac_addresses(void); -extern const char __dtb_octeon_3xxx_begin; -extern const char __dtb_octeon_3xxx_end; -extern const char __dtb_octeon_68xx_begin; -extern const char __dtb_octeon_68xx_end; void __init device_tree_init(void) { - int dt_size; - struct boot_param_header *fdt; + const void *fdt; bool do_prune; + bool fill_mac; +#ifdef CONFIG_MIPS_ELF_APPENDED_DTB + if (!fdt_check_header(&__appended_dtb)) { + fdt = &__appended_dtb; + do_prune = false; + fill_mac = true; + pr_info("Using appended Device Tree.\n"); + } else +#endif if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { fdt = phys_to_virt(octeon_bootinfo->fdt_addr); if (fdt_check_header(fdt)) panic("Corrupt Device Tree passed to kernel."); - dt_size = be32_to_cpu(fdt->totalsize); do_prune = false; + fill_mac = false; + pr_info("Using passed Device Tree.\n"); } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { - fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin; - dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin; + fdt = &__dtb_octeon_68xx_begin; do_prune = true; + fill_mac = true; } else { - fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin; - dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin; + fdt = &__dtb_octeon_3xxx_begin; do_prune = true; + fill_mac = true; } - /* Copy the default tree from init memory. */ - initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8); - if (initial_boot_params == NULL) - panic("Could not allocate initial_boot_params\n"); - memcpy(initial_boot_params, fdt, dt_size); + initial_boot_params = (void *)fdt; if (do_prune) { octeon_prune_device_tree(); pr_info("Using internal Device Tree.\n"); - } else { - pr_info("Using passed Device Tree.\n"); } - unflatten_device_tree(); + if (fill_mac) + octeon_fill_mac_addresses(); + unflatten_and_copy_device_tree(); + init_octeon_system_type(); } static int __initdata disable_octeon_edac_p; @@ -1120,7 +1210,7 @@ static int __init edac_devinit(void) name = edac_device_names[i]; dev = platform_device_register_simple(name, -1, NULL, 0); if (IS_ERR(dev)) { - pr_err("Registation of %s failed!\n", name); + pr_err("Registration of %s failed!\n", name); err = PTR_ERR(dev); } } @@ -1131,7 +1221,7 @@ static int __init edac_devinit(void) dev = platform_device_register_simple("octeon_lmc_edac", i, NULL, 0); if (IS_ERR(dev)) { - pr_err("Registation of octeon_lmc_edac %d failed!\n", i); + pr_err("Registration of octeon_lmc_edac %d failed!\n", i); err = PTR_ERR(dev); } } @@ -1139,3 +1229,30 @@ static int __init edac_devinit(void) return err; } device_initcall(edac_devinit); + +static void __initdata *octeon_dummy_iospace; + +static int __init octeon_no_pci_init(void) +{ + /* + * Initially assume there is no PCI. The PCI/PCIe platform code will + * later re-initialize these to correct values if they are present. + */ + octeon_dummy_iospace = vzalloc(IO_SPACE_LIMIT); + set_io_port_base((unsigned long)octeon_dummy_iospace); + ioport_resource.start = RESOURCE_SIZE_MAX; + ioport_resource.end = 0; + return 0; +} +core_initcall(octeon_no_pci_init); + +static int __init octeon_no_pci_release(void) +{ + /* + * Release the allocated memory if a real IO space is there. + */ + if ((unsigned long)octeon_dummy_iospace != mips_io_port_base) + vfree(octeon_dummy_iospace); + return 0; +} +late_initcall(octeon_no_pci_release); |
