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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * hades-pci.c - Hardware specific PCI BIOS functions the Hades Atari clone.
  3.  *
  4.  * Written by Wout Klaren.
  5.  */
  6. #include <linux/config.h>
  7. #include <linux/init.h>
  8. #include <linux/kernel.h>
  9. #include <asm/io.h>
  10. #if 0
  11. # define DBG_DEVS(args) printk args
  12. #else
  13. # define DBG_DEVS(args)
  14. #endif
  15. #if defined(CONFIG_PCI) && defined(CONFIG_HADES)
  16. #include <linux/slab.h>
  17. #include <linux/mm.h>
  18. #include <linux/pci.h>
  19. #include <asm/atarihw.h>
  20. #include <asm/atariints.h>
  21. #include <asm/byteorder.h>
  22. #include <asm/pci.h>
  23. #define HADES_MEM_BASE 0x80000000
  24. #define HADES_MEM_SIZE 0x20000000
  25. #define HADES_CONFIG_BASE 0xA0000000
  26. #define HADES_CONFIG_SIZE 0x10000000
  27. #define HADES_IO_BASE 0xB0000000
  28. #define HADES_IO_SIZE 0x10000000
  29. #define HADES_VIRT_IO_SIZE 0x00010000 /* Only 64k is remapped and actually used. */
  30. #define N_SLOTS 4 /* Number of PCI slots. */
  31. static const char pci_mem_name[] = "PCI memory space";
  32. static const char pci_io_name[] = "PCI I/O space";
  33. static const char pci_config_name[] = "PCI config space";
  34. static struct resource config_space = { pci_config_name, HADES_CONFIG_BASE,
  35. HADES_CONFIG_BASE + HADES_CONFIG_SIZE - 1 };
  36. static struct resource io_space = { pci_io_name, HADES_IO_BASE, HADES_IO_BASE +
  37.     HADES_IO_SIZE - 1 };
  38. static const unsigned long pci_conf_base_phys[] = { 0xA0080000, 0xA0040000,
  39.     0xA0020000, 0xA0010000 };
  40. static unsigned long pci_conf_base_virt[N_SLOTS];
  41. static unsigned long pci_io_base_virt;
  42. /*
  43.  * static void *mk_conf_addr(unsigned char bus, unsigned char device_fn,
  44.  *      unsigned char where)
  45.  *
  46.  * Calculate the address of the PCI configuration area of the given
  47.  * device.
  48.  *
  49.  * BUG: boards with multiple functions are probably not correctly
  50.  * supported.
  51.  */
  52. static void *mk_conf_addr(struct pci_dev *dev, int where)
  53. {
  54. int device = dev->devfn >> 3, function = dev->devfn & 7;
  55. void *result;
  56. DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)n",
  57.   dev->bus->number, dev->devfn, where, pci_addr));
  58. if (device > 3)
  59. {
  60. DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning NULLn", device));
  61. return NULL;
  62. }
  63. if (dev->bus->number != 0)
  64. {
  65. DBG_DEVS(("mk_conf_addr: bus (%d) > 0, returning NULLn", device));
  66. return NULL;
  67. }
  68. result = (void *) (pci_conf_base_virt[device] | (function << 8) | (where));
  69. DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lxn", (unsigned long) result));
  70. return result;
  71. }
  72. static int hades_read_config_byte(struct pci_dev *dev, int where, u8 *value)
  73. {
  74. volatile unsigned char *pci_addr;
  75. *value = 0xff;
  76. if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
  77. return PCIBIOS_DEVICE_NOT_FOUND;
  78. *value = *pci_addr;
  79. return PCIBIOS_SUCCESSFUL;
  80. }
  81. static int hades_read_config_word(struct pci_dev *dev, int where, u16 *value)
  82. {
  83. volatile unsigned short *pci_addr;
  84. *value = 0xffff;
  85. if (where & 0x1)
  86. return PCIBIOS_BAD_REGISTER_NUMBER;
  87. if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
  88. return PCIBIOS_DEVICE_NOT_FOUND;
  89. *value = le16_to_cpu(*pci_addr);
  90. return PCIBIOS_SUCCESSFUL;
  91. }
  92. static int hades_read_config_dword(struct pci_dev *dev, int where, u32 *value)
  93. {
  94. volatile unsigned int *pci_addr;
  95. unsigned char header_type;
  96. int result;
  97. *value = 0xffffffff;
  98. if (where & 0x3)
  99. return PCIBIOS_BAD_REGISTER_NUMBER;
  100. if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
  101. return PCIBIOS_DEVICE_NOT_FOUND;
  102. *value = le32_to_cpu(*pci_addr);
  103. /*
  104.  * Check if the value is an address on the bus. If true, add the
  105.  * base address of the PCI memory or PCI I/O area on the Hades.
  106.  */
  107. if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
  108.      &header_type)) != PCIBIOS_SUCCESSFUL)
  109. return result;
  110. if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
  111.     ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
  112.  (where <= PCI_BASE_ADDRESS_5))))
  113. {
  114. if ((*value & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
  115. {
  116. /*
  117.  * Base address register that contains an I/O address. If the
  118.  * address is valid on the Hades (0 <= *value < HADES_VIRT_IO_SIZE),
  119.  * add 'pci_io_base_virt' to the value.
  120.  */
  121. if (*value < HADES_VIRT_IO_SIZE)
  122. *value += pci_io_base_virt;
  123. }
  124. else
  125. {
  126. /*
  127.  * Base address register that contains an memory address. If the
  128.  * address is valid on the Hades (0 <= *value < HADES_MEM_SIZE),
  129.  * add HADES_MEM_BASE to the value.
  130.  */
  131. if (*value == 0)
  132. {
  133. /*
  134.  * Base address is 0. Test if this base
  135.  * address register is used.
  136.  */
  137. *pci_addr = 0xffffffff;
  138. if (*pci_addr != 0)
  139. {
  140. *pci_addr = *value;
  141. if (*value < HADES_MEM_SIZE)
  142. *value += HADES_MEM_BASE;
  143. }
  144. }
  145. else
  146. {
  147. if (*value < HADES_MEM_SIZE)
  148. *value += HADES_MEM_BASE;
  149. }
  150. }
  151. }
  152. return PCIBIOS_SUCCESSFUL;
  153. }
  154. static int hades_write_config_byte(struct pci_dev *dev, int where, u8 value)
  155. {
  156. volatile unsigned char *pci_addr;
  157. if ((pci_addr = (unsigned char *) mk_conf_addr(dev, where)) == NULL)
  158. return PCIBIOS_DEVICE_NOT_FOUND;
  159. *pci_addr = value;
  160. return PCIBIOS_SUCCESSFUL;
  161. }
  162. static int hades_write_config_word(struct pci_dev *dev, int where, u16 value)
  163. {
  164. volatile unsigned short *pci_addr;
  165. if ((pci_addr = (unsigned short *) mk_conf_addr(dev, where)) == NULL)
  166. return PCIBIOS_DEVICE_NOT_FOUND;
  167. *pci_addr = cpu_to_le16(value);
  168. return PCIBIOS_SUCCESSFUL;
  169. }
  170. static int hades_write_config_dword(struct pci_dev *dev, int where, u32 value)
  171. {
  172. volatile unsigned int *pci_addr;
  173. unsigned char header_type;
  174. int result;
  175. if ((pci_addr = (unsigned int *) mk_conf_addr(dev, where)) == NULL)
  176. return PCIBIOS_DEVICE_NOT_FOUND;
  177. /*
  178.  * Check if the value is an address on the bus. If true, subtract the
  179.  * base address of the PCI memory or PCI I/O area on the Hades.
  180.  */
  181. if ((result = hades_read_config_byte(dev, PCI_HEADER_TYPE,
  182.      &header_type)) != PCIBIOS_SUCCESSFUL)
  183. return result;
  184. if (((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_1)) ||
  185.     ((header_type != PCI_HEADER_TYPE_BRIDGE) && ((where >= PCI_BASE_ADDRESS_2) &&
  186.  (where <= PCI_BASE_ADDRESS_5))))
  187. {
  188. if ((value & PCI_BASE_ADDRESS_SPACE) ==
  189.     PCI_BASE_ADDRESS_SPACE_IO)
  190. {
  191. /*
  192.  * I/O address. Check if the address is valid address on
  193.  * the Hades (pci_io_base_virt <= value < pci_io_base_virt +
  194.  * HADES_VIRT_IO_SIZE) or if the value is 0xffffffff. If not
  195.  * true do not write the base address register. If it is a
  196.  * valid base address subtract 'pci_io_base_virt' from the value.
  197.  */
  198. if ((value >= pci_io_base_virt) && (value < (pci_io_base_virt +
  199.  HADES_VIRT_IO_SIZE)))
  200. value -= pci_io_base_virt;
  201. else
  202. {
  203. if (value != 0xffffffff)
  204. return PCIBIOS_SET_FAILED;
  205. }
  206. }
  207. else
  208. {
  209. /*
  210.  * Memory address. Check if the address is valid address on
  211.  * the Hades (HADES_MEM_BASE <= value < HADES_MEM_BASE + HADES_MEM_SIZE) or
  212.  * if the value is 0xffffffff. If not true do not write
  213.  * the base address register. If it is a valid base address
  214.  * subtract HADES_MEM_BASE from the value.
  215.  */
  216. if ((value >= HADES_MEM_BASE) && (value < (HADES_MEM_BASE + HADES_MEM_SIZE)))
  217. value -= HADES_MEM_BASE;
  218. else
  219. {
  220. if (value != 0xffffffff)
  221. return PCIBIOS_SET_FAILED;
  222. }
  223. }
  224. }
  225. *pci_addr = cpu_to_le32(value);
  226. return PCIBIOS_SUCCESSFUL;
  227. }
  228. /*
  229.  * static inline void hades_fixup(void)
  230.  *
  231.  * Assign IRQ numbers as used by Linux to the interrupt pins
  232.  * of the PCI cards.
  233.  */
  234. static void __init hades_fixup(int pci_modify)
  235. {
  236. char irq_tab[4] = {
  237.     IRQ_TT_MFP_IO0, /* Slot 0. */
  238.     IRQ_TT_MFP_IO1, /* Slot 1. */
  239.     IRQ_TT_MFP_SCC, /* Slot 2. */
  240.     IRQ_TT_MFP_SCSIDMA /* Slot 3. */
  241.   };
  242. struct pci_dev *dev;
  243. unsigned char slot;
  244. /*
  245.  * Go through all devices, fixing up irqs as we see fit:
  246.  */
  247. for (dev = pci_devices; dev; dev = dev->next)
  248. {
  249. if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
  250. {
  251. slot = PCI_SLOT(dev->devfn); /* Determine slot number. */
  252. dev->irq = irq_tab[slot];
  253. if (pci_modify)
  254. pcibios_write_config_byte(dev->bus->number, dev->devfn,
  255.   PCI_INTERRUPT_LINE, dev->irq);
  256. }
  257. }
  258. }
  259. /*
  260.  * static void hades_conf_device(unsigned char bus, unsigned char device_fn)
  261.  *
  262.  * Machine dependent Configure the given device.
  263.  *
  264.  * Parameters:
  265.  *
  266.  * bus - bus number of the device.
  267.  * device_fn - device and function number of the device.
  268.  */
  269. static void __init hades_conf_device(unsigned char bus, unsigned char device_fn)
  270. {
  271. pcibios_write_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, 0);
  272. }
  273. static struct pci_ops hades_pci_ops = {
  274. read_byte: hades_read_config_byte
  275. read_word: hades_read_config_word
  276. read_dword: hades_read_config_dword
  277. write_byte: hades_write_config_byte
  278. write_word: hades_write_config_word
  279. write_dword: hades_write_config_dword
  280. };
  281. /*
  282.  * struct pci_bus_info *init_hades_pci(void)
  283.  *
  284.  * Machine specific initialisation:
  285.  *
  286.  * - Allocate and initialise a 'pci_bus_info' structure
  287.  * - Initialise hardware
  288.  *
  289.  * Result: pointer to 'pci_bus_info' structure.
  290.  */
  291. struct pci_bus_info * __init init_hades_pci(void)
  292. {
  293. struct pci_bus_info *bus;
  294. int i;
  295. /*
  296.  * Remap I/O and configuration space.
  297.  */
  298. pci_io_base_virt = (unsigned long) ioremap(HADES_IO_BASE, HADES_VIRT_IO_SIZE);
  299. for (i = 0; i < N_SLOTS; i++)
  300. pci_conf_base_virt[i] = (unsigned long) ioremap(pci_conf_base_phys[i], 0x10000);
  301. /*
  302.  * Allocate memory for bus info structure.
  303.  */
  304. bus = kmalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
  305. if (!bus)
  306. return NULL;
  307. memset(bus, 0, sizeof(struct pci_bus_info));
  308. /*
  309.  * Claim resources. The m68k has no seperate I/O space, both
  310.  * PCI memory space and PCI I/O space are in memory space. Therefore
  311.  * the I/O resources are requested in memory space as well.
  312.  */
  313. if (request_resource(&iomem_resource, &config_space) != 0)
  314. {
  315. kfree(bus);
  316. return NULL;
  317. }
  318. if (request_resource(&iomem_resource, &io_space) != 0)
  319. {
  320. release_resource(&config_space);
  321. kfree(bus);
  322. return NULL;
  323. }
  324. bus->mem_space.start = HADES_MEM_BASE;
  325. bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
  326. bus->mem_space.name = pci_mem_name;
  327. #if 1
  328. if (request_resource(&iomem_resource, &bus->mem_space) != 0)
  329. {
  330. release_resource(&io_space);
  331. release_resource(&config_space);
  332. kfree(bus);
  333. return NULL;
  334. }
  335. #endif
  336. bus->io_space.start = pci_io_base_virt;
  337. bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
  338. bus->io_space.name = pci_io_name;
  339. #if 1
  340. if (request_resource(&ioport_resource, &bus->io_space) != 0)
  341. {
  342. release_resource(&bus->mem_space);
  343. release_resource(&io_space);
  344. release_resource(&config_space);
  345. kfree(bus);
  346. return NULL;
  347. }
  348. #endif
  349. /*
  350.  * Set hardware dependent functions.
  351.  */
  352. bus->m68k_pci_ops = &hades_pci_ops;
  353. bus->fixup = hades_fixup;
  354. bus->conf_device = hades_conf_device;
  355. /*
  356.  * Select high to low edge for PCI interrupts.
  357.  */
  358. tt_mfp.active_edge &= ~0x27;
  359. return bus;
  360. }
  361. #endif