amd766rom.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * amd766rom.c
  3.  *
  4.  * Normal mappings of chips in physical memory
  5.  * $Id: amd766rom.c,v 1.1 2002/01/10 22:59:13 eric Exp $
  6.  */
  7. #include <linux/module.h>
  8. #include <linux/types.h>
  9. #include <linux/kernel.h>
  10. #include <asm/io.h>
  11. #include <linux/mtd/mtd.h>
  12. #include <linux/mtd/map.h>
  13. #include <linux/config.h>
  14. #include <linux/pci.h>
  15. #include <linux/pci_ids.h>
  16. struct amd766rom_map_info {
  17. struct map_info map;
  18. struct mtd_info *mtd;
  19. unsigned long window_addr;
  20. u32 window_start, window_size;
  21. struct pci_dev *pdev;
  22. };
  23. static __u8 amd766rom_read8(struct map_info *map, unsigned long ofs)
  24. {
  25. return __raw_readb(map->map_priv_1 + ofs);
  26. }
  27. static __u16 amd766rom_read16(struct map_info *map, unsigned long ofs)
  28. {
  29. return __raw_readw(map->map_priv_1 + ofs);
  30. }
  31. static __u32 amd766rom_read32(struct map_info *map, unsigned long ofs)
  32. {
  33. return __raw_readl(map->map_priv_1 + ofs);
  34. }
  35. static void amd766rom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  36. {
  37. memcpy_fromio(to, map->map_priv_1 + from, len);
  38. }
  39. static void amd766rom_write8(struct map_info *map, __u8 d, unsigned long adr)
  40. {
  41. __raw_writeb(d, map->map_priv_1 + adr);
  42. mb();
  43. }
  44. static void amd766rom_write16(struct map_info *map, __u16 d, unsigned long adr)
  45. {
  46. __raw_writew(d, map->map_priv_1 + adr);
  47. mb();
  48. }
  49. static void amd766rom_write32(struct map_info *map, __u32 d, unsigned long adr)
  50. {
  51. __raw_writel(d, map->map_priv_1 + adr);
  52. mb();
  53. }
  54. static void amd766rom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  55. {
  56. memcpy_toio(map->map_priv_1 + to, from, len);
  57. }
  58. static struct amd766rom_map_info amd766rom_map = {
  59. map: {
  60. name: "AMD766 rom",
  61. size: 0,
  62. buswidth: 1,
  63. read8: amd766rom_read8,
  64. read16: amd766rom_read16,
  65. read32: amd766rom_read32,
  66. copy_from: amd766rom_copy_from,
  67. write8: amd766rom_write8,
  68. write16: amd766rom_write16,
  69. write32: amd766rom_write32,
  70. copy_to: amd766rom_copy_to,
  71. /* The standard rom socket is for single power supply chips
  72.  * that don't have an extra vpp.
  73.  */
  74. },
  75. mtd: 0,
  76. window_addr: 0,
  77. };
  78. static int __devinit amd766rom_init_one (struct pci_dev *pdev,
  79. const struct pci_device_id *ent)
  80. {
  81. struct rom_window {
  82. u32 start;
  83. u32 size;
  84. u8 segen_bits;
  85. };
  86. static struct rom_window rom_window[] = {
  87. { 0xffb00000, 5*1024*1024, (1<<7) | (1<<6), },
  88. { 0xffc00000, 4*1024*1024, (1<<7), },
  89. { 0xffff0000, 64*1024,     0 },
  90. { 0         , 0,           0 },
  91. };
  92. static const u32 rom_probe_sizes[] = { 
  93. 5*1024*1024, 4*1024*1024, 2*1024*1024, 1024*1024, 512*1024, 
  94. 256*1024, 128*1024, 64*1024, 0};
  95. static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", 0 };
  96. u8 byte;
  97. struct amd766rom_map_info *info = &amd766rom_map;
  98. struct rom_window *window;
  99. int i;
  100. u32 rom_size;
  101. window = &rom_window[0];
  102. while(window->size) {
  103. if (request_mem_region(window->start, window->size, "amd766rom")) {
  104. break;
  105. }
  106. window++;
  107. }
  108. if (!window->size) {
  109. printk(KERN_ERR "amd766rom: cannot reserve rom window");
  110. goto err_out_none;
  111. }
  112. /* Enable the selected rom window */
  113. pci_read_config_byte(pdev, 0x43, &byte);
  114. pci_write_config_byte(pdev, 0x43, byte | window->segen_bits);
  115. /* Enable writes through the rom window */
  116. pci_read_config_byte(pdev, 0x40, &byte);
  117. pci_write_config_byte(pdev, 0x40, byte | 1);
  118. /* FIXME handle registers 0x80 - 0x8C the bios region locks */
  119. printk(KERN_NOTICE "amd766rom window : %x at %xn", 
  120. window->size, window->start);
  121. /* For write accesses caches are useless */
  122. info->window_addr = (unsigned long)ioremap_nocache(window->start, window->size);
  123. if (!info->window_addr) {
  124. printk(KERN_ERR "Failed to ioremapn");
  125. goto err_out_free_mmio_region;
  126. }
  127. info->mtd = 0;
  128. for(i = 0; (rom_size = rom_probe_sizes[i]); i++) {
  129. char **chip_type;
  130. if (rom_size > window->size) {
  131. continue;
  132. }
  133. info->map.map_priv_1 = 
  134. info->window_addr + window->size - rom_size;
  135. info->map.size = rom_size;
  136. chip_type = rom_probe_types;
  137. for(; !info->mtd && *chip_type; chip_type++) {
  138. info->mtd = do_map_probe(*chip_type, &amd766rom_map.map);
  139. }
  140. if (info->mtd) {
  141. break;
  142. }
  143. }
  144. if (!info->mtd) {
  145. goto err_out_iounmap;
  146. }
  147. printk(KERN_NOTICE "amd766rom chip at offset: %xn",
  148. window->size - rom_size);
  149. info->mtd->module = THIS_MODULE;
  150. add_mtd_device(info->mtd);
  151. info->window_start = window->start;
  152. info->window_size = window->size;
  153. return 0;
  154. err_out_iounmap:
  155. iounmap((void *)(info->window_addr));
  156. err_out_free_mmio_region:
  157. release_mem_region(window->start, window->size);
  158. err_out_none:
  159. return -ENODEV;
  160. }
  161. static void __devexit amd766rom_remove_one (struct pci_dev *pdev)
  162. {
  163. struct amd766rom_map_info *info = &amd766rom_map;
  164. u8 byte;
  165. del_mtd_device(info->mtd);
  166. map_destroy(info->mtd);
  167. info->mtd = 0;
  168. info->map.map_priv_1 = 0;
  169. iounmap((void *)(info->window_addr));
  170. info->window_addr = 0;
  171. /* Disable writes through the rom window */
  172. pci_read_config_byte(pdev, 0x40, &byte);
  173. pci_write_config_byte(pdev, 0x40, byte & ~1);
  174. release_mem_region(info->window_start, info->window_size);
  175. }
  176. static struct pci_device_id amd766rom_pci_tbl[] __devinitdata = {
  177. { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 
  178.   PCI_ANY_ID, PCI_ANY_ID, },
  179. };
  180. MODULE_DEVICE_TABLE(pci, amd766rom_pci_tbl);
  181. #if 0
  182. static struct pci_driver amd766rom_driver = {
  183. name:   "amd766rom",
  184. id_table: amd766rom_pci_tbl,
  185. probe:    amd766rom_init_one,
  186. remove:   amd766rom_remove_one,
  187. };
  188. #endif
  189. int __init init_amd766rom(void)
  190. {
  191. struct pci_dev *pdev;
  192. pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
  193. if (pdev) {
  194. amd766rom_map.pdev = pdev;
  195. return amd766rom_init_one(pdev, &amd766rom_pci_tbl[0]);
  196. }
  197. return -ENXIO;
  198. #if 0
  199. return pci_module_init(&amd766rom_driver);
  200. #endif
  201. }
  202. static void __exit cleanup_amd766rom(void)
  203. {
  204. amd766rom_remove_one(amd766rom_map.pdev);
  205. }
  206. module_init(init_amd766rom);
  207. module_exit(cleanup_amd766rom);
  208. MODULE_LICENSE("GPL");
  209. MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
  210. MODULE_DESCRIPTION("MTD map driver for BIOS chips on the AMD766 southbridge");