4 * Normal mappings of chips in physical memory
5 * $Id: amd766rom.c,v 1.1 2002/01/10 22:59:13 eric Exp $
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
12 #include <linux/mtd/mtd.h>
13 #include <linux/mtd/map.h>
14 #include <linux/config.h>
15 #include <linux/pci.h>
16 #include <linux/pci_ids.h>
19 struct amd766rom_map_info {
22 unsigned long window_addr;
23 u32 window_start, window_size;
27 static __u8 amd766rom_read8(struct map_info *map, unsigned long ofs)
29 return __raw_readb(map->map_priv_1 + ofs);
32 static __u16 amd766rom_read16(struct map_info *map, unsigned long ofs)
34 return __raw_readw(map->map_priv_1 + ofs);
37 static __u32 amd766rom_read32(struct map_info *map, unsigned long ofs)
39 return __raw_readl(map->map_priv_1 + ofs);
42 static void amd766rom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
44 memcpy_fromio(to, map->map_priv_1 + from, len);
47 static void amd766rom_write8(struct map_info *map, __u8 d, unsigned long adr)
49 __raw_writeb(d, map->map_priv_1 + adr);
53 static void amd766rom_write16(struct map_info *map, __u16 d, unsigned long adr)
55 __raw_writew(d, map->map_priv_1 + adr);
59 static void amd766rom_write32(struct map_info *map, __u32 d, unsigned long adr)
61 __raw_writel(d, map->map_priv_1 + adr);
65 static void amd766rom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
67 memcpy_toio(map->map_priv_1 + to, from, len);
70 static struct amd766rom_map_info amd766rom_map = {
75 read8: amd766rom_read8,
76 read16: amd766rom_read16,
77 read32: amd766rom_read32,
78 copy_from: amd766rom_copy_from,
79 write8: amd766rom_write8,
80 write16: amd766rom_write16,
81 write32: amd766rom_write32,
82 copy_to: amd766rom_copy_to,
83 /* The standard rom socket is for single power supply chips
84 * that don't have an extra vpp.
91 static int __devinit amd766rom_init_one (struct pci_dev *pdev,
92 const struct pci_device_id *ent)
99 static struct rom_window rom_window[] = {
100 { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), },
101 { 0xffc00000, 4*1024*1024, (1<<7), },
102 { 0xffff0000, 64*1024, 0 },
105 static const u32 rom_probe_sizes[] = {
106 5*1024*1024, 4*1024*1024, 2*1024*1024, 1024*1024, 512*1024,
107 256*1024, 128*1024, 64*1024, 0};
108 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", 0 };
110 struct amd766rom_map_info *info = &amd766rom_map;
111 struct rom_window *window;
115 window = &rom_window[0];
116 while(window->size) {
117 if (request_mem_region(window->start, window->size, "amd766rom")) {
123 printk(KERN_ERR "amd766rom: cannot reserve rom window");
127 /* Enable the selected rom window */
128 pci_read_config_byte(pdev, 0x43, &byte);
129 pci_write_config_byte(pdev, 0x43, byte | window->segen_bits);
131 /* Enable writes through the rom window */
132 pci_read_config_byte(pdev, 0x40, &byte);
133 pci_write_config_byte(pdev, 0x40, byte | 1);
135 /* FIXME handle registers 0x80 - 0x8C the bios region locks */
137 printk(KERN_NOTICE "amd766rom window : %x at %x\n",
138 window->size, window->start);
139 /* For write accesses caches are useless */
140 info->window_addr = (unsigned long)ioremap_nocache(window->start, window->size);
142 if (!info->window_addr) {
143 printk(KERN_ERR "Failed to ioremap\n");
144 goto err_out_free_mmio_region;
147 for(i = 0; (rom_size = rom_probe_sizes[i]); i++) {
149 if (rom_size > window->size) {
152 info->map.map_priv_1 =
153 info->window_addr + window->size - rom_size;
154 info->map.size = rom_size;
155 chip_type = rom_probe_types;
156 for(; !info->mtd && *chip_type; chip_type++) {
157 info->mtd = do_map_probe(*chip_type, &amd766rom_map.map);
164 goto err_out_iounmap;
166 printk(KERN_NOTICE "amd766rom chip at offset: %x\n",
167 window->size - rom_size);
169 info->mtd->module = THIS_MODULE;
170 add_mtd_device(info->mtd);
171 info->window_start = window->start;
172 info->window_size = window->size;
176 iounmap((void *)(info->window_addr));
177 err_out_free_mmio_region:
178 release_mem_region(window->start, window->size);
184 static void __devexit amd766rom_remove_one (struct pci_dev *pdev)
186 struct amd766rom_map_info *info = &amd766rom_map;
189 del_mtd_device(info->mtd);
190 map_destroy(info->mtd);
192 info->map.map_priv_1 = 0;
194 iounmap((void *)(info->window_addr));
195 info->window_addr = 0;
197 /* Disable writes through the rom window */
198 pci_read_config_byte(pdev, 0x40, &byte);
199 pci_write_config_byte(pdev, 0x40, byte & ~1);
201 release_mem_region(info->window_start, info->window_size);
204 static struct pci_device_id amd766rom_pci_tbl[] __devinitdata = {
205 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,
206 PCI_ANY_ID, PCI_ANY_ID, },
209 MODULE_DEVICE_TABLE(pci, amd766rom_pci_tbl);
212 static struct pci_driver amd766rom_driver = {
214 id_table: amd766rom_pci_tbl,
215 probe: amd766rom_init_one,
216 remove: amd766rom_remove_one,
220 int __init init_amd766rom(void)
222 struct pci_dev *pdev;
223 pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
225 amd766rom_map.pdev = pdev;
226 return amd766rom_init_one(pdev, &amd766rom_pci_tbl[0]);
230 return pci_module_init(&amd766rom_driver);
234 static void __exit cleanup_amd766rom(void)
236 amd766rom_remove_one(amd766rom_map.pdev);
239 module_init(init_amd766rom);
240 module_exit(cleanup_amd766rom);
242 MODULE_LICENSE("GPL");
243 MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
244 MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD766 southbridge");