hp-agp.c revision 24b8e0cc09483adc0fdd9c68914b19597bb9fddc
1/* 2 * HP zx1 AGPGART routines. 3 * 4 * (c) Copyright 2002, 2003 Hewlett-Packard Development Company, L.P. 5 * Bjorn Helgaas <bjorn.helgaas@hp.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11 12#include <linux/acpi.h> 13#include <linux/module.h> 14#include <linux/pci.h> 15#include <linux/init.h> 16#include <linux/agp_backend.h> 17 18#include <asm/acpi-ext.h> 19 20#include "agp.h" 21 22#ifndef log2 23#define log2(x) ffz(~(x)) 24#endif 25 26#define HP_ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */ 27 28/* HP ZX1 IOC registers */ 29#define HP_ZX1_IBASE 0x300 30#define HP_ZX1_IMASK 0x308 31#define HP_ZX1_PCOM 0x310 32#define HP_ZX1_TCNFG 0x318 33#define HP_ZX1_PDIR_BASE 0x320 34 35#define HP_ZX1_IOVA_BASE GB(1UL) 36#define HP_ZX1_IOVA_SIZE GB(1UL) 37#define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2) 38#define HP_ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL 39 40#define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL 41#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> hp_private.io_tlb_shift) 42 43#define AGP8X_MODE_BIT 3 44#define AGP8X_MODE (1 << AGP8X_MODE_BIT) 45 46/* AGP bridge need not be PCI device, but DRM thinks it is. */ 47static struct pci_dev fake_bridge_dev; 48 49static int hp_zx1_gart_found; 50 51static struct aper_size_info_fixed hp_zx1_sizes[] = 52{ 53 {0, 0, 0}, /* filled in by hp_zx1_fetch_size() */ 54}; 55 56static struct gatt_mask hp_zx1_masks[] = 57{ 58 {.mask = HP_ZX1_PDIR_VALID_BIT, .type = 0} 59}; 60 61static struct _hp_private { 62 volatile u8 __iomem *ioc_regs; 63 volatile u8 __iomem *lba_regs; 64 int lba_cap_offset; 65 u64 *io_pdir; // PDIR for entire IOVA 66 u64 *gatt; // PDIR just for GART (subset of above) 67 u64 gatt_entries; 68 u64 iova_base; 69 u64 gart_base; 70 u64 gart_size; 71 u64 io_pdir_size; 72 int io_pdir_owner; // do we own it, or share it with sba_iommu? 73 int io_page_size; 74 int io_tlb_shift; 75 int io_tlb_ps; // IOC ps config 76 int io_pages_per_kpage; 77} hp_private; 78 79static int __init hp_zx1_ioc_shared(void) 80{ 81 struct _hp_private *hp = &hp_private; 82 83 printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR shared with sba_iommu\n"); 84 85 /* 86 * IOC already configured by sba_iommu module; just use 87 * its setup. We assume: 88 * - IOVA space is 1Gb in size 89 * - first 512Mb is IOMMU, second 512Mb is GART 90 */ 91 hp->io_tlb_ps = readq(hp->ioc_regs+HP_ZX1_TCNFG); 92 switch (hp->io_tlb_ps) { 93 case 0: hp->io_tlb_shift = 12; break; 94 case 1: hp->io_tlb_shift = 13; break; 95 case 2: hp->io_tlb_shift = 14; break; 96 case 3: hp->io_tlb_shift = 16; break; 97 default: 98 printk(KERN_ERR PFX "Invalid IOTLB page size " 99 "configuration 0x%x\n", hp->io_tlb_ps); 100 hp->gatt = NULL; 101 hp->gatt_entries = 0; 102 return -ENODEV; 103 } 104 hp->io_page_size = 1 << hp->io_tlb_shift; 105 hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; 106 107 hp->iova_base = readq(hp->ioc_regs+HP_ZX1_IBASE) & ~0x1; 108 hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - HP_ZX1_GART_SIZE; 109 110 hp->gart_size = HP_ZX1_GART_SIZE; 111 hp->gatt_entries = hp->gart_size / hp->io_page_size; 112 113 hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE)); 114 hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; 115 116 if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { 117 /* Normal case when no AGP device in system */ 118 hp->gatt = NULL; 119 hp->gatt_entries = 0; 120 printk(KERN_ERR PFX "No reserved IO PDIR entry found; " 121 "GART disabled\n"); 122 return -ENODEV; 123 } 124 125 return 0; 126} 127 128static int __init 129hp_zx1_ioc_owner (void) 130{ 131 struct _hp_private *hp = &hp_private; 132 133 printk(KERN_INFO PFX "HP ZX1 IOC: IOPDIR dedicated to GART\n"); 134 135 /* 136 * Select an IOV page size no larger than system page size. 137 */ 138 if (PAGE_SIZE >= KB(64)) { 139 hp->io_tlb_shift = 16; 140 hp->io_tlb_ps = 3; 141 } else if (PAGE_SIZE >= KB(16)) { 142 hp->io_tlb_shift = 14; 143 hp->io_tlb_ps = 2; 144 } else if (PAGE_SIZE >= KB(8)) { 145 hp->io_tlb_shift = 13; 146 hp->io_tlb_ps = 1; 147 } else { 148 hp->io_tlb_shift = 12; 149 hp->io_tlb_ps = 0; 150 } 151 hp->io_page_size = 1 << hp->io_tlb_shift; 152 hp->io_pages_per_kpage = PAGE_SIZE / hp->io_page_size; 153 154 hp->iova_base = HP_ZX1_IOVA_BASE; 155 hp->gart_size = HP_ZX1_GART_SIZE; 156 hp->gart_base = hp->iova_base + HP_ZX1_IOVA_SIZE - hp->gart_size; 157 158 hp->gatt_entries = hp->gart_size / hp->io_page_size; 159 hp->io_pdir_size = (HP_ZX1_IOVA_SIZE / hp->io_page_size) * sizeof(u64); 160 161 return 0; 162} 163 164static int __init 165hp_zx1_ioc_init (u64 hpa) 166{ 167 struct _hp_private *hp = &hp_private; 168 169 hp->ioc_regs = ioremap(hpa, 1024); 170 if (!hp->ioc_regs) 171 return -ENOMEM; 172 173 /* 174 * If the IOTLB is currently disabled, we can take it over. 175 * Otherwise, we have to share with sba_iommu. 176 */ 177 hp->io_pdir_owner = (readq(hp->ioc_regs+HP_ZX1_IBASE) & 0x1) == 0; 178 179 if (hp->io_pdir_owner) 180 return hp_zx1_ioc_owner(); 181 182 return hp_zx1_ioc_shared(); 183} 184 185static int 186hp_zx1_lba_find_capability (volatile u8 __iomem *hpa, int cap) 187{ 188 u16 status; 189 u8 pos, id; 190 int ttl = 48; 191 192 status = readw(hpa+PCI_STATUS); 193 if (!(status & PCI_STATUS_CAP_LIST)) 194 return 0; 195 pos = readb(hpa+PCI_CAPABILITY_LIST); 196 while (ttl-- && pos >= 0x40) { 197 pos &= ~3; 198 id = readb(hpa+pos+PCI_CAP_LIST_ID); 199 if (id == 0xff) 200 break; 201 if (id == cap) 202 return pos; 203 pos = readb(hpa+pos+PCI_CAP_LIST_NEXT); 204 } 205 return 0; 206} 207 208static int __init 209hp_zx1_lba_init (u64 hpa) 210{ 211 struct _hp_private *hp = &hp_private; 212 int cap; 213 214 hp->lba_regs = ioremap(hpa, 256); 215 if (!hp->lba_regs) 216 return -ENOMEM; 217 218 hp->lba_cap_offset = hp_zx1_lba_find_capability(hp->lba_regs, PCI_CAP_ID_AGP); 219 220 cap = readl(hp->lba_regs+hp->lba_cap_offset) & 0xff; 221 if (cap != PCI_CAP_ID_AGP) { 222 printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n", 223 cap, hp->lba_cap_offset); 224 return -ENODEV; 225 } 226 227 return 0; 228} 229 230static int 231hp_zx1_fetch_size(void) 232{ 233 int size; 234 235 size = hp_private.gart_size / MB(1); 236 hp_zx1_sizes[0].size = size; 237 agp_bridge->current_size = (void *) &hp_zx1_sizes[0]; 238 return size; 239} 240 241static int 242hp_zx1_configure (void) 243{ 244 struct _hp_private *hp = &hp_private; 245 246 agp_bridge->gart_bus_addr = hp->gart_base; 247 agp_bridge->capndx = hp->lba_cap_offset; 248 agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS); 249 250 if (hp->io_pdir_owner) { 251 writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE); 252 readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); 253 writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); 254 readl(hp->ioc_regs+HP_ZX1_TCNFG); 255 writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK); 256 readl(hp->ioc_regs+HP_ZX1_IMASK); 257 writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); 258 readl(hp->ioc_regs+HP_ZX1_IBASE); 259 writel(hp->iova_base|log2(HP_ZX1_IOVA_SIZE), hp->ioc_regs+HP_ZX1_PCOM); 260 readl(hp->ioc_regs+HP_ZX1_PCOM); 261 } 262 263 return 0; 264} 265 266static void 267hp_zx1_cleanup (void) 268{ 269 struct _hp_private *hp = &hp_private; 270 271 if (hp->ioc_regs) { 272 if (hp->io_pdir_owner) { 273 writeq(0, hp->ioc_regs+HP_ZX1_IBASE); 274 readq(hp->ioc_regs+HP_ZX1_IBASE); 275 } 276 iounmap(hp->ioc_regs); 277 } 278 if (hp->lba_regs) 279 iounmap(hp->lba_regs); 280} 281 282static void 283hp_zx1_tlbflush (struct agp_memory *mem) 284{ 285 struct _hp_private *hp = &hp_private; 286 287 writeq(hp->gart_base | log2(hp->gart_size), hp->ioc_regs+HP_ZX1_PCOM); 288 readq(hp->ioc_regs+HP_ZX1_PCOM); 289} 290 291static int 292hp_zx1_create_gatt_table (struct agp_bridge_data *bridge) 293{ 294 struct _hp_private *hp = &hp_private; 295 int i; 296 297 if (hp->io_pdir_owner) { 298 hp->io_pdir = (u64 *) __get_free_pages(GFP_KERNEL, 299 get_order(hp->io_pdir_size)); 300 if (!hp->io_pdir) { 301 printk(KERN_ERR PFX "Couldn't allocate contiguous " 302 "memory for I/O PDIR\n"); 303 hp->gatt = NULL; 304 hp->gatt_entries = 0; 305 return -ENOMEM; 306 } 307 memset(hp->io_pdir, 0, hp->io_pdir_size); 308 309 hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; 310 } 311 312 for (i = 0; i < hp->gatt_entries; i++) { 313 hp->gatt[i] = (unsigned long) agp_bridge->scratch_page; 314 } 315 316 return 0; 317} 318 319static int 320hp_zx1_free_gatt_table (struct agp_bridge_data *bridge) 321{ 322 struct _hp_private *hp = &hp_private; 323 324 if (hp->io_pdir_owner) 325 free_pages((unsigned long) hp->io_pdir, 326 get_order(hp->io_pdir_size)); 327 else 328 hp->gatt[0] = HP_ZX1_SBA_IOMMU_COOKIE; 329 return 0; 330} 331 332static int 333hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type) 334{ 335 struct _hp_private *hp = &hp_private; 336 int i, k; 337 off_t j, io_pg_start; 338 int io_pg_count; 339 340 if (type != 0 || mem->type != 0) { 341 return -EINVAL; 342 } 343 344 io_pg_start = hp->io_pages_per_kpage * pg_start; 345 io_pg_count = hp->io_pages_per_kpage * mem->page_count; 346 if ((io_pg_start + io_pg_count) > hp->gatt_entries) { 347 return -EINVAL; 348 } 349 350 j = io_pg_start; 351 while (j < (io_pg_start + io_pg_count)) { 352 if (hp->gatt[j]) { 353 return -EBUSY; 354 } 355 j++; 356 } 357 358 if (mem->is_flushed == FALSE) { 359 global_cache_flush(); 360 mem->is_flushed = TRUE; 361 } 362 363 for (i = 0, j = io_pg_start; i < mem->page_count; i++) { 364 unsigned long paddr; 365 366 paddr = mem->memory[i]; 367 for (k = 0; 368 k < hp->io_pages_per_kpage; 369 k++, j++, paddr += hp->io_page_size) { 370 hp->gatt[j] = 371 agp_bridge->driver->mask_memory(agp_bridge, 372 paddr, type); 373 } 374 } 375 376 agp_bridge->driver->tlb_flush(mem); 377 return 0; 378} 379 380static int 381hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type) 382{ 383 struct _hp_private *hp = &hp_private; 384 int i, io_pg_start, io_pg_count; 385 386 if (type != 0 || mem->type != 0) { 387 return -EINVAL; 388 } 389 390 io_pg_start = hp->io_pages_per_kpage * pg_start; 391 io_pg_count = hp->io_pages_per_kpage * mem->page_count; 392 for (i = io_pg_start; i < io_pg_count + io_pg_start; i++) { 393 hp->gatt[i] = agp_bridge->scratch_page; 394 } 395 396 agp_bridge->driver->tlb_flush(mem); 397 return 0; 398} 399 400static unsigned long 401hp_zx1_mask_memory (struct agp_bridge_data *bridge, 402 unsigned long addr, int type) 403{ 404 return HP_ZX1_PDIR_VALID_BIT | addr; 405} 406 407static void 408hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode) 409{ 410 struct _hp_private *hp = &hp_private; 411 u32 command; 412 413 command = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS); 414 command = agp_collect_device_status(bridge, mode, command); 415 command |= 0x00000100; 416 417 writel(command, hp->lba_regs+hp->lba_cap_offset+PCI_AGP_COMMAND); 418 419 agp_device_command(command, (mode & AGP8X_MODE) != 0); 420} 421 422struct agp_bridge_driver hp_zx1_driver = { 423 .owner = THIS_MODULE, 424 .size_type = FIXED_APER_SIZE, 425 .configure = hp_zx1_configure, 426 .fetch_size = hp_zx1_fetch_size, 427 .cleanup = hp_zx1_cleanup, 428 .tlb_flush = hp_zx1_tlbflush, 429 .mask_memory = hp_zx1_mask_memory, 430 .masks = hp_zx1_masks, 431 .agp_enable = hp_zx1_enable, 432 .cache_flush = global_cache_flush, 433 .create_gatt_table = hp_zx1_create_gatt_table, 434 .free_gatt_table = hp_zx1_free_gatt_table, 435 .insert_memory = hp_zx1_insert_memory, 436 .remove_memory = hp_zx1_remove_memory, 437 .alloc_by_type = agp_generic_alloc_by_type, 438 .free_by_type = agp_generic_free_by_type, 439 .agp_alloc_page = agp_generic_alloc_page, 440 .agp_destroy_page = agp_generic_destroy_page, 441 .cant_use_aperture = 1, 442}; 443 444static int __init 445hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa) 446{ 447 struct agp_bridge_data *bridge; 448 int error = 0; 449 450 error = hp_zx1_ioc_init(ioc_hpa); 451 if (error) 452 goto fail; 453 454 error = hp_zx1_lba_init(lba_hpa); 455 if (error) 456 goto fail; 457 458 bridge = agp_alloc_bridge(); 459 if (!bridge) { 460 error = -ENOMEM; 461 goto fail; 462 } 463 bridge->driver = &hp_zx1_driver; 464 465 fake_bridge_dev.vendor = PCI_VENDOR_ID_HP; 466 fake_bridge_dev.device = PCI_DEVICE_ID_HP_PCIX_LBA; 467 bridge->dev = &fake_bridge_dev; 468 469 error = agp_add_bridge(bridge); 470 fail: 471 if (error) 472 hp_zx1_cleanup(); 473 return error; 474} 475 476static acpi_status __init 477zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) 478{ 479 acpi_handle handle, parent; 480 acpi_status status; 481 struct acpi_buffer buffer; 482 struct acpi_device_info *info; 483 u64 lba_hpa, sba_hpa, length; 484 int match; 485 486 status = hp_acpi_csr_space(obj, &lba_hpa, &length); 487 if (ACPI_FAILURE(status)) 488 return AE_OK; /* keep looking for another bridge */ 489 490 /* Look for an enclosing IOC scope and find its CSR space */ 491 handle = obj; 492 do { 493 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; 494 status = acpi_get_object_info(handle, &buffer); 495 if (ACPI_SUCCESS(status)) { 496 /* TBD check _CID also */ 497 info = buffer.pointer; 498 info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0'; 499 match = (strcmp(info->hardware_id.value, "HWP0001") == 0); 500 ACPI_MEM_FREE(info); 501 if (match) { 502 status = hp_acpi_csr_space(handle, &sba_hpa, &length); 503 if (ACPI_SUCCESS(status)) 504 break; 505 else { 506 printk(KERN_ERR PFX "Detected HP ZX1 " 507 "AGP LBA but no IOC.\n"); 508 return AE_OK; 509 } 510 } 511 } 512 513 status = acpi_get_parent(handle, &parent); 514 handle = parent; 515 } while (ACPI_SUCCESS(status)); 516 517 if (hp_zx1_setup(sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa)) 518 return AE_OK; 519 520 printk(KERN_INFO PFX "Detected HP ZX1 %s AGP chipset (ioc=%lx, lba=%lx)\n", 521 (char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa); 522 523 hp_zx1_gart_found = 1; 524 return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */ 525} 526 527static int __init 528agp_hp_init (void) 529{ 530 if (agp_off) 531 return -EINVAL; 532 533 acpi_get_devices("HWP0003", zx1_gart_probe, "HWP0003", NULL); 534 if (hp_zx1_gart_found) 535 return 0; 536 537 acpi_get_devices("HWP0007", zx1_gart_probe, "HWP0007", NULL); 538 if (hp_zx1_gart_found) 539 return 0; 540 541 return -ENODEV; 542} 543 544static void __exit 545agp_hp_cleanup (void) 546{ 547} 548 549module_init(agp_hp_init); 550module_exit(agp_hp_cleanup); 551 552MODULE_LICENSE("GPL and additional rights"); 553