Home | History | Annotate | Line # | Download | only in cavium
octeonvar.h revision 1.1
      1 /*	$NetBSD: octeonvar.h,v 1.1 2015/04/29 08:32:00 hikaru 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 <mips/locore.h>
     37 #include <dev/pci/pcivar.h>
     38 
     39 /* XXX elsewhere */
     40 #define	_ASM_PROLOGUE \
     41 		"	.set push			\n" \
     42 		"	.set noreorder			\n"
     43 #define	_ASM_PROLOGUE_MIPS64 \
     44 		_ASM_PROLOGUE				\
     45 		"	.set mips64			\n"
     46 #define	_ASM_PROLOGUE_OCTEON \
     47 		_ASM_PROLOGUE				\
     48 		"	.set arch=octeon		\n"
     49 #define	_ASM_EPILOGUE \
     50 		"	.set pop			\n"
     51 /*
     52  * subbits = __BITS64_GET(XXX, bits);
     53  * bits = __BITS64_SET(XXX, subbits);
     54  */
     55 #ifndef	__BITS64_GET
     56 #define	__BITS64_GET(name, bits)	\
     57 	    (((uint64_t)(bits) & name) >> name##_SHIFT)
     58 #endif
     59 #ifndef	__BITS64_SET
     60 #define	__BITS64_SET(name, subbits)	\
     61 	    (((uint64_t)(subbits) << name##_SHIFT) & name)
     62 #endif
     63 
     64 struct octeon_config {
     65 	struct mips_bus_space mc_iobus_bust;
     66 	struct mips_bus_space mc_bootbus_bust;
     67 	struct mips_pci_chipset mc_pc;
     68 
     69 	struct mips_bus_dma_tag mc_iobus_dmat;
     70 	struct mips_bus_dma_tag mc_bootbus_dmat;
     71 	struct mips_bus_dma_tag mc_core1_dmat;
     72 
     73 	struct extent *mc_io_ex;
     74 	struct extent *mc_mem_ex;
     75 
     76 	int	mc_mallocsafe;
     77 };
     78 
     79 /*
     80  * FPA map
     81  */
     82 
     83 #define	OCTEON_POOL_NO_PKT	0
     84 #define	OCTEON_POOL_NO_WQE	1
     85 #define	OCTEON_POOL_NO_CMD	2
     86 #define	OCTEON_POOL_NO_SG	3
     87 #define	OCTEON_POOL_NO_XXX_4	4
     88 #define	OCTEON_POOL_NO_XXX_5	5
     89 #define	OCTEON_POOL_NO_XXX_6	6
     90 #define	OCTEON_POOL_NO_DUMP	7	/* FPA debug dump */
     91 
     92 #define	OCTEON_POOL_SIZE_PKT	2048	/* 128 x 16 */
     93 #define	OCTEON_POOL_SIZE_WQE	128	/* 128 x 1 */
     94 #define	OCTEON_POOL_SIZE_CMD	1024	/* 128 x 8 */
     95 #define	OCTEON_POOL_SIZE_SG	512	/* 128 x 4 */
     96 #define	OCTEON_POOL_SIZE_XXX_4	0
     97 #define	OCTEON_POOL_SIZE_XXX_5	0
     98 #define	OCTEON_POOL_SIZE_XXX_6	0
     99 #define	OCTEON_POOL_SIZE_XXX_7	0
    100 
    101 #define	OCTEON_POOL_NELEMS_PKT		4096
    102 #define	OCTEON_POOL_NELEMS_WQE		4096
    103 #define	OCTEON_POOL_NELEMS_CMD		32
    104 #define	OCTEON_POOL_NELEMS_SG		1024
    105 #define	OCTEON_POOL_NELEMS_XXX_4	0
    106 #define	OCTEON_POOL_NELEMS_XXX_5	0
    107 #define	OCTEON_POOL_NELEMS_XXX_6	0
    108 #define	OCTEON_POOL_NELEMS_XXX_7	0
    109 
    110 /*
    111  * CVMSEG (``scratch'') memory map
    112  */
    113 struct octeon_cvmseg_map {
    114 	/* 0-3 */
    115 	uint64_t		csm_xxx_0;
    116 	uint64_t		csm_xxx_1;
    117 	uint64_t		csm_xxx_2;
    118 	uint64_t		csm_pow_intr;
    119 
    120 	/* 4-19 */
    121 	struct octeon_cvmseg_ether_map {
    122 		uint64_t	csm_ether_fau_req;
    123 		uint64_t	csm_ether_fau_done;
    124 		uint64_t	csm_ether_fau_cmdptr;
    125 		uint64_t	csm_ether_xxx_3;
    126 	} csm_ether[4/* XXX */];
    127 
    128 	/* 20-32 */
    129 	uint64_t	xxx_20_32[32 - 20];
    130 } __packed;
    131 #define	OCTEON_CVMSEG_OFFSET(entry) \
    132 	offsetof(struct octeon_cvmseg_map, entry)
    133 #define	OCTEON_CVMSEG_ETHER_OFFSET(n, entry) \
    134 	(offsetof(struct octeon_cvmseg_map, csm_ether) + \
    135 	 sizeof(struct octeon_cvmseg_ether_map) * (n) + \
    136 	 offsetof(struct octeon_cvmseg_ether_map, entry))
    137 
    138 /*
    139  * FAU register map
    140  *
    141  * => FAU registers exist in FAU unit
    142  * => devices (PKO) can access these registers
    143  * => CPU can read those values after loading them into CVMSEG
    144  */
    145 struct octeon_fau_map {
    146 	struct {
    147 		/* PKO command index */
    148 		uint64_t	_fau_map_port_pkocmdidx;
    149 		/* send requested */
    150 		uint64_t	_fau_map_port_txreq;
    151 		/* send completed */
    152 		uint64_t	_fau_map_port_txdone;
    153 		/* XXX */
    154 		uint64_t	_fau_map_port_pad;
    155 	} __packed _fau_map_port[3];
    156 };
    157 
    158 /*
    159  * POW qos/group map
    160  */
    161 
    162 #define	OCTEON_POW_QOS_PIP		0
    163 #define	OCTEON_POW_QOS_CORE1		1
    164 #define	OCTEON_POW_QOS_XXX_2		2
    165 #define	OCTEON_POW_QOS_XXX_3		3
    166 #define	OCTEON_POW_QOS_XXX_4		4
    167 #define	OCTEON_POW_QOS_XXX_5		5
    168 #define	OCTEON_POW_QOS_XXX_6		6
    169 #define	OCTEON_POW_QOS_XXX_7		7
    170 
    171 #define	OCTEON_POW_GROUP_PIP		0
    172 #define	OCTEON_POW_GROUP_XXX_1		1
    173 #define	OCTEON_POW_GROUP_XXX_2		2
    174 #define	OCTEON_POW_GROUP_XXX_3		3
    175 #define	OCTEON_POW_GROUP_XXX_4		4
    176 #define	OCTEON_POW_GROUP_XXX_5		5
    177 #define	OCTEON_POW_GROUP_XXX_6		6
    178 #define	OCTEON_POW_GROUP_CORE1_SEND	7
    179 #define	OCTEON_POW_GROUP_CORE1_TASK_0	8
    180 #define	OCTEON_POW_GROUP_CORE1_TASK_1	9
    181 #define	OCTEON_POW_GROUP_CORE1_TASK_2	10
    182 #define	OCTEON_POW_GROUP_CORE1_TASK_3	11
    183 #define	OCTEON_POW_GROUP_CORE1_TASK_4	12
    184 #define	OCTEON_POW_GROUP_CORE1_TASK_5	13
    185 #define	OCTEON_POW_GROUP_CORE1_TASK_6	14
    186 #define	OCTEON_POW_GROUP_CORE1_TASK_7	15
    187 
    188 #ifdef _KERNEL
    189 extern struct octeon_config	octeon_configuration;
    190 
    191 void	octeon_bus_io_init(bus_space_tag_t, void *);
    192 void	octeon_bus_mem_init(bus_space_tag_t, void *);
    193 void	octeon_cal_timer(int);
    194 void	octeon_dma_init(struct octeon_config *);
    195 void	octeon_intr_init(void);
    196 int	octeon_intr_check_masks(void);
    197 void	octeon_iointr(int, vaddr_t, uint32_t);
    198 void	octeon_pci_init(pci_chipset_tag_t, struct octeon_config *);
    199 void	*octeon_intr_establish(int, int, int, int (*)(void *), void *);
    200 void	octeon_intr_disestablish(void *cookie);
    201 #endif /* _KERNEL */
    202 
    203 #if defined(__mips_n32)
    204 #define ffs64	__builtin_ffsll
    205 #elif defined(_LP64)
    206 #define ffs64	__builtin_ffsl
    207 #else
    208 #error unknown ABI
    209 #endif
    210 
    211 /*
    212  * Prefetch
    213  *
    214  *	OCTEON_PREF		normal (L1 and L2)
    215  *	OCTEON_PREF_L1		L1 only
    216  *	OCTEON_PREF_L2		L2 only
    217  *	OCTEON_PREF_DWB		don't write back
    218  *	OCTEON_PREF_PFS		prepare for store
    219  */
    220 #define __OCTEON_PREF_N(n, base, offset)			\
    221 	__asm __volatile (					\
    222 		"	.set	push				\
    223 		"	.set	arch=octeon			\n" \
    224 		"	pref	"#n", "#offset"(%[base])	\n" \
    225 		"	.set	pop				\
    226 		: : [base] "d" (base)				\
    227 	)
    228 #define __OCTEON_PREF_0(base, offset)	__OCTEON_PREF_N(0, base, offset)
    229 #define __OCTEON_PREF_4(base, offset)	__OCTEON_PREF_N(4, base, offset)
    230 #define __OCTEON_PREF_28(base, offset)	__OCTEON_PREF_N(28, base, offset)
    231 #define __OCTEON_PREF_29(base, offset)	__OCTEON_PREF_N(29, base, offset)
    232 #define __OCTEON_PREF_30(base, offset)	__OCTEON_PREF_N(30, base, offset)
    233 #define OCTEON_PREF(base, offset)	__OCTEON_PREF_0(base, offset)
    234 #define OCTEON_PREF_L1(base, offset)	__OCTEON_PREF_4(base, offset)
    235 #define OCTEON_PREF_L2(base, offset)	__OCTEON_PREF_28(base, offset)
    236 #define OCTEON_PREF_DWB(base, offset)	__OCTEON_PREF_29(base, offset)
    237 #define OCTEON_PREF_PFS(base, offset)	__OCTEON_PREF_30(base, offset)
    238 
    239 /*
    240  * Sync
    241  */
    242 #define OCTEON_SYNCCOMMON(name) \
    243 	__asm __volatile ( \
    244 		_ASM_PROLOGUE_OCTEON			\
    245 		"	"#name"				\n" \
    246 		_ASM_EPILOGUE				\
    247 		::: "memory")
    248 #define OCTEON_SYNCIOBDMA	OCTEON_SYNCCOMMON(synciobdma)
    249 #define OCTEON_SYNCW		OCTEON_SYNCCOMMON(syncw)
    250 #define OCTEON_SYNC		OCTEON_SYNCCOMMON(sync)
    251 #define OCTEON_SYNCWS		OCTEON_SYNCCOMMON(syncws)
    252 #define OCTEON_SYNCS		OCTEON_SYNCCOMMON(syncs)
    253 /* XXX backward compatibility */
    254 #if 1
    255 #define	OCT_SYNCIOBDMA		OCTEON_SYNCIOBDMA
    256 #define	OCT_SYNCW		OCTEON_SYNCW
    257 #define	OCT_SYNC		OCTEON_SYNC
    258 #define	OCT_SYNCWS		OCTEON_SYNCWS
    259 #define	OCT_SYNCS		OCTEON_SYNCS
    260 #endif
    261 
    262 /* octeon core does not use cca to determine cacheability */
    263 #define OCTEON_CCA_NONE UINT64_C(0)
    264 
    265 static inline uint64_t
    266 octeon_xkphys_read_8(paddr_t address)
    267 {
    268 	return mips64_ld_a64(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address));
    269 }
    270 
    271 static inline void
    272 octeon_xkphys_write_8(paddr_t address, uint64_t value)
    273 {
    274 	mips64_sd_a64(MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, address), value);
    275 }
    276 
    277 /* XXX backward compatibility */
    278 #if 1
    279 #define octeon_read_csr(address) \
    280 	octeon_xkphys_read_8(address)
    281 #define octeon_write_csr(address, value) \
    282 	octeon_xkphys_write_8(address, value)
    283 #endif
    284 
    285 static inline void
    286 octeon_iobdma_write_8(uint64_t value)
    287 {
    288 	uint64_t addr = UINT64_C(0xffffffffffffa200);
    289 
    290 	octeon_xkphys_write_8(addr, value);
    291 }
    292 
    293 static inline uint64_t
    294 octeon_cvmseg_read_8(size_t offset)
    295 {
    296 	return octeon_xkphys_read_8(UINT64_C(0xffffffffffff8000) + offset);
    297 }
    298 
    299 static inline void
    300 octeon_cvmseg_write_8(size_t offset, uint64_t value)
    301 {
    302 	octeon_xkphys_write_8(UINT64_C(0xffffffffffff8000) + offset, value);
    303 }
    304 
    305 /* XXX */
    306 static inline uint32_t
    307 octeon_disable_interrupt(uint32_t *new)
    308 {
    309 	uint32_t s, tmp;
    310 
    311 	__asm __volatile (
    312 		_ASM_PROLOGUE
    313 		"	mfc0	%[s], $12		\n"
    314 		"	and	%[tmp], %[s], ~1	\n"
    315 		"	mtc0	%[tmp], $12		\n"
    316 		_ASM_EPILOGUE
    317 		: [s]"=&r"(s), [tmp]"=&r"(tmp));
    318 	if (new)
    319 		*new = tmp;
    320 	return s;
    321 }
    322 
    323 /* XXX */
    324 static inline void
    325 octeon_restore_status(uint32_t s)
    326 {
    327 	__asm __volatile (
    328 		_ASM_PROLOGUE
    329 		"	mtc0	%[s], $12		\n"
    330 		_ASM_EPILOGUE
    331 		:: [s]"r"(s));
    332 }
    333 
    334 static inline uint64_t
    335 octeon_get_cycles(void)
    336 {
    337 #if defined(__mips_o32)
    338 	uint32_t s, lo, hi;
    339 
    340 	s = octeon_disable_interrupt((void *)0);
    341 	__asm __volatile (
    342 		_ASM_PROLOGUE_MIPS64
    343 		"	dmfc0	%[lo], $9, 6		\n"
    344 		"	add	%[hi], %[lo], $0	\n"
    345 		"	srl	%[hi], 32		\n"
    346 		"	sll	%[lo], 32		\n"
    347 		"	srl	%[lo], 32		\n"
    348 		_ASM_EPILOGUE
    349 		: [lo]"=&r"(lo), [hi]"=&r"(hi));
    350 	octeon_restore_status(s);
    351 	return ((uint64_t)hi << 32) + (uint64_t)lo;
    352 #else
    353 	uint64_t tmp;
    354 
    355 	__asm __volatile (
    356 		_ASM_PROLOGUE_MIPS64
    357 		"	dmfc0	%[tmp], $9, 6		\n"
    358 		_ASM_EPILOGUE
    359 		: [tmp]"=&r"(tmp));
    360 	return tmp;
    361 #endif
    362 }
    363 
    364 /* -------------------------------------------------------------------------- */
    365 
    366 /* ---- event counter */
    367 
    368 #if defined(OCTEON_ETH_DEBUG)
    369 #define	OCTEON_EVCNT_INC(sc, name) \
    370 	do { (sc)->sc_ev_##name.ev_count++; } while (0)
    371 #define	OCTEON_EVCNT_ADD(sc, name, n) \
    372 	do { (sc)->sc_ev_##name.ev_count += (n); } while (0)
    373 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname) \
    374 do {								\
    375 	int i;							\
    376 	const struct octeon_evcnt_entry *ee;			\
    377 								\
    378 	for (i = 0; i < (int)__arraycount(entries); i++) {	\
    379 		ee = &(entries)[i];				\
    380 		evcnt_attach_dynamic(				\
    381 		    (struct evcnt *)((uintptr_t)(sc) + ee->ee_offset), \
    382 		    ee->ee_type, ee->ee_parent, devname,	\
    383 		    ee->ee_name);				\
    384 	}							\
    385 } while (0)
    386 #else
    387 #define	OCTEON_EVCNT_INC(sc, name)
    388 #define	OCTEON_EVCNT_ADD(sc, name, n)
    389 #define	OCTEON_EVCNT_ATTACH_EVCNTS(sc, entries, devname)
    390 #endif
    391 
    392 struct octeon_evcnt_entry {
    393 	size_t		ee_offset;
    394 	int		ee_type;
    395 	struct evcnt	*ee_parent;
    396 	const char	*ee_name;
    397 };
    398 
    399 #define	OCTEON_EVCNT_ENTRY(_sc_type, _var, _ev_type, _parent, _name) \
    400 	{							\
    401 		.ee_offset = offsetof(_sc_type, sc_ev_##_var),	\
    402 		.ee_type = EVCNT_TYPE_##_ev_type,		\
    403 		.ee_parent = _parent,				\
    404 		.ee_name = _name				\
    405 	}
    406 
    407 #endif	/* _MIPS_OCTEON_OCTEONVAR_H_ */
    408