1 /* $NetBSD: uart.c,v 1.3 2022/04/11 21:23:07 andvar Exp $ */ 2 3 /* 4 * Copyright (c) 2021 Brad Spencer <brad@anduin.eldar.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifdef __RCSID 20 __RCSID("$NetBSD: uart.c,v 1.3 2022/04/11 21:23:07 andvar Exp $"); 21 #endif 22 23 /* Functions that know how to talk to a SCMD using the uart tty 24 * mode or via SPI userland, which ends up being mostly the same. 25 * 26 * Some of this is the same stuff that the kernel scmd(4) driver 27 * ends up doing. 28 */ 29 30 #include <inttypes.h> 31 #include <stdbool.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <err.h> 36 #include <fcntl.h> 37 #include <string.h> 38 #include <limits.h> 39 #include <termios.h> 40 #include <errno.h> 41 #include <sys/ioctl.h> 42 #include <sys/time.h> 43 #include <dev/spi/spi_io.h> 44 45 #include <dev/ic/scmdreg.h> 46 47 #include "scmdctl.h" 48 #include "responses.h" 49 50 #define EXTERN 51 #include "uart.h" 52 53 54 static int uart_subtype = -1; 55 static int uart_spi_slave_addr = -1; 56 57 /* The uart tty mode of the SCMD device is useful for human or 58 * machine use. However you can't really know what state it is in 59 * so send some junk and look for '>' character indicating a new 60 * command can be entered. Usually this won't be needed, but 61 * you can never know when it is. 62 */ 63 int 64 uart_clear(int fd, bool debug) 65 { 66 const char jcmd[4] = "qq\r\n"; 67 char input; 68 int i; 69 70 if (uart_subtype == UART_IS_PURE_UART) { 71 i = write(fd,jcmd,4); 72 if (i == 4) { 73 i = read(fd,&input,1); 74 while (input != '>') { 75 if (debug) 76 fprintf(stderr,"uart_clear: %c\n",input); 77 i = read(fd,&input,1); 78 } 79 } else { 80 return EINVAL; 81 } 82 } 83 84 return 0; 85 } 86 87 /* The SCMD device will echo back the characters in uart tty mode. 88 * Eat them here. 89 */ 90 static int 91 pure_uart_send_cmd(int fd, const char *s, char *ibuf, int len) 92 { 93 int i; 94 95 i = write(fd,s,len); 96 if (i == len) { 97 i = read(fd,ibuf,len); 98 return 0; 99 } else { 100 return EINVAL; 101 } 102 } 103 104 /* In pure uart tty mode, the command is sent as text and we are 105 * looking for '>'. There is not a lot that can go wrong, but 106 * noise on the line is one of them, and that really is not detected here. 107 * This is probably the least reliable method of speaking to a SCMD 108 * device. 109 */ 110 static int 111 uart_get_response(int fd, bool debug, char *obuf, int len) 112 { 113 int n,i; 114 char c; 115 116 memset(obuf,0,len); 117 n = 0; 118 i = read(fd,&c,1); 119 if (i == -1) 120 return EINVAL; 121 while (c != '>' && c != '\r' && n < len) { 122 obuf[n] = c; 123 if (debug) 124 fprintf(stderr,"uart_get_response: looking for EOL or NL: %d %d -%c-\n",i,n,c); 125 n++; 126 i = read(fd,&c,1); 127 } 128 129 if (c != '>') { 130 i = read(fd,&c,1); 131 if (i == -1) 132 return EINVAL; 133 while (c != '>') { 134 if (debug) 135 fprintf(stderr,"uart_get_response: draining: %d -%c-\n",i,c); 136 i = read(fd,&c,1); 137 if (i == -1) 138 return EINVAL; 139 } 140 } 141 142 return 0; 143 } 144 145 /* This handles the two uart cases. Either pure tty uart or SPI 146 * userland. The first uses text commands and the second is binary, 147 * but has the strange read situation that scmd(4) has. 148 */ 149 static int 150 uart_phy_read_register(int fd, bool debug, uint8_t reg, uint8_t *buf) 151 { 152 int err; 153 char cmdbuf[9]; 154 char qbuf[10]; 155 struct timespec ts; 156 struct spi_ioctl_transfer spi_t; 157 uint8_t b; 158 159 if (SCMD_IS_HOLE(reg)) { 160 *buf = SCMD_HOLE_VALUE; 161 return 0; 162 } 163 164 switch (uart_subtype) { 165 case UART_IS_PURE_UART: 166 sprintf(cmdbuf, "R%02X\r\n", reg); 167 err = pure_uart_send_cmd(fd, cmdbuf, qbuf, 5); 168 if (! err) { 169 err = uart_get_response(fd, debug, qbuf, 5); 170 *buf = (uint8_t)strtol(qbuf,NULL,16); 171 } 172 break; 173 case UART_IS_SPI_USERLAND: 174 spi_t.sit_addr = uart_spi_slave_addr; 175 reg = reg | 0x80; 176 spi_t.sit_send = ® 177 spi_t.sit_sendlen = 1; 178 spi_t.sit_recv = NULL; 179 spi_t.sit_recvlen = 0; 180 181 err = ioctl(fd,SPI_IOCTL_TRANSFER,&spi_t); 182 if (debug) 183 fprintf(stderr,"uart_phy_read_register: IOCTL UL SPI send err: %d ; reg: %02x ; xreg: %02x\n", 184 err,reg,reg & 0x7f); 185 186 if (err == -1) 187 return errno; 188 189 ts.tv_sec = 0; 190 ts.tv_nsec = 50; 191 nanosleep(&ts,NULL); 192 193 spi_t.sit_addr = uart_spi_slave_addr; 194 spi_t.sit_send = NULL; 195 spi_t.sit_sendlen = 0; 196 b = SCMD_HOLE_VALUE; 197 spi_t.sit_recv = &b; 198 spi_t.sit_recvlen = 1; 199 200 err = ioctl(fd,SPI_IOCTL_TRANSFER,&spi_t); 201 if (debug) 202 fprintf(stderr,"uart_phy_read_register: IOCTL UL SPI receive 1 err: %d ; b: %02x\n", 203 err,b); 204 205 if (err == -1) 206 return errno; 207 208 ts.tv_sec = 0; 209 ts.tv_nsec = 50; 210 nanosleep(&ts,NULL); 211 212 *buf = (uint8_t)b; 213 214 /* Bogus read that is needed */ 215 spi_t.sit_addr = uart_spi_slave_addr; 216 spi_t.sit_send = NULL; 217 spi_t.sit_sendlen = 0; 218 b = SCMD_HOLE_VALUE; 219 spi_t.sit_recv = &b; 220 spi_t.sit_recvlen = 1; 221 222 err = ioctl(fd,SPI_IOCTL_TRANSFER,&spi_t); 223 if (debug) 224 fprintf(stderr,"uart_phy_read_register: IOCTL UL SPI receive 2 err: %d ; b: %02x\n", 225 err,b); 226 227 if (err == -1) 228 return errno; 229 230 ts.tv_sec = 0; 231 ts.tv_nsec = 50; 232 nanosleep(&ts,NULL); 233 234 break; 235 default: 236 return EINVAL; 237 break; 238 } 239 240 return err; 241 } 242 243 /* Like read, this handles the two uart cases. */ 244 static int 245 uart_phy_write_register(int fd, bool debug, uint8_t reg, uint8_t buf) 246 { 247 int err; 248 char cmdbuf[9]; 249 char qbuf[10]; 250 struct timespec ts; 251 struct spi_ioctl_transfer spi_t; 252 253 if (SCMD_IS_HOLE(reg)) { 254 return 0; 255 } 256 257 switch (uart_subtype) { 258 case UART_IS_PURE_UART: 259 sprintf(cmdbuf, "W%02X%02X\r\n", reg, buf); 260 err = pure_uart_send_cmd(fd, cmdbuf, qbuf, 7); 261 if (! err) { 262 err = uart_get_response(fd, debug, qbuf, 10); 263 } 264 break; 265 case UART_IS_SPI_USERLAND: 266 spi_t.sit_addr = uart_spi_slave_addr; 267 reg = reg & 0x7f; 268 spi_t.sit_send = ® 269 spi_t.sit_sendlen = 1; 270 spi_t.sit_recv = NULL; 271 spi_t.sit_recvlen = 0; 272 273 err = ioctl(fd,SPI_IOCTL_TRANSFER,&spi_t); 274 if (debug) 275 fprintf(stderr,"uart_phy_write_register: IOCTL UL SPI write send 1 err: %d ; reg: %02x ; xreg: %02x\n", 276 err,reg,reg & 0x7f); 277 278 if (err == -1) 279 return errno; 280 281 spi_t.sit_addr = uart_spi_slave_addr; 282 spi_t.sit_send = &buf; 283 spi_t.sit_sendlen = 1; 284 spi_t.sit_recv = NULL; 285 spi_t.sit_recvlen = 0; 286 287 err = ioctl(fd,SPI_IOCTL_TRANSFER,&spi_t); 288 if (debug) 289 fprintf(stderr,"uart_phy_write_register: IOCTL UL SPI write send 2 err: %d ; buf: %02x\n", 290 err,buf); 291 292 if (err == -1) 293 return errno; 294 295 ts.tv_sec = 0; 296 ts.tv_nsec = 50; 297 nanosleep(&ts,NULL); 298 299 break; 300 default: 301 return EINVAL; 302 break; 303 } 304 305 return err; 306 } 307 308 static int 309 uart_local_read_register(int fd, bool debug, uint8_t reg, uint8_t reg_end, uint8_t *r) 310 { 311 uint8_t b; 312 int err = 0; 313 314 for(int q = reg, g = 0; q <= reg_end; q++, g++) { 315 err = uart_phy_read_register(fd, debug, q, &b); 316 if (!err) 317 r[g] = b; 318 } 319 320 return err; 321 } 322 323 /* When speaking to a SCMD device in any uart mode the view port for 324 * chained slave modules has to be handled in userland. This is similar 325 * to what the scmd(4) kernel driver ends up doing, but is much slower. 326 */ 327 static int 328 uart_set_view_port(int fd, bool debug, int a_module, uint8_t vpi2creg) 329 { 330 int err; 331 uint8_t vpi2caddr = (SCMD_REMOTE_ADDR_LOW + a_module) - 1; 332 333 if (debug) 334 fprintf(stderr, "uart_set_view_port: View port addr: %02x ; View port register: %02x\n", 335 vpi2caddr, vpi2creg); 336 337 err = uart_phy_write_register(fd, debug, SCMD_REG_REM_ADDR, vpi2caddr); 338 if (! err) 339 err = uart_phy_write_register(fd, debug, SCMD_REG_REM_OFFSET, vpi2creg); 340 341 return err; 342 } 343 344 static int 345 uart_remote_read_register(int fd, bool debug, int a_module, uint8_t reg, uint8_t reg_end, uint8_t *r) 346 { 347 int err; 348 int c; 349 uint8_t b; 350 351 for(int q = reg, g = 0; q <= reg_end; q++, g++) { 352 err = uart_set_view_port(fd, debug, a_module, q); 353 if (err) 354 break; 355 356 b = 0xff; /* you can write anything here.. it doesn't matter */ 357 err = uart_phy_write_register(fd, debug, SCMD_REG_REM_READ, b); 358 if (err) 359 break; 360 361 /* So ... there is no way to really know that the data is ready and 362 * there is no way to know if there was an error in the master module reading 363 * the data from the slave module. The data sheet says wait 5ms.. so we will 364 * wait a bit and see if the register cleared, but don't wait forever... I 365 * can't see how it would not be possible to read junk at times. 366 */ 367 c = 0; 368 do { 369 sleep(1); 370 err = uart_phy_read_register(fd, debug, SCMD_REG_REM_READ, &b); 371 c++; 372 } while ((c < 10) && (b != 0x00) && (!err)); 373 374 /* We can only hope that whatever was read from the slave module is there */ 375 if (err) 376 break; 377 err = uart_phy_read_register(fd, debug, SCMD_REG_REM_DATA_RD, &b); 378 if (err) 379 break; 380 r[g] = b; 381 } 382 383 return err; 384 } 385 386 void 387 uart_set_subtype(int subt, int spi_s_addr) 388 { 389 uart_subtype = subt; 390 uart_spi_slave_addr = spi_s_addr; 391 392 return; 393 } 394 395 /* Unlike scmd(4) local reads and remote module reads are done very 396 * differently. 397 */ 398 int 399 uart_read_register(int fd, bool debug, int a_module, uint8_t reg, uint8_t reg_end, uint8_t *r) 400 { 401 int err; 402 403 if (reg > SCMD_LAST_REG || 404 reg_end > SCMD_LAST_REG) 405 return EINVAL; 406 407 if (reg_end < reg) 408 return EINVAL; 409 410 err = uart_clear(fd, debug); 411 if (! err) { 412 if (a_module == 0) { 413 err = uart_local_read_register(fd, debug, reg, reg_end, r); 414 } else { 415 err = uart_remote_read_register(fd, debug, a_module, reg, reg_end, r); 416 } 417 } 418 419 return err; 420 } 421 422 static int 423 uart_remote_write_register(int fd, bool debug, int a_module, uint8_t reg, uint8_t reg_v) 424 { 425 int err; 426 int c; 427 uint8_t b; 428 429 err = uart_set_view_port(fd, debug, a_module, reg); 430 if (! err) { 431 /* We just sort of send this write off and wait to see if the register 432 * clears. There really isn't any indication that the data made it to the 433 * slave modules. 434 */ 435 err = uart_phy_write_register(fd, debug, SCMD_REG_REM_DATA_WR, reg_v); 436 if (! err) { 437 b = 0xff; /* you can write anything here.. it doesn't matter */ 438 err = uart_phy_write_register(fd, debug, SCMD_REG_REM_WRITE, b); 439 if (! err) { 440 c = 0; 441 do { 442 sleep(1); 443 err = uart_phy_read_register(fd, debug, SCMD_REG_REM_WRITE, &b); 444 c++; 445 } while ((c < 10) && (b != 0x00) && (!err)); 446 } 447 } 448 } 449 450 return err; 451 } 452 453 /* Like reads, writes are done very differently between scmd(4) and 454 * the uart modes. 455 */ 456 int 457 uart_write_register(int fd, bool debug, int a_module, uint8_t reg, uint8_t reg_v) 458 { 459 int err; 460 461 if (reg > SCMD_LAST_REG) 462 return EINVAL; 463 464 err = uart_clear(fd, debug); 465 if (! err) { 466 if (a_module == 0) { 467 err = uart_phy_write_register(fd, debug, reg, reg_v); 468 } else { 469 err = uart_remote_write_register(fd, debug, a_module, reg, reg_v); 470 } 471 } 472 473 return err; 474 } 475 476 /* This is a special ability to do a single SPI receive that has the 477 * hope of resyncing the device should it get out of sync in SPI mode. 478 * This will work for either SPI userland mode or scmd(4) when attached 479 * to the SPI bus as you can still write to /dev/spiN then too. 480 */ 481 int 482 uart_ul_spi_read_one(int fd, bool debug) 483 { 484 int err = 0; 485 struct timespec ts; 486 struct spi_ioctl_transfer spi_t; 487 uint8_t b; 488 489 if (uart_subtype == UART_IS_SPI_USERLAND) { 490 spi_t.sit_addr = uart_spi_slave_addr; 491 spi_t.sit_send = NULL; 492 spi_t.sit_sendlen = 0; 493 b = SCMD_HOLE_VALUE; 494 spi_t.sit_recv = &b; 495 spi_t.sit_recvlen = 1; 496 497 err = ioctl(fd,SPI_IOCTL_TRANSFER,&spi_t); 498 if (debug) 499 fprintf(stderr,"uart_ul_spi_read_one: IOCTL UL SPI receive 1 err: %d ; b: %02x\n", 500 err,b); 501 502 if (err == -1) 503 return errno; 504 505 ts.tv_sec = 0; 506 ts.tv_nsec = 50; 507 nanosleep(&ts,NULL); 508 } 509 510 return err; 511 } 512