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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * This file is subject to the terms and conditions of the GNU General Public
  3.  * License.  See the file "COPYING" in the main directory of this archive
  4.  * for more details.
  5.  *
  6.  * SNI specific PCI support for RM200/RM300.
  7.  *
  8.  * Copyright (C) 1997 - 2000 Ralf Baechle
  9.  */
  10. #include <linux/config.h>
  11. #include <linux/kernel.h>
  12. #include <linux/init.h>
  13. #include <linux/pci.h>
  14. #include <linux/types.h>
  15. #include <asm/byteorder.h>
  16. #include <asm/pci_channel.h>
  17. #include <asm/hp-lj/asic.h>
  18. #ifdef CONFIG_PCI
  19. volatile u32* pci_config_address_reg = (volatile u32*)0xfdead000;
  20. volatile u32* pci_config_data_reg = (volatile u32*)0xfdead000;
  21. #define cfgaddr(dev, where) (((dev->bus->number & 0xff) << 0x10) |  
  22.                              ((dev->devfn & 0xff) << 0x08) |        
  23.                              (where & 0xfc))
  24. /*
  25.  * We can't address 8 and 16 bit words directly.  Instead we have to
  26.  * read/write a 32bit word and mask/modify the data we actually want.
  27.  */
  28. static int pcimt_read_config_byte (struct pci_dev *dev,
  29.                                    int where, unsigned char *val)
  30. {
  31.         *pci_config_address_reg = cfgaddr(dev, where);
  32. *val = (le32_to_cpu(*pci_config_data_reg) >> ((where&3)<<3)) & 0xff;
  33. //printk("pci_read_byte 0x%x == 0x%xn", where, *val);
  34. return PCIBIOS_SUCCESSFUL;
  35. }
  36. static int pcimt_read_config_word (struct pci_dev *dev,
  37.                                    int where, unsigned short *val)
  38. {
  39. if (where & 1)
  40. return PCIBIOS_BAD_REGISTER_NUMBER;
  41. *pci_config_address_reg = cfgaddr(dev, where);
  42. *val = (le32_to_cpu(*pci_config_data_reg) >> ((where&3)<<3)) & 0xffff;
  43. //printk("pci_read_word 0x%x == 0x%xn", where, *val);
  44. return PCIBIOS_SUCCESSFUL;
  45. }
  46. int pcimt_read_config_dword (struct pci_dev *dev,
  47.                                     int where, unsigned int *val)
  48. {
  49. if (where & 3)
  50. return PCIBIOS_BAD_REGISTER_NUMBER;
  51. *pci_config_address_reg = cfgaddr(dev, where);
  52. *val = le32_to_cpu(*pci_config_data_reg);
  53. //printk("pci_read_dword 0x%x == 0x%xn", where, *val);
  54. return PCIBIOS_SUCCESSFUL;
  55. }
  56. static int pcimt_write_config_byte (struct pci_dev *dev,
  57.                                     int where, unsigned char val)
  58. {
  59. *pci_config_address_reg = cfgaddr(dev, where);
  60. *(volatile u8 *)(((int)pci_config_data_reg) + (where & 3)) = val;
  61. //printk("pci_write_byte 0x%x = 0x%xn", where, val);
  62. return PCIBIOS_SUCCESSFUL;
  63. }
  64. static int pcimt_write_config_word (struct pci_dev *dev,
  65.                                     int where, unsigned short val)
  66. {
  67. if (where & 1)
  68. return PCIBIOS_BAD_REGISTER_NUMBER;
  69. *pci_config_address_reg = cfgaddr(dev, where);
  70. *(volatile u16 *)(((int)pci_config_data_reg) + (where & 2)) = 
  71.                   le16_to_cpu(val);
  72. //printk("pci_write_word 0x%x = 0x%xn", where, val);
  73. return PCIBIOS_SUCCESSFUL;
  74. }
  75. int pcimt_write_config_dword (struct pci_dev *dev,
  76.                                      int where, unsigned int val)
  77. {
  78. if (where & 3)
  79. return PCIBIOS_BAD_REGISTER_NUMBER;
  80. *pci_config_address_reg = cfgaddr(dev, where);
  81. *pci_config_data_reg = le32_to_cpu(val);
  82. //printk("pci_write_dword 0x%x = 0x%xn", where, val);
  83. return PCIBIOS_SUCCESSFUL;
  84. }
  85. struct pci_ops hp_pci_ops = {
  86. pcimt_read_config_byte,
  87. pcimt_read_config_word,
  88. pcimt_read_config_dword,
  89. pcimt_write_config_byte,
  90. pcimt_write_config_word,
  91. pcimt_write_config_dword
  92. };
  93. struct pci_channel mips_pci_channels[] = {
  94. { &hp_pci_ops, &ioport_resource, &iomem_resource },
  95. { NULL, NULL, NULL }
  96. };
  97. unsigned __init int pcibios_assign_all_busses(void)
  98. {
  99.         return 1;
  100. }
  101. void __init pcibios_fixup(void)
  102. {
  103. }
  104. void __init pcibios_fixup_irqs(void)
  105. {
  106.    struct pci_dev *dev;
  107.    int slot_num;
  108.    pci_for_each_dev(dev) {
  109.       slot_num = PCI_SLOT(dev->devfn);
  110.       switch(slot_num) {
  111.          case 2: dev->irq = 3;  break;
  112.          case 3: dev->irq = 4;  break;
  113.          case 4: dev->irq = 5;  break;
  114.          default: break;
  115.       }
  116.    }
  117. }
  118. #define IO_MEM_LOGICAL_START   0x3e000000
  119. #define IO_MEM_LOGICAL_END     0x3fefffff
  120. #define IO_PORT_LOGICAL_START  0x3ff00000
  121. #define IO_PORT_LOGICAL_END    0x3fffffff
  122. #define IO_MEM_VIRTUAL_OFFSET  0xb0000000
  123. #define IO_PORT_VIRTUAL_OFFSET 0xb0000000
  124. #define ONE_MEG   (1024 * 1024)
  125. void __init pci_setup(void)
  126. {
  127.    u32 pci_regs_base_offset = 0xfdead000;
  128.    switch(GetAsicId()) {
  129.       case AndrosAsic:   pci_regs_base_offset = 0xbff80000;   break;
  130.       case HarmonyAsic:  pci_regs_base_offset = 0xbff70000;   break;
  131.       default:
  132.          printk("ERROR: PCI does not support %s Asicn", GetAsicName()); 
  133.  while(1);
  134.          break; 
  135.    }
  136.    // set bus stat/command reg
  137.    // REVIST this setting may need vary depending on the hardware
  138.    *((volatile unsigned int*)(pci_regs_base_offset | 0x0004)) =  0x38000007;
  139.    iomem_resource.start =  IO_MEM_LOGICAL_START + IO_MEM_VIRTUAL_OFFSET;
  140.    iomem_resource.end =    IO_MEM_LOGICAL_END + IO_MEM_VIRTUAL_OFFSET;
  141.    ioport_resource.start = IO_PORT_LOGICAL_START + IO_PORT_VIRTUAL_OFFSET;
  142.    ioport_resource.end =   IO_PORT_LOGICAL_END + IO_PORT_VIRTUAL_OFFSET;
  143.    // KLUDGE (mips_io_port_base is screwed up, we've got to work around it here)
  144.    // by letting both low (illegal) and high (legal) addresses appear in pci io space
  145.    ioport_resource.start = 0x0; 
  146.    set_io_port_base(IO_PORT_LOGICAL_START + IO_PORT_VIRTUAL_OFFSET);
  147.    // map the PCI address space
  148.    // global map - all levels & processes can access
  149.    // except that the range is outside user space
  150.    // parameters: lo0, lo1, hi, pagemask
  151.    // lo indicates physical page, hi indicates virtual address
  152.    add_wired_entry((IO_MEM_LOGICAL_START >> 6) | 0x17, 
  153.                    ((IO_MEM_LOGICAL_START + (16 * ONE_MEG)) >> 6) | 0x17,
  154.                    0xee000000, PM_16M);
  155.    // These are used in pci r/w routines so need to preceed bus scan
  156.    pci_config_data_reg = (u32*) (((u32)mips_io_port_base) | 0xcfc);
  157.    pci_config_address_reg = (u32*) (((u32)pci_regs_base_offset) | 0xcf8);
  158. }
  159. void __init pcibios_fixup_resources(struct pci_dev *dev)
  160. {
  161.     int pos;
  162.     int bases;
  163.     printk("adjusting pci device: %sn", dev->name);
  164.  
  165.     switch (dev->hdr_type) {
  166.        case PCI_HEADER_TYPE_NORMAL: bases = 6; break;
  167.        case PCI_HEADER_TYPE_BRIDGE: bases = 2; break;
  168.        case PCI_HEADER_TYPE_CARDBUS: bases = 1; break;
  169.        default: bases = 0; break;
  170.     }
  171.     for (pos=0; pos < bases; pos++) {
  172.        struct resource* res = &dev->resource[pos];
  173.        if (res->start >= IO_MEM_LOGICAL_START && 
  174.            res->end <= IO_MEM_LOGICAL_END) {
  175.               res->start += IO_MEM_VIRTUAL_OFFSET;
  176.               res->end += IO_MEM_VIRTUAL_OFFSET;
  177.        }
  178.        if (res->start >= IO_PORT_LOGICAL_START && 
  179.            res->end <= IO_PORT_LOGICAL_END) {
  180.               res->start += IO_PORT_VIRTUAL_OFFSET;
  181.               res->end += IO_PORT_VIRTUAL_OFFSET;
  182.        }
  183.     }
  184. }
  185. #endif /* CONFIG_PCI */