1/*
2 *  This program is free software; you can redistribute it and/or modify it
3 *  under the terms of the GNU General Public License version 2 as published
4 *  by the Free Software Foundation.
5 *
6 *  Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
7 */
8
9#include <linux/io.h>
10#include <linux/serial_reg.h>
11
12#include <asm/addrspace.h>
13
14#ifdef CONFIG_SOC_RT288X
15#define EARLY_UART_BASE		0x300c00
16#define CHIPID_BASE		0x300004
17#elif defined(CONFIG_SOC_MT7621)
18#define EARLY_UART_BASE		0x1E000c00
19#define CHIPID_BASE		0x1E000004
20#else
21#define EARLY_UART_BASE		0x10000c00
22#define CHIPID_BASE		0x10000004
23#endif
24
25#define MT7628_CHIP_NAME1	0x20203832
26
27#define UART_REG_TX		0x04
28#define UART_REG_LSR		0x14
29#define UART_REG_LSR_RT2880	0x1c
30
31static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE);
32static __iomem void *chipid_membase = (__iomem void *) KSEG1ADDR(CHIPID_BASE);
33
34static inline void uart_w32(u32 val, unsigned reg)
35{
36	__raw_writel(val, uart_membase + reg);
37}
38
39static inline u32 uart_r32(unsigned reg)
40{
41	return __raw_readl(uart_membase + reg);
42}
43
44static inline int soc_is_mt7628(void)
45{
46	return IS_ENABLED(CONFIG_SOC_MT7620) &&
47		(__raw_readl(chipid_membase) == MT7628_CHIP_NAME1);
48}
49
50void prom_putchar(unsigned char ch)
51{
52	if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) {
53		uart_w32(ch, UART_TX);
54		while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
55			;
56	} else {
57		while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0)
58			;
59		uart_w32(ch, UART_REG_TX);
60		while ((uart_r32(UART_REG_LSR_RT2880) & UART_LSR_THRE) == 0)
61			;
62	}
63}
64