uart_cpu_powerpc.c revision 266020
155714Skris/*- 255714Skris * Copyright (c) 2006 Marcel Moolenaar 355714Skris * All rights reserved. 455714Skris * 555714Skris * Redistribution and use in source and binary forms, with or without 655714Skris * modification, are permitted provided that the following conditions 755714Skris * are met: 8280304Sjkim * 955714Skris * 1. Redistributions of source code must retain the above copyright 1055714Skris * notice, this list of conditions and the following disclaimer. 1155714Skris * 2. Redistributions in binary form must reproduce the above copyright 1255714Skris * notice, this list of conditions and the following disclaimer in the 1355714Skris * documentation and/or other materials provided with the distribution. 1455714Skris * 15280304Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1655714Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1755714Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1855714Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1955714Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2055714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2155714Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22280304Sjkim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2355714Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2455714Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2555714Skris */ 2655714Skris 2755714Skris#include <sys/cdefs.h> 2855714Skris__FBSDID("$FreeBSD: stable/10/sys/dev/uart/uart_cpu_powerpc.c 266020 2014-05-14 14:17:51Z ian $"); 2955714Skris 3055714Skris#include <sys/param.h> 3155714Skris#include <sys/systm.h> 3255714Skris#include <vm/vm.h> 3355714Skris#include <vm/pmap.h> 3455714Skris 3555714Skris#include <machine/bus.h> 3655714Skris#include <machine/ofw_machdep.h> 37280304Sjkim 3855714Skris#include <dev/ofw/openfirm.h> 3955714Skris#include <dev/uart/uart.h> 40280304Sjkim#include <dev/uart/uart_cpu.h> 4155714Skris 4255714Skrisbus_space_tag_t uart_bus_space_io = &bs_le_tag; 4355714Skrisbus_space_tag_t uart_bus_space_mem = &bs_le_tag; 4455714Skris 4555714Skrisint 4655714Skrisuart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) 4755714Skris{ 4855714Skris 4955714Skris return ((pmap_kextract(b1->bsh) == pmap_kextract(b2->bsh)) ? 1 : 0); 5055714Skris} 5155714Skris 52280304Sjkimstatic int 5355714Skrisofw_get_uart_console(phandle_t opts, phandle_t *result, const char *inputdev, 5455714Skris const char *outputdev) 5555714Skris{ 5655714Skris char buf[64]; 5755714Skris phandle_t input; 5855714Skris 5955714Skris if (OF_getprop(opts, inputdev, buf, sizeof(buf)) == -1) 6055714Skris return (ENXIO); 61160814Ssimon input = OF_finddevice(buf); 62160814Ssimon if (input == -1) 63160814Ssimon return (ENXIO); 64280304Sjkim 65280304Sjkim if (outputdev != NULL) { 66280304Sjkim if (OF_getprop(opts, outputdev, buf, sizeof(buf)) == -1) 67280304Sjkim return (ENXIO); 68280304Sjkim if (OF_finddevice(buf) != input) 69280304Sjkim return (ENXIO); 70280304Sjkim } 7155714Skris 72109998Smarkm *result = input; 73280304Sjkim return (0); 74280304Sjkim} 75280304Sjkim 76109998Smarkmstatic int 77280304Sjkimofw_get_console_phandle_path(phandle_t node, phandle_t *result, 78280304Sjkim const char *prop) 79280304Sjkim{ 80280304Sjkim union { 81109998Smarkm char buf[64]; 82280304Sjkim phandle_t ref; 83280304Sjkim } field; 84280304Sjkim phandle_t output; 85280304Sjkim ssize_t size; 86109998Smarkm 87280304Sjkim size = OF_getproplen(node, prop); 88280304Sjkim if (size == -1) 89280304Sjkim return (ENXIO); 90280304Sjkim OF_getprop(node, prop, &field, sizeof(field)); 91280304Sjkim 92280304Sjkim /* This property might be either a ihandle or path. Hooray. */ 93280304Sjkim 94280304Sjkim output = -1; 95280304Sjkim if (field.buf[size - 1] == 0) 96280304Sjkim output = OF_finddevice(field.buf); 97280304Sjkim if (output == -1 && size == 4) 98280304Sjkim output = OF_instance_to_package(field.ref); 99280304Sjkim 100280304Sjkim if (output != -1) { 10155714Skris *result = output; 102109998Smarkm return (0); 103280304Sjkim } 104280304Sjkim 105280304Sjkim return (ENXIO); 10655714Skris} 107 108int 109uart_cpu_getdev(int devtype, struct uart_devinfo *di) 110{ 111 char buf[64]; 112 struct uart_class *class; 113 phandle_t input, opts, chosen; 114 int error; 115 116 class = &uart_z8530_class; 117 if (class == NULL) 118 return (ENXIO); 119 120 opts = OF_finddevice("/options"); 121 chosen = OF_finddevice("/chosen"); 122 switch (devtype) { 123 case UART_DEV_CONSOLE: 124 error = ENXIO; 125 if (chosen != -1 && error != 0) 126 error = ofw_get_uart_console(chosen, &input, 127 "stdout-path", NULL); 128 if (chosen != -1 && error != 0) 129 error = ofw_get_uart_console(chosen, &input, 130 "linux,stdout-path", NULL); 131 if (chosen != -1 && error != 0) 132 error = ofw_get_console_phandle_path(chosen, &input, 133 "stdout"); 134 if (chosen != -1 && error != 0) 135 error = ofw_get_uart_console(chosen, &input, 136 "stdin-path", NULL); 137 if (chosen != -1 && error != 0) 138 error = ofw_get_console_phandle_path(chosen, &input, 139 "stdin"); 140 if (opts != -1 && error != 0) 141 error = ofw_get_uart_console(opts, &input, 142 "input-device", "output-device"); 143 if (opts != -1 && error != 0) 144 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