1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Joshua Henderson <joshua.henderson@microchip.com>
4*4882a593Smuzhiyun * Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun #include <asm/mach-pic32/pic32.h>
7*4882a593Smuzhiyun #include <asm/fw/fw.h>
8*4882a593Smuzhiyun #include <asm/setup.h>
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include "pic32mzda.h"
11*4882a593Smuzhiyun #include "early_pin.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /* Default early console parameters */
14*4882a593Smuzhiyun #define EARLY_CONSOLE_PORT 1
15*4882a593Smuzhiyun #define EARLY_CONSOLE_BAUDRATE 115200
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define UART_ENABLE BIT(15)
18*4882a593Smuzhiyun #define UART_ENABLE_RX BIT(12)
19*4882a593Smuzhiyun #define UART_ENABLE_TX BIT(10)
20*4882a593Smuzhiyun #define UART_TX_FULL BIT(9)
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* UART1(x == 0) - UART6(x == 5) */
23*4882a593Smuzhiyun #define UART_BASE(x) ((x) * 0x0200)
24*4882a593Smuzhiyun #define U_MODE(x) UART_BASE(x)
25*4882a593Smuzhiyun #define U_STA(x) (UART_BASE(x) + 0x10)
26*4882a593Smuzhiyun #define U_TXR(x) (UART_BASE(x) + 0x20)
27*4882a593Smuzhiyun #define U_BRG(x) (UART_BASE(x) + 0x40)
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun static void __iomem *uart_base;
30*4882a593Smuzhiyun static int console_port = -1;
31*4882a593Smuzhiyun
configure_uart_pins(int port)32*4882a593Smuzhiyun static int __init configure_uart_pins(int port)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun switch (port) {
35*4882a593Smuzhiyun case 1:
36*4882a593Smuzhiyun pic32_pps_input(IN_FUNC_U2RX, IN_RPB0);
37*4882a593Smuzhiyun pic32_pps_output(OUT_FUNC_U2TX, OUT_RPG9);
38*4882a593Smuzhiyun break;
39*4882a593Smuzhiyun case 5:
40*4882a593Smuzhiyun pic32_pps_input(IN_FUNC_U6RX, IN_RPD0);
41*4882a593Smuzhiyun pic32_pps_output(OUT_FUNC_U6TX, OUT_RPB8);
42*4882a593Smuzhiyun break;
43*4882a593Smuzhiyun default:
44*4882a593Smuzhiyun return -1;
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun return 0;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun
configure_uart(int port,int baud)50*4882a593Smuzhiyun static void __init configure_uart(int port, int baud)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun u32 pbclk;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun pbclk = pic32_get_pbclk(2);
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun __raw_writel(0, uart_base + U_MODE(port));
57*4882a593Smuzhiyun __raw_writel(((pbclk / baud) / 16) - 1, uart_base + U_BRG(port));
58*4882a593Smuzhiyun __raw_writel(UART_ENABLE, uart_base + U_MODE(port));
59*4882a593Smuzhiyun __raw_writel(UART_ENABLE_TX | UART_ENABLE_RX,
60*4882a593Smuzhiyun uart_base + PIC32_SET(U_STA(port)));
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
setup_early_console(int port,int baud)63*4882a593Smuzhiyun static void __init setup_early_console(int port, int baud)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun if (configure_uart_pins(port))
66*4882a593Smuzhiyun return;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun console_port = port;
69*4882a593Smuzhiyun configure_uart(console_port, baud);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
pic32_getcmdline(void)72*4882a593Smuzhiyun static char * __init pic32_getcmdline(void)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun /*
75*4882a593Smuzhiyun * arch_mem_init() has not been called yet, so we don't have a real
76*4882a593Smuzhiyun * command line setup if using CONFIG_CMDLINE_BOOL.
77*4882a593Smuzhiyun */
78*4882a593Smuzhiyun #ifdef CONFIG_CMDLINE_OVERRIDE
79*4882a593Smuzhiyun return CONFIG_CMDLINE;
80*4882a593Smuzhiyun #else
81*4882a593Smuzhiyun return fw_getcmdline();
82*4882a593Smuzhiyun #endif
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
get_port_from_cmdline(char * arch_cmdline)85*4882a593Smuzhiyun static int __init get_port_from_cmdline(char *arch_cmdline)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun char *s;
88*4882a593Smuzhiyun int port = -1;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (!arch_cmdline || *arch_cmdline == '\0')
91*4882a593Smuzhiyun goto _out;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun s = strstr(arch_cmdline, "earlyprintk=");
94*4882a593Smuzhiyun if (s) {
95*4882a593Smuzhiyun s = strstr(s, "ttyS");
96*4882a593Smuzhiyun if (s)
97*4882a593Smuzhiyun s += 4;
98*4882a593Smuzhiyun else
99*4882a593Smuzhiyun goto _out;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun port = (*s) - '0';
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun _out:
105*4882a593Smuzhiyun return port;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
get_baud_from_cmdline(char * arch_cmdline)108*4882a593Smuzhiyun static int __init get_baud_from_cmdline(char *arch_cmdline)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun char *s;
111*4882a593Smuzhiyun int baud = -1;
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun if (!arch_cmdline || *arch_cmdline == '\0')
114*4882a593Smuzhiyun goto _out;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun s = strstr(arch_cmdline, "earlyprintk=");
117*4882a593Smuzhiyun if (s) {
118*4882a593Smuzhiyun s = strstr(s, "ttyS");
119*4882a593Smuzhiyun if (s)
120*4882a593Smuzhiyun s += 6;
121*4882a593Smuzhiyun else
122*4882a593Smuzhiyun goto _out;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun baud = 0;
125*4882a593Smuzhiyun while (*s >= '0' && *s <= '9')
126*4882a593Smuzhiyun baud = baud * 10 + *s++ - '0';
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun _out:
130*4882a593Smuzhiyun return baud;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun
fw_init_early_console(void)133*4882a593Smuzhiyun void __init fw_init_early_console(void)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun char *arch_cmdline = pic32_getcmdline();
136*4882a593Smuzhiyun int baud, port;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun uart_base = ioremap(PIC32_BASE_UART, 0xc00);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun baud = get_baud_from_cmdline(arch_cmdline);
141*4882a593Smuzhiyun port = get_port_from_cmdline(arch_cmdline);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (port == -1)
144*4882a593Smuzhiyun port = EARLY_CONSOLE_PORT;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun if (baud == -1)
147*4882a593Smuzhiyun baud = EARLY_CONSOLE_BAUDRATE;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun setup_early_console(port, baud);
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
prom_putchar(char c)152*4882a593Smuzhiyun void prom_putchar(char c)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun if (console_port >= 0) {
155*4882a593Smuzhiyun while (__raw_readl(
156*4882a593Smuzhiyun uart_base + U_STA(console_port)) & UART_TX_FULL)
157*4882a593Smuzhiyun ;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun __raw_writel(c, uart_base + U_TXR(console_port));
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun }
162