aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2007-10-29 04:06:10 -0400
committerDave Airlie <airlied@redhat.com>2008-02-04 23:33:32 -0500
commit6c00a61e1bc969c3ea931f62f8789d9818bf1918 (patch)
tree6ec75d02be64dd7ad4480f03ce800c53bc355a10
parenta13af4b4d842da6d7065b8c73fa8f0ac58fea1b6 (diff)
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.
-rw-r--r--arch/x86/pci/i386.c2
-rw-r--r--drivers/char/agp/intel-agp.c102
2 files changed, 103 insertions, 1 deletions
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 42ba0e2da1a..103b9dff121 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -72,7 +72,7 @@ pcibios_align_resource(void *data, struct resource *res,
72 } 72 }
73 } 73 }
74} 74}
75 75EXPORT_SYMBOL(pcibios_align_resource);
76 76
77/* 77/*
78 * Handle resources of PCI devices. If the world were perfect, we could 78 * Handle resources of PCI devices. If the world were perfect, we could
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 189efb6ef97..4d062fc3e82 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -71,9 +71,11 @@ extern int agp_memory_reserved;
71#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) 71#define I915_GMCH_GMS_STOLEN_64M (0x7 << 4)
72#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4) 72#define G33_GMCH_GMS_STOLEN_128M (0x8 << 4)
73#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) 73#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4)
74#define I915_IFPADDR 0x60
74 75
75/* Intel 965G registers */ 76/* Intel 965G registers */
76#define I965_MSAC 0x62 77#define I965_MSAC 0x62
78#define I965_IFPADDR 0x70
77 79
78/* Intel 7505 registers */ 80/* Intel 7505 registers */
79#define INTEL_I7505_APSIZE 0x74 81#define INTEL_I7505_APSIZE 0x74
@@ -115,6 +117,8 @@ static struct _intel_private {
115 * popup and for the GTT. 117 * popup and for the GTT.
116 */ 118 */
117 int gtt_entries; /* i830+ */ 119 int gtt_entries; /* i830+ */
120 void __iomem *flush_page;
121 struct resource ifp_resource;
118} intel_private; 122} intel_private;
119 123
120static int intel_i810_fetch_size(void) 124static int intel_i810_fetch_size(void)
@@ -768,6 +772,73 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
768 return NULL; 772 return NULL;
769} 773}
770 774
775static int intel_alloc_chipset_flush_resource(void)
776{
777 int ret;
778 ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
779 PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
780 pcibios_align_resource, agp_bridge->dev);
781 if (ret != 0)
782 return ret;
783
784 printk("intel priv bus start %08lx\n", intel_private.ifp_resource.start);
785 return 0;
786}
787
788static void intel_i915_setup_chipset_flush(void)
789{
790 int ret;
791 u32 temp;
792
793 pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp);
794 if (!(temp & 0x1)) {
795 intel_alloc_chipset_flush_resource();
796
797 pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
798 } else {
799 temp &= ~1;
800
801 intel_private.ifp_resource.start = temp;
802 intel_private.ifp_resource.end = temp + PAGE_SIZE;
803 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
804 if (ret) {
805 intel_private.ifp_resource.start = 0;
806 printk("Failed inserting resource into tree\n");
807 }
808 }
809}
810
811static void intel_i965_g33_setup_chipset_flush(void)
812{
813 u32 temp_hi, temp_lo;
814 int ret;
815
816 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi);
817 pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo);
818
819 if (!(temp_lo & 0x1)) {
820
821 intel_alloc_chipset_flush_resource();
822
823 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4, (intel_private.ifp_resource.start >> 32));
824 pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
825 intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
826 } else {
827 u64 l64;
828
829 temp_lo &= ~0x1;
830 l64 = ((u64)temp_hi << 32) | temp_lo;
831
832 intel_private.ifp_resource.start = l64;
833 intel_private.ifp_resource.end = l64 + PAGE_SIZE;
834 ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
835 if (!ret) {
836 intel_private.ifp_resource.start = 0;
837 printk("Failed inserting resource into tree\n");
838 }
839 }
840}
841
771static int intel_i915_configure(void) 842static int intel_i915_configure(void)
772{ 843{
773 struct aper_size_info_fixed *current_size; 844 struct aper_size_info_fixed *current_size;
@@ -796,15 +867,43 @@ static int intel_i915_configure(void)
796 } 867 }
797 868
798 global_cache_flush(); 869 global_cache_flush();
870
871 /* setup a resource for this object */
872 memset(&intel_private.ifp_resource, 0, sizeof(intel_private.ifp_resource));
873
874 intel_private.ifp_resource.name = "Intel Flush Page";
875 intel_private.ifp_resource.flags = IORESOURCE_MEM;
876
877 /* Setup chipset flush for 915 */
878 if (IS_I965 || IS_G33) {
879 intel_i965_g33_setup_chipset_flush();
880 } else {
881 intel_i915_setup_chipset_flush();
882 }
883
884 if (intel_private.ifp_resource.start) {
885 intel_private.flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
886 if (!intel_private.flush_page)
887 printk("unable to ioremap flush page - no chipset flushing");
888 }
889
799 return 0; 890 return 0;
800} 891}
801 892
802static void intel_i915_cleanup(void) 893static void intel_i915_cleanup(void)
803{ 894{
895 if (intel_private.flush_page)
896 iounmap(intel_private.flush_page);
804 iounmap(intel_private.gtt); 897 iounmap(intel_private.gtt);
805 iounmap(intel_private.registers); 898 iounmap(intel_private.registers);
806} 899}
807 900
901static void intel_i915_chipset_flush(struct agp_bridge_data *bridge)
902{
903 if (intel_private.flush_page)
904 writel(1, intel_private.flush_page);
905}
906
808static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, 907static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
809 int type) 908 int type)
810{ 909{
@@ -1721,6 +1820,7 @@ static const struct agp_bridge_driver intel_915_driver = {
1721 .agp_alloc_page = agp_generic_alloc_page, 1820 .agp_alloc_page = agp_generic_alloc_page,
1722 .agp_destroy_page = agp_generic_destroy_page, 1821 .agp_destroy_page = agp_generic_destroy_page,
1723 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1822 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1823 .chipset_flush = intel_i915_chipset_flush,
1724}; 1824};
1725 1825
1726static const struct agp_bridge_driver intel_i965_driver = { 1826static const struct agp_bridge_driver intel_i965_driver = {
@@ -1746,6 +1846,7 @@ static const struct agp_bridge_driver intel_i965_driver = {
1746 .agp_alloc_page = agp_generic_alloc_page, 1846 .agp_alloc_page = agp_generic_alloc_page,
1747 .agp_destroy_page = agp_generic_destroy_page, 1847 .agp_destroy_page = agp_generic_destroy_page,
1748 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1848 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1849 .chipset_flush = intel_i915_chipset_flush,
1749}; 1850};
1750 1851
1751static const struct agp_bridge_driver intel_7505_driver = { 1852static const struct agp_bridge_driver intel_7505_driver = {
@@ -1795,6 +1896,7 @@ static const struct agp_bridge_driver intel_g33_driver = {
1795 .agp_alloc_page = agp_generic_alloc_page, 1896 .agp_alloc_page = agp_generic_alloc_page,
1796 .agp_destroy_page = agp_generic_destroy_page, 1897 .agp_destroy_page = agp_generic_destroy_page,
1797 .agp_type_to_mask_type = intel_i830_type_to_mask_type, 1898 .agp_type_to_mask_type = intel_i830_type_to_mask_type,
1899 .chipset_flush = intel_i915_chipset_flush,
1798}; 1900};
1799 1901
1800static int find_gmch(u16 device) 1902static int find_gmch(u16 device)