1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2019 Axiado Corporation 5 * All rights reserved. 6 * 7 * This software was developed in part by Kristof Provost under contract for 8 * Axiado Corporation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/bus.h> 35 #include <sys/kernel.h> 36 #include <sys/lock.h> 37 #include <sys/module.h> 38 #include <sys/mutex.h> 39 #include <sys/rman.h> 40 41 #include <machine/bus.h> 42 #include <machine/cpu.h> 43 44 #include <dev/extres/clk/clk.h> 45 46 #include <dev/ofw/ofw_bus.h> 47 #include <dev/ofw/ofw_bus_subr.h> 48 #include <dev/ofw/openfirm.h> 49 50 #include <dev/uart/uart.h> 51 #include <dev/uart/uart_bus.h> 52 #include <dev/uart/uart_cpu.h> 53 #include <dev/uart/uart_cpu_fdt.h> 54 55 #include "uart_if.h" 56 57 #define SFUART_TXDATA 0x00 58 #define SFUART_TXDATA_FULL (1 << 31) 59 #define SFUART_RXDATA 0x04 60 #define SFUART_RXDATA_EMPTY (1 << 31) 61 #define SFUART_TXCTRL 0x08 62 #define SFUART_TXCTRL_ENABLE 0x01 63 #define SFUART_TXCTRL_NSTOP 0x02 64 #define SFUART_TXCTRL_TXCNT 0x70000 65 #define SFUART_TXCTRL_TXCNT_SHIFT 16 66 #define SFUART_RXCTRL 0x0c 67 #define SFUART_RXCTRL_ENABLE 0x01 68 #define SFUART_RXCTRL_RXCNT 0x70000 69 #define SFUART_RXCTRL_RXCNT_SHIFT 16 70 #define SFUART_IRQ_ENABLE 0x10 71 #define SFUART_IRQ_ENABLE_TXWM 0x01 72 #define SFUART_IRQ_ENABLE_RXWM 0x02 73 #define SFUART_IRQ_PENDING 0x14 74 #define SFUART_IRQ_PENDING_TXWM 0x01 75 #define SFUART_IRQ_PENDING_RXQM 0x02 76 #define SFUART_DIV 0x18 77 #define SFUART_REGS_SIZE 0x1c 78 79 #define SFUART_RX_FIFO_DEPTH 8 80 #define SFUART_TX_FIFO_DEPTH 8 81 82 struct sfuart_softc { 83 struct uart_softc uart_softc; 84 clk_t clk; 85 }; 86 87 static int 88 sfuart_probe(struct uart_bas *bas) 89 { 90 91 bas->regiowidth = 4; 92 93 return (0); 94 } 95 96 static void 97 sfuart_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, 98 int parity) 99 { 100 uint32_t reg; 101 102 uart_setreg(bas, SFUART_IRQ_ENABLE, 0); 103 104 /* Enable RX and configure the watermark so that we get an interrupt 105 * when a single character arrives (if interrupts are enabled). */ 106 reg = SFUART_RXCTRL_ENABLE; 107 reg |= (0 << SFUART_RXCTRL_RXCNT_SHIFT); 108 uart_setreg(bas, SFUART_RXCTRL, reg); 109 110 /* Enable TX and configure the watermark so that we get an interrupt 111 * when there's room for one more character in the TX fifo (if 112 * interrupts are enabled). */ 113 reg = SFUART_TXCTRL_ENABLE; 114 reg |= (1 << SFUART_TXCTRL_TXCNT_SHIFT); 115 if (stopbits == 2) 116 reg |= SFUART_TXCTRL_NSTOP; 117 uart_setreg(bas, SFUART_TXCTRL, reg); 118 119 /* Don't touch DIV. Assume that's set correctly until we can 120 * reconfigure. */ 121 } 122 123 static void 124 sfuart_putc(struct uart_bas *bas, int c) 125 { 126 127 while ((uart_getreg(bas, SFUART_TXDATA) & SFUART_TXDATA_FULL) 128 != 0) 129 cpu_spinwait(); 130 131 uart_setreg(bas, SFUART_TXDATA, c); 132 } 133 134 static int 135 sfuart_rxready(struct uart_bas *bas) 136 { 137 /* 138 * Unfortunately the FIFO empty flag is in the FIFO data register so 139 * reading it would dequeue the character. Instead, rely on the fact 140 * we've configured the watermark to be 0 and that interrupts are off 141 * when using the low-level console function, and read the interrupt 142 * pending state instead. 143 */ 144 return ((uart_getreg(bas, SFUART_IRQ_PENDING) & 145 SFUART_IRQ_PENDING_RXQM) != 0); 146 } 147 148 static int 149 sfuart_getc(struct uart_bas *bas, struct mtx *hwmtx) 150 { 151 int c; 152 153 uart_lock(hwmtx); 154 155 while (((c = uart_getreg(bas, SFUART_RXDATA)) & 156 SFUART_RXDATA_EMPTY) != 0) { 157 uart_unlock(hwmtx); 158 DELAY(4); 159 uart_lock(hwmtx); 160 } 161 162 uart_unlock(hwmtx); 163 164 return (c & 0xff); 165 } 166 167 static int 168 sfuart_bus_probe(struct uart_softc *sc) 169 { 170 int error; 171 172 error = sfuart_probe(&sc->sc_bas); 173 if (error) 174 return (error); 175 176 sc->sc_rxfifosz = SFUART_RX_FIFO_DEPTH; 177 sc->sc_txfifosz = SFUART_TX_FIFO_DEPTH; 178 sc->sc_hwiflow = 0; 179 sc->sc_hwoflow = 0; 180 181 device_set_desc(sc->sc_dev, "SiFive UART"); 182 183 return (0); 184 } 185 186 static int 187 sfuart_bus_attach(struct uart_softc *sc) 188 { 189 struct uart_bas *bas; 190 struct sfuart_softc *sfsc; 191 uint64_t freq; 192 uint32_t reg; 193 int error; 194 195 sfsc = (struct sfuart_softc *)sc; 196 bas = &sc->sc_bas; 197 198 error = clk_get_by_ofw_index(sc->sc_dev, 0, 0, &sfsc->clk); 199 if (error) { 200 device_printf(sc->sc_dev, "couldn't allocate clock\n"); 201 return (ENXIO); 202 } 203 204 error = clk_enable(sfsc->clk); 205 if (error) { 206 device_printf(sc->sc_dev, "couldn't enable clock\n"); 207 return (ENXIO); 208 } 209 210 error = clk_get_freq(sfsc->clk, &freq); 211 if (error || freq == 0) { 212 clk_disable(sfsc->clk); 213 device_printf(sc->sc_dev, "couldn't get clock frequency\n"); 214 return (ENXIO); 215 } 216 217 bas->rclk = freq; 218 219 /* Enable RX/RX */ 220 reg = SFUART_RXCTRL_ENABLE; 221 reg |= (0 << SFUART_RXCTRL_RXCNT_SHIFT); 222 uart_setreg(bas, SFUART_RXCTRL, reg); 223 224 reg = SFUART_TXCTRL_ENABLE; 225 reg |= (1 << SFUART_TXCTRL_TXCNT_SHIFT); 226 uart_setreg(bas, SFUART_TXCTRL, reg); 227 228 /* Enable RX interrupt */ 229 uart_setreg(bas, SFUART_IRQ_ENABLE, SFUART_IRQ_ENABLE_RXWM); 230 231 return (0); 232 } 233 234 static int 235 sfuart_bus_detach(struct uart_softc *sc) 236 { 237 struct sfuart_softc *sfsc; 238 struct uart_bas *bas; 239 240 sfsc = (struct sfuart_softc *)sc; 241 bas = &sc->sc_bas; 242 243 /* Disable RX/TX */ 244 uart_setreg(bas, SFUART_RXCTRL, 0); 245 uart_setreg(bas, SFUART_TXCTRL, 0); 246 247 /* Disable interrupts */ 248 uart_setreg(bas, SFUART_IRQ_ENABLE, 0); 249 250 clk_disable(sfsc->clk); 251 252 return (0); 253 } 254 255 static int 256 sfuart_bus_flush(struct uart_softc *sc, int what) 257 { 258 struct uart_bas *bas; 259 uint32_t reg; 260 261 bas = &sc->sc_bas; 262 uart_lock(sc->sc_hwmtx); 263 264 if (what & UART_FLUSH_TRANSMITTER) { 265 do { 266 reg = uart_getreg(bas, SFUART_TXDATA); 267 } while ((reg & SFUART_TXDATA_FULL) != 0); 268 } 269 270 if (what & UART_FLUSH_RECEIVER) { 271 do { 272 reg = uart_getreg(bas, SFUART_RXDATA); 273 } while ((reg & SFUART_RXDATA_EMPTY) == 0); 274 } 275 uart_unlock(sc->sc_hwmtx); 276 277 return (0); 278 } 279 280 #define SIGCHG(c, i, s, d) \ 281 do { \ 282 if (c) \ 283 i |= ((i) & (s)) ? (s) : (s) | (d); \ 284 else \ 285 i = ((i) & (s)) ? ((i) & ~(s)) | (d) : (i); \ 286 } while (0) 287 288 static int 289 sfuart_bus_getsig(struct uart_softc *sc) 290 { 291 uint32_t new, old, sig; 292 293 do { 294 old = sc->sc_hwsig; 295 sig = old; 296 SIGCHG(1, sig, SER_DSR, SER_DDSR); 297 SIGCHG(1, sig, SER_DCD, SER_DDCD); 298 SIGCHG(1, sig, SER_CTS, SER_DCTS); 299 new = sig & ~SER_MASK_DELTA; 300 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 301 302 return (sig); 303 } 304 305 static int 306 sfuart_bus_setsig(struct uart_softc *sc, int sig) 307 { 308 uint32_t new, old; 309 310 do { 311 old = sc->sc_hwsig; 312 new = old; 313 if (sig & SER_DDTR) { 314 SIGCHG(sig & SER_DTR, new, SER_DTR, SER_DDTR); 315 } 316 if (sig & SER_DRTS) { 317 SIGCHG(sig & SER_RTS, new, SER_RTS, SER_DRTS); 318 } 319 } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new)); 320 321 return (0); 322 } 323 324 static int 325 sfuart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) 326 { 327 struct uart_bas *bas; 328 uint32_t reg; 329 int error; 330 331 bas = &sc->sc_bas; 332 333 uart_lock(sc->sc_hwmtx); 334 335 switch (request) { 336 case UART_IOCTL_BAUD: 337 reg = uart_getreg(bas, SFUART_DIV); 338 if (reg == 0) { 339 /* Possible if the divisor hasn't been set up yet. */ 340 error = ENXIO; 341 break; 342 } 343 *(int*)data = bas->rclk / (reg + 1); 344 error = 0; 345 break; 346 default: 347 error = EINVAL; 348 break; 349 } 350 351 uart_unlock(sc->sc_hwmtx); 352 353 return (error); 354 } 355 356 static int 357 sfuart_bus_ipend(struct uart_softc *sc) 358 { 359 struct uart_bas *bas; 360 int ipend; 361 uint32_t reg, ie; 362 363 bas = &sc->sc_bas; 364 uart_lock(sc->sc_hwmtx); 365 366 ipend = 0; 367 reg = uart_getreg(bas, SFUART_IRQ_PENDING); 368 ie = uart_getreg(bas, SFUART_IRQ_ENABLE); 369 370 if ((reg & SFUART_IRQ_PENDING_TXWM) != 0 && 371 (ie & SFUART_IRQ_ENABLE_TXWM) != 0) { 372 ipend |= SER_INT_TXIDLE; 373 374 /* Disable TX interrupt */ 375 ie &= ~(SFUART_IRQ_ENABLE_TXWM); 376 uart_setreg(bas, SFUART_IRQ_ENABLE, ie); 377 } 378 379 if ((reg & SFUART_IRQ_PENDING_RXQM) != 0) 380 ipend |= SER_INT_RXREADY; 381 382 uart_unlock(sc->sc_hwmtx); 383 384 return (ipend); 385 } 386 387 static int 388 sfuart_bus_param(struct uart_softc *sc, int baudrate, int databits, 389 int stopbits, int parity) 390 { 391 struct uart_bas *bas; 392 uint32_t reg; 393 394 bas = &sc->sc_bas; 395 396 if (databits != 8) 397 return (EINVAL); 398 399 if (parity != UART_PARITY_NONE) 400 return (EINVAL); 401 402 uart_lock(sc->sc_hwmtx); 403 404 reg = uart_getreg(bas, SFUART_TXCTRL); 405 if (stopbits == 2) { 406 reg |= SFUART_TXCTRL_NSTOP; 407 } else if (stopbits == 1) { 408 reg &= ~SFUART_TXCTRL_NSTOP; 409 } else { 410 uart_unlock(sc->sc_hwmtx); 411 return (EINVAL); 412 } 413 414 if (baudrate > 0 && bas->rclk != 0) { 415 reg = (bas->rclk / baudrate) - 1; 416 uart_setreg(bas, SFUART_DIV, reg); 417 } 418 419 uart_unlock(sc->sc_hwmtx); 420 return (0); 421 } 422 423 static int 424 sfuart_bus_receive(struct uart_softc *sc) 425 { 426 struct uart_bas *bas; 427 uint32_t reg; 428 429 bas = &sc->sc_bas; 430 uart_lock(sc->sc_hwmtx); 431 432 reg = uart_getreg(bas, SFUART_RXDATA); 433 while ((reg & SFUART_RXDATA_EMPTY) == 0) { 434 if (uart_rx_full(sc)) { 435 sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN; 436 break; 437 } 438 439 uart_rx_put(sc, reg & 0xff); 440 441 reg = uart_getreg(bas, SFUART_RXDATA); 442 } 443 444 uart_unlock(sc->sc_hwmtx); 445 446 return (0); 447 } 448 449 static int 450 sfuart_bus_transmit(struct uart_softc *sc) 451 { 452 struct uart_bas *bas; 453 int i; 454 uint32_t reg; 455 456 bas = &sc->sc_bas; 457 uart_lock(sc->sc_hwmtx); 458 459 reg = uart_getreg(bas, SFUART_IRQ_ENABLE); 460 reg |= SFUART_IRQ_ENABLE_TXWM; 461 uart_setreg(bas, SFUART_IRQ_ENABLE, reg); 462 463 for (i = 0; i < sc->sc_txdatasz; i++) 464 sfuart_putc(bas, sc->sc_txbuf[i]); 465 466 sc->sc_txbusy = 1; 467 468 uart_unlock(sc->sc_hwmtx); 469 470 return (0); 471 } 472 473 static void 474 sfuart_bus_grab(struct uart_softc *sc) 475 { 476 struct uart_bas *bas; 477 uint32_t reg; 478 479 bas = &sc->sc_bas; 480 uart_lock(sc->sc_hwmtx); 481 482 reg = uart_getreg(bas, SFUART_IRQ_ENABLE); 483 reg &= ~(SFUART_IRQ_ENABLE_TXWM | SFUART_IRQ_PENDING_RXQM); 484 uart_setreg(bas, SFUART_IRQ_ENABLE, reg); 485 486 uart_unlock(sc->sc_hwmtx); 487 } 488 489 static void 490 sfuart_bus_ungrab(struct uart_softc *sc) 491 { 492 struct uart_bas *bas; 493 uint32_t reg; 494 495 bas = &sc->sc_bas; 496 uart_lock(sc->sc_hwmtx); 497 498 reg = uart_getreg(bas, SFUART_IRQ_ENABLE); 499 reg |= SFUART_IRQ_ENABLE_TXWM | SFUART_IRQ_PENDING_RXQM; 500 uart_setreg(bas, SFUART_IRQ_ENABLE, reg); 501 502 uart_unlock(sc->sc_hwmtx); 503 } 504 505 static kobj_method_t sfuart_methods[] = { 506 KOBJMETHOD(uart_probe, sfuart_bus_probe), 507 KOBJMETHOD(uart_attach, sfuart_bus_attach), 508 KOBJMETHOD(uart_detach, sfuart_bus_detach), 509 KOBJMETHOD(uart_flush, sfuart_bus_flush), 510 KOBJMETHOD(uart_getsig, sfuart_bus_getsig), 511 KOBJMETHOD(uart_setsig, sfuart_bus_setsig), 512 KOBJMETHOD(uart_ioctl, sfuart_bus_ioctl), 513 KOBJMETHOD(uart_ipend, sfuart_bus_ipend), 514 KOBJMETHOD(uart_param, sfuart_bus_param), 515 KOBJMETHOD(uart_receive, sfuart_bus_receive), 516 KOBJMETHOD(uart_transmit, sfuart_bus_transmit), 517 KOBJMETHOD(uart_grab, sfuart_bus_grab), 518 KOBJMETHOD(uart_ungrab, sfuart_bus_ungrab), 519 KOBJMETHOD_END 520 }; 521 522 static struct uart_ops sfuart_ops = { 523 .probe = sfuart_probe, 524 .init = sfuart_init, 525 .term = NULL, 526 .putc = sfuart_putc, 527 .rxready = sfuart_rxready, 528 .getc = sfuart_getc, 529 }; 530 531 struct uart_class sfuart_class = { 532 "sifiveuart", 533 sfuart_methods, 534 sizeof(struct sfuart_softc), 535 .uc_ops = &sfuart_ops, 536 .uc_range = SFUART_REGS_SIZE, 537 .uc_rclk = 0, 538 .uc_rshift = 0 539 }; 540 541 static struct ofw_compat_data compat_data[] = { 542 { "sifive,uart0", (uintptr_t)&sfuart_class }, 543 { NULL, (uintptr_t)NULL } 544 }; 545 546 UART_FDT_CLASS_AND_DEVICE(compat_data); 547