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