ops-tx3927.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * Copyright 2001 MontaVista Software Inc.
  3. * Author: MontaVista Software, Inc.
  4. * ahennessy@mvista.com
  5. *
  6. * Copyright (C) 2000-2001 Toshiba Corporation
  7. * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
  8. *
  9. * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
  10. *
  11. * Define the pci_ops for JMR3927.
  12. *
  13. * Much of the code is derived from the original DDB5074 port by
  14. * Geert Uytterhoeven <geert@sonycom.com>
  15. *
  16. * This program is free software; you can redistribute it and/or modify it
  17. * under the terms of the GNU General Public License as published by the
  18. * Free Software Foundation; either version 2 of the License, or (at your
  19. * option) any later version.
  20. *
  21. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  22. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  23. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
  24. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  26. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  27. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  28. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  30. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * You should have received a copy of the GNU General Public License along
  33. * with this program; if not, write to the Free Software Foundation, Inc.,
  34. * 675 Mass Ave, Cambridge, MA 02139, USA.
  35. */
  36. #include <linux/types.h>
  37. #include <linux/pci.h>
  38. #include <linux/kernel.h>
  39. #include <linux/init.h>
  40. #include <asm/addrspace.h>
  41. #include <asm/jmr3927/jmr3927.h>
  42. #include <asm/debug.h>
  43. static inline int mkaddr(unsigned char bus, unsigned char dev_fn,
  44. unsigned char where)
  45. {
  46. if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0))
  47. return PCIBIOS_DEVICE_NOT_FOUND;
  48. tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) |
  49. ((dev_fn & 0xff) << 0x08) |
  50. (where & 0xfc);
  51. /* clear M_ABORT and Disable M_ABORT Int. */
  52. tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
  53. tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT;
  54. return PCIBIOS_SUCCESSFUL;
  55. }
  56. static inline int check_abort(void)
  57. {
  58. if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
  59. tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
  60. tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
  61. return PCIBIOS_DEVICE_NOT_FOUND;
  62. return PCIBIOS_SUCCESSFUL;
  63. }
  64. static int jmr3927_pci_read_config(struct pci_bus *bus, unsigned int devfn,
  65. int where, int size, u32 * val)
  66. {
  67. int ret;
  68. ret = mkaddr(bus->number, devfn, where);
  69. if (ret)
  70. return ret;
  71. switch (size) {
  72. case 1:
  73. *val = *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3));
  74. break;
  75. case 2:
  76. *val = le16_to_cpu(*(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)));
  77. break;
  78. case 4:
  79. *val = le32_to_cpu(tx3927_pcicptr->icd);
  80. break;
  81. }
  82. return check_abort();
  83. }
  84. static int jmr3927_pci_write_config(struct pci_bus *bus, unsigned int devfn,
  85. int where, int size, u32 val)
  86. {
  87. int ret;
  88. ret = mkaddr(bus->number, devfn, where);
  89. if (ret)
  90. return ret;
  91. switch (size) {
  92. case 1:
  93. *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)) = val;
  94. break;
  95. case 2:
  96. *(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 2)) =
  97. cpu_to_le16(val);
  98. break;
  99. case 4:
  100. tx3927_pcicptr->icd = cpu_to_le32(val);
  101. }
  102. if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
  103. tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
  104. tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
  105. return PCIBIOS_DEVICE_NOT_FOUND;
  106. return check_abort();
  107. }
  108. struct pci_ops jmr3927_pci_ops = {
  109. jmr3927_pci_read_config,
  110. jmr3927_pci_write_config,
  111. };
  112. #ifndef JMR3927_INIT_INDIRECT_PCI
  113. inline unsigned long tc_readl(volatile __u32 * addr)
  114. {
  115. return readl(addr);
  116. }
  117. inline void tc_writel(unsigned long data, volatile __u32 * addr)
  118. {
  119. writel(data, addr);
  120. }
  121. #else
  122. unsigned long tc_readl(volatile __u32 * addr)
  123. {
  124. unsigned long val;
  125. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  126. (unsigned long) CPHYSADDR(addr);
  127. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  128. (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) |
  129. PCI_IPCIBE_IBE_LONG;
  130. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  131. val =
  132. le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
  133. ipcidata);
  134. /* clear by setting */
  135. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  136. return val;
  137. }
  138. void tc_writel(unsigned long data, volatile __u32 * addr)
  139. {
  140. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata =
  141. cpu_to_le32(data);
  142. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  143. (unsigned long) CPHYSADDR(addr);
  144. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  145. (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) |
  146. PCI_IPCIBE_IBE_LONG;
  147. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  148. /* clear by setting */
  149. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  150. }
  151. unsigned char tx_ioinb(unsigned char *addr)
  152. {
  153. unsigned long val;
  154. __u32 ioaddr;
  155. int offset;
  156. int byte;
  157. ioaddr = (unsigned long) addr;
  158. offset = ioaddr & 0x3;
  159. byte = 0xf & ~(8 >> offset);
  160. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  161. (unsigned long) ioaddr;
  162. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  163. (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
  164. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  165. val =
  166. le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
  167. ipcidata);
  168. val = val & 0xff;
  169. /* clear by setting */
  170. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  171. return val;
  172. }
  173. void tx_iooutb(unsigned long data, unsigned char *addr)
  174. {
  175. __u32 ioaddr;
  176. int offset;
  177. int byte;
  178. data = data | (data << 8) | (data << 16) | (data << 24);
  179. ioaddr = (unsigned long) addr;
  180. offset = ioaddr & 0x3;
  181. byte = 0xf & ~(8 >> offset);
  182. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = data;
  183. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  184. (unsigned long) ioaddr;
  185. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  186. (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
  187. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  188. /* clear by setting */
  189. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  190. }
  191. unsigned short tx_ioinw(unsigned short *addr)
  192. {
  193. unsigned long val;
  194. __u32 ioaddr;
  195. int offset;
  196. int byte;
  197. ioaddr = (unsigned long) addr;
  198. offset = ioaddr & 0x2;
  199. byte = 3 << offset;
  200. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  201. (unsigned long) ioaddr;
  202. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  203. (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte;
  204. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  205. val =
  206. le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
  207. ipcidata);
  208. val = val & 0xffff;
  209. /* clear by setting */
  210. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  211. return val;
  212. }
  213. void tx_iooutw(unsigned long data, unsigned short *addr)
  214. {
  215. __u32 ioaddr;
  216. int offset;
  217. int byte;
  218. data = data | (data << 16);
  219. ioaddr = (unsigned long) addr;
  220. offset = ioaddr & 0x2;
  221. byte = 3 << offset;
  222. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata = data;
  223. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  224. (unsigned long) ioaddr;
  225. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  226. (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte;
  227. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  228. /* clear by setting */
  229. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  230. }
  231. unsigned long tx_ioinl(unsigned int *addr)
  232. {
  233. unsigned long val;
  234. __u32 ioaddr;
  235. ioaddr = (unsigned long) addr;
  236. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  237. (unsigned long) ioaddr;
  238. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  239. (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) |
  240. PCI_IPCIBE_IBE_LONG;
  241. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  242. val =
  243. le32_to_cpu(*(volatile u32 *) (unsigned long) & tx3927_pcicptr->
  244. ipcidata);
  245. /* clear by setting */
  246. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  247. return val;
  248. }
  249. void tx_iooutl(unsigned long data, unsigned int *addr)
  250. {
  251. __u32 ioaddr;
  252. ioaddr = (unsigned long) addr;
  253. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcidata =
  254. cpu_to_le32(data);
  255. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipciaddr =
  256. (unsigned long) ioaddr;
  257. *(volatile u32 *) (unsigned long) & tx3927_pcicptr->ipcibe =
  258. (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) |
  259. PCI_IPCIBE_IBE_LONG;
  260. while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC));
  261. /* clear by setting */
  262. tx3927_pcicptr->istat |= PCI_ISTAT_IDICC;
  263. }
  264. void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count)
  265. {
  266. unsigned char *ptr = (unsigned char *) buffer;
  267. while (count--) {
  268. *ptr++ = tx_ioinb(addr);
  269. }
  270. }
  271. void tx_insword(unsigned short *addr, void *buffer, unsigned int count)
  272. {
  273. unsigned short *ptr = (unsigned short *) buffer;
  274. while (count--) {
  275. *ptr++ = tx_ioinw(addr);
  276. }
  277. }
  278. void tx_inslong(unsigned int *addr, void *buffer, unsigned int count)
  279. {
  280. unsigned long *ptr = (unsigned long *) buffer;
  281. while (count--) {
  282. *ptr++ = tx_ioinl(addr);
  283. }
  284. }
  285. void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count)
  286. {
  287. unsigned char *ptr = (unsigned char *) buffer;
  288. while (count--) {
  289. tx_iooutb(*ptr++, addr);
  290. }
  291. }
  292. void tx_outsword(unsigned short *addr, void *buffer, unsigned int count)
  293. {
  294. unsigned short *ptr = (unsigned short *) buffer;
  295. while (count--) {
  296. tx_iooutw(*ptr++, addr);
  297. }
  298. }
  299. void tx_outslong(unsigned int *addr, void *buffer, unsigned int count)
  300. {
  301. unsigned long *ptr = (unsigned long *) buffer;
  302. while (count--) {
  303. tx_iooutl(*ptr++, addr);
  304. }
  305. }
  306. #endif