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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /***********************************************************************
  2.  * Copyright 2001 MontaVista Software Inc.
  3.  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  4.  *
  5.  * arch/mips/ddb5xxx/ddb5477/pci_ops.c
  6.  *     Define the pci_ops for DB5477.
  7.  *
  8.  * Much of the code is derived from the original DDB5074 port by
  9.  * Geert Uytterhoeven <geert@sonycom.com>
  10.  *
  11.  * This program is free software; you can redistribute  it and/or modify it
  12.  * under  the terms of  the GNU General  Public License as published by the
  13.  * Free Software Foundation;  either version 2 of the  License, or (at your
  14.  * option) any later version.
  15.  ***********************************************************************
  16.  */
  17. /*
  18.  * DDB5477 has two PCI channels, external PCI and IOPIC (internal)
  19.  * Therefore we provide two sets of pci_ops.
  20.  */
  21. #include <linux/config.h>
  22. #include <linux/pci.h>
  23. #include <linux/kernel.h>
  24. #include <linux/types.h>
  25. #include <asm/addrspace.h>
  26. #include <asm/debug.h>
  27. #include <asm/ddb5xxx/ddb5xxx.h>
  28. /*
  29.  * config_swap structure records what set of pdar/pmr are used
  30.  * to access pci config space.  It also provides a place hold the
  31.  * original values for future restoring.
  32.  */
  33. struct pci_config_swap {
  34. u32  pdar;
  35. u32 pmr;
  36. u32 config_base;
  37. u32 config_size;
  38. u32 pdar_backup;
  39. u32 pmr_backup;
  40. };
  41. /*
  42.  * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI.
  43.  */
  44. struct pci_config_swap ext_pci_swap = {
  45. DDB_PCIW0,
  46. DDB_PCIINIT00,
  47. DDB_PCI0_CONFIG_BASE,
  48. DDB_PCI0_CONFIG_SIZE
  49. };
  50. struct pci_config_swap io_pci_swap = {
  51. DDB_IOPCIW0,
  52. DDB_PCIINIT01,
  53. DDB_PCI1_CONFIG_BASE,
  54. DDB_PCI1_CONFIG_SIZE
  55. };
  56. /*
  57.  * access config space
  58.  */
  59. static inline u32 ddb_access_config_base(struct pci_config_swap *swap,
  60.  u32 bus,/* 0 means top level bus */
  61.  u32 slot_num)
  62. {
  63. u32 pci_addr = 0;
  64. u32 pciinit_offset = 0;
  65.         u32 virt_addr = swap->config_base;
  66. u32 option;
  67. /* minimum pdar (window) size is 2MB */
  68. db_assert(swap->config_size >= (2 << 20));
  69. db_assert(slot_num < (1 << 5));
  70. db_assert(bus < (1 << 8));
  71. /* backup registers */
  72. swap->pdar_backup = ddb_in32(swap->pdar);
  73. swap->pmr_backup = ddb_in32(swap->pmr);
  74. /* set the pdar (pci window) register */
  75. ddb_set_pdar(swap->pdar,
  76.      swap->config_base,
  77.      swap->config_size,
  78.      32, /* 32 bit wide */
  79.      0, /* not on local memory bus */
  80.      0); /* not visible from PCI bus (N/A) */
  81. /*
  82.  * calcuate the absolute pci config addr;
  83.  * according to the spec, we start scanning from adr:11 (0x800)
  84.  */
  85. if (bus == 0) {
  86. /* type 0 config */
  87. pci_addr = 0x800 << slot_num;
  88. } else {
  89. /* type 1 config */
  90. pci_addr = (bus << 16) | (slot_num << 11);
  91. }
  92. /*
  93.  * if pci_addr is less than pci config window size,  we set
  94.  * pciinit_offset to 0 and adjust the virt_address.
  95.  * Otherwise we will try to adjust pciinit_offset.
  96.  */
  97. if (pci_addr < swap->config_size) {
  98. virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
  99. pciinit_offset = 0;
  100. } else {
  101. db_assert( (pci_addr & (swap->config_size - 1)) == 0);
  102. virt_addr = KSEG1ADDR(swap->config_base);
  103. pciinit_offset = pci_addr;
  104. }
  105. /* set the pmr register */
  106. option = DDB_PCI_ACCESS_32;
  107. if (bus != 0) option |= DDB_PCI_CFGTYPE1;
  108. ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
  109. return virt_addr;
  110. }
  111. static inline void ddb_close_config_base(struct pci_config_swap *swap)
  112. {
  113. ddb_out32(swap->pdar, swap->pdar_backup);
  114. ddb_out32(swap->pmr, swap->pmr_backup);
  115. }
  116. static int read_config_dword(struct pci_config_swap *swap,
  117.      struct pci_dev *dev,
  118.      u32 where,
  119.      u32 *val)
  120. {
  121. u32 bus, slot_num, func_num;
  122. u32 base;
  123. db_assert((where & 3) == 0);
  124. db_assert(where < (1 << 8));
  125. /* check if the bus is top-level */
  126. if (dev->bus->parent != NULL) {
  127. bus = dev->bus->number;
  128. db_assert(bus != 0);
  129. } else {
  130. bus = 0;
  131. }
  132. slot_num = PCI_SLOT(dev->devfn);
  133. func_num = PCI_FUNC(dev->devfn);
  134. base = ddb_access_config_base(swap, bus, slot_num);
  135. *val = *(volatile u32*) (base + (func_num << 8) + where);
  136. ddb_close_config_base(swap);
  137. return PCIBIOS_SUCCESSFUL;
  138. }
  139. static int read_config_word(struct pci_config_swap *swap,
  140.     struct pci_dev *dev,
  141.     u32 where,
  142.     u16 *val)
  143. {
  144.         int status;
  145.         u32 result;
  146. db_assert((where & 1) == 0);
  147.         status = read_config_dword(swap, dev, where & ~3, &result);
  148.         if (where & 2) result >>= 16;
  149.         *val = result & 0xffff;
  150.         return status;
  151. }
  152. static int read_config_byte(struct pci_config_swap *swap,
  153.     struct pci_dev *dev,
  154.     u32 where,
  155.     u8 *val)
  156. {
  157.         int status;
  158.         u32 result;
  159.         status = read_config_dword(swap, dev, where & ~3, &result);
  160.         if (where & 1) result >>= 8;
  161.         if (where & 2) result >>= 16;
  162.         *val = result & 0xff;
  163.         return status;
  164. }
  165. static int write_config_dword(struct pci_config_swap *swap,
  166.       struct pci_dev *dev,
  167.       u32 where,
  168.       u32 val)
  169. {
  170. u32 bus, slot_num, func_num;
  171. u32 base;
  172. db_assert((where & 3) == 0);
  173. db_assert(where < (1 << 8));
  174. /* check if the bus is top-level */
  175. if (dev->bus->parent != NULL) {
  176. bus = dev->bus->number;
  177. db_assert(bus != 0);
  178. } else {
  179. bus = 0;
  180. }
  181. slot_num = PCI_SLOT(dev->devfn);
  182. func_num = PCI_FUNC(dev->devfn);
  183. base = ddb_access_config_base(swap, bus, slot_num);
  184. *(volatile u32*) (base + (func_num << 8) + where) = val;
  185. ddb_close_config_base(swap);
  186. return PCIBIOS_SUCCESSFUL;
  187. }
  188. static int write_config_word(struct pci_config_swap *swap,
  189.      struct pci_dev *dev,
  190.      u32 where,
  191.      u16 val)
  192. {
  193. int status, shift=0;
  194. u32 result;
  195. db_assert((where & 1) == 0);
  196. status = read_config_dword(swap, dev, where & ~3, &result);
  197. if (status != PCIBIOS_SUCCESSFUL) return status;
  198.         if (where & 2)
  199.                 shift += 16;
  200.         result &= ~(0xffff << shift);
  201.         result |= val << shift;
  202.         return write_config_dword(swap, dev, where & ~3, result);
  203. }
  204. static int write_config_byte(struct pci_config_swap *swap,
  205.      struct pci_dev *dev,
  206.      u32 where,
  207.      u8 val)
  208. {
  209. int status, shift=0;
  210. u32 result;
  211. status = read_config_dword(swap, dev, where & ~3, &result);
  212. if (status != PCIBIOS_SUCCESSFUL) return status;
  213.         if (where & 2)
  214.                 shift += 16;
  215.         if (where & 1)
  216.                 shift += 8;
  217.         result &= ~(0xff << shift);
  218.         result |= val << shift;
  219.         return write_config_dword(swap, dev, where & ~3, result);
  220. }
  221. #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) 
  222. static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) 
  223.      return rw##_config_##unitname(pciswap, 
  224.                                    dev, 
  225.                                    where, 
  226.                                    val); 
  227. }
  228. MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
  229. MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
  230. MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
  231. MAKE_PCI_OPS(iopci, read, byte, u8 *, &io_pci_swap)
  232. MAKE_PCI_OPS(iopci, read, word, u16 *, &io_pci_swap)
  233. MAKE_PCI_OPS(iopci, read, dword, u32 *, &io_pci_swap)
  234. MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
  235. MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
  236. MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
  237. MAKE_PCI_OPS(iopci, write, byte, u8, &io_pci_swap)
  238. MAKE_PCI_OPS(iopci, write, word, u16, &io_pci_swap)
  239. MAKE_PCI_OPS(iopci, write, dword, u32, &io_pci_swap)
  240. struct pci_ops ddb5477_ext_pci_ops ={
  241. extpci_read_config_byte,
  242. extpci_read_config_word,
  243. extpci_read_config_dword,
  244. extpci_write_config_byte,
  245. extpci_write_config_word,
  246. extpci_write_config_dword
  247. };
  248. struct pci_ops ddb5477_io_pci_ops ={
  249. iopci_read_config_byte,
  250. iopci_read_config_word,
  251. iopci_read_config_dword,
  252. iopci_write_config_byte,
  253. iopci_write_config_word,
  254. iopci_write_config_dword
  255. };