uart_cpu_powerpc.c revision 266005
1290001Sglebius/*- 2290001Sglebius * Copyright (c) 2006 Marcel Moolenaar 3290001Sglebius * All rights reserved. 4290001Sglebius * 5290001Sglebius * Redistribution and use in source and binary forms, with or without 6290001Sglebius * modification, are permitted provided that the following conditions 7290001Sglebius * are met: 8290001Sglebius * 9290001Sglebius * 1. Redistributions of source code must retain the above copyright 10290001Sglebius * notice, this list of conditions and the following disclaimer. 11290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright 12290001Sglebius * notice, this list of conditions and the following disclaimer in the 13290001Sglebius * documentation and/or other materials provided with the distribution. 14290001Sglebius * 15290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16290001Sglebius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17290001Sglebius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18290001Sglebius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19290001Sglebius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20290001Sglebius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21290001Sglebius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22290001Sglebius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23290001Sglebius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24290001Sglebius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25290001Sglebius */ 26290001Sglebius 27290001Sglebius#include <sys/cdefs.h> 28290001Sglebius__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_powerpc.c 266005 2014-05-14 04:57:55Z ian $"); 29290001Sglebius 30290001Sglebius#include <sys/param.h> 31290001Sglebius#include <sys/systm.h> 32290001Sglebius#include <vm/vm.h> 33290001Sglebius#include <vm/pmap.h> 34290001Sglebius 35290001Sglebius#include <machine/bus.h> 36290001Sglebius#include <machine/ofw_machdep.h> 37290001Sglebius 38290001Sglebius#include <dev/ofw/openfirm.h> 39290001Sglebius#include <dev/uart/uart.h> 40290001Sglebius#include <dev/uart/uart_cpu.h> 41290001Sglebius 42290001Sglebiusbus_space_tag_t uart_bus_space_io = &bs_le_tag; 43290001Sglebiusbus_space_tag_t uart_bus_space_mem = &bs_le_tag; 44290001Sglebius 45290001Sglebiusint 46290001Sglebiusuart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) 47290001Sglebius{ 48290001Sglebius 49290001Sglebius return ((pmap_kextract(b1->bsh) == pmap_kextract(b2->bsh)) ? 1 : 0); 50290001Sglebius} 51290001Sglebius 52290001Sglebiusstatic int 53290001Sglebiusofw_get_uart_console(phandle_t opts, phandle_t *result, const char *inputdev, 54290001Sglebius const char *outputdev) 55290001Sglebius{ 56290001Sglebius char buf[64]; 57290001Sglebius phandle_t input; 58290001Sglebius 59290001Sglebius if (OF_getprop(opts, inputdev, buf, sizeof(buf)) == -1) 60290001Sglebius return (ENXIO); 61290001Sglebius input = OF_finddevice(buf); 62290001Sglebius if (input == -1) 63290001Sglebius return (ENXIO); 64290001Sglebius 65290001Sglebius if (outputdev != NULL) { 66290001Sglebius if (OF_getprop(opts, outputdev, buf, sizeof(buf)) == -1) 67290001Sglebius return (ENXIO); 68290001Sglebius if (OF_finddevice(buf) != input) 69290001Sglebius return (ENXIO); 70290001Sglebius } 71290001Sglebius 72290001Sglebius *result = input; 73290001Sglebius return (0); 74290001Sglebius} 75290001Sglebius 76290001Sglebiusstatic int 77290001Sglebiusofw_get_console_phandle_path(phandle_t node, phandle_t *result, 78290001Sglebius const char *prop) 79290001Sglebius{ 80290001Sglebius union { 81290001Sglebius char buf[64]; 82290001Sglebius phandle_t ref; 83290001Sglebius } field; 84290001Sglebius phandle_t output; 85290001Sglebius ssize_t size; 86290001Sglebius 87290001Sglebius size = OF_getproplen(node, prop); 88290001Sglebius if (size == -1) 89290001Sglebius return (ENXIO); 90290001Sglebius OF_getprop(node, prop, &field, sizeof(field)); 91290001Sglebius 92290001Sglebius /* This property might be a phandle or might be a path. Hooray. */ 93290001Sglebius 94290001Sglebius output = -1; 95290001Sglebius if (field.buf[size - 1] == 0) 96290001Sglebius output = OF_finddevice(field.buf); 97290001Sglebius if (output == -1 && size == 4) 98290001Sglebius output = OF_xref_phandle(field.ref); 99290001Sglebius 100290001Sglebius if (output != -1) { 101290001Sglebius *result = output; 102290001Sglebius return (0); 103290001Sglebius } 104290001Sglebius 105290001Sglebius return (ENXIO); 106290001Sglebius} 107290001Sglebius 108290001Sglebiusint 109290001Sglebiusuart_cpu_getdev(int devtype, struct uart_devinfo *di) 110290001Sglebius{ 111290001Sglebius char buf[64]; 112290001Sglebius struct uart_class *class; 113290001Sglebius phandle_t input, opts, chosen; 114290001Sglebius int error; 115290001Sglebius 116290001Sglebius class = &uart_z8530_class; 117290001Sglebius if (class == NULL) 118290001Sglebius return (ENXIO); 119290001Sglebius 120290001Sglebius opts = OF_finddevice("/options"); 121290001Sglebius chosen = OF_finddevice("/chosen"); 122290001Sglebius switch (devtype) { 123290001Sglebius case UART_DEV_CONSOLE: 124290001Sglebius error = ENXIO; 125290001Sglebius if (chosen != -1 && error != 0) 126290001Sglebius error = ofw_get_uart_console(chosen, &input, 127290001Sglebius "stdout-path", NULL); 128290001Sglebius if (chosen != -1 && error != 0) 129290001Sglebius error = ofw_get_uart_console(chosen, &input, 130290001Sglebius "linux,stdout-path", NULL); 131290001Sglebius if (chosen != -1 && error != 0) 132290001Sglebius error = ofw_get_console_phandle_path(chosen, &input, 133290001Sglebius "stdout"); 134290001Sglebius if (chosen != -1 && error != 0) 135290001Sglebius error = ofw_get_uart_console(chosen, &input, 136290001Sglebius "stdin-path", NULL); 137290001Sglebius if (chosen != -1 && error != 0) 138290001Sglebius error = ofw_get_console_phandle_path(chosen, &input, 139290001Sglebius "stdin"); 140290001Sglebius if (opts != -1 && error != 0) 141290001Sglebius error = ofw_get_uart_console(opts, &input, 142290001Sglebius "input-device", "output-device"); 143290001Sglebius if (opts != -1 && error != 0) 144290001Sglebius error = ofw_get_uart_console(opts, &input, 145 "input-device-1", "output-device-1"); 146 if (error != 0) { 147 input = OF_finddevice("serial0"); /* Last ditch */ 148 if (input == -1) 149 error = (ENXIO); 150 } 151 152 if (error != 0) 153 return (error); 154 break; 155 case UART_DEV_DBGPORT: 156 if (!getenv_string("hw.uart.dbgport", buf, sizeof(buf))) 157 return (ENXIO); 158 input = OF_finddevice(buf); 159 if (input == -1) 160 return (ENXIO); 161 break; 162 default: 163 return (EINVAL); 164 } 165 166 if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) 167 return (ENXIO); 168 if (strcmp(buf, "serial") != 0) 169 return (ENXIO); 170 if (OF_getprop(input, "compatible", buf, sizeof(buf)) == -1) 171 return (ENXIO); 172 173 if (strncmp(buf, "chrp,es", 7) == 0) { 174 class = &uart_z8530_class; 175 di->bas.regshft = 4; 176 di->bas.chan = 1; 177 } else if (strcmp(buf,"ns16550") == 0 || strcmp(buf,"ns8250") == 0) { 178 class = &uart_ns8250_class; 179 di->bas.regshft = 0; 180 di->bas.chan = 0; 181 } else 182 return (ENXIO); 183 184 error = OF_decode_addr(input, 0, &di->bas.bst, &di->bas.bsh); 185 if (error) 186 return (error); 187 188 di->ops = uart_getops(class); 189 190 if (OF_getprop(input, "clock-frequency", &di->bas.rclk, 191 sizeof(di->bas.rclk)) == -1) 192 di->bas.rclk = 230400; 193 if (OF_getprop(input, "current-speed", &di->baudrate, 194 sizeof(di->baudrate)) == -1) 195 di->baudrate = 0; 196 OF_getprop(input, "reg-shift", &di->bas.regshft, 197 sizeof(di->bas.regshft)); 198 199 di->databits = 8; 200 di->stopbits = 1; 201 di->parity = UART_PARITY_NONE; 202 return (0); 203} 204 205