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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: l440gx.c,v 1.8 2002/01/10 20:27:40 eric Exp $
  3.  *
  4.  * BIOS Flash chip on Intel 440GX board.
  5.  *
  6.  * Bugs this currently does not work under linuxBIOS.
  7.  */
  8. #include <linux/module.h>
  9. #include <linux/pci.h>
  10. #include <linux/kernel.h>
  11. #include <asm/io.h>
  12. #include <linux/mtd/mtd.h>
  13. #include <linux/mtd/map.h>
  14. #include <linux/config.h>
  15. #define PIIXE_IOBASE_RESOURCE 11
  16. #define WINDOW_ADDR 0xfff00000
  17. #define WINDOW_SIZE 0x00100000
  18. #define BUSWIDTH 1
  19. static u32 iobase;
  20. #define IOBASE iobase
  21. #define TRIBUF_PORT (IOBASE+0x37)
  22. #define VPP_PORT (IOBASE+0x28)
  23. static struct mtd_info *mymtd;
  24. __u8 l440gx_read8(struct map_info *map, unsigned long ofs)
  25. {
  26. return __raw_readb(map->map_priv_1 + ofs);
  27. }
  28. __u16 l440gx_read16(struct map_info *map, unsigned long ofs)
  29. {
  30. return __raw_readw(map->map_priv_1 + ofs);
  31. }
  32. __u32 l440gx_read32(struct map_info *map, unsigned long ofs)
  33. {
  34. return __raw_readl(map->map_priv_1 + ofs);
  35. }
  36. void l440gx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  37. {
  38. memcpy_fromio(to, map->map_priv_1 + from, len);
  39. }
  40. void l440gx_write8(struct map_info *map, __u8 d, unsigned long adr)
  41. {
  42. __raw_writeb(d, map->map_priv_1 + adr);
  43. mb();
  44. }
  45. void l440gx_write16(struct map_info *map, __u16 d, unsigned long adr)
  46. {
  47. __raw_writew(d, map->map_priv_1 + adr);
  48. mb();
  49. }
  50. void l440gx_write32(struct map_info *map, __u32 d, unsigned long adr)
  51. {
  52. __raw_writel(d, map->map_priv_1 + adr);
  53. mb();
  54. }
  55. void l440gx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  56. {
  57. memcpy_toio(map->map_priv_1 + to, from, len);
  58. }
  59. /* Is this really the vpp port? */
  60. void l440gx_set_vpp(struct map_info *map, int vpp)
  61. {
  62. unsigned long l;
  63. l = inl(VPP_PORT);
  64. if (vpp) {
  65. l |= 1;
  66. } else {
  67. l &= ~1;
  68. }
  69. outl(l, VPP_PORT);
  70. }
  71. struct map_info l440gx_map = {
  72. name: "L440GX BIOS",
  73. size: WINDOW_SIZE,
  74. buswidth: BUSWIDTH,
  75. read8: l440gx_read8,
  76. read16: l440gx_read16,
  77. read32: l440gx_read32,
  78. copy_from: l440gx_copy_from,
  79. write8: l440gx_write8,
  80. write16: l440gx_write16,
  81. write32: l440gx_write32,
  82. copy_to: l440gx_copy_to,
  83. #if 0
  84. /* FIXME verify that this is the 
  85.  * appripriate code for vpp enable/disable
  86.  */
  87. set_vpp: l440gx_set_vpp
  88. #endif
  89. };
  90. static int __init init_l440gx(void)
  91. {
  92. struct pci_dev *dev, *pm_dev;
  93. struct resource *pm_iobase;
  94. __u16 word;
  95. dev = pci_find_device(PCI_VENDOR_ID_INTEL, 
  96. PCI_DEVICE_ID_INTEL_82371AB_0, NULL);
  97. pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL, 
  98. PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
  99. if (!dev || !pm_dev) {
  100. printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continuen");
  101. return -ENODEV;
  102. }
  103. l440gx_map.map_priv_1 = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
  104. if (!l440gx_map.map_priv_1) {
  105. printk(KERN_WARNING "Failed to ioremap L440GX flash regionn");
  106. return -ENOMEM;
  107. }
  108. printk(KERN_NOTICE "window_addr = 0x%08lxn", (unsigned long)l440gx_map.map_priv_1);
  109. /* Setup the pm iobase resource 
  110.  * This code should move into some kind of generic bridge
  111.  * driver but for the moment I'm content with getting the
  112.  * allocation correct. 
  113.  */
  114. pm_iobase = &pm_dev->resource[PIIXE_IOBASE_RESOURCE];
  115. if (!(pm_iobase->flags & IORESOURCE_IO)) {
  116. pm_iobase->name = "pm iobase";
  117. pm_iobase->start = 0;
  118. pm_iobase->end = 63;
  119. pm_iobase->flags = IORESOURCE_IO;
  120. /* Put the current value in the resource */
  121. pci_read_config_dword(pm_dev, 0x40, &iobase);
  122. iobase &= ~1;
  123. pm_iobase->start += iobase & ~1;
  124. pm_iobase->end += iobase & ~1;
  125. /* Allocate the resource region */
  126. if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) {
  127. printk(KERN_WARNING "Could not allocate pm iobase resourcen");
  128. iounmap((void *)l440gx_map.map_priv_1);
  129. return -ENXIO;
  130. }
  131. }
  132. /* Set the iobase */
  133. iobase = pm_iobase->start;
  134. pci_write_config_dword(pm_dev, 0x40, iobase | 1);
  135. /* Set XBCS# */
  136. pci_read_config_word(dev, 0x4e, &word);
  137. word |= 0x4;
  138.         pci_write_config_word(dev, 0x4e, word);
  139. /* Supply write voltage to the chip */
  140. l440gx_set_vpp(&l440gx_map, 1);
  141. /* Enable the gate on the WE line */
  142. outb(inb(TRIBUF_PORT) & ~1, TRIBUF_PORT);
  143.         printk(KERN_NOTICE "Enabled WE line to L440GX BIOS flash chip.n");
  144. mymtd = do_map_probe("jedec_probe", &l440gx_map);
  145. if (!mymtd) {
  146. printk(KERN_NOTICE "JEDEC probe on BIOS chip failed. Using ROMn");
  147. mymtd = do_map_probe("map_rom", &l440gx_map);
  148. }
  149. if (mymtd) {
  150. mymtd->module = THIS_MODULE;
  151. add_mtd_device(mymtd);
  152. return 0;
  153. }
  154. iounmap((void *)l440gx_map.map_priv_1);
  155. return -ENXIO;
  156. }
  157. static void __exit cleanup_l440gx(void)
  158. {
  159. del_mtd_device(mymtd);
  160. map_destroy(mymtd);
  161. iounmap((void *)l440gx_map.map_priv_1);
  162. }
  163. module_init(init_l440gx);
  164. module_exit(cleanup_l440gx);
  165. MODULE_LICENSE("GPL");
  166. MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
  167. MODULE_DESCRIPTION("MTD map driver for BIOS chips on Intel L440GX motherboards");