/arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c

http://github.com/mirrors/linux · C · 323 lines · 184 code · 56 blank · 83 comment · 29 complexity · 76acb7d12da3cc20a71457e0113f0d20 MD5 · raw file

  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * arch/powerpc/platforms/embedded6xx/usbgecko_udbg.c
  4. *
  5. * udbg serial input/output routines for the USB Gecko adapter.
  6. * Copyright (C) 2008-2009 The GameCube Linux Team
  7. * Copyright (C) 2008,2009 Albert Herranz
  8. */
  9. #include <mm/mmu_decl.h>
  10. #include <asm/io.h>
  11. #include <asm/prom.h>
  12. #include <asm/udbg.h>
  13. #include <asm/fixmap.h>
  14. #include "usbgecko_udbg.h"
  15. #define EXI_CLK_32MHZ 5
  16. #define EXI_CSR 0x00
  17. #define EXI_CSR_CLKMASK (0x7<<4)
  18. #define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4)
  19. #define EXI_CSR_CSMASK (0x7<<7)
  20. #define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */
  21. #define EXI_CR 0x0c
  22. #define EXI_CR_TSTART (1<<0)
  23. #define EXI_CR_WRITE (1<<2)
  24. #define EXI_CR_READ_WRITE (2<<2)
  25. #define EXI_CR_TLEN(len) (((len)-1)<<4)
  26. #define EXI_DATA 0x10
  27. #define UG_READ_ATTEMPTS 100
  28. #define UG_WRITE_ATTEMPTS 100
  29. static void __iomem *ug_io_base;
  30. /*
  31. * Performs one input/output transaction between the exi host and the usbgecko.
  32. */
  33. static u32 ug_io_transaction(u32 in)
  34. {
  35. u32 __iomem *csr_reg = ug_io_base + EXI_CSR;
  36. u32 __iomem *data_reg = ug_io_base + EXI_DATA;
  37. u32 __iomem *cr_reg = ug_io_base + EXI_CR;
  38. u32 csr, data, cr;
  39. /* select */
  40. csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
  41. out_be32(csr_reg, csr);
  42. /* read/write */
  43. data = in;
  44. out_be32(data_reg, data);
  45. cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
  46. out_be32(cr_reg, cr);
  47. while (in_be32(cr_reg) & EXI_CR_TSTART)
  48. barrier();
  49. /* deselect */
  50. out_be32(csr_reg, 0);
  51. /* result */
  52. data = in_be32(data_reg);
  53. return data;
  54. }
  55. /*
  56. * Returns true if an usbgecko adapter is found.
  57. */
  58. static int ug_is_adapter_present(void)
  59. {
  60. if (!ug_io_base)
  61. return 0;
  62. return ug_io_transaction(0x90000000) == 0x04700000;
  63. }
  64. /*
  65. * Returns true if the TX fifo is ready for transmission.
  66. */
  67. static int ug_is_txfifo_ready(void)
  68. {
  69. return ug_io_transaction(0xc0000000) & 0x04000000;
  70. }
  71. /*
  72. * Tries to transmit a character.
  73. * If the TX fifo is not ready the result is undefined.
  74. */
  75. static void ug_raw_putc(char ch)
  76. {
  77. ug_io_transaction(0xb0000000 | (ch << 20));
  78. }
  79. /*
  80. * Transmits a character.
  81. * It silently fails if the TX fifo is not ready after a number of retries.
  82. */
  83. static void ug_putc(char ch)
  84. {
  85. int count = UG_WRITE_ATTEMPTS;
  86. if (!ug_io_base)
  87. return;
  88. if (ch == '\n')
  89. ug_putc('\r');
  90. while (!ug_is_txfifo_ready() && count--)
  91. barrier();
  92. if (count >= 0)
  93. ug_raw_putc(ch);
  94. }
  95. /*
  96. * Returns true if the RX fifo is ready for transmission.
  97. */
  98. static int ug_is_rxfifo_ready(void)
  99. {
  100. return ug_io_transaction(0xd0000000) & 0x04000000;
  101. }
  102. /*
  103. * Tries to receive a character.
  104. * If a character is unavailable the function returns -1.
  105. */
  106. static int ug_raw_getc(void)
  107. {
  108. u32 data = ug_io_transaction(0xa0000000);
  109. if (data & 0x08000000)
  110. return (data >> 16) & 0xff;
  111. else
  112. return -1;
  113. }
  114. /*
  115. * Receives a character.
  116. * It fails if the RX fifo is not ready after a number of retries.
  117. */
  118. static int ug_getc(void)
  119. {
  120. int count = UG_READ_ATTEMPTS;
  121. if (!ug_io_base)
  122. return -1;
  123. while (!ug_is_rxfifo_ready() && count--)
  124. barrier();
  125. return ug_raw_getc();
  126. }
  127. /*
  128. * udbg functions.
  129. *
  130. */
  131. /*
  132. * Transmits a character.
  133. */
  134. static void ug_udbg_putc(char ch)
  135. {
  136. ug_putc(ch);
  137. }
  138. /*
  139. * Receives a character. Waits until a character is available.
  140. */
  141. static int ug_udbg_getc(void)
  142. {
  143. int ch;
  144. while ((ch = ug_getc()) == -1)
  145. barrier();
  146. return ch;
  147. }
  148. /*
  149. * Receives a character. If a character is not available, returns -1.
  150. */
  151. static int ug_udbg_getc_poll(void)
  152. {
  153. if (!ug_is_rxfifo_ready())
  154. return -1;
  155. return ug_getc();
  156. }
  157. /*
  158. * Retrieves and prepares the virtual address needed to access the hardware.
  159. */
  160. static void __iomem *ug_udbg_setup_exi_io_base(struct device_node *np)
  161. {
  162. void __iomem *exi_io_base = NULL;
  163. phys_addr_t paddr;
  164. const unsigned int *reg;
  165. reg = of_get_property(np, "reg", NULL);
  166. if (reg) {
  167. paddr = of_translate_address(np, reg);
  168. if (paddr)
  169. exi_io_base = ioremap(paddr, reg[1]);
  170. }
  171. return exi_io_base;
  172. }
  173. /*
  174. * Checks if a USB Gecko adapter is inserted in any memory card slot.
  175. */
  176. static void __iomem *ug_udbg_probe(void __iomem *exi_io_base)
  177. {
  178. int i;
  179. /* look for a usbgecko on memcard slots A and B */
  180. for (i = 0; i < 2; i++) {
  181. ug_io_base = exi_io_base + 0x14 * i;
  182. if (ug_is_adapter_present())
  183. break;
  184. }
  185. if (i == 2)
  186. ug_io_base = NULL;
  187. return ug_io_base;
  188. }
  189. /*
  190. * USB Gecko udbg support initialization.
  191. */
  192. void __init ug_udbg_init(void)
  193. {
  194. struct device_node *np;
  195. void __iomem *exi_io_base;
  196. if (ug_io_base)
  197. udbg_printf("%s: early -> final\n", __func__);
  198. np = of_find_compatible_node(NULL, NULL, "nintendo,flipper-exi");
  199. if (!np) {
  200. udbg_printf("%s: EXI node not found\n", __func__);
  201. goto out;
  202. }
  203. exi_io_base = ug_udbg_setup_exi_io_base(np);
  204. if (!exi_io_base) {
  205. udbg_printf("%s: failed to setup EXI io base\n", __func__);
  206. goto done;
  207. }
  208. if (!ug_udbg_probe(exi_io_base)) {
  209. udbg_printf("usbgecko_udbg: not found\n");
  210. iounmap(exi_io_base);
  211. } else {
  212. udbg_putc = ug_udbg_putc;
  213. udbg_getc = ug_udbg_getc;
  214. udbg_getc_poll = ug_udbg_getc_poll;
  215. udbg_printf("usbgecko_udbg: ready\n");
  216. }
  217. done:
  218. of_node_put(np);
  219. out:
  220. return;
  221. }
  222. #ifdef CONFIG_PPC_EARLY_DEBUG_USBGECKO
  223. static phys_addr_t __init ug_early_grab_io_addr(void)
  224. {
  225. #if defined(CONFIG_GAMECUBE)
  226. return 0x0c000000;
  227. #elif defined(CONFIG_WII)
  228. return 0x0d000000;
  229. #else
  230. #error Invalid platform for USB Gecko based early debugging.
  231. #endif
  232. }
  233. /*
  234. * USB Gecko early debug support initialization for udbg.
  235. */
  236. void __init udbg_init_usbgecko(void)
  237. {
  238. void __iomem *early_debug_area;
  239. void __iomem *exi_io_base;
  240. /*
  241. * At this point we have a BAT already setup that enables I/O
  242. * to the EXI hardware.
  243. *
  244. * The BAT uses a virtual address range reserved at the fixmap.
  245. * This must match the virtual address configured in
  246. * head_32.S:setup_usbgecko_bat().
  247. */
  248. early_debug_area = (void __iomem *)__fix_to_virt(FIX_EARLY_DEBUG_BASE);
  249. exi_io_base = early_debug_area + 0x00006800;
  250. /* try to detect a USB Gecko */
  251. if (!ug_udbg_probe(exi_io_base))
  252. return;
  253. /* we found a USB Gecko, load udbg hooks */
  254. udbg_putc = ug_udbg_putc;
  255. udbg_getc = ug_udbg_getc;
  256. udbg_getc_poll = ug_udbg_getc_poll;
  257. /*
  258. * Prepare again the same BAT for MMU_init.
  259. * This allows udbg I/O to continue working after the MMU is
  260. * turned on for real.
  261. * It is safe to continue using the same virtual address as it is
  262. * a reserved fixmap area.
  263. */
  264. setbat(1, (unsigned long)early_debug_area,
  265. ug_early_grab_io_addr(), 128*1024, PAGE_KERNEL_NCG);
  266. }
  267. #endif /* CONFIG_PPC_EARLY_DEBUG_USBGECKO */