^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * ATi AGPGART routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/agp_backend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/agp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/set_memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "agp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define ATI_GART_MMBASE_BAR 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define ATI_RS100_APSIZE 0xac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define ATI_RS100_IG_AGPMODE 0xb0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define ATI_RS300_APSIZE 0xf8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define ATI_RS300_IG_AGPMODE 0xfc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define ATI_GART_FEATURE_ID 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define ATI_GART_BASE 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define ATI_GART_CACHE_SZBASE 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define ATI_GART_CACHE_CNTRL 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define ATI_GART_CACHE_ENTRY_CNTRL 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static const struct aper_size_info_lvl2 ati_generic_sizes[7] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {2048, 524288, 0x0000000c},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {1024, 262144, 0x0000000a},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {512, 131072, 0x00000008},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {256, 65536, 0x00000006},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {128, 32768, 0x00000004},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {64, 16384, 0x00000002},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {32, 8192, 0x00000000}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static struct gatt_mask ati_generic_masks[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { .mask = 1, .type = 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct ati_page_map {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) unsigned long *real;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned long __iomem *remapped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static struct _ati_generic_private {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) volatile u8 __iomem *registers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct ati_page_map **gatt_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int num_tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) } ati_generic_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static int ati_create_page_map(struct ati_page_map *page_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (page_map->real == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) set_memory_uc((unsigned long)page_map->real, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) err = map_page_into_agp(virt_to_page(page_map->real));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) page_map->remapped = page_map->real;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) writel(agp_bridge->scratch_page, page_map->remapped+i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) readl(page_map->remapped+i); /* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static void ati_free_page_map(struct ati_page_map *page_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unmap_page_from_agp(virt_to_page(page_map->real));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) set_memory_wb((unsigned long)page_map->real, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) free_page((unsigned long) page_map->real);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static void ati_free_gatt_pages(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct ati_page_map **tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct ati_page_map *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) tables = ati_generic_private.gatt_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for (i = 0; i < ati_generic_private.num_tables; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) entry = tables[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (entry != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (entry->real != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ati_free_page_map(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) kfree(tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int ati_create_gatt_pages(int nr_tables)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct ati_page_map **tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct ati_page_map *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) tables = kcalloc(nr_tables + 1, sizeof(struct ati_page_map *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (tables == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) for (i = 0; i < nr_tables; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) tables[i] = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (entry == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) retval = ati_create_page_map(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (retval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ati_generic_private.num_tables = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ati_generic_private.gatt_pages = tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (retval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ati_free_gatt_pages();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int is_r200(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if ((agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS100) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS200) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS200_B) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) (agp_bridge->dev->device == PCI_DEVICE_ID_ATI_RS250))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int ati_fetch_size(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct aper_size_info_lvl2 *values;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (is_r200())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) temp = (temp & 0x0000000e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (temp == values[i].size_value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) agp_bridge->previous_size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) agp_bridge->current_size = (void *) (values + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) agp_bridge->aperture_size_idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return values[i].size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) static void ati_tlbflush(struct agp_memory * mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) writel(1, ati_generic_private.registers+ATI_GART_CACHE_CNTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) readl(ati_generic_private.registers+ATI_GART_CACHE_CNTRL); /* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static void ati_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct aper_size_info_lvl2 *previous_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) previous_size = A_SIZE_LVL2(agp_bridge->previous_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* Write back the previous size and disable gart translation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (is_r200()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) temp = ((temp & ~(0x0000000f)) | previous_size->size_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) iounmap((volatile u8 __iomem *)ati_generic_private.registers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static int ati_configure(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) phys_addr_t reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* Get the memory mapped registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) reg = pci_resource_start(agp_bridge->dev, ATI_GART_MMBASE_BAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) ati_generic_private.registers = (volatile u8 __iomem *) ioremap(reg, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!ati_generic_private.registers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (is_r200())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) pci_write_config_dword(agp_bridge->dev, ATI_RS100_IG_AGPMODE, 0x20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) pci_write_config_dword(agp_bridge->dev, ATI_RS300_IG_AGPMODE, 0x20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* address to map to */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) agp_bridge.gart_bus_addr = pci_bus_address(agp_bridge.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) AGP_APERTURE_BAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) printk(KERN_INFO PFX "IGP320 gart_bus_addr: %x\n", agp_bridge.gart_bus_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) writel(0x60000, ati_generic_private.registers+ATI_GART_FEATURE_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) readl(ati_generic_private.registers+ATI_GART_FEATURE_ID); /* PCI Posting.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* SIGNALED_SYSTEM_ERROR @ NB_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pci_read_config_dword(agp_bridge->dev, PCI_COMMAND, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) pci_write_config_dword(agp_bridge->dev, PCI_COMMAND, temp | (1<<14));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Write out the address of the gatt table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) writel(agp_bridge->gatt_bus_addr, ati_generic_private.registers+ATI_GART_BASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) readl(ati_generic_private.registers+ATI_GART_BASE); /* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) pci_save_state(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) pci_set_power_state(dev, PCI_D3hot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int agp_ati_resume(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) pci_set_power_state(dev, PCI_D0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) pci_restore_state(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return ati_configure();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *Since we don't need contiguous memory we just try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * to get the gatt table once
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) #define GET_PAGE_DIR_OFF(addr) (addr >> 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #undef GET_GATT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #define GET_GATT(addr) (ati_generic_private.gatt_pages[\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) GET_PAGE_DIR_IDX(addr)]->remapped)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static int ati_insert_memory(struct agp_memory * mem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) off_t pg_start, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int i, j, num_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) unsigned long __iomem *cur_gatt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) int mask_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (mask_type != 0 || type != mem->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (mem->page_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if ((pg_start + mem->page_count) > num_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) j = pg_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) while (j < (pg_start + mem->page_count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) cur_gatt = GET_GATT(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (!PGE_EMPTY(agp_bridge,readl(cur_gatt+GET_GATT_OFF(addr))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!mem->is_flushed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /*CACHE_FLUSH(); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) global_cache_flush();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) mem->is_flushed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) cur_gatt = GET_GATT(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) writel(agp_bridge->driver->mask_memory(agp_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) page_to_phys(mem->pages[i]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) mem->type),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) cur_gatt+GET_GATT_OFF(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) agp_bridge->driver->tlb_flush(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int ati_remove_memory(struct agp_memory * mem, off_t pg_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) unsigned long __iomem *cur_gatt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int mask_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) mask_type = agp_generic_type_to_mask_type(mem->bridge, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (mask_type != 0 || type != mem->type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (mem->page_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) for (i = pg_start; i < (mem->page_count + pg_start); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) cur_gatt = GET_GATT(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) readl(GET_GATT(agp_bridge->gart_bus_addr)); /* PCI posting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) agp_bridge->driver->tlb_flush(mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static int ati_create_gatt_table(struct agp_bridge_data *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct aper_size_info_lvl2 *value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct ati_page_map page_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) unsigned long __iomem *cur_gatt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u32 temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) struct aper_size_info_lvl2 *current_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) value = A_SIZE_LVL2(agp_bridge->current_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) retval = ati_create_page_map(&page_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (retval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) retval = ati_create_gatt_pages(value->num_entries / 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (retval != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) ati_free_page_map(&page_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) agp_bridge->gatt_table_real = (u32 *)page_dir.real;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* Write out the size register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) current_size = A_SIZE_LVL2(agp_bridge->current_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (is_r200()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) temp = (((temp & ~(0x0000000e)) | current_size->size_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) | 0x00000001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) pci_write_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) pci_read_config_dword(agp_bridge->dev, ATI_RS100_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) temp = (((temp & ~(0x0000000e)) | current_size->size_value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) | 0x00000001);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) pci_write_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) pci_read_config_dword(agp_bridge->dev, ATI_RS300_APSIZE, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * Get the address for the gart region.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * This is a bus address even on the alpha, b/c its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * used to program the agp master not the cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) addr = pci_bus_address(agp_bridge->dev, AGP_APERTURE_BAR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) agp_bridge->gart_bus_addr = addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* Calculate the agp offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) writel(virt_to_phys(ati_generic_private.gatt_pages[i]->real) | 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) page_dir.remapped+GET_PAGE_DIR_OFF(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) for (i = 0; i < value->num_entries; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) cur_gatt = GET_GATT(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) writel(agp_bridge->scratch_page, cur_gatt+GET_GATT_OFF(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int ati_free_gatt_table(struct agp_bridge_data *bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) struct ati_page_map page_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) page_dir.real = (unsigned long *)agp_bridge->gatt_table_real;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ati_free_gatt_pages();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ati_free_page_map(&page_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) static const struct agp_bridge_driver ati_generic_bridge = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .aperture_sizes = ati_generic_sizes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .size_type = LVL2_APER_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) .num_aperture_sizes = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) .needs_scratch_page = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) .configure = ati_configure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) .fetch_size = ati_fetch_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) .cleanup = ati_cleanup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) .tlb_flush = ati_tlbflush,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) .mask_memory = agp_generic_mask_memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) .masks = ati_generic_masks,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) .agp_enable = agp_generic_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) .cache_flush = global_cache_flush,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) .create_gatt_table = ati_create_gatt_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) .free_gatt_table = ati_free_gatt_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) .insert_memory = ati_insert_memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) .remove_memory = ati_remove_memory,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) .alloc_by_type = agp_generic_alloc_by_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) .free_by_type = agp_generic_free_by_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) .agp_alloc_page = agp_generic_alloc_page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) .agp_alloc_pages = agp_generic_alloc_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) .agp_destroy_page = agp_generic_destroy_page,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) .agp_destroy_pages = agp_generic_destroy_pages,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) .agp_type_to_mask_type = agp_generic_type_to_mask_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static struct agp_device_ids ati_agp_device_ids[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .device_id = PCI_DEVICE_ID_ATI_RS100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .chipset_name = "IGP320/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) .device_id = PCI_DEVICE_ID_ATI_RS200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) .chipset_name = "IGP330/340/345/350/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) .device_id = PCI_DEVICE_ID_ATI_RS200_B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) .chipset_name = "IGP345M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) .device_id = PCI_DEVICE_ID_ATI_RS250,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .chipset_name = "IGP7000/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .device_id = PCI_DEVICE_ID_ATI_RS300_100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .chipset_name = "IGP9100/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) .device_id = PCI_DEVICE_ID_ATI_RS300_133,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) .chipset_name = "IGP9100/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) .device_id = PCI_DEVICE_ID_ATI_RS300_166,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) .chipset_name = "IGP9100/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) .device_id = PCI_DEVICE_ID_ATI_RS300_200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) .chipset_name = "IGP9100/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) .device_id = PCI_DEVICE_ID_ATI_RS350_133,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) .chipset_name = "IGP9000/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) .device_id = PCI_DEVICE_ID_ATI_RS350_200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) .chipset_name = "IGP9100/M",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) { }, /* dummy final entry, always present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) static int agp_ati_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) struct agp_device_ids *devs = ati_agp_device_ids;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) struct agp_bridge_data *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) u8 cap_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (!cap_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* probe for known chipsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) for (j = 0; devs[j].chipset_name; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (pdev->device == devs[j].device_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dev_err(&pdev->dev, "unsupported Ati chipset [%04x/%04x])\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) pdev->vendor, pdev->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) bridge = agp_alloc_bridge();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (!bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) bridge->dev = pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) bridge->capndx = cap_ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) bridge->driver = &ati_generic_bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) dev_info(&pdev->dev, "Ati %s chipset\n", devs[j].chipset_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* Fill in the mode register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) pci_read_config_dword(pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) bridge->capndx+PCI_AGP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) &bridge->mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) pci_set_drvdata(pdev, bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return agp_add_bridge(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) static void agp_ati_remove(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) agp_remove_bridge(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) agp_put_bridge(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) static const struct pci_device_id agp_ati_pci_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) .class = (PCI_CLASS_BRIDGE_HOST << 8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) .class_mask = ~0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) .vendor = PCI_VENDOR_ID_ATI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .device = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .subvendor = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .subdevice = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) MODULE_DEVICE_TABLE(pci, agp_ati_pci_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) static struct pci_driver agp_ati_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) .name = "agpgart-ati",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) .id_table = agp_ati_pci_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) .probe = agp_ati_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) .remove = agp_ati_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) .suspend = agp_ati_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) .resume = agp_ati_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) static int __init agp_ati_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (agp_off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return pci_register_driver(&agp_ati_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) static void __exit agp_ati_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) pci_unregister_driver(&agp_ati_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) module_init(agp_ati_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) module_exit(agp_ati_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) MODULE_AUTHOR("Dave Jones");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) MODULE_LICENSE("GPL and additional rights");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)