tioca_provider.h 6.0 KB
Newer Older
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
/*
 * 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 occuring 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
	 */
	uint64_t	ca_ap_size;		/* size of aperature in bytes */
	uint32_t	ca_gart_entries;	/* # uint64_t entries in gart */
	uint32_t	ca_ap_pagesize; 	/* aperature page size in bytes */
	uint64_t	ca_ap_bus_base; 	/* bus address of CA aperature */
	uint64_t	ca_gart_size;		/* gart size in bytes */
	uint64_t	*ca_gart;		/* gart table vaddr */
	uint64_t	ca_gart_coretalk_addr;	/* gart coretalk addr */
	uint8_t		ca_gart_iscoherent;	/* used in tioca_tlbflush */

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

	/* AGP GART convenience values */
	uint64_t	ca_gfxap_base;		/* gfx aperature bus base address */
	uint64_t	ca_gfxap_size;		/* gfx aperature size (bytes) */
	uint64_t	ca_gfxgart_base;	/* gfx GART bus base address */
	uint64_t	*ca_gfxgart;		/* gfx GART vm address */
	uint32_t	ca_gfxgart_entries;
	uint32_t	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 */

	uint32_t		ca_rev;
	uint32_t		ca_closest_nasid;

	uint64_t		ca_prom_private;
	uint64_t		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(uint64_t page_addr)
{
	uint64_t 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 uint64_t 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.
			 */

			ca_base->ca_control2 &= ~(CA_GART_MEM_PARAM);
			ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
			ca_base->ca_control2 |=
			    (0x2ull << CA_GART_MEM_PARAM_SHFT);
			tmp = ca_base->ca_control2;
		}

		return;
	}

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

	ca_base->ca_control2 |= CA_GART_FLUSH_TLB;
	tmp = ca_base->ca_control2;
}

extern uint32_t	tioca_gart_found;
204
extern struct list_head tioca_list;
205 206 207
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 */