pci_ops.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:10k
源码类别:

嵌入式Linux

开发平台:

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/ddb5xxx/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. /* [jsun] hack for testing */
  68. // if (slot_num == 4) slot_num = 0;
  69. /* minimum pdar (window) size is 2MB */
  70. MIPS_ASSERT(swap->config_size >= (2 << 20));
  71. MIPS_ASSERT(slot_num < (1 << 5));
  72. MIPS_ASSERT(bus < (1 << 8));
  73. /* backup registers */
  74. swap->pdar_backup = ddb_in32(swap->pdar);
  75. swap->pmr_backup = ddb_in32(swap->pmr);
  76. /* set the pdar (pci window) register */
  77. ddb_set_pdar(swap->pdar,
  78.      swap->config_base,
  79.      swap->config_size,
  80.      32, /* 32 bit wide */
  81.      0, /* not on local memory bus */
  82.      0); /* not visible from PCI bus (N/A) */
  83. /* 
  84.  * calcuate the absolute pci config addr; 
  85.  * according to the spec, we start scanning from adr:11 (0x800)
  86.  */ 
  87. if (bus == 0) {
  88. /* type 0 config */
  89. pci_addr = 0x800 << slot_num;
  90. } else {
  91. /* type 1 config */
  92. pci_addr = (bus << 16) | (slot_num << 11);
  93. panic("ddb_access_config_base: we don't support type 1 config Yet");
  94. }
  95. /*
  96.  * if pci_addr is less than pci config window size,  we set
  97.  * pciinit_offset to 0 and adjust the virt_address.
  98.  * Otherwise we will try to adjust pciinit_offset.
  99.  */
  100. if (pci_addr < swap->config_size) {
  101. virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
  102. pciinit_offset = 0;
  103. } else {
  104. MIPS_ASSERT( (pci_addr & (swap->config_size - 1)) == 0);
  105. virt_addr = KSEG1ADDR(swap->config_base);
  106. pciinit_offset = pci_addr;
  107. }
  108. /* set the pmr register */
  109. option = DDB_PCI_ACCESS_32;
  110. if (bus != 0) option |= DDB_PCI_CFGTYPE1;
  111. ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
  112. return virt_addr;
  113. }
  114. static inline void ddb_close_config_base(struct pci_config_swap *swap)
  115. {
  116. ddb_out32(swap->pdar, swap->pdar_backup);
  117. ddb_out32(swap->pmr, swap->pmr_backup);
  118. }
  119. static int read_config_dword(struct pci_config_swap *swap,
  120.      struct pci_dev *dev,
  121.      u32 where,
  122.      u32 *val)
  123. {
  124. u32 bus, slot_num, func_num;
  125. u32 base;
  126. MIPS_ASSERT((where & 3) == 0);
  127. MIPS_ASSERT(where < (1 << 8));
  128. /* check if the bus is top-level */
  129. if (dev->bus->parent != NULL) {
  130. bus = dev->bus->number;
  131. MIPS_ASSERT(bus != 0);
  132. } else {
  133. bus = 0;
  134. }
  135. slot_num = PCI_SLOT(dev->devfn);
  136. func_num = PCI_FUNC(dev->devfn);
  137. base = ddb_access_config_base(swap, bus, slot_num);
  138. *val = *(volatile u32*) (base + (func_num << 8) + where);
  139. ddb_close_config_base(swap);
  140. return PCIBIOS_SUCCESSFUL;
  141. }
  142. static int read_config_word(struct pci_config_swap *swap,
  143.     struct pci_dev *dev,
  144.     u32 where,
  145.     u16 *val)
  146. {
  147.         int status;
  148.         u32 result;
  149. MIPS_ASSERT((where & 1) == 0);
  150.         status = read_config_dword(swap, dev, where & ~3, &result);
  151.         if (where & 2) result >>= 16;
  152.         *val = result & 0xffff;
  153.         return status;
  154. }
  155. static int read_config_byte(struct pci_config_swap *swap,
  156.     struct pci_dev *dev,
  157.     u32 where,
  158.     u8 *val)
  159. {
  160.         int status;
  161.         u32 result;
  162.         status = read_config_dword(swap, dev, where & ~3, &result);
  163.         if (where & 1) result >>= 8;
  164.         if (where & 2) result >>= 16;
  165.         *val = result & 0xff;
  166.         return status;
  167. }
  168. static int write_config_dword(struct pci_config_swap *swap,
  169.       struct pci_dev *dev,
  170.       u32 where,
  171.       u32 val)
  172. {
  173. u32 bus, slot_num, func_num;
  174. u32 base;
  175. MIPS_ASSERT((where & 3) == 0);
  176. MIPS_ASSERT(where < (1 << 8));
  177. /* check if the bus is top-level */
  178. if (dev->bus->parent != NULL) {
  179. bus = dev->bus->number;
  180. MIPS_ASSERT(bus != 0);
  181. } else {
  182. bus = 0;
  183. }
  184. slot_num = PCI_SLOT(dev->devfn);
  185. func_num = PCI_FUNC(dev->devfn);
  186. base = ddb_access_config_base(swap, bus, slot_num);
  187. *(volatile u32*) (base + (func_num << 8) + where) = val; 
  188. ddb_close_config_base(swap);
  189. return PCIBIOS_SUCCESSFUL;
  190. }
  191. static int write_config_word(struct pci_config_swap *swap,
  192.      struct pci_dev *dev,
  193.      u32 where,
  194.      u16 val)
  195. {
  196. int status, shift=0;
  197. u32 result;
  198. MIPS_ASSERT((where & 1) == 0);
  199. status = read_config_dword(swap, dev, where & ~3, &result);
  200. if (status != PCIBIOS_SUCCESSFUL) return status;
  201.         if (where & 2)
  202.                 shift += 16;
  203.         result &= ~(0xffff << shift);
  204.         result |= val << shift;
  205.         return write_config_dword(swap, dev, where & ~3, result);
  206. }
  207. static int write_config_byte(struct pci_config_swap *swap,
  208.      struct pci_dev *dev,
  209.      u32 where,
  210.      u8 val)
  211. {
  212. int status, shift=0;
  213. u32 result;
  214. status = read_config_dword(swap, dev, where & ~3, &result);
  215. if (status != PCIBIOS_SUCCESSFUL) return status;
  216.         if (where & 2)
  217.                 shift += 16;
  218.         if (where & 1)
  219.                 shift += 8;
  220.         result &= ~(0xff << shift);
  221.         result |= val << shift;
  222.         return write_config_dword(swap, dev, where & ~3, result);
  223. }
  224. #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) 
  225. static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) 
  226.      return rw##_config_##unitname(pciswap, 
  227.                                    dev, 
  228.                                    where, 
  229.                                    val); 
  230. }
  231. MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
  232. MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
  233. MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
  234. MAKE_PCI_OPS(iopci, read, byte, u8 *, &io_pci_swap)
  235. MAKE_PCI_OPS(iopci, read, word, u16 *, &io_pci_swap)
  236. MAKE_PCI_OPS(iopci, read, dword, u32 *, &io_pci_swap)
  237. MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
  238. MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
  239. MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
  240. MAKE_PCI_OPS(iopci, write, byte, u8, &io_pci_swap)
  241. MAKE_PCI_OPS(iopci, write, word, u16, &io_pci_swap)
  242. MAKE_PCI_OPS(iopci, write, dword, u32, &io_pci_swap)
  243. struct pci_ops ddb5477_ext_pci_ops ={
  244. extpci_read_config_byte,
  245. extpci_read_config_word,
  246. extpci_read_config_dword,
  247. extpci_write_config_byte,
  248. extpci_write_config_word,
  249. extpci_write_config_dword
  250. };
  251. struct pci_ops ddb5477_io_pci_ops ={
  252. iopci_read_config_byte,
  253. iopci_read_config_word,
  254. iopci_read_config_dword,
  255. iopci_write_config_byte,
  256. iopci_write_config_word,
  257. iopci_write_config_dword
  258. };
  259. #if defined(CONFIG_LL_DEBUG)
  260. void jsun_scan_pci_bus(void)
  261. {
  262. struct pci_bus bus;
  263. struct pci_dev dev;
  264. unsigned int devfn;
  265. int j;
  266. bus.parent = NULL; /* we scan the top level only */
  267. dev.bus = &bus;
  268. dev.sysdata = NULL;
  269. /* scan ext pci bus and io pci bus*/
  270. for (j=0; j< 2; j++) {
  271. if (j ==  0) {
  272. printk("scan ddb5477 external PCI bus:n");
  273. bus.ops = &ddb5477_ext_pci_ops;
  274. } else {
  275. printk("scan ddb5477 IO PCI bus:n");
  276. bus.ops = &ddb5477_io_pci_ops;
  277. }
  278. for (devfn = 0; devfn < 0x100; devfn += 8) {
  279. u32 temp;
  280. u16 temp16;
  281. u8 temp8;
  282. int i;
  283. dev.devfn = devfn;
  284. MIPS_VERIFY(pci_read_config_dword(&dev, 0, &temp),
  285.     == PCIBIOS_SUCCESSFUL);
  286. if (temp == 0xffffffff) continue;
  287. printk("slot %d: (addr %d) n", devfn/8, 11+devfn/8);
  288. /* verify read word and byte */
  289. MIPS_VERIFY(pci_read_config_word(&dev, 2, &temp16),
  290.     == PCIBIOS_SUCCESSFUL);
  291. MIPS_ASSERT(temp16 == (temp >> 16));
  292. MIPS_VERIFY(pci_read_config_byte(&dev, 3, &temp8),
  293.     == PCIBIOS_SUCCESSFUL);
  294. MIPS_ASSERT(temp8 == (temp >> 24));
  295. MIPS_VERIFY(pci_read_config_byte(&dev, 1, &temp8),
  296.     == PCIBIOS_SUCCESSFUL);
  297. MIPS_ASSERT(temp8 == ((temp >> 8) & 0xff));
  298. for (i=0; i < 16; i++) {
  299. MIPS_VERIFY(pci_read_config_dword(&dev, i*4, &temp),
  300.     == PCIBIOS_SUCCESSFUL);
  301. printk("t%08X", temp);
  302. if ((i%4) == 3) printk("n");
  303. }
  304. }
  305. }
  306. }
  307. static void jsun_hardcode_pci_resources_eepro(void)
  308. {
  309. struct pci_bus bus;
  310. struct pci_dev dev;
  311. u32 temp;
  312. bus.parent = NULL; /* we scan the top level only */
  313. bus.ops = &ddb5477_ext_pci_ops;
  314. dev.bus = &bus;
  315. dev.sysdata = NULL;
  316. /* for slot 5 (ext pci 1) eepro card */
  317. dev.devfn = 5*8;
  318. pci_read_config_dword(&dev, 0, &temp);
  319. MIPS_ASSERT(temp == 0x12298086);
  320. pci_write_config_dword(&dev, PCI_BASE_ADDRESS_0, DDB_PCI0_MEM_BASE);
  321. pci_write_config_dword(&dev, PCI_BASE_ADDRESS_1, 0);
  322. pci_write_config_dword(&dev, PCI_BASE_ADDRESS_2, DDB_PCI0_MEM_BASE+0x100000);
  323. pci_write_config_dword(&dev, PCI_INTERRUPT_LINE, 17);
  324. }
  325. static void jsun_hardcode_pci_resources_onboard_tulip(void)
  326. {
  327. struct pci_bus bus;
  328. struct pci_dev dev;
  329. u32 temp;
  330. bus.parent = NULL; /* we scan the top level only */
  331. bus.ops = &ddb5477_ext_pci_ops;
  332. dev.bus = &bus;
  333. dev.sysdata = NULL;
  334. /* for slot 4 on board ether chip */
  335. dev.devfn = 4*8;
  336. pci_read_config_dword(&dev, 0, &temp);
  337. MIPS_ASSERT(temp == 0x00191011);
  338. pci_write_config_dword(&dev, PCI_BASE_ADDRESS_0, 0x1000);
  339. pci_write_config_dword(&dev, PCI_BASE_ADDRESS_1, DDB_PCI0_MEM_BASE);
  340. pci_write_config_dword(&dev, PCI_INTERRUPT_LINE, 16);
  341. }
  342. static void jsun_hardcode_pci_resources(void)
  343. {
  344. jsun_hardcode_pci_resources_onboard_tulip();
  345. }
  346. void jsun_assign_pci_resource(void)
  347. {
  348. jsun_hardcode_pci_resources();
  349. }
  350. #endif