Home | History | Annotate | Line # | Download | only in cavium
octeonvar.h revision 1.11
      1 /*	$NetBSD: octeonvar.h,v 1.11 2020/06/18 13:52:08 simonb Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #ifndef _MIPS_OCTEON_OCTEONVAR_H_
     33 #define _MIPS_OCTEON_OCTEONVAR_H_
     34 
     35 #include <sys/bus.h>
     36 #include <sys/evcnt.h>
     37 #include <sys/kcpuset.h>
     38 #include <mips/locore.h>
     39 #include <dev/pci/pcivar.h>
     40 
     41 #include <mips/cavium/octeonreg.h>
     42 
     43 /* XXX elsewhere */
     44 #define	_ASM_PROLOGUE \
     45 		"	.set push			\n" \
     46 		"	.set noreorder			\n"
     47 #define	_ASM_PROLOGUE_MIPS64 \
     48 		_ASM_PROLOGUE				\
     49 		"	.set mips64			\n"
     50 #define	_ASM_PROLOGUE_OCTEON \
     51 		_ASM_PROLOGUE				\
     52 		"	.set arch=octeon		\n"
     53 #define	_ASM_EPILOGUE \
     54 		"	.set pop			\n"
     55 /*
     56  * subbits = __BITS64_GET(XXX, bits);
     57  * bits = __BITS64_SET(XXX, subbits);
     58  */
     59 #ifndef	__BITS64_GET
     60 #define	__BITS64_GET(name, bits)	\
     61 	    (((uint64_t)(bits) & name) >> name##_SHIFT)
     62 #endif
     63 #ifndef	__BITS64_SET
     64 #define	__BITS64_SET(name, subbits)	\
     65 	    (((uint64_t)(subbits) << name##_SHIFT) & name)
     66 #endif
     67 
     68 #ifdef _KERNEL
     69 extern int	octeon_core_ver;
     70 #endif /* _KERNEL */
     71 #define	OCTEON_1		1
     72 #define	OCTEON_PLUS		10	/* arbitary, keep sequence for others */
     73 #define	OCTEON_2		2
     74 #define	OCTEON_3		3
     75 
     76 struct octeon_config {
     77 	struct mips_bus_space mc_iobus_bust;
     78 	struct mips_bus_space mc_bootbus_bust;
     79 	struct mips_pci_chipset mc_pc;
     80 
     81 	struct mips_bus_dma_tag mc_iobus_dmat;
     82 	struct mips_bus_dma_tag mc_bootbus_dmat;
     83 	struct mips_bus_dma_tag mc_core1_dmat;
     84 	struct mips_bus_dma_tag mc_fpa_dmat;
     85 
     86 	struct extent *mc_io_ex;
     87 	struct extent *mc_mem_ex;
     88 
     89 	int	mc_mallocsafe;
     90 };
     91 
     92 #define NIRQS	64
     93 
     94 struct cpu_softc {
     95 	struct cpu_info *cpu_ci;
     96 
     97 	uint64_t cpu_int0_sum0;
     98 	uint64_t cpu_int1_sum0;
     99 	uint64_t cpu_int2_sum0;
    100 
    101 	uint64_t cpu_int0_en0;
    102 	uint64_t cpu_int1_en0;
    103 	uint64_t cpu_int2_en0;
    104 
    105 	uint64_t cpu_int0_en1;
    106 	uint64_t cpu_int1_en1;
    107 	uint64_t cpu_int2_en1;
    108 
    109 	uint64_t cpu_int32_en;
    110 
    111 	struct evcnt cpu_intr_evs[NIRQS];
    112 
    113 	uint64_t cpu_int0_enable0;
    114 	uint64_t cpu_int1_enable0;
    115 	uint64_t cpu_int2_enable0;
    116 
    117 	void *cpu_wdog_sih;		// wdog softint handler
    118 	uint64_t cpu_wdog;
    119 	uint64_t cpu_pp_poke;
    120 
    121 #ifdef MULTIPROCESSOR
    122 	uint64_t cpu_mbox_set;
    123 	uint64_t cpu_mbox_clr;
    124 #endif
    125 };
    126 
    127 /*
    128  * FPA map
    129  */
    130 
    131 #define	OCTEON_POOL_NO_PKT	0
    132 #define	OCTEON_POOL_NO_WQE	1
    133 #define	OCTEON_POOL_NO_CMD	2
    134 #define	OCTEON_POOL_NO_SG	3
    135 #define	OCTEON_POOL_NO_XXX_4	4
    136 #define	OCTEON_POOL_NO_XXX_5	5
    137 #define	OCTEON_POOL_NO_XXX_6	6
    138 #define	OCTEON_POOL_NO_DUMP	7	/* FPA debug dump */
    139 
    140 #define	OCTEON_POOL_SIZE_PKT	2048	/* 128 x 16 */
    141 #define	OCTEON_POOL_SIZE_WQE	128	/* 128 x 1 */
    142 #define	OCTEON_POOL_SIZE_CMD	1024	/* 128 x 8 */
    143 #define	OCTEON_POOL_SIZE_SG	512	/* 128 x 4 */
    144 #define	OCTEON_POOL_SIZE_XXX_4	0
    145 #define	OCTEON_POOL_SIZE_XXX_5	0
    146 #define	OCTEON_POOL_SIZE_XXX_6	0
    147 #define	OCTEON_POOL_SIZE_XXX_7	0
    148 
    149 #define	OCTEON_POOL_NELEMS_PKT		4096
    150 #define	OCTEON_POOL_NELEMS_WQE		4096
    151 #define	OCTEON_POOL_NELEMS_CMD		32
    152 #define	OCTEON_POOL_NELEMS_SG		1024
    153 #define	OCTEON_POOL_NELEMS_XXX_4	0
    154 #define	OCTEON_POOL_NELEMS_XXX_5	0
    155 #define	OCTEON_POOL_NELEMS_XXX_6	0
    156 #define	OCTEON_POOL_NELEMS_XXX_7	0
    157 
    158 /*
    159  * CVMSEG (``scratch'') memory map
    160  */
    161 
    162 #define CVMSEG_LM_RNM_SIZE	16	/* limited by CN70XX hardware (why?) */
    163 #define CVMSEG_LM_ETHER_COUNT	4	/* limits number of cnmac devices */
    164 
    165 struct octeon_cvmseg_map {
    166 	uint64_t		csm_pow_intr;
    167 
    168 	struct octeon_cvmseg_ether_map {
    169 		uint64_t	csm_ether_fau_done;
    170 	} csm_ether[CVMSEG_LM_ETHER_COUNT];
    171 
    172 	uint64_t	csm_rnm[CVMSEG_LM_RNM_SIZE];
    173 } __packed;
    174 #define	OCTEON_CVMSEG_OFFSET(entry) \
    175 	offsetof(struct octeon_cvmseg_map, entry)
    176 #define	OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \
    177 	(offsetof(struct octeon_cvmseg_map, csm_ether) + \
    178 	 sizeof(struct octeon_cvmseg_ether_map) * (n) + \
    179 	 offsetof(struct octeon_cvmseg_ether_map, entry))
    180 
    181 /*
    182  * FAU register map
    183  *
    184  * => FAU registers exist in FAU unit
    185  * => devices (PKO) can access these registers
    186  * => CPU can read those values after loading them into CVMSEG
    187  */
    188 struct octfau_map {
    189 	struct {
    190 		/* PKO command index */
    191 		uint64_t	_fau_map_port_pkocmdidx;
    192 		/* send requested */
    193 		uint64_t	_fau_map_port_txreq;
    194 		/* send completed */
    195 		uint64_t	_fau_map_port_txdone;
    196 		/* XXX */
    197 		uint64_t	_fau_map_port_pad;
    198 	} __packed _fau_map_port[3];
    199 };
    200 
    201 /*
    202  * POW qos/group map
    203  */
    204 
    205 #define	OCTEON_POW_QOS_PIP		0
    206 #define	OCTEON_POW_QOS_CORE1		1
    207 #define	OCTEON_POW_QOS_XXX_2		2
    208 #define	OCTEON_POW_QOS_XXX_3		3
    209 #define	OCTEON_POW_QOS_XXX_4		4
    210 #define	OCTEON_POW_QOS_XXX_5		5
    211 #define	OCTEON_POW_QOS_XXX_6		6
    212 #define	OCTEON_POW_QOS_XXX_7		7
    213 
    214 #define	OCTEON_POW_GROUP_PIP		0
    215 #define	OCTEON_POW_GROUP_XXX_1		1
    216 #define	OCTEON_POW_GROUP_XXX_2		2
    217 #define	OCTEON_POW_GROUP_XXX_3		3
    218 #define	OCTEON_POW_GROUP_XXX_4		4
    219 #define	OCTEON_POW_GROUP_XXX_5		5
    220 #define	OCTEON_POW_GROUP_XXX_6		6
    221 #define	OCTEON_POW_GROUP_CORE1_SEND	7
    222 #define	OCTEON_POW_GROUP_CORE1_TASK_0	8
    223 #define	OCTEON_POW_GROUP_CORE1_TASK_1	9
    224 #define	OCTEON_POW_GROUP_CORE1_TASK_2	10
    225 #define	OCTEON_POW_GROUP_CORE1_TASK_3	11
    226 #define	OCTEON_POW_GROUP_CORE1_TASK_4	12
    227 #define	OCTEON_POW_GROUP_CORE1_TASK_5	13
    228 #define	OCTEON_POW_GROUP_CORE1_TASK_6	14
    229 #define	OCTEON_POW_GROUP_CORE1_TASK_7	15
    230 
    231 #ifdef _KERNEL
    232 extern struct octeon_config	octeon_configuration;
    233 #ifdef MULTIPROCESSOR
    234 extern kcpuset_t		*cpus_booted;
    235 extern struct cpu_softc		octeon_cpu1_softc;
    236 #endif
    237 
    238 const char	*octeon_cpu_model(mips_prid_t);
    239 
    240 void		octeon_bus_io_init(bus_space_tag_t, void *);
    241 void		octeon_bus_mem_init(bus_space_tag_t, void *);
    242 void		octeon_cal_timer(int);
    243 void		octeon_dma_init(struct octeon_config *);
    244 void		octeon_intr_init(struct cpu_info *);
    245 void		octeon_iointr(int, vaddr_t, uint32_t);
    246 void		octpci_init(pci_chipset_tag_t, struct octeon_config *);
    247 void		*octeon_intr_establish(int, int, int (*)(void *), void *);
    248 void		octeon_intr_disestablish(void *cookie);
    249 
    250 int		octeon_ioclock_speed(void);
    251 void		octeon_soft_reset(void);
    252 
    253 void		octeon_reset_vector(void);
    254 uint64_t	mips_cp0_cvmctl_read(void);
    255 void		mips_cp0_cvmctl_write(uint64_t);
    256 #endif /* _KERNEL */
    257 
    258 #if defined(__mips_n32)
    259 #define ffs64	__builtin_ffsll
    260 #elif defined(_LP64)
    261 #define ffs64	__builtin_ffsl
    262 #else
    263 #error unknown ABI
    264 #endif
    265 
    266 /*
    267  * Prefetch
    268  *
    269  *	OCTEON_PREF		normal (L1 and L2)
    270  *	OCTEON_PREF_L1		L1 only
    271  *	OCTEON_PREF_L2		L2 only
    272  *	OCTEON_PREF_DWB		don't write back
    273  *	OCTEON_PREF_PFS		prepare for store
    274  */
    275 #define __OCTEON_PREF_N(n, base, offset)			\
    276 	__asm __volatile (					\
    277 		"	.set	push				\
    278 		"	.set	arch=octeon			\n" \
    279 		"	pref	"#n", "#offset"(%[base])	\n" \
    280 		"	.set	pop				\
    281 		: : [base] "d" (base)				\
    282 	)
    283 #define __OCTEON_PREF_0(base, offset)	__OCTEON_PREF_N(0, base, offset)
    284 #define __OCTEON_PREF_4(base, offset)	__OCTEON_PREF_N(4, base, offset)
    285 #define __OCTEON_PREF_28(base, offset)	__OCTEON_PREF_N(28, base, offset)
    286 #define __OCTEON_PREF_29(base, offset)	__OCTEON_PREF_N(29, base, offset)
    287 #define __OCTEON_PREF_30(base, offset)	__OCTEON_PREF_N(30, base, offset)
    288 #define OCTEON_PREF(base, offset)	__OCTEON_PREF_0(base, offset)
    289 #define OCTEON_PREF_L1(base, offset)	__OCTEON_PREF_4(base, offset)
    290 #define OCTEON_PREF_L2(base, offset)	__OCTEON_PREF_28(base, offset)
    291 #define OCTEON_PREF_DWB(base, offset)	__OCTEON_PREF_29(base, offset)
    292 #define OCTEON_PREF_PFS(base, offset)	__OCTEON_PREF_30(base, offset)
    293 
    294 /*
    295  * Sync
    296  */
    297 #define OCTEON_SYNCCOMMON(name) \
    298 	__asm __volatile ( \
    299 		_ASM_PROLOGUE_OCTEON			\
    300 		"	"#name"				\n" \
    301 		_ASM_EPILOGUE				\
    302 		::: "memory")
    303 #define OCTEON_SYNCIOBDMA	OCTEON_SYNCCOMMON(synciobdma)
    304 #define OCTEON_SYNCW		OCTEON_SYNCCOMMON(syncw)
    305 #define OCTEON_SYNC		OCTEON_SYNCCOMMON(sync)
    306 #define OCTEON_SYNCWS		OCTEON_SYNCCOMMON(syncws)
    307 #define OCTEON_SYNCS		OCTEON_SYNCCOMMON(syncs)
    308 /* XXX backward compatibility */
    309 #if 1
    310 #define	OCT_SYNCIOBDMA		OCTEON_SYNCIOBDMA
    311 #define	OCT_SYNCW		OCTEON_SYNCW
    312 #define	OCT_SYNC		OCTEON_SYNC
    313 #define	OCT_SYNCWS		OCTEON_SYNCWS
    314 #define	OCT_SYNCS		OCTEON_SYNCS
    315 #endif
    316 
    317 /* octeon core does not use cca to determine cacheability */
    318 #define OCTEON_CCA_NONE UINT64_C(0)
    319 
    320 static __inline uint64_t
    321 octeon_xkphys_read_8(paddr_t address)
    322 {
    323 	return mips3_ld(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address));
    324 }
    325 
    326 static __inline void
    327 octeon_xkphys_write_8(paddr_t address, uint64_t value)
    328 {
    329 	mips3_sd(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address), value);
    330 }
    331 
    332 /* XXX backward compatibility */
    333 #if 1
    334 #define octeon_read_csr(address) \
    335 	octeon_xkphys_read_8(address)
    336 #define octeon_write_csr(address, value) \
    337 	octeon_xkphys_write_8(address, value)
    338 #endif
    339 
    340 static __inline void
    341 octeon_iobdma_write_8(uint64_t value)
    342 {
    343 
    344 	octeon_xkphys_write_8(OCTEON_IOBDMA_ADDR, value);
    345 }
    346 
    347 static __inline uint64_t
    348 octeon_cvmseg_read_8(size_t offset)
    349 {
    350 	return octeon_xkphys_read_8(OCTEON_CVMSEG_LM + offset);
    351 }
    352 
    353 static __inline void
    354 octeon_cvmseg_write_8(size_t offset, uint64_t value)
    355 {
    356 	octeon_xkphys_write_8(OCTEON_CVMSEG_LM + offset, value);
    357 }
    358 
    359 /* XXX */
    360 static __inline uint32_t
    361 octeon_disable_interrupt(uint32_t *new)
    362 {
    363 	uint32_t s, tmp;
    364 
    365 	__asm __volatile (
    366 		_ASM_PROLOGUE
    367 		"	mfc0	%[s], $12		\n"
    368 		"	and	%[tmp], %[s], ~1	\n"
    369 		"	mtc0	%[tmp], $12		\n"
    370 		_ASM_EPILOGUE
    371 		: [s]"=&r"(s), [tmp]"=&r"(tmp));
    372 	if (new)
    373 		*new = tmp;
    374 	return s;
    375 }
    376 
    377 /* XXX */
    378 static __inline void
    379 octeon_restore_status(uint32_t s)
    380 {
    381 	__asm __volatile (
    382 		_ASM_PROLOGUE
    383 		"	mtc0	%[s], $12		\n"
    384 		_ASM_EPILOGUE
    385 		:: [s]"r"(s));
    386 }
    387 
    388 static __inline uint64_t
    389 octeon_get_cycles(void)
    390 {
    391 #if defined(__mips_o32)
    392 	uint32_t s, lo, hi;
    393 
    394 	s = octeon_disable_interrupt((void *)0);
    395 	__asm __volatile (
    396 		_ASM_PROLOGUE_MIPS64
    397 		"	dmfc0	%[lo], $9, 6		\n"
    398 		"	add	%[hi], %[lo], $0	\n"
    399 		"	srl	%[hi], 32		\n"
    400 		"	sll	%[lo], 32		\n"
    401 		"	srl	%[lo], 32		\n"
    402 		_ASM_EPILOGUE
    403 		: [lo]"=&r"(lo), [hi]"=&r"(hi));
    404 	octeon_restore_status(s);
    405 	return ((uint64_t)hi << 32) + (uint64_t)lo;
    406 #else
    407 	uint64_t tmp;
    408 
    409 	__asm __volatile (
    410 		_ASM_PROLOGUE_MIPS64
    411 		"	dmfc0	%[tmp], $9, 6		\n"
    412 		_ASM_EPILOGUE
    413 		: [tmp]"=&r"(tmp));
    414 	return tmp;
    415 #endif
    416 }
    417 
    418 /* -------------------------------------------------------------------------- */
    419 
    420 /* ---- event counter */
    421 
    422 #if defined(CNMAC_DEBUG)
    423 #define	OCTEON_EVCNT_INC(sc, name) \
    424 	do { (sc)->sc_ev_##name.ev_count++; } while (0)
    425 #define	OCTEON_EVCNT_ADD(sc, name, n) \
    426 	do { (sc)->sc_ev_##name.ev_count += (n); } while (0)
    427 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \
    428 do {								\
    429 	int i;							\
    430 	const struct octeon_evcnt_entry *ee;			\
    431 								\
    432 	for (i = 0; i < (int)__arraycount(entries); i++) {	\
    433 		ee = &(entries)[i];				\
    434 		evcnt_attach_dynamic(				\
    435 		    (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \
    436 		    ee->ee_type, ee->ee_parent, devname,	\
    437 		    ee->ee_name);				\
    438 	}							\
    439 } while (0)
    440 #else
    441 #define	OCTEON_EVCNT_INC(sc, name)
    442 #define	OCTEON_EVCNT_ADD(sc, name, n)
    443 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname)
    444 #endif
    445 
    446 struct octeon_evcnt_entry {
    447 	size_t		ee_offset;
    448 	int		ee_type;
    449 	struct evcnt	*ee_parent;
    450 	const char	*ee_name;
    451 };
    452 
    453 #define	OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \
    454 	{							\
    455 		.ee_offset = offsetof(_sc_type, sc_ev_##_var),	\
    456 		.ee_type = EVCNT_TYPE_##_ev_type,		\
    457 		.ee_parent = _parent,				\
    458 		.ee_name = _name				\
    459 	}
    460 
    461 #endif	/* _MIPS_OCTEON_OCTEONVAR_H_ */
    462