aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-ia64/sn/tioca_provider.h
blob: 65cdd73c2a57a641e3c32461f55053c04c1c16da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (c) 2003-2005 Silicon Graphics, Inc. All rights reserved.
 */

#ifndef _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H
#define _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H

#include <asm/sn/tioca.h>

/*
 * WAR enables
 * Defines for individual WARs. Each is a bitmask of applicable
 * part revision numbers. (1 << 1) == rev A, (1 << 2) == rev B,
 * (3 << 1) == (rev A or rev B), etc
 */

#define TIOCA_WAR_ENABLED(pv, tioca_common) \
	((1 << tioca_common->ca_rev) & pv)

  /* TIO:ICE:FRZ:Freezer loses a PIO data ucred on PIO RD RSP with CW error */
#define PV907908 (1 << 1)
  /* ATI config space problems after BIOS execution starts */
#define PV908234 (1 << 1)
  /* CA:AGPDMA write request data mismatch with ABC1CL merge */
#define PV895469 (1 << 1)
  /* TIO:CA TLB invalidate of written GART entries possibly not occurring in CA*/
#define PV910244 (1 << 1)

struct tioca_dmamap{
	struct list_head	cad_list;	/* headed by ca_list */

	dma_addr_t		cad_dma_addr;	/* Linux dma handle */
	uint			cad_gart_entry; /* start entry in ca_gart_pagemap */
	uint			cad_gart_size;	/* #entries for this map */
};

/*
 * Kernel only fields.  Prom may look at this stuff for debugging only.
 * Access this structure through the ca_kernel_private ptr.
 */

struct tioca_common ;

struct tioca_kernel {
	struct tioca_common	*ca_common;	/* tioca this belongs to */
	struct list_head	ca_list;	/* list of all ca's */
	struct list_head	ca_dmamaps;
	spinlock_t		ca_lock;	/* Kernel lock */
	cnodeid_t		ca_closest_node;
	struct list_head	*ca_devices;	/* bus->devices */

	/*
	 * General GART stuff
	 */
	u64	ca_ap_size;		/* size of aperature in bytes */
	u32	ca_gart_entries;	/* # u64 entries in gart */
	u32	ca_ap_pagesize; 	/* aperature page size in bytes */
	u64	ca_ap_bus_base; 	/* bus address of CA aperature */
	u64	ca_gart_size;		/* gart size in bytes */
	u64	*ca_gart;		/* gart table vaddr */
	u64	ca_gart_coretalk_addr;	/* gart coretalk addr */
	u8		ca_gart_iscoherent;	/* used in tioca_tlbflush */

	/* PCI GART convenience values */
	u64	ca_pciap_base;		/* pci aperature bus base address */
	u64	ca_pciap_size;		/* pci aperature size (bytes) */
	u64	ca_pcigart_base;	/* gfx GART bus base address */
	u64	*ca_pcigart;		/* gfx GART vm address */
	u32	ca_pcigart_entries;
	u32	ca_pcigart_start;	/* PCI start index in ca_gart */
	void		*ca_pcigart_pagemap;

	/* AGP GART convenience values */
	u64	ca_gfxap_base;		/* gfx aperature bus base address */
	u64	ca_gfxap_size;		/* gfx aperature size (bytes) */
	u64	ca_gfxgart_base;	/* gfx GART bus base address */
	u64	*ca_gfxgart;		/* gfx GART vm address */
	u32	ca_gfxgart_entries;
	u32	ca_gfxgart_start;	/* agpgart start index in ca_gart */
};

/*
 * Common tioca info shared between kernel and prom
 *
 * DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES
 * TO THE PROM VERSION.
 */

struct tioca_common {
	struct pcibus_bussoft	ca_common;	/* common pciio header */

	u32		ca_rev;
	u32		ca_closest_nasid;

	u64		ca_prom_private;
	u64		ca_kernel_private;
};

/**
 * tioca_paddr_to_gart - Convert an SGI coretalk address to a CA GART entry
 * @paddr: page address to convert
 *
 * Convert a system [coretalk] address to a GART entry.  GART entries are
 * formed using the following:
 *
 *     data = ( (1<<63) |  ( (REMAP_NODE_ID << 40) | (MD_CHIPLET_ID << 38) | 
 * (REMAP_SYS_ADDR) ) >> 12 )
 *
 * DATA written to 1 GART TABLE Entry in system memory is remapped system
 * addr for 1 page 
 *
 * The data is for coretalk address format right shifted 12 bits with a
 * valid bit.
 *
 *	GART_TABLE_ENTRY [ 25:0 ]  -- REMAP_SYS_ADDRESS[37:12].
 *	GART_TABLE_ENTRY [ 27:26 ] -- SHUB MD chiplet id.
 *	GART_TABLE_ENTRY [ 41:28 ] -- REMAP_NODE_ID.
 *	GART_TABLE_ENTRY [ 63 ]    -- Valid Bit 
 */
static inline u64
tioca_paddr_to_gart(unsigned long paddr)
{
	/*
	 * We are assuming right now that paddr already has the correct
	 * format since the address from xtalk_dmaXXX should already have
	 * NODE_ID, CHIPLET_ID, and SYS_ADDR in the correct locations.
	 */

	return ((paddr) >> 12) | (1UL << 63);
}

/**
 * tioca_physpage_to_gart - Map a host physical page for SGI CA based DMA
 * @page_addr: system page address to map
 */

static inline unsigned long
tioca_physpage_to_gart(u64 page_addr)
{
	u64 coretalk_addr;

	coretalk_addr = PHYS_TO_TIODMA(page_addr);
	if (!coretalk_addr) {
		return 0;
	}

	return tioca_paddr_to_gart(coretalk_addr);
}

/**
 * tioca_tlbflush - invalidate cached SGI CA GART TLB entries
 * @tioca_kernel: CA context 
 *
 * Invalidate tlb entries for a given CA GART.  Main complexity is to account
 * for revA bug.
 */
static inline void
tioca_tlbflush(struct tioca_kernel *tioca_kernel)
{
	volatile u64 tmp;
	volatile struct tioca *ca_base;
	struct tioca_common *tioca_common;

	tioca_common = tioca_kernel->ca_common;
	ca_base = (struct tioca *)tioca_common->ca_common.bs_base;

	/*
	 * Explicit flushes not needed if GART is in cached mode
	 */
	if (tioca_kernel->ca_gart_iscoherent) {
		if (TIOCA_WAR_ENABLED(PV910244, tioca_common)) {
			/*
			 * PV910244:  RevA CA needs explicit flushes.
			 * Need to put GART into uncached mode before
			 * flushing otherwise the explicit flush is ignored.
			 *
			 * Alternate WAR would be to leave GART cached and
			 * touch every CL aligned GART entry.
			 */

			__sn_clrq_relaxed(&ca_base->ca_control2, CA_GART_MEM_PARAM);
			__sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
			__sn_setq_relaxed(&ca_base->ca_control2,
			    (0x2ull << CA_GART_MEM_PARAM_SHFT));
			tmp = __sn_readq_relaxed(&ca_base->ca_control2);
		}

		return;
	}

	/*
	 * Gart in uncached mode ... need an explicit flush.
	 */

	__sn_setq_relaxed(&ca_base->ca_control2, CA_GART_FLUSH_TLB);
	tmp = __sn_readq_relaxed(&ca_base->ca_control2);
}

extern u32	tioca_gart_found;
extern struct list_head tioca_list;
extern int tioca_init_provider(void);
extern void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern);
#endif /* _ASM_IA64_SN_TIO_CA_AGP_PROVIDER_H */