summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/arch/rlx/kernel/early_printk.c
blob: b1983af9c7120f0c7062394bc060e7f15f98c2f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2002, 2003, 06, 07 Ralf Baechle (ralf@linux-mips.org)
 * Copyright (C) 2007 MIPS Technologies, Inc.
 *   written by Ralf Baechle (ralf@linux-mips.org)
 */
#include <linux/console.h>
#include <linux/init.h>

#include <asm/setup.h>

#ifdef CONFIG_SERIAL_SC16IS7X0_CONSOLE
extern int __init early_sc16is7x0_init_i2c_and_check( void );
extern int __init early_sc16is7x0_setup(struct console * console, char * option);
static int early_sc16is7x0_workable = -1;
#endif

#include "bspchip.h"

//extern void prom_putchar(char);
int prom_putchar(char c)
{
#ifdef CONFIG_SERIAL_SC16IS7X0_CONSOLE
   extern unsigned int sc16is7x0_serial_out_i2c(int offset, int value);
   extern unsigned int sc16is7x0_serial_in_i2c(int offset);
#endif

#define UART0_BASE		0xB8002000
#define UART0_THR		(UART0_BASE + 0x000)
#define UART0_FCR		(UART0_BASE + 0x008)
#define UART0_LSR       (UART0_BASE + 0x014)
#define TXRST			0x04
#define CHAR_TRIGGER_14	0xC0
#define LSR_THRE		0x20
#define TxCHAR_AVAIL	0x00
#define TxCHAR_EMPTY	0x20
   unsigned int busy_cnt = 0;

#ifndef CONFIG_SERIAL_SC16IS7X0_CONSOLE
   do
   {
      /* Prevent Hanging */
      if (busy_cnt++ >= 30000)
      {
         /* Reset Tx FIFO */
         REG8(UART0_FCR) = TXRST | CHAR_TRIGGER_14;
         return 0;
      }
   } while ((REG8(UART0_LSR) & LSR_THRE) == TxCHAR_AVAIL);

   /* Send Character */
   REG8(UART0_THR) = c;
#endif
	
   // -------------------------------------------------------
   	
#ifdef CONFIG_SERIAL_SC16IS7X0_CONSOLE
   if( early_sc16is7x0_workable < 0 )
      return 0;
   
   #define MEM2REG( x )		( ( x - UART0_BASE ) / 4 )
   
   do
   {
      /* Prevent Hanging */
      if (busy_cnt++ >= 30000)
      {
         /* Reset Tx FIFO */
         sc16is7x0_serial_out_i2c( MEM2REG(UART0_FCR), TXRST | CHAR_TRIGGER_14 );
         
         return 0;
      }
   } while ((sc16is7x0_serial_in_i2c( MEM2REG(UART0_LSR) ) & LSR_THRE) == TxCHAR_AVAIL);

   /* Send Character */
   sc16is7x0_serial_out_i2c( MEM2REG(UART0_THR), c );
   
   #undef MEM2REG
#endif

   return 1;
}

static void __init
early_console_write(struct console *con, const char *s, unsigned n)
{
	while (n-- && *s) {
		if (*s == '\n')
			prom_putchar('\r');
		prom_putchar(*s);
		s++;
	}
}

static struct console early_console __initdata = {
	.name	= "early",
	.write	= early_console_write,
	.flags	= CON_PRINTBUFFER | CON_BOOT,
	.index	= -1
};

static int early_console_initialized __initdata;

void __init setup_early_printk(void)
{
	if (early_console_initialized)
		return;
	early_console_initialized = 1;

#ifdef CONFIG_SERIAL_SC16IS7X0_CONSOLE
	early_sc16is7x0_workable = early_sc16is7x0_setup( NULL, NULL );
#endif
	register_console(&early_console);
}