o) Add SMP support for Octeon using U-Boot to launch all the processors at the
same time. o) Remove some unused trivial uart functions from octeon_machdep now that the uart part is fully working and they are unused. o) Use __func__ instead of __FUNCTION__. o) Use intr_*() instead of other routines that do the same thing. o) Remove some duplicate printfs from the Octeon port, as well as duplicate setting of Maxmem. o) Use the right frequency divider on Octeon. o) Use PCPU_GET(cpuid) consistently to get the cpuid of the running core. o) Remove some unused macros in the Octeon port. o) Use mips_sync() around use of the global dpcpu, whose value may not be visible to APs at first. o) When loading the first thread's stack, use macros to make the code correct for n64 as well. o) Remove stub, do-nothing FAU init/enable/disable functions from the RGMX driver.
This commit is contained in:
parent
a97a1ee3d9
commit
b6777295a6
@ -1,182 +1,66 @@
|
||||
/***********************license start***************
|
||||
* Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights
|
||||
* reserved.
|
||||
/*-
|
||||
* Copyright (c) 2004-2010 Juli Mallett <jmallett@FreeBSD.org>
|
||||
* 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 <machine/asm.h>
|
||||
#include <machine/cache_r4k.h>
|
||||
#include <machine/cpuregs.h>
|
||||
#include <machine/param.h>
|
||||
#include <machine/pte.h>
|
||||
|
||||
#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
|
||||
|
@ -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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <mips/cavium/octeon_pcmap_regs.h>
|
||||
#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)
|
||||
{
|
||||
}
|
@ -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___ */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
102
sys/mips/cavium/octeon_mp.c
Normal file
102
sys/mips/cavium/octeon_mp.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2010 Juli Mallett <jmallett@FreeBSD.org>
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/hwfunc.h>
|
||||
#include <machine/smp.h>
|
||||
|
||||
#include <mips/cavium/octeon_pcmap_regs.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user