diff --git a/sys/mips/cavium/asm_octeon.S b/sys/mips/cavium/asm_octeon.S index d9f79f134ffd..94ac875a1996 100644 --- a/sys/mips/cavium/asm_octeon.S +++ b/sys/mips/cavium/asm_octeon.S @@ -1,182 +1,66 @@ -/***********************license start*************** - * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights - * reserved. +/*- + * Copyright (c) 2004-2010 Juli Mallett + * All rights reserved. * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * * Neither the name of Cavium Networks nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS - * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH - * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY - * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT - * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES - * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR - * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET - * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT - * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. - * - * - * For any questions regarding licensing please contact marketing@caviumnetworks.com - * - ***********************license end**************************************/ - -/* $FreeBSD$ */ + * $FreeBSD$ + */ #include -#include -#include -#include -#include -#include "assym.s" - + .set noreorder - -#define CPU_DISABLE_INTERRUPTS(reg, reg2, reg3) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - nop; \ - move reg3, reg; \ - li reg2, ~MIPS_SR_INT_IE; \ - and reg, reg2, reg; \ - mtc0 reg, MIPS_COP_0_STATUS; \ - COP0_SYNC - - - -#define CPU_ENABLE_INTERRUPTS(reg, reg3) \ - mfc0 reg, MIPS_COP_0_STATUS; \ - nop; \ - or reg, reg, reg3; \ - mtc0 reg, MIPS_COP_0_STATUS; \ - COP0_SYNC - - -#define PUSHR(reg) \ - addiu sp,sp,-16 ; \ - sd reg, 8(sp) ; \ - nop ; - -#define POPR(reg) \ - ld reg, 8(sp) ; \ - addiu sp,sp,16 ; \ - nop ; - - - - +#ifdef SMP /* - * octeon_ciu_get_interrupt_reg_addr - * - * Given Int-X, En-X combination, return the CIU Interrupt Enable Register addr - * a0 = ciu Int-X: 0/1 - * a1 = ciu EN-0: 0/1 + * This function must be implemented in assembly because it is called early + * in AP boot without a valid stack. */ -LEAF(octeon_ciu_get_interrupt_reg_addr) - .set noreorder - .set mips3 +LEAF(platform_processor_id) + .set push + .set mips32r2 + jr ra + rdhwr v0, $0 + .set pop +END(platform_processor_id) - beqz a0, ciu_get_interrupt_reg_addr_Int_0 - nop - -ciu_get_interrupt_reg_addr_Int_1: - beqz a1, ciu_get_interrupt_reg_addr_Int_1_En_0 - nop - -ciu_get_interrupt_reg_addr_Int_1_En1: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN1_INT1_LO - j ciu_get_interrupt_reg_addr_ret - nop - -ciu_get_interrupt_reg_addr_Int_1_En_0: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN0_INT1_LO - j ciu_get_interrupt_reg_addr_ret - nop - -ciu_get_interrupt_reg_addr_Int_0: - beqz a1, ciu_get_interrupt_reg_addr_Int_0_En_0 - nop - -ciu_get_interrupt_reg_addr_Int_0_En_1: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN1_INT0_LO - j ciu_get_interrupt_reg_addr_ret - nop - -ciu_get_interrupt_reg_addr_Int_0_En_0: - li a0, OCTEON_CIU_ADDR_HI - dsll32 a0, a0, 0 - nop - ori a0, OCTEON_CIU_EN0_INT0_LO - - -ciu_get_interrupt_reg_addr_ret: - j ra - nop - - .set mips0 - .set reorder -END(octeon_ciu_get_interrupt_reg_addr) - - - /* - * octeon_ciu_mask_all_interrupts - * - * a0 = ciu Interrupt-X: 0/1 - * a1 = ciu Enable-X: 0/1 + * Called on APs to wait until they are told to launch. */ -LEAF(octeon_ciu_mask_all_interrupts) - .set noreorder - .set mips3 +LEAF(octeon_ap_wait) + jal platform_processor_id + nop - PUSHR(ra) - PUSHR(s0) - - move t0, a0 - move t1, a1 - li a0, MIPS_SR_INT_IE - CPU_DISABLE_INTERRUPTS(a2, a1, s0) - move a0, t0 - move t1, a1 - jal octeon_ciu_get_interrupt_reg_addr - nop - ld a2, 0(a0) # Dummy read - nop - move a2, zero # Clear all - sd a2, 0(a0) # Write new Enable bits - nop - CPU_ENABLE_INTERRUPTS(a2, s0) +1: ll t0, octeon_ap_boot + bne v0, t0, 1b + nop - POPR(s0) - POPR(ra) - j ra # Return - nop # (bd slot) + move t0, zero + sc t0, octeon_ap_boot - .set mips0 - .set reorder -END(octeon_ciu_mask_all_interrupts) + beqz t0, 1b + nop + j mpentry + nop +END(octeon_ap_wait) +#endif diff --git a/sys/mips/cavium/dev/rgmii/octeon_fau.c b/sys/mips/cavium/dev/rgmii/octeon_fau.c deleted file mode 100644 index fb4c0ad3a80e..000000000000 --- a/sys/mips/cavium/dev/rgmii/octeon_fau.c +++ /dev/null @@ -1,83 +0,0 @@ -/***********************license start*************** - * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights - * reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * * Neither the name of Cavium Networks nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - * - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS - * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH - * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY - * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT - * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES - * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR - * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET - * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT - * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. - * - * - * For any questions regarding licensing please contact marketing@caviumnetworks.com - * - ***********************license end**************************************/ - -/*------------------------------------------------------------------ - * octeon_fau.c Fetch & Add Block - * - *------------------------------------------------------------------ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include "octeon_fau.h" - -/* - * oct_fau_init - * - * How do we initialize FAU unit. I don't even think we can reset it. - */ -void octeon_fau_init (void) -{ -} - - -/* - * oct_fau_enable - * - * Let the Fetch/Add unit roll - */ -void octeon_fau_enable (void) -{ -} - - -/* - * oct_fau_disable - * - * disable fau - * - * Don't know if we can even do that. - */ -void octeon_fau_disable (void) -{ -} diff --git a/sys/mips/cavium/dev/rgmii/octeon_fau.h b/sys/mips/cavium/dev/rgmii/octeon_fau.h index 1683ff55e005..acf5132e2e89 100644 --- a/sys/mips/cavium/dev/rgmii/octeon_fau.h +++ b/sys/mips/cavium/dev/rgmii/octeon_fau.h @@ -217,9 +217,4 @@ static inline void octeon_fau_atomic_add64 (octeon_fau_reg_64_t reg, int64_t val } -extern void octeon_fau_init(void); -extern void octeon_fau_enable(void); -extern void octeon_fau_disable(void); - - #endif /* ___OCTEON_FAU__H___ */ diff --git a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c b/sys/mips/cavium/dev/rgmii/octeon_rgmx.c index ada09461778f..5b84af5dcaad 100644 --- a/sys/mips/cavium/dev/rgmii/octeon_rgmx.c +++ b/sys/mips/cavium/dev/rgmii/octeon_rgmx.c @@ -1481,7 +1481,7 @@ static void octeon_config_hw_units_post_ports (void) oct_write64(OCTEON_POW_WORKQUEUE_INT_THRESHOLD(OCTEON_POW_RX_GROUP_NUM), thr.word64); #endif - ciu_enable_interrupts(OCTEON_CORE_ID, OCTEON_RGMX_CIU_INTX, OCTEON_RGMX_CIU_ENX, + ciu_enable_interrupts(PCPU_GET(cpuid), OCTEON_RGMX_CIU_INTX, OCTEON_RGMX_CIU_ENX, (OCTEON_POW_RX_GROUP_MASK | CIU_GENTIMER_BITS_ENABLE(CIU_GENTIMER_NUM_1)), CIU_MIPS_IP2); diff --git a/sys/mips/cavium/files.octeon1 b/sys/mips/cavium/files.octeon1 index c10988c46c13..4cf31f84310f 100644 --- a/sys/mips/cavium/files.octeon1 +++ b/sys/mips/cavium/files.octeon1 @@ -1,8 +1,7 @@ # $FreeBSD$ # Octeon Support Files # -mips/mips/mp_machdep.c optional smp -mips/cavium/dev/rgmii/octeon_fau.c optional rgmii +mips/cavium/asm_octeon.S optional smp mips/cavium/dev/rgmii/octeon_fpa.c optional rgmii mips/cavium/dev/rgmii/octeon_ipd.c optional rgmii mips/cavium/dev/rgmii/octeon_pko.c optional rgmii @@ -10,6 +9,7 @@ mips/cavium/dev/rgmii/octeon_rgmx.c optional rgmii mips/cavium/obio.c optional uart mips/cavium/octeon_ebt3000_cf.c optional cf mips/cavium/octeon_machdep.c standard +mips/cavium/octeon_mp.c optional smp mips/cavium/uart_bus_octeonusart.c optional uart mips/cavium/uart_cpu_octeonusart.c optional uart mips/cavium/uart_dev_oct16550.c optional uart diff --git a/sys/mips/cavium/octeon_machdep.c b/sys/mips/cavium/octeon_machdep.c index f55c7ea4dfb3..c796071a3859 100644 --- a/sys/mips/cavium/octeon_machdep.c +++ b/sys/mips/cavium/octeon_machdep.c @@ -111,25 +111,6 @@ platform_reset(void) oct_write64(OCTEON_CIU_SOFT_RST, 1); } - -static inline uint32_t -octeon_disable_interrupts(void) -{ - uint32_t status_bits; - - status_bits = mips_rd_status(); - mips_wr_status(status_bits & ~MIPS_SR_INT_IE); - return (status_bits); -} - - -static inline void -octeon_set_interrupts(uint32_t status_bits) -{ - mips_wr_status(status_bits); -} - - void octeon_led_write_char(int char_position, char val) { @@ -203,82 +184,6 @@ octeon_led_run_wheel(int *prog_count, int led_position) *prog_count &= 0x7; } -#define LSR_DATAREADY 0x01 /* Data ready */ -#define LSR_THRE 0x20 /* Transmit holding register empty */ -#define LSR_TEMT 0x40 /* Transmitter Empty. THR, TSR & FIFO */ -#define USR_TXFIFO_NOTFULL 0x02 /* Uart TX FIFO Not full */ - -/* - * octeon_uart_write_byte - * - * Put out a single byte off of uart port. - */ - -void -octeon_uart_write_byte(int uart_index, uint8_t ch) -{ - uint64_t val, val2; - if (uart_index < 0 || uart_index > 1) - return; - - while (1) { - val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); - val2 = oct_read64(OCTEON_MIO_UART0_USR + (uart_index * 0x400)); - if ((((uint8_t) val) & LSR_THRE) || - (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { - break; - } - } - - /* Write the byte */ - oct_write8(OCTEON_MIO_UART0_THR + (uart_index * 0x400), (uint64_t) ch); - - /* Force Flush the IOBus */ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); -} - - -void -octeon_uart_write_byte0(uint8_t ch) -{ - uint64_t val, val2; - - while (1) { - val = oct_read64(OCTEON_MIO_UART0_LSR); - val2 = oct_read64(OCTEON_MIO_UART0_USR); - if ((((uint8_t) val) & LSR_THRE) || - (((uint8_t) val2) & USR_TXFIFO_NOTFULL)) { - break; - } - } - - /* Write the byte */ - oct_write8(OCTEON_MIO_UART0_THR, (uint64_t) ch); - - /* Force Flush the IOBus */ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); -} - -/* - * octeon_uart_write_string - * - */ -void -octeon_uart_write_string(int uart_index, const char *str) -{ - /* Just loop writing one byte at a time */ - - while (*str) { - octeon_uart_write_byte(uart_index, *str); - if (*str == '\n') { - octeon_uart_write_byte(uart_index, '\r'); - } - str++; - } -} - -static char wstr[30]; - void octeon_led_write_hex(uint32_t wl) { @@ -289,44 +194,6 @@ octeon_led_write_hex(uint32_t wl) } -void octeon_uart_write_hex2(uint32_t wl, uint32_t wh) -{ - sprintf(wstr, "0x%X-0x%X ", wh, wl); - octeon_uart_write_string(0, wstr); -} - -void -octeon_uart_write_hex(uint32_t wl) -{ - sprintf(wstr, " 0x%X ", wl); - octeon_uart_write_string(0, wstr); -} - -/* - * octeon_wait_uart_flush - */ -void -octeon_wait_uart_flush(int uart_index, uint8_t ch) -{ - uint64_t val; - int64_t val3; - uint32_t cpu_status_bits; - - if (uart_index < 0 || uart_index > 1) - return; - - cpu_status_bits = octeon_disable_interrupts(); - /* Force Flush the IOBus */ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); - for (val3 = 0xfffffffff; val3 > 0; val3--) { - val = oct_read64(OCTEON_MIO_UART0_LSR + (uart_index * 0x400)); - if (((uint8_t) val) & LSR_TEMT) - break; - } - octeon_set_interrupts(cpu_status_bits); -} - - /* * octeon_debug_symbol * @@ -450,17 +317,17 @@ ciu_get_en_reg_addr_new(int corenum, int intx, int enx, int ciu_ip) /* XXX kasserts? */ if (enx < CIU_EN_0 || enx > CIU_EN_1) { printf("%s: invalid enx value %d, should be %d or %d\n", - __FUNCTION__, enx, CIU_EN_0, CIU_EN_1); + __func__, enx, CIU_EN_0, CIU_EN_1); return 0; } if (intx < CIU_INT_0 || intx > CIU_INT_1) { printf("%s: invalid intx value %d, should be %d or %d\n", - __FUNCTION__, enx, CIU_INT_0, CIU_INT_1); + __func__, enx, CIU_INT_0, CIU_INT_1); return 0; } if (ciu_ip < CIU_MIPS_IP2 || ciu_ip > CIU_MIPS_IP3) { printf("%s: invalid ciu_ip value %d, should be %d or %d\n", - __FUNCTION__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); + __func__, ciu_ip, CIU_MIPS_IP2, CIU_MIPS_IP3); return 0; } @@ -517,7 +384,7 @@ ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits) core_num, intx, enx, write_bits); #endif - cpu_status_bits = octeon_disable_interrupts(); + cpu_status_bits = intr_disable(); ciu_intr_sum_reg_addr = ciu_get_intr_sum_reg_addr(core_num, intx, enx); @@ -535,7 +402,7 @@ ciu_clear_int_summary(int core_num, int intx, int enx, uint64_t write_bits) printf(" Readback: 0x%llX\n\n ", (uint64_t) oct_read64(ciu_intr_sum_reg_addr)); #endif - octeon_set_interrupts(cpu_status_bits); + intr_restore(cpu_status_bits); } /* @@ -550,7 +417,7 @@ ciu_disable_intr(int core_num, int intx, int enx) if (core_num == CIU_THIS_CORE) core_num = octeon_get_core_num(); - cpu_status_bits = octeon_disable_interrupts(); + cpu_status_bits = intr_disable(); ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); @@ -559,7 +426,7 @@ ciu_disable_intr(int core_num, int intx, int enx) oct_write64(ciu_intr_reg_addr, 0LL); oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ - octeon_set_interrupts(cpu_status_bits); + intr_restore(cpu_status_bits); } void @@ -580,7 +447,7 @@ ciu_dump_interrutps_enabled(int core_num, int intx, int enx, int ciu_ip) #endif if (!ciu_intr_reg_addr) { - printf("Bad call to %s\n", __FUNCTION__); + printf("Bad call to %s\n", __func__); while(1); return; } @@ -612,7 +479,7 @@ void ciu_enable_interrupts(int core_num, int intx, int enx, core_num, intx, enx, ciu_ip, set_these_interrupt_bits); #endif - cpu_status_bits = octeon_disable_interrupts(); + cpu_status_bits = intr_disable(); #ifndef OCTEON_SMP_1 ciu_intr_reg_addr = ciu_get_intr_en_reg_addr(core_num, intx, enx); @@ -621,7 +488,7 @@ void ciu_enable_interrupts(int core_num, int intx, int enx, #endif if (!ciu_intr_reg_addr) { - printf("Bad call to %s\n", __FUNCTION__); + printf("Bad call to %s\n", __func__); while(1); return; /* XXX */ } @@ -634,7 +501,7 @@ void ciu_enable_interrupts(int core_num, int intx, int enx, #endif ciu_intr_bits |= set_these_interrupt_bits; oct_write64(ciu_intr_reg_addr, ciu_intr_bits); -#ifdef OCTEON_SMP +#ifdef SMP mips_wbflush(); #endif oct_read64(OCTEON_MIO_BOOT_BIST_STAT); /* Bus Barrier */ @@ -644,7 +511,7 @@ void ciu_enable_interrupts(int core_num, int intx, int enx, (uint64_t)oct_read64(ciu_intr_reg_addr)); #endif - octeon_set_interrupts(cpu_status_bits); + intr_restore(cpu_status_bits); } unsigned long @@ -659,12 +526,8 @@ octeon_memory_init(void) uint32_t realmem_bytes; if (octeon_board_real()) { - printf("octeon_dram == %jx\n", (intmax_t)octeon_dram); - printf("reduced to ram: %u MB", (uint32_t)octeon_dram >> 20); - realmem_bytes = (octeon_dram - PAGE_SIZE); realmem_bytes &= ~(PAGE_SIZE - 1); - printf("Real memory bytes is %x\n", realmem_bytes); } else { /* Simulator we limit to 96 meg */ realmem_bytes = (96 << 20); @@ -678,8 +541,6 @@ octeon_memory_init(void) phys_avail[1] = realmem_bytes; realmem_bytes -= OCTEON_DRAM_FIRST_256_END; realmem_bytes &= ~(PAGE_SIZE - 1); - printf("phys_avail[0] = %#lx phys_avail[1] = %#lx\n", - (long)phys_avail[0], (long)phys_avail[1]); } else { /* Simulator gets 96Meg period. */ phys_avail[1] = (96 << 20); @@ -705,23 +566,14 @@ octeon_memory_init(void) realmem_bytes &= ~(PAGE_SIZE - 1); /* Now map the rest of the memory */ phys_avail[2] = 0x20000000; - printf("realmem_bytes is now at %x\n", realmem_bytes); phys_avail[3] = ((uint32_t) 0x20000000 + realmem_bytes); - printf("Next block of memory goes from %#lx to %#lx\n", - (long)phys_avail[2], (long)phys_avail[3]); physmem += btoc(phys_avail[3] - phys_avail[2]); - } else { - printf("realmem_bytes is %d\n", realmem_bytes); } realmem = physmem; printf("Total DRAM Size %#X\n", (uint32_t) octeon_dram); printf("Bank 0 = %#08lX -> %#08lX\n", (long)phys_avail[0], (long)phys_avail[1]); printf("Bank 1 = %#08lX -> %#08lX\n", (long)phys_avail[2], (long)phys_avail[3]); - printf("physmem: %#lx\n", physmem); - - Maxmem = physmem; - } void @@ -760,7 +612,15 @@ platform_start(__register_t a0, __register_t a1, __register_t a2 __unused, kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); #endif platform_counter_freq = octeon_get_clock_rate(); - mips_timer_init_params(platform_counter_freq, 1); + mips_timer_init_params(platform_counter_freq, 0); + +#ifdef SMP + /* + * Clear any pending IPIs and enable the IPI interrupt. + */ + oct_write64(OCTEON_CIU_MBOX_CLRX(0), 0xffffffff); + ciu_enable_interrupts(0, CIU_INT_1, CIU_EN_0, OCTEON_CIU_ENABLE_MBOX_INTR, CIU_MIPS_IP3); +#endif } /* impSTART: This stuff should move back into the Cavium SDK */ @@ -982,7 +842,7 @@ octeon_boot_params_init(register_t ptr) printf("Boot Descriptor Ver: %u -> %u/%u", octeon_bd_ver, octeon_cvmx_bd_ver/100, octeon_cvmx_bd_ver%100); - printf(" CPU clock: %uMHz\n", octeon_cpu_clock/1000000); + printf(" CPU clock: %uMHz Core Mask: %#x\n", octeon_cpu_clock/1000000, octeon_core_mask); printf(" Dram: %u MB", (uint32_t)(octeon_dram >> 20)); printf(" Board Type: %u Revision: %u/%u\n", octeon_board_type, octeon_board_rev_major, octeon_board_rev_minor); diff --git a/sys/mips/cavium/octeon_mp.c b/sys/mips/cavium/octeon_mp.c new file mode 100644 index 000000000000..85cdc45dadd4 --- /dev/null +++ b/sys/mips/cavium/octeon_mp.c @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2004-2010 Juli Mallett + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include + +unsigned octeon_ap_boot = ~0; + +void +platform_ipi_send(int cpuid) +{ + oct_write64(OCTEON_CIU_MBOX_SETX(cpuid), 1); + mips_wbflush(); +} + +void +platform_ipi_clear(void) +{ + uint64_t action; + + action = oct_read64(OCTEON_CIU_MBOX_CLRX(PCPU_GET(cpuid))); + KASSERT(action == 1, ("unexpected IPIs: %#jx", (uintmax_t)action)); + oct_write64(OCTEON_CIU_MBOX_CLRX(PCPU_GET(cpuid)), action); +} + +int +platform_ipi_intrnum(void) +{ + return (1); +} + +void +platform_init_ap(int cpuid) +{ + /* + * Set the exception base. + */ + mips_wr_prid1(0x80000000 | cpuid); + + /* + * Set up interrupts, clear IPIs and unmask the IPI interrupt. + */ + octeon_ciu_reset(); + + oct_write64(OCTEON_CIU_MBOX_CLRX(cpuid), 0xffffffff); + ciu_enable_interrupts(cpuid, CIU_INT_1, CIU_EN_0, OCTEON_CIU_ENABLE_MBOX_INTR, CIU_MIPS_IP3); + + mips_wbflush(); +} + +int +platform_num_processors(void) +{ + return (fls(octeon_core_mask)); +} + +int +platform_start_ap(int cpuid) +{ + if (atomic_cmpset_32(&octeon_ap_boot, ~0, cpuid) == 0) + return (-1); + for (;;) { + DELAY(1000); + if (atomic_cmpset_32(&octeon_ap_boot, 0, ~0) != 0) + return (0); + printf("Waiting for cpu%d to start\n", cpuid); + } +} diff --git a/sys/mips/cavium/octeon_pcmap_regs.h b/sys/mips/cavium/octeon_pcmap_regs.h index 16dff5b35c95..0ee1a73ea8a1 100644 --- a/sys/mips/cavium/octeon_pcmap_regs.h +++ b/sys/mips/cavium/octeon_pcmap_regs.h @@ -54,14 +54,6 @@ #ifndef LOCORE -/* XXXimp: From Cavium's include/pcpu.h, need to port that over */ -#ifndef OCTEON_SMP -#define OCTEON_CORE_ID 0 -#else -extern struct pcpu *cpuid_to_pcpu[]; -#define OCTEON_CORE_ID (mips_rd_coreid()) -#endif - /* * Utility inlines & macros */ @@ -324,62 +316,6 @@ static inline void oct_write32 (uint64_t csr_addr, uint32_t val32) #define OCTEON_SCRATCH_2 32 -static inline uint64_t oct_mf_chord (void) -{ - uint64_t dest; - - __asm __volatile ( ".set push\n" - ".set noreorder\n" - ".set noat\n" - ".set mips64\n" - "dmfc2 $1, 0x400\n" - "move %0, $1\n" - ".set pop\n" - : "=r" (dest) : : "$1"); - return dest; -} - - -#define MIPS64_DMFCz(cop,regnum,cp0reg,select) \ - .word (0x40200000 | (cop << 25) | (regnum << 16) | (cp0reg << 11) | select) - - -#define mips64_getcpz_xstr(s) mips64_getcpz_str(s) -#define mips64_getcpz_str(s) #s - -#define mips64_dgetcpz(cop,cpzreg,sel,val_ptr) \ - ({ __asm __volatile( \ - ".set push\n" \ - ".set mips3\n" \ - ".set noreorder\n" \ - ".set noat\n" \ - mips64_getcpz_xstr(MIPS64_DMFCz(cop,1,cpzreg,sel)) "\n" \ - "nop\n" \ - "nop\n" \ - "nop\n" \ - "nop\n" \ - "sd $1,0(%0)\n" \ - ".set pop" \ - : /* no outputs */ : "r" (val_ptr) : "$1"); \ - }) - - -#define mips64_dgetcp2(cp2reg,sel,retval_ptr) \ - mips64_dgetcpz(2,cp2reg,sel,retval_ptr) - - -#define OCTEON_MF_CHORD(dest) mips64_dgetcp2(0x400, 0, &dest) - - - -#define OCTEON_RDHWR(result, regstr) \ - __asm __volatile ( \ - ".set mips3\n" \ - "rdhwr %0,$" OCTEON_TMP_STR(regstr) "\n" \ - ".set mips\n" \ - : "=d" (result)); - -#define CVMX_MF_CHORD(dest) OCTEON_RDHWR(dest, 30) #define OCTEON_CHORD_HEX(dest_ptr) \ ({ __asm __volatile( \ @@ -397,15 +333,6 @@ static inline uint64_t oct_mf_chord (void) : /* no outputs */ : "r" (dest_ptr) : "$2"); \ }) - - -#define OCTEON_MF_CHORD_BAD(dest) \ - __asm __volatile ( \ - ".set mips3\n" \ - "dmfc2 %0, 0x400\n" \ - ".set mips0\n" \ - : "=&r" (dest) : ) - static inline uint64_t oct_scratch_read64 (uint64_t address) { return(*((volatile uint64_t *)(OCTEON_SCRATCH_BASE + address))); @@ -417,17 +344,6 @@ static inline void oct_scratch_write64 (uint64_t address, uint64_t value) } -#define OCTEON_READ_CSR32(addr, val) \ - addr_ptr = addr; \ - oct_read_32_ptr(&addr_ptr, &val); - -#define OCTEON_WRITE_CSR32(addr, val, val_dummy) \ - addr_ptr = addr; \ - oct_write_32_ptr(&addr_ptr, &val); \ - oct_read64(OCTEON_MIO_BOOT_BIST_STAT); - - - /* * Octeon Address Space Definitions */ @@ -791,12 +707,6 @@ extern void octeon_led_write_hexchar(int char_position, char hexval); extern void octeon_led_write_hex(uint32_t wl); extern void octeon_led_write_string(const char *str); extern void octeon_reset(void); -extern void octeon_uart_write_byte(int uart_index, uint8_t ch); -extern void octeon_uart_write_string(int uart_index, const char *str); -extern void octeon_uart_write_hex(uint32_t wl); -extern void octeon_uart_write_hex2(uint32_t wl, uint32_t wh); -extern void octeon_wait_uart_flush(int uart_index, uint8_t ch); -extern void octeon_uart_write_byte0(uint8_t ch); extern void octeon_led_write_char0(char val); extern void octeon_led_run_wheel(int *pos, int led_position); extern void octeon_debug_symbol(void); diff --git a/sys/mips/mips/locore.S b/sys/mips/mips/locore.S index 1574d7542a18..697b81884f55 100644 --- a/sys/mips/mips/locore.S +++ b/sys/mips/mips/locore.S @@ -162,6 +162,18 @@ VECTOR(_locore, unknown) sw a2, _C_LABEL(fenvp) #endif +#if defined(TARGET_OCTEON) && defined(SMP) + .set push + .set mips32r2 + rdhwr t2, $0 + beqz t2, 1f + nop + j octeon_ap_wait + nop + .set pop +1: +#endif + /* * Initialize stack and call machine startup. */ @@ -178,10 +190,10 @@ VECTOR(_locore, unknown) nop PTR_LA sp, _C_LABEL(thread0) - lw a0, TD_PCB(sp) - li t0, ~7 + PTR_L a0, TD_PCB(sp) + REG_LI t0, ~7 and a0, a0, t0 - subu sp, a0, CALLFRAME_SIZ + PTR_SUBU sp, a0, CALLFRAME_SIZ jal _C_LABEL(mi_startup) # mi_startup(frame) sw zero, CALLFRAME_SIZ - 8(sp) # Zero out old fp for debugger diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c index 52d05fad7118..f0c142f0c3a5 100644 --- a/sys/mips/mips/mp_machdep.c +++ b/sys/mips/mips/mp_machdep.c @@ -157,6 +157,8 @@ start_ap(int cpuid) cpus = mp_naps; dpcpu = (void *)kmem_alloc(kernel_map, DPCPU_SIZE); + mips_sync(); + if (platform_start_ap(cpuid) != 0) return (-1); /* could not start AP */ @@ -246,6 +248,8 @@ smp_init_secondary(u_int32_t cpuid) mips_dcache_wbinv_all(); mips_icache_sync_all(); + mips_sync(); + MachSetPID(0); pcpu_init(PCPU_ADDR(cpuid), cpuid, sizeof(struct pcpu)); diff --git a/sys/mips/mips/mpboot.S b/sys/mips/mips/mpboot.S index ce2982d4005c..e1c578a79613 100644 --- a/sys/mips/mips/mpboot.S +++ b/sys/mips/mips/mpboot.S @@ -36,8 +36,21 @@ .set noat .set noreorder +#ifdef TARGET_OCTEON +#define CLEAR_STATUS \ + mfc0 a0, COP_0_STATUS_REG ;\ + li a2, (MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX) ; \ + or a0, a0, a2 ; \ + li a2, ~(MIPS_SR_INT_IE | MIPS_SR_EXL | SR_KSU_USER | MIPS_SR_BEV) ; \ + and a0, a0, a2 ; \ + mtc0 a0, COP_0_STATUS_REG +#else +#define CLEAR_STATUS \ + mtc0 zero, COP_0_STATUS_REG +#endif + GLOBAL(mpentry) - mtc0 zero, COP_0_STATUS_REG /* disable interrupts */ + CLEAR_STATUS /* disable interrupts */ mtc0 zero, COP_0_CAUSE_REG /* clear soft interrupts */