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 } 73 } 74 } 75 - 76 77 /* 78 * Handle resources of PCI devices. If the world were perfect, we could
··· 72 } 73 } 74 } 75 + EXPORT_SYMBOL(pcibios_align_resource); 76 77 /* 78 * Handle resources of PCI devices. If the world were perfect, we could
+102
drivers/char/agp/intel-agp.c
··· 71 #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) 72 #define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) 73 #define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) 74 75 /* Intel 965G registers */ 76 #define I965_MSAC 0x62 77 78 /* Intel 7505 registers */ 79 #define INTEL_I7505_APSIZE 0x74 ··· 117 * popup and for the GTT. 118 */ 119 int gtt_entries; /* i830+ */ 120 } intel_private; 121 122 static int intel_i810_fetch_size(void) ··· 772 return NULL; 773 } 774 775 static int intel_i915_configure(void) 776 { 777 struct aper_size_info_fixed *current_size; ··· 867 } 868 869 global_cache_flush(); 870 return 0; 871 } 872 873 static void intel_i915_cleanup(void) 874 { 875 iounmap(intel_private.gtt); 876 iounmap(intel_private.registers); 877 } 878 879 static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, ··· 1820 .agp_alloc_page = agp_generic_alloc_page, 1821 .agp_destroy_page = agp_generic_destroy_page, 1822 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1823 }; 1824 1825 static const struct agp_bridge_driver intel_i965_driver = { ··· 1846 .agp_alloc_page = agp_generic_alloc_page, 1847 .agp_destroy_page = agp_generic_destroy_page, 1848 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1849 }; 1850 1851 static const struct agp_bridge_driver intel_7505_driver = { ··· 1896 .agp_alloc_page = agp_generic_alloc_page, 1897 .agp_destroy_page = agp_generic_destroy_page, 1898 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1899 }; 1900 1901 static int find_gmch(u16 device)
··· 71 #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) 72 #define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) 73 #define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) 74 + #define I915_IFPADDR 0x60 75 76 /* Intel 965G registers */ 77 #define I965_MSAC 0x62 78 + #define I965_IFPADDR 0x70 79 80 /* Intel 7505 registers */ 81 #define INTEL_I7505_APSIZE 0x74 ··· 115 * popup and for the GTT. 116 */ 117 int gtt_entries; /* i830+ */ 118 + void __iomem *flush_page; 119 + struct resource ifp_resource; 120 } intel_private; 121 122 static int intel_i810_fetch_size(void) ··· 768 return NULL; 769 } 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 + 838 static int intel_i915_configure(void) 839 { 840 struct aper_size_info_fixed *current_size; ··· 796 } 797 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 + 819 return 0; 820 } 821 822 static void intel_i915_cleanup(void) 823 { 824 + if (intel_private.flush_page) 825 + iounmap(intel_private.flush_page); 826 iounmap(intel_private.gtt); 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); 834 } 835 836 static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, ··· 1721 .agp_alloc_page = agp_generic_alloc_page, 1722 .agp_destroy_page = agp_generic_destroy_page, 1723 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1724 + .chipset_flush = intel_i915_chipset_flush, 1725 }; 1726 1727 static const struct agp_bridge_driver intel_i965_driver = { ··· 1746 .agp_alloc_page = agp_generic_alloc_page, 1747 .agp_destroy_page = agp_generic_destroy_page, 1748 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1749 + .chipset_flush = intel_i915_chipset_flush, 1750 }; 1751 1752 static const struct agp_bridge_driver intel_7505_driver = { ··· 1795 .agp_alloc_page = agp_generic_alloc_page, 1796 .agp_destroy_page = agp_generic_destroy_page, 1797 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1798 + .chipset_flush = intel_i915_chipset_flush, 1799 }; 1800 1801 static int find_gmch(u16 device)