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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/arch/alpha/kernel/core_apecs.c
  3.  *
  4.  * Rewritten for Apecs from the lca.c from:
  5.  *
  6.  * Written by David Mosberger (davidm@cs.arizona.edu) with some code
  7.  * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
  8.  * bios code.
  9.  *
  10.  * Code common to all APECS core logic chips.
  11.  */
  12. #include <linux/kernel.h>
  13. #include <linux/types.h>
  14. #include <linux/pci.h>
  15. #include <linux/init.h>
  16. #include <asm/system.h>
  17. #include <asm/ptrace.h>
  18. #include <asm/smp.h>
  19. #define __EXTERN_INLINE inline
  20. #include <asm/io.h>
  21. #include <asm/core_apecs.h>
  22. #undef __EXTERN_INLINE
  23. #include "proto.h"
  24. #include "pci_impl.h"
  25. /*
  26.  * NOTE: Herein lie back-to-back mb instructions.  They are magic. 
  27.  * One plausible explanation is that the i/o controller does not properly
  28.  * handle the system transaction.  Another involves timing.  Ho hum.
  29.  */
  30. /*
  31.  * BIOS32-style PCI interface:
  32.  */
  33. #define DEBUG_CONFIG 0
  34. #if DEBUG_CONFIG
  35. # define DBGC(args) printk args
  36. #else
  37. # define DBGC(args)
  38. #endif
  39. #define vuip volatile unsigned int  *
  40. /*
  41.  * Given a bus, device, and function number, compute resulting
  42.  * configuration space address and setup the APECS_HAXR2 register
  43.  * accordingly.  It is therefore not safe to have concurrent
  44.  * invocations to configuration space access routines, but there
  45.  * really shouldn't be any need for this.
  46.  *
  47.  * Type 0:
  48.  *
  49.  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  50.  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  51.  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  52.  * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
  53.  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  54.  *
  55.  * 31:11 Device select bit.
  56.  *  10:8 Function number
  57.  *   7:2 Register number
  58.  *
  59.  * Type 1:
  60.  *
  61.  *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
  62.  *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
  63.  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  64.  * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
  65.  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  66.  *
  67.  * 31:24 reserved
  68.  * 23:16 bus number (8 bits = 128 possible buses)
  69.  * 15:11 Device number (5 bits)
  70.  * 10:8 function number
  71.  *  7:2 register number
  72.  *  
  73.  * Notes:
  74.  * The function number selects which function of a multi-function device 
  75.  * (e.g., SCSI and Ethernet).
  76.  * 
  77.  * The register selects a DWORD (32 bit) register offset.  Hence it
  78.  * doesn't get shifted by 2 bits as we want to "drop" the bottom two
  79.  * bits.
  80.  */
  81. static int
  82. mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr,
  83.      unsigned char *type1)
  84. {
  85. unsigned long addr;
  86. u8 bus = dev->bus->number;
  87. u8 device_fn = dev->devfn;
  88. DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
  89.       " pci_addr=0x%p, type1=0x%p)n",
  90.       bus, device_fn, where, pci_addr, type1));
  91. if (bus == 0) {
  92. int device = device_fn >> 3;
  93. /* type 0 configuration cycle: */
  94. if (device > 20) {
  95. DBGC(("mk_conf_addr: device (%d) > 20, returning -1n",
  96.       device));
  97. return -1;
  98. }
  99. *type1 = 0;
  100. addr = (device_fn << 8) | (where);
  101. } else {
  102. /* type 1 configuration cycle: */
  103. *type1 = 1;
  104. addr = (bus << 16) | (device_fn << 8) | (where);
  105. }
  106. *pci_addr = addr;
  107. DBGC(("mk_conf_addr: returning pci_addr 0x%lxn", addr));
  108. return 0;
  109. }
  110. static unsigned int
  111. conf_read(unsigned long addr, unsigned char type1)
  112. {
  113. unsigned long flags;
  114. unsigned int stat0, value;
  115. unsigned int haxr2 = 0;
  116. __save_and_cli(flags); /* avoid getting hit by machine check */
  117. DBGC(("conf_read(addr=0x%lx, type1=%d)n", addr, type1));
  118. /* Reset status register to avoid losing errors.  */
  119. stat0 = *(vuip)APECS_IOC_DCSR;
  120. *(vuip)APECS_IOC_DCSR = stat0;
  121. mb();
  122. DBGC(("conf_read: APECS DCSR was 0x%xn", stat0));
  123. /* If Type1 access, must set HAE #2. */
  124. if (type1) {
  125. haxr2 = *(vuip)APECS_IOC_HAXR2;
  126. mb();
  127. *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
  128. DBGC(("conf_read: TYPE1 accessn"));
  129. }
  130. draina();
  131. mcheck_expected(0) = 1;
  132. mcheck_taken(0) = 0;
  133. mb();
  134. /* Access configuration space.  */
  135. /* Some SRMs step on these registers during a machine check.  */
  136. asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
  137.      : "$9", "$10", "$11", "$12", "$13", "$14", "memory");
  138. if (mcheck_taken(0)) {
  139. mcheck_taken(0) = 0;
  140. value = 0xffffffffU;
  141. mb();
  142. }
  143. mcheck_expected(0) = 0;
  144. mb();
  145. #if 1
  146. /*
  147.  * david.rusling@reo.mts.dec.com.  This code is needed for the
  148.  * EB64+ as it does not generate a machine check (why I don't
  149.  * know).  When we build kernels for one particular platform
  150.  * then we can make this conditional on the type.
  151.  */
  152. draina();
  153. /* Now look for any errors.  */
  154. stat0 = *(vuip)APECS_IOC_DCSR;
  155. DBGC(("conf_read: APECS DCSR after read 0x%xn", stat0));
  156. /* Is any error bit set? */
  157. if (stat0 & 0xffe0U) {
  158. /* If not NDEV, print status.  */
  159. if (!(stat0 & 0x0800)) {
  160. printk("apecs.c:conf_read: got stat0=%xn", stat0);
  161. }
  162. /* Reset error status.  */
  163. *(vuip)APECS_IOC_DCSR = stat0;
  164. mb();
  165. wrmces(0x7); /* reset machine check */
  166. value = 0xffffffff;
  167. }
  168. #endif
  169. /* If Type1 access, must reset HAE #2 so normal IO space ops work.  */
  170. if (type1) {
  171. *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
  172. mb();
  173. }
  174. __restore_flags(flags);
  175. return value;
  176. }
  177. static void
  178. conf_write(unsigned long addr, unsigned int value, unsigned char type1)
  179. {
  180. unsigned long flags;
  181. unsigned int stat0;
  182. unsigned int haxr2 = 0;
  183. __save_and_cli(flags); /* avoid getting hit by machine check */
  184. /* Reset status register to avoid losing errors.  */
  185. stat0 = *(vuip)APECS_IOC_DCSR;
  186. *(vuip)APECS_IOC_DCSR = stat0;
  187. mb();
  188. /* If Type1 access, must set HAE #2. */
  189. if (type1) {
  190. haxr2 = *(vuip)APECS_IOC_HAXR2;
  191. mb();
  192. *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
  193. }
  194. draina();
  195. mcheck_expected(0) = 1;
  196. mb();
  197. /* Access configuration space.  */
  198. *(vuip)addr = value;
  199. mb();
  200. mb();  /* magic */
  201. mcheck_expected(0) = 0;
  202. mb();
  203. #if 1
  204. /*
  205.  * david.rusling@reo.mts.dec.com.  This code is needed for the
  206.  * EB64+ as it does not generate a machine check (why I don't
  207.  * know).  When we build kernels for one particular platform
  208.  * then we can make this conditional on the type.
  209.  */
  210. draina();
  211. /* Now look for any errors.  */
  212. stat0 = *(vuip)APECS_IOC_DCSR;
  213. /* Is any error bit set? */
  214. if (stat0 & 0xffe0U) {
  215. /* If not NDEV, print status.  */
  216. if (!(stat0 & 0x0800)) {
  217. printk("apecs.c:conf_write: got stat0=%xn", stat0);
  218. }
  219. /* Reset error status.  */
  220. *(vuip)APECS_IOC_DCSR = stat0;
  221. mb();
  222. wrmces(0x7); /* reset machine check */
  223. }
  224. #endif
  225. /* If Type1 access, must reset HAE #2 so normal IO space ops work.  */
  226. if (type1) {
  227. *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
  228. mb();
  229. }
  230. __restore_flags(flags);
  231. }
  232. static int
  233. apecs_read_config_byte(struct pci_dev *dev, int where, u8 *value)
  234. {
  235. unsigned long addr, pci_addr;
  236. unsigned char type1;
  237. if (mk_conf_addr(dev, where, &pci_addr, &type1))
  238. return PCIBIOS_DEVICE_NOT_FOUND;
  239. addr = (pci_addr << 5) + 0x00 + APECS_CONF;
  240. *value = conf_read(addr, type1) >> ((where & 3) * 8);
  241. return PCIBIOS_SUCCESSFUL;
  242. }
  243. static int 
  244. apecs_read_config_word(struct pci_dev *dev, int where, u16 *value)
  245. {
  246. unsigned long addr, pci_addr;
  247. unsigned char type1;
  248. if (mk_conf_addr(dev, where, &pci_addr, &type1))
  249. return PCIBIOS_DEVICE_NOT_FOUND;
  250. addr = (pci_addr << 5) + 0x08 + APECS_CONF;
  251. *value = conf_read(addr, type1) >> ((where & 3) * 8);
  252. return PCIBIOS_SUCCESSFUL;
  253. }
  254. static int
  255. apecs_read_config_dword(struct pci_dev *dev, int where, u32 *value)
  256. {
  257. unsigned long addr, pci_addr;
  258. unsigned char type1;
  259. if (mk_conf_addr(dev, where, &pci_addr, &type1))
  260. return PCIBIOS_DEVICE_NOT_FOUND;
  261. addr = (pci_addr << 5) + 0x18 + APECS_CONF;
  262. *value = conf_read(addr, type1);
  263. return PCIBIOS_SUCCESSFUL;
  264. }
  265. static int
  266. apecs_write_config(struct pci_dev *dev, int where, u32 value, long mask)
  267. {
  268. unsigned long addr, pci_addr;
  269. unsigned char type1;
  270. if (mk_conf_addr(dev, where, &pci_addr, &type1))
  271. return PCIBIOS_DEVICE_NOT_FOUND;
  272. addr = (pci_addr << 5) + mask + APECS_CONF;
  273. conf_write(addr, value << ((where & 3) * 8), type1);
  274. return PCIBIOS_SUCCESSFUL;
  275. }
  276. static int
  277. apecs_write_config_byte(struct pci_dev *dev, int where, u8 value)
  278. {
  279. return apecs_write_config(dev, where, value, 0x00);
  280. }
  281. static int
  282. apecs_write_config_word(struct pci_dev *dev, int where, u16 value)
  283. {
  284. return apecs_write_config(dev, where, value, 0x08);
  285. }
  286. static int
  287. apecs_write_config_dword(struct pci_dev *dev, int where, u32 value)
  288. {
  289. return apecs_write_config(dev, where, value, 0x18);
  290. }
  291. struct pci_ops apecs_pci_ops = 
  292. {
  293. read_byte: apecs_read_config_byte,
  294. read_word: apecs_read_config_word,
  295. read_dword: apecs_read_config_dword,
  296. write_byte: apecs_write_config_byte,
  297. write_word: apecs_write_config_word,
  298. write_dword: apecs_write_config_dword
  299. };
  300. void
  301. apecs_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
  302. {
  303. wmb();
  304. *(vip)APECS_IOC_TBIA = 0;
  305. mb();
  306. }
  307. void __init
  308. apecs_init_arch(void)
  309. {
  310. struct pci_controller *hose;
  311. /*
  312.  * Create our single hose.
  313.  */
  314. pci_isa_hose = hose = alloc_pci_controller();
  315. hose->io_space = &ioport_resource;
  316. hose->mem_space = &iomem_resource;
  317. hose->index = 0;
  318. hose->sparse_mem_base = APECS_SPARSE_MEM - IDENT_ADDR;
  319. hose->dense_mem_base = APECS_DENSE_MEM - IDENT_ADDR;
  320. hose->sparse_io_base = APECS_IO - IDENT_ADDR;
  321. hose->dense_io_base = 0;
  322. /*
  323.  * Set up the PCI to main memory translation windows.
  324.  *
  325.  * Window 1 is direct access 1GB at 1GB
  326.  * Window 2 is scatter-gather 8MB at 8MB (for isa)
  327.  */
  328. hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
  329. hose->sg_pci = NULL;
  330. __direct_map_base = 0x40000000;
  331. __direct_map_size = 0x40000000;
  332. *(vuip)APECS_IOC_PB1R = __direct_map_base | 0x00080000;
  333. *(vuip)APECS_IOC_PM1R = (__direct_map_size - 1) & 0xfff00000U;
  334. *(vuip)APECS_IOC_TB1R = 0;
  335. *(vuip)APECS_IOC_PB2R = hose->sg_isa->dma_base | 0x000c0000;
  336. *(vuip)APECS_IOC_PM2R = (hose->sg_isa->size - 1) & 0xfff00000;
  337. *(vuip)APECS_IOC_TB2R = virt_to_phys(hose->sg_isa->ptes) >> 1;
  338. apecs_pci_tbi(hose, 0, -1);
  339. /*
  340.  * Finally, clear the HAXR2 register, which gets used
  341.  * for PCI Config Space accesses. That is the way
  342.  * we want to use it, and we do not want to depend on
  343.  * what ARC or SRM might have left behind...
  344.  */
  345. *(vuip)APECS_IOC_HAXR2 = 0;
  346. mb();
  347. }
  348. void
  349. apecs_pci_clr_err(void)
  350. {
  351. unsigned int jd;
  352. jd = *(vuip)APECS_IOC_DCSR;
  353. if (jd & 0xffe0L) {
  354. *(vuip)APECS_IOC_SEAR;
  355. *(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
  356. mb();
  357. *(vuip)APECS_IOC_DCSR;
  358. }
  359. *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
  360. mb();
  361. *(vuip)APECS_IOC_TBIA;
  362. }
  363. void
  364. apecs_machine_check(unsigned long vector, unsigned long la_ptr,
  365.     struct pt_regs * regs)
  366. {
  367. struct el_common *mchk_header;
  368. struct el_apecs_procdata *mchk_procdata;
  369. struct el_apecs_sysdata_mcheck *mchk_sysdata;
  370. mchk_header = (struct el_common *)la_ptr;
  371. mchk_procdata = (struct el_apecs_procdata *)
  372. (la_ptr + mchk_header->proc_offset
  373.  - sizeof(mchk_procdata->paltemp));
  374. mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
  375. (la_ptr + mchk_header->sys_offset);
  376. /* Clear the error before any reporting.  */
  377. mb();
  378. mb(); /* magic */
  379. draina();
  380. apecs_pci_clr_err();
  381. wrmces(0x7); /* reset machine check pending flag */
  382. mb();
  383. process_mcheck_info(vector, la_ptr, regs, "APECS",
  384.     (mcheck_expected(0)
  385.      && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
  386. }