0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <stddef.h>
0011 #include "stdio.h"
0012 #include "types.h"
0013 #include "io.h"
0014 #include "ops.h"
0015
0016
0017 #define EXI_CLK_32MHZ 5
0018
0019 #define EXI_CSR 0x00
0020 #define EXI_CSR_CLKMASK (0x7<<4)
0021 #define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4)
0022 #define EXI_CSR_CSMASK (0x7<<7)
0023 #define EXI_CSR_CS_0 (0x1<<7)
0024
0025 #define EXI_CR 0x0c
0026 #define EXI_CR_TSTART (1<<0)
0027 #define EXI_CR_WRITE (1<<2)
0028 #define EXI_CR_READ_WRITE (2<<2)
0029 #define EXI_CR_TLEN(len) (((len)-1)<<4)
0030
0031 #define EXI_DATA 0x10
0032
0033
0034
0035 static void *ug_io_base;
0036
0037
0038 static u32 ug_io_transaction(u32 in)
0039 {
0040 u32 *csr_reg = ug_io_base + EXI_CSR;
0041 u32 *data_reg = ug_io_base + EXI_DATA;
0042 u32 *cr_reg = ug_io_base + EXI_CR;
0043 u32 csr, data, cr;
0044
0045
0046 csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
0047 out_be32(csr_reg, csr);
0048
0049
0050 data = in;
0051 out_be32(data_reg, data);
0052 cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
0053 out_be32(cr_reg, cr);
0054
0055 while (in_be32(cr_reg) & EXI_CR_TSTART)
0056 barrier();
0057
0058
0059 out_be32(csr_reg, 0);
0060
0061 data = in_be32(data_reg);
0062 return data;
0063 }
0064
0065 static int ug_is_txfifo_ready(void)
0066 {
0067 return ug_io_transaction(0xc0000000) & 0x04000000;
0068 }
0069
0070 static void ug_raw_putc(char ch)
0071 {
0072 ug_io_transaction(0xb0000000 | (ch << 20));
0073 }
0074
0075 static void ug_putc(char ch)
0076 {
0077 int count = 16;
0078
0079 if (!ug_io_base)
0080 return;
0081
0082 while (!ug_is_txfifo_ready() && count--)
0083 barrier();
0084 if (count >= 0)
0085 ug_raw_putc(ch);
0086 }
0087
0088 void ug_console_write(const char *buf, int len)
0089 {
0090 char *b = (char *)buf;
0091
0092 while (len--) {
0093 if (*b == '\n')
0094 ug_putc('\r');
0095 ug_putc(*b++);
0096 }
0097 }
0098
0099 static int ug_is_adapter_present(void)
0100 {
0101 if (!ug_io_base)
0102 return 0;
0103 return ug_io_transaction(0x90000000) == 0x04700000;
0104 }
0105
0106 static void *ug_grab_exi_io_base(void)
0107 {
0108 u32 v;
0109 void *devp;
0110
0111 devp = find_node_by_compatible(NULL, "nintendo,flipper-exi");
0112 if (devp == NULL)
0113 goto err_out;
0114 if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
0115 goto err_out;
0116
0117 return (void *)v;
0118
0119 err_out:
0120 return NULL;
0121 }
0122
0123 void *ug_probe(void)
0124 {
0125 void *exi_io_base;
0126 int i;
0127
0128 exi_io_base = ug_grab_exi_io_base();
0129 if (!exi_io_base)
0130 return NULL;
0131
0132
0133 for (i = 0; i < 2; i++) {
0134 ug_io_base = exi_io_base + 0x14 * i;
0135 if (ug_is_adapter_present())
0136 break;
0137 }
0138 if (i == 2)
0139 ug_io_base = NULL;
0140 return ug_io_base;
0141 }
0142