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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
  3.  *
  4.  * May be copied or modified under the terms of the GNU General Public
  5.  * License.  See linux/COPYING for more information.                            
  6.  *
  7.  * Support functions for the ST40 PCI hardware.
  8.  */
  9. #include <linux/config.h>
  10. #include <linux/kernel.h>
  11. #include <linux/smp.h>
  12. #include <linux/smp_lock.h>
  13. #include <linux/init.h>
  14. #include <linux/errno.h>
  15. #include <linux/pci.h>
  16. #include <linux/delay.h>
  17. #include <linux/types.h>
  18. #include <asm/pci.h>
  19. #include <linux/irq.h>
  20. #include "pci_st40.h"
  21. /* This is in P2 of course */
  22. #define ST40PCI_BASE_ADDRESS     (0xb0000000)
  23. #define ST40PCI_MEM_ADDRESS      (ST40PCI_BASE_ADDRESS+0x0)
  24. #define ST40PCI_IO_ADDRESS       (ST40PCI_BASE_ADDRESS+0x06000000)
  25. #define ST40PCI_REG_ADDRESS      (ST40PCI_BASE_ADDRESS+0x07000000)
  26. #define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x))
  27. #define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg))
  28. #define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg))
  29. #define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg))
  30. #define ST40PCI_READ(reg) readl(ST40PCI_REG(reg))
  31. #define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg))
  32. #define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg))
  33. #define ST40PCI_SERR_IRQ        64
  34. #define ST40PCI_SERR_INT_GROUP  0
  35. #define ST40PCI_SERR_INT_POS    0
  36. #define ST40PCI_SERR_INT_PRI    15
  37. #define ST40PCI_ERR_IRQ        65
  38. #define ST40PCI_ERR_INT_GROUP   1
  39. #define ST40PCI_ERR_INT_POS     1
  40. #define ST40PCI_ERR_INT_PRI     14
  41. /* Macros to extract PLL params */
  42. #define PLL_MDIV(reg)  ( ((unsigned)reg) & 0xff )
  43. #define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff )
  44. #define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 )
  45. #define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff )
  46. /* Build up the appropriate settings */
  47. #define PLL_SET(mdiv,ndiv,pdiv,setup) 
  48. ( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19))
  49. #define PLLPCICR (0xbb040000+0x10)
  50. #define PLLPCICR_POWERON (1<<28)
  51. #define PLLPCICR_OUT_EN (1<<29)
  52. #define PLLPCICR_LOCKSELECT (1<<30)
  53. #define PLLPCICR_LOCK (1<<31)
  54. #define PLL_25MHZ 0x793c8512
  55. #define PLL_33MHZ PLL_SET(18,88,3,295)
  56. static __init void SetPCIPLL(void)
  57. {
  58. /* Stop the PLL */
  59. writel(0, PLLPCICR);
  60. /* Always run at 33Mhz. The PCI clock is totally async 
  61.  * to the rest of the system
  62.  */
  63. writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR);
  64. printk("ST40PCI: Waiting for PCI PLL to lockn");
  65. while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0);
  66. writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR);
  67. }
  68. static void st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
  69. {
  70. unsigned pci_int, pci_air, pci_cir, pci_aint;
  71. pci_int = ST40PCI_READ(INT);
  72. pci_cir = ST40PCI_READ(CIR);
  73. pci_air = ST40PCI_READ(AIR);
  74. if (pci_int) {
  75. printk("PCI INTERRUPT!n");
  76. printk("PCI INT -> 0x%xn", pci_int & 0xffff);
  77. printk("PCI AIR -> 0x%xn", pci_air);
  78. printk("PCI CIR -> 0x%xn", pci_cir);
  79. ST40PCI_WRITE(INT, ~0);
  80. }
  81. pci_aint = ST40PCI_READ(AINT);
  82. if (pci_aint) {
  83. printk("PCI ARB INTERRUPT!n");
  84. printk("PCI AINT -> 0x%xn", pci_aint);
  85. printk("PCI AIR -> 0x%xn", pci_air);
  86. printk("PCI CIR -> 0x%xn", pci_cir);
  87. ST40PCI_WRITE(AINT, ~0);
  88. }
  89. }
  90. /* Rounds a number UP to the nearest power of two. Used for
  91.  * sizing the PCI window.
  92.  */
  93. static u32 __init r2p2(u32 num)
  94. {
  95. int i = 31;
  96. u32 tmp = num;
  97. if (num == 0)
  98. return 0;
  99. do {
  100. if (tmp & (1 << 31))
  101. break;
  102. i--;
  103. tmp <<= 1;
  104. } while (i >= 0);
  105. tmp = 1 << i;
  106. /* If the original number isn't a power of 2, round it up */
  107. if (tmp != num)
  108. tmp <<= 1;
  109. return tmp;
  110. }
  111. static void __init pci_fixup_ide_bases(struct pci_dev *d)
  112. {
  113. int i;
  114. /*
  115.  * PCI IDE controllers use non-standard I/O port decoding, respect it.
  116.  */
  117. if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
  118. return;
  119. printk("PCI: IDE base address fixup for %sn", d->slot_name);
  120. for(i=0; i<4; i++) {
  121. struct resource *r = &d->resource[i];
  122. if ((r->start & ~0x80) == 0x374) {
  123. r->start |= 2;
  124. r->end = r->start;
  125. }
  126. }
  127. }
  128. /* Add future fixups here... */
  129. struct pci_fixup pcibios_fixups[] = {
  130. { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases },
  131. { 0 }
  132. };
  133. int __init st40pci_init(unsigned memStart, unsigned memSize)
  134. {
  135. u32 lsr0;
  136. SetPCIPLL();
  137. /* Initialises the ST40 pci subsystem, performing a reset, then programming
  138.  * up the address space decoders appropriately
  139.  */
  140. /* Should reset core here as well methink */
  141. ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET);
  142. /* Loop while core resets */
  143. while (ST40PCI_READ(CR) & CR_SOFT_RESET);
  144. /* Now, lets reset all the cards on the bus with extreme prejudice */
  145. ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL);
  146. udelay(250);
  147. /* Set bus active, take it out of reset */
  148. ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE);
  149. /* The PCI spec says that no access must be made to the bus until 1 second
  150.  * after reset. This seem ludicrously long, but some delay is needed here
  151.  */
  152. mdelay(1000);
  153. /* Switch off interrupts */
  154. ST40PCI_WRITE(INTM, 0);
  155. ST40PCI_WRITE(AINT, 0);
  156. /* Allow it to be a master */
  157. ST40PCI_WRITE_SHORT(CSR_CMD,
  158.     PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
  159.     PCI_COMMAND_IO);
  160. /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000
  161.  * on the PCI bus. This allows a nice 1-1 bus to phys mapping.
  162.  */
  163. ST40PCI_WRITE(MBR, 0x10000000);
  164. /* Always set the max size 128M (actually, it is only 96MB wide) */
  165. ST40PCI_WRITE(MBMR, 0x07ff0000);
  166. /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to 
  167.  * allow cards that have legacy io such as vga to function correctly. This gives a 
  168.  * maximum of 64K of io/space as only the bottom 16 bits of the address are copied 
  169.  * over to the bus  when the transaction is made. 64K of io space is more than enough
  170.  */
  171. ST40PCI_WRITE(IOBR, 0x0);
  172. /* Set up the 64K window */
  173. ST40PCI_WRITE(IOBMR, 0x0);
  174. /* Now we set up the mbars so the PCI bus can see the memory of the machine */
  175. if (memSize < (64 * 1024)) {
  176. printk("Ridiculous memory size of 0x%x?n",memSize);
  177. return 0;
  178. }
  179. lsr0 =
  180.     (memSize >
  181.      (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) -
  182.    0x10000) | 0x1);
  183. ST40PCI_WRITE(LSR0, lsr0);
  184. ST40PCI_WRITE(CSR_MBAR0, memStart);
  185. ST40PCI_WRITE(LAR0, memStart);
  186. /* Maximise timeout values */
  187. ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff);
  188. ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff);
  189. ST40PCI_WRITE_BYTE(CSR_MIT, 0xff);
  190. /* Install the pci interrupt handlers */
  191. make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0,
  192.        ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS,
  193.        ST40PCI_SERR_INT_PRI);
  194. make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP,
  195.        ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI);
  196. return 1;
  197. }
  198. char * __init pcibios_setup(char *str)
  199. {
  200. return str;
  201. }
  202. #define SET_CONFIG_BITS(bus,devfn,where)
  203.   (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
  204. #define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
  205. static int CheckForMasterAbort(void)
  206. {
  207. if (ST40PCI_READ(INT) & INT_MADIM) {
  208. /* Should we clear config space version as well ??? */
  209. ST40PCI_WRITE(INT, INT_MADIM);
  210. ST40PCI_WRITE_SHORT(CSR_STATUS, 0);
  211. return 1;
  212. }
  213. return 0;
  214. }
  215. /* Write to config register */
  216. static int st40pci_read_config_byte(struct pci_dev *dev, int where,
  217.     u8 * val)
  218. {
  219. ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
  220. *val = ST40PCI_READ_BYTE(PDR + (where & 3));
  221. if (CheckForMasterAbort())
  222. *val = 0xff;
  223. return PCIBIOS_SUCCESSFUL;
  224. }
  225. static int st40pci_read_config_word(struct pci_dev *dev, int where,
  226.     u16 * val)
  227. {
  228. ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
  229. *val = ST40PCI_READ_SHORT(PDR + (where & 2));
  230. if (CheckForMasterAbort())
  231. *val = 0xffff;
  232. return PCIBIOS_SUCCESSFUL;
  233. }
  234. static int st40pci_read_config_dword(struct pci_dev *dev, int where,
  235.      u32 * val)
  236. {
  237. ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
  238. *val = ST40PCI_READ(PDR);
  239. if (CheckForMasterAbort())
  240. *val = 0xffffffff;
  241. return PCIBIOS_SUCCESSFUL;
  242. }
  243. static int st40pci_write_config_byte(struct pci_dev *dev, int where,
  244.      u8 val)
  245. {
  246. ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
  247. ST40PCI_WRITE_BYTE(PDR + (where & 3), val);
  248. CheckForMasterAbort();
  249. return PCIBIOS_SUCCESSFUL;
  250. }
  251. static int st40pci_write_config_word(struct pci_dev *dev, int where,
  252.      u16 val)
  253. {
  254. ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
  255. ST40PCI_WRITE_SHORT(PDR + (where & 2), val);
  256. CheckForMasterAbort();
  257. return PCIBIOS_SUCCESSFUL;
  258. }
  259. static int st40pci_write_config_dword(struct pci_dev *dev, int where,
  260.       u32 val)
  261. {
  262. ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
  263. ST40PCI_WRITE(PDR, val);
  264. CheckForMasterAbort();
  265. return PCIBIOS_SUCCESSFUL;
  266. }
  267. static struct pci_ops pci_config_ops = {
  268. st40pci_read_config_byte,
  269. st40pci_read_config_word,
  270. st40pci_read_config_dword,
  271. st40pci_write_config_byte,
  272. st40pci_write_config_word,
  273. st40pci_write_config_dword
  274. };
  275. /* Everything hangs off this */
  276. static struct pci_bus *pci_root_bus;
  277. static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
  278. {
  279. return PCI_SLOT(dev->devfn);
  280. }
  281. /* This needs to be shunted out of here into the board specific bit */
  282. #define HARP_PCI_IRQ    1
  283. #define HARP_BRIDGE_IRQ 2
  284. #define OVERDRIVE_SLOT0_IRQ 0
  285. static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin)
  286. {
  287. switch (slot) {
  288. #ifdef CONFIG_SH_STB1_HARP
  289. case 2: /*This is the PCI slot on the */
  290. return HARP_PCI_IRQ;
  291. case 1: /* this is the bridge */
  292. return HARP_BRIDGE_IRQ;
  293. #elif defined(CONFIG_SH_STB1_OVERDRIVE)
  294. case 1:
  295. case 2:
  296. case 3:
  297. return slot - 1;
  298. #else
  299. #error Unknown board
  300. #endif
  301. default:
  302. return -1;
  303. }
  304. }
  305. void __init
  306. pcibios_fixup_pbus_ranges(struct pci_bus *bus,
  307.   struct pbus_set_ranges_data *ranges)
  308. {
  309. ranges->io_start -= bus->resource[0]->start;
  310. ranges->io_end -= bus->resource[0]->start;
  311. ranges->mem_start -= bus->resource[1]->start;
  312. ranges->mem_end -= bus->resource[1]->start;
  313. }
  314. void __init pcibios_init(void)
  315. {
  316. extern unsigned long memory_start, memory_end;
  317. if (sh_mv.mv_init_pci != NULL) {
  318. sh_mv.mv_init_pci();
  319. }
  320. /* The pci subsytem needs to know where memory is and how much 
  321.  * of it there is. I've simply made these globals. A better mechanism
  322.  * is probably needed.
  323.  */
  324. st40pci_init(PHYSADDR(memory_start),
  325.      PHYSADDR(memory_end) - PHYSADDR(memory_start));
  326. if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, 
  327.                         SA_INTERRUPT, "st40pci", NULL)) {
  328. printk(KERN_ERR "st40pci: Cannot hook interruptn");
  329. return;
  330. }
  331. /* Enable the PCI interrupts on the device */
  332. ST40PCI_WRITE(INTM, ~0);
  333. ST40PCI_WRITE(AINT, ~0);
  334. /* Map the io address apprioately */
  335. #ifdef CONFIG_HD64465
  336. hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1,
  337.  ST40_IO_ADDR + PCIBIOS_MIN_IO, 0);
  338. #endif
  339. /* ok, do the scan man */
  340. pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
  341. pci_assign_unassigned_resources();
  342. pci_fixup_irqs(no_swizzle, map_harp_irq);
  343. }
  344. void __init pcibios_fixup_bus(struct pci_bus *bus)
  345. {
  346. }