Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * arch/powerpc/boot/ugecon.c
0004  *
0005  * USB Gecko bootwrapper console.
0006  * Copyright (C) 2008-2009 The GameCube Linux Team
0007  * Copyright (C) 2008,2009 Albert Herranz
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)  /* Chip Select 001 */
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 /* virtual address base for input/output, retrieved from device tree */
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     /* select */
0046     csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
0047     out_be32(csr_reg, csr);
0048 
0049     /* read/write */
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     /* deselect */
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     /* look for a usbgecko on memcard slots A and B */
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