1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Core driver for the microcontroller unit in QNAP NAS devices that is 4 * connected via a dedicated UART port. 5 * 6 * Copyright (C) 2024 Heiko Stuebner <heiko@sntech.de> 7 */ 8 9 #include <linux/cleanup.h> 10 #include <linux/export.h> 11 #include <linux/mfd/core.h> 12 #include <linux/mfd/qnap-mcu.h> 13 #include <linux/module.h> 14 #include <linux/of.h> 15 #include <linux/reboot.h> 16 #include <linux/serdev.h> 17 #include <linux/slab.h> 18 19 /* The longest command found so far is 5 bytes long */ 20 #define QNAP_MCU_MAX_CMD_SIZE 5 21 #define QNAP_MCU_MAX_DATA_SIZE 36 22 #define QNAP_MCU_ERROR_SIZE 2 23 #define QNAP_MCU_CHECKSUM_SIZE 1 24 25 #define QNAP_MCU_RX_BUFFER_SIZE \ 26 (QNAP_MCU_MAX_DATA_SIZE + QNAP_MCU_CHECKSUM_SIZE) 27 28 #define QNAP_MCU_TX_BUFFER_SIZE \ 29 (QNAP_MCU_MAX_CMD_SIZE + QNAP_MCU_CHECKSUM_SIZE) 30 31 #define QNAP_MCU_ACK_LEN 2 32 #define QNAP_MCU_VERSION_LEN 4 33 34 #define QNAP_MCU_TIMEOUT_MS 500 35 36 /** 37 * struct qnap_mcu_reply - Reply to a command 38 * 39 * @data: Buffer to store reply payload in 40 * @length: Expected reply length, including the checksum 41 * @received: Received number of bytes, so far 42 * @done: Triggered when the entire reply has been received 43 */ 44 struct qnap_mcu_reply { 45 u8 *data; 46 size_t length; 47 size_t received; 48 struct completion done; 49 }; 50 51 /** 52 * struct qnap_mcu - QNAP NAS embedded controller 53 * 54 * @serdev: Pointer to underlying serdev 55 * @bus_lock: Lock to serialize access to the device 56 * @reply: Reply data structure 57 * @variant: Device variant specific information 58 * @version: MCU firmware version 59 * @rx: Receive buffer the reply is assembled in 60 */ 61 struct qnap_mcu { 62 struct serdev_device *serdev; 63 struct mutex bus_lock; 64 struct qnap_mcu_reply reply; 65 const struct qnap_mcu_variant *variant; 66 u8 version[QNAP_MCU_VERSION_LEN]; 67 u8 rx[QNAP_MCU_RX_BUFFER_SIZE]; 68 }; 69 70 /* 71 * The QNAP-MCU uses a basic XOR checksum. 72 * It is always the last byte and XORs the whole previous message. 73 */ 74 static u8 qnap_mcu_csum(const u8 *buf, size_t size) 75 { 76 u8 csum = 0; 77 78 while (size--) 79 csum ^= *buf++; 80 81 return csum; 82 } 83 84 static bool qnap_mcu_verify_checksum(const u8 *buf, size_t size) 85 { 86 u8 crc = qnap_mcu_csum(buf, size - QNAP_MCU_CHECKSUM_SIZE); 87 88 return crc == buf[size - QNAP_MCU_CHECKSUM_SIZE]; 89 } 90 91 static int qnap_mcu_write(struct qnap_mcu *mcu, const u8 *data, u8 data_size) 92 { 93 unsigned char tx[QNAP_MCU_TX_BUFFER_SIZE]; 94 size_t length = data_size + QNAP_MCU_CHECKSUM_SIZE; 95 96 if (length > sizeof(tx)) { 97 dev_err(&mcu->serdev->dev, "data too big for transmit buffer"); 98 return -EINVAL; 99 } 100 101 memcpy(tx, data, data_size); 102 tx[data_size] = qnap_mcu_csum(data, data_size); 103 104 serdev_device_write_flush(mcu->serdev); 105 106 return serdev_device_write(mcu->serdev, tx, length, HZ); 107 } 108 109 static bool qnap_mcu_is_error_msg(size_t size) 110 { 111 return (size == QNAP_MCU_ERROR_SIZE + QNAP_MCU_CHECKSUM_SIZE); 112 } 113 114 static bool qnap_mcu_reply_is_generic_error(unsigned char *buf, size_t size) 115 { 116 if (!qnap_mcu_is_error_msg(size)) 117 return false; 118 119 if (buf[0] == '@' && buf[1] == '9') 120 return true; 121 122 return false; 123 } 124 125 static bool qnap_mcu_reply_is_checksum_error(unsigned char *buf, size_t size) 126 { 127 if (!qnap_mcu_is_error_msg(size)) 128 return false; 129 130 if (buf[0] == '@' && buf[1] == '8') 131 return true; 132 133 return false; 134 } 135 136 static bool qnap_mcu_reply_is_any_error(struct qnap_mcu *mcu, unsigned char *buf, size_t size) 137 { 138 if (qnap_mcu_reply_is_generic_error(buf, size)) { 139 dev_err(&mcu->serdev->dev, "Controller sent generic error response\n"); 140 return true; 141 } 142 143 if (qnap_mcu_reply_is_checksum_error(buf, size)) { 144 dev_err(&mcu->serdev->dev, "Controller received invalid checksum for the command\n"); 145 return true; 146 } 147 148 return false; 149 } 150 151 static size_t qnap_mcu_receive_buf(struct serdev_device *serdev, const u8 *buf, size_t size) 152 { 153 struct device *dev = &serdev->dev; 154 struct qnap_mcu *mcu = dev_get_drvdata(dev); 155 struct qnap_mcu_reply *reply = &mcu->reply; 156 const u8 *src = buf; 157 const u8 *end = buf + size; 158 159 if (!reply->length) { 160 dev_warn(dev, "Received %zu bytes, we were not waiting for\n", size); 161 return size; 162 } 163 164 while (src < end) { 165 reply->data[reply->received] = *src++; 166 reply->received++; 167 168 if (reply->received == reply->length) { 169 /* We don't expect any characters from the device now */ 170 reply->length = 0; 171 172 complete(&reply->done); 173 174 /* 175 * We report the consumed number of bytes. If there 176 * are still bytes remaining (though there shouldn't) 177 * the serdev layer will re-execute this handler with 178 * the remainder of the Rx bytes. 179 */ 180 return src - buf; 181 } 182 } 183 184 /* 185 * We received everything the uart had to offer for now. 186 * This could mean that either the uart will send more in a 2nd 187 * receive run, or that the MCU cut the reply short because it 188 * sent an error code instead of the expected reply. 189 * 190 * So check if the received data has the correct size for an error 191 * reply and if it matches, is an actual error code. 192 */ 193 if (qnap_mcu_is_error_msg(reply->received) && 194 qnap_mcu_verify_checksum(reply->data, reply->received) && 195 qnap_mcu_reply_is_any_error(mcu, reply->data, reply->received)) { 196 /* The reply was an error code, we're done */ 197 reply->length = 0; 198 199 complete(&reply->done); 200 } 201 202 /* 203 * The only way to get out of the above loop and end up here 204 * is through consuming all of the supplied data, so here we 205 * report that we processed it all. 206 */ 207 return size; 208 } 209 210 static const struct serdev_device_ops qnap_mcu_serdev_device_ops = { 211 .receive_buf = qnap_mcu_receive_buf, 212 .write_wakeup = serdev_device_write_wakeup, 213 }; 214 215 int qnap_mcu_exec(struct qnap_mcu *mcu, 216 const u8 *cmd_data, size_t cmd_data_size, 217 u8 *reply_data, size_t reply_data_size) 218 { 219 size_t length = reply_data_size + QNAP_MCU_CHECKSUM_SIZE; 220 struct qnap_mcu_reply *reply = &mcu->reply; 221 int ret = 0; 222 223 if (length > sizeof(mcu->rx)) { 224 dev_err(&mcu->serdev->dev, "expected data too big for receive buffer"); 225 return -EINVAL; 226 } 227 228 guard(mutex)(&mcu->bus_lock); 229 230 reply->data = mcu->rx; 231 reply->length = length; 232 reply->received = 0; 233 reinit_completion(&reply->done); 234 235 ret = qnap_mcu_write(mcu, cmd_data, cmd_data_size); 236 if (ret < 0) 237 return ret; 238 239 serdev_device_wait_until_sent(mcu->serdev, msecs_to_jiffies(QNAP_MCU_TIMEOUT_MS)); 240 241 if (!wait_for_completion_timeout(&reply->done, msecs_to_jiffies(QNAP_MCU_TIMEOUT_MS))) { 242 dev_err(&mcu->serdev->dev, "Command timeout\n"); 243 return -ETIMEDOUT; 244 } 245 246 if (!qnap_mcu_verify_checksum(mcu->rx, reply->received)) { 247 dev_err(&mcu->serdev->dev, "Invalid Checksum received from controller\n"); 248 return -EPROTO; 249 } 250 251 if (qnap_mcu_reply_is_any_error(mcu, mcu->rx, reply->received)) 252 return -EPROTO; 253 254 memcpy(reply_data, mcu->rx, reply_data_size); 255 256 return 0; 257 } 258 EXPORT_SYMBOL_GPL(qnap_mcu_exec); 259 260 int qnap_mcu_exec_with_ack(struct qnap_mcu *mcu, 261 const u8 *cmd_data, size_t cmd_data_size) 262 { 263 u8 ack[QNAP_MCU_ACK_LEN]; 264 int ret; 265 266 ret = qnap_mcu_exec(mcu, cmd_data, cmd_data_size, ack, sizeof(ack)); 267 if (ret) 268 return ret; 269 270 /* Should return @0 */ 271 if (ack[0] != '@' || ack[1] != '0') { 272 dev_err(&mcu->serdev->dev, "Did not receive ack\n"); 273 return -EIO; 274 } 275 276 return 0; 277 } 278 EXPORT_SYMBOL_GPL(qnap_mcu_exec_with_ack); 279 280 static int qnap_mcu_get_version(struct qnap_mcu *mcu) 281 { 282 const u8 cmd[] = { '%', 'V' }; 283 u8 rx[14]; 284 int ret; 285 286 /* Reply is the 2 command-bytes + 4 bytes describing the version */ 287 ret = qnap_mcu_exec(mcu, cmd, sizeof(cmd), rx, QNAP_MCU_VERSION_LEN + 2); 288 if (ret) 289 return ret; 290 291 memcpy(mcu->version, &rx[2], QNAP_MCU_VERSION_LEN); 292 293 return 0; 294 } 295 296 /* 297 * The MCU controls power to the peripherals but not the CPU. 298 * 299 * So using the PMIC to power off the system keeps the MCU and hard-drives 300 * running. This also then prevents the system from turning back on until 301 * the MCU is turned off by unplugging the power cable. 302 * Turning off the MCU alone on the other hand turns off the hard drives, 303 * LEDs, etc while the main SoC stays running - including its network ports. 304 */ 305 static int qnap_mcu_power_off(struct sys_off_data *data) 306 { 307 const u8 cmd[] = { '@', 'C', '0' }; 308 struct qnap_mcu *mcu = data->cb_data; 309 int ret; 310 311 ret = qnap_mcu_exec_with_ack(mcu, cmd, sizeof(cmd)); 312 if (ret) { 313 dev_err(&mcu->serdev->dev, "MCU poweroff failed %d\n", ret); 314 return NOTIFY_STOP; 315 } 316 317 return NOTIFY_DONE; 318 } 319 320 static const struct qnap_mcu_variant qnap_ts133_mcu = { 321 .baud_rate = 115200, 322 .num_drives = 1, 323 .fan_pwm_min = 51, /* Specified in original model.conf */ 324 .fan_pwm_max = 255, 325 .usb_led = false, 326 }; 327 328 static const struct qnap_mcu_variant qnap_ts233_mcu = { 329 .baud_rate = 115200, 330 .num_drives = 2, 331 .fan_pwm_min = 51, /* Specified in original model.conf */ 332 .fan_pwm_max = 255, 333 .usb_led = true, 334 }; 335 336 static const struct qnap_mcu_variant qnap_ts433_mcu = { 337 .baud_rate = 115200, 338 .num_drives = 4, 339 .fan_pwm_min = 51, /* Specified in original model.conf */ 340 .fan_pwm_max = 255, 341 .usb_led = true, 342 }; 343 344 static struct mfd_cell qnap_mcu_cells[] = { 345 { .name = "qnap-mcu-eeprom", }, 346 { .name = "qnap-mcu-input", }, 347 { .name = "qnap-mcu-leds", }, 348 { .name = "qnap-mcu-hwmon", } 349 }; 350 351 static int qnap_mcu_probe(struct serdev_device *serdev) 352 { 353 struct device *dev = &serdev->dev; 354 struct qnap_mcu *mcu; 355 int ret; 356 357 mcu = devm_kzalloc(dev, sizeof(*mcu), GFP_KERNEL); 358 if (!mcu) 359 return -ENOMEM; 360 361 mcu->serdev = serdev; 362 dev_set_drvdata(dev, mcu); 363 364 mcu->variant = of_device_get_match_data(dev); 365 if (!mcu->variant) 366 return -ENODEV; 367 368 mutex_init(&mcu->bus_lock); 369 init_completion(&mcu->reply.done); 370 371 serdev_device_set_client_ops(serdev, &qnap_mcu_serdev_device_ops); 372 ret = devm_serdev_device_open(dev, serdev); 373 if (ret) 374 return ret; 375 376 serdev_device_set_baudrate(serdev, mcu->variant->baud_rate); 377 serdev_device_set_flow_control(serdev, false); 378 379 ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE); 380 if (ret) 381 return dev_err_probe(dev, ret, "Failed to set parity\n"); 382 383 ret = qnap_mcu_get_version(mcu); 384 if (ret) 385 return ret; 386 387 ret = devm_register_sys_off_handler(dev, 388 SYS_OFF_MODE_POWER_OFF_PREPARE, 389 SYS_OFF_PRIO_DEFAULT, 390 &qnap_mcu_power_off, mcu); 391 if (ret) 392 return dev_err_probe(dev, ret, 393 "Failed to register poweroff handler\n"); 394 395 for (int i = 0; i < ARRAY_SIZE(qnap_mcu_cells); i++) { 396 qnap_mcu_cells[i].platform_data = mcu->variant; 397 qnap_mcu_cells[i].pdata_size = sizeof(*mcu->variant); 398 } 399 400 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, qnap_mcu_cells, 401 ARRAY_SIZE(qnap_mcu_cells), NULL, 0, NULL); 402 if (ret) 403 return dev_err_probe(dev, ret, "Failed to add child devices\n"); 404 405 return 0; 406 } 407 408 static const struct of_device_id qnap_mcu_dt_ids[] = { 409 { .compatible = "qnap,ts133-mcu", .data = &qnap_ts133_mcu }, 410 { .compatible = "qnap,ts233-mcu", .data = &qnap_ts233_mcu }, 411 { .compatible = "qnap,ts433-mcu", .data = &qnap_ts433_mcu }, 412 { /* sentinel */ } 413 }; 414 MODULE_DEVICE_TABLE(of, qnap_mcu_dt_ids); 415 416 static struct serdev_device_driver qnap_mcu_drv = { 417 .probe = qnap_mcu_probe, 418 .driver = { 419 .name = "qnap-mcu", 420 .of_match_table = qnap_mcu_dt_ids, 421 }, 422 }; 423 module_serdev_device_driver(qnap_mcu_drv); 424 425 MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 426 MODULE_DESCRIPTION("QNAP MCU core driver"); 427 MODULE_LICENSE("GPL"); 428