1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Beagleplay Linux Driver for Greybus 4 * 5 * Copyright (c) 2023 Ayush Singh <ayushdevel1325@gmail.com> 6 * Copyright (c) 2023 BeagleBoard.org Foundation 7 */ 8 9 #include <linux/gfp.h> 10 #include <linux/greybus.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/printk.h> 14 #include <linux/serdev.h> 15 #include <linux/tty.h> 16 #include <linux/tty_driver.h> 17 #include <linux/greybus/hd.h> 18 #include <linux/init.h> 19 #include <linux/device.h> 20 #include <linux/crc-ccitt.h> 21 #include <linux/circ_buf.h> 22 #include <linux/types.h> 23 #include <linux/workqueue.h> 24 25 #define RX_HDLC_PAYLOAD 256 26 #define CRC_LEN 2 27 #define MAX_RX_HDLC (1 + RX_HDLC_PAYLOAD + CRC_LEN) 28 #define TX_CIRC_BUF_SIZE 1024 29 30 #define ADDRESS_GREYBUS 0x01 31 #define ADDRESS_DBG 0x02 32 #define ADDRESS_CONTROL 0x03 33 34 #define HDLC_FRAME 0x7E 35 #define HDLC_ESC 0x7D 36 #define HDLC_XOR 0x20 37 38 #define CONTROL_SVC_START 0x01 39 #define CONTROL_SVC_STOP 0x02 40 41 /* The maximum number of CPorts supported by Greybus Host Device */ 42 #define GB_MAX_CPORTS 32 43 44 /** 45 * struct gb_beagleplay - BeaglePlay Greybus driver 46 * 47 * @sd: underlying serdev device 48 * 49 * @gb_hd: greybus host device 50 * 51 * @tx_work: hdlc transmit work 52 * @tx_producer_lock: hdlc transmit data producer lock. acquired when appending data to buffer. 53 * @tx_consumer_lock: hdlc transmit data consumer lock. acquired when sending data over uart. 54 * @tx_circ_buf: hdlc transmit circular buffer. 55 * @tx_crc: hdlc transmit crc-ccitt fcs 56 * 57 * @rx_buffer_len: length of receive buffer filled. 58 * @rx_buffer: hdlc frame receive buffer 59 * @rx_in_esc: hdlc rx flag to indicate ESC frame 60 */ 61 struct gb_beagleplay { 62 struct serdev_device *sd; 63 64 struct gb_host_device *gb_hd; 65 66 struct work_struct tx_work; 67 spinlock_t tx_producer_lock; 68 spinlock_t tx_consumer_lock; 69 struct circ_buf tx_circ_buf; 70 u16 tx_crc; 71 72 u16 rx_buffer_len; 73 bool rx_in_esc; 74 u8 rx_buffer[MAX_RX_HDLC]; 75 }; 76 77 /** 78 * struct hdlc_payload - Structure to represent part of HDCL frame payload data. 79 * 80 * @len: buffer length in bytes 81 * @buf: payload buffer 82 */ 83 struct hdlc_payload { 84 u16 len; 85 void *buf; 86 }; 87 88 static void hdlc_rx_greybus_frame(struct gb_beagleplay *bg, u8 *buf, u16 len) 89 { 90 u16 cport_id; 91 struct gb_operation_msg_hdr *hdr = (struct gb_operation_msg_hdr *)buf; 92 93 memcpy(&cport_id, hdr->pad, sizeof(cport_id)); 94 95 dev_dbg(&bg->sd->dev, "Greybus Operation %u type %X cport %u status %u received", 96 hdr->operation_id, hdr->type, cport_id, hdr->result); 97 98 greybus_data_rcvd(bg->gb_hd, cport_id, buf, len); 99 } 100 101 static void hdlc_rx_dbg_frame(const struct gb_beagleplay *bg, const char *buf, u16 len) 102 { 103 dev_dbg(&bg->sd->dev, "CC1352 Log: %.*s", (int)len, buf); 104 } 105 106 /** 107 * hdlc_write() - Consume HDLC Buffer. 108 * @bg: beagleplay greybus driver 109 * 110 * Assumes that consumer lock has been acquired. 111 */ 112 static void hdlc_write(struct gb_beagleplay *bg) 113 { 114 int written; 115 /* Start consuming HDLC data */ 116 int head = smp_load_acquire(&bg->tx_circ_buf.head); 117 int tail = bg->tx_circ_buf.tail; 118 int count = CIRC_CNT_TO_END(head, tail, TX_CIRC_BUF_SIZE); 119 const unsigned char *buf = &bg->tx_circ_buf.buf[tail]; 120 121 if (count > 0) { 122 written = serdev_device_write_buf(bg->sd, buf, count); 123 124 /* Finish consuming HDLC data */ 125 smp_store_release(&bg->tx_circ_buf.tail, (tail + written) & (TX_CIRC_BUF_SIZE - 1)); 126 } 127 } 128 129 /** 130 * hdlc_append() - Queue HDLC data for sending. 131 * @bg: beagleplay greybus driver 132 * @value: hdlc byte to transmit 133 * 134 * Assumes that producer lock as been acquired. 135 */ 136 static void hdlc_append(struct gb_beagleplay *bg, u8 value) 137 { 138 int tail, head = bg->tx_circ_buf.head; 139 140 while (true) { 141 tail = READ_ONCE(bg->tx_circ_buf.tail); 142 143 if (CIRC_SPACE(head, tail, TX_CIRC_BUF_SIZE) >= 1) { 144 bg->tx_circ_buf.buf[head] = value; 145 146 /* Finish producing HDLC byte */ 147 smp_store_release(&bg->tx_circ_buf.head, 148 (head + 1) & (TX_CIRC_BUF_SIZE - 1)); 149 return; 150 } 151 dev_warn(&bg->sd->dev, "Tx circ buf full"); 152 usleep_range(3000, 5000); 153 } 154 } 155 156 static void hdlc_append_escaped(struct gb_beagleplay *bg, u8 value) 157 { 158 if (value == HDLC_FRAME || value == HDLC_ESC) { 159 hdlc_append(bg, HDLC_ESC); 160 value ^= HDLC_XOR; 161 } 162 hdlc_append(bg, value); 163 } 164 165 static void hdlc_append_tx_frame(struct gb_beagleplay *bg) 166 { 167 bg->tx_crc = 0xFFFF; 168 hdlc_append(bg, HDLC_FRAME); 169 } 170 171 static void hdlc_append_tx_u8(struct gb_beagleplay *bg, u8 value) 172 { 173 bg->tx_crc = crc_ccitt(bg->tx_crc, &value, 1); 174 hdlc_append_escaped(bg, value); 175 } 176 177 static void hdlc_append_tx_buf(struct gb_beagleplay *bg, const u8 *buf, u16 len) 178 { 179 size_t i; 180 181 for (i = 0; i < len; i++) 182 hdlc_append_tx_u8(bg, buf[i]); 183 } 184 185 static void hdlc_append_tx_crc(struct gb_beagleplay *bg) 186 { 187 bg->tx_crc ^= 0xffff; 188 hdlc_append_escaped(bg, bg->tx_crc & 0xff); 189 hdlc_append_escaped(bg, (bg->tx_crc >> 8) & 0xff); 190 } 191 192 static void hdlc_transmit(struct work_struct *work) 193 { 194 struct gb_beagleplay *bg = container_of(work, struct gb_beagleplay, tx_work); 195 196 spin_lock_bh(&bg->tx_consumer_lock); 197 hdlc_write(bg); 198 spin_unlock_bh(&bg->tx_consumer_lock); 199 } 200 201 static void hdlc_tx_frames(struct gb_beagleplay *bg, u8 address, u8 control, 202 const struct hdlc_payload payloads[], size_t count) 203 { 204 size_t i; 205 206 spin_lock(&bg->tx_producer_lock); 207 208 hdlc_append_tx_frame(bg); 209 hdlc_append_tx_u8(bg, address); 210 hdlc_append_tx_u8(bg, control); 211 212 for (i = 0; i < count; ++i) 213 hdlc_append_tx_buf(bg, payloads[i].buf, payloads[i].len); 214 215 hdlc_append_tx_crc(bg); 216 hdlc_append_tx_frame(bg); 217 218 spin_unlock(&bg->tx_producer_lock); 219 220 schedule_work(&bg->tx_work); 221 } 222 223 static void hdlc_tx_s_frame_ack(struct gb_beagleplay *bg) 224 { 225 hdlc_tx_frames(bg, bg->rx_buffer[0], (bg->rx_buffer[1] >> 1) & 0x7, NULL, 0); 226 } 227 228 static void hdlc_rx_frame(struct gb_beagleplay *bg) 229 { 230 u16 crc, len; 231 u8 ctrl, *buf; 232 u8 address = bg->rx_buffer[0]; 233 234 crc = crc_ccitt(0xffff, bg->rx_buffer, bg->rx_buffer_len); 235 if (crc != 0xf0b8) { 236 dev_warn_ratelimited(&bg->sd->dev, "CRC failed from %02x: 0x%04x", address, crc); 237 return; 238 } 239 240 ctrl = bg->rx_buffer[1]; 241 buf = &bg->rx_buffer[2]; 242 len = bg->rx_buffer_len - 4; 243 244 /* I-Frame, send S-Frame ACK */ 245 if ((ctrl & 1) == 0) 246 hdlc_tx_s_frame_ack(bg); 247 248 switch (address) { 249 case ADDRESS_DBG: 250 hdlc_rx_dbg_frame(bg, buf, len); 251 break; 252 case ADDRESS_GREYBUS: 253 hdlc_rx_greybus_frame(bg, buf, len); 254 break; 255 default: 256 dev_warn_ratelimited(&bg->sd->dev, "unknown frame %u", address); 257 } 258 } 259 260 static int hdlc_rx(struct gb_beagleplay *bg, const u8 *data, size_t count) 261 { 262 size_t i; 263 u8 c; 264 265 for (i = 0; i < count; ++i) { 266 c = data[i]; 267 268 switch (c) { 269 case HDLC_FRAME: 270 if (bg->rx_buffer_len) 271 hdlc_rx_frame(bg); 272 273 bg->rx_buffer_len = 0; 274 break; 275 case HDLC_ESC: 276 bg->rx_in_esc = true; 277 break; 278 default: 279 if (bg->rx_in_esc) { 280 c ^= 0x20; 281 bg->rx_in_esc = false; 282 } 283 284 if (bg->rx_buffer_len < MAX_RX_HDLC) { 285 bg->rx_buffer[bg->rx_buffer_len] = c; 286 bg->rx_buffer_len++; 287 } else { 288 dev_err_ratelimited(&bg->sd->dev, "RX Buffer Overflow"); 289 bg->rx_buffer_len = 0; 290 } 291 } 292 } 293 294 return count; 295 } 296 297 static int hdlc_init(struct gb_beagleplay *bg) 298 { 299 INIT_WORK(&bg->tx_work, hdlc_transmit); 300 spin_lock_init(&bg->tx_producer_lock); 301 spin_lock_init(&bg->tx_consumer_lock); 302 bg->tx_circ_buf.head = 0; 303 bg->tx_circ_buf.tail = 0; 304 305 bg->tx_circ_buf.buf = devm_kmalloc(&bg->sd->dev, TX_CIRC_BUF_SIZE, GFP_KERNEL); 306 if (!bg->tx_circ_buf.buf) 307 return -ENOMEM; 308 309 bg->rx_buffer_len = 0; 310 bg->rx_in_esc = false; 311 312 return 0; 313 } 314 315 static void hdlc_deinit(struct gb_beagleplay *bg) 316 { 317 flush_work(&bg->tx_work); 318 } 319 320 static int gb_tty_receive(struct serdev_device *sd, const unsigned char *data, size_t count) 321 { 322 struct gb_beagleplay *bg = serdev_device_get_drvdata(sd); 323 324 return hdlc_rx(bg, data, count); 325 } 326 327 static void gb_tty_wakeup(struct serdev_device *serdev) 328 { 329 struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev); 330 331 schedule_work(&bg->tx_work); 332 } 333 334 static struct serdev_device_ops gb_beagleplay_ops = { 335 .receive_buf = gb_tty_receive, 336 .write_wakeup = gb_tty_wakeup, 337 }; 338 339 static int gb_message_send(struct gb_host_device *hd, u16 cport, struct gb_message *msg, gfp_t mask) 340 { 341 struct gb_beagleplay *bg = dev_get_drvdata(&hd->dev); 342 struct hdlc_payload payloads[2]; 343 344 dev_dbg(&hd->dev, "Sending greybus message with Operation %u, Type: %X on Cport %u", 345 msg->header->operation_id, msg->header->type, cport); 346 347 if (msg->header->size > RX_HDLC_PAYLOAD) 348 return dev_err_probe(&hd->dev, -E2BIG, "Greybus message too big"); 349 350 memcpy(msg->header->pad, &cport, sizeof(cport)); 351 352 payloads[0].buf = msg->header; 353 payloads[0].len = sizeof(*msg->header); 354 payloads[1].buf = msg->payload; 355 payloads[1].len = msg->payload_size; 356 357 hdlc_tx_frames(bg, ADDRESS_GREYBUS, 0x03, payloads, 2); 358 greybus_message_sent(bg->gb_hd, msg, 0); 359 360 return 0; 361 } 362 363 static void gb_message_cancel(struct gb_message *message) 364 { 365 } 366 367 static struct gb_hd_driver gb_hdlc_driver = { .message_send = gb_message_send, 368 .message_cancel = gb_message_cancel }; 369 370 static void gb_beagleplay_start_svc(struct gb_beagleplay *bg) 371 { 372 const u8 command = CONTROL_SVC_START; 373 const struct hdlc_payload payload = { .len = 1, .buf = (void *)&command }; 374 375 hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1); 376 } 377 378 static void gb_beagleplay_stop_svc(struct gb_beagleplay *bg) 379 { 380 const u8 command = CONTROL_SVC_STOP; 381 const struct hdlc_payload payload = { .len = 1, .buf = (void *)&command }; 382 383 hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1); 384 } 385 386 static void gb_greybus_deinit(struct gb_beagleplay *bg) 387 { 388 gb_hd_del(bg->gb_hd); 389 gb_hd_put(bg->gb_hd); 390 } 391 392 static int gb_greybus_init(struct gb_beagleplay *bg) 393 { 394 int ret; 395 396 bg->gb_hd = gb_hd_create(&gb_hdlc_driver, &bg->sd->dev, TX_CIRC_BUF_SIZE, GB_MAX_CPORTS); 397 if (IS_ERR(bg->gb_hd)) { 398 dev_err(&bg->sd->dev, "Failed to create greybus host device"); 399 return PTR_ERR(bg->gb_hd); 400 } 401 402 ret = gb_hd_add(bg->gb_hd); 403 if (ret) { 404 dev_err(&bg->sd->dev, "Failed to add greybus host device"); 405 goto free_gb_hd; 406 } 407 dev_set_drvdata(&bg->gb_hd->dev, bg); 408 409 return 0; 410 411 free_gb_hd: 412 gb_greybus_deinit(bg); 413 return ret; 414 } 415 416 static void gb_serdev_deinit(struct gb_beagleplay *bg) 417 { 418 serdev_device_close(bg->sd); 419 } 420 421 static int gb_serdev_init(struct gb_beagleplay *bg) 422 { 423 int ret; 424 425 serdev_device_set_drvdata(bg->sd, bg); 426 serdev_device_set_client_ops(bg->sd, &gb_beagleplay_ops); 427 ret = serdev_device_open(bg->sd); 428 if (ret) 429 return dev_err_probe(&bg->sd->dev, ret, "Unable to open serial device"); 430 431 serdev_device_set_baudrate(bg->sd, 115200); 432 serdev_device_set_flow_control(bg->sd, false); 433 434 return 0; 435 } 436 437 static int gb_beagleplay_probe(struct serdev_device *serdev) 438 { 439 int ret = 0; 440 struct gb_beagleplay *bg; 441 442 bg = devm_kmalloc(&serdev->dev, sizeof(*bg), GFP_KERNEL); 443 if (!bg) 444 return -ENOMEM; 445 446 bg->sd = serdev; 447 ret = gb_serdev_init(bg); 448 if (ret) 449 return ret; 450 451 ret = hdlc_init(bg); 452 if (ret) 453 goto free_serdev; 454 455 ret = gb_greybus_init(bg); 456 if (ret) 457 goto free_hdlc; 458 459 gb_beagleplay_start_svc(bg); 460 461 return 0; 462 463 free_hdlc: 464 hdlc_deinit(bg); 465 free_serdev: 466 gb_serdev_deinit(bg); 467 return ret; 468 } 469 470 static void gb_beagleplay_remove(struct serdev_device *serdev) 471 { 472 struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev); 473 474 gb_greybus_deinit(bg); 475 gb_beagleplay_stop_svc(bg); 476 hdlc_deinit(bg); 477 gb_serdev_deinit(bg); 478 } 479 480 static const struct of_device_id gb_beagleplay_of_match[] = { 481 { 482 .compatible = "ti,cc1352p7", 483 }, 484 {}, 485 }; 486 MODULE_DEVICE_TABLE(of, gb_beagleplay_of_match); 487 488 static struct serdev_device_driver gb_beagleplay_driver = { 489 .probe = gb_beagleplay_probe, 490 .remove = gb_beagleplay_remove, 491 .driver = { 492 .name = "gb_beagleplay", 493 .of_match_table = gb_beagleplay_of_match, 494 }, 495 }; 496 497 module_serdev_device_driver(gb_beagleplay_driver); 498 499 MODULE_LICENSE("GPL"); 500 MODULE_AUTHOR("Ayush Singh <ayushdevel1325@gmail.com>"); 501 MODULE_DESCRIPTION("A Greybus driver for BeaglePlay"); 502