1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/cleanup.h> 4 #include <linux/completion.h> 5 #include <linux/module.h> 6 #include <linux/of.h> 7 #include <linux/pse-pd/pse.h> 8 #include <linux/serdev.h> 9 #include <linux/spinlock.h> 10 #include <linux/string.h> 11 12 #include "realtek-pse-mcu.h" 13 14 #define RTPSE_MCU_UART_BAUD_DEFAULT 19200 15 #define RTPSE_MCU_UART_TX_TIMEOUT msecs_to_jiffies(100) 16 #define RTPSE_MCU_UART_RX_TIMEOUT msecs_to_jiffies(RTPSE_MCU_RESPONSE_MAX_MS) 17 18 struct rtpse_mcu_uart { 19 struct rtpse_mcu_ctrl pse; 20 struct serdev_device *serdev; 21 struct completion rx_done; 22 spinlock_t rx_lock; /* protects rx_buf and rx_len */ 23 size_t rx_len; 24 u8 rx_buf[RTPSE_MCU_MSG_SIZE]; 25 }; 26 27 #define to_rtpse_mcu_uart(p) container_of(p, struct rtpse_mcu_uart, pse) 28 29 /* 30 * No framing is done here: a glitched frame costs one transaction, then 31 * the next _send re-frames from rx_len 0. Resync works by returning count 32 * (not take), dropping any overflow so serdev keeps no leftover to bleed 33 * into the next frame. 34 */ 35 static size_t rtpse_mcu_uart_receive(struct serdev_device *serdev, 36 const u8 *buf, size_t count) 37 { 38 struct rtpse_mcu_uart *ctx = serdev_device_get_drvdata(serdev); 39 size_t take; 40 41 scoped_guard(spinlock_irqsave, &ctx->rx_lock) { 42 take = min(count, sizeof(ctx->rx_buf) - ctx->rx_len); 43 if (take) { 44 memcpy(ctx->rx_buf + ctx->rx_len, buf, take); 45 ctx->rx_len += take; 46 if (ctx->rx_len == sizeof(ctx->rx_buf)) 47 complete(&ctx->rx_done); 48 } 49 } 50 51 /* consume all to avoid desync/misalignment */ 52 return count; 53 } 54 55 static const struct serdev_device_ops rtpse_mcu_uart_serdev_ops = { 56 .receive_buf = rtpse_mcu_uart_receive, 57 .write_wakeup = serdev_device_write_wakeup, 58 }; 59 60 static int rtpse_mcu_uart_send(struct rtpse_mcu_ctrl *pse, const struct rtpse_mcu_msg *req) 61 { 62 struct rtpse_mcu_uart *ctx = to_rtpse_mcu_uart(pse); 63 int written; 64 65 /* clear any leftover rx state before transmitting */ 66 scoped_guard(spinlock_irqsave, &ctx->rx_lock) { 67 reinit_completion(&ctx->rx_done); 68 ctx->rx_len = 0; 69 } 70 71 written = serdev_device_write(ctx->serdev, (const u8 *)req, sizeof(*req), 72 RTPSE_MCU_UART_TX_TIMEOUT); 73 if (written < 0) 74 return written; 75 if (written != sizeof(*req)) 76 return -EIO; 77 78 return 0; 79 } 80 81 static int rtpse_mcu_uart_recv(struct rtpse_mcu_ctrl *pse, 82 const struct rtpse_mcu_msg *req, 83 struct rtpse_mcu_msg *resp) 84 { 85 struct rtpse_mcu_uart *ctx = to_rtpse_mcu_uart(pse); 86 87 if (!wait_for_completion_timeout(&ctx->rx_done, RTPSE_MCU_UART_RX_TIMEOUT)) 88 return -ETIMEDOUT; 89 90 scoped_guard(spinlock_irqsave, &ctx->rx_lock) { 91 if (ctx->rx_len != sizeof(*resp)) 92 return -EIO; 93 94 memcpy(resp, ctx->rx_buf, sizeof(*resp)); 95 } 96 return 0; 97 } 98 99 static const struct rtpse_mcu_transport_ops rtpse_mcu_uart_transport_ops = { 100 .send = rtpse_mcu_uart_send, 101 .recv = rtpse_mcu_uart_recv, 102 }; 103 104 static int rtpse_mcu_uart_probe(struct serdev_device *serdev) 105 { 106 u32 speed = RTPSE_MCU_UART_BAUD_DEFAULT; 107 struct device *dev = &serdev->dev; 108 struct rtpse_mcu_uart *ctx; 109 unsigned int baud; 110 int ret; 111 112 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); 113 if (!ctx) 114 return -ENOMEM; 115 116 ctx->serdev = serdev; 117 ctx->pse.dev = dev; 118 ctx->pse.pcdev.owner = THIS_MODULE; 119 ctx->pse.transport = &rtpse_mcu_uart_transport_ops; 120 init_completion(&ctx->rx_done); 121 spin_lock_init(&ctx->rx_lock); 122 123 serdev_device_set_drvdata(serdev, ctx); 124 serdev_device_set_client_ops(serdev, &rtpse_mcu_uart_serdev_ops); 125 126 ret = devm_serdev_device_open(dev, serdev); 127 if (ret) 128 return dev_err_probe(dev, ret, "failed to open serdev\n"); 129 130 fwnode_property_read_u32(dev_fwnode(dev), "current-speed", &speed); 131 132 baud = serdev_device_set_baudrate(serdev, speed); 133 if (baud != speed) 134 dev_warn(dev, "could not set baudrate %u, controller uses %u\n", 135 speed, baud); 136 137 serdev_device_set_flow_control(serdev, false); 138 139 ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); 140 if (ret) 141 dev_warn(dev, "could not set parity to none: %d\n", ret); 142 143 return rtpse_mcu_register(&ctx->pse); 144 } 145 146 static const struct of_device_id rtpse_mcu_uart_of_match[] = { 147 { .compatible = "realtek,pse-mcu-gen1", .data = &rtpse_mcu_gen1_data }, 148 { .compatible = "realtek,pse-mcu-gen2", .data = &rtpse_mcu_gen2_data }, 149 { /* sentinel */ } 150 }; 151 MODULE_DEVICE_TABLE(of, rtpse_mcu_uart_of_match); 152 153 static struct serdev_device_driver rtpse_mcu_uart_driver = { 154 .driver = { 155 .name = "realtek-pse-mcu-uart", 156 .of_match_table = rtpse_mcu_uart_of_match, 157 }, 158 .probe = rtpse_mcu_uart_probe, 159 }; 160 module_serdev_device_driver(rtpse_mcu_uart_driver); 161 162 MODULE_AUTHOR("Jonas Jelonek <jelonek.jonas@gmail.com>"); 163 MODULE_DESCRIPTION("Realtek PSE MCU driver (UART transport)"); 164 MODULE_LICENSE("GPL"); 165