intel-agp: add chipset flushing support

This adds support for flushing the chipsets on the 915, 945, 965 and G33
families of Intel chips.

The BIOS doesn't seem to always allocate the BAR on the 965 chipsets
so I have to use pci resource code to create a resource

It adds an export for pcibios_align_resource.

authored by Dave Airlie and committed by Dave Airlie 6c00a61e a13af4b4

+103 -1
+1 -1
arch/x86/pci/i386.c
··· 72 72 } 73 73 } 74 74 } 75 - 75 + EXPORT_SYMBOL(pcibios_align_resource); 76 76 77 77 /* 78 78 * Handle resources of PCI devices. If the world were perfect, we could
+102
drivers/char/agp/intel-agp.c
··· 71 71 #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) 72 72 #define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) 73 73 #define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) 74 + #define I915_IFPADDR 0x60 74 75 75 76 /* Intel 965G registers */ 76 77 #define I965_MSAC 0x62 78 + #define I965_IFPADDR 0x70 77 79 78 80 /* Intel 7505 registers */ 79 81 #define INTEL_I7505_APSIZE 0x74 ··· 117 115 * popup and for the GTT. 118 116 */ 119 117 int gtt_entries; /* i830+ */ 118 + void __iomem *flush_page; 119 + struct resource ifp_resource; 120 120 } intel_private; 121 121 122 122 static int intel_i810_fetch_size(void) ··· 772 768 return NULL; 773 769 } 774 770 771 + static int intel_alloc_chipset_flush_resource(void) 772 + { 773 + int ret; 774 + ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE, 775 + PAGE_SIZE, PCIBIOS_MIN_MEM, 0, 776 + pcibios_align_resource, agp_bridge->dev); 777 + if (ret != 0) 778 + return ret; 779 + 780 + printk("intel priv bus start %08lx\n", intel_private.ifp_resource.start); 781 + return 0; 782 + } 783 + 784 + static void intel_i915_setup_chipset_flush(void) 785 + { 786 + int ret; 787 + u32 temp; 788 + 789 + pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp); 790 + if (!(temp & 0x1)) { 791 + intel_alloc_chipset_flush_resource(); 792 + 793 + pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 794 + } else { 795 + temp &= ~1; 796 + 797 + intel_private.ifp_resource.start = temp; 798 + intel_private.ifp_resource.end = temp + PAGE_SIZE; 799 + ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 800 + if (ret) { 801 + intel_private.ifp_resource.start = 0; 802 + printk("Failed inserting resource into tree\n"); 803 + } 804 + } 805 + } 806 + 807 + static void intel_i965_g33_setup_chipset_flush(void) 808 + { 809 + u32 temp_hi, temp_lo; 810 + int ret; 811 + 812 + pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi); 813 + pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo); 814 + 815 + if (!(temp_lo & 0x1)) { 816 + 817 + intel_alloc_chipset_flush_resource(); 818 + 819 + pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, (intel_private.ifp_resource.start >> 32)); 820 + pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1); 821 + intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 822 + } else { 823 + u64 l64; 824 + 825 + temp_lo &= ~0x1; 826 + l64 = ((u64)temp_hi << 32) | temp_lo; 827 + 828 + intel_private.ifp_resource.start = l64; 829 + intel_private.ifp_resource.end = l64 + PAGE_SIZE; 830 + ret = request_resource(&iomem_resource, &intel_private.ifp_resource); 831 + if (!ret) { 832 + intel_private.ifp_resource.start = 0; 833 + printk("Failed inserting resource into tree\n"); 834 + } 835 + } 836 + } 837 + 775 838 static int intel_i915_configure(void) 776 839 { 777 840 struct aper_size_info_fixed *current_size; ··· 867 796 } 868 797 869 798 global_cache_flush(); 799 + 800 + /* setup a resource for this object */ 801 + memset(&intel_private.ifp_resource, 0, sizeof(intel_private.ifp_resource)); 802 + 803 + intel_private.ifp_resource.name = "Intel Flush Page"; 804 + intel_private.ifp_resource.flags = IORESOURCE_MEM; 805 + 806 + /* Setup chipset flush for 915 */ 807 + if (IS_I965 || IS_G33) { 808 + intel_i965_g33_setup_chipset_flush(); 809 + } else { 810 + intel_i915_setup_chipset_flush(); 811 + } 812 + 813 + if (intel_private.ifp_resource.start) { 814 + intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); 815 + if (!intel_private.flush_page) 816 + printk("unable to ioremap flush page - no chipset flushing"); 817 + } 818 + 870 819 return 0; 871 820 } 872 821 873 822 static void intel_i915_cleanup(void) 874 823 { 824 + if (intel_private.flush_page) 825 + iounmap(intel_private.flush_page); 875 826 iounmap(intel_private.gtt); 876 827 iounmap(intel_private.registers); 828 + } 829 + 830 + static void intel_i915_chipset_flush(struct agp_bridge_data *bridge) 831 + { 832 + if (intel_private.flush_page) 833 + writel(1, intel_private.flush_page); 877 834 } 878 835 879 836 static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, ··· 1820 1721 .agp_alloc_page = agp_generic_alloc_page, 1821 1722 .agp_destroy_page = agp_generic_destroy_page, 1822 1723 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1724 + .chipset_flush = intel_i915_chipset_flush, 1823 1725 }; 1824 1726 1825 1727 static const struct agp_bridge_driver intel_i965_driver = { ··· 1846 1746 .agp_alloc_page = agp_generic_alloc_page, 1847 1747 .agp_destroy_page = agp_generic_destroy_page, 1848 1748 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1749 + .chipset_flush = intel_i915_chipset_flush, 1849 1750 }; 1850 1751 1851 1752 static const struct agp_bridge_driver intel_7505_driver = { ··· 1896 1795 .agp_alloc_page = agp_generic_alloc_page, 1897 1796 .agp_destroy_page = agp_generic_destroy_page, 1898 1797 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1798 + .chipset_flush = intel_i915_chipset_flush, 1899 1799 }; 1900 1800 1901 1801 static int find_gmch(u16 device)