diff options
author | jchandra <jchandra@FreeBSD.org> | 2011-07-16 19:35:44 +0000 |
---|---|---|
committer | jchandra <jchandra@FreeBSD.org> | 2011-07-16 19:35:44 +0000 |
commit | e798ada01f1454e101057b020a078ae7b5766f9a (patch) | |
tree | e3e3f11eb79bb870df9440eb366cc41e74fdab65 /sys | |
parent | 046524f41de3c23997965fb7bf010d0346da4d3c (diff) | |
download | FreeBSD-src-e798ada01f1454e101057b020a078ae7b5766f9a.zip FreeBSD-src-e798ada01f1454e101057b020a078ae7b5766f9a.tar.gz |
Add MIPS platform files for Netlogic XLP SoC.
Processor, UART, PIC and Messaging Network code. Also add
sys/mips/nlm/hal for on-chip device registers.
In collaboration with: Prabhath Raman <prabhathpr at netlogicmicro com>
Approved by: bz(re), jmallett, imp(mips)
Diffstat (limited to 'sys')
30 files changed, 7112 insertions, 0 deletions
diff --git a/sys/mips/nlm/board.c b/sys/mips/nlm/board.c new file mode 100644 index 0000000..d75059e --- /dev/null +++ b/sys/mips/nlm/board.c @@ -0,0 +1,80 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> + +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/fmn.h> +#include <mips/nlm/hal/pic.h> +#include <mips/nlm/hal/uart.h> + +#include <mips/nlm/board.h> + +struct xlp_board_info xlp_board_info; + +int nlm_setup_xlp_board(void); + +/* + * All our knowledge of chip and board that cannot be detected by probing + * at run-time goes here + */ + +int +nlm_setup_xlp_board(void) +{ + struct xlp_board_info *boardp; + int node; + + /* start with a clean slate */ + boardp = &xlp_board_info; + memset(boardp, 0, sizeof(xlp_board_info)); + boardp->nodemask = 0x1; /* only node 0 */ + + for (node = 0; node < XLP_MAX_NODES; node++) { + if ((boardp->nodemask & (1 << node)) == 0) + continue; + } + return 0; +} + +int nlm_board_info_setup() +{ + nlm_setup_xlp_board(); + return 0; +} diff --git a/sys/mips/nlm/board.h b/sys/mips/nlm/board.h new file mode 100644 index 0000000..742ebba --- /dev/null +++ b/sys/mips/nlm/board.h @@ -0,0 +1,75 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_BOARD_H__ +#define __NLM_BOARD_H__ + +#define XLP_NAE_NBLOCKS 5 +#define XLP_NAE_NPORTS 4 +#define XLP_I2C_MAXDEVICES 8 + +struct xlp_i2c_devinfo { + u_int addr; /* keep first, for i2c ivars to work */ + int bus; + char *device; +}; + +struct xlp_port_ivars { + int port; + int block; + int type; + int phy_addr; +}; + +struct xlp_block_ivars { + int block; + int type; + u_int portmask; + struct xlp_port_ivars port_ivars[XLP_NAE_NPORTS]; +}; + +struct xlp_nae_ivars { + int node; + u_int blockmask; + struct xlp_block_ivars block_ivars[XLP_NAE_NBLOCKS]; +}; + +struct xlp_board_info { + u_int nodemask; + struct xlp_node_info { + struct xlp_i2c_devinfo i2c_devs[XLP_I2C_MAXDEVICES]; + struct xlp_nae_ivars nae_ivars; + } nodes[XLP_MAX_NODES]; +}; + +extern struct xlp_board_info xlp_board_info; +int nlm_board_info_setup(void); + +#endif diff --git a/sys/mips/nlm/bus_space_rmi.c b/sys/mips/nlm/bus_space_rmi.c new file mode 100644 index 0000000..8653cdf --- /dev/null +++ b/sys/mips/nlm/bus_space_rmi.c @@ -0,0 +1,688 @@ +/* + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/endian.h> +#include <sys/malloc.h> +#include <sys/ktr.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_kern.h> +#include <vm/vm_extern.h> + +#include <machine/bus.h> +#include <machine/cache.h> + +static int +rmi_bus_space_map(void *t, bus_addr_t addr, + bus_size_t size, int flags, + bus_space_handle_t *bshp); + +static void +rmi_bus_space_unmap(void *t, bus_space_handle_t bsh, + bus_size_t size); + +static int +rmi_bus_space_subregion(void *t, + bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size, + bus_space_handle_t *nbshp); + +static u_int8_t +rmi_bus_space_read_1(void *t, + bus_space_handle_t handle, + bus_size_t offset); + +static u_int16_t +rmi_bus_space_read_2(void *t, + bus_space_handle_t handle, + bus_size_t offset); + +static u_int32_t +rmi_bus_space_read_4(void *t, + bus_space_handle_t handle, + bus_size_t offset); + +static void +rmi_bus_space_read_multi_1(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int8_t *addr, + size_t count); + +static void +rmi_bus_space_read_multi_2(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int16_t *addr, + size_t count); + +static void +rmi_bus_space_read_multi_4(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int32_t *addr, + size_t count); + +static void +rmi_bus_space_read_region_1(void *t, + bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, + size_t count); + +static void +rmi_bus_space_read_region_2(void *t, + bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, + size_t count); + +static void +rmi_bus_space_read_region_4(void *t, + bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, + size_t count); + +static void +rmi_bus_space_write_1(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int8_t value); + +static void +rmi_bus_space_write_2(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int16_t value); + +static void +rmi_bus_space_write_4(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int32_t value); + +static void +rmi_bus_space_write_multi_1(void *t, + bus_space_handle_t handle, + bus_size_t offset, + const u_int8_t *addr, + size_t count); + +static void +rmi_bus_space_write_multi_2(void *t, + bus_space_handle_t handle, + bus_size_t offset, + const u_int16_t *addr, + size_t count); + +static void +rmi_bus_space_write_multi_4(void *t, + bus_space_handle_t handle, + bus_size_t offset, + const u_int32_t *addr, + size_t count); + +static void +rmi_bus_space_write_region_2(void *t, + bus_space_handle_t bsh, + bus_size_t offset, + const u_int16_t *addr, + size_t count); + +static void +rmi_bus_space_write_region_4(void *t, + bus_space_handle_t bsh, + bus_size_t offset, + const u_int32_t *addr, + size_t count); + + +static void +rmi_bus_space_set_region_2(void *t, + bus_space_handle_t bsh, + bus_size_t offset, u_int16_t value, + size_t count); +static void +rmi_bus_space_set_region_4(void *t, + bus_space_handle_t bsh, + bus_size_t offset, u_int32_t value, + size_t count); + +static void +rmi_bus_space_barrier(void *tag __unused, bus_space_handle_t bsh __unused, + bus_size_t offset __unused, bus_size_t len __unused, int flags); + +static void +rmi_bus_space_copy_region_2(void *t, + bus_space_handle_t bsh1, + bus_size_t off1, + bus_space_handle_t bsh2, + bus_size_t off2, size_t count); + +u_int8_t +rmi_bus_space_read_stream_1(void *t, bus_space_handle_t handle, + bus_size_t offset); + +static u_int16_t +rmi_bus_space_read_stream_2(void *t, bus_space_handle_t handle, + bus_size_t offset); + +static u_int32_t +rmi_bus_space_read_stream_4(void *t, bus_space_handle_t handle, + bus_size_t offset); +static void +rmi_bus_space_read_multi_stream_1(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int8_t *addr, + size_t count); + +static void +rmi_bus_space_read_multi_stream_2(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int16_t *addr, + size_t count); + +static void +rmi_bus_space_read_multi_stream_4(void *t, + bus_space_handle_t handle, + bus_size_t offset, u_int32_t *addr, + size_t count); + +void +rmi_bus_space_write_stream_1(void *t, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t value); +static void +rmi_bus_space_write_stream_2(void *t, bus_space_handle_t handle, + bus_size_t offset, u_int16_t value); + +static void +rmi_bus_space_write_stream_4(void *t, bus_space_handle_t handle, + bus_size_t offset, u_int32_t value); + +static void +rmi_bus_space_write_multi_stream_1(void *t, + bus_space_handle_t handle, + bus_size_t offset, + const u_int8_t *addr, + size_t count); +static void +rmi_bus_space_write_multi_stream_2(void *t, + bus_space_handle_t handle, + bus_size_t offset, + const u_int16_t *addr, + size_t count); + +static void +rmi_bus_space_write_multi_stream_4(void *t, + bus_space_handle_t handle, + bus_size_t offset, + const u_int32_t *addr, + size_t count); + +#define TODO() printf("XLP bus space: '%s' unimplemented\n", __func__) + +static struct bus_space local_rmi_bus_space = { + /* cookie */ + (void *)0, + + /* mapping/unmapping */ + rmi_bus_space_map, + rmi_bus_space_unmap, + rmi_bus_space_subregion, + + /* allocation/deallocation */ + NULL, + NULL, + + /* barrier */ + rmi_bus_space_barrier, + + /* read (single) */ + rmi_bus_space_read_1, + rmi_bus_space_read_2, + rmi_bus_space_read_4, + NULL, + + /* read multiple */ + rmi_bus_space_read_multi_1, + rmi_bus_space_read_multi_2, + rmi_bus_space_read_multi_4, + NULL, + + /* read region */ + rmi_bus_space_read_region_1, + rmi_bus_space_read_region_2, + rmi_bus_space_read_region_4, + NULL, + + /* write (single) */ + rmi_bus_space_write_1, + rmi_bus_space_write_2, + rmi_bus_space_write_4, + NULL, + + /* write multiple */ + rmi_bus_space_write_multi_1, + rmi_bus_space_write_multi_2, + rmi_bus_space_write_multi_4, + NULL, + + /* write region */ + NULL, + rmi_bus_space_write_region_2, + rmi_bus_space_write_region_4, + NULL, + + /* set multiple */ + NULL, + NULL, + NULL, + NULL, + + /* set region */ + NULL, + rmi_bus_space_set_region_2, + rmi_bus_space_set_region_4, + NULL, + + /* copy */ + NULL, + rmi_bus_space_copy_region_2, + NULL, + NULL, + + /* read (single) stream */ + rmi_bus_space_read_stream_1, + rmi_bus_space_read_stream_2, + rmi_bus_space_read_stream_4, + NULL, + + /* read multiple stream */ + rmi_bus_space_read_multi_stream_1, + rmi_bus_space_read_multi_stream_2, + rmi_bus_space_read_multi_stream_4, + NULL, + + /* read region stream */ + rmi_bus_space_read_region_1, + rmi_bus_space_read_region_2, + rmi_bus_space_read_region_4, + NULL, + + /* write (single) stream */ + rmi_bus_space_write_stream_1, + rmi_bus_space_write_stream_2, + rmi_bus_space_write_stream_4, + NULL, + + /* write multiple stream */ + rmi_bus_space_write_multi_stream_1, + rmi_bus_space_write_multi_stream_2, + rmi_bus_space_write_multi_stream_4, + NULL, + + /* write region stream */ + NULL, + rmi_bus_space_write_region_2, + rmi_bus_space_write_region_4, + NULL, +}; + +/* generic bus_space tag */ +bus_space_tag_t rmi_bus_space = &local_rmi_bus_space; + +/* + * Map a region of device bus space into CPU virtual address space. + */ +static int +rmi_bus_space_map(void *t __unused, bus_addr_t addr, + bus_size_t size __unused, int flags __unused, + bus_space_handle_t *bshp) +{ + + *bshp = addr; + return (0); +} + +/* + * Unmap a region of device bus space. + */ +static void +rmi_bus_space_unmap(void *t __unused, bus_space_handle_t bsh __unused, + bus_size_t size __unused) +{ +} + +/* + * Get a new handle for a subregion of an already-mapped area of bus space. + */ + +static int +rmi_bus_space_subregion(void *t __unused, bus_space_handle_t bsh, + bus_size_t offset, bus_size_t size __unused, + bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + return (0); +} + +/* + * Read a 1, 2, 4, or 8 byte quantity from bus space + * described by tag/handle/offset. + */ + +static u_int8_t +rmi_bus_space_read_1(void *tag, bus_space_handle_t handle, + bus_size_t offset) +{ + return (u_int8_t) (*(volatile u_int32_t *)(handle + offset)); +} + +static u_int16_t +rmi_bus_space_read_2(void *tag, bus_space_handle_t handle, + bus_size_t offset) +{ + return (u_int16_t)(*(volatile u_int32_t *)(handle + offset)); +} + +static u_int32_t +rmi_bus_space_read_4(void *tag, bus_space_handle_t handle, + bus_size_t offset) +{ + return (*(volatile u_int32_t *)(handle + offset)); +} + + +/* + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ +static void +rmi_bus_space_read_multi_1(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_read_multi_2(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_read_multi_4(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + TODO(); +} + +/* + * Write the 1, 2, 4, or 8 byte value `value' to bus space + * described by tag/handle/offset. + */ + +static void +rmi_bus_space_write_1(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int8_t value) +{ + *(volatile u_int32_t *)(handle + offset) = (u_int32_t)value; +} + +static void +rmi_bus_space_write_2(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int16_t value) +{ + *(volatile u_int32_t *)(handle + offset) = (u_int32_t)value; +} + +static void +rmi_bus_space_write_4(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int32_t value) +{ + *(volatile u_int32_t *)(handle + offset) = value; +} + + +/* + * Write `count' 1, 2, 4, or 8 byte quantities from the buffer + * provided to bus space described by tag/handle/offset. + */ + + +static void +rmi_bus_space_write_multi_1(void *tag, bus_space_handle_t handle, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_write_multi_2(void *tag, bus_space_handle_t handle, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_write_multi_4(void *tag, bus_space_handle_t handle, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + TODO(); +} + +/* + * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described + * by tag/handle starting at `offset'. + */ + +static void +rmi_bus_space_set_region_2(void *t, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t value, size_t count) +{ + bus_addr_t addr = bsh + offset; + + for (; count != 0; count--, addr += 2) + (*(volatile u_int32_t *)(addr)) = value; +} + +static void +rmi_bus_space_set_region_4(void *t, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t value, size_t count) +{ + bus_addr_t addr = bsh + offset; + + for (; count != 0; count--, addr += 4) + (*(volatile u_int32_t *)(addr)) = value; +} + + +/* + * Copy `count' 1, 2, 4, or 8 byte values from bus space starting + * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2. + */ +static void +rmi_bus_space_copy_region_2(void *t, bus_space_handle_t bsh1, + bus_size_t off1, bus_space_handle_t bsh2, + bus_size_t off2, size_t count) +{ + printf("bus_space_copy_region_2 - unimplemented\n"); +} + +/* + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle/offset and copy into buffer provided. + */ + +u_int8_t +rmi_bus_space_read_stream_1(void *t, bus_space_handle_t handle, + bus_size_t offset) +{ + + return *((volatile u_int8_t *)(handle + offset)); +} + + +static u_int16_t +rmi_bus_space_read_stream_2(void *t, bus_space_handle_t handle, + bus_size_t offset) +{ + return *(volatile u_int16_t *)(handle + offset); +} + + +static u_int32_t +rmi_bus_space_read_stream_4(void *t, bus_space_handle_t handle, + bus_size_t offset) +{ + return (*(volatile u_int32_t *)(handle + offset)); +} + + +static void +rmi_bus_space_read_multi_stream_1(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_read_multi_stream_2(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_read_multi_stream_4(void *tag, bus_space_handle_t handle, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + TODO(); +} + + +/* + * Read `count' 1, 2, 4, or 8 byte quantities from bus space + * described by tag/handle and starting at `offset' and copy into + * buffer provided. + */ +void +rmi_bus_space_read_region_1(void *t, bus_space_handle_t bsh, + bus_size_t offset, u_int8_t *addr, size_t count) +{ + TODO(); +} + +void +rmi_bus_space_read_region_2(void *t, bus_space_handle_t bsh, + bus_size_t offset, u_int16_t *addr, size_t count) +{ + TODO(); +} + +void +rmi_bus_space_read_region_4(void *t, bus_space_handle_t bsh, + bus_size_t offset, u_int32_t *addr, size_t count) +{ + bus_addr_t baddr = bsh + offset; + + while (count--) { + *addr++ = (*(volatile u_int32_t *)(baddr)); + baddr += 4; + } +} + +void +rmi_bus_space_write_stream_1(void *t, bus_space_handle_t handle, + bus_size_t offset, u_int8_t value) +{ + TODO(); +} + + +static void +rmi_bus_space_write_stream_2(void *t, bus_space_handle_t handle, + bus_size_t offset, u_int16_t value) +{ + TODO(); +} + + +static void +rmi_bus_space_write_stream_4(void *t, bus_space_handle_t handle, + bus_size_t offset, u_int32_t value) +{ + TODO(); +} + + +static void +rmi_bus_space_write_multi_stream_1(void *tag, bus_space_handle_t handle, + bus_size_t offset, const u_int8_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_write_multi_stream_2(void *tag, bus_space_handle_t handle, + bus_size_t offset, const u_int16_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_write_multi_stream_4(void *tag, bus_space_handle_t handle, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + TODO(); +} + +void +rmi_bus_space_write_region_2(void *t, + bus_space_handle_t bsh, + bus_size_t offset, + const u_int16_t *addr, + size_t count) +{ + TODO(); +} + +void +rmi_bus_space_write_region_4(void *t, bus_space_handle_t bsh, + bus_size_t offset, const u_int32_t *addr, size_t count) +{ + TODO(); +} + +static void +rmi_bus_space_barrier(void *tag __unused, bus_space_handle_t bsh __unused, + bus_size_t offset __unused, bus_size_t len __unused, int flags) +{ +} diff --git a/sys/mips/nlm/clock.h b/sys/mips/nlm/clock.h new file mode 100644 index 0000000..2135dbf --- /dev/null +++ b/sys/mips/nlm/clock.h @@ -0,0 +1,41 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef _RMI_CLOCK_H_ +#define _RMI_CLOCK_H_ + +#define XLP_PIC_HZ 133000000U +#define XLP_CPU_HZ (nlm_cpu_frequency) + +void count_compare_clockhandler(struct trapframe *); +void pic_hardclockhandler(struct trapframe *); +void pic_timecounthandler(struct trapframe *); + +#endif /* _RMI_CLOCK_H_ */ diff --git a/sys/mips/nlm/cms.c b/sys/mips/nlm/cms.c new file mode 100644 index 0000000..c8a06f2 --- /dev/null +++ b/sys/mips/nlm/cms.c @@ -0,0 +1,451 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/limits.h> +#include <sys/bus.h> + +#include <sys/ktr.h> +#include <sys/kernel.h> +#include <sys/kthread.h> +#include <sys/proc.h> +#include <sys/resourcevar.h> +#include <sys/sched.h> +#include <sys/unistd.h> +#include <sys/sysctl.h> +#include <sys/malloc.h> + +#include <machine/reg.h> +#include <machine/cpu.h> +#include <machine/hwfunc.h> +#include <machine/mips_opcode.h> +#include <machine/param.h> +#include <machine/intr_machdep.h> + +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/cop0.h> +#include <mips/nlm/hal/cop2.h> +#include <mips/nlm/hal/fmn.h> +#include <mips/nlm/hal/pic.h> + +#include <mips/nlm/msgring.h> +#include <mips/nlm/interrupt.h> +#include <mips/nlm/xlp.h> +#include <mips/nlm/board.h> + +#define MSGRNG_NSTATIONS 1024 +/* + * Keep track of our message ring handler threads, each core has a + * different message station. Ideally we will need to start a few + * message handling threads every core, and wake them up depending on + * load + */ +struct msgring_thread { + struct thread *thread; /* msgring handler threads */ + int needed; /* thread needs to wake up */ +}; +static struct msgring_thread msgring_threads[XLP_MAX_CORES * XLP_MAX_THREADS]; +static struct proc *msgring_proc; /* all threads are under a proc */ + +/* + * The device drivers can register a handler for the the messages sent + * from a station (corresponding to the device). + */ +struct tx_stn_handler { + msgring_handler action; + void *arg; +}; +static struct tx_stn_handler msgmap[MSGRNG_NSTATIONS]; +static struct mtx msgmap_lock; +uint64_t xlp_cms_base; +uint32_t xlp_msg_thread_mask; +static int xlp_msg_threads_per_core = 3; /* Make tunable */ + +static void create_msgring_thread(int hwtid); +static int msgring_process_fast_intr(void *arg); +/* + * Boot time init, called only once + */ +void +xlp_msgring_config(void) +{ + unsigned int thrmask, mask; + int i; + + /* TODO: Add other nodes */ + xlp_cms_base = nlm_regbase_cms(0); + + mtx_init(&msgmap_lock, "msgring", NULL, MTX_SPIN); + if (xlp_threads_per_core < xlp_msg_threads_per_core) + xlp_msg_threads_per_core = xlp_threads_per_core; + thrmask = ((1 << xlp_msg_threads_per_core) - 1); + /*thrmask <<= xlp_threads_per_core - xlp_msg_threads_per_core;*/ + mask = 0; + for (i = 0; i < XLP_MAX_CORES; i++) { + mask <<= XLP_MAX_THREADS; + mask |= thrmask; + } + xlp_msg_thread_mask = xlp_hw_thread_mask & mask; + printf("Initializing CMS...@%jx, Message handler thread mask %#jx\n", + (uintmax_t)xlp_cms_base, (uintmax_t)xlp_msg_thread_mask); +} + +/* + * Initialize the messaging subsystem. + * + * Message Stations are shared among all threads in a cpu core, this + * has to be called once from every core which is online. + */ +void +xlp_msgring_iodi_config(void) +{ + void *cookie; + + xlp_msgring_config(); +/* nlm_cms_default_setup(0,0,0,0); */ + nlm_cms_credit_setup(50); + create_msgring_thread(0); + cpu_establish_hardintr("msgring", msgring_process_fast_intr, NULL, + NULL, IRQ_MSGRING, INTR_TYPE_NET, &cookie); +} + +void +nlm_cms_credit_setup(int credit) +{ + int src, qid, i; + +#if 0 + /* there are a total of 18 src stations on XLP. */ + printf("Setting up CMS credits!\n"); + for(src=0; src<18; src++) { + for(qid=0; qid<1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + } +#endif + printf("Setting up CMS credits!\n"); + /* CPU Credits */ + for(i = 1; i < 8; i++) { + src = (i << 4); + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + } + /* PCIE Credits */ + for(i = 0; i < 4; i++) { + src = (256 + (i * 2)); + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + } + /* DTE Credits */ + src = 264; + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + /* RSA Credits */ + src = 272; + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + /* Crypto Credits */ + src = 281; + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + /* CMP Credits */ + src = 298; + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + /* POE Credits */ + src = 384; + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } + /* NAE Credits */ + src = 476; + for(qid = 0; qid < 1024; qid++) { + nlm_cms_setup_credits(xlp_cms_base, qid, src, credit); + } +} + +void +xlp_msgring_cpu_init(uint32_t cpuid) +{ + int queue,i; + + queue = XLP_CMS_CPU_PUSHQ(0, ((cpuid >> 2) & 0x7), (cpuid & 0x3), 0); + /* temp allocate 4 segments to each output queue */ + nlm_cms_alloc_onchip_q(xlp_cms_base, queue, 4); + /* Enable high watermark and non empty interrupt */ + nlm_cms_per_queue_level_intr(xlp_cms_base, queue,2,0); + for(i=0;i<8;i++) { + /* temp distribute the credits to all CPU stations */ + nlm_cms_setup_credits(xlp_cms_base, queue, i * 16, 8); + } +} + +void +xlp_cpu_msgring_handler(int bucket, int size, int code, int stid, + struct nlm_fmn_msg *msg, void *data) +{ + int i; + + printf("vc:%d srcid:%d size:%d\n",bucket,stid,size); + for(i=0;i<size;i++) { + printf("msg->msg[%d]:0x%jx ", i, (uintmax_t)msg->msg[i]); + } + printf("\n"); +} + +/* + * Drain out max_messages for the buckets set in the bucket mask. + * Use max_msgs = 0 to drain out all messages. + */ +int +xlp_handle_msg_vc(int vc, int max_msgs) +{ + struct nlm_fmn_msg msg; + int i, srcid = 0, size = 0, code = 0; + struct tx_stn_handler *he; + uint32_t mflags, status; + + for (i = 0; i < max_msgs; i++) { + mflags = nlm_fmn_saveflags(); + status = nlm_fmn_msgrcv(vc, &srcid, &size, &code, &msg); + nlm_fmn_restoreflags(mflags); + if (status != 0) /* If there is no msg or error */ + break; + if (srcid < 0 && srcid >= 1024) { + printf("[%s]: bad src id %d\n", __func__, srcid); + continue; + } + he = &msgmap[srcid]; + if(he->action == NULL) { + printf("[%s]: No Handler for message from stn_id=%d," + " vc=%d, size=%d, msg0=%jx, dropping message\n", + __func__, srcid, vc, size, (uintmax_t)msg.msg[0]); + continue; + } + (he->action)(vc, size, code, srcid, &msg, he->arg); + } + + return (i); +} + +static int +msgring_process_fast_intr(void *arg) +{ + struct msgring_thread *mthd; + struct thread *td; + int cpu; + + cpu = nlm_cpuid(); + mthd = &msgring_threads[cpu]; + td = mthd->thread; + + /* clear pending interrupts */ + nlm_write_c0_eirr(1ULL << IRQ_MSGRING); + + /* wake up the target thread */ + mthd->needed = 1; + thread_lock(td); + if (TD_AWAITING_INTR(td)) { + TD_CLR_IWAIT(td); + sched_add(td, SRQ_INTR); + } + + thread_unlock(td); + return (FILTER_HANDLED); +} + +u_int fmn_msgcount[32][4]; +u_int fmn_loops[32]; + +static void +msgring_process(void * arg) +{ + volatile struct msgring_thread *mthd; + struct thread *td; + uint32_t mflags; + int hwtid, vc, handled, nmsgs; + + hwtid = (intptr_t)arg; + mthd = &msgring_threads[hwtid]; + td = mthd->thread; + KASSERT(curthread == td, + ("%s:msg_ithread and proc linkage out of sync", __func__)); + + /* First bind this thread to the right CPU */ + thread_lock(td); + sched_bind(td, xlp_hwtid_to_cpuid[hwtid]); + thread_unlock(td); + + if (hwtid != nlm_cpuid()) + printf("Misscheduled hwtid %d != cpuid %d\n", hwtid, nlm_cpuid()); + mflags = nlm_fmn_saveflags(); + nlm_fmn_cpu_init(IRQ_MSGRING, 0, 0, 0, 0, 0); + nlm_fmn_restoreflags(mflags); + + /* start processing messages */ + for( ; ; ) { + /*atomic_store_rel_int(&mthd->needed, 0);*/ + + /* enable cop2 access */ + do { + handled = 0; + for (vc = 0; vc < 4; vc++) { + nmsgs = xlp_handle_msg_vc(vc, 1); + fmn_msgcount[hwtid][vc] += nmsgs; + handled += nmsgs; + } + } while (handled); + + /* sleep */ +#if 0 + thread_lock(td); + if (mthd->needed) { + thread_unlock(td); + continue; + } + sched_class(td, PRI_ITHD); + TD_SET_IWAIT(td); + mi_switch(SW_VOL, NULL); + thread_unlock(td); +#else + pause("wmsg", 1); +#endif + fmn_loops[hwtid]++; + } +} + +static void +create_msgring_thread(int hwtid) +{ + struct msgring_thread *mthd; + struct thread *td; + int error; + + mthd = &msgring_threads[hwtid]; + error = kproc_kthread_add(msgring_process, (void *)(uintptr_t)hwtid, + &msgring_proc, &td, RFSTOPPED, 2, "msgrngproc", + "msgthr%d", hwtid); + if (error) + panic("kproc_kthread_add() failed with %d", error); + mthd->thread = td; + + thread_lock(td); + sched_class(td, PRI_ITHD); + sched_add(td, SRQ_INTR); + thread_unlock(td); + CTR2(KTR_INTR, "%s: created %s", __func__, td->td_name); +} + +int +register_msgring_handler(int startb, int endb, msgring_handler action, + void *arg) +{ + int i; + + printf("Register handler %d-%d %p(%p)\n", startb, endb, action, arg); + KASSERT(startb >= 0 && startb <= endb && endb < MSGRNG_NSTATIONS, + ("Invalid value for for bucket range %d,%d", startb, endb)); + + mtx_lock_spin(&msgmap_lock); + for (i = startb; i <= endb; i++) { + KASSERT(msgmap[i].action == NULL, + ("Bucket %d already used [action %p]", i, msgmap[i].action)); + msgmap[i].action = action; + msgmap[i].arg = arg; + } + mtx_unlock_spin(&msgmap_lock); + + return (0); +} + +/* + * Start message ring processing threads on other CPUs, after SMP start + */ +static void +start_msgring_threads(void *arg) +{ + int hwt; + + for (hwt = 1; hwt < XLP_MAX_CORES * XLP_MAX_THREADS; hwt++) { + if ((xlp_msg_thread_mask & (1 << hwt)) == 0) + continue; + create_msgring_thread(hwt); + } +} + +SYSINIT(start_msgring_threads, SI_SUB_SMP, SI_ORDER_MIDDLE, + start_msgring_threads, NULL); + +/* + * DEBUG support, XXX: static buffer, not locked + */ +static int +sys_print_debug(SYSCTL_HANDLER_ARGS) +{ + int error, nb, i, fs; + static char xprintb[4096], *buf; + + buf = xprintb; + fs = sizeof(xprintb); + nb = snprintf(buf, fs, + "\nID vc0 vc1 vc2 vc3 loops\n"); + buf += nb; + fs -= nb; + for (i = 0; i < 32; i++) { + if ((xlp_hw_thread_mask & (1 << i)) == 0) + continue; + nb = snprintf(buf, fs, + "%2d: %8d %8d %8d %8d %8d\n", i, + fmn_msgcount[i][0], fmn_msgcount[i][1], + fmn_msgcount[i][2], fmn_msgcount[i][3], + fmn_loops[i]); + buf += nb; + fs -= nb; + } + error = SYSCTL_OUT(req, xprintb, buf - xprintb); + return (error); +} + +SYSCTL_PROC(_debug, OID_AUTO, msgring, CTLTYPE_STRING | CTLFLAG_RD, 0, 0, + sys_print_debug, "A", "msgring debug info"); diff --git a/sys/mips/nlm/files.xlp b/sys/mips/nlm/files.xlp new file mode 100644 index 0000000..ac13845 --- /dev/null +++ b/sys/mips/nlm/files.xlp @@ -0,0 +1,12 @@ +# $FreeBSD$ +mips/nlm/hal/fmn.c standard +mips/nlm/xlp_machdep.c standard +mips/nlm/intr_machdep.c standard +mips/nlm/tick.c standard +mips/nlm/iodi.c standard +mips/nlm/board.c standard +mips/nlm/cms.c standard +mips/nlm/bus_space_rmi.c standard +mips/nlm/mpreset.S standard +mips/nlm/uart_bus_xlp_iodi.c optional uart +mips/nlm/uart_cpu_mips_xlp.c optional uart diff --git a/sys/mips/nlm/hal/bridge.h b/sys/mips/nlm/hal/bridge.h new file mode 100644 index 0000000..d91ccd6 --- /dev/null +++ b/sys/mips/nlm/hal/bridge.h @@ -0,0 +1,177 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_BRIDGE_H__ +#define __NLM_BRIDGE_H__ + +/** +* @file_name mio.h +* @author Netlogic Microsystems +* @brief Basic definitions of XLP memory and io subsystem +*/ + +/* BRIDGE specific registers */ +#define XLP_BRIDGE_MODE_REG 0x40 +#define XLP_BRIDGE_PCI_CFG_BASE_REG 0x41 +#define XLP_BRIDGE_PCI_CFG_LIMIT_REG 0x42 +#define XLP_BRIDGE_PCIE_CFG_BASE_REG 0x43 +#define XLP_BRIDGE_PCIE_CFG_LIMIT_REG 0x44 +#define XLP_BRIDGE_BUSNUM_BAR0_REG 0x45 +#define XLP_BRIDGE_BUSNUM_BAR1_REG 0x46 +#define XLP_BRIDGE_BUSNUM_BAR2_REG 0x47 +#define XLP_BRIDGE_BUSNUM_BAR3_REG 0x48 +#define XLP_BRIDGE_BUSNUM_BAR4_REG 0x49 +#define XLP_BRIDGE_BUSNUM_BAR5_REG 0x4a +#define XLP_BRIDGE_BUSNUM_BAR6_REG 0x4b +#define XLP_BRIDGE_FLASH_BAR0_REG 0x4c +#define XLP_BRIDGE_FLASH_BAR1_REG 0x4d +#define XLP_BRIDGE_FLASH_BAR2_REG 0x4e +#define XLP_BRIDGE_FLASH_BAR3_REG 0x4f +#define XLP_BRIDGE_FLASH_LIMIT0_REG 0x50 +#define XLP_BRIDGE_FLASH_LIMIT1_REG 0x51 +#define XLP_BRIDGE_FLASH_LIMIT2_REG 0x52 +#define XLP_BRIDGE_FLASH_LIMIT3_REG 0x53 + +#define XLP_BRIDGE_DRAM_BAR_REG(i) (0x54 + (i)) +#define XLP_BRIDGE_DRAM_BAR0_REG 0x54 +#define XLP_BRIDGE_DRAM_BAR1_REG 0x55 +#define XLP_BRIDGE_DRAM_BAR2_REG 0x56 +#define XLP_BRIDGE_DRAM_BAR3_REG 0x57 +#define XLP_BRIDGE_DRAM_BAR4_REG 0x58 +#define XLP_BRIDGE_DRAM_BAR5_REG 0x59 +#define XLP_BRIDGE_DRAM_BAR6_REG 0x5a +#define XLP_BRIDGE_DRAM_BAR7_REG 0x5b + +#define XLP_BRIDGE_DRAM_LIMIT_REG(i) (0x5c + (i)) +#define XLP_BRIDGE_DRAM_LIMIT0_REG 0x5c +#define XLP_BRIDGE_DRAM_LIMIT1_REG 0x5d +#define XLP_BRIDGE_DRAM_LIMIT2_REG 0x5e +#define XLP_BRIDGE_DRAM_LIMIT3_REG 0x5f +#define XLP_BRIDGE_DRAM_LIMIT4_REG 0x60 +#define XLP_BRIDGE_DRAM_LIMIT5_REG 0x61 +#define XLP_BRIDGE_DRAM_LIMIT6_REG 0x62 +#define XLP_BRIDGE_DRAM_LIMIT7_REG 0x63 + +#define XLP_BRIDGE_DRAM_NODE_TRANSLN0_REG 0x64 +#define XLP_BRIDGE_DRAM_NODE_TRANSLN1_REG 0x65 +#define XLP_BRIDGE_DRAM_NODE_TRANSLN2_REG 0x66 +#define XLP_BRIDGE_DRAM_NODE_TRANSLN3_REG 0x67 +#define XLP_BRIDGE_DRAM_NODE_TRANSLN4_REG 0x68 +#define XLP_BRIDGE_DRAM_NODE_TRANSLN5_REG 0x69 +#define XLP_BRIDGE_DRAM_NODE_TRANSLN6_REG 0x6a +#define XLP_BRIDGE_DRAM_NODE_TRANSLN7_REG 0x6b +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN0_REG 0x6c +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN1_REG 0x6d +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN2_REG 0x6e +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN3_REG 0x6f +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN4_REG 0x70 +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN5_REG 0x71 +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN6_REG 0x72 +#define XLP_BRIDGE_DRAM_CHNL_TRANSLN7_REG 0x73 +#define XLP_BRIDGE_PCIEMEM_BASE0_REG 0x74 +#define XLP_BRIDGE_PCIEMEM_BASE1_REG 0x75 +#define XLP_BRIDGE_PCIEMEM_BASE2_REG 0x76 +#define XLP_BRIDGE_PCIEMEM_BASE3_REG 0x77 +#define XLP_BRIDGE_PCIEMEM_LIMIT0_REG 0x78 +#define XLP_BRIDGE_PCIEMEM_LIMIT1_REG 0x79 +#define XLP_BRIDGE_PCIEMEM_LIMIT2_REG 0x7a +#define XLP_BRIDGE_PCIEMEM_LIMIT3_REG 0x7b +#define XLP_BRIDGE_PCIEIO_BASE0_REG 0x7c +#define XLP_BRIDGE_PCIEIO_BASE1_REG 0x7d +#define XLP_BRIDGE_PCIEIO_BASE2_REG 0x7e +#define XLP_BRIDGE_PCIEIO_BASE3_REG 0x7f +#define XLP_BRIDGE_PCIEIO_LIMIT0_REG 0x80 +#define XLP_BRIDGE_PCIEIO_LIMIT1_REG 0x81 +#define XLP_BRIDGE_PCIEIO_LIMIT2_REG 0x82 +#define XLP_BRIDGE_PCIEIO_LIMIT3_REG 0x83 +#define XLP_BRIDGE_PCIEMEM_BASE4_REG 0x84 +#define XLP_BRIDGE_PCIEMEM_BASE5_REG 0x85 +#define XLP_BRIDGE_PCIEMEM_BASE6_REG 0x86 +#define XLP_BRIDGE_PCIEMEM_LIMIT4_REG 0x87 +#define XLP_BRIDGE_PCIEMEM_LIMIT5_REG 0x88 +#define XLP_BRIDGE_PCIEMEM_LIMIT6_REG 0x89 +#define XLP_BRIDGE_PCIEIO_BASE4_REG 0x8a +#define XLP_BRIDGE_PCIEIO_BASE5_REG 0x8b +#define XLP_BRIDGE_PCIEIO_BASE6_REG 0x8c +#define XLP_BRIDGE_PCIEIO_LIMIT4_REG 0x8d +#define XLP_BRIDGE_PCIEIO_LIMIT5_REG 0x8e +#define XLP_BRIDGE_PCIEIO_LIMIT6_REG 0x8f +#define XLP_BRIDGE_NBU_EVENT_CNT_CTL_REG 0x90 +#define XLP_BRIDGE_EVNTCTR1_LOW_REG 0x91 +#define XLP_BRIDGE_EVNTCTR1_HI_REG 0x92 +#define XLP_BRIDGE_EVNT_CNT_CTL2_REG 0x93 +#define XLP_BRIDGE_EVNTCTR2_LOW_REG 0x94 +#define XLP_BRIDGE_EVNTCTR2_HI_REG 0x95 +#define XLP_BRIDGE_TRACEBUF_MATCH_REG0 0x96 +#define XLP_BRIDGE_TRACEBUF_MATCH_REG1 0x97 +#define XLP_BRIDGE_TRACEBUF_MATCH_LOW_REG 0x98 +#define XLP_BRIDGE_TRACEBUF_MATCH_HI_REG 0x99 +#define XLP_BRIDGE_TRACEBUF_CTRL_REG 0x9a +#define XLP_BRIDGE_TRACEBUF_INIT_REG 0x9b +#define XLP_BRIDGE_TRACEBUF_ACCESS_REG 0x9c +#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG0 0x9d +#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG1 0x9d +#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG2 0x9f +#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG3 0xa0 +#define XLP_BRIDGE_TRACEBUF_STATUS_REG 0xa1 +#define XLP_BRIDGE_ADDRESS_ERROR0_REG 0xa2 +#define XLP_BRIDGE_ADDRESS_ERROR1_REG 0xa3 +#define XLP_BRIDGE_ADDRESS_ERROR2_REG 0xa4 +#define XLP_BRIDGE_TAG_ECC_ADDR_ERROR0_REG 0xa5 +#define XLP_BRIDGE_TAG_ECC_ADDR_ERROR1_REG 0xa6 +#define XLP_BRIDGE_TAG_ECC_ADDR_ERROR2_REG 0xa7 +#define XLP_BRIDGE_LINE_FLUSH_REG0 0xa8 +#define XLP_BRIDGE_LINE_FLUSH_REG1 0xa9 +#define XLP_BRIDGE_NODE_ID_REG 0xaa +#define XLP_BRIDGE_ERROR_INTERRUPT_EN_REG 0xab +#define XLP_BRIDGE_PCIE0_WEIGHT_REG 0x300 +#define XLP_BRIDGE_PCIE1_WEIGHT_REG 0x301 +#define XLP_BRIDGE_PCIE2_WEIGHT_REG 0x302 +#define XLP_BRIDGE_PCIE3_WEIGHT_REG 0x303 +#define XLP_BRIDGE_USB_WEIGHT_REG 0x304 +#define XLP_BRIDGE_NET_WEIGHT_REG 0x305 +#define XLP_BRIDGE_POE_WEIGHT_REG 0x306 +#define XLP_BRIDGE_CMS_WEIGHT_REG 0x307 +#define XLP_BRIDGE_DMAENG_WEIGHT_REG 0x308 +#define XLP_BRIDGE_SEC_WEIGHT_REG 0x309 +#define XLP_BRIDGE_COMP_WEIGHT_REG 0x30a +#define XLP_BRIDGE_GIO_WEIGHT_REG 0x30b +#define XLP_BRIDGE_FLASH_WEIGHT_REG 0x30c + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +#define nlm_rdreg_bridge(b, r) nlm_read_reg_kseg(b, r) +#define nlm_wreg_bridge(b, r, v) nlm_write_reg_kseg(b, r, v) +#define nlm_pcibase_bridge(node) nlm_pcicfg_base(XLP_IO_BRIDGE_OFFSET(node)) +#define nlm_regbase_bridge(node) nlm_pcibase_bridge(node) + +#endif + +#endif diff --git a/sys/mips/nlm/hal/cop0.h b/sys/mips/nlm/hal/cop0.h new file mode 100644 index 0000000..18ecc97 --- /dev/null +++ b/sys/mips/nlm/hal/cop0.h @@ -0,0 +1,280 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_COP0_H__ +#define __NLM_COP0_H__ + +#define NLM_C0_INDEX 0 +#define NLM_C0_RANDOM 1 +#define NLM_C0_ENTRYLO0 2 +#define NLM_C0_ENTRYLO1 3 +#define NLM_C0_CONTEXT 4 +#define NLM_C0_USERLOCAL 4 +#define NLM_C0_PAGEMASK 5 +#define NLM_C0_WIRED 6 +#define NLM_C0_BADVADDR 8 +#define NLM_C0_COUNT 9 +#define NLM_C0_EIRR 9 +#define NLM_C0_EIMR 9 +#define NLM_C0_ENTRYHI 10 +#define NLM_C0_COMPARE 11 +#define NLM_C0_STATUS 12 +#define NLM_C0_INTCTL 12 +#define NLM_C0_SRSCTL 12 +#define NLM_C0_CAUSE 13 +#define NLM_C0_EPC 14 +#define NLM_C0_PRID 15 +#define NLM_C0_EBASE 15 +#define NLM_C0_CONFIG 16 +#define NLM_C0_CONFIG0 16 +#define NLM_C0_CONFIG1 16 +#define NLM_C0_CONFIG2 16 +#define NLM_C0_CONFIG3 16 +#define NLM_C0_CONFIG4 16 +#define NLM_C0_CONFIG5 16 +#define NLM_C0_CONFIG6 16 +#define NLM_C0_CONFIG7 16 +#define NLM_C0_WATCHLO 18 +#define NLM_C0_WATCHHI 19 +#define NLM_C0_XCONTEXT 20 +#define NLM_C0_SCRATCH 22 +#define NLM_C0_SCRATCH0 22 +#define NLM_C0_SCRATCH1 22 +#define NLM_C0_SCRATCH2 22 +#define NLM_C0_SCRATCH3 22 +#define NLM_C0_SCRATCH4 22 +#define NLM_C0_SCRATCH5 22 +#define NLM_C0_SCRATCH6 22 +#define NLM_C0_SCRATCH7 22 +#define NLM_C0_DEBUG 23 +#define NLM_C0_DEPC 24 +#define NLM_C0_PERFCNT 25 +#define NLM_C0_PERFCNT0 25 +#define NLM_C0_PERFCNT1 25 +#define NLM_C0_TAGLO 28 +#define NLM_C0_DATALO 28 +#define NLM_C0_TAGHI 29 +#define NLM_C0_DATAHI 29 +#define NLM_C0_ERROREPC 30 +#define NLM_C0_DESAVE 31 + +/* cop0 status bits */ +#define NLM_STATUS_CP0_EN (1<<28) +#define NLM_STATUS_CP1_EN (1<<29) +#define NLM_STATUS_CP2_EN (1<<30) +#define NLM_STATUS_KX_EN (1<<7) +#define NLM_STATUS_UX_EN (1<<5) + +#ifndef LOCORE + +#define nlm_memory_barrier() \ + __asm__ __volatile__( \ + ".set push\n\t" \ + ".set noreorder\n\t" \ + " sync\n\t" \ + ".set pop" \ + ::: "memory") + +#define NLM_DEFINE_ACCESSORS32(name, reg, sel) \ +static __inline__ uint32_t nlm_read_c0_##name(void) \ +{ \ + uint32_t __rv; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "mfc0 %0, $%1, %2\n" \ + ".set pop\n" \ + : "=r" (__rv) \ + : "i" (reg), "i" (sel) \ + ); \ + return __rv; \ +} \ + \ +static __inline__ void nlm_write_c0_##name(uint32_t val) \ +{ \ + __asm__ __volatile__( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "mtc0 %0, $%1, %2\n" \ + ".set pop\n" \ + :: "r" (val), "i" (reg), "i" (sel) \ + ); \ +} struct __hack + +/* struct __hack above swallows a semicolon - otherwise the macro + * usage below cannot have the terminating semicolon */ +#if (__mips == 64) +#define NLM_DEFINE_ACCESSORS64(name, reg, sel) \ +static __inline__ uint64_t nlm_read_c0_##name(void) \ +{ \ + uint64_t __rv; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dmfc0 %0,$%1,%2\n" \ + ".set pop\n" \ + : "=r" (__rv) \ + : "i" (reg), "i" (sel) ); \ + return __rv; \ +} \ + \ +static __inline__ void nlm_write_c0_##name(uint64_t val) \ +{ \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dmtc0 %0,$%1,%2\n" \ + ".set pop\n" \ + :: "r" (val), "i" (reg), "i" (sel) ); \ +} struct __hack + +#else + +#define NLM_DEFINE_ACCESSORS64(name, reg, sel) \ +static __inline__ uint64_t nlm_read_c0_##name(void) \ +{ \ + uint32_t __high, __low; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dmfc0 $8, $%2, %3\n" \ + "dsra32 %0, $8, 0\n" \ + "sll %1, $8, 0\n" \ + ".set pop\n" \ + : "=r"(__high), "=r"(__low) \ + : "i"(reg), "i"(sel) \ + : "$8" ); \ + \ + return (((uint64_t)__high << 32) | __low); \ +} \ + \ +static __inline__ void nlm_write_c0_##name(uint64_t val) \ +{ \ + uint32_t __high = val >> 32; \ + uint32_t __low = val & 0xffffffff; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dsll32 $8, %1, 0\n" \ + "dsll32 $9, %0, 0\n" \ + "dsrl32 $8, $8, 0\n" \ + "or $8, $8, $9\n" \ + "dmtc0 $8, $%2, %3\n" \ + ".set pop\n" \ + :: "r"(__high), "r"(__low), "i"(reg), "i"(sel) \ + : "$8", "$9"); \ +} struct __hack + +#endif + +NLM_DEFINE_ACCESSORS32(index, 0, 0); +NLM_DEFINE_ACCESSORS32(random, 1, 0); +NLM_DEFINE_ACCESSORS64(entrylo0, 2, 0); +NLM_DEFINE_ACCESSORS64(entrylo1, 3, 0); +NLM_DEFINE_ACCESSORS64(context, 4, 0); +NLM_DEFINE_ACCESSORS64(userlocal, 4, 0); +NLM_DEFINE_ACCESSORS32(pagemask, 5, 0); +NLM_DEFINE_ACCESSORS32(wired, 6, 0); +NLM_DEFINE_ACCESSORS64(badvaddr, 8, 0); +NLM_DEFINE_ACCESSORS32(count, 9, 0); +NLM_DEFINE_ACCESSORS64(eirr, 9, 6); +NLM_DEFINE_ACCESSORS64(eimr, 9, 7); +NLM_DEFINE_ACCESSORS64(entryhi, 10, 0); +NLM_DEFINE_ACCESSORS32(compare, 11, 0); +NLM_DEFINE_ACCESSORS32(status, 12, 0); +NLM_DEFINE_ACCESSORS32(intctl, 12, 1); +NLM_DEFINE_ACCESSORS32(srsctl, 12, 2); +NLM_DEFINE_ACCESSORS32(cause, 13, 0); +NLM_DEFINE_ACCESSORS64(epc, 14, 0); +NLM_DEFINE_ACCESSORS32(prid, 15, 0); +NLM_DEFINE_ACCESSORS32(ebase, 15, 1); +NLM_DEFINE_ACCESSORS32(config0, 16, 0); +NLM_DEFINE_ACCESSORS32(config1, 16, 1); +NLM_DEFINE_ACCESSORS32(config2, 16, 2); +NLM_DEFINE_ACCESSORS32(config3, 16, 3); +NLM_DEFINE_ACCESSORS32(config6, 16, 6); +NLM_DEFINE_ACCESSORS32(config7, 16, 7); +NLM_DEFINE_ACCESSORS64(watchlo0, 18, 0); +NLM_DEFINE_ACCESSORS32(watchhi0, 19, 0); +NLM_DEFINE_ACCESSORS64(xcontext, 20, 0); +NLM_DEFINE_ACCESSORS64(scratch0, 22, 0); +NLM_DEFINE_ACCESSORS64(scratch1, 22, 1); +NLM_DEFINE_ACCESSORS64(scratch2, 22, 2); +NLM_DEFINE_ACCESSORS64(scratch3, 22, 3); +NLM_DEFINE_ACCESSORS64(scratch4, 22, 4); +NLM_DEFINE_ACCESSORS64(scratch5, 22, 5); +NLM_DEFINE_ACCESSORS64(scratch6, 22, 6); +NLM_DEFINE_ACCESSORS64(scratch7, 22, 7); +NLM_DEFINE_ACCESSORS32(debug, 23, 0); +NLM_DEFINE_ACCESSORS32(depc, 24, 0); +NLM_DEFINE_ACCESSORS32(perfctrl0, 25, 0); +NLM_DEFINE_ACCESSORS64(perfcntr0, 25, 1); +NLM_DEFINE_ACCESSORS32(perfctrl1, 25, 2); +NLM_DEFINE_ACCESSORS64(perfcntr1, 25, 3); +NLM_DEFINE_ACCESSORS32(perfctrl2, 25, 4); +NLM_DEFINE_ACCESSORS64(perfcntr2, 25, 5); +NLM_DEFINE_ACCESSORS32(perfctrl3, 25, 6); +NLM_DEFINE_ACCESSORS64(perfcntr3, 25, 7); +NLM_DEFINE_ACCESSORS64(taglo0, 28, 0); +NLM_DEFINE_ACCESSORS64(taglo2, 28, 2); +NLM_DEFINE_ACCESSORS64(taghi0, 29, 0); +NLM_DEFINE_ACCESSORS64(taghi2, 29, 2); +NLM_DEFINE_ACCESSORS64(errorepc, 30, 0); +NLM_DEFINE_ACCESSORS64(desave, 31, 0); + +static __inline__ int nlm_nodeid(void) +{ + return (nlm_read_c0_ebase() >> 5) & 0x3; +} + +static __inline__ int nlm_cpuid(void) +{ + return nlm_read_c0_ebase() & 0x1f; +} + +static __inline__ int nlm_threadid(void) +{ + return nlm_read_c0_ebase() & 0x3; +} + +static __inline__ int nlm_coreid(void) +{ + return (nlm_read_c0_ebase() >> 2) & 0x7; +} + +#endif + +#endif diff --git a/sys/mips/nlm/hal/cop2.h b/sys/mips/nlm/hal/cop2.h new file mode 100644 index 0000000..062cd9d --- /dev/null +++ b/sys/mips/nlm/hal/cop2.h @@ -0,0 +1,327 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_COP2_H__ +#define __NLM_COP2_H__ + +#define XLP_COP2_TX_BUF_REG 0 +#define XLP_COP2_RX_BUF_REG 1 +#define XLP_COP2_TXMSGSTATUS_REG 2 +#define XLP_COP2_RXMSGSTATUS_REG 3 +#define XLP_COP2_MSGSTATUS1_REG 4 +#define XLP_COP2_MSGCONFIG_REG 5 +#define XLP_COP2_MSGCONFIG1_REG 6 + +#define CROSSTHR_POPQ_EN 0x01 +#define VC0_POPQ_EN 0x02 +#define VC1_POPQ_EN 0x04 +#define VC2_POPQ_EN 0x08 +#define VC3_POPQ_EN 0x10 +#define ALL_VC_POPQ_EN 0x1E +#define ALL_VC_CT_POPQ_EN 0x1F + +struct nlm_fmn_msg { + uint64_t msg[4]; +}; + +#define NLM_DEFINE_COP2_ACCESSORS32(name, reg, sel) \ +static inline uint32_t nlm_read_c2_##name(void) \ +{ \ + uint32_t __rv; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "mfc2 %0, $%1, %2\n" \ + ".set pop\n" \ + : "=r" (__rv) \ + : "i" (reg), "i" (sel) \ + ); \ + return __rv; \ +} \ + \ +static inline void nlm_write_c2_##name(uint32_t val) \ +{ \ + __asm__ __volatile__( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "mtc2 %0, $%1, %2\n" \ + ".set pop\n" \ + :: "r" (val), "i" (reg), "i" (sel) \ + ); \ +} struct __hack + +#if (__mips == 64) +#define NLM_DEFINE_COP2_ACCESSORS64(name, reg, sel) \ +static inline uint64_t nlm_read_c2_##name(void) \ +{ \ + uint64_t __rv; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dmfc2 %0, $%1, %2\n" \ + ".set pop\n" \ + : "=r" (__rv) \ + : "i" (reg), "i" (sel) ); \ + return __rv; \ +} \ + \ +static inline void nlm_write_c2_##name(uint64_t val) \ +{ \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dmtc2 %0, $%1, %2\n" \ + ".set pop\n" \ + :: "r" (val), "i" (reg), "i" (sel) ); \ +} struct __hack + +#else + +#define NLM_DEFINE_COP2_ACCESSORS64(name, reg, sel) \ +static inline uint64_t nlm_read_c2_##name(void) \ +{ \ + uint32_t __high, __low; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dmfc2 $8, $%2, %3\n" \ + "dsra32 %0, $8, 0\n" \ + "sll %1, $8, 0\n" \ + ".set pop\n" \ + : "=r"(__high), "=r"(__low) \ + : "i"(reg), "i"(sel) \ + : "$8" ); \ + \ + return (((uint64_t)__high << 32) | __low); \ +} \ + \ +static inline void nlm_write_c2_##name(uint64_t val) \ +{ \ + uint32_t __high = val >> 32; \ + uint32_t __low = val & 0xffffffff; \ + __asm__ __volatile__ ( \ + ".set push\n" \ + ".set noreorder\n" \ + ".set mips64\n" \ + "dsll32 $8, %1, 0\n" \ + "dsll32 $9, %0, 0\n" \ + "dsrl32 $8, $8, 0\n" \ + "or $8, $8, $9\n" \ + "dmtc2 $8, $%2, %3\n" \ + ".set pop\n" \ + :: "r"(__high), "r"(__low), "i"(reg), "i"(sel) \ + :"$8", "$9"); \ +} struct __hack + +#endif + +NLM_DEFINE_COP2_ACCESSORS64(txbuf0, XLP_COP2_TX_BUF_REG, 0); +NLM_DEFINE_COP2_ACCESSORS64(txbuf1, XLP_COP2_TX_BUF_REG, 1); +NLM_DEFINE_COP2_ACCESSORS64(txbuf2, XLP_COP2_TX_BUF_REG, 2); +NLM_DEFINE_COP2_ACCESSORS64(txbuf3, XLP_COP2_TX_BUF_REG, 3); + +NLM_DEFINE_COP2_ACCESSORS64(rxbuf0, XLP_COP2_RX_BUF_REG, 0); +NLM_DEFINE_COP2_ACCESSORS64(rxbuf1, XLP_COP2_RX_BUF_REG, 1); +NLM_DEFINE_COP2_ACCESSORS64(rxbuf2, XLP_COP2_RX_BUF_REG, 2); +NLM_DEFINE_COP2_ACCESSORS64(rxbuf3, XLP_COP2_RX_BUF_REG, 3); + +NLM_DEFINE_COP2_ACCESSORS32(txmsgstatus, XLP_COP2_TXMSGSTATUS_REG, 0); +NLM_DEFINE_COP2_ACCESSORS32(rxmsgstatus, XLP_COP2_RXMSGSTATUS_REG, 0); +NLM_DEFINE_COP2_ACCESSORS32(msgstatus1, XLP_COP2_MSGSTATUS1_REG, 0); +NLM_DEFINE_COP2_ACCESSORS32(msgconfig, XLP_COP2_MSGCONFIG_REG, 0); +NLM_DEFINE_COP2_ACCESSORS32(msgconfig1, XLP_COP2_MSGCONFIG1_REG, 0); + +/* successful completion returns 1, else 0 */ +static __inline__ int nlm_msgsend(int val) +{ + int result; + __asm__ volatile ( + ".set push \n" + ".set noreorder \n" + ".set mips64 \n" + "move $8, %1 \n" + "sync \n" + "/* msgsnds $9, $8 */ \n" + ".word 0x4a084801 \n" + "move %0, $9 \n" + ".set pop \n" + : "=r" (result) + : "r" (val) + : "$8", "$9" + ); + return result; +} + +static __inline__ int nlm_msgld(int vc) +{ + int val; + __asm__ volatile ( + ".set push \n" + ".set noreorder \n" + ".set mips64 \n" + "move $8, %1 \n" + "/* msgld $9, $8 */ \n" + ".word 0x4a084802 \n" + "move %0, $9 \n" + ".set pop \n" + : "=r" (val) + : "r" (vc) + : "$8", "$9" + ); + return val; +} + +static __inline__ void nlm_msgwait(int vc) +{ + __asm__ volatile ( + ".set push \n" + ".set noreorder \n" + ".set mips64 \n" + "move $8, %0 \n" + "/* msgwait $8 */ \n" + ".word 0x4a080003 \n" + ".set pop \n" + :: "r" (vc) + : "$8" + ); +} + +/* TODO this is not needed in n32 and n64 */ +static __inline uint32_t +nlm_fmn_saveflags(void) +{ + uint32_t sr = mips_rd_status(); + + mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_COP_2_BIT); + return (sr); +} + +static __inline void +nlm_fmn_restoreflags(uint32_t sr) +{ + + mips_wr_status(sr); +} + +static __inline__ int nlm_fmn_msgsend(int dstid, int size, int swcode, + struct nlm_fmn_msg *m) +{ + uint32_t flags, status; + int rv; + + size -= 1; + flags = nlm_fmn_saveflags(); + switch(size) { + case 3: nlm_write_c2_txbuf3(m->msg[3]); + case 2: nlm_write_c2_txbuf2(m->msg[2]); + case 1: nlm_write_c2_txbuf1(m->msg[1]); + case 0: nlm_write_c2_txbuf0(m->msg[0]); + } + + dstid |= ((swcode << 24) | (size << 16)); + status = nlm_msgsend(dstid); + rv = !status; + if (rv != 0) + rv = nlm_read_c2_txmsgstatus(); + nlm_fmn_restoreflags(flags); + + return (rv); +} + +static __inline__ int nlm_fmn_msgrcv(int vc, int *srcid, int *size, int *code, + struct nlm_fmn_msg *m) +{ + uint32_t status; + uint32_t msg_status, flags; + int tmp_sz, rv; + + flags = nlm_fmn_saveflags(); + status = nlm_msgld(vc); /* will return 0, if error */ + rv = !status; + if (rv == 0) { + msg_status = nlm_read_c2_rxmsgstatus(); + *size = ((msg_status >> 26) & 0x3) + 1; + *code = (msg_status >> 18) & 0xff; + *srcid = (msg_status >> 4) & 0xfff; + tmp_sz = *size - 1; + switch(tmp_sz) { + case 3: m->msg[3] = nlm_read_c2_rxbuf3(); + case 2: m->msg[2] = nlm_read_c2_rxbuf2(); + case 1: m->msg[1] = nlm_read_c2_rxbuf1(); + case 0: m->msg[0] = nlm_read_c2_rxbuf0(); + } + } + nlm_fmn_restoreflags(flags); + + return rv; +} + +/** + * nlm_fmn_cpu_init() initializes the per-h/w thread cop2 w.r.t the following + * configuration parameters. It needs to be individually setup on each + * hardware thread. + * + * int_vec - interrupt vector getting placed into msgconfig reg + * ctpe - cross thread message pop enable. When set to 1, the thread (h/w cpu) + * associated where this cop2 register is setup, can pop messages + * intended for any other thread in the same core. + * v0pe - VC0 pop message request mode enable. When set to 1, the thread + * can send pop requests to vc0. + * v1pe - VC1 pop message request mode enable. When set to 1, the thread + * can send pop requests to vc1. + * v2pe - VC2 pop message request mode enable. When set to 1, the thread + * can send pop requests to vc2. + * v3pe - VC3 pop message request mode enable. When set to 1, the thread + * can send pop requests to vc3. + */ +static __inline__ void nlm_fmn_cpu_init(int int_vec, int ctpe, int v0pe, + int v1pe, int v2pe, int v3pe) +{ + uint32_t val = nlm_read_c2_msgconfig(); + + /* Note: in XLP PRM 0.8.1, the int_vec bits are un-documented + * in msgconfig register of cop2. + * As per chip/cpu RTL, [16:20] bits consist of int_vec. + */ + val |= ((int_vec & 0x1f) << 16) | + ((v3pe & 0x1) << 4) | + ((v2pe & 0x1) << 3) | + ((v1pe & 0x1) << 2) | + ((v0pe & 0x1) << 1) | + (ctpe & 0x1); + + nlm_write_c2_msgconfig(val); +} +#endif diff --git a/sys/mips/nlm/hal/cpucontrol.h b/sys/mips/nlm/hal/cpucontrol.h new file mode 100644 index 0000000..0bc0f5b --- /dev/null +++ b/sys/mips/nlm/hal/cpucontrol.h @@ -0,0 +1,70 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_CPUCONTROL_H__ +#define __NLM_CPUCONTROL_H__ + +#define XLP_CPU_BLOCKID_IFU 0 +#define XLP_CPU_BLOCKID_ICU 1 + +#define XLP_CPU_BLOCKID_IEU 2 +#define XLP_CPU_BLOCKID_LSU 3 +#define XLP_LSU_DEFEATURE 0x304 +#define XLP_LSU_CERRLOG_REGID 0x09 + +#define XLP_CPU_BLOCKID_MMU 4 +#define XLP_CPU_BLOCKID_PRF 5 + +#define XLP_CPU_BLOCKID_SCH 7 +#define XLP_SCHED_DEFEATURE 0x700 + +#define XLP_CPU_BLOCKID_SCU 8 +#define XLP_CPU_BLOCKID_FPU 9 + +#define XLP_CPU_BLOCKID_MAP 10 + +/* Offsets of interest from the 'MAP' Block */ +#define XLP_BLKID_MAP_THREADMODE 0x00 +#define XLP_BLKID_MAP_EXT_EBASE_ENABLE 0x04 +#define XLP_BLKID_MAP_CCDI_CONFIG 0x08 +#define XLP_BLKID_MAP_THRD0_CCDI_STATUS 0x0c +#define XLP_BLKID_MAP_THRD1_CCDI_STATUS 0x10 +#define XLP_BLKID_MAP_THRD2_CCDI_STATUS 0x14 +#define XLP_BLKID_MAP_THRD3_CCDI_STATUS 0x18 +#define XLP_BLKID_MAP_THRD0_DEBUG_MODE 0x1c +#define XLP_BLKID_MAP_THRD1_DEBUG_MODE 0x20 +#define XLP_BLKID_MAP_THRD2_DEBUG_MODE 0x24 +#define XLP_BLKID_MAP_THRD3_DEBUG_MODE 0x28 +#define XLP_BLKID_MAP_MISC_STATE 0x60 +#define XLP_BLKID_MAP_DEBUG_READ_CTL 0x64 +#define XLP_BLKID_MAP_DEBUG_READ_REG0 0x68 +#define XLP_BLKID_MAP_DEBUG_READ_REG1 0x6c + +#endif /* __NLM_CPUCONTROL_H__ */ diff --git a/sys/mips/nlm/hal/fmn.c b/sys/mips/nlm/hal/fmn.c new file mode 100644 index 0000000..fd4f7c8 --- /dev/null +++ b/sys/mips/nlm/hal/fmn.c @@ -0,0 +1,789 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/fmn.h> +#include <sys/systm.h> + +uint32_t bad_xlp_num_nodes = 4; +/* XLP can take upto 16K of FMN messages per hardware queue, as spill. +* But, configuring all 16K causes the total spill memory to required +* to blow upto 192MB for single chip configuration, and 768MB in four +* chip configuration. Hence for now, we will setup the per queue spill +* as 1K FMN messages. With this, the total spill memory needed for 1024 +* hardware queues (with 12bytes per single entry FMN message) becomes +* (1*1024)*12*1024queues = 12MB. For the four chip config, the memory +* needed = 12 * 4 = 48MB. +*/ +uint64_t nlm_cms_spill_total_messages = 1 * 1024; + +/* On a XLP832, we have the following FMN stations: +* CPU stations: 8 +* PCIE0 stations: 1 +* PCIE1 stations: 1 +* PCIE2 stations: 1 +* PCIE3 stations: 1 +* GDX stations: 1 +* CRYPTO stations: 1 +* RSA stations: 1 +* CMP stations: 1 +* POE stations: 1 +* NAE stations: 1 +* ================== +* Total : 18 stations per chip +* +* For all 4 nodes, there are 18*4 = 72 FMN stations +*/ +uint32_t nlm_cms_total_stations = 18 * 4 /*xlp_num_nodes*/; +uint32_t cms_onchip_seg_availability[XLP_CMS_ON_CHIP_PER_QUEUE_SPACE]; + +int nlm_cms_verify_credit_config (int spill_en, int tot_credit) +{ + /* Note: In XLP there seem to be no mechanism to read back + * the credit count that has been programmed into a sid / did pair; + * since we have only one register 0x2000 to read. + * Hence it looks like all credit mgmt/verification needs to + * be done by software. Software could keep track of total credits + * getting programmed and verify it from this function. + */ + + if (spill_en) { + /* TODO */ + } + + if (tot_credit > (XLP_CMS_ON_CHIP_MESG_SPACE*bad_xlp_num_nodes)) + return 1; /* credits overflowed - should not happen */ + + return 0; +} + +/** + * Takes inputs as node, queue_size and maximum number of queues. + * Calculates the base, start & end and returns the same for a + * defined qid. + * + * The output queues are maintained in the internal output buffer + * which is a on-chip SRAM structure. For the actial hardware + * internal implementation, It is a structure which consists + * of eight banks of 4096-entry x message-width SRAMs. The SRAM + * implementation is designed to run at 1GHz with a 1-cycle read/write + * access. A read/write transaction can be initiated for each bank + * every cycle for a total of eight accesses per cycle. Successive + * entries of the same output queue are placed in successive banks. + * This is done to spread different read & write accesses to same/different + * output queue over as many different banks as possible so that they + * can be scheduled concurrently. Spreading the accesses to as many banks + * as possible to maximize the concurrency internally is important for + * achieving the desired peak throughput. This is done by h/w implementation + * itself. + * + * Output queues are allocated from this internal output buffer by + * software. The total capacity of the output buffer is 32K-entry. + * Each output queue can be sized from 32-entry to 1024-entry in + * increments of 32-entry. This is done by specifying a Start & a + * End pointer: pointers to the first & last 32-entry chunks allocated + * to the output queue. + * + * To optimize the storage required for 1024 OQ pointers, the upper 5-bits + * are shared by the Start & the End pointer. The side-effect of this + * optimization is that an OQ can't cross a 1024-entry boundary. Also, the + * lower 5-bits don't need to be specified in the Start & the End pointer + * as the allocation is in increments of 32-entries. + * + * Queue occupancy is tracked by a Head & a Tail pointer. Tail pointer + * indicates the location to which next entry will be written & Head + * pointer indicates the location from which next entry will be read. When + * these pointers reach the top of the allocated space (indicated by the + * End pointer), they are reset to the bottom of the allocated space + * (indicated by the Start pointer). + * + * Output queue pointer information: + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * 14 10 9 5 4 0 + * ------------------ + * | base ptr | + * ------------------ + * ---------------- + * | start ptr | + * ---------------- + * ---------------- + * | end ptr | + * ---------------- + * ------------------------------------ + * | head ptr | + * ------------------------------------ + * ------------------------------------ + * | tail ptr | + * ------------------------------------ + * Note: + * A total of 1024 segments can sit on one software-visible "bank" + * of internal SRAM. Each segment contains 32 entries. Also note + * that sw-visible "banks" are not the same as the actual internal + * 8-bank implementation of hardware. It is an optimization of + * internal access. + * + */ + +void nlm_cms_setup_credits(uint64_t base, int destid, int srcid, int credit) +{ + uint32_t val; + + val = ((credit << 24) | (destid << 12) | (srcid << 0)); + nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CREDIT_CFG_REG, val); + +} + +int nlm_cms_config_onchip_queue (uint64_t base, uint64_t spill_base, + int qid, int spill_en) +{ + + /* Configure 32 as onchip queue depth */ + nlm_cms_alloc_onchip_q(base, qid, 1); + + /* Spill configuration */ + if (spill_en) { + /* Configure 4*4KB = 16K as spill size */ + nlm_cms_alloc_spill_q(base, qid, spill_base, 4); + } + +#if 0 + /* configure credits for src cpu0, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU0_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cpu1, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU1_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cpu2, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU2_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cpu3, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU3_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cpu4, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU4_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cpu5, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU5_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cpu6, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU6_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cpu7, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CPU7_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src pcie0, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE0_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src pcie1, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE1_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src pcie2, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE2_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src pcie3, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE3_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src dte, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_DTE_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src rsa_ecc, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_RSA_ECC_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src crypto, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CRYPTO_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src cmp, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_CMP_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src poe, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_POE_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); + + /* configure credits for src nae, on this queue */ + nlm_cms_setup_credits(base, qid, XLP_CMS_NAE_SRC_STID, + XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations, + nlm_cms_spill_total_messages)); +#endif + + return 0; +} + +/* + * base - CMS module base address for this node. + * qid - is the output queue id otherwise called as vc id + * spill_base - is the 40-bit physical address of spill memory. Must be + 4KB aligned. + * nsegs - No of segments where a "1" indicates 4KB. Spill size must be + * a multiple of 4KB. + */ +int nlm_cms_alloc_spill_q(uint64_t base, int qid, uint64_t spill_base, + int nsegs) +{ + uint64_t queue_config; + uint32_t spill_start; + + if(nsegs > XLP_CMS_MAX_SPILL_SEGMENTS_PER_QUEUE) { + return 1; + } + + queue_config = nlm_rdreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid))); + + spill_start = ((spill_base >> 12) & 0x3F); + /* Spill configuration */ + queue_config = (((uint64_t)XLP_CMS_SPILL_ENA << 62) | + (((spill_base >> 18) & 0x3FFFFF) << 27) | + (spill_start + nsegs - 1) << 21 | + (spill_start << 15)); + + nlm_wreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid)),queue_config); + + return 0; +} + +/* + * base - CMS module base address for this node. + * qid - is the output queue id otherwise called as vc id + * nsegs - No of segments where a "1" indicates 32 credits. On chip + * credits must be a multiple of 32. + */ +int nlm_cms_alloc_onchip_q(uint64_t base, int qid, int nsegs) +{ + static uint32_t curr_end = 0; + uint64_t queue_config; + int onchipbase, start, last; + uint8_t i; + + if( ((curr_end + nsegs) > XLP_CMS_MAX_ONCHIP_SEGMENTS) || + (nsegs > XLP_CMS_ON_CHIP_PER_QUEUE_SPACE) ) { + /* Invalid configuration */ + return 1; + } + if(((curr_end % 32) + nsegs - 1) <= 31) { + onchipbase = (curr_end / 32); + start = (curr_end % 32); + curr_end += nsegs; + } else { + onchipbase = (curr_end / 32) + 1; + start = 0; + curr_end = ((onchipbase * 32) + nsegs); + } + last = start + nsegs - 1; + + for(i = start;i <= last;i++) { + if(cms_onchip_seg_availability[onchipbase] & (1 << i)) { + /* Conflict!!! segment is already allocated */ + return 1; + } + } + /* Update the availability bitmap as consumed */ + for(i = start; i <= last; i++) { + cms_onchip_seg_availability[onchipbase] |= (1 << i); + } + + queue_config = nlm_rdreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid))); + + /* On chip configuration */ + queue_config = (((uint64_t)XLP_CMS_QUEUE_ENA << 63) | + ((onchipbase & 0x1f) << 10) | + ((last & 0x1f) << 5) | + (start & 0x1f)); + + nlm_wreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid)),queue_config); + + return 0; +} + +void nlm_cms_default_setup(int node, uint64_t spill_base, int spill_en, + int popq_en) +{ + int j, k, vc; + int queue; + uint64_t base; + + base = nlm_regbase_cms(node); + for(j=0; j<1024; j++) { + printf("Qid:0x%04d Val:0x%016jx\n",j, (uintmax_t)nlm_cms_get_onchip_queue (base, j)); + } + /* Enable all cpu push queues */ + for (j=0; j<XLP_MAX_CORES; j++) + for (k=0; k<XLP_MAX_THREADS; k++) + for (vc=0; vc<XLP_CMS_MAX_VCPU_VC; vc++) { + /* TODO : remove this once SMP works */ + if( (j == 0) && (k == 0) ) + continue; + queue = XLP_CMS_CPU_PUSHQ(node, j, k, vc); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable pcie 0 push queue */ + for (j=XLP_CMS_PCIE0_QID(0); j<XLP_CMS_PCIE0_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable pcie 1 push queue */ + for (j=XLP_CMS_PCIE1_QID(0); j<XLP_CMS_PCIE1_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable pcie 2 push queue */ + for (j=XLP_CMS_PCIE2_QID(0); j<XLP_CMS_PCIE2_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable pcie 3 push queue */ + for (j=XLP_CMS_PCIE3_QID(0); j<XLP_CMS_PCIE3_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable DTE push queue */ + for (j=XLP_CMS_DTE_QID(0); j<XLP_CMS_DTE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable RSA/ECC push queue */ + for (j=XLP_CMS_RSA_ECC_QID(0); j<XLP_CMS_RSA_ECC_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable crypto push queue */ + for (j=XLP_CMS_CRYPTO_QID(0); j<XLP_CMS_CRYPTO_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable CMP push queue */ + for (j=XLP_CMS_CMP_QID(0); j<XLP_CMS_CMP_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable POE push queue */ + for (j=XLP_CMS_POE_QID(0); j<XLP_CMS_POE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable NAE push queue */ + for (j=XLP_CMS_NAE_QID(0); j<XLP_CMS_NAE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en); + } + + /* Enable all pop queues */ + if (popq_en) { + for (j=XLP_CMS_POPQ_QID(0); j<XLP_CMS_POPQ_MAXQID; j++) { + queue = XLP_CMS_POPQ(node, j); + nlm_cms_config_onchip_queue(base, spill_base, queue, + spill_en); + } + } +} + +uint64_t nlm_cms_get_onchip_queue (uint64_t base, int qid) +{ + return nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid)); +} + +void nlm_cms_set_onchip_queue (uint64_t base, int qid, uint64_t val) +{ + uint64_t rdval; + + rdval = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid)); + rdval |= val; + nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), rdval); +} + +void nlm_cms_per_queue_level_intr(uint64_t base, int qid, int sub_type, + int intr_val) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid)); + + val |= (((uint64_t)sub_type<<54) | + ((uint64_t)intr_val<<56)); + + nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), val); +} + +void nlm_cms_level_intr(int node, int sub_type, int intr_val) +{ + int j, k, vc; + int queue; + uint64_t base; + + base = nlm_regbase_cms(node); + /* setup level intr config on all cpu push queues */ + for (j=0; j<XLP_MAX_CORES; j++) + for (k=0; k<XLP_MAX_THREADS; k++) + for (vc=0; vc<XLP_CMS_MAX_VCPU_VC; vc++) { + queue = XLP_CMS_CPU_PUSHQ(node, j, k, vc); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all pcie 0 push queue */ + for (j=XLP_CMS_PCIE0_QID(0); j<XLP_CMS_PCIE0_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all pcie 1 push queue */ + for (j=XLP_CMS_PCIE1_QID(0); j<XLP_CMS_PCIE1_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all pcie 2 push queue */ + for (j=XLP_CMS_PCIE2_QID(0); j<XLP_CMS_PCIE2_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all pcie 3 push queue */ + for (j=XLP_CMS_PCIE3_QID(0); j<XLP_CMS_PCIE3_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all DTE push queue */ + for (j=XLP_CMS_DTE_QID(0); j<XLP_CMS_DTE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all RSA/ECC push queue */ + for (j=XLP_CMS_RSA_ECC_QID(0); j<XLP_CMS_RSA_ECC_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all crypto push queue */ + for (j=XLP_CMS_CRYPTO_QID(0); j<XLP_CMS_CRYPTO_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all CMP push queue */ + for (j=XLP_CMS_CMP_QID(0); j<XLP_CMS_CMP_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all POE push queue */ + for (j=XLP_CMS_POE_QID(0); j<XLP_CMS_POE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all NAE push queue */ + for (j=XLP_CMS_NAE_QID(0); j<XLP_CMS_NAE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } + + /* setup level intr config on all pop queues */ + for (j=XLP_CMS_POPQ_QID(0); j<XLP_CMS_POPQ_MAXQID; j++) { + queue = XLP_CMS_POPQ(node, j); + nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val); + } +} + +void nlm_cms_per_queue_timer_intr(uint64_t base, int qid, int sub_type, + int intr_val) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid)); + + val |= (((uint64_t)sub_type<<49) | + ((uint64_t)intr_val<<51)); + + nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), val); +} + +void nlm_cms_timer_intr(int node, int en, int sub_type, int intr_val) +{ + int j, k, vc; + int queue; + uint64_t base; + + base = nlm_regbase_cms(node); + /* setup timer intr config on all cpu push queues */ + for (j=0; j<XLP_MAX_CORES; j++) + for (k=0; k<XLP_MAX_THREADS; k++) + for (vc=0; vc<XLP_CMS_MAX_VCPU_VC; vc++) { + queue = XLP_CMS_CPU_PUSHQ(node, j, k, vc); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all pcie 0 push queue */ + for (j=XLP_CMS_PCIE0_QID(0); j<XLP_CMS_PCIE0_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all pcie 1 push queue */ + for (j=XLP_CMS_PCIE1_QID(0); j<XLP_CMS_PCIE1_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all pcie 2 push queue */ + for (j=XLP_CMS_PCIE2_QID(0); j<XLP_CMS_PCIE2_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all pcie 3 push queue */ + for (j=XLP_CMS_PCIE3_QID(0); j<XLP_CMS_PCIE3_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all DTE push queue */ + for (j=XLP_CMS_DTE_QID(0); j<XLP_CMS_DTE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all RSA/ECC push queue */ + for (j=XLP_CMS_RSA_ECC_QID(0); j<XLP_CMS_RSA_ECC_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all crypto push queue */ + for (j=XLP_CMS_CRYPTO_QID(0); j<XLP_CMS_CRYPTO_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all CMP push queue */ + for (j=XLP_CMS_CMP_QID(0); j<XLP_CMS_CMP_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all POE push queue */ + for (j=XLP_CMS_POE_QID(0); j<XLP_CMS_POE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all NAE push queue */ + for (j=XLP_CMS_NAE_QID(0); j<XLP_CMS_NAE_MAXQID; j++) { + queue = XLP_CMS_IO_PUSHQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } + + /* setup timer intr config on all pop queues */ + for (j=XLP_CMS_POPQ_QID(0); j<XLP_CMS_POPQ_MAXQID; j++) { + queue = XLP_CMS_POPQ(node, j); + nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val); + } +} + +/* returns 1 if interrupt has been generated for this output queue */ +int nlm_cms_outputq_intr_check(uint64_t base, int qid) +{ + uint64_t val; + val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid)); + + return ((val >> 59) & 0x1); +} + +void nlm_cms_outputq_clr_intr(uint64_t base, int qid) +{ + uint64_t val; + val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid)); + val |= (1ULL<<59); + nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), val); +} + +void nlm_cms_illegal_dst_error_intr(uint64_t base, int en) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG); + val |= (en<<8); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +void nlm_cms_timeout_error_intr(uint64_t base, int en) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG); + val |= (en<<7); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +void nlm_cms_biu_error_resp_intr(uint64_t base, int en) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG); + val |= (en<<6); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +void nlm_cms_spill_uncorrectable_ecc_error_intr(uint64_t base, int en) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG); + val |= (en<<5) | (en<<3); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +void nlm_cms_spill_correctable_ecc_error_intr(uint64_t base, int en) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG); + val |= (en<<4) | (en<<2); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +void nlm_cms_outputq_uncorrectable_ecc_error_intr(uint64_t base, int en) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG); + val |= (en<<1); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +void nlm_cms_outputq_correctable_ecc_error_intr(uint64_t base, int en) +{ + uint64_t val; + + val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG); + val |= (en<<0); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +uint64_t nlm_cms_network_error_status(uint64_t base) +{ + return nlm_rdreg_cms(base, XLP_CMS_MSG_ERR_REG); +} + +int nlm_cms_get_net_error_code(uint64_t err) +{ + return ((err >> 12) & 0xf); +} + +int nlm_cms_get_net_error_syndrome(uint64_t err) +{ + return ((err >> 32) & 0x1ff); +} + +int nlm_cms_get_net_error_ramindex(uint64_t err) +{ + return ((err >> 44) & 0x7fff); +} + +int nlm_cms_get_net_error_outputq(uint64_t err) +{ + return ((err >> 16) & 0xfff); +} + +/*========================= FMN Tracing related APIs ================*/ + +void nlm_cms_trace_setup(uint64_t base, int en, uint64_t trace_base, + uint64_t trace_limit, int match_dstid_en, + int dst_id, int match_srcid_en, int src_id, + int wrap) +{ + uint64_t val; + + nlm_wreg_cms(base, XLP_CMS_TRACE_BASE_ADDR_REG, trace_base); + nlm_wreg_cms(base, XLP_CMS_TRACE_LIMIT_ADDR_REG, trace_limit); + + val = nlm_rdreg_cms(base, XLP_CMS_TRACE_CONFIG_REG); + val |= (((uint64_t)match_dstid_en << 39) | + ((dst_id & 0xfff) << 24) | + (match_srcid_en << 23) | + ((src_id & 0xfff) << 8) | + (wrap << 1) | + (en << 0)); + nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val); +} + +void nlm_cms_endian_byte_swap (uint64_t base, int en) +{ + nlm_wreg_cms(base, XLP_CMS_MSG_ENDIAN_SWAP_REG, en); +} diff --git a/sys/mips/nlm/hal/fmn.h b/sys/mips/nlm/hal/fmn.h new file mode 100644 index 0000000..75fc774 --- /dev/null +++ b/sys/mips/nlm/hal/fmn.h @@ -0,0 +1,275 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_FMNV2_H__ +#define __NLM_FMNV2_H__ + +/** +* @file_name fmn.h +* @author Netlogic Microsystems +* @brief HAL for Fast message network V2 +*/ + +/* FMN configuration registers */ +#define XLP_CMS_OUTPUTQ_CONFIG_REG(i) ((i)*2) +#define XLP_CMS_MAX_OUTPUTQ 1024 +#define XLP_CMS_OUTPUTQ_CREDIT_CFG_REG (0x2000/4) +#define XLP_CMS_MSG_CONFIG_REG (0x2008/4) +#define XLP_CMS_MSG_ERR_REG (0x2010/4) +#define XLP_CMS_TRACE_CONFIG_REG (0x2018/4) +#define XLP_CMS_TRACE_BASE_ADDR_REG (0x2020/4) +#define XLP_CMS_TRACE_LIMIT_ADDR_REG (0x2028/4) +#define XLP_CMS_TRACE_CURRENT_ADDR_REG (0x2030/4) +#define XLP_CMS_MSG_ENDIAN_SWAP_REG (0x2038/4) + +#define XLP_CMS_CPU_PUSHQ(node, core, thread, vc) \ + (((node)<<10) | ((core)<<4) | ((thread)<<2) | ((vc)<<0)) +#define XLP_CMS_POPQ(node, queue) (((node)<<10) | (queue)) +#define XLP_CMS_IO_PUSHQ(node, queue) (((node)<<10) | (queue)) + +#define XLP_CMS_POPQ_QID(i) (128+(i)) +#define XLP_CMS_POPQ_MAXQID 255 +#define XLP_CMS_PCIE0_QID(i) (256+(i)) +#define XLP_CMS_PCIE0_MAXQID 257 +#define XLP_CMS_PCIE1_QID(i) (258+(i)) +#define XLP_CMS_PCIE1_MAXQID 259 +#define XLP_CMS_PCIE2_QID(i) (260+(i)) +#define XLP_CMS_PCIE2_MAXQID 261 +#define XLP_CMS_PCIE3_QID(i) (262+(i)) +#define XLP_CMS_PCIE3_MAXQID 263 +#define XLP_CMS_DTE_QID(i) (264+(i)) +#define XLP_CMS_DTE_MAXQID 267 +#define XLP_CMS_RSA_ECC_QID(i) (272+(i)) +#define XLP_CMS_RSA_ECC_MAXQID 280 +#define XLP_CMS_CRYPTO_QID(i) (281+(i)) +#define XLP_CMS_CRYPTO_MAXQID 296 +/* TODO PCI header register 0x3C says CMP starts at 297(0x129) VERIFY */ +#define XLP_CMS_CMP_QID(i) (298+(i)) +#define XLP_CMS_CMP_MAXQID 305 +#define XLP_CMS_POE_QID(i) (384+(i)) +#define XLP_CMS_POE_MAXQID 391 +#define XLP_CMS_NAE_QID(i) (476+(i)) +#define XLP_CMS_NAE_MAXQID 1023 + +#define XLP_CMS_NAE_TX_VC_BASE 476 +#define XLP_CMS_NAE_TX_VC_LIMIT 999 +#define XLP_CMS_NAE_RX_VC_BASE 1000 +#define XLP_CMS_NAE_RX_VC_LIMIT 1019 + +#define XLP_MAX_CMS_QUEUES 1024 + +/* FMN Level Interrupt Type */ +#define XLP_CMS_LVL_INTR_DISABLE 0 +#define XLP_CMS_LVL_LOW_WATERMARK 1 +#define XLP_CMS_LVL_HI_WATERMARK 2 + +/* FMN Level interrupt trigger values */ +#define XLP_CMS_QUEUE_NON_EMPTY 0 +#define XLP_CMS_QUEUE_QUARTER_FULL 1 +#define XLP_CMS_QUEUE_HALF_FULL 2 +#define XLP_CMS_QUEUE_THREE_QUARTER_FULL 3 +#define XLP_CMS_QUEUE_FULL 4 + +/* FMN Timer Interrupt Type */ +#define XLP_CMS_TIMER_INTR_DISABLE 0 +#define XLP_CMS_TIMER_CONSUMER 1 +#define XLP_CMS_TIMER_PRODUCER 1 + +/* FMN timer interrupt trigger values */ +#define XLP_CMS_TWO_POW_EIGHT_CYCLES 0 +#define XLP_CMS_TWO_POW_TEN_CYCLES 1 +#define XLP_CMS_TWO_POW_TWELVE_CYCLES 2 +#define XLP_CMS_TWO_POW_FOURTEEN_CYCLES 3 +#define XLP_CMS_TWO_POW_SIXTEEN_CYCLES 4 +#define XLP_CMS_TWO_POW_EIGHTTEEN_CYCLES 5 +#define XLP_CMS_TWO_POW_TWENTY_CYCLES 6 +#define XLP_CMS_TWO_POW_TWENTYTWO_CYCLES 7 + +#define XLP_CMS_QUEUE_ENA 1ULL +#define XLP_CMS_QUEUE_DIS 0 +#define XLP_CMS_SPILL_ENA 1ULL +#define XLP_CMS_SPILL_DIS 0 + +#define XLP_CMS_MAX_VCPU_VC 4 + +/* Each XLP chip can hold upto 32K messages on the chip itself */ +#define XLP_CMS_ON_CHIP_MESG_SPACE (32*1024) +#define XLP_CMS_ON_CHIP_PER_QUEUE_SPACE \ + ((XLP_CMS_ON_CHIP_MESG_SPACE)/(XLP_MAX_CMS_QUEUES)) +#define XLP_CMS_MAX_ONCHIP_SEGMENTS 1024 +#define XLP_CMS_MAX_SPILL_SEGMENTS_PER_QUEUE 64 + +/* FMN Network error */ +#define XLP_CMS_ILLEGAL_DST_ERROR 0x100 +#define XLP_CMS_BIU_TIMEOUT_ERROR 0x080 +#define XLP_CMS_BIU_ERROR 0x040 +#define XLP_CMS_SPILL_FILL_UNCORRECT_ECC_ERROR 0x020 +#define XLP_CMS_SPILL_FILL_CORRECT_ECC_ERROR 0x010 +#define XLP_CMS_SPILL_UNCORRECT_ECC_ERROR 0x008 +#define XLP_CMS_SPILL_CORRECT_ECC_ERROR 0x004 +#define XLP_CMS_OUTPUTQ_UNCORRECT_ECC_ERROR 0x002 +#define XLP_CMS_OUTPUTQ_CORRECT_ECC_ERROR 0x001 + +/* worst case, a single entry message consists of a 4 byte header + * and an 8-byte entry = 12 bytes in total + */ +#define XLP_CMS_SINGLE_ENTRY_MSG_SIZE 12 +/* total spill memory needed for one FMN queue */ +#define XLP_CMS_PER_QUEUE_SPILL_MEM(spilltotmsgs) \ + ((spilltotmsgs) * (XLP_CMS_SINGLE_ENTRY_MSG_SIZE)) +/* total spill memory needed */ +#define XLP_CMS_TOTAL_SPILL_MEM(spilltotmsgs) \ + ((XLP_CMS_PER_QUEUE_SPILL_MEM(spilltotmsgs)) * \ + (XLP_MAX_CMS_QUEUES)) +/* total number of FMN messages possible in a queue */ +#define XLP_CMS_TOTAL_QUEUE_SIZE(spilltotmsgs) \ + ((spilltotmsgs) + (XLP_CMS_ON_CHIP_PER_QUEUE_SPACE)) + +/* FMN Src station id's */ +#define XLP_CMS_CPU0_SRC_STID (0 << 4) +#define XLP_CMS_CPU1_SRC_STID (1 << 4) +#define XLP_CMS_CPU2_SRC_STID (2 << 4) +#define XLP_CMS_CPU3_SRC_STID (3 << 4) +#define XLP_CMS_CPU4_SRC_STID (4 << 4) +#define XLP_CMS_CPU5_SRC_STID (5 << 4) +#define XLP_CMS_CPU6_SRC_STID (6 << 4) +#define XLP_CMS_CPU7_SRC_STID (7 << 4) +#define XLP_CMS_PCIE0_SRC_STID 256 +#define XLP_CMS_PCIE1_SRC_STID 258 +#define XLP_CMS_PCIE2_SRC_STID 260 +#define XLP_CMS_PCIE3_SRC_STID 262 +#define XLP_CMS_DTE_SRC_STID 264 +#define XLP_CMS_RSA_ECC_SRC_STID 272 +#define XLP_CMS_CRYPTO_SRC_STID 281 +#define XLP_CMS_CMP_SRC_STID 298 +#define XLP_CMS_POE_SRC_STID 384 +#define XLP_CMS_NAE_SRC_STID 476 +#if 0 +#define XLP_CMS_DEFAULT_CREDIT(cmstotstns,spilltotmsgs) \ + ((XLP_CMS_TOTAL_QUEUE_SIZE(spilltotmsgs)) / \ + (cmstotstns)) +#endif +#define XLP_CMS_DEFAULT_CREDIT(cmstotstns,spilltotmsgs) 8 + +/* POPQ related defines */ +#define XLP_CMS_POPQID_START 128 +#define XLP_CMS_POPQID_END 255 + +#define XLP_CMS_INT_RCVD 0x800000000000000ULL + +#define nlm_rdreg_cms(b, r) nlm_read_reg64_xkseg(b,r) +#define nlm_wreg_cms(b, r, v) nlm_write_reg64_xkseg(b,r,v) +#define nlm_pcibase_cms(node) nlm_pcicfg_base(XLP_IO_CMS_OFFSET(node)) +#define nlm_regbase_cms(node) nlm_pcibar0_base_xkphys(nlm_pcibase_cms(node)) + +enum fmn_swcode { + FMN_SWCODE_CPU0=1, + FMN_SWCODE_CPU1, + FMN_SWCODE_CPU2, + FMN_SWCODE_CPU3, + FMN_SWCODE_CPU4, + FMN_SWCODE_CPU5, + FMN_SWCODE_CPU6, + FMN_SWCODE_CPU7, + FMN_SWCODE_CPU8, + FMN_SWCODE_CPU9, + FMN_SWCODE_CPU10, + FMN_SWCODE_CPU11, + FMN_SWCODE_CPU12, + FMN_SWCODE_CPU13, + FMN_SWCODE_CPU14, + FMN_SWCODE_CPU15, + FMN_SWCODE_CPU16, + FMN_SWCODE_CPU17, + FMN_SWCODE_CPU18, + FMN_SWCODE_CPU19, + FMN_SWCODE_CPU20, + FMN_SWCODE_CPU21, + FMN_SWCODE_CPU22, + FMN_SWCODE_CPU23, + FMN_SWCODE_CPU24, + FMN_SWCODE_CPU25, + FMN_SWCODE_CPU26, + FMN_SWCODE_CPU27, + FMN_SWCODE_CPU28, + FMN_SWCODE_CPU29, + FMN_SWCODE_CPU30, + FMN_SWCODE_CPU31, + FMN_SWCODE_CPU32, + FMN_SWCODE_PCIE0, + FMN_SWCODE_PCIE1, + FMN_SWCODE_PCIE2, + FMN_SWCODE_PCIE3, + FMN_SWCODE_DTE, + FMN_SWCODE_CRYPTO, + FMN_SWCODE_RSA, + FMN_SWCODE_CMP, + FMN_SWCODE_POE, + FMN_SWCODE_NAE, +}; + +extern uint64_t nlm_cms_spill_total_messages; +extern uint32_t nlm_cms_total_stations; +extern uint32_t cms_onchip_seg_availability[XLP_CMS_ON_CHIP_PER_QUEUE_SPACE]; + +extern uint64_t cms_base_addr(int node); +extern int nlm_cms_verify_credit_config (int spill_en, int tot_credit); +extern int nlm_cms_get_oc_space(int qsize, int max_queues, int qid, int *ocbase, int *ocstart, int *ocend); +extern void nlm_cms_setup_credits (uint64_t base, int destid, int srcid, int credit); +extern int nlm_cms_config_onchip_queue (uint64_t base, uint64_t cms_spill_base, int qid, int spill_en); +extern void nlm_cms_default_setup(int node, uint64_t spill_base, int spill_en, int popq_en); +extern uint64_t nlm_cms_get_onchip_queue (uint64_t base, int qid); +extern void nlm_cms_set_onchip_queue (uint64_t base, int qid, uint64_t val); +extern void nlm_cms_per_queue_level_intr(uint64_t base, int qid, int sub_type, int intr_val); +extern void nlm_cms_level_intr(int node, int sub_type, int intr_val); +extern void nlm_cms_per_queue_timer_intr(uint64_t base, int qid, int sub_type, int intr_val); +extern void nlm_cms_timer_intr(int node, int en, int sub_type, int intr_val); +extern int nlm_cms_outputq_intr_check(uint64_t base, int qid); +extern void nlm_cms_outputq_clr_intr(uint64_t base, int qid); +extern void nlm_cms_illegal_dst_error_intr(uint64_t base, int en); +extern void nlm_cms_timeout_error_intr(uint64_t base, int en); +extern void nlm_cms_biu_error_resp_intr(uint64_t base, int en); +extern void nlm_cms_spill_uncorrectable_ecc_error_intr(uint64_t base, int en); +extern void nlm_cms_spill_correctable_ecc_error_intr(uint64_t base, int en); +extern void nlm_cms_outputq_uncorrectable_ecc_error_intr(uint64_t base, int en); +extern void nlm_cms_outputq_correctable_ecc_error_intr(uint64_t base, int en); +extern uint64_t nlm_cms_network_error_status(uint64_t base); +extern int nlm_cms_get_net_error_code(uint64_t err); +extern int nlm_cms_get_net_error_syndrome(uint64_t err); +extern int nlm_cms_get_net_error_ramindex(uint64_t err); +extern int nlm_cms_get_net_error_outputq(uint64_t err); +extern void nlm_cms_trace_setup(uint64_t base, int en, uint64_t trace_base, uint64_t trace_limit, int match_dstid_en, int dst_id, int match_srcid_en, int src_id, int wrap); +extern void nlm_cms_endian_byte_swap (uint64_t base, int en); +extern uint8_t xlp_msg_send(uint8_t vc, uint8_t size); +extern int nlm_cms_alloc_spill_q(uint64_t base, int qid, uint64_t spill_base, + int nsegs); +extern int nlm_cms_alloc_onchip_q(uint64_t base, int qid, int nsegs); + +#endif diff --git a/sys/mips/nlm/hal/iomap.h b/sys/mips/nlm/hal/iomap.h new file mode 100644 index 0000000..e11dcdd --- /dev/null +++ b/sys/mips/nlm/hal/iomap.h @@ -0,0 +1,237 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_IOMAP_H__ +#define __NLM_IOMAP_H__ + +/** +* @file_name xlpiomap.h +* @author Netlogic Microsystems +* @brief Basic definitions Netlogic XLP IO BASEs +*/ + +/* ---------------------------------- + * XLP RESET Physical Address Map + * ---------------------------------- + * PCI ECFG : 0x18000000 - 0x1bffffff + * PCI CFG : 0x1c000000 - 0x1cffffff + * FLASH : 0x1fc00000 - 0x1fffffff + * ---------------------------------- + */ + +#define XLP_DEFAULT_IO_BASE 0x18000000 +#define XLP_DEFAULT_IO_BASE_KSEG1 0xb8000000 +#define XLP_IO_SIZE (64 << 20) /* Size of the ECFG Space */ +#define XLP_IO_PCI_HDRSZ 0x100 +#define XLP_IO_DEV(node, dev) ((dev) + (node) * 8) +#define XLP_HDR_OFFSET(node, bus, dev, fn) (((bus) << 20) | \ + ((XLP_IO_DEV(node, dev)) << 15) | ((fn) << 12)) + +#define XLP_IO_BRIDGE_OFFSET(node) XLP_HDR_OFFSET(node,0,0,0) +/* coherent inter chip */ +#define XLP_IO_CIC0_OFFSET(node) XLP_HDR_OFFSET(node,0,0,1) +#define XLP_IO_CIC1_OFFSET(node) XLP_HDR_OFFSET(node,0,0,2) +#define XLP_IO_CIC2_OFFSET(node) XLP_HDR_OFFSET(node,0,0,3) +#define XLP_IO_PIC_OFFSET(node) XLP_HDR_OFFSET(node,0,0,4) + +#define XLP_IO_PCIE_OFFSET(node,i) XLP_HDR_OFFSET(node,0,1,i) +#define XLP_IO_PCIE0_OFFSET(node) XLP_HDR_OFFSET(node,0,1,0) +#define XLP_IO_PCIE1_OFFSET(node) XLP_HDR_OFFSET(node,0,1,1) +#define XLP_IO_PCIE2_OFFSET(node) XLP_HDR_OFFSET(node,0,1,2) +#define XLP_IO_PCIE3_OFFSET(node) XLP_HDR_OFFSET(node,0,1,3) + +#define XLP_IO_USB_OFFSET(node, i) XLP_HDR_OFFSET(node,0,2,i) +#define XLP_IO_USB_EHCI0_OFFSET(node) XLP_HDR_OFFSET(node,0,2,0) +#define XLP_IO_USB_OHCI0_OFFSET(node) XLP_HDR_OFFSET(node,0,2,1) +#define XLP_IO_USB_OHCI1_OFFSET(node) XLP_HDR_OFFSET(node,0,2,2) +#define XLP_IO_USB_EHCI1_OFFSET(node) XLP_HDR_OFFSET(node,0,2,3) +#define XLP_IO_USB_OHCI2_OFFSET(node) XLP_HDR_OFFSET(node,0,2,4) +#define XLP_IO_USB_OHCI3_OFFSET(node) XLP_HDR_OFFSET(node,0,2,5) + +#define XLP_IO_NAE_OFFSET(node) XLP_HDR_OFFSET(node,0,3,0) +#define XLP_IO_POE_OFFSET(node) XLP_HDR_OFFSET(node,0,3,1) + +#define XLP_IO_CMS_OFFSET(node) XLP_HDR_OFFSET(node,0,4,0) + +#define XLP_IO_DMA_OFFSET(node) XLP_HDR_OFFSET(node,0,5,1) +#define XLP_IO_SEC_OFFSET(node) XLP_HDR_OFFSET(node,0,5,2) +#define XLP_IO_CMP_OFFSET(node) XLP_HDR_OFFSET(node,0,5,3) + +#define XLP_IO_UART_OFFSET(node, i) XLP_HDR_OFFSET(node,0,6,i) +#define XLP_IO_UART0_OFFSET(node) XLP_HDR_OFFSET(node,0,6,0) +#define XLP_IO_UART1_OFFSET(node) XLP_HDR_OFFSET(node,0,6,1) +#define XLP_IO_I2C_OFFSET(node, i) XLP_HDR_OFFSET(node,0,6,2+i) +#define XLP_IO_I2C0_OFFSET(node) XLP_HDR_OFFSET(node,0,6,2) +#define XLP_IO_I2C1_OFFSET(node) XLP_HDR_OFFSET(node,0,6,3) +#define XLP_IO_GPIO_OFFSET(node) XLP_HDR_OFFSET(node,0,6,4) +/* system management */ +#define XLP_IO_SYS_OFFSET(node) XLP_HDR_OFFSET(node,0,6,5) +#define XLP_IO_JTAG_OFFSET(node) XLP_HDR_OFFSET(node,0,6,6) + +#define XLP_IO_NOR_OFFSET(node) XLP_HDR_OFFSET(node,0,7,0) +#define XLP_IO_NAND_OFFSET(node) XLP_HDR_OFFSET(node,0,7,1) +#define XLP_IO_SPI_OFFSET(node) XLP_HDR_OFFSET(node,0,7,2) +/* SD flash */ +#define XLP_IO_SD_OFFSET(node) XLP_HDR_OFFSET(node,0,7,3) +#define XLP_IO_MMC_OFFSET(node, slot) ((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ) +/* PCI config header register id's */ +#define XLP_PCI_CFGREG0 0x00 +#define XLP_PCI_CFGREG1 0x01 +#define XLP_PCI_CFGREG2 0x02 +#define XLP_PCI_CFGREG3 0x03 +#define XLP_PCI_CFGREG4 0x04 +#define XLP_PCI_CFGREG5 0x05 +#define XLP_PCI_DEVINFO_REG0 0x30 +#define XLP_PCI_DEVINFO_REG1 0x31 +#define XLP_PCI_DEVINFO_REG2 0x32 +#define XLP_PCI_DEVINFO_REG3 0x33 +#define XLP_PCI_DEVINFO_REG4 0x34 +#define XLP_PCI_DEVINFO_REG5 0x35 +#define XLP_PCI_DEVINFO_REG6 0x36 +#define XLP_PCI_DEVINFO_REG7 0x37 +#define XLP_PCI_DEVSCRATCH_REG0 0x38 +#define XLP_PCI_DEVSCRATCH_REG1 0x39 +#define XLP_PCI_DEVSCRATCH_REG2 0x3a +#define XLP_PCI_DEVSCRATCH_REG3 0x3b +#define XLP_PCI_MSGSTN_REG 0x3c +#define XLP_PCI_IRTINFO_REG 0x3d +#define XLP_PCI_UCODEINFO_REG 0x3e +#define XLP_PCI_SBB_WT_REG 0x3f + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +#ifndef __NLM_NLMIO_H__ +#error iomap.h needs mmio.h to be included +#endif + +static __inline__ uint32_t +nlm_read_reg_kseg(uint64_t base, uint32_t reg) +{ + volatile uint32_t *addr = (volatile uint32_t *)(intptr_t)base + reg; + + return (*addr); +} + +static __inline__ void +nlm_write_reg_kseg(uint64_t base, uint32_t reg, uint32_t val) +{ + volatile uint32_t *addr = (volatile uint32_t *)(intptr_t)base + reg; + + *addr = val; +} + +static __inline__ uint64_t +nlm_read_reg64_kseg(uint64_t base, uint32_t reg) +{ + volatile uint64_t *addr = (volatile uint64_t *)(intptr_t)base + (reg >> 1); + + return (nlm_load_dword(addr)); +} + +static __inline__ void +nlm_write_reg64_kseg(uint64_t base, uint32_t reg, uint64_t val) +{ + volatile uint64_t *addr = (volatile uint64_t *)(intptr_t)base + (reg >> 1); + + return (nlm_store_dword(addr, val)); +} + +/* + * Routines to store 32/64 bit values to 64 bit addresses, + * used when going thru XKPHYS to access registers + */ +static __inline__ uint32_t +nlm_read_reg_xkseg(uint64_t base, uint32_t reg) +{ + uint64_t addr = base + reg * sizeof(uint32_t); + + return (nlm_load_word_daddr(addr)); +} + +static __inline__ void +nlm_write_reg_xkseg(uint64_t base, uint32_t reg, uint32_t val) +{ + uint64_t addr = base + reg * sizeof(uint32_t); + + return (nlm_store_word_daddr(addr, val)); +} + +static __inline__ uint64_t +nlm_read_reg64_xkseg(uint64_t base, uint32_t reg) +{ + uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); + + return (nlm_load_dword_daddr(addr)); +} + +static __inline__ void +nlm_write_reg64_xkseg(uint64_t base, uint32_t reg, uint64_t val) +{ + uint64_t addr = base + (reg >> 1) * sizeof(uint64_t); + + return (nlm_store_dword_daddr(addr, val)); +} + +/* Location where IO base is mapped */ +extern uint64_t nlm_pcicfg_baseaddr; + +static __inline__ uint64_t +nlm_pcicfg_base(uint32_t devoffset) +{ + return (nlm_pcicfg_baseaddr + devoffset); +} + +static __inline__ uint64_t +nlm_pcibar0_base_xkphys(uint64_t pcibase) +{ + uint64_t paddr; + + paddr = nlm_read_reg_kseg(pcibase, XLP_PCI_CFGREG4) & ~0xfu; + return (0x9000000000000000 | paddr); +} +#define nlm_pci_rdreg(b, r) nlm_read_reg_kseg(b, r) +#define nlm_pci_wreg(b, r, v) nlm_write_reg_kseg(b, r, v) + +#endif /* !LOCORE && !__ASSEMBLY__*/ + + +/* COMPAT stuff - TODO remove */ +#define bit_set(p, m) ((p) |= (m)) +#define bit_clear(p, m) ((p) &= ~(m)) +#define bit_get(p,m) ((p) & (m)) +#define BIT(x) (0x01 << (x)) + +#define XLP_MAX_NODES 4 +#define XLP_MAX_CORES 8 +#define XLP_MAX_THREADS 4 +#define XLP_CACHELINE_SIZE 64 +#define XLP_NUM_NODES 1 /* we support only one now */ + +#endif diff --git a/sys/mips/nlm/hal/mips-extns.h b/sys/mips/nlm/hal/mips-extns.h new file mode 100644 index 0000000..7851b1b --- /dev/null +++ b/sys/mips/nlm/hal/mips-extns.h @@ -0,0 +1,200 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_MIPS_EXTNS_H__ +#define __NLM_MIPS_EXTNS_H__ + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) +static __inline__ int32_t nlm_swapw(int32_t *loc, int32_t val) +{ + int32_t oldval = 0; + + __asm__ __volatile__ ( + ".set push\n" + ".set noreorder\n" + "move $9, %2\n" + "move $8, %3\n" + ".word 0x71280014\n" /* "swapw $8, $9\n" */ + "move %1, $8\n" + ".set pop\n" + : "+m" (*loc), "=r" (oldval) + : "r" (loc), "r" (val) + : "$8", "$9" ); + + return oldval; +} + +static __inline__ uint32_t nlm_swapwu(int32_t *loc, uint32_t val) +{ + uint32_t oldval; + + __asm__ __volatile__ ( + ".set push\n" + ".set noreorder\n" + "move $9, %2\n" + "move $8, %3\n" + ".word 0x71280015\n" /* "swapwu $8, $9\n" */ + "move %1, $8\n" + ".set pop\n" + : "+m" (*loc), "=r" (oldval) + : "r" (loc), "r" (val) + : "$8", "$9" ); + + return oldval; +} + +#if (__mips == 64) +static __inline__ uint64_t nlm_swapd(int32_t *loc, uint64_t val) +{ + uint64_t oldval; + + __asm__ __volatile__ ( + ".set push\n" + ".set noreorder\n" + "move $9, %2\n" + "move $8, %3\n" + ".word 0x71280014\n" /* "swapw $8, $9\n" */ + "move %1, $8\n" + ".set pop\n" + : "+m" (*loc), "=r" (oldval) + : "r" (loc), "r" (val) + : "$8", "$9" ); + + return oldval; +} +#endif + +#if defined(__mips_n64) || defined(__mips_n32) +static __inline uint64_t +nlm_mfcr(uint32_t reg) +{ + uint64_t res; + + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + "move $9, %1\n\t" + ".word 0x71280018\n\t" /* mfcr $8, $9 */ + "move %0, $8\n\t" + ".set pop\n" + : "=r" (res) : "r"(reg) + : "$8", "$9" + ); + return (res); +} + +static __inline void +nlm_mtcr(uint32_t reg, uint64_t value) +{ + __asm__ __volatile__( + ".set push\n\t" + ".set noreorder\n\t" + "move $8, %0\n" + "move $9, %1\n" + ".word 0x71280019\n" /* mtcr $8, $9 */ + ".set pop\n" + : + : "r" (value), "r" (reg) + : "$8", "$9" + ); +} + +#else /* !(defined(__mips_n64) || defined(__mips_n32)) */ + +static __inline__ uint64_t +nlm_mfcr(uint32_t reg) +{ + uint64_t hi; + uint64_t lo; + + __asm__ __volatile__ ( + ".set push\n" + ".set mips64\n" + "move $8, %2\n" + ".word 0x71090018\n" + "nop \n" + "dsra32 %0, $9, 0\n" + "sll %1, $9, 0\n" + ".set pop\n" + : "=r"(hi), "=r"(lo) + : "r"(reg) : "$8", "$9"); + + return (((uint64_t)hi) << 32) | lo; +} + +static __inline__ void +nlm_mtcr(uint32_t reg, uint64_t val) +{ + uint32_t hi, lo; + hi = val >> 32; + lo = val & 0xffffffff; + + __asm__ __volatile__ ( + ".set push\n" + ".set mips64\n" + "move $9, %0\n" + "dsll32 $9, %1, 0\n" + "dsll32 $8, %0, 0\n" + "dsrl32 $9, $9, 0\n" + "or $9, $9, $8\n" + "move $8, %2\n" + ".word 0x71090019\n" + "nop \n" + ".set pop\n" + ::"r"(hi), "r"(lo), "r"(reg) + : "$8", "$9"); +} +#endif /* (defined(__mips_n64) || defined(__mips_n32)) */ + +/* dcrc2 */ +/* XLP additional instructions */ + +/* + * Atomic increment a unsigned int + */ +static __inline unsigned int +nlm_ldaddwu(unsigned int value, unsigned int *addr) +{ + __asm__ __volatile__( + ".set push\n" + ".set noreorder\n" + "move $8, %2\n" + "move $9, %3\n" + ".word 0x71280011\n" /* ldaddwu $8, $9 */ + "move %0, $8\n" + ".set pop\n" + : "=&r"(value), "+m"(*addr) + : "0"(value), "r" ((unsigned long)addr) + : "$8", "$9"); + + return (value); +} +#endif +#endif diff --git a/sys/mips/nlm/hal/mmio.h b/sys/mips/nlm/hal/mmio.h new file mode 100644 index 0000000..a19a867 --- /dev/null +++ b/sys/mips/nlm/hal/mmio.h @@ -0,0 +1,338 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_NLMIO_H__ +#define __NLM_NLMIO_H__ + +#if !defined(__mips_n32) && !defined(__mips_n64) +/* + * For o32 compilation, we have to disable interrupts and enable KX bit to + * access 64 bit addresses or data. + * + * We need to disable interrupts because we save just the lower 32 bits of + * registers in interrupt handling. So if we get hit by an interrupt while + * using the upper 32 bits of a register, we lose. + */ +static __inline__ uint32_t nlm_enable_kx(void) +{ + uint32_t sr; + + __asm__ __volatile__( + "mfc0 %0, $12 \n\t" /* read status reg */ + "move $8, %0 \n\t" + "ori $8, $8, 0x81 \n\t" /* set KX, and IE */ + "xori $8, $8, 0x1 \n\t" /* flip IE */ + "mtc0 $8, $12 \n\t" /* update status reg */ + : "=r"(sr) + : : "$8"); + + return (sr); +} + +static __inline__ void nlm_restore_kx(uint32_t sr) +{ + __asm__ __volatile__("mtc0 %0, $12" : : "r"(sr)); +} +#endif + +static __inline__ uint32_t +nlm_load_word(volatile uint32_t *addr) +{ + return (*addr); +} + +static __inline__ void +nlm_store_word(volatile uint32_t *addr, uint32_t val) +{ + *addr = val; +} + +#if defined(__mips_n64) || defined(__mips_n32) +static __inline__ uint64_t +nlm_load_dword(volatile uint64_t *addr) +{ + return (*addr); +} + +static __inline__ void +nlm_store_dword(volatile uint64_t *addr, uint64_t val) +{ + *addr = val; +} + +#else /* o32 */ +static __inline__ uint64_t +nlm_load_dword(volatile uint64_t *addr) +{ + uint32_t valhi, vallo, sr; + + sr = nlm_enable_kx(); + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "ld $8, 0(%2) \n\t" + "dsra32 %0, $8, 0 \n\t" + "sll %1, $8, 0 \n\t" + ".set pop \n" + : "=r"(valhi), "=r"(vallo) + : "r"(addr) + : "$8" ); + nlm_restore_kx(sr); + + return (((uint64_t)valhi << 32) | vallo); +} + +static __inline__ void +nlm_store_dword(volatile uint64_t *addr, uint64_t val) +{ + uint32_t valhi, vallo, sr; + + valhi = val >> 32; + vallo = val & 0xffffffff; + + sr = nlm_enable_kx(); + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "dsll32 $8, %1, 0 \n\t" + "dsll32 $9, %2, 0 \n\t" /* get rid of the */ + "dsrl32 $9, $9, 0 \n\t" /* sign extend */ + "or $9, $9, $8 \n\t" + "sd $9, 0(%0) \n\t" + ".set pop \n" + : : "r"(addr), "r"(valhi), "r"(vallo) + : "$8", "$9", "memory"); + nlm_restore_kx(sr); +} +#endif + +#if defined(__mips_n64) +static __inline__ uint64_t +nlm_load_word_daddr(uint64_t addr) +{ + volatile uint32_t *p = (volatile uint32_t *)(intptr_t)addr; + + return (*p); +} + +static __inline__ void +nlm_store_word_daddr(uint64_t addr, uint32_t val) +{ + volatile uint32_t *p = (volatile uint32_t *)(intptr_t)addr; + + *p = val; +} + +static __inline__ uint64_t +nlm_load_dword_daddr(uint64_t addr) +{ + volatile uint64_t *p = (volatile uint64_t *)(intptr_t)addr; + + return (*p); +} + +static __inline__ void +nlm_store_dword_daddr(uint64_t addr, uint64_t val) +{ + volatile uint64_t *p = (volatile uint64_t *)(intptr_t)addr; + + *p = val; +} + +#elif defined(__mips_n32) + +static __inline__ uint64_t +nlm_load_word_daddr(uint64_t addr) +{ + uint32_t val; + + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "lw %0, 0(%1) \n\t" + ".set pop \n" + : "=r"(val) + : "r"(addr)); + + return (val); +} + +static __inline__ void +nlm_store_word_daddr(uint64_t addr, uint32_t val) +{ + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "sw %0, 0(%1) \n\t" + ".set pop \n" + : : "r"(val), "r"(addr) + : "memory"); +} + +static __inline__ uint64_t +nlm_load_dword_daddr(uint64_t addr) +{ + uint64_t val; + + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "ld %0, 0(%1) \n\t" + ".set pop \n" + : "=r"(val) + : "r"(addr)); + return (val); +} + +static __inline__ void +nlm_store_dword_daddr(uint64_t addr, uint64_t val) +{ + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "sd %0, 0(%1) \n\t" + ".set pop \n" + : : "r"(val), "r"(addr) + : "memory"); +} + +#else /* o32 */ +static __inline__ uint64_t +nlm_load_word_daddr(uint64_t addr) +{ + uint32_t val, addrhi, addrlo, sr; + + addrhi = addr >> 32; + addrlo = addr & 0xffffffff; + + sr = nlm_enable_kx(); + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "dsll32 $8, %1, 0 \n\t" + "dsll32 $9, %2, 0 \n\t" /* get rid of the */ + "dsrl32 $9, $9, 0 \n\t" /* sign extend */ + "or $9, $9, $8 \n\t" + "lw %0, 0($9) \n\t" + ".set pop \n" + : "=r"(val) + : "r"(addrhi), "r"(addrlo) + : "$8", "$9"); + nlm_restore_kx(sr); + + return (val); + +} + +static __inline__ void +nlm_store_word_daddr(uint64_t addr, uint32_t val) +{ + uint32_t addrhi, addrlo, sr; + + addrhi = addr >> 32; + addrlo = addr & 0xffffffff; + + sr = nlm_enable_kx(); + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "dsll32 $8, %1, 0 \n\t" + "dsll32 $9, %2, 0 \n\t" /* get rid of the */ + "dsrl32 $9, $9, 0 \n\t" /* sign extend */ + "or $9, $9, $8 \n\t" + "sw %0, 0($9) \n\t" + ".set pop \n" + :: "r"(val), "r"(addrhi), "r"(addrlo) + : "$8", "$9", "memory"); + nlm_restore_kx(sr); +} + +static __inline__ uint64_t +nlm_load_dword_daddr(uint64_t addr) +{ + uint32_t addrh, addrl, sr; + uint32_t valh, vall; + + addrh = addr >> 32; + addrl = addr & 0xffffffff; + + sr = nlm_enable_kx(); + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "dsll32 $8, %2, 0 \n\t" + "dsll32 $9, %3, 0 \n\t" /* get rid of the */ + "dsrl32 $9, $9, 0 \n\t" /* sign extend */ + "or $9, $9, $8 \n\t" + "ld $8, 0($9) \n\t" + "dsra32 %0, $8, 0 \n\t" + "sll %1, $8, 0 \n\t" + ".set pop \n" + : "=r"(valh), "=r"(vall) + : "r"(addrh), "r"(addrl) + : "$8", "$9"); + nlm_restore_kx(sr); + + return (((uint64_t)valh << 32) | vall); +} + +static __inline__ void +nlm_store_dword_daddr(uint64_t addr, uint64_t val) +{ + uint32_t addrh, addrl, sr; + uint32_t valh, vall; + + addrh = addr >> 32; + addrl = addr & 0xffffffff; + valh = val >> 32; + vall = val & 0xffffffff; + + sr = nlm_enable_kx(); + __asm__ __volatile__( + ".set push \n\t" + ".set mips64 \n\t" + "dsll32 $8, %2, 0 \n\t" + "dsll32 $9, %3, 0 \n\t" /* get rid of the */ + "dsrl32 $9, $9, 0 \n\t" /* sign extend */ + "or $9, $9, $8 \n\t" + "dsll32 $8, %0, 0 \n\t" + "dsll32 $10, %1, 0 \n\t" /* get rid of the */ + "dsrl32 $10, $10, 0 \n\t" /* sign extend */ + "or $8, $8, $10 \n\t" + "sd $8, 0($9) \n\t" + ".set pop \n" + : : "r"(valh), "r"(vall), "r"(addrh), "r"(addrl) + : "$8", "$9", "memory"); + nlm_restore_kx(sr); +} + +#endif /* __mips_n64 */ + +#endif diff --git a/sys/mips/nlm/hal/mmu.h b/sys/mips/nlm/hal/mmu.h new file mode 100644 index 0000000..a620727 --- /dev/null +++ b/sys/mips/nlm/hal/mmu.h @@ -0,0 +1,204 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __XLP_MMU_H__ +#define __XLP_MMU_H__ + +#include <mips/nlm/hal/cop0.h> +#include <mips/nlm/hal/mips-extns.h> + +#define XLP_MMU_SETUP_REG 0x400 +#define XLP_MMU_LFSRSEED_REG 0x401 +#define XLP_MMU_HPW_NUM_PAGE_LVL_REG 0x410 +#define XLP_MMU_PGWKR_PGDBASE_REG 0x411 +#define XLP_MMU_PGWKR_PGDSHFT_REG 0x412 +#define XLP_MMU_PGWKR_PGDMASK_REG 0x413 +#define XLP_MMU_PGWKR_PUDSHFT_REG 0x414 +#define XLP_MMU_PGWKR_PUDMASK_REG 0x415 +#define XLP_MMU_PGWKR_PMDSHFT_REG 0x416 +#define XLP_MMU_PGWKR_PMDMASK_REG 0x417 +#define XLP_MMU_PGWKR_PTESHFT_REG 0x418 +#define XLP_MMU_PGWKR_PTEMASK_REG 0x419 + +typedef struct hw_pagewalker { + int pgd_present; + int pud_present; + int pmd_present; + int pte_present; + uint64_t pgd_baseaddr; + uint32_t pgd_shift; + uint32_t pgd_mask; + uint32_t pud_shift; + uint32_t pud_mask; + uint32_t pmd_shift; + uint32_t pmd_mask; + uint32_t pte_shift; + uint32_t pte_mask; +} nlm_pagewalker; + +/** + * On power on reset, XLP comes up with 64 TLBs. + * Large-variable-tlb's (ELVT) and extended TLB is disabled. + * Enabling large-variable-tlb's sets up the standard + * TLB size from 64 to 128 TLBs. + * Enabling fixed TLB (EFT) sets up an additional 2048 tlbs. + * ELVT + EFT = 128 + 2048 = 2176 TLB entries. + * threads 64-entry-standard-tlb 128-entry-standard-tlb + * per std-tlb-only| std+EFT | std-tlb-only| std+EFT + * core | | | + * -------------------------------------------------------- + * 1 64 64+2048 128 128+2048 + * 2 64 64+1024 64 64+1024 + * 4 32 32+512 32 32+512 + * + * 1(G) 64 64+2048 128 128+2048 + * 2(G) 128 128+2048 128 128+2048 + * 4(G) 128 128+2048 128 128+2048 + * (G) = Global mode + */ + + +/* en = 1 to enable + * en = 0 to disable + */ +static __inline__ void nlm_large_variable_tlb_en (int en) +{ + unsigned int val; + + val = nlm_read_c0_config6(); + val |= (en << 5); + nlm_write_c0_config6(val); + return; +} + +/* en = 1 to enable + * en = 0 to disable + */ +static __inline__ void nlm_pagewalker_en (int en) +{ + unsigned int val; + + val = nlm_read_c0_config6(); + val |= (en << 3); + nlm_write_c0_config6(val); + return; +} + +/* en = 1 to enable + * en = 0 to disable + */ +static __inline__ void nlm_extended_tlb_en (int en) +{ + unsigned int val; + + val = nlm_read_c0_config6(); + val |= (en << 2); + nlm_write_c0_config6(val); + return; +} + +static __inline__ int nlm_get_num_combined_tlbs(void) +{ + return (((nlm_read_c0_config6() >> 16) & 0xffff) + 1); +} + +/* get number of variable TLB entries */ +static __inline__ int nlm_get_num_vtlbs(void) +{ + return (((nlm_read_c0_config6() >> 6) & 0x3ff) + 1); +} + +static __inline__ void nlm_setup_extended_pagemask (int mask) +{ + nlm_write_c0_config7(mask); +} + +/* hashindex_en = 1 to enable hash mode, hashindex_en=0 to disable + * global_mode = 1 to enable global mode, global_mode=0 to disable + * clk_gating = 0 to enable clock gating, clk_gating=1 to disable + */ +static __inline__ void nlm_mmu_setup(int hashindex_en, int global_mode, + int clk_gating) +{ + /*uint32_t mmusetup = nlm_mfcr(XLP_MMU_SETUP_REG);*/ + + uint32_t mmusetup = 0; + mmusetup |= (hashindex_en << 13); + mmusetup |= (clk_gating << 3); + mmusetup |= (global_mode << 0); + nlm_mtcr(XLP_MMU_SETUP_REG, mmusetup); +} + +static __inline__ void nlm_mmu_lfsr_seed (int thr0_seed, int thr1_seed, + int thr2_seed, int thr3_seed) +{ + uint32_t seed = nlm_mfcr(XLP_MMU_LFSRSEED_REG); + seed |= ((thr3_seed & 0x7f) << 23); + seed |= ((thr2_seed & 0x7f) << 16); + seed |= ((thr1_seed & 0x7f) << 7); + seed |= ((thr0_seed & 0x7f) << 0); + nlm_mtcr(XLP_MMU_LFSRSEED_REG, seed); +} + +static __inline__ void nlm_pagewalker_setup (nlm_pagewalker *walker) +{ + uint64_t val; + + if (!walker->pgd_present) + return; + + val = nlm_mfcr(XLP_MMU_HPW_NUM_PAGE_LVL_REG); + + if (walker->pgd_present) + val |= (1 << 3); + + if (walker->pud_present) + val |= (1 << 2); + + if (walker->pmd_present) + val |= (1 << 1); + + if (walker->pte_present) + val |= (1 << 0); + + nlm_mtcr(XLP_MMU_HPW_NUM_PAGE_LVL_REG, val); + + nlm_mtcr(XLP_MMU_PGWKR_PGDBASE_REG, walker->pgd_baseaddr); + nlm_mtcr(XLP_MMU_PGWKR_PGDSHFT_REG, walker->pgd_shift); + nlm_mtcr(XLP_MMU_PGWKR_PGDMASK_REG, walker->pgd_mask); + nlm_mtcr(XLP_MMU_PGWKR_PUDSHFT_REG, walker->pud_shift); + nlm_mtcr(XLP_MMU_PGWKR_PUDMASK_REG, walker->pud_mask); + nlm_mtcr(XLP_MMU_PGWKR_PMDSHFT_REG, walker->pmd_shift); + nlm_mtcr(XLP_MMU_PGWKR_PMDMASK_REG, walker->pmd_mask); + nlm_mtcr(XLP_MMU_PGWKR_PTESHFT_REG, walker->pte_shift); + nlm_mtcr(XLP_MMU_PGWKR_PTEMASK_REG, walker->pte_mask); +} + +#endif diff --git a/sys/mips/nlm/hal/pic.h b/sys/mips/nlm/hal/pic.h new file mode 100644 index 0000000..842a367 --- /dev/null +++ b/sys/mips/nlm/hal/pic.h @@ -0,0 +1,427 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __XLP_PIC_H__ +#define __XLP_PIC_H__ + +/* PIC Specific registers */ +#define XLP_PIC_CTRL_REG 0x40 +#define XLP_PIC_BYTESWAP_REG 0x42 +#define XLP_PIC_STATUS_REG 0x44 +#define XLP_PIC_INTR_TIMEOUT 0x46 +#define XLP_PIC_ICI0_INTR_TIMEOUT 0x48 +#define XLP_PIC_ICI1_INTR_TIMEOUT 0x4a +#define XLP_PIC_ICI2_INTR_TIMEOUT 0x4c +#define XLP_PIC_IPI_CTRL_REG 0x4e +#define XLP_PIC_INT_ACK_REG 0x50 +#define XLP_PIC_INT_PENDING0_REG 0x52 +#define XLP_PIC_INT_PENDING1_REG 0x54 +#define XLP_PIC_INT_PENDING2_REG 0x56 + +#define XLP_PIC_WDOG0_MAXVAL_REG 0x58 +#define XLP_PIC_WDOG0_COUNT_REG 0x5a +#define XLP_PIC_WDOG0_ENABLE0_REG 0x5c +#define XLP_PIC_WDOG0_ENABLE1_REG 0x5e +#define XLP_PIC_WDOG0_BEATCMD_REG 0x60 +#define XLP_PIC_WDOG0_BEAT0_REG 0x62 +#define XLP_PIC_WDOG0_BEAT1_REG 0x64 + +#define XLP_PIC_WDOG1_MAXVAL_REG 0x66 +#define XLP_PIC_WDOG1_COUNT_REG 0x68 +#define XLP_PIC_WDOG1_ENABLE0_REG 0x6a +#define XLP_PIC_WDOG1_ENABLE1_REG 0x6c +#define XLP_PIC_WDOG1_BEATCMD_REG 0x6e +#define XLP_PIC_WDOG1_BEAT0_REG 0x70 +#define XLP_PIC_WDOG1_BEAT1_REG 0x72 + +#define XLP_PIC_WDOG_MAXVAL_REG(i) (XLP_PIC_WDOG0_MAXVAL_REG + ((i) ? 7 : 0)) +#define XLP_PIC_WDOG_COUNT_REG(i) (XLP_PIC_WDOG0_COUNT_REG + ((i) ? 7 : 0)) +#define XLP_PIC_WDOG_ENABLE0_REG(i) (XLP_PIC_WDOG0_ENABLE0_REG + ((i) ? 7 : 0)) +#define XLP_PIC_WDOG_ENABLE1_REG(i) (XLP_PIC_WDOG0_ENABLE1_REG + ((i) ? 7 : 0)) +#define XLP_PIC_WDOG_BEATCMD_REG(i) (XLP_PIC_WDOG0_BEATCMD_REG + ((i) ? 7 : 0)) +#define XLP_PIC_WDOG_BEAT0_REG(i) (XLP_PIC_WDOG0_BEAT0_REG + ((i) ? 7 : 0)) +#define XLP_PIC_WDOG_BEAT1_REG(i) (XLP_PIC_WDOG0_BEAT1_REG + ((i) ? 7 : 0)) + +#define XLP_PIC_SYSTIMER0_MAXVAL_REG 0x74 +#define XLP_PIC_SYSTIMER1_MAXVAL_REG 0x76 +#define XLP_PIC_SYSTIMER2_MAXVAL_REG 0x78 +#define XLP_PIC_SYSTIMER3_MAXVAL_REG 0x7a +#define XLP_PIC_SYSTIMER4_MAXVAL_REG 0x7c +#define XLP_PIC_SYSTIMER5_MAXVAL_REG 0x7e +#define XLP_PIC_SYSTIMER6_MAXVAL_REG 0x80 +#define XLP_PIC_SYSTIMER7_MAXVAL_REG 0x82 +#define XLP_PIC_SYSTIMER_MAXVAL_REG(i) (XLP_PIC_SYSTIMER0_MAXVAL_REG + ((i)*2)) + +#define XLP_PIC_SYSTIMER0_COUNT_REG 0x84 +#define XLP_PIC_SYSTIMER1_COUNT_REG 0x86 +#define XLP_PIC_SYSTIMER2_COUNT_REG 0x88 +#define XLP_PIC_SYSTIMER3_COUNT_REG 0x8a +#define XLP_PIC_SYSTIMER4_COUNT_REG 0x8c +#define XLP_PIC_SYSTIMER5_COUNT_REG 0x8e +#define XLP_PIC_SYSTIMER6_COUNT_REG 0x90 +#define XLP_PIC_SYSTIMER7_COUNT_REG 0x92 +#define XLP_PIC_SYSTIMER_COUNT_REG(i) (XLP_PIC_SYSTIMER0_COUNT_REG + ((i)*2)) + +#define XLP_PIC_ITE0_N0_N1_REG 0x94 +#define XLP_PIC_ITE1_N0_N1_REG 0x98 +#define XLP_PIC_ITE2_N0_N1_REG 0x9c +#define XLP_PIC_ITE3_N0_N1_REG 0xa0 +#define XLP_PIC_ITE4_N0_N1_REG 0xa4 +#define XLP_PIC_ITE5_N0_N1_REG 0xa8 +#define XLP_PIC_ITE6_N0_N1_REG 0xac +#define XLP_PIC_ITE7_N0_N1_REG 0xb0 +#define XLP_PIC_ITE_N0_N1_REG(i) (XLP_PIC_ITE0_N0_N1_REG + ((i)*4)) + +#define XLP_PIC_ITE0_N2_N3_REG 0x96 +#define XLP_PIC_ITE1_N2_N3_REG 0x9a +#define XLP_PIC_ITE2_N2_N3_REG 0x9e +#define XLP_PIC_ITE3_N2_N3_REG 0xa2 +#define XLP_PIC_ITE4_N2_N3_REG 0xa6 +#define XLP_PIC_ITE5_N2_N3_REG 0xaa +#define XLP_PIC_ITE6_N2_N3_REG 0xae +#define XLP_PIC_ITE7_N2_N3_REG 0xb2 +#define XLP_PIC_ITE_N2_N3_REG(i) (XLP_PIC_ITE0_N2_N3_REG + ((i)*4)) + +#define XLP_PIC_IRT0_REG 0xb4 +#define XLP_PIC_IRT_REG(i) (XLP_PIC_IRT0_REG + ((i)*2)) + +/* PIC IRT indices */ + +#define XLP_PIC_IRT_WD0_INDEX 0 +#define XLP_PIC_IRT_WD1_INDEX 1 +#define XLP_PIC_IRT_WD_NMI0_INDEX 2 +#define XLP_PIC_IRT_WD_NMI1_INDEX 3 +#define XLP_PIC_IRT_TIMER0_INDEX 4 +#define XLP_PIC_IRT_TIMER1_INDEX 5 +#define XLP_PIC_IRT_TIMER2_INDEX 6 +#define XLP_PIC_IRT_TIMER3_INDEX 7 +#define XLP_PIC_IRT_TIMER4_INDEX 8 +#define XLP_PIC_IRT_TIMER5_INDEX 9 +#define XLP_PIC_IRT_TIMER6_INDEX 10 +#define XLP_PIC_IRT_TIMER7_INDEX 11 +#define XLP_PIC_IRT_TIMER_INDEX(i) (XLP_PIC_IRT_TIMER0_INDEX + (i)) + +#define XLP_PIC_IRT_MSGQ0_INDEX 12 +#define XLP_PIC_IRT_MSGQ_INDEX(i) (XLP_PIC_IRT_MSGQ0_INDEX + (i)) +/* 12 to 43 */ +#define XLP_PIC_IRT_MSG0_INDEX 44 +#define XLP_PIC_IRT_MSG1_INDEX 45 + +#define XLP_PIC_IRT_PCIE_MSIX0_INDEX 46 +#define XLP_PIC_IRT_PCIE_MSIX_INDEX(i) (XLP_PIC_IRT_PCIE_MSIX0_INDEX + (i)) +/* 46 to 77 */ +#define XLP_PIC_IRT_PCIE_LINK0_INDEX 78 +#define XLP_PIC_IRT_PCIE_LINK1_INDEX 79 +#define XLP_PIC_IRT_PCIE_LINK2_INDEX 80 +#define XLP_PIC_IRT_PCIE_LINK3_INDEX 81 +#define XLP_PIC_IRT_PCIE_LINK_INDEX(i) (XLP_PIC_IRT_PCIE_LINK0_INDEX + (i)) +/* 78 to 81 */ +#define XLP_PIC_IRT_NA0_INDEX 82 +#define XLP_PIC_IRT_NA_INDEX(i) (XLP_PIC_IRT_NA0_INDEX + (i)) +/* 82 to 113 */ +#define XLP_PIC_IRT_POE_INDEX 114 +#define XLP_PIC_IRT_USB0_INDEX 115 +#define XLP_PIC_IRT_EHCI0_INDEX 115 +#define XLP_PIC_IRT_EHCI1_INDEX 118 +#define XLP_PIC_IRT_USB_INDEX(i) (XLP_PIC_IRT_USB0_INDEX + (i)) +/* 115 to 120 */ +#define XLP_PIC_IRT_GDX_INDEX 121 +#define XLP_PIC_IRT_SEC_INDEX 122 +#define XLP_PIC_IRT_RSA_INDEX 123 +#define XLP_PIC_IRT_COMP0_INDEX 124 +#define XLP_PIC_IRT_COMP_INDEX(i) (XLP_PIC_IRT_COMP0_INDEX + (i)) +/* 124 to 127 */ +#define XLP_PIC_IRT_GBU_INDEX 128 +/* coherent inter chip */ +#define XLP_PIC_IRT_CIC0_INDEX 129 +#define XLP_PIC_IRT_CIC1_INDEX 130 +#define XLP_PIC_IRT_CIC2_INDEX 131 +#define XLP_PIC_IRT_CAM_INDEX 132 +#define XLP_PIC_IRT_UART0_INDEX 133 +#define XLP_PIC_IRT_UART1_INDEX 134 +#define XLP_PIC_IRT_I2C0_INDEX 135 +#define XLP_PIC_IRT_I2C1_INDEX 136 +#define XLP_PIC_IRT_SYS0_INDEX 137 +#define XLP_PIC_IRT_SYS1_INDEX 138 +#define XLP_PIC_IRT_JTAG_INDEX 139 +#define XLP_PIC_IRT_PIC_INDEX 140 +#define XLP_PIC_IRT_NBU_INDEX 141 +#define XLP_PIC_IRT_TCU_INDEX 142 +/* global coherency */ +#define XLP_PIC_IRT_GCU_INDEX 143 +#define XLP_PIC_IRT_DMC0_INDEX 144 +#define XLP_PIC_IRT_DMC1_INDEX 145 +#define XLP_PIC_IRT_GPIO0_INDEX 146 +#define XLP_PIC_IRT_GPIO_INDEX(i) (XLP_PIC_IRT_GPIO0_INDEX + (i)) +/* 146 to 149 */ +#define XLP_PIC_IRT_NOR_INDEX 150 +#define XLP_PIC_IRT_NAND_INDEX 151 +#define XLP_PIC_IRT_SPI_INDEX 152 +#define XLP_PIC_IRT_MMC_INDEX 153 + +/* PIC control register defines */ +#define XLP_PIC_ITV_OFFSET 32 /* interrupt timeout value */ +#define XLP_PIC_ICI_OFFSET 19 /* ICI interrupt timeout enable */ +#define XLP_PIC_ITE_OFFSET 18 /* interrupt timeout enable */ +#define XLP_PIC_STE_OFFSET 10 /* system timer interrupt enable */ +#define XLP_PIC_WWR1_OFFSET 8 /* watchdog timer 1 wraparound count for reset */ +#define XLP_PIC_WWR0_OFFSET 6 /* watchdog timer 0 wraparound count for reset */ +#define XLP_PIC_WWN1_OFFSET 4 /* watchdog timer 1 wraparound count for NMI */ +#define XLP_PIC_WWN0_OFFSET 2 /* watchdog timer 0 wraparound count for NMI */ +#define XLP_PIC_WTE_OFFSET 0 /* watchdog timer enable */ + +/* PIC Status register defines */ +#define XLP_PIC_ICI_STATUS_OFFSET 33 /* ICI interrupt timeout interrupt status */ +#define XLP_PIC_ITE_STATUS_OFFSET 32 /* interrupt timeout interrupt status */ +#define XLP_PIC_STS_STATUS_OFFSET 4 /* System timer interrupt status */ +#define XLP_PIC_WNS_STATUS_OFFSET 2 /* NMI interrupt status for watchdog timers */ +#define XLP_PIC_WIS_STATUS_OFFSET 0 /* Interrupt status for watchdog timers */ + +/* PIC IPI control register offsets */ +#define XLP_PIC_IPICTRL_NMI_OFFSET 32 +#define XLP_PIC_IPICTRL_RIV_OFFSET 20 /* received interrupt vector */ +#define XLP_PIC_IPICTRL_IDB_OFFSET 16 /* interrupt destination base */ +#define XLP_PIC_IPICTRL_DTE_OFFSET 16 /* interrupt destination thread enables */ + +/* PIC IRT register offsets */ +#define XLP_PIC_IRT_ENABLE_OFFSET 31 +#define XLP_PIC_IRT_NMI_OFFSET 29 +#define XLP_PIC_IRT_SCH_OFFSET 28 /* Scheduling scheme */ +#define XLP_PIC_IRT_RVEC_OFFSET 20 /* Interrupt receive vectors */ +#define XLP_PIC_IRT_DT_OFFSET 19 /* Destination type */ +#define XLP_PIC_IRT_DB_OFFSET 16 /* Destination base */ +#define XLP_PIC_IRT_DTE_OFFSET 0 /* Destination thread enables */ + +#define XLP_PIC_MAX_IRQ 64 +#define XLP_PIC_MAX_IRT 160 +#define XLP_PIC_TIMER_FREQ 133000000 + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +#define nlm_rdreg_pic(b, r) nlm_read_reg64_kseg(b,r) +#define nlm_wreg_pic(b, r, v) nlm_write_reg64_kseg(b,r,v) +#define nlm_pcibase_pic(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node)) +#define nlm_regbase_pic(node) nlm_pcibase_pic(node) + +/* IRT and h/w interrupt routines */ +static __inline__ int +nlm_pic_get_numirts(uint64_t pcibase) +{ + return (nlm_pci_rdreg(pcibase, XLP_PCI_IRTINFO_REG) >> 16); +} + +static __inline__ int +nlm_pic_get_startirt(uint64_t base) +{ + return (nlm_pci_rdreg(base, XLP_PCI_IRTINFO_REG) & 0xff); +} + + +static __inline__ int +nlm_pic_read_irt(uint64_t base, int irt_index) +{ + return nlm_rdreg_pic(base, XLP_PIC_IRT_REG(irt_index)); +} + +/* IRT's can be written into in two modes + * ITE mode - Here the destination of the interrupt is one of the + * eight interrupt-thread-enable groups, allowing the interrupt + * to be distributed to any thread on any node + * ID mode - In ID mode, the IRT has the DB and DTE fields. + * DB[18:17] hold the node select and DB[16], if set to 0 selects + * cpu-cores 0-3, and if set to 1 selects cpu-cores 4-7. + * The DTE[15:0] field is a thread mask, allowing the PIC to broadcast + * the interrupt to 1-16 threads selectable from that mask + */ + +static __inline__ void +nlm_pic_write_irt_raw(uint64_t base, int irt_index, int en, int nmi, int sch, + int vec, int dt, int db, int dte) +{ + uint64_t val = + (((en & 0x1) << XLP_PIC_IRT_ENABLE_OFFSET) | + ((nmi & 0x1) << XLP_PIC_IRT_NMI_OFFSET) | + ((sch & 0x1) << XLP_PIC_IRT_SCH_OFFSET) | + ((vec & 0x3f) << XLP_PIC_IRT_RVEC_OFFSET) | + ((dt & 0x1 ) << XLP_PIC_IRT_DT_OFFSET) | + ((db & 0x7) << XLP_PIC_IRT_DB_OFFSET) | + (dte & 0xffff)); + nlm_wreg_pic(base, XLP_PIC_IRT_REG(irt_index), val); +} + +/* write IRT in ID mode */ +static __inline__ void +nlm_pic_write_irt_id(uint64_t base, int irt_index, int en, int nmi, int vec, + int node, int cpugroup, uint32_t cpu_mask) +{ + nlm_pic_write_irt_raw(base, irt_index, en, nmi, 1, vec, 1, + (node << 1) | cpugroup , cpu_mask); +} + +/* write IRT in ITE mode */ +static __inline__ void +nlm_pic_write_ite(uint64_t base, int ite, uint32_t node0_thrmask, + uint32_t node1_thrmask, uint32_t node2_thrmask, uint32_t node3_thrmask) +{ + uint64_t tm10 = ((uint64_t)node1_thrmask << 32) | node0_thrmask; + uint64_t tm32 = ((uint64_t)node1_thrmask << 32) | node0_thrmask; + + /* Enable the ITE register for all nodes */ + nlm_wreg_pic(base, XLP_PIC_ITE_N0_N1_REG(ite), tm10); + nlm_wreg_pic(base, XLP_PIC_ITE_N2_N3_REG(ite), tm32); +} + +static __inline__ void +nlm_pic_write_irt_ite(uint64_t base, int irt_index, int ite, int en, int nmi, + int sch, int vec) +{ + nlm_pic_write_irt_raw(base, irt_index, en, nmi, sch, vec, 0, ite, 0); +} + +/* Goto PIC on that node, and ack the interrupt */ +static __inline__ void nlm_pic_ack(uint64_t src_base, int irt) +{ + nlm_wreg_pic(src_base, XLP_PIC_INT_ACK_REG, irt); + /* ack in the status registers for watchdog and system timers */ + if (irt < 12) + nlm_wreg_pic(src_base, XLP_PIC_STATUS_REG, (1 << irt)); +} + +/* IPI routines */ + +static __inline__ void +nlm_pic_send_ipi(uint64_t local_base, int target_node, int vcpu, int vec, int nmi) +{ + uint64_t ipi = + (((uint64_t)nmi << XLP_PIC_IPICTRL_NMI_OFFSET) | + (vec << XLP_PIC_IPICTRL_RIV_OFFSET) | + (target_node << 17) | + (1 << (vcpu & 0xf))); + if (vcpu > 15) + ipi |= 0x10000; /* set bit 16 to select cpus 16-31 */ + + nlm_wreg_pic(local_base, XLP_PIC_IPI_CTRL_REG, ipi); +} + +/* System Timer routines -- broadcasts systemtimer to 16 vcpus defined in cpu_mask */ + +static __inline__ void +nlm_pic_set_systimer(uint64_t base, int timer, uint64_t value, int irq, int node, + int cpugroup, uint32_t cpumask) +{ + uint64_t pic_ctrl = nlm_rdreg_pic(base, XLP_PIC_CTRL_REG); + int en; + + en = (cpumask != 0); + nlm_wreg_pic(base, XLP_PIC_SYSTIMER_MAXVAL_REG(timer), value); + nlm_pic_write_irt_id(base, XLP_PIC_IRT_TIMER_INDEX(timer), + en, 0, irq, node, cpugroup, cpumask); + + /* enable the timer */ + pic_ctrl |= (1 << (XLP_PIC_STE_OFFSET+timer)); + nlm_wreg_pic(base, XLP_PIC_CTRL_REG, pic_ctrl); +} + +static __inline__ uint64_t +nlm_pic_read_systimer(uint64_t base, int timer) +{ + return nlm_rdreg_pic(base, XLP_PIC_SYSTIMER_COUNT_REG(timer)); +} + +/* Watchdog timer routines */ + +/* node - XLP node + * timer - watchdog timer. valid values are 0 and 1 + * wrap_around_count - defines the number of times the watchdog timer can wrap-around + * after which the reset / NMI gets generated to the threads defined in thread-enable-masks. + * value - the vatchdog timer max value, upto which the timer will count down + */ + +static __inline__ void +nlm_pic_set_wdogtimer(uint64_t base, int timer, int wrap_around_count, int nmi, + uint32_t node0_thrmask, uint32_t node1_thrmask, + uint32_t node2_thrmask, uint32_t node3_thrmask, uint64_t value) +{ + uint64_t pic_ctrl = nlm_rdreg_pic(base, XLP_PIC_CTRL_REG); + uint64_t mask0, mask1; + + if (timer > 1 || wrap_around_count > 3) + return; + + /* enable watchdog timer interrupt */ + pic_ctrl |= (((1 << timer) & 0xf)); + + if (timer) { + if (nmi) + pic_ctrl |= (wrap_around_count << XLP_PIC_WWN1_OFFSET); + else + pic_ctrl |= (wrap_around_count << XLP_PIC_WWN0_OFFSET); + } else { + if (nmi) + pic_ctrl |= (wrap_around_count << XLP_PIC_WWR1_OFFSET); + else + pic_ctrl |= (wrap_around_count << XLP_PIC_WWR0_OFFSET); + } + + mask0 = ((unsigned long long)node1_thrmask << 32) | node0_thrmask; + mask1 = ((unsigned long long)node3_thrmask << 32) | node2_thrmask; + + nlm_wreg_pic(base, XLP_PIC_WDOG_MAXVAL_REG(timer), value); + + nlm_wreg_pic(base, XLP_PIC_WDOG_ENABLE0_REG(timer), mask0); + nlm_wreg_pic(base, XLP_PIC_WDOG_ENABLE1_REG(timer), mask1); + + nlm_wreg_pic(base, XLP_PIC_CTRL_REG, pic_ctrl); +} + +/* watchdog's need to be "stroked" by heartbeats from vcpus. + * On XLP, the heartbeat bit for a specific cpu thread on a specific + * node is set according to the following formula: + * 32N + 4C + T + * where N = node, C=cpu-core number, T=thread number + * + * src_node = source node of watchdog timer interrupts. These interrupts + * get generated from the PIC on src_node. + * timer = watchdog timer 0 or 1 + * node = node for which the hearbeat is being done + * cpu = cpu-core for which the hearbeat is being done + * thread = h/w thread for which the hearbeat is being done + */ +static __inline__ void +nlm_pic_set_wdog_heartbeat(uint64_t base, int timer, int node, int cpu, + int thread) +{ + int val = 32 * node + 4 * cpu + thread; + + nlm_wreg_pic(base, XLP_PIC_WDOG_BEATCMD_REG(timer), val); +} + +#endif /* !LOCORE && !__ASSEMBLY__ */ +#endif diff --git a/sys/mips/nlm/hal/sys.h b/sys/mips/nlm/hal/sys.h new file mode 100644 index 0000000..89e4c52 --- /dev/null +++ b/sys/mips/nlm/hal/sys.h @@ -0,0 +1,125 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_SYS_H__ +#define __NLM_SYS_H__ + +/** +* @file_name sys.h +* @author Netlogic Microsystems +* @brief HAL for System configuration registers +*/ +#define XLP_SYS_CHIP_RESET_REG 0x40 +#define XLP_SYS_POWER_ON_RESET_REG 0x41 +#define XLP_SYS_EFUSE_DEVICE_CFG_STATUS0_REG 0x42 +#define XLP_SYS_EFUSE_DEVICE_CFG_STATUS1_REG 0x43 +#define XLP_SYS_EFUSE_DEVICE_CFG_STATUS2_REG 0x44 +#define XLP_SYS_EFUSE_DEVICE_CFG3_REG 0x45 +#define XLP_SYS_EFUSE_DEVICE_CFG4_REG 0x46 +#define XLP_SYS_EFUSE_DEVICE_CFG5_REG 0x47 +#define XLP_SYS_EFUSE_DEVICE_CFG6_REG 0x48 +#define XLP_SYS_EFUSE_DEVICE_CFG7_REG 0x49 +#define XLP_SYS_PLL_CTRL_REG 0x4a +#define XLP_SYS_CPU_RESET_REG 0x4b +#define XLP_SYS_CPU_NONCOHERENT_MODE_REG 0x4d +#define XLP_SYS_CORE_DFS_DIS_CTRL_REG 0x4e +#define XLP_SYS_CORE_DFS_RST_CTRL_REG 0x4f +#define XLP_SYS_CORE_DFS_BYP_CTRL_REG 0x50 +#define XLP_SYS_CORE_DFS_PHA_CTRL_REG 0x51 +#define XLP_SYS_CORE_DFS_DIV_INC_CTRL_REG 0x52 +#define XLP_SYS_CORE_DFS_DIV_DEC_CTRL_REG 0x53 +#define XLP_SYS_CORE_DFS_DIV_VALUE_REG 0x54 +#define XLP_SYS_RESET_REG 0x55 +#define XLP_SYS_DFS_DIS_CTRL_REG 0x56 +#define XLP_SYS_DFS_RST_CTRL_REG 0x57 +#define XLP_SYS_DFS_BYP_CTRL_REG 0x58 +#define XLP_SYS_DFS_DIV_INC_CTRL_REG 0x59 +#define XLP_SYS_DFS_DIV_DEC_CTRL_REG 0x5a +#define XLP_SYS_DFS_DIV_VALUE0_REG 0x5b +#define XLP_SYS_DFS_DIV_VALUE1_REG 0x5c +#define XLP_SYS_SENSE_AMP_DLY_REG 0x5d +#define XLP_SYS_SOC_SENSE_AMP_DLY_REG 0x5e +#define XLP_SYS_CTRL0_REG 0x5f +#define XLP_SYS_CTRL1_REG 0x60 +#define XLP_SYS_TIMEOUT_BS1_REG 0x61 +#define XLP_SYS_BYTE_SWAP_REG 0x62 +#define XLP_SYS_VRM_VID_REG 0x63 +#define XLP_SYS_PWR_RAM_CMD_REG 0x64 +#define XLP_SYS_PWR_RAM_ADDR_REG 0x65 +#define XLP_SYS_PWR_RAM_DATA0_REG 0x66 +#define XLP_SYS_PWR_RAM_DATA1_REG 0x67 +#define XLP_SYS_PWR_RAM_DATA2_REG 0x68 +#define XLP_SYS_PWR_UCODE_REG 0x69 +#define XLP_SYS_CPU0_PWR_STATUS_REG 0x6a +#define XLP_SYS_CPU1_PWR_STATUS_REG 0x6b +#define XLP_SYS_CPU2_PWR_STATUS_REG 0x6c +#define XLP_SYS_CPU3_PWR_STATUS_REG 0x6d +#define XLP_SYS_CPU4_PWR_STATUS_REG 0x6e +#define XLP_SYS_CPU5_PWR_STATUS_REG 0x6f +#define XLP_SYS_CPU6_PWR_STATUS_REG 0x70 +#define XLP_SYS_CPU7_PWR_STATUS_REG 0x71 +#define XLP_SYS_STATUS_REG 0x72 +#define XLP_SYS_INT_POL_REG 0x73 +#define XLP_SYS_INT_TYPE_REG 0x74 +#define XLP_SYS_INT_STATUS_REG 0x75 +#define XLP_SYS_INT_MASK0_REG 0x76 +#define XLP_SYS_INT_MASK1_REG 0x77 +#define XLP_SYS_UCO_S_ECC_REG 0x78 +#define XLP_SYS_UCO_M_ECC_REG 0x79 +#define XLP_SYS_UCO_ADDR_REG 0x7a +#define XLP_SYS_UCO_INSTR_REG 0x7b +#define XLP_SYS_MEM_BIST0_REG 0x7c +#define XLP_SYS_MEM_BIST1_REG 0x7d +#define XLP_SYS_MEM_BIST2_REG 0x7e +#define XLP_SYS_MEM_BIST3_REG 0x7f +#define XLP_SYS_MEM_BIST4_REG 0x80 +#define XLP_SYS_MEM_BIST5_REG 0x81 +#define XLP_SYS_MEM_BIST6_REG 0x82 +#define XLP_SYS_MEM_BIST7_REG 0x83 +#define XLP_SYS_MEM_BIST8_REG 0x84 +#define XLP_SYS_MEM_BIST9_REG 0x85 +#define XLP_SYS_MEM_BIST10_REG 0x86 +#define XLP_SYS_MEM_BIST11_REG 0x87 +#define XLP_SYS_MEM_BIST12_REG 0x88 +#define XLP_SYS_SCRTCH0_REG 0x89 +#define XLP_SYS_SCRTCH1_REG 0x8a +#define XLP_SYS_SCRTCH2_REG 0x8b +#define XLP_SYS_SCRTCH3_REG 0x8c + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +#define nlm_rdreg_sys(b, r) nlm_read_reg_kseg(b,r) +#define nlm_wreg_sys(b, r, v) nlm_write_reg_kseg(b,r,v) +#define nlm_pcibase_sys(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node)) +#define nlm_regbase_sys(node) nlm_pcibase_sys(node) + +#endif + +#endif diff --git a/sys/mips/nlm/hal/uart.h b/sys/mips/nlm/hal/uart.h new file mode 100644 index 0000000..9eebb49 --- /dev/null +++ b/sys/mips/nlm/hal/uart.h @@ -0,0 +1,196 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __XLP_UART_H__ +#define __XLP_UART_H__ + +/* UART Specific registers */ +#define XLP_UART_RX_DATA_REG 0x40 +#define XLP_UART_TX_DATA_REG 0x40 + +#define XLP_UART_INT_EN_REG 0x41 +#define XLP_UART_INT_ID_REG 0x42 +#define XLP_UART_FIFO_CTL_REG 0x42 +#define XLP_UART_LINE_CTL_REG 0x43 +#define XLP_UART_MODEM_CTL_REG 0x44 +#define XLP_UART_LINE_STS_REG 0x45 +#define XLP_UART_MODEM_STS_REG 0x46 + +#define XLP_UART_DIVISOR0_REG 0x40 +#define XLP_UART_DIVISOR1_REG 0x41 + +#define XLP_UART_BASE_BAUD (133000000/16) +#define XLP_UART_BAUD_DIVISOR(baud) (XLP_UART_BASE_BAUD / baud) + +/* LCR mask values */ +#define LCR_5BITS 0x00 +#define LCR_6BITS 0x01 +#define LCR_7BITS 0x02 +#define LCR_8BITS 0x03 +#define LCR_STOPB 0x04 +#define LCR_PENAB 0x08 +#define LCR_PODD 0x00 +#define LCR_PEVEN 0x10 +#define LCR_PONE 0x20 +#define LCR_PZERO 0x30 +#define LCR_SBREAK 0x40 +#define LCR_EFR_ENABLE 0xbf +#define LCR_DLAB 0x80 + +/* MCR mask values */ +#define MCR_DTR 0x01 +#define MCR_RTS 0x02 +#define MCR_DRS 0x04 +#define MCR_IE 0x08 +#define MCR_LOOPBACK 0x10 + +/* FCR mask values */ +#define FCR_RCV_RST 0x02 +#define FCR_XMT_RST 0x04 +#define FCR_RX_LOW 0x00 +#define FCR_RX_MEDL 0x40 +#define FCR_RX_MEDH 0x80 +#define FCR_RX_HIGH 0xc0 + +/* IER mask values */ +#define IER_ERXRDY 0x1 +#define IER_ETXRDY 0x2 +#define IER_ERLS 0x4 +#define IER_EMSC 0x8 + +/* uart IRQ info */ +#define XLP_NODE0_UART0_IRQ 17 +#define XLP_NODE1_UART0_IRQ 18 +#define XLP_NODE2_UART0_IRQ 19 +#define XLP_NODE3_UART0_IRQ 20 +#define XLP_NODE0_UART1_IRQ 21 +#define XLP_NODE1_UART1_IRQ 22 +#define XLP_NODE2_UART1_IRQ 23 +#define XLP_NODE3_UART1_IRQ 24 + +#if !defined(LOCORE) && !defined(__ASSEMBLY__) + +#define nlm_rdreg_uart(b, r) nlm_read_reg_kseg(b,r) +#define nlm_wreg_uart(b, r, v) nlm_write_reg_kseg(b,r,v) +#define nlm_pcibase_uart(node, inst) nlm_pcicfg_base(XLP_IO_UART_OFFSET(node, inst)) +#define nlm_regbase_uart(node, inst) nlm_pcibase_uart(node, inst) + +static __inline__ void +nlm_uart_set_baudrate(uint64_t base, int baud) +{ + uint32_t lcr; + + lcr = nlm_rdreg_uart(base, XLP_UART_LINE_CTL_REG); + + /* enable divisor register, and write baud values */ + nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, lcr | (1 << 7)); + nlm_wreg_uart(base, XLP_UART_DIVISOR0_REG, + (XLP_UART_BAUD_DIVISOR(baud) & 0xff)); + nlm_wreg_uart(base, XLP_UART_DIVISOR1_REG, + ((XLP_UART_BAUD_DIVISOR(baud) >> 8) & 0xff)); + + /* restore default lcr */ + nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, lcr); +} + +static __inline__ void +nlm_outbyte (uint64_t base, char c) +{ + uint32_t lsr; + + for (;;) { + lsr = nlm_rdreg_uart(base, XLP_UART_LINE_STS_REG); + if (lsr & 0x20) break; + } + + nlm_wreg_uart(base, XLP_UART_TX_DATA_REG, (int)c); +} + +static __inline__ char +nlm_inbyte (uint64_t base) +{ + int data, lsr; + + for(;;) { + lsr = nlm_rdreg_uart(base, XLP_UART_LINE_STS_REG); + if (lsr & 0x80) { /* parity/frame/break-error - push a zero */ + data = 0; + break; + } + if (lsr & 0x01) { /* Rx data */ + data = nlm_rdreg_uart(base, XLP_UART_RX_DATA_REG); + break; + } + } + + return (char)data; +} + +static __inline__ int +nlm_uart_init(uint64_t base, int baud, int databits, int stopbits, + int parity, int int_en, int loopback) +{ + uint32_t lcr; + + lcr = 0; + if (databits >= 8) + lcr |= LCR_8BITS; + else if (databits == 7) + lcr |= LCR_7BITS; + else if (databits == 6) + lcr |= LCR_6BITS; + else + lcr |= LCR_5BITS; + + if (stopbits > 1) + lcr |= LCR_STOPB; + + lcr |= parity << 3; + + /* setup default lcr */ + nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, lcr); + + /* Reset the FIFOs */ + nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, FCR_RCV_RST | FCR_XMT_RST); + + nlm_uart_set_baudrate(base, baud); + + if (loopback) + nlm_wreg_uart(base, XLP_UART_MODEM_CTL_REG, 0x1f); + + if (int_en) + nlm_wreg_uart(base, XLP_UART_INT_EN_REG, IER_ERXRDY | IER_ETXRDY); + + return 0; +} + +#endif /* !LOCORE && !__ASSEMBLY__ */ +#endif /* __XLP_UART_H__ */ + diff --git a/sys/mips/nlm/interrupt.h b/sys/mips/nlm/interrupt.h new file mode 100644 index 0000000..41904eb --- /dev/null +++ b/sys/mips/nlm/interrupt.h @@ -0,0 +1,49 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef _RMI_INTERRUPT_H_ +#define _RMI_INTERRUPT_H_ + +/* Defines for the IRQ numbers */ + +#define IRQ_IPI 41 /* 8-39 are mapped by PIC intr 0-31 */ +#define IRQ_MSGRING 6 +#define IRQ_TIMER 7 + +/* + * XLR needs custom pre and post handlers for PCI/PCI-e interrupts + * XXX: maybe follow i386 intsrc model + */ +void xlp_establish_intr(const char *name, driver_filter_t filt, + driver_intr_t handler, void *arg, int irq, int flags, + void **cookiep, void (*busack)(int)); +void xlp_enable_irq(int irq); + +#endif /* _RMI_INTERRUPT_H_ */ diff --git a/sys/mips/nlm/intr_machdep.c b/sys/mips/nlm/intr_machdep.c new file mode 100644 index 0000000..4862356 --- /dev/null +++ b/sys/mips/nlm/intr_machdep.c @@ -0,0 +1,253 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> + +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/cpuinfo.h> +#include <machine/cpuregs.h> +#include <machine/frame.h> +#include <machine/intr_machdep.h> +#include <machine/md_var.h> +#include <machine/trap.h> +#include <machine/hwfunc.h> + +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/cop0.h> +#include <mips/nlm/interrupt.h> +#include <mips/nlm/hal/pic.h> +#include <mips/nlm/xlp.h> + +struct xlp_intrsrc { + void (*busack)(int); /* Additional ack */ + struct intr_event *ie; /* event corresponding to intr */ + int irq; +}; + +static struct xlp_intrsrc xlp_interrupts[XLR_MAX_INTR]; +static mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR]; +static int intrcnt_index; + +void +xlp_enable_irq(int irq) +{ + uint64_t eimr; + + eimr = nlm_read_c0_eimr(); + nlm_write_c0_eimr(eimr | (1ULL << irq)); +} + +void +cpu_establish_softintr(const char *name, driver_filter_t * filt, + void (*handler) (void *), void *arg, int irq, int flags, + void **cookiep) +{ + + panic("Soft interrupts unsupported!\n"); +} + +void +cpu_establish_hardintr(const char *name, driver_filter_t * filt, + void (*handler) (void *), void *arg, int irq, int flags, + void **cookiep) +{ + + xlp_establish_intr(name, filt, handler, arg, irq, flags, + cookiep, NULL); +} + +static void +xlp_post_filter(void *source) +{ + struct xlp_intrsrc *src = source; + + if (src->busack) + src->busack(src->irq); + nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq)); +} + +static void +xlp_pre_ithread(void *source) +{ + struct xlp_intrsrc *src = source; + + if (src->busack) + src->busack(src->irq); +} + +static void +xlp_post_ithread(void *source) +{ + struct xlp_intrsrc *src = source; + + nlm_pic_ack(xlp_pic_base, xlp_irq_to_irt(src->irq)); +} + +void +xlp_establish_intr(const char *name, driver_filter_t filt, + driver_intr_t handler, void *arg, int irq, int flags, + void **cookiep, void (*busack)(int)) +{ + struct intr_event *ie; /* descriptor for the IRQ */ + struct xlp_intrsrc *src = NULL; + int errcode; + + if (irq < 0 || irq > XLR_MAX_INTR) + panic("%s called for unknown hard intr %d", __func__, irq); + + /* + * FIXME locking - not needed now, because we do this only on + * startup from CPU0 + */ + src = &xlp_interrupts[irq]; + ie = src->ie; + if (ie == NULL) { + /* + * PIC based interrupts need ack in PIC, and some SoC + * components need additional acks (e.g. PCI) + */ + if (xlp_irq_is_picintr(irq)) + errcode = intr_event_create(&ie, src, 0, irq, + xlp_pre_ithread, xlp_post_ithread, xlp_post_filter, + NULL, "hard intr%d:", irq); + else { + if (filt == NULL) + panic("Not supported - non filter percpu intr"); + errcode = intr_event_create(&ie, src, 0, irq, + NULL, NULL, NULL, NULL, "hard intr%d:", irq); + } + if (errcode) { + printf("Could not create event for intr %d\n", irq); + return; + } + src->irq = irq; + src->busack = busack; + src->ie = ie; + } + intr_event_add_handler(ie, name, filt, handler, arg, + intr_priority(flags), flags, cookiep); + xlp_enable_irq(irq); +} + +void +cpu_intr(struct trapframe *tf) +{ + struct intr_event *ie; + uint64_t eirr, eimr; + int i; + + critical_enter(); + + /* find a list of enabled interrupts */ + eirr = nlm_read_c0_eirr(); + eimr = nlm_read_c0_eimr(); + eirr &= eimr; + + if (eirr == 0) { + critical_exit(); + return; + } + /* + * No need to clear the EIRR here as the handler writes to + * compare which ACKs the interrupt. + */ + if (eirr & (1 << IRQ_TIMER)) { + intr_event_handle(xlp_interrupts[IRQ_TIMER].ie, tf); + critical_exit(); + return; + } + + /* FIXME sched pin >? LOCK>? */ + for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) { + if ((eirr & (1ULL << i)) == 0) + continue; + + ie = xlp_interrupts[i].ie; + /* Don't account special IRQs */ + switch (i) { + case IRQ_IPI: + case IRQ_MSGRING: + break; + default: + mips_intrcnt_inc(mips_intr_counters[i]); + } + + /* Ack the IRQ on the CPU */ + nlm_write_c0_eirr(1ULL << i); + if (intr_event_handle(ie, tf) != 0) { + printf("stray interrupt %d\n", i); + } + } + critical_exit(); +} + +void +mips_intrcnt_setname(mips_intrcnt_t counter, const char *name) +{ + int idx = counter - intrcnt; + + KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter")); + + snprintf(intrnames + (MAXCOMLEN + 1) * idx, + MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name); +} + +mips_intrcnt_t +mips_intrcnt_create(const char* name) +{ + mips_intrcnt_t counter = &intrcnt[intrcnt_index++]; + + mips_intrcnt_setname(counter, name); + return counter; +} + +void +cpu_init_interrupts() +{ + int i; + char name[MAXCOMLEN + 1]; + + /* + * Initialize all available vectors so spare IRQ + * would show up in systat output + */ + for (i = 0; i < XLR_MAX_INTR; i++) { + snprintf(name, MAXCOMLEN + 1, "int%d:", i); + mips_intr_counters[i] = mips_intrcnt_create(name); + } +} diff --git a/sys/mips/nlm/iodi.c b/sys/mips/nlm/iodi.c new file mode 100644 index 0000000..3b372bb --- /dev/null +++ b/sys/mips/nlm/iodi.c @@ -0,0 +1,233 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#define __RMAN_RESOURCE_VISIBLE +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/reboot.h> +#include <sys/rman.h> + +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> + +#include <machine/cpu.h> +#include <machine/bus.h> +#include <machine/intr_machdep.h> + +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/pic.h> +#include <mips/nlm/hal/uart.h> +#include <mips/nlm/hal/cop2.h> +#include <mips/nlm/hal/fmn.h> + +#include <mips/nlm/msgring.h> +#include <mips/nlm/xlp.h> +#include <mips/nlm/board.h> + +extern void iodi_activateirqs(void); + +extern bus_space_tag_t uart_bus_space_mem; + +static struct resource *iodi_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); + +static int iodi_activate_resource(device_t, device_t, int, int, + struct resource *); +struct iodi_softc *iodi_softc; /* There can be only one. */ + +static int +iodi_setup_intr(device_t dev, device_t child, + struct resource *ires, int flags, driver_filter_t *filt, + driver_intr_t *intr, void *arg, void **cookiep) +{ + const char *name = device_get_name(child); + int unit = device_get_unit(child); + + if (strcmp(name, "uart") == 0) { + /* Note: in xlp, all pic interrupts are level triggered */ + nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_UART0_INDEX, 1, 0, + xlp_irt_to_irq(XLP_PIC_IRT_UART0_INDEX), 0, 0, 0x1); + + cpu_establish_hardintr("uart", filt, intr, arg, + xlp_irt_to_irq(XLP_PIC_IRT_UART0_INDEX), flags, cookiep); + } else if (strcmp(name, "ehci") == 0) { + if (unit == 0) { + nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_EHCI0_INDEX, 1, 0, + xlp_irt_to_irq(XLP_PIC_IRT_EHCI0_INDEX), 0, 0, 0x1); + + cpu_establish_hardintr("ehci0", filt, intr, arg, + xlp_irt_to_irq(XLP_PIC_IRT_EHCI0_INDEX), flags, cookiep); + } else if (unit == 1) { + nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_EHCI1_INDEX, 1, 0, + xlp_irt_to_irq(XLP_PIC_IRT_EHCI1_INDEX), 0, 0, 0x1); + + cpu_establish_hardintr("ehci1", filt, intr, arg, + xlp_irt_to_irq(XLP_PIC_IRT_EHCI1_INDEX), flags, cookiep); + + } + } else if (strcmp(name, "xlp_sdhci") == 0) { + nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_MMC_INDEX, 1, 0, + xlp_irt_to_irq(XLP_PIC_IRT_MMC_INDEX), 0, 0, 0x1); + + cpu_establish_hardintr("xlp_sdhci", filt, intr, arg, + xlp_irt_to_irq(XLP_PIC_IRT_MMC_INDEX), flags, cookiep); + + } + + return (0); +} + +static struct resource * +iodi_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK); + const char *name = device_get_name(child); + int unit; + + switch (type) { + case SYS_RES_IRQ: + device_printf(bus, "IRQ resource - for %s %lx-%lx\n", + device_get_nameunit(child), start, end); + break; + + case SYS_RES_IOPORT: + device_printf(bus, "IOPORT resource - for %s %lx-%lx\n", + device_get_nameunit(child), start, end); + break; + + case SYS_RES_MEMORY: + device_printf(bus, "MEMORY resource - for %s %lx-%lx\n", + device_get_nameunit(child), start, end); + break; + } + + unit = device_get_unit(child); + if (strcmp(name, "uart") == 0) { + if (unit == 0) { + res->r_bushandle = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ; + } else if ( unit == 1) { + res->r_bushandle = nlm_regbase_uart(0, 1) + XLP_IO_PCI_HDRSZ; + } else + printf("%s: Unknown uart unit\n", __FUNCTION__); + + res->r_bustag = uart_bus_space_mem; + } + + return (res); +} + +static int +iodi_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (0); +} +/* prototypes */ +static int iodi_probe(device_t); +static int iodi_attach(device_t); +static void iodi_identify(driver_t *, device_t); + +int +iodi_probe(device_t dev) +{ + return 0; +} + +void +iodi_identify(driver_t *driver, device_t parent) +{ + + BUS_ADD_CHILD(parent, 0, "iodi", 0); +} + + +int +iodi_attach(device_t dev) +{ + device_t tmpd; + char desc[32]; + int i; + + device_printf(dev, "IODI - Initialize message ring.\n"); + xlp_msgring_iodi_config(); + + /* + * Attach each devices + */ + device_add_child(dev, "uart", 0); + device_add_child(dev, "xlp_i2c", 0); + device_add_child(dev, "xlp_i2c", 1); + device_add_child(dev, "ehci", 0); + device_add_child(dev, "ehci", 1); + device_add_child(dev, "xlp_sdhci", 0); + + for (i=0; i < XLP_NUM_NODES; i++) { + tmpd = device_add_child(dev, "xlpnae", i); + device_set_ivars(tmpd, &xlp_board_info.nodes[i].nae_ivars); + snprintf(desc, sizeof(desc), "XLP NAE %d", i); + device_set_desc_copy(tmpd, desc); + } + + bus_generic_probe(dev); + bus_generic_attach(dev); + return 0; +} + +static device_method_t iodi_methods[] = { + DEVMETHOD(device_probe, iodi_probe), + DEVMETHOD(device_attach, iodi_attach), + DEVMETHOD(device_identify, iodi_identify), + DEVMETHOD(bus_alloc_resource, iodi_alloc_resource), + DEVMETHOD(bus_activate_resource, iodi_activate_resource), + DEVMETHOD(bus_add_child, bus_generic_add_child), + DEVMETHOD(bus_setup_intr, iodi_setup_intr), + {0, 0}, +}; + +static driver_t iodi_driver = { + "iodi", + iodi_methods, + 1 /* no softc */ +}; +static devclass_t iodi_devclass; + +DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0); diff --git a/sys/mips/nlm/mpreset.S b/sys/mips/nlm/mpreset.S new file mode 100644 index 0000000..c56bd9f --- /dev/null +++ b/sys/mips/nlm/mpreset.S @@ -0,0 +1,159 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#include <machine/asm.h> +#include <machine/cpu.h> +#include <machine/cpuregs.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/cpucontrol.h> + +#include "assym.s" + + .text + .set noat + .set noreorder + .set mips64 + +VECTOR(XLPResetEntry, unknown) + mfc0 t0, MIPS_COP_0_STATUS + li t1, 0x80000 + and t1, t0, t1 + bnez t1, nmi_handler + nop + +#ifdef SMP + /* Reset entry for secordary cores */ + mfc0 t0, MIPS_COP_0_PRID, 1 + srl t0, t0, 2 /* discard thread id */ + andi t0, t0, 0x7 /* core id */ + li t1, 1 + sll t0, t1, t0 + nor t0, t0, zero /* mask with core id bit clear */ + + /* clear CPU non-coherent bit */ + li t2, XLP_DEFAULT_IO_BASE_KSEG1 + XLP_IO_SYS_OFFSET(0) + XLP_SYS_CPU_NONCOHERENT_MODE_REG * 4 + lw t1, 0(t2) + and t1, t1, t0 + sw t1, 0(t2) + lw t1, 0(t2) /* read-back ensures operation complete */ + sync + + dla t2, mpentry + jr t2 + nop +#endif + nop + /* NOT REACHED */ +VECTOR_END(XLPResetEntry) + + + /* Not yet */ +nmi_handler: + nop + nop + j nmi_handler + +#ifdef SMP + /* + * Enable other threads in the core, called from thread 0 + * of the core + */ +LEAF(xlp_enable_threads) + /* + * Save and restore callee saved registers of all ABIs + * Enabling threads trashes the registers + */ + dmtc0 sp, $4, 2 /* SP saved in UserLocal */ + ori sp, sp, 0x7 + xori sp, sp, 0x7 /* align 64 bit */ + addiu sp, sp, -128 + mfc0 t1, MIPS_COP_0_STATUS + sd s0, 0(sp) + sd s1, 8(sp) + sd s2, 16(sp) + sd s3, 24(sp) + sd s4, 32(sp) + sd s5, 40(sp) + sd s6, 48(sp) + sd s7, 56(sp) + sd s8, 64(sp) + sd t1, 72(sp) + sd gp, 80(sp) + sd ra, 88(sp) + /* Use register number to work in o32 and n32 */ + li $9, ((XLP_CPU_BLOCKID_MAP << 8) | XLP_BLKID_MAP_THREADMODE) + move $8, a0 + sync + .word 0x71280019 /* mtcr t0, t1*/ + mfc0 t0, MIPS_COP_0_PRID, 1 + andi t0, 0x3 + beqz t0, 2f + nop + dla t1, mpentry /* child thread, go to hardware init */ + jr t1 + nop + + +2: /* + * Parent hardware thread, restore registers, return + */ +#if 1 + /* + * A0 Errata - Write MMU_SETUP after changing thread mode register. + */ + li $9, 0x400 + li $8, 0 + .word 0x71280019 /* mtcr $8, $9*/ + .word 0x000000c0 /* ehb */ +#endif + dmfc0 t0, $4, 2 /* SP saved in UserLocal */ + ori sp, t0, 0x7 + xori sp, sp, 0x7 /* align 64 bit */ + addiu sp, sp, -128 + ld s0, 0(sp) + ld s1, 8(sp) + ld s2, 16(sp) + ld s3, 24(sp) + ld s4, 32(sp) + ld s5, 40(sp) + ld s6, 48(sp) + ld s7, 56(sp) + ld s8, 64(sp) + ld t1, 72(sp) + ld gp, 80(sp) + ld ra, 88(sp) + mfc0 t1, MIPS_COP_0_STATUS + + move sp, t0 /* Restore the real SP */ + jr ra + nop +END(xlp_enable_threads) +#endif diff --git a/sys/mips/nlm/msgring.h b/sys/mips/nlm/msgring.h new file mode 100644 index 0000000..b951569 --- /dev/null +++ b/sys/mips/nlm/msgring.h @@ -0,0 +1,44 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +/** FIXME **/ +extern uint32_t xlp_msg_thread_mask; +typedef void (*msgring_handler)(int, int, int, int, struct nlm_fmn_msg *, void *); +int register_msgring_handler(int startb, int endb, msgring_handler action, + void *arg); +int xlp_handle_msg_vc(int vc, int max_msgs); +void xlp_msgring_cpu_init(uint32_t); +void xlp_msgring_config(void); +void xlp_cpu_msgring_handler(int bucket, int size, int code, int stid, + struct nlm_fmn_msg *msg, void *data); + +void nlm_cms_credit_setup(int credit); +void xlp_msgring_iodi_config(void); + diff --git a/sys/mips/nlm/std.xlp b/sys/mips/nlm/std.xlp new file mode 100644 index 0000000..7b5eed5 --- /dev/null +++ b/sys/mips/nlm/std.xlp @@ -0,0 +1,12 @@ +# $FreeBSD$ +files "../nlm/files.xlp" +cpu CPU_NLMXLP + +# +# XXXMIPS: It's a stub, isn't it? +# +#option HW_PAGEWALKER +#option MMU_HASH_MODE # enables hash based lookup into extended TLBs +#option MMU_CLOCK_GATING # enables clock gating on MMU +#option MMU_GLOBAL_MODE # enables global mode of sharing all TLBs with all h/w threads +#option NOFPU diff --git a/sys/mips/nlm/tick.c b/sys/mips/nlm/tick.c new file mode 100644 index 0000000..874a252 --- /dev/null +++ b/sys/mips/nlm/tick.c @@ -0,0 +1,393 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +/* + * Simple driver for the 32-bit interval counter built in to all + * MIPS32 CPUs. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_cputype.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/power.h> +#include <sys/smp.h> +#include <sys/time.h> +#include <sys/timeet.h> +#include <sys/timetc.h> + +#include <machine/hwfunc.h> +#include <machine/clock.h> +#include <machine/locore.h> +#include <machine/md_var.h> +#include <machine/intr_machdep.h> + +#include <mips/nlm/interrupt.h> + +uint64_t counter_freq; + +struct timecounter *platform_timecounter; + +static DPCPU_DEFINE(uint32_t, cycles_per_tick); +static uint32_t cycles_per_usec; + +static DPCPU_DEFINE(volatile uint32_t, counter_upper); +static DPCPU_DEFINE(volatile uint32_t, counter_lower_last); +static DPCPU_DEFINE(uint32_t, compare_ticks); +static DPCPU_DEFINE(uint32_t, lost_ticks); + +struct clock_softc { + int intr_rid; + struct resource *intr_res; + void *intr_handler; + struct timecounter tc; + struct eventtimer et; +}; +static struct clock_softc *softc; + +/* + * Device methods + */ +static int clock_probe(device_t); +static void clock_identify(driver_t *, device_t); +static int clock_attach(device_t); +static unsigned counter_get_timecount(struct timecounter *tc); + +void +mips_timer_early_init(uint64_t clock_hz) +{ + /* Initialize clock early so that we can use DELAY sooner */ + counter_freq = clock_hz; + cycles_per_usec = (clock_hz / (1000 * 1000)); +} + +void +platform_initclocks(void) +{ + + if (platform_timecounter != NULL) + tc_init(platform_timecounter); +} + +static uint64_t +tick_ticker(void) +{ + uint64_t ret; + uint32_t ticktock; + uint32_t t_lower_last, t_upper; + + /* + * Disable preemption because we are working with cpu specific data. + */ + critical_enter(); + + /* + * Note that even though preemption is disabled, interrupts are + * still enabled. In particular there is a race with clock_intr() + * reading the values of 'counter_upper' and 'counter_lower_last'. + * + * XXX this depends on clock_intr() being executed periodically + * so that 'counter_upper' and 'counter_lower_last' are not stale. + */ + do { + t_upper = DPCPU_GET(counter_upper); + t_lower_last = DPCPU_GET(counter_lower_last); + } while (t_upper != DPCPU_GET(counter_upper)); + + ticktock = mips_rd_count(); + + critical_exit(); + + /* COUNT register wrapped around */ + if (ticktock < t_lower_last) + t_upper++; + + ret = ((uint64_t)t_upper << 32) | ticktock; + return (ret); +} + +void +mips_timer_init_params(uint64_t platform_counter_freq, int double_count) +{ + + /* + * XXX: Do not use printf here: uart code 8250 may use DELAY so this + * function should be called before cninit. + */ + counter_freq = platform_counter_freq; + /* + * XXX: Some MIPS32 cores update the Count register only every two + * pipeline cycles. + * We know this because of status registers in CP0, make it automatic. + */ + if (double_count != 0) + counter_freq /= 2; + + cycles_per_usec = counter_freq / (1 * 1000 * 1000); + set_cputicker(tick_ticker, counter_freq, 1); +} + +static int +sysctl_machdep_counter_freq(SYSCTL_HANDLER_ARGS) +{ + int error; + uint64_t freq; + + if (softc == NULL) + return (EOPNOTSUPP); + freq = counter_freq; + error = sysctl_handle_64(oidp, &freq, sizeof(freq), req); + if (error == 0 && req->newptr != NULL) { + counter_freq = freq; + softc->et.et_frequency = counter_freq; + softc->tc.tc_frequency = counter_freq; + } + return (error); +} + +SYSCTL_PROC(_machdep, OID_AUTO, counter_freq, CTLTYPE_U64 | CTLFLAG_RW, + NULL, 0, sysctl_machdep_counter_freq, "QU", + "Timecounter frequency in Hz"); + +static unsigned +counter_get_timecount(struct timecounter *tc) +{ + + return (mips_rd_count()); +} + +/* + * Wait for about n microseconds (at least!). + */ +void +DELAY(int n) +{ + uint32_t cur, last, delta, usecs; + + /* + * This works by polling the timer and counting the number of + * microseconds that go by. + */ + last = mips_rd_count(); + delta = usecs = 0; + + while (n > usecs) { + cur = mips_rd_count(); + + /* Check to see if the timer has wrapped around. */ + if (cur < last) + delta += cur + (0xffffffff - last) + 1; + else + delta += cur - last; + + last = cur; + + if (delta >= cycles_per_usec) { + usecs += delta / cycles_per_usec; + delta %= cycles_per_usec; + } + } +} + +static int +clock_start(struct eventtimer *et, + struct bintime *first, struct bintime *period) +{ + uint32_t fdiv, div, next; + + if (period != NULL) { + div = (et->et_frequency * (period->frac >> 32)) >> 32; + if (period->sec != 0) + div += et->et_frequency * period->sec; + } else + div = 0; + if (first != NULL) { + fdiv = (et->et_frequency * (first->frac >> 32)) >> 32; + if (first->sec != 0) + fdiv += et->et_frequency * first->sec; + } else + fdiv = div; + DPCPU_SET(cycles_per_tick, div); + next = mips_rd_count() + fdiv; + DPCPU_SET(compare_ticks, next); + mips_wr_compare(next); + return (0); +} + +static int +clock_stop(struct eventtimer *et) +{ + + DPCPU_SET(cycles_per_tick, 0); + mips_wr_compare(0xffffffff); + return (0); +} + +/* + * Device section of file below + */ +static int +clock_intr(void *arg) +{ + struct clock_softc *sc = (struct clock_softc *)arg; + uint32_t cycles_per_tick; + uint32_t count, compare_last, compare_next, lost_ticks; + + cycles_per_tick = DPCPU_GET(cycles_per_tick); + /* + * Set next clock edge. + */ + count = mips_rd_count(); + compare_last = DPCPU_GET(compare_ticks); + if (cycles_per_tick > 0) { + compare_next = count + cycles_per_tick; + DPCPU_SET(compare_ticks, compare_next); + mips_wr_compare(compare_next); + } else /* In one-shot mode timer should be stopped after the event. */ + mips_wr_compare(0xffffffff); + + /* COUNT register wrapped around */ + if (count < DPCPU_GET(counter_lower_last)) { + DPCPU_SET(counter_upper, DPCPU_GET(counter_upper) + 1); + } + DPCPU_SET(counter_lower_last, count); + + if (cycles_per_tick > 0) { + + /* + * Account for the "lost time" between when the timer interrupt + * fired and when 'clock_intr' actually started executing. + */ + lost_ticks = DPCPU_GET(lost_ticks); + lost_ticks += count - compare_last; + + /* + * If the COUNT and COMPARE registers are no longer in sync + * then make up some reasonable value for the 'lost_ticks'. + * + * This could happen, for e.g., after we resume normal + * operations after exiting the debugger. + */ + if (lost_ticks > 2 * cycles_per_tick) + lost_ticks = cycles_per_tick; + + while (lost_ticks >= cycles_per_tick) { + if (sc->et.et_active) + sc->et.et_event_cb(&sc->et, sc->et.et_arg); + lost_ticks -= cycles_per_tick; + } + DPCPU_SET(lost_ticks, lost_ticks); + } + if (sc->et.et_active) + sc->et.et_event_cb(&sc->et, sc->et.et_arg); + return (FILTER_HANDLED); +} + +static int +clock_probe(device_t dev) +{ + + if (device_get_unit(dev) != 0) + panic("can't attach more clocks"); + + device_set_desc(dev, "Generic MIPS32 ticker"); + return (0); +} + +static void +clock_identify(driver_t * drv, device_t parent) +{ + + BUS_ADD_CHILD(parent, 0, "clock", 0); +} + +static int +clock_attach(device_t dev) +{ + struct clock_softc *sc; + + softc = sc = device_get_softc(dev); + cpu_establish_hardintr("compare", clock_intr, NULL, + sc, IRQ_TIMER, INTR_TYPE_CLK, &sc->intr_handler); + + sc->tc.tc_get_timecount = counter_get_timecount; + sc->tc.tc_counter_mask = 0xffffffff; + sc->tc.tc_frequency = counter_freq; + sc->tc.tc_name = "MIPS32"; + sc->tc.tc_quality = 800; + sc->tc.tc_priv = sc; + tc_init(&sc->tc); + sc->et.et_name = "MIPS32"; +#if 0 + sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | + ET_FLAGS_PERCPU; +#endif + sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_PERCPU; + sc->et.et_quality = 800; + sc->et.et_frequency = counter_freq; + sc->et.et_min_period.sec = 0; + sc->et.et_min_period.frac = 0x00004000LLU << 32; /* To be safe. */ + sc->et.et_max_period.sec = 0xfffffffeU / sc->et.et_frequency; + sc->et.et_max_period.frac = + ((0xfffffffeLLU << 32) / sc->et.et_frequency) << 32; + sc->et.et_start = clock_start; + sc->et.et_stop = clock_stop; + sc->et.et_priv = sc; + et_register(&sc->et); + return (0); +} + +static device_method_t clock_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, clock_probe), + DEVMETHOD(device_identify, clock_identify), + DEVMETHOD(device_attach, clock_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + {0, 0} +}; + +static driver_t clock_driver = { + "clock", + clock_methods, + sizeof(struct clock_softc), +}; + +static devclass_t clock_devclass; + +DRIVER_MODULE(clock, nexus, clock_driver, clock_devclass, 0, 0); diff --git a/sys/mips/nlm/uart_bus_xlp_iodi.c b/sys/mips/nlm/uart_bus_xlp_iodi.c new file mode 100644 index 0000000..236900a --- /dev/null +++ b/sys/mips/nlm/uart_bus_xlp_iodi.c @@ -0,0 +1,88 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/rman.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/uart.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_bus.h> +#include <dev/uart/uart_cpu.h> + +static int uart_iodi_probe(device_t dev); + +static device_method_t uart_iodi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_iodi_probe), + DEVMETHOD(device_attach, uart_bus_attach), + DEVMETHOD(device_detach, uart_bus_detach), + {0, 0} +}; + +static driver_t uart_iodi_driver = { + uart_driver_name, + uart_iodi_methods, + sizeof(struct uart_softc), +}; + +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; + +static int +uart_iodi_probe(device_t dev) +{ + struct uart_softc *sc; + + sc = device_get_softc(dev); + sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); + sc->sc_class = &uart_ns8250_class; + bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); + sc->sc_sysdev->bas.bst = rmi_bus_space; + sc->sc_sysdev->bas.bsh = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ; + sc->sc_bas.bst = rmi_bus_space; + sc->sc_bas.bsh = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ; + /* regshft = 2, rclk = 66000000, rid = 0, chan = 0 */ + return (uart_bus_probe(dev, 2, 133000000, 0, 0)); +} + +DRIVER_MODULE(uart, iodi, uart_iodi_driver, uart_devclass, 0, 0); diff --git a/sys/mips/nlm/uart_cpu_mips_xlp.c b/sys/mips/nlm/uart_cpu_mips_xlp.c new file mode 100644 index 0000000..07bdd6a --- /dev/null +++ b/sys/mips/nlm/uart_cpu_mips_xlp.c @@ -0,0 +1,89 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +/* + * Skeleton of this file was based on respective code for ARM + * code written by Olivier Houchard. + */ +/* + * XLRMIPS: This file is hacked from arm/... + */ +#include "opt_uart.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/cons.h> +#include <sys/kdb.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> + +#include <machine/bus.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_cpu.h> + +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/uart.h> + +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; + +int +uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) +{ + return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); +} + + +int +uart_cpu_getdev(int devtype, struct uart_devinfo *di) +{ + di->ops = uart_getops(&uart_ns8250_class); + di->bas.chan = 0; + di->bas.bst = rmi_bus_space; + di->bas.bsh = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ; + + di->bas.regshft = 2; + /* divisor = rclk / (baudrate * 16); */ + di->bas.rclk = 133000000; + di->baudrate = 115200; + di->databits = 8; + di->stopbits = 1; + di->parity = UART_PARITY_NONE; + + uart_bus_space_io = NULL; + uart_bus_space_mem = rmi_bus_space; + return (0); +} diff --git a/sys/mips/nlm/xlp.h b/sys/mips/nlm/xlp.h new file mode 100644 index 0000000..5c79aaf --- /dev/null +++ b/sys/mips/nlm/xlp.h @@ -0,0 +1,133 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$ + * NETLOGIC_BSD */ + +#ifndef __NLM_XLP_H__ +#define __NLM_XLP_H__ +#include <mips/nlm/hal/pic.h> + +#define XLP_PIC_IRT_UART0_IRQ 9 +#define XLP_PIC_IRT_UART1_IRQ 10 + +#define XLP_PIC_IRT_PCIE0_IRQ 11 +#define XLP_PIC_IRT_PCIE1_IRQ 12 +#define XLP_PIC_IRT_PCIE2_IRQ 13 +#define XLP_PIC_IRT_PCIE3_IRQ 14 + +#define XLP_PIC_IRT_EHCI0_IRQ 39 +#define XLP_PIC_IRT_EHCI1_IRQ 42 +#define XLP_PIC_IRT_MMC_IRQ 43 + + +#ifndef LOCORE +/* + * FreeBSD can be started with few threads and cores turned off, + * so have a hardware thread id to FreeBSD cpuid mapping. + */ +extern int xlp_ncores; +extern int xlp_threads_per_core; +extern uint32_t xlp_hw_thread_mask; +extern int xlp_cpuid_to_hwtid[]; +extern int xlp_hwtid_to_cpuid[]; +#ifdef SMP +extern void xlp_enable_threads(int code); +#endif + +extern uint64_t xlp_pic_base; /* TODO just for node 0 now */ + +static __inline__ int +xlp_irt_to_irq(int irt) +{ + switch (irt) { + case XLP_PIC_IRT_MMC_INDEX : + return XLP_PIC_IRT_MMC_IRQ; + case XLP_PIC_IRT_EHCI0_INDEX : + return XLP_PIC_IRT_EHCI0_IRQ; + case XLP_PIC_IRT_EHCI1_INDEX : + return XLP_PIC_IRT_EHCI1_IRQ; + case XLP_PIC_IRT_UART0_INDEX : + return XLP_PIC_IRT_UART0_IRQ; + case XLP_PIC_IRT_UART1_INDEX : + return XLP_PIC_IRT_UART1_IRQ; + case XLP_PIC_IRT_PCIE_LINK0_INDEX : + return XLP_PIC_IRT_PCIE0_IRQ; + case XLP_PIC_IRT_PCIE_LINK1_INDEX : + return XLP_PIC_IRT_PCIE1_IRQ; + case XLP_PIC_IRT_PCIE_LINK2_INDEX : + return XLP_PIC_IRT_PCIE2_IRQ; + case XLP_PIC_IRT_PCIE_LINK3_INDEX : + return XLP_PIC_IRT_PCIE3_IRQ; + default: panic("Bad IRT %d\n", irt); + } +} + +static __inline__ int +xlp_irq_to_irt(int irq) +{ + switch (irq) { + case XLP_PIC_IRT_MMC_IRQ : + return XLP_PIC_IRT_MMC_INDEX; + case XLP_PIC_IRT_EHCI0_IRQ : + return XLP_PIC_IRT_EHCI0_INDEX; + case XLP_PIC_IRT_EHCI1_IRQ : + return XLP_PIC_IRT_EHCI1_INDEX; + case XLP_PIC_IRT_UART0_IRQ : + return XLP_PIC_IRT_UART0_INDEX; + case XLP_PIC_IRT_UART1_IRQ : + return XLP_PIC_IRT_UART1_INDEX; + case XLP_PIC_IRT_PCIE0_IRQ : + return XLP_PIC_IRT_PCIE_LINK0_INDEX; + case XLP_PIC_IRT_PCIE1_IRQ : + return XLP_PIC_IRT_PCIE_LINK1_INDEX; + case XLP_PIC_IRT_PCIE2_IRQ : + return XLP_PIC_IRT_PCIE_LINK2_INDEX; + case XLP_PIC_IRT_PCIE3_IRQ : + return XLP_PIC_IRT_PCIE_LINK3_INDEX; + default: panic("Bad IRQ %d\n", irq); + } +} + +static __inline__ int +xlp_irq_is_picintr(int irq) +{ + switch (irq) { + case XLP_PIC_IRT_MMC_IRQ : return 1; + case XLP_PIC_IRT_EHCI0_IRQ : return 1; + case XLP_PIC_IRT_EHCI1_IRQ : return 1; + case XLP_PIC_IRT_UART0_IRQ : return 1; + case XLP_PIC_IRT_UART1_IRQ : return 1; + case XLP_PIC_IRT_PCIE0_IRQ : return 1; + case XLP_PIC_IRT_PCIE1_IRQ : return 1; + case XLP_PIC_IRT_PCIE2_IRQ : return 1; + case XLP_PIC_IRT_PCIE3_IRQ : return 1; + default: return 0; + } +} +#endif /* LOCORE */ +#endif /* __NLM_XLP_H__ */ diff --git a/sys/mips/nlm/xlp_machdep.c b/sys/mips/nlm/xlp_machdep.c new file mode 100644 index 0000000..4bf92462 --- /dev/null +++ b/sys/mips/nlm/xlp_machdep.c @@ -0,0 +1,667 @@ +/*- + * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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. + * + * NETLOGIC_BSD */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_ddb.h" + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/rtprio.h> +#include <sys/systm.h> +#include <sys/interrupt.h> +#include <sys/limits.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/random.h> + +#include <sys/cons.h> /* cinit() */ +#include <sys/kdb.h> +#include <sys/reboot.h> +#include <sys/queue.h> +#include <sys/smp.h> +#include <sys/timetc.h> + +#include <vm/vm.h> +#include <vm/vm_page.h> + +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/cpuinfo.h> +#include <machine/tlb.h> +#include <machine/cpuregs.h> +#include <machine/frame.h> +#include <machine/hwfunc.h> +#include <machine/md_var.h> +#include <machine/asm.h> +#include <machine/pmap.h> +#include <machine/trap.h> +#include <machine/clock.h> +#include <machine/fls64.h> +#include <machine/intr_machdep.h> +#include <machine/smp.h> + +#include <mips/nlm/hal/mips-extns.h> +#include <mips/nlm/hal/mmio.h> +#include <mips/nlm/hal/iomap.h> +#include <mips/nlm/hal/cop0.h> +#include <mips/nlm/hal/sys.h> +#include <mips/nlm/hal/pic.h> +#include <mips/nlm/hal/uart.h> +#include <mips/nlm/hal/mmu.h> +#include <mips/nlm/hal/bridge.h> +#include <mips/nlm/hal/cpucontrol.h> + +#include <mips/nlm/clock.h> +#include <mips/nlm/interrupt.h> +#include <mips/nlm/board.h> +#include <mips/nlm/xlp.h> + +/* 4KB static data aread to keep a copy of the bootload env until + the dynamic kenv is setup */ +char boot1_env[4096]; +int xlp_argc; +char **xlp_argv, **xlp_envp; + +uint64_t xlp_cpu_frequency; +uint64_t nlm_pcicfg_baseaddr = MIPS_PHYS_TO_KSEG1(XLP_DEFAULT_IO_BASE); + +int xlp_ncores; +int xlp_threads_per_core; +uint32_t xlp_hw_thread_mask; +int xlp_cpuid_to_hwtid[MAXCPU]; +int xlp_hwtid_to_cpuid[MAXCPU]; +uint64_t xlp_pic_base; + +static int xlp_mmuval; + +extern uint32_t _end; +extern char XLPResetEntry[], XLPResetEntryEnd[]; + +static void +xlp_setup_core(void) +{ + uint64_t reg; + + reg = nlm_mfcr(XLP_LSU_DEFEATURE); + /* Enable Unaligned and L2HPE */ + reg |= (1 << 30) | (1 << 23); + /* + * Experimental : Enable SUE + * Speculative Unmap Enable. Enable speculative L2 cache request for + * unmapped access. + */ + reg |= (1ull << 31); + /* Clear S1RCM - A0 errata */ + reg &= ~0xeull; + nlm_mtcr(XLP_LSU_DEFEATURE, reg); + + reg = nlm_mfcr(XLP_SCHED_DEFEATURE); + /* Experimental: Disable BRU accepting ALU ops - A0 errata */ + reg |= (1 << 24); + nlm_mtcr(XLP_SCHED_DEFEATURE, reg); +} + +static void +xlp_setup_mmu(void) +{ + + nlm_setup_extended_pagemask(0); /* pagemask = 0 for 4K pages */ + nlm_large_variable_tlb_en(0); + nlm_extended_tlb_en(1); + nlm_mmu_setup(0, 0, 0); +} + +static void +xlp_parse_mmu_options(void) +{ + int i, j, k; + uint32_t cpu_map = xlp_hw_thread_mask; + uint32_t core0_thr_mask, core_thr_mask; + +#ifndef SMP /* Uniprocessor! */ + if (cpu_map != 0x1) { + printf("WARNING: Starting uniprocessor kernel on cpumask [0x%lx]!\n" + "WARNING: Other CPUs will be unused.\n", (u_long)cpu_map); + cpu_map = 0x1; + } +#endif + + xlp_ncores = 1; + core0_thr_mask = cpu_map & 0xf; + switch (core0_thr_mask) { + case 1: + xlp_threads_per_core = 1; + xlp_mmuval = 0; + break; + case 3: + xlp_threads_per_core = 2; + xlp_mmuval = 2; + break; + case 0xf: + xlp_threads_per_core = 4; + xlp_mmuval = 3; + break; + default: + goto unsupp; + } + + /* Verify other cores CPU masks */ + for (i = 1; i < XLP_MAX_CORES; i++) { + core_thr_mask = (cpu_map >> (i*4)) & 0xf; + if (core_thr_mask) { + if (core_thr_mask != core0_thr_mask) + goto unsupp; + xlp_ncores++; + } + } + + xlp_hw_thread_mask = cpu_map; + /* setup hardware processor id to cpu id mapping */ + for (i = 0; i< MAXCPU; i++) + xlp_cpuid_to_hwtid[i] = + xlp_hwtid_to_cpuid [i] = -1; + for (i = 0, k = 0; i < XLP_MAX_CORES; i++) { + if (((cpu_map >> (i*4)) & 0xf) == 0) + continue; + for (j = 0; j < xlp_threads_per_core; j++) { + xlp_cpuid_to_hwtid[k] = i*4 + j; + xlp_hwtid_to_cpuid[i*4 + j] = k; + k++; + } + } + +#ifdef SMP + /* + * We will enable the other threads in core 0 here + * so that the TLB and cache info is correct when + * mips_init runs + */ + xlp_enable_threads(xlp_mmuval); +#endif + /* setup for the startup core */ + xlp_setup_mmu(); + return; + +unsupp: + printf("ERROR : Unsupported CPU mask [use 1,2 or 4 threads per core].\n" + "\tcore0 thread mask [%lx], boot cpu mask [%lx]\n" + "\tUsing default, 16 TLB entries per CPU, split mode\n", + (u_long)core0_thr_mask, (u_long)cpu_map); + panic("Invalid CPU mask - halting.\n"); + return; +} + +static void +xlp_set_boot_flags(void) +{ + char *p; + + p = getenv("bootflags"); + if (p == NULL) + return; + + for (; p && *p != '\0'; p++) { + switch (*p) { + case 'd': + case 'D': + boothowto |= RB_KDB; + break; + case 'g': + case 'G': + boothowto |= RB_GDB; + break; + case 'v': + case 'V': + boothowto |= RB_VERBOSE; + break; + + case 's': /* single-user (default, supported for sanity) */ + case 'S': + boothowto |= RB_SINGLE; + break; + + default: + printf("Unrecognized boot flag '%c'.\n", *p); + break; + } + } + + freeenv(p); + return; +} + +static void +mips_init(void) +{ + init_param1(); + init_param2(physmem); + + mips_cpu_init(); + cpuinfo.cache_coherent_dma = TRUE; + pmap_bootstrap(); +#ifdef DDB + kdb_init(); + if (boothowto & RB_KDB) { + kdb_enter("Boot flags requested debugger", NULL); + } +#endif + mips_proc0_init(); + mutex_init(); +} + +unsigned int +platform_get_timecount(struct timecounter *tc __unused) +{ + + return ((unsigned int)~nlm_pic_read_systimer(xlp_pic_base, 7)); +} + +static void +xlp_pic_init(void) +{ + struct timecounter pic_timecounter = { + platform_get_timecount, /* get_timecount */ + 0, /* no poll_pps */ + ~0U, /* counter_mask */ + XLP_PIC_TIMER_FREQ, /* frequency */ + "XLRPIC", /* name */ + 2000, /* quality (adjusted in code) */ + }; + int i; + + xlp_pic_base = nlm_regbase_pic(0); /* TOOD: Add other nodes */ + printf("Initializing PIC...@%jx\n", (uintmax_t)xlp_pic_base); + /* Bind all PIC irqs to cpu 0 */ + for(i = 0; i < XLP_PIC_MAX_IRT; i++) { + nlm_pic_write_irt_raw(xlp_pic_base, i, 0, 0, 1, 0, + 1, 0, 0x1); + } + + nlm_pic_set_systimer(xlp_pic_base, 7, ~0ULL, 0, 0, 0, 0); + platform_timecounter = &pic_timecounter; +} + +#if defined(__mips_n32) || defined(__mips_n64) /* PHYSADDR_64_BIT */ +#ifdef XLP_SIM +#define XLP_MEM_LIM 0x200000000ULL +#else +#define XLP_MEM_LIM 0x10000000000ULL +#endif +#else +#define XLP_MEM_LIM 0xfffff000UL +#endif +static void +xlp_mem_init(void) +{ + uint64_t bridgebase = nlm_regbase_bridge(0); /* TOOD: Add other nodes */ + vm_size_t physsz = 0; + uint64_t base, lim, val; + int i, j; + + for (i = 0, j = 0; i < 8; i++) { + val = nlm_rdreg_bridge(bridgebase, XLP_BRIDGE_DRAM_BAR_REG(i)); + base = ((val >> 12) & 0xfffff) << 20; + val = nlm_rdreg_bridge(bridgebase, XLP_BRIDGE_DRAM_LIMIT_REG(i)); + lim = ((val >> 12) & 0xfffff) << 20; + + /* BAR not enabled */ + if (lim == 0) + continue; + + /* first bar, start a bit after end */ + if (base == 0) { + base = (vm_paddr_t)MIPS_KSEG0_TO_PHYS(&_end) + 0x20000; + lim = 0x0c000000; /* TODO : hack to avoid uboot packet mem */ + } + if (base >= XLP_MEM_LIM) { + printf("Mem [%d]: Ignore %#jx - %#jx\n", i, + (intmax_t)base, (intmax_t)lim); + continue; + } + if (lim > XLP_MEM_LIM) { + printf("Mem [%d]: Restrict %#jx -> %#jx\n", i, + (intmax_t)lim, (intmax_t)XLP_MEM_LIM); + lim = XLP_MEM_LIM; + } + if (lim <= base) { + printf("Mem[%d]: Malformed %#jx -> %#jx\n", i, + (intmax_t)base, (intmax_t)lim); + continue; + } + + /* + * Exclude reset entry memory range 0x1fc00000 - 0x20000000 + * from free memory + */ + if (base <= 0x1fc00000 && (base + lim) > 0x1fc00000) { + uint64_t base0, lim0, base1, lim1; + + base0 = base; + lim0 = 0x1fc00000; + base1 = 0x20000000; + lim1 = lim; + + if (lim0 > base0) { + phys_avail[j++] = (vm_paddr_t)base0; + phys_avail[j++] = (vm_paddr_t)lim0; + physsz += lim0 - base0; + printf("Mem[%d]: %#jx - %#jx (excl reset)\n", i, + (intmax_t)base0, (intmax_t)lim0); + } + if (lim1 > base1) { + phys_avail[j++] = (vm_paddr_t)base1; + phys_avail[j++] = (vm_paddr_t)lim1; + physsz += lim1 - base1; + printf("Mem[%d]: %#jx - %#jx (excl reset)\n", i, + (intmax_t)base1, (intmax_t)lim1); + } + } else { + phys_avail[j++] = (vm_paddr_t)base; + phys_avail[j++] = (vm_paddr_t)lim; + physsz += lim - base; + printf("Mem[%d]: %#jx - %#jx\n", i, + (intmax_t)base, (intmax_t)lim); + } + + } + + /* setup final entry with 0 */ + phys_avail[j] = phys_avail[j + 1] = 0; + realmem = physmem = btoc(physsz); +} + +static uint32_t +xlp_get_cpu_frequency(void) +{ + uint64_t sysbase = nlm_regbase_sys(0); + unsigned int pll_divf, pll_divr, dfs_div, num, denom; + uint32_t val; + + val = nlm_rdreg_sys(sysbase, XLP_SYS_POWER_ON_RESET_REG); + pll_divf = (val >> 10) & 0x7f; + pll_divr = (val >> 8) & 0x3; + dfs_div = (val >> 17) & 0x3; + + num = pll_divf + 1; + denom = 3 * (pll_divr + 1) * (1<< (dfs_div + 1)); + val = 800000000ULL * num / denom; + return (val); +} + +void +platform_start(__register_t a0 __unused, + __register_t a1 __unused, + __register_t a2 __unused, + __register_t a3 __unused) +{ + int i; + + xlp_argc = 1; + /* + * argv and envp are passed in array of 32bit pointers + */ + xlp_argv = NULL; + xlp_envp = NULL; + + /* Initialize pcpu stuff */ + mips_pcpu0_init(); + + /* initialize console so that we have printf */ + boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */ + + /* For now */ + boothowto |= RB_VERBOSE; + boothowto |= RB_SINGLE; + bootverbose++; + + /* clockrate used by delay, so initialize it here */ + xlp_cpu_frequency = xlp_get_cpu_frequency(); + cpu_clock = xlp_cpu_frequency / 1000000; + mips_timer_early_init(xlp_cpu_frequency); + + /* Init console please */ + cninit(); + + /* Environment */ + printf("Args %#jx %#jx %#jx %#jx:\n", (intmax_t)a0, + (intmax_t)a1, (intmax_t)a2, (intmax_t)a3); + xlp_hw_thread_mask = a0; + init_static_kenv(boot1_env, sizeof(boot1_env)); + printf("Environment (from %d args):\n", xlp_argc - 1); + if (xlp_argc == 1) + printf("\tNone\n"); + for (i = 1; i < xlp_argc; i++) { + char *n, *arg; + + arg = (char *)(intptr_t)xlp_argv[i]; + printf("\t%s\n", arg); + n = strsep(&arg, "="); + if (arg == NULL) + setenv(n, "1"); + else + setenv(n, arg); + } + + /* Early core init and fixes for errata */ + xlp_setup_core(); + + xlp_set_boot_flags(); + xlp_parse_mmu_options(); + + xlp_mem_init(); + + bcopy(XLPResetEntry, (void *)MIPS_RESET_EXC_VEC, + XLPResetEntryEnd - XLPResetEntry); + + /* + * MIPS generic init + */ + mips_init(); + /* + * XLP specific post initialization + * initialize other on chip stuff + */ + nlm_board_info_setup(); + xlp_pic_init(); + + mips_timer_init_params(xlp_cpu_frequency, 0); + + printf("Platform specific startup now completes\n"); +} + +void +platform_cpu_init() +{ +} + +void +platform_identify(void) +{ + + printf("XLP Eval Board\n"); +} + +/* + * XXX Maybe return the state of the watchdog in enter, and pass it to + * exit? Like spl(). + */ +void +platform_trap_enter(void) +{ +} + +void +platform_reset(void) +{ + uint64_t sysbase = nlm_regbase_sys(0); + + nlm_wreg_sys(sysbase, XLP_SYS_CHIP_RESET_REG, 1); + for(;;) + __asm __volatile("wait"); +} + +void +platform_trap_exit(void) +{ +} + +#ifdef SMP +/* + * XLP threads are started simultaneously when we enable threads, this will + * ensure that the threads are blocked in platform_init_ap, until they are + * ready to proceed to smp_init_secondary() + */ +static volatile int thr_unblock[4]; + +int +platform_start_ap(int cpuid) +{ + uint32_t coremask, val; + uint64_t sysbase = nlm_regbase_sys(0); + int hwtid = xlp_cpuid_to_hwtid[cpuid]; + int core, thr; + + core = hwtid / 4; + thr = hwtid % 4; + if (thr == 0) { + /* First thread in core, do core wake up */ + coremask = 1u << core; + + /* Enable core clock */ + val = nlm_rdreg_sys(sysbase, XLP_SYS_CORE_DFS_DIS_CTRL_REG); + val &= ~coremask; + nlm_wreg_sys(sysbase, XLP_SYS_CORE_DFS_DIS_CTRL_REG, val); + + /* Remove CPU Reset */ + val = nlm_rdreg_sys(sysbase, XLP_SYS_CPU_RESET_REG); + val &= ~coremask & 0xff; + nlm_wreg_sys(sysbase, XLP_SYS_CPU_RESET_REG, val); + + if (bootverbose) + printf("Waking up core %d ...", core); + + /* Poll for CPU to mark itself coherent */ + do { + val = nlm_rdreg_sys(sysbase, XLP_SYS_CPU_NONCOHERENT_MODE_REG); + } while ((val & coremask) != 0); + if (bootverbose) + printf("Done\n"); + } else { + /* otherwise release the threads stuck in platform_init_ap */ + thr_unblock[thr] = 1; + } + + return (0); +} + +void +platform_init_ap(int cpuid) +{ + uint32_t stat; + int thr; + + /* The first thread has to setup the MMU and enable other threads */ + thr = nlm_threadid(); + if (thr == 0) { + xlp_setup_core(); + xlp_enable_threads(xlp_mmuval); + xlp_setup_mmu(); + } else { + /* + * FIXME busy wait here eats too many cycles, especially + * in the core 0 while bootup + */ + while (thr_unblock[thr] == 0) + __asm__ __volatile__ ("nop;nop;nop;nop"); + thr_unblock[thr] = 0; + } + + stat = mips_rd_status(); + KASSERT((stat & MIPS_SR_INT_IE) == 0, + ("Interrupts enabled in %s!", __func__)); + stat |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT; + mips_wr_status(stat); + + nlm_write_c0_eimr(0ull); + xlp_enable_irq(IRQ_IPI); + xlp_enable_irq(IRQ_TIMER); + xlp_enable_irq(IRQ_MSGRING); + + return; +} + +int +platform_ipi_intrnum(void) +{ + + return (IRQ_IPI); +} + +void +platform_ipi_send(int cpuid) +{ + nlm_pic_send_ipi(xlp_pic_base, 0, xlp_cpuid_to_hwtid[cpuid], + platform_ipi_intrnum(), 0); +} + +void +platform_ipi_clear(void) +{ +} + +int +platform_processor_id(void) +{ + + return (xlp_hwtid_to_cpuid[nlm_cpuid()]); +} + +void +platform_cpu_mask(cpuset_t *mask) +{ + int i, s; + + CPU_ZERO(mask); + s = xlp_ncores * xlp_threads_per_core; + for (i = 0; i < s; i++) + CPU_SET(i, mask); +} + +struct cpu_group * +platform_smp_topo() +{ + + return (smp_topo_2level(CG_SHARE_L2, xlp_ncores, CG_SHARE_L1, + xlp_threads_per_core, CG_FLAG_THREAD)); +} +#endif |