1/*- 2 * Copyright (c) 2016 Michael Zhilin <mizhka@gmail.com> 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD$"); 30 31#include "opt_uart.h" 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/bus.h> 36#include <sys/cons.h> 37#include <sys/lock.h> 38#include <sys/mutex.h> 39 40#include <machine/bus.h> 41 42#include <dev/bhnd/cores/chipc/chipcreg.h> 43 44#include <dev/uart/uart.h> 45#include <dev/uart/uart_bus.h> 46#include <dev/uart/uart_cpu.h> 47 48#ifdef CFE 49#include <dev/cfe/cfe_api.h> 50#include <dev/cfe/cfe_ioctl.h> 51#include <dev/cfe/cfe_error.h> 52#endif 53 54#include "bcm_machdep.h" 55 56bus_space_tag_t uart_bus_space_io; 57bus_space_tag_t uart_bus_space_mem; 58 59static struct uart_class *chipc_uart_class = &uart_ns8250_class; 60 61#define CHIPC_UART_BAUDRATE 115200 62 63int 64uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) 65{ 66 return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); 67} 68 69static int 70uart_cpu_init(struct uart_devinfo *di, u_int uart, int baudrate) 71{ 72 if (uart >= CHIPC_UART_MAX) 73 return (EINVAL); 74 75 di->ops = uart_getops(chipc_uart_class); 76 di->bas.chan = 0; 77 di->bas.bst = uart_bus_space_mem; 78 di->bas.bsh = (bus_space_handle_t) BCM_CORE_ADDR(bcm_get_platform(), 79 cc_addr, CHIPC_UART(uart)); 80 di->bas.regshft = 0; 81 di->bas.rclk = bcm_get_uart_rclk(bcm_get_platform()); 82 di->baudrate = baudrate; 83 di->databits = 8; 84 di->stopbits = 1; 85 di->parity = UART_PARITY_NONE; 86 87 return (0); 88} 89 90#ifdef CFE 91static int 92uart_getenv_cfe(int devtype, struct uart_devinfo *di) 93{ 94 char device[sizeof("uartXX")]; 95 int baud, fd, len; 96 int ret; 97 u_int uart; 98 99 /* CFE only vends console configuration */ 100 if (devtype != UART_DEV_CONSOLE) 101 return (ENODEV); 102 103 /* Fetch console device */ 104 ret = cfe_getenv("BOOT_CONSOLE", device, sizeof(device)); 105 if (ret != CFE_OK) 106 return (ENXIO); 107 108 /* Parse serial console unit. Fails on non-uart devices. */ 109 if (sscanf(device, "uart%u", &uart) != 1) 110 return (ENXIO); 111 112 /* Fetch device handle */ 113 fd = bcm_get_platform()->cfe_console; 114 if (fd < 0) 115 return (ENXIO); 116 117 /* Fetch serial configuration */ 118 ret = cfe_ioctl(fd, IOCTL_SERIAL_GETSPEED, (unsigned char *)&baud, 119 sizeof(baud), &len, 0); 120 if (ret != CFE_OK) 121 baud = CHIPC_UART_BAUDRATE; 122 123 /* Initialize device info */ 124 return (uart_cpu_init(di, uart, baud)); 125} 126#endif /* CFE */ 127 128int 129uart_cpu_getdev(int devtype, struct uart_devinfo *di) 130{ 131 int ivar; 132 133 uart_bus_space_io = NULL; 134 uart_bus_space_mem = mips_bus_space_generic; 135 136#ifdef CFE 137 /* Check the CFE environment */ 138 if (uart_getenv_cfe(devtype, di) == 0) 139 return (0); 140#endif /* CFE */ 141 142 /* Check the kernel environment. */ 143 if (uart_getenv(devtype, di, chipc_uart_class) == 0) 144 return (0); 145 146 /* Scan the device hints for the first matching device */ 147 for (u_int i = 0; i < CHIPC_UART_MAX; i++) { 148 if (resource_int_value("uart", i, "flags", &ivar)) 149 continue; 150 151 /* Check usability */ 152 if (devtype == UART_DEV_CONSOLE && !UART_FLAGS_CONSOLE(ivar)) 153 continue; 154 155 if (devtype == UART_DEV_DBGPORT && !UART_FLAGS_DBGPORT(ivar)) 156 continue; 157 158 if (resource_int_value("uart", i, "disabled", &ivar) == 0 && 159 ivar == 0) 160 continue; 161 162 /* Found */ 163 if (resource_int_value("uart", i, "baud", &ivar) != 0) 164 ivar = CHIPC_UART_BAUDRATE; 165 166 return (uart_cpu_init(di, i, ivar)); 167 } 168 169 /* Default to uart0/115200 */ 170 return (uart_cpu_init(di, 0, CHIPC_UART_BAUDRATE)); 171} 172