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