Commit 723ab324 authored by David Mosberger's avatar David Mosberger

ia64: Forward-port hp-agp.c fix from 2.4

See this ChangeSet:

http://lia64.bkbits.net:8080/linux-ia64-2.4/cset@40524248tkgE0RDYQL0IyiAdFxo_Ew
parent 2c7c376e
...@@ -27,10 +27,6 @@ ...@@ -27,10 +27,6 @@
#define HP_ZX1_TCNFG 0x318 #define HP_ZX1_TCNFG 0x318
#define HP_ZX1_PDIR_BASE 0x320 #define HP_ZX1_PDIR_BASE 0x320
/* HP ZX1 LBA registers */
#define HP_ZX1_AGP_STATUS 0x64
#define HP_ZX1_AGP_COMMAND 0x68
#define HP_ZX1_IOVA_BASE GB(1UL) #define HP_ZX1_IOVA_BASE GB(1UL)
#define HP_ZX1_IOVA_SIZE GB(1UL) #define HP_ZX1_IOVA_SIZE GB(1UL)
#define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2) #define HP_ZX1_GART_SIZE (HP_ZX1_IOVA_SIZE / 2)
...@@ -39,6 +35,9 @@ ...@@ -39,6 +35,9 @@
#define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL #define HP_ZX1_PDIR_VALID_BIT 0x8000000000000000UL
#define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> hp_private.io_tlb_shift) #define HP_ZX1_IOVA_TO_PDIR(va) ((va - hp_private.iova_base) >> hp_private.io_tlb_shift)
#define AGP8X_MODE_BIT 3
#define AGP8X_MODE (1 << AGP8X_MODE_BIT)
/* AGP bridge need not be PCI device, but DRM thinks it is. */ /* AGP bridge need not be PCI device, but DRM thinks it is. */
static struct pci_dev fake_bridge_dev; static struct pci_dev fake_bridge_dev;
...@@ -57,6 +56,7 @@ static struct gatt_mask hp_zx1_masks[] = ...@@ -57,6 +56,7 @@ static struct gatt_mask hp_zx1_masks[] =
static struct _hp_private { static struct _hp_private {
volatile u8 *ioc_regs; volatile u8 *ioc_regs;
volatile u8 *lba_regs; volatile u8 *lba_regs;
int lba_cap_offset;
u64 *io_pdir; // PDIR for entire IOVA u64 *io_pdir; // PDIR for entire IOVA
u64 *gatt; // PDIR just for GART (subset of above) u64 *gatt; // PDIR just for GART (subset of above)
u64 gatt_entries; u64 gatt_entries;
...@@ -109,6 +109,7 @@ static int __init hp_zx1_ioc_shared(void) ...@@ -109,6 +109,7 @@ static int __init hp_zx1_ioc_shared(void)
hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
/* Normal case when no AGP device in system */
hp->gatt = 0; hp->gatt = 0;
hp->gatt_entries = 0; hp->gatt_entries = 0;
printk(KERN_ERR PFX "No reserved IO PDIR entry found; " printk(KERN_ERR PFX "No reserved IO PDIR entry found; "
...@@ -156,12 +157,13 @@ hp_zx1_ioc_owner (void) ...@@ -156,12 +157,13 @@ hp_zx1_ioc_owner (void)
} }
static int __init static int __init
hp_zx1_ioc_init (u64 ioc_hpa, u64 lba_hpa) hp_zx1_ioc_init (u64 hpa)
{ {
struct _hp_private *hp = &hp_private; struct _hp_private *hp = &hp_private;
hp->ioc_regs = ioremap(ioc_hpa, 1024); hp->ioc_regs = ioremap(hpa, 1024);
hp->lba_regs = ioremap(lba_hpa, 256); if (!hp->ioc_regs)
return -ENOMEM;
/* /*
* If the IOTLB is currently disabled, we can take it over. * If the IOTLB is currently disabled, we can take it over.
...@@ -175,6 +177,51 @@ hp_zx1_ioc_init (u64 ioc_hpa, u64 lba_hpa) ...@@ -175,6 +177,51 @@ hp_zx1_ioc_init (u64 ioc_hpa, u64 lba_hpa)
return hp_zx1_ioc_shared(); return hp_zx1_ioc_shared();
} }
static int
hp_zx1_lba_find_capability (volatile u8 *hpa, int cap)
{
u16 status;
u8 pos, id;
int ttl = 48;
status = INREG16(hpa, PCI_STATUS);
if (!(status & PCI_STATUS_CAP_LIST))
return 0;
pos = INREG8(hpa, PCI_CAPABILITY_LIST);
while (ttl-- && pos >= 0x40) {
pos &= ~3;
id = INREG8(hpa, pos + PCI_CAP_LIST_ID);
if (id == 0xff)
break;
if (id == cap)
return pos;
pos = INREG8(hpa, pos + PCI_CAP_LIST_NEXT);
}
return 0;
}
static int __init
hp_zx1_lba_init (u64 hpa)
{
struct _hp_private *hp = &hp_private;
int cap;
hp->lba_regs = ioremap(hpa, 256);
if (!hp->lba_regs)
return -ENOMEM;
hp->lba_cap_offset = hp_zx1_lba_find_capability(hp->lba_regs, PCI_CAP_ID_AGP);
cap = INREG32(hp->lba_regs, hp->lba_cap_offset) & 0xff;
if (cap != PCI_CAP_ID_AGP) {
printk(KERN_ERR PFX "Invalid capability ID 0x%02x at 0x%x\n",
cap, hp->lba_cap_offset);
return -ENODEV;
}
return 0;
}
static int static int
hp_zx1_fetch_size(void) hp_zx1_fetch_size(void)
{ {
...@@ -192,13 +239,8 @@ hp_zx1_configure (void) ...@@ -192,13 +239,8 @@ hp_zx1_configure (void)
struct _hp_private *hp = &hp_private; struct _hp_private *hp = &hp_private;
agp_bridge->gart_bus_addr = hp->gart_base; agp_bridge->gart_bus_addr = hp->gart_base;
#if 0 agp_bridge->capndx = hp->lba_cap_offset;
/* ouch!! can't do that with a non-PCI AGP bridge... */ agp_bridge->mode = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS);
agp_bridge->capndx = pci_find_capability(agp_bridge->dev, PCI_CAP_ID_AGP);
#else
agp_bridge->capndx = 0;
#endif
agp_bridge->mode = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS);
if (hp->io_pdir_owner) { if (hp->io_pdir_owner) {
OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_phys(hp->io_pdir)); OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_phys(hp->io_pdir));
...@@ -217,9 +259,13 @@ hp_zx1_cleanup (void) ...@@ -217,9 +259,13 @@ hp_zx1_cleanup (void)
{ {
struct _hp_private *hp = &hp_private; struct _hp_private *hp = &hp_private;
if (hp->io_pdir_owner) if (hp->ioc_regs) {
OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0); if (hp->io_pdir_owner)
iounmap((void *) hp->ioc_regs); OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, 0);
iounmap((void *) hp->ioc_regs);
}
if (hp->lba_regs)
iounmap((void *) hp->lba_regs);
} }
static void static void
...@@ -350,14 +396,14 @@ hp_zx1_enable (u32 mode) ...@@ -350,14 +396,14 @@ hp_zx1_enable (u32 mode)
struct _hp_private *hp = &hp_private; struct _hp_private *hp = &hp_private;
u32 command; u32 command;
command = INREG32(hp->lba_regs, HP_ZX1_AGP_STATUS); command = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS);
command = agp_collect_device_status(mode, command); command = agp_collect_device_status(mode, command);
command |= 0x00000100; command |= 0x00000100;
OUTREG32(hp->lba_regs, HP_ZX1_AGP_COMMAND, command); OUTREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_COMMAND, command);
agp_device_command(command, 0); agp_device_command(command, (mode & AGP8X_MODE) != 0);
} }
struct agp_bridge_driver hp_zx1_driver = { struct agp_bridge_driver hp_zx1_driver = {
...@@ -386,22 +432,32 @@ static int __init ...@@ -386,22 +432,32 @@ static int __init
hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa) hp_zx1_setup (u64 ioc_hpa, u64 lba_hpa)
{ {
struct agp_bridge_data *bridge; struct agp_bridge_data *bridge;
int error; int error = 0;
error = hp_zx1_ioc_init(ioc_hpa);
if (error)
goto fail;
error = hp_zx1_ioc_init(ioc_hpa, lba_hpa); error = hp_zx1_lba_init(lba_hpa);
if (error) if (error)
return error; goto fail;
bridge = agp_alloc_bridge(); bridge = agp_alloc_bridge();
if (!bridge) if (!bridge) {
return -ENOMEM; error = -ENOMEM;
goto fail;
}
bridge->driver = &hp_zx1_driver; bridge->driver = &hp_zx1_driver;
fake_bridge_dev.vendor = PCI_VENDOR_ID_HP; fake_bridge_dev.vendor = PCI_VENDOR_ID_HP;
fake_bridge_dev.device = PCI_DEVICE_ID_HP_PCIX_LBA; fake_bridge_dev.device = PCI_DEVICE_ID_HP_PCIX_LBA;
bridge->dev = &fake_bridge_dev; bridge->dev = &fake_bridge_dev;
return agp_add_bridge(bridge); error = agp_add_bridge(bridge);
fail:
if (error)
hp_zx1_cleanup();
return error;
} }
static acpi_status __init static acpi_status __init
...@@ -416,7 +472,7 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) ...@@ -416,7 +472,7 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
status = hp_acpi_csr_space(obj, &lba_hpa, &length); status = hp_acpi_csr_space(obj, &lba_hpa, &length);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
return AE_OK; return AE_OK; /* keep looking for another bridge */
/* Look for an enclosing IOC scope and find its CSR space */ /* Look for an enclosing IOC scope and find its CSR space */
handle = obj; handle = obj;
...@@ -452,7 +508,7 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) ...@@ -452,7 +508,7 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret)
(char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa); (char *) context, sba_hpa + HP_ZX1_IOC_OFFSET, lba_hpa);
hp_zx1_gart_found = 1; hp_zx1_gart_found = 1;
return AE_CTRL_TERMINATE; return AE_CTRL_TERMINATE; /* we only support one bridge; quit looking */
} }
static int __init static int __init
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment