4 * Normal mappings of chips in physical memory
5 * $Id: amd76xrom.c,v 1.8 2003/05/28 15:44:28 dwmw2 Exp $
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/init.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/map.h>
15 #include <linux/config.h>
16 #include <linux/pci.h>
17 #include <linux/pci_ids.h>
20 struct amd76xrom_map_info {
23 unsigned long window_addr;
24 u32 window_start, window_size;
29 static struct amd76xrom_map_info amd76xrom_map = {
39 static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
40 const struct pci_device_id *ent)
47 static struct rom_window rom_window[] = {
48 { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), },
49 { 0xffc00000, 4*1024*1024, (1<<7), },
50 { 0xffff0000, 64*1024, 0 },
53 static const u32 rom_probe_sizes[] = {
54 5*1024*1024, 4*1024*1024, 2*1024*1024, 1024*1024, 512*1024,
55 256*1024, 128*1024, 64*1024, 0};
56 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", 0 };
58 struct amd76xrom_map_info *info = &amd76xrom_map;
59 struct rom_window *window;
63 window = &rom_window[0];
65 /* disabled because it fights with BIOS reserved regions */
66 #define REQUEST_MEM_REGION 0
67 #if REQUEST_MEM_REGION
69 if (request_mem_region(window->start, window->size, "amd76xrom")) {
75 printk(KERN_ERR "amd76xrom: cannot reserve rom window\n");
78 #endif /* REQUEST_MEM_REGION */
80 /* Enable the selected rom window */
81 pci_read_config_byte(pdev, 0x43, &byte);
82 pci_write_config_byte(pdev, 0x43, byte | window->segen_bits);
84 /* Enable writes through the rom window */
85 pci_read_config_byte(pdev, 0x40, &byte);
86 pci_write_config_byte(pdev, 0x40, byte | 1);
88 /* FIXME handle registers 0x80 - 0x8C the bios region locks */
90 printk(KERN_NOTICE "amd76xrom window : %x at %x\n",
91 window->size, window->start);
92 /* For write accesses caches are useless */
93 info->window_addr = (unsigned long)ioremap_nocache(window->start, window->size);
95 if (!info->window_addr) {
96 printk(KERN_ERR "Failed to ioremap\n");
97 goto err_out_free_mmio_region;
100 for(i = 0; (rom_size = rom_probe_sizes[i]); i++) {
102 if (rom_size > window->size) {
105 info->map.phys = window->start + window->size - rom_size;
107 info->window_addr + window->size - rom_size;
108 info->map.size = rom_size;
109 simple_map_init(&info->map);
110 chip_type = rom_probe_types;
111 for(; !info->mtd && *chip_type; chip_type++) {
112 info->mtd = do_map_probe(*chip_type, &amd76xrom_map.map);
119 goto err_out_iounmap;
121 printk(KERN_NOTICE "amd76xrom chip at offset: 0x%x\n",
122 window->size - rom_size);
124 info->mtd->owner = THIS_MODULE;
125 add_mtd_device(info->mtd);
126 info->window_start = window->start;
127 info->window_size = window->size;
131 iounmap((void *)(info->window_addr));
132 err_out_free_mmio_region:
133 #if REQUEST_MEM_REGION
134 release_mem_region(window->start, window->size);
136 #endif /* REQUEST_MEM_REGION */
141 static void __devexit amd76xrom_remove_one (struct pci_dev *pdev)
143 struct amd76xrom_map_info *info = &amd76xrom_map;
146 del_mtd_device(info->mtd);
147 map_destroy(info->mtd);
151 iounmap((void *)(info->window_addr));
152 info->window_addr = 0;
154 /* Disable writes through the rom window */
155 pci_read_config_byte(pdev, 0x40, &byte);
156 pci_write_config_byte(pdev, 0x40, byte & ~1);
158 #if REQUEST_MEM_REGION
159 release_mem_region(info->window_start, info->window_size);
160 #endif /* REQUEST_MEM_REGION */
163 static struct pci_device_id amd76xrom_pci_tbl[] = {
164 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,
165 PCI_ANY_ID, PCI_ANY_ID, },
166 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7440,
167 PCI_ANY_ID, PCI_ANY_ID, },
168 { PCI_VENDOR_ID_AMD, 0x7468 }, /* amd8111 support */
172 MODULE_DEVICE_TABLE(pci, amd76xrom_pci_tbl);
175 static struct pci_driver amd76xrom_driver = {
177 .id_table = amd76xrom_pci_tbl,
178 .probe = amd76xrom_init_one,
179 .remove = amd76xrom_remove_one,
183 int __init init_amd76xrom(void)
185 struct pci_dev *pdev;
186 struct pci_device_id *id;
188 for(id = amd76xrom_pci_tbl; id->vendor; id++) {
189 pdev = pci_find_device(id->vendor, id->device, 0);
195 amd76xrom_map.pdev = pdev;
196 return amd76xrom_init_one(pdev, &amd76xrom_pci_tbl[0]);
200 return pci_module_init(&amd76xrom_driver);
204 static void __exit cleanup_amd76xrom(void)
206 amd76xrom_remove_one(amd76xrom_map.pdev);
209 module_init(init_amd76xrom);
210 module_exit(cleanup_amd76xrom);
212 MODULE_LICENSE("GPL");
213 MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
214 MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD76X southbridge");