linux/arch/powerpc/boot/ugecon.c
Thomas Gleixner 2874c5fd28 treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152
Based on 1 normalized pattern(s):

  this program is free software you can redistribute it and or modify
  it under the terms of the gnu general public license as published by
  the free software foundation either version 2 of the license or at
  your option any later version

extracted by the scancode license scanner the SPDX license identifier

  GPL-2.0-or-later

has been chosen to replace the boilerplate/reference in 3029 file(s).

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Allison Randal <allison@lohutok.net>
Cc: linux-spdx@vger.kernel.org
Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-05-30 11:26:32 -07:00

143 lines
2.6 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* arch/powerpc/boot/ugecon.c
*
* USB Gecko bootwrapper console.
* Copyright (C) 2008-2009 The GameCube Linux Team
* Copyright (C) 2008,2009 Albert Herranz
*/
#include <stddef.h>
#include "stdio.h"
#include "types.h"
#include "io.h"
#include "ops.h"
#define EXI_CLK_32MHZ 5
#define EXI_CSR 0x00
#define EXI_CSR_CLKMASK (0x7<<4)
#define EXI_CSR_CLK_32MHZ (EXI_CLK_32MHZ<<4)
#define EXI_CSR_CSMASK (0x7<<7)
#define EXI_CSR_CS_0 (0x1<<7) /* Chip Select 001 */
#define EXI_CR 0x0c
#define EXI_CR_TSTART (1<<0)
#define EXI_CR_WRITE (1<<2)
#define EXI_CR_READ_WRITE (2<<2)
#define EXI_CR_TLEN(len) (((len)-1)<<4)
#define EXI_DATA 0x10
/* virtual address base for input/output, retrieved from device tree */
static void *ug_io_base;
static u32 ug_io_transaction(u32 in)
{
u32 *csr_reg = ug_io_base + EXI_CSR;
u32 *data_reg = ug_io_base + EXI_DATA;
u32 *cr_reg = ug_io_base + EXI_CR;
u32 csr, data, cr;
/* select */
csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
out_be32(csr_reg, csr);
/* read/write */
data = in;
out_be32(data_reg, data);
cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
out_be32(cr_reg, cr);
while (in_be32(cr_reg) & EXI_CR_TSTART)
barrier();
/* deselect */
out_be32(csr_reg, 0);
data = in_be32(data_reg);
return data;
}
static int ug_is_txfifo_ready(void)
{
return ug_io_transaction(0xc0000000) & 0x04000000;
}
static void ug_raw_putc(char ch)
{
ug_io_transaction(0xb0000000 | (ch << 20));
}
static void ug_putc(char ch)
{
int count = 16;
if (!ug_io_base)
return;
while (!ug_is_txfifo_ready() && count--)
barrier();
if (count >= 0)
ug_raw_putc(ch);
}
void ug_console_write(const char *buf, int len)
{
char *b = (char *)buf;
while (len--) {
if (*b == '\n')
ug_putc('\r');
ug_putc(*b++);
}
}
static int ug_is_adapter_present(void)
{
if (!ug_io_base)
return 0;
return ug_io_transaction(0x90000000) == 0x04700000;
}
static void *ug_grab_exi_io_base(void)
{
u32 v;
void *devp;
devp = find_node_by_compatible(NULL, "nintendo,flipper-exi");
if (devp == NULL)
goto err_out;
if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v))
goto err_out;
return (void *)v;
err_out:
return NULL;
}
void *ug_probe(void)
{
void *exi_io_base;
int i;
exi_io_base = ug_grab_exi_io_base();
if (!exi_io_base)
return NULL;
/* look for a usbgecko on memcard slots A and B */
for (i = 0; i < 2; i++) {
ug_io_base = exi_io_base + 0x14 * i;
if (ug_is_adapter_present())
break;
}
if (i == 2)
ug_io_base = NULL;
return ug_io_base;
}