134d8a380SJack Steiner /*
234d8a380SJack Steiner  * SN Platform GRU Driver
334d8a380SJack Steiner  *
434d8a380SJack Steiner  *              GRU HANDLE DEFINITION
534d8a380SJack Steiner  *
634d8a380SJack Steiner  *  Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
734d8a380SJack Steiner  *
834d8a380SJack Steiner  *  This program is free software; you can redistribute it and/or modify
934d8a380SJack Steiner  *  it under the terms of the GNU General Public License as published by
1034d8a380SJack Steiner  *  the Free Software Foundation; either version 2 of the License, or
1134d8a380SJack Steiner  *  (at your option) any later version.
1234d8a380SJack Steiner  *
1334d8a380SJack Steiner  *  This program is distributed in the hope that it will be useful,
1434d8a380SJack Steiner  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
1534d8a380SJack Steiner  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1634d8a380SJack Steiner  *  GNU General Public License for more details.
1734d8a380SJack Steiner  *
1834d8a380SJack Steiner  *  You should have received a copy of the GNU General Public License
1934d8a380SJack Steiner  *  along with this program; if not, write to the Free Software
2034d8a380SJack Steiner  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
2134d8a380SJack Steiner  */
2234d8a380SJack Steiner 
2334d8a380SJack Steiner #ifndef __GRUHANDLES_H__
2434d8a380SJack Steiner #define __GRUHANDLES_H__
2534d8a380SJack Steiner #include "gru_instructions.h"
2634d8a380SJack Steiner 
2734d8a380SJack Steiner /*
2834d8a380SJack Steiner  * Manifest constants for GRU Memory Map
2934d8a380SJack Steiner  */
3034d8a380SJack Steiner #define GRU_GSEG0_BASE		0
3134d8a380SJack Steiner #define GRU_MCS_BASE		(64 * 1024 * 1024)
3234d8a380SJack Steiner #define GRU_SIZE		(128UL * 1024 * 1024)
3334d8a380SJack Steiner 
3434d8a380SJack Steiner /* Handle & resource counts */
3534d8a380SJack Steiner #define GRU_NUM_CB		128
3634d8a380SJack Steiner #define GRU_NUM_DSR_BYTES	(32 * 1024)
3734d8a380SJack Steiner #define GRU_NUM_TFM		16
3834d8a380SJack Steiner #define GRU_NUM_TGH		24
3934d8a380SJack Steiner #define GRU_NUM_CBE		128
4034d8a380SJack Steiner #define GRU_NUM_TFH		128
4134d8a380SJack Steiner #define GRU_NUM_CCH		16
4234d8a380SJack Steiner #define GRU_NUM_GSH		1
4334d8a380SJack Steiner 
4434d8a380SJack Steiner /* Maximum resource counts that can be reserved by user programs */
4534d8a380SJack Steiner #define GRU_NUM_USER_CBR	GRU_NUM_CBE
4634d8a380SJack Steiner #define GRU_NUM_USER_DSR_BYTES	GRU_NUM_DSR_BYTES
4734d8a380SJack Steiner 
4834d8a380SJack Steiner /* Bytes per handle & handle stride. Code assumes all cb, tfh, cbe handles
4934d8a380SJack Steiner  * are the same */
5034d8a380SJack Steiner #define GRU_HANDLE_BYTES	64
5134d8a380SJack Steiner #define GRU_HANDLE_STRIDE	256
5234d8a380SJack Steiner 
5334d8a380SJack Steiner /* Base addresses of handles */
5434d8a380SJack Steiner #define GRU_TFM_BASE		(GRU_MCS_BASE + 0x00000)
5534d8a380SJack Steiner #define GRU_TGH_BASE		(GRU_MCS_BASE + 0x08000)
5634d8a380SJack Steiner #define GRU_CBE_BASE		(GRU_MCS_BASE + 0x10000)
5734d8a380SJack Steiner #define GRU_TFH_BASE		(GRU_MCS_BASE + 0x18000)
5834d8a380SJack Steiner #define GRU_CCH_BASE		(GRU_MCS_BASE + 0x20000)
5934d8a380SJack Steiner #define GRU_GSH_BASE		(GRU_MCS_BASE + 0x30000)
6034d8a380SJack Steiner 
6134d8a380SJack Steiner /* User gseg constants */
6234d8a380SJack Steiner #define GRU_GSEG_STRIDE		(4 * 1024 * 1024)
6334d8a380SJack Steiner #define GSEG_BASE(a)		((a) & ~(GRU_GSEG_PAGESIZE - 1))
6434d8a380SJack Steiner 
6534d8a380SJack Steiner /* Data segment constants */
6634d8a380SJack Steiner #define GRU_DSR_AU_BYTES	1024
6734d8a380SJack Steiner #define GRU_DSR_CL		(GRU_NUM_DSR_BYTES / GRU_CACHE_LINE_BYTES)
6834d8a380SJack Steiner #define GRU_DSR_AU_CL		(GRU_DSR_AU_BYTES / GRU_CACHE_LINE_BYTES)
6934d8a380SJack Steiner #define GRU_DSR_AU		(GRU_NUM_DSR_BYTES / GRU_DSR_AU_BYTES)
7034d8a380SJack Steiner 
7134d8a380SJack Steiner /* Control block constants */
7234d8a380SJack Steiner #define GRU_CBR_AU_SIZE		2
7334d8a380SJack Steiner #define GRU_CBR_AU		(GRU_NUM_CBE / GRU_CBR_AU_SIZE)
7434d8a380SJack Steiner 
7534d8a380SJack Steiner /* Convert resource counts to the number of AU */
7634d8a380SJack Steiner #define GRU_DS_BYTES_TO_AU(n)	DIV_ROUND_UP(n, GRU_DSR_AU_BYTES)
7734d8a380SJack Steiner #define GRU_CB_COUNT_TO_AU(n)	DIV_ROUND_UP(n, GRU_CBR_AU_SIZE)
7834d8a380SJack Steiner 
7934d8a380SJack Steiner /* UV limits */
8034d8a380SJack Steiner #define GRU_CHIPLETS_PER_HUB	2
8134d8a380SJack Steiner #define GRU_HUBS_PER_BLADE	1
8234d8a380SJack Steiner #define GRU_CHIPLETS_PER_BLADE	(GRU_HUBS_PER_BLADE * GRU_CHIPLETS_PER_HUB)
8334d8a380SJack Steiner 
8434d8a380SJack Steiner /* User GRU Gseg offsets */
8534d8a380SJack Steiner #define GRU_CB_BASE		0
8634d8a380SJack Steiner #define GRU_CB_LIMIT		(GRU_CB_BASE + GRU_HANDLE_STRIDE * GRU_NUM_CBE)
8734d8a380SJack Steiner #define GRU_DS_BASE		0x20000
8834d8a380SJack Steiner #define GRU_DS_LIMIT		(GRU_DS_BASE + GRU_NUM_DSR_BYTES)
8934d8a380SJack Steiner 
9034d8a380SJack Steiner /* Convert a GRU physical address to the chiplet offset */
9134d8a380SJack Steiner #define GSEGPOFF(h) 		((h) & (GRU_SIZE - 1))
9234d8a380SJack Steiner 
9334d8a380SJack Steiner /* Convert an arbitrary handle address to the beginning of the GRU segment */
9434d8a380SJack Steiner #ifndef __PLUGIN__
9534d8a380SJack Steiner #define GRUBASE(h)		((void *)((unsigned long)(h) & ~(GRU_SIZE - 1)))
9634d8a380SJack Steiner #else
9734d8a380SJack Steiner extern void *gmu_grubase(void *h);
9834d8a380SJack Steiner #define GRUBASE(h)		gmu_grubase(h)
9934d8a380SJack Steiner #endif
10034d8a380SJack Steiner 
10134d8a380SJack Steiner /* General addressing macros. */
10234d8a380SJack Steiner static inline void *get_gseg_base_address(void *base, int ctxnum)
10334d8a380SJack Steiner {
10434d8a380SJack Steiner 	return (void *)(base + GRU_GSEG0_BASE + GRU_GSEG_STRIDE * ctxnum);
10534d8a380SJack Steiner }
10634d8a380SJack Steiner 
10734d8a380SJack Steiner static inline void *get_gseg_base_address_cb(void *base, int ctxnum, int line)
10834d8a380SJack Steiner {
10934d8a380SJack Steiner 	return (void *)(get_gseg_base_address(base, ctxnum) +
11034d8a380SJack Steiner 			GRU_CB_BASE + GRU_HANDLE_STRIDE * line);
11134d8a380SJack Steiner }
11234d8a380SJack Steiner 
11334d8a380SJack Steiner static inline void *get_gseg_base_address_ds(void *base, int ctxnum, int line)
11434d8a380SJack Steiner {
11534d8a380SJack Steiner 	return (void *)(get_gseg_base_address(base, ctxnum) + GRU_DS_BASE +
11634d8a380SJack Steiner 			GRU_CACHE_LINE_BYTES * line);
11734d8a380SJack Steiner }
11834d8a380SJack Steiner 
11934d8a380SJack Steiner static inline struct gru_tlb_fault_map *get_tfm(void *base, int ctxnum)
12034d8a380SJack Steiner {
12134d8a380SJack Steiner 	return (struct gru_tlb_fault_map *)(base + GRU_TFM_BASE +
12234d8a380SJack Steiner 					ctxnum * GRU_HANDLE_STRIDE);
12334d8a380SJack Steiner }
12434d8a380SJack Steiner 
12534d8a380SJack Steiner static inline struct gru_tlb_global_handle *get_tgh(void *base, int ctxnum)
12634d8a380SJack Steiner {
12734d8a380SJack Steiner 	return (struct gru_tlb_global_handle *)(base + GRU_TGH_BASE +
12834d8a380SJack Steiner 					ctxnum * GRU_HANDLE_STRIDE);
12934d8a380SJack Steiner }
13034d8a380SJack Steiner 
13134d8a380SJack Steiner static inline struct gru_control_block_extended *get_cbe(void *base, int ctxnum)
13234d8a380SJack Steiner {
13334d8a380SJack Steiner 	return (struct gru_control_block_extended *)(base + GRU_CBE_BASE +
13434d8a380SJack Steiner 					ctxnum * GRU_HANDLE_STRIDE);
13534d8a380SJack Steiner }
13634d8a380SJack Steiner 
13734d8a380SJack Steiner static inline struct gru_tlb_fault_handle *get_tfh(void *base, int ctxnum)
13834d8a380SJack Steiner {
13934d8a380SJack Steiner 	return (struct gru_tlb_fault_handle *)(base + GRU_TFH_BASE +
14034d8a380SJack Steiner 					ctxnum * GRU_HANDLE_STRIDE);
14134d8a380SJack Steiner }
14234d8a380SJack Steiner 
14334d8a380SJack Steiner static inline struct gru_context_configuration_handle *get_cch(void *base,
14434d8a380SJack Steiner 					int ctxnum)
14534d8a380SJack Steiner {
14634d8a380SJack Steiner 	return (struct gru_context_configuration_handle *)(base +
14734d8a380SJack Steiner 				GRU_CCH_BASE + ctxnum * GRU_HANDLE_STRIDE);
14834d8a380SJack Steiner }
14934d8a380SJack Steiner 
15034d8a380SJack Steiner static inline unsigned long get_cb_number(void *cb)
15134d8a380SJack Steiner {
15234d8a380SJack Steiner 	return (((unsigned long)cb - GRU_CB_BASE) % GRU_GSEG_PAGESIZE) /
15334d8a380SJack Steiner 					GRU_HANDLE_STRIDE;
15434d8a380SJack Steiner }
15534d8a380SJack Steiner 
15634d8a380SJack Steiner /* byte offset to a specific GRU chiplet. (p=pnode, c=chiplet (0 or 1)*/
15734d8a380SJack Steiner static inline unsigned long gru_chiplet_paddr(unsigned long paddr, int pnode,
15834d8a380SJack Steiner 							int chiplet)
15934d8a380SJack Steiner {
16034d8a380SJack Steiner 	return paddr + GRU_SIZE * (2 * pnode  + chiplet);
16134d8a380SJack Steiner }
16234d8a380SJack Steiner 
16334d8a380SJack Steiner static inline void *gru_chiplet_vaddr(void *vaddr, int pnode, int chiplet)
16434d8a380SJack Steiner {
16534d8a380SJack Steiner 	return vaddr + GRU_SIZE * (2 * pnode  + chiplet);
16634d8a380SJack Steiner }
16734d8a380SJack Steiner 
16834d8a380SJack Steiner 
16934d8a380SJack Steiner 
17034d8a380SJack Steiner /*
17134d8a380SJack Steiner  * Global TLB Fault Map
17234d8a380SJack Steiner  * 	Bitmap of outstanding TLB misses needing interrupt/polling service.
17334d8a380SJack Steiner  *
17434d8a380SJack Steiner  */
17534d8a380SJack Steiner struct gru_tlb_fault_map {
17634d8a380SJack Steiner 	unsigned long fault_bits[BITS_TO_LONGS(GRU_NUM_CBE)];
17734d8a380SJack Steiner 	unsigned long fill0[2];
17834d8a380SJack Steiner 	unsigned long done_bits[BITS_TO_LONGS(GRU_NUM_CBE)];
17934d8a380SJack Steiner 	unsigned long fill1[2];
18034d8a380SJack Steiner };
18134d8a380SJack Steiner 
18234d8a380SJack Steiner /*
18334d8a380SJack Steiner  * TGH - TLB Global Handle
18434d8a380SJack Steiner  * 	Used for TLB flushing.
18534d8a380SJack Steiner  *
18634d8a380SJack Steiner  */
18734d8a380SJack Steiner struct gru_tlb_global_handle {
18834d8a380SJack Steiner 	unsigned int cmd:1;		/* DW 0 */
18934d8a380SJack Steiner 	unsigned int delresp:1;
19034d8a380SJack Steiner 	unsigned int opc:1;
19134d8a380SJack Steiner 	unsigned int fill1:5;
19234d8a380SJack Steiner 
19334d8a380SJack Steiner 	unsigned int fill2:8;
19434d8a380SJack Steiner 
19534d8a380SJack Steiner 	unsigned int status:2;
19634d8a380SJack Steiner 	unsigned long fill3:2;
19734d8a380SJack Steiner 	unsigned int state:3;
19834d8a380SJack Steiner 	unsigned long fill4:1;
19934d8a380SJack Steiner 
20034d8a380SJack Steiner 	unsigned int cause:3;
20134d8a380SJack Steiner 	unsigned long fill5:37;
20234d8a380SJack Steiner 
20334d8a380SJack Steiner 	unsigned long vaddr:64;		/* DW 1 */
20434d8a380SJack Steiner 
20534d8a380SJack Steiner 	unsigned int asid:24;		/* DW 2 */
20634d8a380SJack Steiner 	unsigned int fill6:8;
20734d8a380SJack Steiner 
20834d8a380SJack Steiner 	unsigned int pagesize:5;
20934d8a380SJack Steiner 	unsigned int fill7:11;
21034d8a380SJack Steiner 
21134d8a380SJack Steiner 	unsigned int global:1;
21234d8a380SJack Steiner 	unsigned int fill8:15;
21334d8a380SJack Steiner 
21434d8a380SJack Steiner 	unsigned long vaddrmask:39;	/* DW 3 */
21534d8a380SJack Steiner 	unsigned int fill9:9;
21634d8a380SJack Steiner 	unsigned int n:10;
21734d8a380SJack Steiner 	unsigned int fill10:6;
21834d8a380SJack Steiner 
21934d8a380SJack Steiner 	unsigned int ctxbitmap:16;	/* DW4 */
22034d8a380SJack Steiner 	unsigned long fill11[3];
22134d8a380SJack Steiner };
22234d8a380SJack Steiner 
22334d8a380SJack Steiner enum gru_tgh_cmd {
22434d8a380SJack Steiner 	TGHCMD_START
22534d8a380SJack Steiner };
22634d8a380SJack Steiner 
22734d8a380SJack Steiner enum gru_tgh_opc {
22834d8a380SJack Steiner 	TGHOP_TLBNOP,
22934d8a380SJack Steiner 	TGHOP_TLBINV
23034d8a380SJack Steiner };
23134d8a380SJack Steiner 
23234d8a380SJack Steiner enum gru_tgh_status {
23334d8a380SJack Steiner 	TGHSTATUS_IDLE,
23434d8a380SJack Steiner 	TGHSTATUS_EXCEPTION,
23534d8a380SJack Steiner 	TGHSTATUS_ACTIVE
23634d8a380SJack Steiner };
23734d8a380SJack Steiner 
23834d8a380SJack Steiner enum gru_tgh_state {
23934d8a380SJack Steiner 	TGHSTATE_IDLE,
24034d8a380SJack Steiner 	TGHSTATE_PE_INVAL,
24134d8a380SJack Steiner 	TGHSTATE_INTERRUPT_INVAL,
24234d8a380SJack Steiner 	TGHSTATE_WAITDONE,
24334d8a380SJack Steiner 	TGHSTATE_RESTART_CTX,
24434d8a380SJack Steiner };
24534d8a380SJack Steiner 
24634d8a380SJack Steiner /*
24734d8a380SJack Steiner  * TFH - TLB Global Handle
24834d8a380SJack Steiner  * 	Used for TLB dropins into the GRU TLB.
24934d8a380SJack Steiner  *
25034d8a380SJack Steiner  */
25134d8a380SJack Steiner struct gru_tlb_fault_handle {
25234d8a380SJack Steiner 	unsigned int cmd:1;		/* DW 0 - low 32*/
25334d8a380SJack Steiner 	unsigned int delresp:1;
25434d8a380SJack Steiner 	unsigned int fill0:2;
25534d8a380SJack Steiner 	unsigned int opc:3;
25634d8a380SJack Steiner 	unsigned int fill1:9;
25734d8a380SJack Steiner 
25834d8a380SJack Steiner 	unsigned int status:2;
25934d8a380SJack Steiner 	unsigned int fill2:1;
26034d8a380SJack Steiner 	unsigned int color:1;
26134d8a380SJack Steiner 	unsigned int state:3;
26234d8a380SJack Steiner 	unsigned int fill3:1;
26334d8a380SJack Steiner 
26434d8a380SJack Steiner 	unsigned int cause:7;		/* DW 0 - high 32 */
26534d8a380SJack Steiner 	unsigned int fill4:1;
26634d8a380SJack Steiner 
26734d8a380SJack Steiner 	unsigned int indexway:12;
26834d8a380SJack Steiner 	unsigned int fill5:4;
26934d8a380SJack Steiner 
27034d8a380SJack Steiner 	unsigned int ctxnum:4;
27134d8a380SJack Steiner 	unsigned int fill6:12;
27234d8a380SJack Steiner 
27334d8a380SJack Steiner 	unsigned long missvaddr:64;	/* DW 1 */
27434d8a380SJack Steiner 
27534d8a380SJack Steiner 	unsigned int missasid:24;	/* DW 2 */
27634d8a380SJack Steiner 	unsigned int fill7:8;
27734d8a380SJack Steiner 	unsigned int fillasid:24;
27834d8a380SJack Steiner 	unsigned int dirty:1;
27934d8a380SJack Steiner 	unsigned int gaa:2;
28034d8a380SJack Steiner 	unsigned long fill8:5;
28134d8a380SJack Steiner 
28234d8a380SJack Steiner 	unsigned long pfn:41;		/* DW 3 */
28334d8a380SJack Steiner 	unsigned int fill9:7;
28434d8a380SJack Steiner 	unsigned int pagesize:5;
28534d8a380SJack Steiner 	unsigned int fill10:11;
28634d8a380SJack Steiner 
28734d8a380SJack Steiner 	unsigned long fillvaddr:64;	/* DW 4 */
28834d8a380SJack Steiner 
28934d8a380SJack Steiner 	unsigned long fill11[3];
29034d8a380SJack Steiner };
29134d8a380SJack Steiner 
29234d8a380SJack Steiner enum gru_tfh_opc {
29334d8a380SJack Steiner 	TFHOP_NOOP,
29434d8a380SJack Steiner 	TFHOP_RESTART,
29534d8a380SJack Steiner 	TFHOP_WRITE_ONLY,
29634d8a380SJack Steiner 	TFHOP_WRITE_RESTART,
29734d8a380SJack Steiner 	TFHOP_EXCEPTION,
29834d8a380SJack Steiner 	TFHOP_USER_POLLING_MODE = 7,
29934d8a380SJack Steiner };
30034d8a380SJack Steiner 
30134d8a380SJack Steiner enum tfh_status {
30234d8a380SJack Steiner 	TFHSTATUS_IDLE,
30334d8a380SJack Steiner 	TFHSTATUS_EXCEPTION,
30434d8a380SJack Steiner 	TFHSTATUS_ACTIVE,
30534d8a380SJack Steiner };
30634d8a380SJack Steiner 
30734d8a380SJack Steiner enum tfh_state {
30834d8a380SJack Steiner 	TFHSTATE_INACTIVE,
30934d8a380SJack Steiner 	TFHSTATE_IDLE,
31034d8a380SJack Steiner 	TFHSTATE_MISS_UPM,
31134d8a380SJack Steiner 	TFHSTATE_MISS_FMM,
31234d8a380SJack Steiner 	TFHSTATE_HW_ERR,
31334d8a380SJack Steiner 	TFHSTATE_WRITE_TLB,
31434d8a380SJack Steiner 	TFHSTATE_RESTART_CBR,
31534d8a380SJack Steiner };
31634d8a380SJack Steiner 
31734d8a380SJack Steiner /* TFH cause bits */
31834d8a380SJack Steiner enum tfh_cause {
31934d8a380SJack Steiner 	TFHCAUSE_NONE,
32034d8a380SJack Steiner 	TFHCAUSE_TLB_MISS,
32134d8a380SJack Steiner 	TFHCAUSE_TLB_MOD,
32234d8a380SJack Steiner 	TFHCAUSE_HW_ERROR_RR,
32334d8a380SJack Steiner 	TFHCAUSE_HW_ERROR_MAIN_ARRAY,
32434d8a380SJack Steiner 	TFHCAUSE_HW_ERROR_VALID,
32534d8a380SJack Steiner 	TFHCAUSE_HW_ERROR_PAGESIZE,
32634d8a380SJack Steiner 	TFHCAUSE_INSTRUCTION_EXCEPTION,
32734d8a380SJack Steiner 	TFHCAUSE_UNCORRECTIBLE_ERROR,
32834d8a380SJack Steiner };
32934d8a380SJack Steiner 
33034d8a380SJack Steiner /* GAA values */
33134d8a380SJack Steiner #define GAA_RAM				0x0
33234d8a380SJack Steiner #define GAA_NCRAM			0x2
33334d8a380SJack Steiner #define GAA_MMIO			0x1
33434d8a380SJack Steiner #define GAA_REGISTER			0x3
33534d8a380SJack Steiner 
33634d8a380SJack Steiner /* GRU paddr shift for pfn. (NOTE: shift is NOT by actual pagesize) */
33734d8a380SJack Steiner #define GRU_PADDR_SHIFT			12
33834d8a380SJack Steiner 
33934d8a380SJack Steiner /*
34034d8a380SJack Steiner  * Context Configuration handle
34134d8a380SJack Steiner  * 	Used to allocate resources to a GSEG context.
34234d8a380SJack Steiner  *
34334d8a380SJack Steiner  */
34434d8a380SJack Steiner struct gru_context_configuration_handle {
34534d8a380SJack Steiner 	unsigned int cmd:1;			/* DW0 */
34634d8a380SJack Steiner 	unsigned int delresp:1;
34734d8a380SJack Steiner 	unsigned int opc:3;
34834d8a380SJack Steiner 	unsigned int unmap_enable:1;
34934d8a380SJack Steiner 	unsigned int req_slice_set_enable:1;
35034d8a380SJack Steiner 	unsigned int req_slice:2;
35134d8a380SJack Steiner 	unsigned int cb_int_enable:1;
35234d8a380SJack Steiner 	unsigned int tlb_int_enable:1;
35334d8a380SJack Steiner 	unsigned int tfm_fault_bit_enable:1;
35434d8a380SJack Steiner 	unsigned int tlb_int_select:4;
35534d8a380SJack Steiner 
35634d8a380SJack Steiner 	unsigned int status:2;
35734d8a380SJack Steiner 	unsigned int state:2;
35834d8a380SJack Steiner 	unsigned int reserved2:4;
35934d8a380SJack Steiner 
36034d8a380SJack Steiner 	unsigned int cause:4;
36134d8a380SJack Steiner 	unsigned int tfm_done_bit_enable:1;
36234d8a380SJack Steiner 	unsigned int unused:3;
36334d8a380SJack Steiner 
36434d8a380SJack Steiner 	unsigned int dsr_allocation_map;
36534d8a380SJack Steiner 
36634d8a380SJack Steiner 	unsigned long cbr_allocation_map;	/* DW1 */
36734d8a380SJack Steiner 
36834d8a380SJack Steiner 	unsigned int asid[8];			/* DW 2 - 5 */
36934d8a380SJack Steiner 	unsigned short sizeavail[8];		/* DW 6 - 7 */
37034d8a380SJack Steiner } __attribute__ ((packed));
37134d8a380SJack Steiner 
37234d8a380SJack Steiner enum gru_cch_opc {
37334d8a380SJack Steiner 	CCHOP_START = 1,
37434d8a380SJack Steiner 	CCHOP_ALLOCATE,
37534d8a380SJack Steiner 	CCHOP_INTERRUPT,
37634d8a380SJack Steiner 	CCHOP_DEALLOCATE,
37734d8a380SJack Steiner 	CCHOP_INTERRUPT_SYNC,
37834d8a380SJack Steiner };
37934d8a380SJack Steiner 
38034d8a380SJack Steiner enum gru_cch_status {
38134d8a380SJack Steiner 	CCHSTATUS_IDLE,
38234d8a380SJack Steiner 	CCHSTATUS_EXCEPTION,
38334d8a380SJack Steiner 	CCHSTATUS_ACTIVE,
38434d8a380SJack Steiner };
38534d8a380SJack Steiner 
38634d8a380SJack Steiner enum gru_cch_state {
38734d8a380SJack Steiner 	CCHSTATE_INACTIVE,
38834d8a380SJack Steiner 	CCHSTATE_MAPPED,
38934d8a380SJack Steiner 	CCHSTATE_ACTIVE,
39034d8a380SJack Steiner 	CCHSTATE_INTERRUPTED,
39134d8a380SJack Steiner };
39234d8a380SJack Steiner 
39334d8a380SJack Steiner /* CCH Exception cause */
39434d8a380SJack Steiner enum gru_cch_cause {
39534d8a380SJack Steiner 	CCHCAUSE_REGION_REGISTER_WRITE_ERROR = 1,
39634d8a380SJack Steiner 	CCHCAUSE_ILLEGAL_OPCODE = 2,
39734d8a380SJack Steiner 	CCHCAUSE_INVALID_START_REQUEST = 3,
39834d8a380SJack Steiner 	CCHCAUSE_INVALID_ALLOCATION_REQUEST = 4,
39934d8a380SJack Steiner 	CCHCAUSE_INVALID_DEALLOCATION_REQUEST = 5,
40034d8a380SJack Steiner 	CCHCAUSE_INVALID_INTERRUPT_REQUEST = 6,
40134d8a380SJack Steiner 	CCHCAUSE_CCH_BUSY = 7,
40234d8a380SJack Steiner 	CCHCAUSE_NO_CBRS_TO_ALLOCATE = 8,
40334d8a380SJack Steiner 	CCHCAUSE_BAD_TFM_CONFIG = 9,
40434d8a380SJack Steiner 	CCHCAUSE_CBR_RESOURCES_OVERSUBSCRIPED = 10,
40534d8a380SJack Steiner 	CCHCAUSE_DSR_RESOURCES_OVERSUBSCRIPED = 11,
40634d8a380SJack Steiner 	CCHCAUSE_CBR_DEALLOCATION_ERROR = 12,
40734d8a380SJack Steiner };
40834d8a380SJack Steiner /*
40934d8a380SJack Steiner  * CBE - Control Block Extended
41034d8a380SJack Steiner  * 	Maintains internal GRU state for active CBs.
41134d8a380SJack Steiner  *
41234d8a380SJack Steiner  */
41334d8a380SJack Steiner struct gru_control_block_extended {
41434d8a380SJack Steiner 	unsigned int reserved0:1;	/* DW 0  - low */
41534d8a380SJack Steiner 	unsigned int imacpy:3;
41634d8a380SJack Steiner 	unsigned int reserved1:4;
41734d8a380SJack Steiner 	unsigned int xtypecpy:3;
41834d8a380SJack Steiner 	unsigned int iaa0cpy:2;
41934d8a380SJack Steiner 	unsigned int iaa1cpy:2;
42034d8a380SJack Steiner 	unsigned int reserved2:1;
42134d8a380SJack Steiner 	unsigned int opccpy:8;
42234d8a380SJack Steiner 	unsigned int exopccpy:8;
42334d8a380SJack Steiner 
42434d8a380SJack Steiner 	unsigned int idef2cpy:22;	/* DW 0  - high */
42534d8a380SJack Steiner 	unsigned int reserved3:10;
42634d8a380SJack Steiner 
42734d8a380SJack Steiner 	unsigned int idef4cpy:22;	/* DW 1 */
42834d8a380SJack Steiner 	unsigned int reserved4:10;
42934d8a380SJack Steiner 	unsigned int idef4upd:22;
43034d8a380SJack Steiner 	unsigned int reserved5:10;
43134d8a380SJack Steiner 
43234d8a380SJack Steiner 	unsigned long idef1upd:64;	/* DW 2 */
43334d8a380SJack Steiner 
43434d8a380SJack Steiner 	unsigned long idef5cpy:64;	/* DW 3 */
43534d8a380SJack Steiner 
43634d8a380SJack Steiner 	unsigned long idef6cpy:64;	/* DW 4 */
43734d8a380SJack Steiner 
43834d8a380SJack Steiner 	unsigned long idef3upd:64;	/* DW 5 */
43934d8a380SJack Steiner 
44034d8a380SJack Steiner 	unsigned long idef5upd:64;	/* DW 6 */
44134d8a380SJack Steiner 
44234d8a380SJack Steiner 	unsigned int idef2upd:22;	/* DW 7 */
44334d8a380SJack Steiner 	unsigned int reserved6:10;
44434d8a380SJack Steiner 
44534d8a380SJack Steiner 	unsigned int ecause:20;
44634d8a380SJack Steiner 	unsigned int cbrstate:4;
44734d8a380SJack Steiner 	unsigned int cbrexecstatus:8;
44834d8a380SJack Steiner };
44934d8a380SJack Steiner 
45034d8a380SJack Steiner enum gru_cbr_state {
45134d8a380SJack Steiner 	CBRSTATE_INACTIVE,
45234d8a380SJack Steiner 	CBRSTATE_IDLE,
45334d8a380SJack Steiner 	CBRSTATE_PE_CHECK,
45434d8a380SJack Steiner 	CBRSTATE_QUEUED,
45534d8a380SJack Steiner 	CBRSTATE_WAIT_RESPONSE,
45634d8a380SJack Steiner 	CBRSTATE_INTERRUPTED,
45734d8a380SJack Steiner 	CBRSTATE_INTERRUPTED_MISS_FMM,
45834d8a380SJack Steiner 	CBRSTATE_BUSY_INTERRUPT_MISS_FMM,
45934d8a380SJack Steiner 	CBRSTATE_INTERRUPTED_MISS_UPM,
46034d8a380SJack Steiner 	CBRSTATE_BUSY_INTERRUPTED_MISS_UPM,
46134d8a380SJack Steiner 	CBRSTATE_REQUEST_ISSUE,
46234d8a380SJack Steiner 	CBRSTATE_BUSY_INTERRUPT,
46334d8a380SJack Steiner };
46434d8a380SJack Steiner 
46534d8a380SJack Steiner /* CBE cbrexecstatus bits */
46634d8a380SJack Steiner #define CBR_EXS_ABORT_OCC_BIT			0
46734d8a380SJack Steiner #define CBR_EXS_INT_OCC_BIT			1
46834d8a380SJack Steiner #define CBR_EXS_PENDING_BIT			2
46934d8a380SJack Steiner #define CBR_EXS_QUEUED_BIT			3
47034d8a380SJack Steiner #define CBR_EXS_TLBHW_BIT			4
47134d8a380SJack Steiner #define CBR_EXS_EXCEPTION_BIT			5
47234d8a380SJack Steiner 
47334d8a380SJack Steiner #define CBR_EXS_ABORT_OCC			(1 << CBR_EXS_ABORT_OCC_BIT)
47434d8a380SJack Steiner #define CBR_EXS_INT_OCC				(1 << CBR_EXS_INT_OCC_BIT)
47534d8a380SJack Steiner #define CBR_EXS_PENDING				(1 << CBR_EXS_PENDING_BIT)
47634d8a380SJack Steiner #define CBR_EXS_QUEUED				(1 << CBR_EXS_QUEUED_BIT)
47734d8a380SJack Steiner #define CBR_EXS_TLBHW				(1 << CBR_EXS_TLBHW_BIT)
47834d8a380SJack Steiner #define CBR_EXS_EXCEPTION			(1 << CBR_EXS_EXCEPTION_BIT)
47934d8a380SJack Steiner 
48034d8a380SJack Steiner /* CBE ecause bits  - defined in gru_instructions.h */
48134d8a380SJack Steiner 
48234d8a380SJack Steiner /*
48334d8a380SJack Steiner  * Convert a processor pagesize into the strange encoded pagesize used by the
48434d8a380SJack Steiner  * GRU. Processor pagesize is encoded as log of bytes per page. (or PAGE_SHIFT)
48534d8a380SJack Steiner  * 	pagesize	log pagesize	grupagesize
48634d8a380SJack Steiner  * 	  4k			12	0
48734d8a380SJack Steiner  * 	 16k 			14	1
48834d8a380SJack Steiner  * 	 64k			16	2
48934d8a380SJack Steiner  * 	256k			18	3
49034d8a380SJack Steiner  * 	  1m			20	4
49134d8a380SJack Steiner  * 	  2m			21	5
49234d8a380SJack Steiner  * 	  4m			22	6
49334d8a380SJack Steiner  * 	 16m			24	7
49434d8a380SJack Steiner  * 	 64m			26	8
49534d8a380SJack Steiner  * 	...
49634d8a380SJack Steiner  */
49734d8a380SJack Steiner #define GRU_PAGESIZE(sh)	((((sh) > 20 ? (sh) + 2: (sh)) >> 1) - 6)
49834d8a380SJack Steiner #define GRU_SIZEAVAIL(sh)	(1UL << GRU_PAGESIZE(sh))
49934d8a380SJack Steiner 
50034d8a380SJack Steiner /* minimum TLB purge count to ensure a full purge */
50134d8a380SJack Steiner #define GRUMAXINVAL		1024UL
50234d8a380SJack Steiner 
50334d8a380SJack Steiner 
50434d8a380SJack Steiner /* Extract the status field from a kernel handle */
50534d8a380SJack Steiner #define GET_MSEG_HANDLE_STATUS(h)	(((*(unsigned long *)(h)) >> 16) & 3)
50634d8a380SJack Steiner 
50734d8a380SJack Steiner static inline void start_instruction(void *h)
50834d8a380SJack Steiner {
50934d8a380SJack Steiner 	unsigned long *w0 = h;
51034d8a380SJack Steiner 
51134d8a380SJack Steiner 	wmb();		/* setting CMD bit must be last */
51234d8a380SJack Steiner 	*w0 = *w0 | 1;
51334d8a380SJack Steiner 	gru_flush_cache(h);
51434d8a380SJack Steiner }
51534d8a380SJack Steiner 
51634d8a380SJack Steiner static inline int wait_instruction_complete(void *h)
51734d8a380SJack Steiner {
51834d8a380SJack Steiner 	int status;
51934d8a380SJack Steiner 
52034d8a380SJack Steiner 	do {
52134d8a380SJack Steiner 		cpu_relax();
52234d8a380SJack Steiner 		barrier();
52334d8a380SJack Steiner 		status = GET_MSEG_HANDLE_STATUS(h);
52434d8a380SJack Steiner 	} while (status == CCHSTATUS_ACTIVE);
52534d8a380SJack Steiner 	return status;
52634d8a380SJack Steiner }
52734d8a380SJack Steiner 
52834d8a380SJack Steiner #if defined CONFIG_IA64
52934d8a380SJack Steiner static inline void cch_allocate_set_asids(
53034d8a380SJack Steiner 		  struct gru_context_configuration_handle *cch, int asidval)
53134d8a380SJack Steiner {
53234d8a380SJack Steiner 	int i;
53334d8a380SJack Steiner 
53434d8a380SJack Steiner 	for (i = 0; i <= RGN_HPAGE; i++) {  /*  assume HPAGE is last region */
53534d8a380SJack Steiner 		cch->asid[i] = (asidval++);
53634d8a380SJack Steiner #if 0
53734d8a380SJack Steiner 		/* ZZZ hugepages not supported yet */
53834d8a380SJack Steiner 		if (i == RGN_HPAGE)
53934d8a380SJack Steiner 			cch->sizeavail[i] = GRU_SIZEAVAIL(hpage_shift);
54034d8a380SJack Steiner 		else
54134d8a380SJack Steiner #endif
54234d8a380SJack Steiner 			cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT);
54334d8a380SJack Steiner 	}
54434d8a380SJack Steiner }
54534d8a380SJack Steiner #elif defined CONFIG_X86_64
54634d8a380SJack Steiner static inline void cch_allocate_set_asids(
54734d8a380SJack Steiner 		  struct gru_context_configuration_handle *cch, int asidval)
54834d8a380SJack Steiner {
54934d8a380SJack Steiner 	int i;
55034d8a380SJack Steiner 
55134d8a380SJack Steiner 	for (i = 0; i < 8; i++) {
55234d8a380SJack Steiner 		cch->asid[i] = asidval++;
55334d8a380SJack Steiner 		cch->sizeavail[i] = GRU_SIZEAVAIL(PAGE_SHIFT) |
55434d8a380SJack Steiner 			GRU_SIZEAVAIL(21);
55534d8a380SJack Steiner 	}
55634d8a380SJack Steiner }
55734d8a380SJack Steiner #endif
55834d8a380SJack Steiner 
55934d8a380SJack Steiner static inline int cch_allocate(struct gru_context_configuration_handle *cch,
56034d8a380SJack Steiner 			       int asidval, unsigned long cbrmap,
56134d8a380SJack Steiner 			       unsigned long dsrmap)
56234d8a380SJack Steiner {
56334d8a380SJack Steiner 	cch_allocate_set_asids(cch, asidval);
56434d8a380SJack Steiner 	cch->dsr_allocation_map = dsrmap;
56534d8a380SJack Steiner 	cch->cbr_allocation_map = cbrmap;
56634d8a380SJack Steiner 	cch->opc = CCHOP_ALLOCATE;
56734d8a380SJack Steiner 	start_instruction(cch);
56834d8a380SJack Steiner 	return wait_instruction_complete(cch);
56934d8a380SJack Steiner }
57034d8a380SJack Steiner 
57134d8a380SJack Steiner static inline int cch_start(struct gru_context_configuration_handle *cch)
57234d8a380SJack Steiner {
57334d8a380SJack Steiner 	cch->opc = CCHOP_START;
57434d8a380SJack Steiner 	start_instruction(cch);
57534d8a380SJack Steiner 	return wait_instruction_complete(cch);
57634d8a380SJack Steiner }
57734d8a380SJack Steiner 
57834d8a380SJack Steiner static inline int cch_interrupt(struct gru_context_configuration_handle *cch)
57934d8a380SJack Steiner {
58034d8a380SJack Steiner 	cch->opc = CCHOP_INTERRUPT;
58134d8a380SJack Steiner 	start_instruction(cch);
58234d8a380SJack Steiner 	return wait_instruction_complete(cch);
58334d8a380SJack Steiner }
58434d8a380SJack Steiner 
58534d8a380SJack Steiner static inline int cch_deallocate(struct gru_context_configuration_handle *cch)
58634d8a380SJack Steiner {
58734d8a380SJack Steiner 	cch->opc = CCHOP_DEALLOCATE;
58834d8a380SJack Steiner 	start_instruction(cch);
58934d8a380SJack Steiner 	return wait_instruction_complete(cch);
59034d8a380SJack Steiner }
59134d8a380SJack Steiner 
59234d8a380SJack Steiner static inline int cch_interrupt_sync(struct gru_context_configuration_handle
59334d8a380SJack Steiner 				     *cch)
59434d8a380SJack Steiner {
59534d8a380SJack Steiner 	cch->opc = CCHOP_INTERRUPT_SYNC;
59634d8a380SJack Steiner 	start_instruction(cch);
59734d8a380SJack Steiner 	return wait_instruction_complete(cch);
59834d8a380SJack Steiner }
59934d8a380SJack Steiner 
60034d8a380SJack Steiner static inline int tgh_invalidate(struct gru_tlb_global_handle *tgh,
60134d8a380SJack Steiner 				 unsigned long vaddr, unsigned long vaddrmask,
60234d8a380SJack Steiner 				 int asid, int pagesize, int global, int n,
60334d8a380SJack Steiner 				 unsigned short ctxbitmap)
60434d8a380SJack Steiner {
60534d8a380SJack Steiner 	tgh->vaddr = vaddr;
60634d8a380SJack Steiner 	tgh->asid = asid;
60734d8a380SJack Steiner 	tgh->pagesize = pagesize;
60834d8a380SJack Steiner 	tgh->n = n;
60934d8a380SJack Steiner 	tgh->global = global;
61034d8a380SJack Steiner 	tgh->vaddrmask = vaddrmask;
61134d8a380SJack Steiner 	tgh->ctxbitmap = ctxbitmap;
61234d8a380SJack Steiner 	tgh->opc = TGHOP_TLBINV;
61334d8a380SJack Steiner 	start_instruction(tgh);
61434d8a380SJack Steiner 	return wait_instruction_complete(tgh);
61534d8a380SJack Steiner }
61634d8a380SJack Steiner 
61734d8a380SJack Steiner static inline void tfh_write_only(struct gru_tlb_fault_handle *tfh,
61834d8a380SJack Steiner 				  unsigned long pfn, unsigned long vaddr,
61934d8a380SJack Steiner 				  int asid, int dirty, int pagesize)
62034d8a380SJack Steiner {
62134d8a380SJack Steiner 	tfh->fillasid = asid;
62234d8a380SJack Steiner 	tfh->fillvaddr = vaddr;
62334d8a380SJack Steiner 	tfh->pfn = pfn;
62434d8a380SJack Steiner 	tfh->dirty = dirty;
62534d8a380SJack Steiner 	tfh->pagesize = pagesize;
62634d8a380SJack Steiner 	tfh->opc = TFHOP_WRITE_ONLY;
62734d8a380SJack Steiner 	start_instruction(tfh);
62834d8a380SJack Steiner }
62934d8a380SJack Steiner 
63034d8a380SJack Steiner static inline void tfh_write_restart(struct gru_tlb_fault_handle *tfh,
63134d8a380SJack Steiner 				     unsigned long paddr, int gaa,
63234d8a380SJack Steiner 				     unsigned long vaddr, int asid, int dirty,
63334d8a380SJack Steiner 				     int pagesize)
63434d8a380SJack Steiner {
63534d8a380SJack Steiner 	tfh->fillasid = asid;
63634d8a380SJack Steiner 	tfh->fillvaddr = vaddr;
63734d8a380SJack Steiner 	tfh->pfn = paddr >> GRU_PADDR_SHIFT;
63834d8a380SJack Steiner 	tfh->gaa = gaa;
63934d8a380SJack Steiner 	tfh->dirty = dirty;
64034d8a380SJack Steiner 	tfh->pagesize = pagesize;
64134d8a380SJack Steiner 	tfh->opc = TFHOP_WRITE_RESTART;
64234d8a380SJack Steiner 	start_instruction(tfh);
64334d8a380SJack Steiner }
64434d8a380SJack Steiner 
64534d8a380SJack Steiner static inline void tfh_restart(struct gru_tlb_fault_handle *tfh)
64634d8a380SJack Steiner {
64734d8a380SJack Steiner 	tfh->opc = TFHOP_RESTART;
64834d8a380SJack Steiner 	start_instruction(tfh);
64934d8a380SJack Steiner }
65034d8a380SJack Steiner 
65134d8a380SJack Steiner static inline void tfh_user_polling_mode(struct gru_tlb_fault_handle *tfh)
65234d8a380SJack Steiner {
65334d8a380SJack Steiner 	tfh->opc = TFHOP_USER_POLLING_MODE;
65434d8a380SJack Steiner 	start_instruction(tfh);
65534d8a380SJack Steiner }
65634d8a380SJack Steiner 
65734d8a380SJack Steiner static inline void tfh_exception(struct gru_tlb_fault_handle *tfh)
65834d8a380SJack Steiner {
65934d8a380SJack Steiner 	tfh->opc = TFHOP_EXCEPTION;
66034d8a380SJack Steiner 	start_instruction(tfh);
66134d8a380SJack Steiner }
66234d8a380SJack Steiner 
66334d8a380SJack Steiner #endif /* __GRUHANDLES_H__ */
664