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/ddb5476/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. #include <linux/config.h>
  18. #include <linux/pci.h>
  19. #include <linux/kernel.h>
  20. #include <linux/types.h>
  21. #include <asm/addrspace.h>
  22. #include <asm/debug.h>
  23. #include <asm/ddb5xxx/ddb5xxx.h>
  24. /*
  25.  * config_swap structure records what set of pdar/pmr are used
  26.  * to access pci config space.  It also provides a place hold the
  27.  * original values for future restoring.
  28.  */
  29. struct pci_config_swap {
  30. u32  pdar;
  31. u32 pmr;
  32. u32 config_base;
  33. u32 config_size;
  34. u32 pdar_backup;
  35. u32 pmr_backup;
  36. };
  37. /*
  38.  * On DDB5476, we have one set of swap registers
  39.  */
  40. struct pci_config_swap ext_pci_swap = {
  41. DDB_PCIW0,
  42. DDB_PCIINIT0,
  43. DDB_PCI_CONFIG_BASE,
  44. DDB_PCI_CONFIG_SIZE
  45. };
  46. static int pci_config_workaround=1;
  47. /*
  48.  * access config space
  49.  */
  50. static inline u32 ddb_access_config_base(struct pci_config_swap *swap,
  51.  u32 bus,/* 0 means top level bus */
  52.  u32 slot_num)
  53. {
  54. u32 pci_addr = 0;
  55. u32 pciinit_offset = 0;
  56.         u32 virt_addr = swap->config_base;
  57. u32 option;
  58. if (pci_config_workaround) {
  59. if (slot_num == 5) slot_num = 14;
  60. }
  61. else {
  62. if (slot_num == 5) return DDB_BASE + DDB_PCI_BASE;
  63. }
  64. /* minimum pdar (window) size is 2MB */
  65. db_assert(swap->config_size >= (2 << 20));
  66. db_assert(slot_num < (1 << 5));
  67. db_assert(bus < (1 << 8));
  68. /* backup registers */
  69. swap->pdar_backup = ddb_in32(swap->pdar);
  70. swap->pmr_backup = ddb_in32(swap->pmr);
  71. /* set the pdar (pci window) register */
  72. ddb_set_pdar(swap->pdar,
  73.      swap->config_base,
  74.      swap->config_size,
  75.      32, /* 32 bit wide */
  76.      0, /* not on local memory bus */
  77.      0); /* not visible from PCI bus (N/A) */
  78. /*
  79.  * calcuate the absolute pci config addr;
  80.  * according to the spec, we start scanning from adr:11 (0x800)
  81.  */
  82. if (bus == 0) {
  83. /* type 0 config */
  84. pci_addr = 0x00040000 << slot_num;
  85. } else {
  86. /* type 1 config */
  87. pci_addr = 0x00040000 << slot_num;
  88. panic("ddb_access_config_base: we don't support type 1 config Yet");
  89. }
  90. /*
  91.  * if pci_addr is less than pci config window size,  we set
  92.  * pciinit_offset to 0 and adjust the virt_address.
  93.  * Otherwise we will try to adjust pciinit_offset.
  94.  */
  95. if (pci_addr < swap->config_size) {
  96. virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
  97. pciinit_offset = 0;
  98. } else {
  99. db_assert( (pci_addr & (swap->config_size - 1)) == 0);
  100. virt_addr = KSEG1ADDR(swap->config_base);
  101. pciinit_offset = pci_addr;
  102. }
  103. /* set the pmr register */
  104. option = DDB_PCI_ACCESS_32;
  105. if (bus != 0) option |= DDB_PCI_CFGTYPE1;
  106. ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
  107. return virt_addr;
  108. }
  109. static inline void ddb_close_config_base(struct pci_config_swap *swap)
  110. {
  111. ddb_out32(swap->pdar, swap->pdar_backup);
  112. ddb_out32(swap->pmr, swap->pmr_backup);
  113. }
  114. static int read_config_dword(struct pci_config_swap *swap,
  115.      struct pci_dev *dev,
  116.      u32 where,
  117.      u32 *val)
  118. {
  119. u32 bus, slot_num, func_num;
  120. u32 base;
  121. db_assert((where & 3) == 0);
  122. db_assert(where < (1 << 8));
  123. /* check if the bus is top-level */
  124. if (dev->bus->parent != NULL) {
  125. bus = dev->bus->number;
  126. db_assert(bus != 0);
  127. } else {
  128. bus = 0;
  129. }
  130. slot_num = PCI_SLOT(dev->devfn);
  131. func_num = PCI_FUNC(dev->devfn);
  132. base = ddb_access_config_base(swap, bus, slot_num);
  133. *val = *(volatile u32*) (base + (func_num << 8) + where);
  134. ddb_close_config_base(swap);
  135. return PCIBIOS_SUCCESSFUL;
  136. }
  137. static int read_config_word(struct pci_config_swap *swap,
  138.     struct pci_dev *dev,
  139.     u32 where,
  140.     u16 *val)
  141. {
  142.         int status;
  143.         u32 result;
  144. db_assert((where & 1) == 0);
  145.         status = read_config_dword(swap, dev, where & ~3, &result);
  146.         if (where & 2) result >>= 16;
  147.         *val = result & 0xffff;
  148.         return status;
  149. }
  150. static int read_config_byte(struct pci_config_swap *swap,
  151.     struct pci_dev *dev,
  152.     u32 where,
  153.     u8 *val)
  154. {
  155.         int status;
  156.         u32 result;
  157.         status = read_config_dword(swap, dev, where & ~3, &result);
  158.         if (where & 1) result >>= 8;
  159.         if (where & 2) result >>= 16;
  160.         *val = result & 0xff;
  161.         return status;
  162. }
  163. static int write_config_dword(struct pci_config_swap *swap,
  164.       struct pci_dev *dev,
  165.       u32 where,
  166.       u32 val)
  167. {
  168. u32 bus, slot_num, func_num;
  169. u32 base;
  170. db_assert((where & 3) == 0);
  171. db_assert(where < (1 << 8));
  172. /* check if the bus is top-level */
  173. if (dev->bus->parent != NULL) {
  174. bus = dev->bus->number;
  175. db_assert(bus != 0);
  176. } else {
  177. bus = 0;
  178. }
  179. slot_num = PCI_SLOT(dev->devfn);
  180. func_num = PCI_FUNC(dev->devfn);
  181. base = ddb_access_config_base(swap, bus, slot_num);
  182. *(volatile u32*) (base + (func_num << 8) + where) = val;
  183. ddb_close_config_base(swap);
  184. return PCIBIOS_SUCCESSFUL;
  185. }
  186. static int write_config_word(struct pci_config_swap *swap,
  187.      struct pci_dev *dev,
  188.      u32 where,
  189.      u16 val)
  190. {
  191. int status, shift=0;
  192. u32 result;
  193. db_assert((where & 1) == 0);
  194. status = read_config_dword(swap, dev, where & ~3, &result);
  195. if (status != PCIBIOS_SUCCESSFUL) return status;
  196.         if (where & 2)
  197.                 shift += 16;
  198.         result &= ~(0xffff << shift);
  199.         result |= val << shift;
  200.         return write_config_dword(swap, dev, where & ~3, result);
  201. }
  202. static int write_config_byte(struct pci_config_swap *swap,
  203.      struct pci_dev *dev,
  204.      u32 where,
  205.      u8 val)
  206. {
  207. int status, shift=0;
  208. u32 result;
  209. status = read_config_dword(swap, dev, where & ~3, &result);
  210. if (status != PCIBIOS_SUCCESSFUL) return status;
  211.         if (where & 2)
  212.                 shift += 16;
  213.         if (where & 1)
  214.                 shift += 8;
  215.         result &= ~(0xff << shift);
  216.         result |= val << shift;
  217.         return write_config_dword(swap, dev, where & ~3, result);
  218. }
  219. #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) 
  220. static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) 
  221.      return rw##_config_##unitname(pciswap, 
  222.                                    dev, 
  223.                                    where, 
  224.                                    val); 
  225. }
  226. MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
  227. MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
  228. MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
  229. MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
  230. MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
  231. MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
  232. struct pci_ops ddb5476_ext_pci_ops ={
  233. extpci_read_config_byte,
  234. extpci_read_config_word,
  235. extpci_read_config_dword,
  236. extpci_write_config_byte,
  237. extpci_write_config_word,
  238. extpci_write_config_dword
  239. };
  240. #if defined(CONFIG_DEBUG)
  241. void jsun_scan_pci_bus(void)
  242. {
  243. struct pci_bus bus;
  244. struct pci_dev dev;
  245. unsigned int devfn;
  246. int j;
  247. pci_config_workaround = 0;
  248. bus.parent = NULL; /* we scan the top level only */
  249. dev.bus = &bus;
  250. dev.sysdata = NULL;
  251. /* scan ext pci bus and io pci bus*/
  252. for (j=0; j< 1; j++) {
  253. printk(KERN_INFO "scan ddb5476 external PCI bus:n");
  254. bus.ops = &ddb5476_ext_pci_ops;
  255. for (devfn = 0; devfn < 0x100; devfn += 8) {
  256. u32 temp;
  257. u16 temp16;
  258. u8 temp8;
  259. int i;
  260. dev.devfn = devfn;
  261. db_verify(pci_read_config_dword(&dev, 0, &temp),
  262.     == PCIBIOS_SUCCESSFUL);
  263. if (temp == 0xffffffff) continue;
  264. printk(KERN_INFO "slot %d: (addr %d) n", devfn/8,
  265.        11+devfn/8);
  266. /* verify read word and byte */
  267. db_verify(pci_read_config_word(&dev, 2, &temp16),
  268.   == PCIBIOS_SUCCESSFUL);
  269. db_assert(temp16 == (temp >> 16));
  270. db_verify(pci_read_config_byte(&dev, 3, &temp8),
  271.   == PCIBIOS_SUCCESSFUL);
  272. db_assert(temp8 == (temp >> 24));
  273. db_verify(pci_read_config_byte(&dev, 1, &temp8),
  274.   == PCIBIOS_SUCCESSFUL);
  275. db_assert(temp8 == ((temp >> 8) & 0xff));
  276. for (i=0; i < 16; i++) {
  277. if ((i%4) == 0)
  278. printk(KERN_INFO);
  279. db_verify(pci_read_config_dword(&dev, i*4, &temp),
  280.   == PCIBIOS_SUCCESSFUL);
  281. printk("t%08X", temp);
  282. if ((i%4) == 3)
  283. printk("n");
  284. }
  285. }
  286. }
  287. pci_config_workaround = 1;
  288. }
  289. #endif