11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/arch/alpha/kernel/core_titan.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Code common to all TITAN core logic chips. 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define __EXTERN_INLINE inline 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/core_titan.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef __EXTERN_INLINE 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vmalloc.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ptrace.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/smp.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgalloc.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/tlbflush.h> 24025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook#include <asm/vga.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "proto.h" 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pci_impl.h" 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Save Titan configuration data as the console had it set up. */ 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long wsba[4]; 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long wsm[4]; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long tba[4]; 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} saved_config[4] __attribute__((common)); 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 39025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook * Is PChip 1 present? No need to query it more than once. 40025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook */ 41025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrookstatic int titan_pchip1_present; 42025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook 43025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook/* 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BIOS32-style PCI interface: 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_CONFIG 0 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_CONFIG 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define DBG_CFG(args) printk args 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds# define DBG_CFG(args) 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Routines to access TIG registers. 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline volatile unsigned long * 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmk_tig_addr(int offset) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (volatile unsigned long *)(TITAN_TIG_SPACE + (offset << 6)); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u8 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_read_tig(int offset, u8 value) 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned long *tig_addr = mk_tig_addr(offset); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (u8)(*tig_addr & 0xff); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_write_tig(int offset, u8 value) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned long *tig_addr = mk_tig_addr(offset); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *tig_addr = (unsigned long)value; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Given a bus, device, and function number, compute resulting 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * configuration space address 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * accordingly. It is therefore not safe to have concurrent 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * invocations to configuration space access routines, but there 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * really shouldn't be any need for this. 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that all config space accesses use Type 1 address format. 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note also that type 1 is determined by non-zero bus number. 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Type 1: 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 31:24 reserved 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 23:16 bus number (8 bits = 128 possible buses) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 15:11 Device number (5 bits) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10:8 function number 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7:2 register number 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Notes: 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The function number selects which function of a multi-function device 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (e.g., SCSI and Ethernet). 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The register selects a DWORD (32 bit) register offset. Hence it 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't get shifted by 2 bits as we want to "drop" the bottom two 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bits. 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *pci_addr, unsigned char *type1) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_controller *hose = pbus->sysdata; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long addr; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 bus = pbus->number; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, " 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pci_addr=0x%p, type1=0x%p)\n", 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus, device_fn, where, pci_addr, type1)); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pbus->parent) /* No parent means peer PCI bus. */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus = 0; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *type1 = (bus != 0); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr = (bus << 16) | (device_fn << 8) | where; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr |= hose->config_space_base; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *pci_addr = addr; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_read_config(struct pci_bus *bus, unsigned int devfn, int where, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size, u32 *value) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long addr; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char type1; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mk_conf_addr(bus, devfn, where, &addr, &type1)) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PCIBIOS_DEVICE_NOT_FOUND; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (size) { 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = __kernel_ldbu(*(vucp)addr); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = __kernel_ldwu(*(vusp)addr); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *value = *(vuip)addr; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PCIBIOS_SUCCESSFUL; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_write_config(struct pci_bus *bus, unsigned int devfn, int where, 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size, u32 value) 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long addr; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char type1; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mk_conf_addr(bus, devfn, where, &addr, &type1)) 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PCIBIOS_DEVICE_NOT_FOUND; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (size) { 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __kernel_stb(value, *(vucp)addr); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mb(); 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __kernel_ldbu(*(vucp)addr); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __kernel_stw(value, *(vusp)addr); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mb(); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __kernel_ldwu(*(vusp)addr); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(vuip)addr = value; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mb(); 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(vuip)addr; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PCIBIOS_SUCCESSFUL; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_ops titan_pci_ops = 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = titan_read_config, 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .write = titan_write_config, 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end) 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_pachip *pachip = 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (hose->index & 1) ? TITAN_pachip1 : TITAN_pachip0; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_pachip_port *port; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds volatile unsigned long *csr; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long value; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get the right hose. */ 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = &pachip->g_port; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hose->index & 2) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = &pachip->a_port; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We can invalidate up to 8 tlb entries in a go. The flush 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds matches against <31:16> in the pci address. 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Note that gtlbi* and atlbi* are in the same place in the g_port 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds and a_port, respectively, so the g_port offset can be used 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds even if hose is an a_port */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csr = &port->port_specific.g.gtlbia.csr; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((start ^ end) & 0xffff0000) == 0) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds csr = &port->port_specific.g.gtlbiv.csr; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* For TBIA, it doesn't matter what value we write. For TBI, 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it's the shifted tag bits. */ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = (start & 0xffff0000) >> 12; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csr = value; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mb(); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *csr; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_query_agp(titan_pachip_port *port) 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union TPAchipPCTL pctl; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set up APCTL */ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_q_whole = port->pctl.csr; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pctl.pctl_r_bits.apctl_v_agp_present; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_init_one_pachip_port(titan_pachip_port *port, int index) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_controller *hose; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose = alloc_pci_controller(); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (index == 0) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_isa_hose = hose; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->io_space = alloc_resource(); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->mem_space = alloc_resource(); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is for userland consumption. The 40-bit PIO bias that we 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * use in the kernel through KSEG doesn't work in the page table 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * based user mappings. (43-bit KSEG sign extends the physical 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * address from bit 40 to hit the I/O bit - mapped addresses don't). 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * So make sure we get the 43-bit PIO bias. 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->sparse_mem_base = 0; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->sparse_io_base = 0; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->dense_mem_base 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds = (TITAN_MEM(index) & 0xffffffffffUL) | 0x80000000000UL; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->dense_io_base 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds = (TITAN_IO(index) & 0xffffffffffUL) | 0x80000000000UL; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->config_space_base = TITAN_CONF(index); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->index = index; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->io_space->start = TITAN_IO(index) - TITAN_IO_BIAS; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->io_space->end = hose->io_space->start + TITAN_IO_SPACE - 1; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->io_space->name = pci_io_names[index]; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->io_space->flags = IORESOURCE_IO; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->mem_space->start = TITAN_MEM(index) - TITAN_MEM_BIAS; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->mem_space->end = hose->mem_space->start + 0xffffffff; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->mem_space->name = pci_mem_names[index]; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->mem_space->flags = IORESOURCE_MEM; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_resource(&ioport_resource, hose->io_space) < 0) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Failed to request IO on hose %d\n", index); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_resource(&iomem_resource, hose->mem_space) < 0) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Failed to request MEM on hose %d\n", index); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save the existing PCI window translations. SRM will 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need them when we go to reboot. 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsba[0] = port->wsba[0].csr; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsm[0] = port->wsm[0].csr; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].tba[0] = port->tba[0].csr; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsba[1] = port->wsba[1].csr; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsm[1] = port->wsm[1].csr; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].tba[1] = port->tba[1].csr; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsba[2] = port->wsba[2].csr; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsm[2] = port->wsm[2].csr; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].tba[2] = port->tba[2].csr; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsba[3] = port->wsba[3].csr; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].wsm[3] = port->wsm[3].csr; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_config[index].tba[3] = port->tba[3].csr; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up the PCI to main memory translation windows. 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: Window 3 on Titan is Scatter-Gather ONLY. 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Window 0 is scatter-gather 8MB at 8MB (for isa) 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Window 1 is direct access 1GB at 2GB 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Window 2 is scatter-gather 1GB at 3GB 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->sg_isa->align_entry = 8; /* 64KB for ISA */ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x40000000, 0); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hose->sg_pci->align_entry = 4; /* Titan caches 4 PTEs at a time */ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[0].csr = hose->sg_isa->dma_base | 3; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tba[0].csr = virt_to_phys(hose->sg_isa->ptes); 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[1].csr = __direct_map_base | 1; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsm[1].csr = (__direct_map_size - 1) & 0xfff00000; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tba[1].csr = 0; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[2].csr = hose->sg_pci->dma_base | 3; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsm[2].csr = (hose->sg_pci->size - 1) & 0xfff00000; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tba[2].csr = virt_to_phys(hose->sg_pci->ptes); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[3].csr = 0; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Enable the Monster Window to make DAC pci64 possible. */ 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->pctl.csr |= pctl_m_mwin; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it's an AGP port, initialize agplastwr. 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (titan_query_agp(port)) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->port_specific.a.agplastwr.csr = __direct_map_base; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_pci_tbi(hose, 0, -1); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1) 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 353025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook titan_pchip1_present = TITAN_cchip->csc.csr & 1L<<14; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Init the ports in hose order... */ 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_init_one_pachip_port(&pachip0->g_port, 0); /* hose 0 */ 357025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook if (titan_pchip1_present) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_init_one_pachip_port(&pachip1->g_port, 1);/* hose 1 */ 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_init_one_pachip_port(&pachip0->a_port, 2); /* hose 2 */ 360025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook if (titan_pchip1_present) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_init_arch(void) 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 368bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: titan_init_arch()\n", __func__); 369bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CChip registers:\n", __func__); 370bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_CSC 0x%lx\n", __func__, TITAN_cchip->csc.csr); 371bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_MTR 0x%lx\n", __func__, TITAN_cchip->mtr.csr); 372bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_MISC 0x%lx\n", __func__, TITAN_cchip->misc.csr); 373bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_DIM0 0x%lx\n", __func__, TITAN_cchip->dim0.csr); 374bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_DIM1 0x%lx\n", __func__, TITAN_cchip->dim1.csr); 375bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_DIR0 0x%lx\n", __func__, TITAN_cchip->dir0.csr); 376bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_DIR1 0x%lx\n", __func__, TITAN_cchip->dir1.csr); 377bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_DRIR 0x%lx\n", __func__, TITAN_cchip->drir.csr); 378bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison 379bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: DChip registers:\n", __func__); 380bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_DSC 0x%lx\n", __func__, TITAN_dchip->dsc.csr); 381bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_STR 0x%lx\n", __func__, TITAN_dchip->str.csr); 382bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: CSR_DREV 0x%lx\n", __func__, TITAN_dchip->drev.csr); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boot_cpuid = __hard_smp_processor_id(); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* With multiple PCI busses, we play with I/O as physical addrs. */ 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioport_resource.end = ~0UL; 389025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook iomem_resource.end = ~0UL; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PCI DMA Direct Mapping is 1GB at 2GB. */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __direct_map_base = 0x80000000; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __direct_map_size = 0x40000000; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Init the PA chip(s). */ 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_init_pachips(TITAN_pachip0, TITAN_pachip1); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for graphic console location (if any). */ 399025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook find_console_vga_hose(); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_kill_one_pachip_port(titan_pachip_port *port, int index) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[0].csr = saved_config[index].wsba[0]; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsm[0].csr = saved_config[index].wsm[0]; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tba[0].csr = saved_config[index].tba[0]; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[1].csr = saved_config[index].wsba[1]; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsm[1].csr = saved_config[index].wsm[1]; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tba[1].csr = saved_config[index].tba[1]; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[2].csr = saved_config[index].wsba[2]; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsm[2].csr = saved_config[index].wsm[2]; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tba[2].csr = saved_config[index].tba[2]; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsba[3].csr = saved_config[index].wsba[3]; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->wsm[3].csr = saved_config[index].wsm[3]; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->tba[3].csr = saved_config[index].tba[3]; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1) 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 425025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook if (titan_pchip1_present) { 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_kill_one_pachip_port(&pachip1->g_port, 1); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_kill_one_pachip_port(&pachip1->a_port, 3); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_kill_one_pachip_port(&pachip0->g_port, 0); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_kill_one_pachip_port(&pachip0->a_port, 2); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_kill_arch(int mode) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_kill_pachips(TITAN_pachip0, TITAN_pachip1); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IO map support. 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __iomem * 445025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrooktitan_ioportmap(unsigned long addr) 446025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook{ 447025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook FIXUP_IOADDR_VGA(addr); 448025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook return (void __iomem *)(addr + TITAN_IO_BIAS); 449025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook} 450025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook 451025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook 452025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrookvoid __iomem * 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_ioremap(unsigned long addr, unsigned long size) 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long baddr = addr & ~TITAN_HOSE_MASK; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long last = baddr + size - 1; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_controller *hose; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vm_struct *area; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long vaddr; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *ptes; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long pfn; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 465025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook * Adjust the address and hose, if necessary. 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 467025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook if (pci_vga_hose && __is_mem_vga(addr)) { 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds h = pci_vga_hose->index; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr += pci_vga_hose->mem_space->start; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find the hose. 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (hose = hose_head; hose; hose = hose->next) 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hose->index == h) 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!hose) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Is it direct-mapped? 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((baddr >= __direct_map_base) && 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((baddr + size - 1) < __direct_map_base + __direct_map_size)) { 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vaddr = addr - __direct_map_base + TITAN_MEM_BIAS; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (void __iomem *) vaddr; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check the scatter-gather arena. 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hose->sg_pci && 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baddr >= (unsigned long)hose->sg_pci->dma_base && 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adjust the limits (mappings must be page aligned) 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baddr -= hose->sg_pci->dma_base; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last -= hose->sg_pci->dma_base; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baddr &= PAGE_MASK; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = PAGE_ALIGN(last) - baddr; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Map it 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds area = get_vm_area(size, VM_IOREMAP); 509025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook if (!area) { 510025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook printk("ioremap failed... no vm_area...\n"); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 512025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook } 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptes = hose->sg_pci->ptes; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (vaddr = (unsigned long)area->addr; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baddr <= last; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds baddr += PAGE_SIZE, vaddr += PAGE_SIZE) { 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pfn = ptes[baddr >> PAGE_SHIFT]; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(pfn & 1)) { 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("ioremap failed... pte not valid...\n"); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vfree(area->addr); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pfn >>= 1; /* make it a true pfn */ 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__alpha_remap_area_pages(vaddr, 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pfn << PAGE_SHIFT, 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PAGE_SIZE, 0)) { 529025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook printk("FAILED to remap_area_pages...\n"); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vfree(area->addr); 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flush_tlb_all(); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (void __iomem *) vaddr; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook /* Assume a legacy (read: VGA) address, and return appropriately. */ 542025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook return (void __iomem *)(addr + TITAN_MEM_BIAS); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_iounmap(volatile void __iomem *xaddr) 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long addr = (unsigned long) xaddr; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr >= VMALLOC_START) 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vfree((void *)(PAGE_MASK & addr)); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_is_mmio(const volatile void __iomem *xaddr) 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long addr = (unsigned long) xaddr; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr >= VMALLOC_START) 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (addr & 0x100000000UL) == 0; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_ALPHA_GENERIC 565025a22151c41890e5d30a1d4fb84c547b84d7671Jay EstabrookEXPORT_SYMBOL(titan_ioportmap); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(titan_ioremap); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(titan_iounmap); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(titan_is_mmio); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AGP GART Support. 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/agp_backend.h> 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/agp_backend.h> 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct titan_agp_aperture { 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_iommu_arena *arena; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long pg_start; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long pg_count; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_agp_setup(alpha_agp_info *agp) 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct titan_agp_aperture *aper; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!alpha_agpgart_size) 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aper = kmalloc(sizeof(struct titan_agp_aperture), GFP_KERNEL); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (aper == NULL) 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aper->arena = agp->hose->sg_pci; 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aper->pg_count = alpha_agpgart_size / PAGE_SIZE; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aper->pg_start = iommu_reserve(aper->arena, aper->pg_count, 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aper->pg_count - 1); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (aper->pg_start < 0) { 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Failed to reserve AGP memory\n"); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(aper); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->aperture.bus_base = 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aper->arena->dma_base + aper->pg_start * PAGE_SIZE; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->aperture.size = aper->pg_count * PAGE_SIZE; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->aperture.sysdata = aper; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_agp_cleanup(alpha_agp_info *agp) 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct titan_agp_aperture *aper = agp->aperture.sysdata; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = iommu_release(aper->arena, aper->pg_start, aper->pg_count); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status == -EBUSY) { 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "Attempted to release bound AGP memory - unbinding\n"); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iommu_unbind(aper->arena, aper->pg_start, aper->pg_count); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = iommu_release(aper->arena, aper->pg_start, 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds aper->pg_count); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status < 0) 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "Failed to release AGP memory\n"); 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(aper); 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(agp); 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_agp_configure(alpha_agp_info *agp) 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union TPAchipPCTL pctl; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_pachip_port *port = agp->private; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_q_whole = port->pctl.csr; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Side-Band Addressing? */ 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_sba_en = agp->mode.bits.sba; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* AGP Rate? */ 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_rate = 0; /* 1x */ 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp->mode.bits.rate & 2) 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_rate = 1; /* 2x */ 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (agp->mode.bits.rate & 4) 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_rate = 2; /* 4x */ 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* RQ Depth? */ 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_hp_rd = 2; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_lp_rd = 7; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * AGP Enable. 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_en = agp->mode.bits.enable; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Tell the user. */ 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Enabling AGP: %dX%s\n", 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1 << pctl.pctl_r_bits.apctl_v_agp_rate, 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_r_bits.apctl_v_agp_sba_en ? " - SBA" : ""); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Write it. */ 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port->pctl.csr = pctl.pctl_q_whole; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* And wait at least 5000 66MHz cycles (per Titan spec). */ 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(100); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem) 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct titan_agp_aperture *aper = agp->aperture.sysdata; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return iommu_bind(aper->arena, aper->pg_start + pg_start, 683d68721eb339e9237c11c1fea5f73f86211d14918Ivan Kokshaysky mem->page_count, mem->pages); 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem) 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct titan_agp_aperture *aper = agp->aperture.sysdata; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return iommu_unbind(aper->arena, aper->pg_start + pg_start, 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem->page_count); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_agp_translate(alpha_agp_info *agp, dma_addr_t addr) 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct titan_agp_aperture *aper = agp->aperture.sysdata; 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long baddr = addr - aper->arena->dma_base; 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long pte; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (addr < agp->aperture.bus_base || 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds addr >= agp->aperture.bus_base + agp->aperture.size) { 703bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: addr out of range\n", __func__); 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pte = aper->arena->ptes[baddr >> PAGE_SHIFT]; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(pte & 1)) { 709bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison printk("%s: pte not valid\n", __func__); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (pte >> 1) << PAGE_SHIFT; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct alpha_agp_ops titan_agp_ops = 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .setup = titan_agp_setup, 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cleanup = titan_agp_cleanup, 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .configure = titan_agp_configure, 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .bind = titan_agp_bind_memory, 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .unbind = titan_agp_unbind_memory, 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .translate = titan_agp_translate 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsalpha_agp_info * 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstitan_agp_info(void) 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds alpha_agp_info *agp; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_controller *hose; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_pachip_port *port; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hosenum = -1; 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds union TPAchipPCTL pctl; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find the AGP port. 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = &TITAN_pachip0->a_port; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (titan_query_agp(port)) 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hosenum = 2; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hosenum < 0 && 742025a22151c41890e5d30a1d4fb84c547b84d7671Jay Estabrook titan_pchip1_present && 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds titan_query_agp(port = &TITAN_pachip1->a_port)) 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hosenum = 3; 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find the hose the port is on. 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (hose = hose_head; hose; hose = hose->next) 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (hose->index == hosenum) 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!hose || !hose->sg_pci) 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate the info structure. 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp = kmalloc(sizeof(*agp), GFP_KERNEL); 760cc9a2c8301683f73b7e0d1fc2cb5159110f3469fJulia Lawall if (!agp) 761cc9a2c8301683f73b7e0d1fc2cb5159110f3469fJulia Lawall return NULL; 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fill it in. 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->hose = hose; 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->private = port; 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->ops = &titan_agp_ops; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Aperture - not configured until ops.setup(). 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME - should we go ahead and allocate it here? 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->aperture.bus_base = 0; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->aperture.size = 0; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->aperture.sysdata = NULL; 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Capabilities. 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->capability.lw = 0; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->capability.bits.rate = 3; /* 2x, 1x */ 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->capability.bits.sba = 1; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->capability.bits.rq = 7; /* 8 - 1 */ 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Mode. 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pctl.pctl_q_whole = port->pctl.csr; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->mode.lw = 0; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->mode.bits.rate = 1 << pctl.pctl_r_bits.apctl_v_agp_rate; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->mode.bits.sba = pctl.pctl_r_bits.apctl_v_agp_sba_en; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->mode.bits.rq = 7; /* RQ Depth? */ 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds agp->mode.bits.enable = pctl.pctl_r_bits.apctl_v_agp_en; 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return agp; 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 799