/arch/mips/pci/pci-vr41xx.c

https://bitbucket.org/evzijst/gittest · C · 291 lines · 214 code · 44 blank · 33 comment · 41 complexity · 735dbfc45c1ba99e8f9d489e2b58580a MD5 · raw file

  1. /*
  2. * pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series.
  3. *
  4. * Copyright (C) 2001-2003 MontaVista Software Inc.
  5. * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
  6. * Copyright (C) 2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  7. * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. */
  23. /*
  24. * Changes:
  25. * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
  26. * - New creation, NEC VR4122 and VR4131 are supported.
  27. */
  28. #include <linux/init.h>
  29. #include <linux/pci.h>
  30. #include <linux/types.h>
  31. #include <asm/cpu.h>
  32. #include <asm/io.h>
  33. #include <asm/vr41xx/vr41xx.h>
  34. #include "pci-vr41xx.h"
  35. extern struct pci_ops vr41xx_pci_ops;
  36. static struct pci_master_address_conversion pci_master_memory1 = {
  37. .bus_base_address = PCI_MASTER_MEM1_BUS_BASE_ADDRESS,
  38. .address_mask = PCI_MASTER_MEM1_ADDRESS_MASK,
  39. .pci_base_address = PCI_MASTER_MEM1_PCI_BASE_ADDRESS,
  40. };
  41. static struct pci_target_address_conversion pci_target_memory1 = {
  42. .address_mask = PCI_TARGET_MEM1_ADDRESS_MASK,
  43. .bus_base_address = PCI_TARGET_MEM1_BUS_BASE_ADDRESS,
  44. };
  45. static struct pci_master_address_conversion pci_master_io = {
  46. .bus_base_address = PCI_MASTER_IO_BUS_BASE_ADDRESS,
  47. .address_mask = PCI_MASTER_IO_ADDRESS_MASK,
  48. .pci_base_address = PCI_MASTER_IO_PCI_BASE_ADDRESS,
  49. };
  50. static struct pci_mailbox_address pci_mailbox = {
  51. .base_address = PCI_MAILBOX_BASE_ADDRESS,
  52. };
  53. static struct pci_target_address_window pci_target_window1 = {
  54. .base_address = PCI_TARGET_WINDOW1_BASE_ADDRESS,
  55. };
  56. static struct resource pci_mem_resource = {
  57. .name = "PCI Memory resources",
  58. .start = PCI_MEM_RESOURCE_START,
  59. .end = PCI_MEM_RESOURCE_END,
  60. .flags = IORESOURCE_MEM,
  61. };
  62. static struct resource pci_io_resource = {
  63. .name = "PCI I/O resources",
  64. .start = PCI_IO_RESOURCE_START,
  65. .end = PCI_IO_RESOURCE_END,
  66. .flags = IORESOURCE_IO,
  67. };
  68. static struct pci_controller_unit_setup vr41xx_pci_controller_unit_setup = {
  69. .master_memory1 = &pci_master_memory1,
  70. .target_memory1 = &pci_target_memory1,
  71. .master_io = &pci_master_io,
  72. .exclusive_access = CANNOT_LOCK_FROM_DEVICE,
  73. .wait_time_limit_from_irdy_to_trdy = 0,
  74. .mailbox = &pci_mailbox,
  75. .target_window1 = &pci_target_window1,
  76. .master_latency_timer = 0x80,
  77. .retry_limit = 0,
  78. .arbiter_priority_control = PCI_ARBITRATION_MODE_FAIR,
  79. .take_away_gnt_mode = PCI_TAKE_AWAY_GNT_DISABLE,
  80. };
  81. static struct pci_controller vr41xx_pci_controller = {
  82. .pci_ops = &vr41xx_pci_ops,
  83. .mem_resource = &pci_mem_resource,
  84. .io_resource = &pci_io_resource,
  85. };
  86. void __init vr41xx_pciu_setup(struct pci_controller_unit_setup *setup)
  87. {
  88. vr41xx_pci_controller_unit_setup = *setup;
  89. }
  90. static int __init vr41xx_pciu_init(void)
  91. {
  92. struct pci_controller_unit_setup *setup;
  93. struct pci_master_address_conversion *master;
  94. struct pci_target_address_conversion *target;
  95. struct pci_mailbox_address *mailbox;
  96. struct pci_target_address_window *window;
  97. unsigned long vtclock, pci_clock_max;
  98. uint32_t val;
  99. setup = &vr41xx_pci_controller_unit_setup;
  100. /* Disable PCI interrupt */
  101. vr41xx_disable_pciint();
  102. /* Supply VTClock to PCIU */
  103. vr41xx_supply_clock(PCIU_CLOCK);
  104. /* Dummy write, waiting for supply of VTClock. */
  105. vr41xx_disable_pciint();
  106. /* Select PCI clock */
  107. if (setup->pci_clock_max != 0)
  108. pci_clock_max = setup->pci_clock_max;
  109. else
  110. pci_clock_max = PCI_CLOCK_MAX;
  111. vtclock = vr41xx_get_vtclock_frequency();
  112. if (vtclock < pci_clock_max)
  113. writel(EQUAL_VTCLOCK, PCICLKSELREG);
  114. else if ((vtclock / 2) < pci_clock_max)
  115. writel(HALF_VTCLOCK, PCICLKSELREG);
  116. else if (current_cpu_data.processor_id >= PRID_VR4131_REV2_1 &&
  117. (vtclock / 3) < pci_clock_max)
  118. writel(ONE_THIRD_VTCLOCK, PCICLKSELREG);
  119. else if ((vtclock / 4) < pci_clock_max)
  120. writel(QUARTER_VTCLOCK, PCICLKSELREG);
  121. else {
  122. printk(KERN_ERR "PCI Clock is over 33MHz.\n");
  123. return -EINVAL;
  124. }
  125. /* Supply PCI clock by PCI bus */
  126. vr41xx_supply_clock(PCI_CLOCK);
  127. if (setup->master_memory1 != NULL) {
  128. master = setup->master_memory1;
  129. val = IBA(master->bus_base_address) |
  130. MASTER_MSK(master->address_mask) |
  131. WINEN |
  132. PCIA(master->pci_base_address);
  133. writel(val, PCIMMAW1REG);
  134. } else {
  135. val = readl(PCIMMAW1REG);
  136. val &= ~WINEN;
  137. writel(val, PCIMMAW1REG);
  138. }
  139. if (setup->master_memory2 != NULL) {
  140. master = setup->master_memory2;
  141. val = IBA(master->bus_base_address) |
  142. MASTER_MSK(master->address_mask) |
  143. WINEN |
  144. PCIA(master->pci_base_address);
  145. writel(val, PCIMMAW2REG);
  146. } else {
  147. val = readl(PCIMMAW2REG);
  148. val &= ~WINEN;
  149. writel(val, PCIMMAW2REG);
  150. }
  151. if (setup->target_memory1 != NULL) {
  152. target = setup->target_memory1;
  153. val = TARGET_MSK(target->address_mask) |
  154. WINEN |
  155. ITA(target->bus_base_address);
  156. writel(val, PCITAW1REG);
  157. } else {
  158. val = readl(PCITAW1REG);
  159. val &= ~WINEN;
  160. writel(val, PCITAW1REG);
  161. }
  162. if (setup->target_memory2 != NULL) {
  163. target = setup->target_memory2;
  164. val = TARGET_MSK(target->address_mask) |
  165. WINEN |
  166. ITA(target->bus_base_address);
  167. writel(val, PCITAW2REG);
  168. } else {
  169. val = readl(PCITAW2REG);
  170. val &= ~WINEN;
  171. writel(val, PCITAW2REG);
  172. }
  173. if (setup->master_io != NULL) {
  174. master = setup->master_io;
  175. val = IBA(master->bus_base_address) |
  176. MASTER_MSK(master->address_mask) |
  177. WINEN |
  178. PCIIA(master->pci_base_address);
  179. writel(val, PCIMIOAWREG);
  180. } else {
  181. val = readl(PCIMIOAWREG);
  182. val &= ~WINEN;
  183. writel(val, PCIMIOAWREG);
  184. }
  185. if (setup->exclusive_access == CANNOT_LOCK_FROM_DEVICE)
  186. writel(UNLOCK, PCIEXACCREG);
  187. else
  188. writel(0, PCIEXACCREG);
  189. if (current_cpu_data.cputype == CPU_VR4122)
  190. writel(TRDYV(setup->wait_time_limit_from_irdy_to_trdy), PCITRDYVREG);
  191. writel(MLTIM(setup->master_latency_timer), LATTIMEREG);
  192. if (setup->mailbox != NULL) {
  193. mailbox = setup->mailbox;
  194. val = MBADD(mailbox->base_address) | TYPE_32BITSPACE |
  195. MSI_MEMORY | PREF_APPROVAL;
  196. writel(val, MAILBAREG);
  197. }
  198. if (setup->target_window1) {
  199. window = setup->target_window1;
  200. val = PMBA(window->base_address) | TYPE_32BITSPACE |
  201. MSI_MEMORY | PREF_APPROVAL;
  202. writel(val, PCIMBA1REG);
  203. }
  204. if (setup->target_window2) {
  205. window = setup->target_window2;
  206. val = PMBA(window->base_address) | TYPE_32BITSPACE |
  207. MSI_MEMORY | PREF_APPROVAL;
  208. writel(val, PCIMBA2REG);
  209. }
  210. val = readl(RETVALREG);
  211. val &= ~RTYVAL_MASK;
  212. val |= RTYVAL(setup->retry_limit);
  213. writel(val, RETVALREG);
  214. val = readl(PCIAPCNTREG);
  215. val &= ~(TKYGNT | PAPC);
  216. switch (setup->arbiter_priority_control) {
  217. case PCI_ARBITRATION_MODE_ALTERNATE_0:
  218. val |= PAPC_ALTERNATE_0;
  219. break;
  220. case PCI_ARBITRATION_MODE_ALTERNATE_B:
  221. val |= PAPC_ALTERNATE_B;
  222. break;
  223. default:
  224. val |= PAPC_FAIR;
  225. break;
  226. }
  227. if (setup->take_away_gnt_mode == PCI_TAKE_AWAY_GNT_ENABLE)
  228. val |= TKYGNT_ENABLE;
  229. writel(val, PCIAPCNTREG);
  230. writel(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
  231. PCI_COMMAND_PARITY | PCI_COMMAND_SERR, COMMANDREG);
  232. /* Clear bus error */
  233. readl(BUSERRADREG);
  234. writel(BLOODY_CONFIG_DONE, PCIENREG);
  235. if (setup->mem_resource != NULL)
  236. vr41xx_pci_controller.mem_resource = setup->mem_resource;
  237. if (setup->io_resource != NULL) {
  238. vr41xx_pci_controller.io_resource = setup->io_resource;
  239. } else {
  240. set_io_port_base(IO_PORT_BASE);
  241. ioport_resource.start = IO_PORT_RESOURCE_START;
  242. ioport_resource.end = IO_PORT_RESOURCE_END;
  243. }
  244. register_pci_controller(&vr41xx_pci_controller);
  245. return 0;
  246. }
  247. arch_initcall(vr41xx_pciu_init);