1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | |
3 | /* |
4 | * Multifunction core driver for Zodiac Inflight Innovations RAVE |
5 | * Supervisory Processor(SP) MCU that is connected via dedicated UART |
6 | * port |
7 | * |
8 | * Copyright (C) 2017 Zodiac Inflight Innovations |
9 | */ |
10 | |
11 | #include <linux/atomic.h> |
12 | #include <linux/crc-itu-t.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/export.h> |
15 | #include <linux/init.h> |
16 | #include <linux/slab.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/mfd/rave-sp.h> |
19 | #include <linux/module.h> |
20 | #include <linux/of.h> |
21 | #include <linux/of_platform.h> |
22 | #include <linux/sched.h> |
23 | #include <linux/serdev.h> |
24 | #include <asm/unaligned.h> |
25 | |
26 | /* |
27 | * UART protocol using following entities: |
28 | * - message to MCU => ACK response |
29 | * - event from MCU => event ACK |
30 | * |
31 | * Frame structure: |
32 | * <STX> <DATA> <CHECKSUM> <ETX> |
33 | * Where: |
34 | * - STX - is start of transmission character |
35 | * - ETX - end of transmission |
36 | * - DATA - payload |
37 | * - CHECKSUM - checksum calculated on <DATA> |
38 | * |
39 | * If <DATA> or <CHECKSUM> contain one of control characters, then it is |
40 | * escaped using <DLE> control code. Added <DLE> does not participate in |
41 | * checksum calculation. |
42 | */ |
43 | #define RAVE_SP_STX 0x02 |
44 | #define RAVE_SP_ETX 0x03 |
45 | #define RAVE_SP_DLE 0x10 |
46 | |
47 | #define RAVE_SP_MAX_DATA_SIZE 64 |
48 | #define RAVE_SP_CHECKSUM_8B2C 1 |
49 | #define RAVE_SP_CHECKSUM_CCITT 2 |
50 | #define RAVE_SP_CHECKSUM_SIZE RAVE_SP_CHECKSUM_CCITT |
51 | /* |
52 | * We don't store STX, ETX and unescaped bytes, so Rx is only |
53 | * DATA + CSUM |
54 | */ |
55 | #define RAVE_SP_RX_BUFFER_SIZE \ |
56 | (RAVE_SP_MAX_DATA_SIZE + RAVE_SP_CHECKSUM_SIZE) |
57 | |
58 | #define RAVE_SP_STX_ETX_SIZE 2 |
59 | /* |
60 | * For Tx we have to have space for everything, STX, EXT and |
61 | * potentially stuffed DATA + CSUM data + csum |
62 | */ |
63 | #define RAVE_SP_TX_BUFFER_SIZE \ |
64 | (RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE) |
65 | |
66 | /** |
67 | * enum rave_sp_deframer_state - Possible state for de-framer |
68 | * |
69 | * @RAVE_SP_EXPECT_SOF: Scanning input for start-of-frame marker |
70 | * @RAVE_SP_EXPECT_DATA: Got start of frame marker, collecting frame |
71 | * @RAVE_SP_EXPECT_ESCAPED_DATA: Got escape character, collecting escaped byte |
72 | */ |
73 | enum rave_sp_deframer_state { |
74 | RAVE_SP_EXPECT_SOF, |
75 | RAVE_SP_EXPECT_DATA, |
76 | RAVE_SP_EXPECT_ESCAPED_DATA, |
77 | }; |
78 | |
79 | /** |
80 | * struct rave_sp_deframer - Device protocol deframer |
81 | * |
82 | * @state: Current state of the deframer |
83 | * @data: Buffer used to collect deframed data |
84 | * @length: Number of bytes de-framed so far |
85 | */ |
86 | struct rave_sp_deframer { |
87 | enum rave_sp_deframer_state state; |
88 | unsigned char data[RAVE_SP_RX_BUFFER_SIZE]; |
89 | size_t length; |
90 | }; |
91 | |
92 | /** |
93 | * struct rave_sp_reply - Reply as per RAVE device protocol |
94 | * |
95 | * @length: Expected reply length |
96 | * @data: Buffer to store reply payload in |
97 | * @code: Expected reply code |
98 | * @ackid: Expected reply ACK ID |
99 | * @received: Successful reply reception completion |
100 | */ |
101 | struct rave_sp_reply { |
102 | size_t length; |
103 | void *data; |
104 | u8 code; |
105 | u8 ackid; |
106 | struct completion received; |
107 | }; |
108 | |
109 | /** |
110 | * struct rave_sp_checksum - Variant specific checksum implementation details |
111 | * |
112 | * @length: Calculated checksum length |
113 | * @subroutine: Utilized checksum algorithm implementation |
114 | */ |
115 | struct rave_sp_checksum { |
116 | size_t length; |
117 | void (*subroutine)(const u8 *, size_t, u8 *); |
118 | }; |
119 | |
120 | struct rave_sp_version { |
121 | u8 hardware; |
122 | __le16 major; |
123 | u8 minor; |
124 | u8 letter[2]; |
125 | } __packed; |
126 | |
127 | struct rave_sp_status { |
128 | struct rave_sp_version bootloader_version; |
129 | struct rave_sp_version firmware_version; |
130 | u16 rdu_eeprom_flag; |
131 | u16 dds_eeprom_flag; |
132 | u8 pic_flag; |
133 | u8 orientation; |
134 | u32 etc; |
135 | s16 temp[2]; |
136 | u8 backlight_current[3]; |
137 | u8 dip_switch; |
138 | u8 host_interrupt; |
139 | u16 voltage_28; |
140 | u8 i2c_device_status; |
141 | u8 power_status; |
142 | u8 general_status; |
143 | u8 deprecated1; |
144 | u8 power_led_status; |
145 | u8 deprecated2; |
146 | u8 periph_power_shutoff; |
147 | } __packed; |
148 | |
149 | /** |
150 | * struct rave_sp_variant_cmds - Variant specific command routines |
151 | * |
152 | * @translate: Generic to variant specific command mapping routine |
153 | * @get_status: Variant specific implementation of CMD_GET_STATUS |
154 | */ |
155 | struct rave_sp_variant_cmds { |
156 | int (*translate)(enum rave_sp_command); |
157 | int (*get_status)(struct rave_sp *sp, struct rave_sp_status *); |
158 | }; |
159 | |
160 | /** |
161 | * struct rave_sp_variant - RAVE supervisory processor core variant |
162 | * |
163 | * @checksum: Variant specific checksum implementation |
164 | * @cmd: Variant specific command pointer table |
165 | * |
166 | */ |
167 | struct rave_sp_variant { |
168 | const struct rave_sp_checksum *checksum; |
169 | struct rave_sp_variant_cmds cmd; |
170 | }; |
171 | |
172 | /** |
173 | * struct rave_sp - RAVE supervisory processor core |
174 | * |
175 | * @serdev: Pointer to underlying serdev |
176 | * @deframer: Stored state of the protocol deframer |
177 | * @ackid: ACK ID used in last reply sent to the device |
178 | * @bus_lock: Lock to serialize access to the device |
179 | * @reply_lock: Lock protecting @reply |
180 | * @reply: Pointer to memory to store reply payload |
181 | * |
182 | * @variant: Device variant specific information |
183 | * @event_notifier_list: Input event notification chain |
184 | * |
185 | * @part_number_firmware: Firmware version |
186 | * @part_number_bootloader: Bootloader version |
187 | */ |
188 | struct rave_sp { |
189 | struct serdev_device *serdev; |
190 | struct rave_sp_deframer deframer; |
191 | atomic_t ackid; |
192 | struct mutex bus_lock; |
193 | struct mutex reply_lock; |
194 | struct rave_sp_reply *reply; |
195 | |
196 | const struct rave_sp_variant *variant; |
197 | struct blocking_notifier_head event_notifier_list; |
198 | |
199 | const char *part_number_firmware; |
200 | const char *part_number_bootloader; |
201 | }; |
202 | |
203 | static bool rave_sp_id_is_event(u8 code) |
204 | { |
205 | return (code & 0xF0) == RAVE_SP_EVNT_BASE; |
206 | } |
207 | |
208 | static void rave_sp_unregister_event_notifier(struct device *dev, void *res) |
209 | { |
210 | struct rave_sp *sp = dev_get_drvdata(dev: dev->parent); |
211 | struct notifier_block *nb = *(struct notifier_block **)res; |
212 | struct blocking_notifier_head *bnh = &sp->event_notifier_list; |
213 | |
214 | WARN_ON(blocking_notifier_chain_unregister(bnh, nb)); |
215 | } |
216 | |
217 | int devm_rave_sp_register_event_notifier(struct device *dev, |
218 | struct notifier_block *nb) |
219 | { |
220 | struct rave_sp *sp = dev_get_drvdata(dev: dev->parent); |
221 | struct notifier_block **rcnb; |
222 | int ret; |
223 | |
224 | rcnb = devres_alloc(rave_sp_unregister_event_notifier, |
225 | sizeof(*rcnb), GFP_KERNEL); |
226 | if (!rcnb) |
227 | return -ENOMEM; |
228 | |
229 | ret = blocking_notifier_chain_register(nh: &sp->event_notifier_list, nb); |
230 | if (!ret) { |
231 | *rcnb = nb; |
232 | devres_add(dev, res: rcnb); |
233 | } else { |
234 | devres_free(res: rcnb); |
235 | } |
236 | |
237 | return ret; |
238 | } |
239 | EXPORT_SYMBOL_GPL(devm_rave_sp_register_event_notifier); |
240 | |
241 | static void csum_8b2c(const u8 *buf, size_t size, u8 *crc) |
242 | { |
243 | *crc = *buf++; |
244 | size--; |
245 | |
246 | while (size--) |
247 | *crc += *buf++; |
248 | |
249 | *crc = 1 + ~(*crc); |
250 | } |
251 | |
252 | static void csum_ccitt(const u8 *buf, size_t size, u8 *crc) |
253 | { |
254 | const u16 calculated = crc_itu_t(crc: 0xffff, buffer: buf, len: size); |
255 | |
256 | /* |
257 | * While the rest of the wire protocol is little-endian, |
258 | * CCITT-16 CRC in RDU2 device is sent out in big-endian order. |
259 | */ |
260 | put_unaligned_be16(val: calculated, p: crc); |
261 | } |
262 | |
263 | static void *stuff(unsigned char *dest, const unsigned char *src, size_t n) |
264 | { |
265 | while (n--) { |
266 | const unsigned char byte = *src++; |
267 | |
268 | switch (byte) { |
269 | case RAVE_SP_STX: |
270 | case RAVE_SP_ETX: |
271 | case RAVE_SP_DLE: |
272 | *dest++ = RAVE_SP_DLE; |
273 | fallthrough; |
274 | default: |
275 | *dest++ = byte; |
276 | } |
277 | } |
278 | |
279 | return dest; |
280 | } |
281 | |
282 | static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size) |
283 | { |
284 | const size_t checksum_length = sp->variant->checksum->length; |
285 | unsigned char frame[RAVE_SP_TX_BUFFER_SIZE]; |
286 | unsigned char crc[RAVE_SP_CHECKSUM_SIZE]; |
287 | unsigned char *dest = frame; |
288 | size_t length; |
289 | |
290 | if (WARN_ON(checksum_length > sizeof(crc))) |
291 | return -ENOMEM; |
292 | |
293 | if (WARN_ON(data_size > sizeof(frame))) |
294 | return -ENOMEM; |
295 | |
296 | sp->variant->checksum->subroutine(data, data_size, crc); |
297 | |
298 | *dest++ = RAVE_SP_STX; |
299 | dest = stuff(dest, src: data, n: data_size); |
300 | dest = stuff(dest, src: crc, n: checksum_length); |
301 | *dest++ = RAVE_SP_ETX; |
302 | |
303 | length = dest - frame; |
304 | |
305 | print_hex_dump_debug("rave-sp tx: " , DUMP_PREFIX_NONE, |
306 | 16, 1, frame, length, false); |
307 | |
308 | return serdev_device_write(sp->serdev, frame, length, HZ); |
309 | } |
310 | |
311 | static u8 rave_sp_reply_code(u8 command) |
312 | { |
313 | /* |
314 | * There isn't a single rule that describes command code -> |
315 | * ACK code transformation, but, going through various |
316 | * versions of ICDs, there appear to be three distinct groups |
317 | * that can be described by simple transformation. |
318 | */ |
319 | switch (command) { |
320 | case 0xA0 ... 0xBE: |
321 | /* |
322 | * Commands implemented by firmware found in RDU1 and |
323 | * older devices all seem to obey the following rule |
324 | */ |
325 | return command + 0x20; |
326 | case 0xE0 ... 0xEF: |
327 | /* |
328 | * Events emitted by all versions of the firmare use |
329 | * least significant bit to get an ACK code |
330 | */ |
331 | return command | 0x01; |
332 | default: |
333 | /* |
334 | * Commands implemented by firmware found in RDU2 are |
335 | * similar to "old" commands, but they use slightly |
336 | * different offset |
337 | */ |
338 | return command + 0x40; |
339 | } |
340 | } |
341 | |
342 | int rave_sp_exec(struct rave_sp *sp, |
343 | void *__data, size_t data_size, |
344 | void *reply_data, size_t reply_data_size) |
345 | { |
346 | struct rave_sp_reply reply = { |
347 | .data = reply_data, |
348 | .length = reply_data_size, |
349 | .received = COMPLETION_INITIALIZER_ONSTACK(reply.received), |
350 | }; |
351 | unsigned char *data = __data; |
352 | int command, ret = 0; |
353 | u8 ackid; |
354 | |
355 | command = sp->variant->cmd.translate(data[0]); |
356 | if (command < 0) |
357 | return command; |
358 | |
359 | ackid = atomic_inc_return(v: &sp->ackid); |
360 | reply.ackid = ackid; |
361 | reply.code = rave_sp_reply_code(command: (u8)command); |
362 | |
363 | mutex_lock(&sp->bus_lock); |
364 | |
365 | mutex_lock(&sp->reply_lock); |
366 | sp->reply = &reply; |
367 | mutex_unlock(lock: &sp->reply_lock); |
368 | |
369 | data[0] = command; |
370 | data[1] = ackid; |
371 | |
372 | rave_sp_write(sp, data, data_size); |
373 | |
374 | if (!wait_for_completion_timeout(x: &reply.received, HZ)) { |
375 | dev_err(&sp->serdev->dev, "Command timeout\n" ); |
376 | ret = -ETIMEDOUT; |
377 | |
378 | mutex_lock(&sp->reply_lock); |
379 | sp->reply = NULL; |
380 | mutex_unlock(lock: &sp->reply_lock); |
381 | } |
382 | |
383 | mutex_unlock(lock: &sp->bus_lock); |
384 | return ret; |
385 | } |
386 | EXPORT_SYMBOL_GPL(rave_sp_exec); |
387 | |
388 | static void rave_sp_receive_event(struct rave_sp *sp, |
389 | const unsigned char *data, size_t length) |
390 | { |
391 | u8 cmd[] = { |
392 | [0] = rave_sp_reply_code(command: data[0]), |
393 | [1] = data[1], |
394 | }; |
395 | |
396 | rave_sp_write(sp, data: cmd, data_size: sizeof(cmd)); |
397 | |
398 | blocking_notifier_call_chain(nh: &sp->event_notifier_list, |
399 | val: rave_sp_action_pack(event: data[0], value: data[2]), |
400 | NULL); |
401 | } |
402 | |
403 | static void rave_sp_receive_reply(struct rave_sp *sp, |
404 | const unsigned char *data, size_t length) |
405 | { |
406 | struct device *dev = &sp->serdev->dev; |
407 | struct rave_sp_reply *reply; |
408 | const size_t payload_length = length - 2; |
409 | |
410 | mutex_lock(&sp->reply_lock); |
411 | reply = sp->reply; |
412 | |
413 | if (reply) { |
414 | if (reply->code == data[0] && reply->ackid == data[1] && |
415 | payload_length >= reply->length) { |
416 | /* |
417 | * We are relying on memcpy(dst, src, 0) to be a no-op |
418 | * when handling commands that have a no-payload reply |
419 | */ |
420 | memcpy(reply->data, &data[2], reply->length); |
421 | complete(&reply->received); |
422 | sp->reply = NULL; |
423 | } else { |
424 | dev_err(dev, "Ignoring incorrect reply\n" ); |
425 | dev_dbg(dev, "Code: expected = 0x%08x received = 0x%08x\n" , |
426 | reply->code, data[0]); |
427 | dev_dbg(dev, "ACK ID: expected = 0x%08x received = 0x%08x\n" , |
428 | reply->ackid, data[1]); |
429 | dev_dbg(dev, "Length: expected = %zu received = %zu\n" , |
430 | reply->length, payload_length); |
431 | } |
432 | } |
433 | |
434 | mutex_unlock(lock: &sp->reply_lock); |
435 | } |
436 | |
437 | static void rave_sp_receive_frame(struct rave_sp *sp, |
438 | const unsigned char *data, |
439 | size_t length) |
440 | { |
441 | const size_t checksum_length = sp->variant->checksum->length; |
442 | const size_t payload_length = length - checksum_length; |
443 | const u8 *crc_reported = &data[payload_length]; |
444 | struct device *dev = &sp->serdev->dev; |
445 | u8 crc_calculated[RAVE_SP_CHECKSUM_SIZE]; |
446 | |
447 | if (unlikely(checksum_length > sizeof(crc_calculated))) { |
448 | dev_warn(dev, "Checksum too long, dropping\n" ); |
449 | return; |
450 | } |
451 | |
452 | print_hex_dump_debug("rave-sp rx: " , DUMP_PREFIX_NONE, |
453 | 16, 1, data, length, false); |
454 | |
455 | if (unlikely(length <= checksum_length)) { |
456 | dev_warn(dev, "Dropping short frame\n" ); |
457 | return; |
458 | } |
459 | |
460 | sp->variant->checksum->subroutine(data, payload_length, |
461 | crc_calculated); |
462 | |
463 | if (memcmp(p: crc_calculated, q: crc_reported, size: checksum_length)) { |
464 | dev_warn(dev, "Dropping bad frame\n" ); |
465 | return; |
466 | } |
467 | |
468 | if (rave_sp_id_is_event(code: data[0])) |
469 | rave_sp_receive_event(sp, data, length); |
470 | else |
471 | rave_sp_receive_reply(sp, data, length); |
472 | } |
473 | |
474 | static size_t rave_sp_receive_buf(struct serdev_device *serdev, |
475 | const u8 *buf, size_t size) |
476 | { |
477 | struct device *dev = &serdev->dev; |
478 | struct rave_sp *sp = dev_get_drvdata(dev); |
479 | struct rave_sp_deframer *deframer = &sp->deframer; |
480 | const u8 *src = buf; |
481 | const u8 *end = buf + size; |
482 | |
483 | while (src < end) { |
484 | const u8 byte = *src++; |
485 | |
486 | switch (deframer->state) { |
487 | case RAVE_SP_EXPECT_SOF: |
488 | if (byte == RAVE_SP_STX) |
489 | deframer->state = RAVE_SP_EXPECT_DATA; |
490 | break; |
491 | |
492 | case RAVE_SP_EXPECT_DATA: |
493 | /* |
494 | * Treat special byte values first |
495 | */ |
496 | switch (byte) { |
497 | case RAVE_SP_ETX: |
498 | rave_sp_receive_frame(sp, |
499 | data: deframer->data, |
500 | length: deframer->length); |
501 | /* |
502 | * Once we extracted a complete frame |
503 | * out of a stream, we call it done |
504 | * and proceed to bailing out while |
505 | * resetting the framer to initial |
506 | * state, regardless if we've consumed |
507 | * all of the stream or not. |
508 | */ |
509 | goto reset_framer; |
510 | case RAVE_SP_STX: |
511 | dev_warn(dev, "Bad frame: STX before ETX\n" ); |
512 | /* |
513 | * If we encounter second "start of |
514 | * the frame" marker before seeing |
515 | * corresponding "end of frame", we |
516 | * reset the framer and ignore both: |
517 | * frame started by first SOF and |
518 | * frame started by current SOF. |
519 | * |
520 | * NOTE: The above means that only the |
521 | * frame started by third SOF, sent |
522 | * after this one will have a chance |
523 | * to get throught. |
524 | */ |
525 | goto reset_framer; |
526 | case RAVE_SP_DLE: |
527 | deframer->state = RAVE_SP_EXPECT_ESCAPED_DATA; |
528 | /* |
529 | * If we encounter escape sequence we |
530 | * need to skip it and collect the |
531 | * byte that follows. We do it by |
532 | * forcing the next iteration of the |
533 | * encompassing while loop. |
534 | */ |
535 | continue; |
536 | } |
537 | /* |
538 | * For the rest of the bytes, that are not |
539 | * speical snoflakes, we do the same thing |
540 | * that we do to escaped data - collect it in |
541 | * deframer buffer |
542 | */ |
543 | |
544 | fallthrough; |
545 | |
546 | case RAVE_SP_EXPECT_ESCAPED_DATA: |
547 | if (deframer->length == sizeof(deframer->data)) { |
548 | dev_warn(dev, "Bad frame: Too long\n" ); |
549 | /* |
550 | * If the amount of data we've |
551 | * accumulated for current frame so |
552 | * far starts to exceed the capacity |
553 | * of deframer's buffer, there's |
554 | * nothing else we can do but to |
555 | * discard that data and start |
556 | * assemblying a new frame again |
557 | */ |
558 | goto reset_framer; |
559 | } |
560 | |
561 | deframer->data[deframer->length++] = byte; |
562 | |
563 | /* |
564 | * We've extracted out special byte, now we |
565 | * can go back to regular data collecting |
566 | */ |
567 | deframer->state = RAVE_SP_EXPECT_DATA; |
568 | break; |
569 | } |
570 | } |
571 | |
572 | /* |
573 | * The only way to get out of the above loop and end up here |
574 | * is throught consuming all of the supplied data, so here we |
575 | * report that we processed it all. |
576 | */ |
577 | return size; |
578 | |
579 | reset_framer: |
580 | /* |
581 | * NOTE: A number of codepaths that will drop us here will do |
582 | * so before consuming all 'size' bytes of the data passed by |
583 | * serdev layer. We rely on the fact that serdev layer will |
584 | * re-execute this handler with the remainder of the Rx bytes |
585 | * once we report actual number of bytes that we processed. |
586 | */ |
587 | deframer->state = RAVE_SP_EXPECT_SOF; |
588 | deframer->length = 0; |
589 | |
590 | return src - buf; |
591 | } |
592 | |
593 | static int rave_sp_rdu1_cmd_translate(enum rave_sp_command command) |
594 | { |
595 | if (command >= RAVE_SP_CMD_STATUS && |
596 | command <= RAVE_SP_CMD_CONTROL_EVENTS) |
597 | return command; |
598 | |
599 | return -EINVAL; |
600 | } |
601 | |
602 | static int rave_sp_rdu2_cmd_translate(enum rave_sp_command command) |
603 | { |
604 | if (command >= RAVE_SP_CMD_GET_FIRMWARE_VERSION && |
605 | command <= RAVE_SP_CMD_GET_GPIO_STATE) |
606 | return command; |
607 | |
608 | if (command == RAVE_SP_CMD_REQ_COPPER_REV) { |
609 | /* |
610 | * As per RDU2 ICD 3.4.47 CMD_GET_COPPER_REV code is |
611 | * different from that for RDU1 and it is set to 0x28. |
612 | */ |
613 | return 0x28; |
614 | } |
615 | |
616 | return rave_sp_rdu1_cmd_translate(command); |
617 | } |
618 | |
619 | static int rave_sp_default_cmd_translate(enum rave_sp_command command) |
620 | { |
621 | /* |
622 | * All of the following command codes were taken from "Table : |
623 | * Communications Protocol Message Types" in section 3.3 |
624 | * "MESSAGE TYPES" of Rave PIC24 ICD. |
625 | */ |
626 | switch (command) { |
627 | case RAVE_SP_CMD_GET_FIRMWARE_VERSION: |
628 | return 0x11; |
629 | case RAVE_SP_CMD_GET_BOOTLOADER_VERSION: |
630 | return 0x12; |
631 | case RAVE_SP_CMD_BOOT_SOURCE: |
632 | return 0x14; |
633 | case RAVE_SP_CMD_SW_WDT: |
634 | return 0x1C; |
635 | case RAVE_SP_CMD_PET_WDT: |
636 | return 0x1D; |
637 | case RAVE_SP_CMD_RESET: |
638 | return 0x1E; |
639 | case RAVE_SP_CMD_RESET_REASON: |
640 | return 0x1F; |
641 | case RAVE_SP_CMD_RMB_EEPROM: |
642 | return 0x20; |
643 | default: |
644 | return -EINVAL; |
645 | } |
646 | } |
647 | |
648 | static const char *devm_rave_sp_version(struct device *dev, |
649 | struct rave_sp_version *version) |
650 | { |
651 | /* |
652 | * NOTE: The format string below uses %02d to display u16 |
653 | * intentionally for the sake of backwards compatibility with |
654 | * legacy software. |
655 | */ |
656 | return devm_kasprintf(dev, GFP_KERNEL, fmt: "%02d%02d%02d.%c%c\n" , |
657 | version->hardware, |
658 | le16_to_cpu(version->major), |
659 | version->minor, |
660 | version->letter[0], |
661 | version->letter[1]); |
662 | } |
663 | |
664 | static int rave_sp_rdu1_get_status(struct rave_sp *sp, |
665 | struct rave_sp_status *status) |
666 | { |
667 | u8 cmd[] = { |
668 | [0] = RAVE_SP_CMD_STATUS, |
669 | [1] = 0 |
670 | }; |
671 | |
672 | return rave_sp_exec(sp, cmd, sizeof(cmd), status, sizeof(*status)); |
673 | } |
674 | |
675 | static int rave_sp_emulated_get_status(struct rave_sp *sp, |
676 | struct rave_sp_status *status) |
677 | { |
678 | u8 cmd[] = { |
679 | [0] = RAVE_SP_CMD_GET_FIRMWARE_VERSION, |
680 | [1] = 0, |
681 | }; |
682 | int ret; |
683 | |
684 | ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status->firmware_version, |
685 | sizeof(status->firmware_version)); |
686 | if (ret) |
687 | return ret; |
688 | |
689 | cmd[0] = RAVE_SP_CMD_GET_BOOTLOADER_VERSION; |
690 | return rave_sp_exec(sp, cmd, sizeof(cmd), &status->bootloader_version, |
691 | sizeof(status->bootloader_version)); |
692 | } |
693 | |
694 | static int rave_sp_get_status(struct rave_sp *sp) |
695 | { |
696 | struct device *dev = &sp->serdev->dev; |
697 | struct rave_sp_status status; |
698 | const char *version; |
699 | int ret; |
700 | |
701 | ret = sp->variant->cmd.get_status(sp, &status); |
702 | if (ret) |
703 | return ret; |
704 | |
705 | version = devm_rave_sp_version(dev, version: &status.firmware_version); |
706 | if (!version) |
707 | return -ENOMEM; |
708 | |
709 | sp->part_number_firmware = version; |
710 | |
711 | version = devm_rave_sp_version(dev, version: &status.bootloader_version); |
712 | if (!version) |
713 | return -ENOMEM; |
714 | |
715 | sp->part_number_bootloader = version; |
716 | |
717 | return 0; |
718 | } |
719 | |
720 | static const struct rave_sp_checksum rave_sp_checksum_8b2c = { |
721 | .length = 1, |
722 | .subroutine = csum_8b2c, |
723 | }; |
724 | |
725 | static const struct rave_sp_checksum rave_sp_checksum_ccitt = { |
726 | .length = 2, |
727 | .subroutine = csum_ccitt, |
728 | }; |
729 | |
730 | static const struct rave_sp_variant rave_sp_legacy = { |
731 | .checksum = &rave_sp_checksum_ccitt, |
732 | .cmd = { |
733 | .translate = rave_sp_default_cmd_translate, |
734 | .get_status = rave_sp_emulated_get_status, |
735 | }, |
736 | }; |
737 | |
738 | static const struct rave_sp_variant rave_sp_rdu1 = { |
739 | .checksum = &rave_sp_checksum_8b2c, |
740 | .cmd = { |
741 | .translate = rave_sp_rdu1_cmd_translate, |
742 | .get_status = rave_sp_rdu1_get_status, |
743 | }, |
744 | }; |
745 | |
746 | static const struct rave_sp_variant rave_sp_rdu2 = { |
747 | .checksum = &rave_sp_checksum_ccitt, |
748 | .cmd = { |
749 | .translate = rave_sp_rdu2_cmd_translate, |
750 | .get_status = rave_sp_emulated_get_status, |
751 | }, |
752 | }; |
753 | |
754 | static const struct of_device_id rave_sp_dt_ids[] = { |
755 | { .compatible = "zii,rave-sp-niu" , .data = &rave_sp_legacy }, |
756 | { .compatible = "zii,rave-sp-mezz" , .data = &rave_sp_legacy }, |
757 | { .compatible = "zii,rave-sp-esb" , .data = &rave_sp_legacy }, |
758 | { .compatible = "zii,rave-sp-rdu1" , .data = &rave_sp_rdu1 }, |
759 | { .compatible = "zii,rave-sp-rdu2" , .data = &rave_sp_rdu2 }, |
760 | { /* sentinel */ } |
761 | }; |
762 | |
763 | static const struct serdev_device_ops rave_sp_serdev_device_ops = { |
764 | .receive_buf = rave_sp_receive_buf, |
765 | .write_wakeup = serdev_device_write_wakeup, |
766 | }; |
767 | |
768 | static int rave_sp_probe(struct serdev_device *serdev) |
769 | { |
770 | struct device *dev = &serdev->dev; |
771 | const char *unknown = "unknown\n" ; |
772 | struct rave_sp *sp; |
773 | u32 baud; |
774 | int ret; |
775 | |
776 | if (of_property_read_u32(np: dev->of_node, propname: "current-speed" , out_value: &baud)) { |
777 | dev_err(dev, |
778 | "'current-speed' is not specified in device node\n" ); |
779 | return -EINVAL; |
780 | } |
781 | |
782 | sp = devm_kzalloc(dev, size: sizeof(*sp), GFP_KERNEL); |
783 | if (!sp) |
784 | return -ENOMEM; |
785 | |
786 | sp->serdev = serdev; |
787 | dev_set_drvdata(dev, data: sp); |
788 | |
789 | sp->variant = of_device_get_match_data(dev); |
790 | if (!sp->variant) |
791 | return -ENODEV; |
792 | |
793 | mutex_init(&sp->bus_lock); |
794 | mutex_init(&sp->reply_lock); |
795 | BLOCKING_INIT_NOTIFIER_HEAD(&sp->event_notifier_list); |
796 | |
797 | serdev_device_set_client_ops(serdev, ops: &rave_sp_serdev_device_ops); |
798 | ret = devm_serdev_device_open(dev, serdev); |
799 | if (ret) |
800 | return ret; |
801 | |
802 | serdev_device_set_baudrate(serdev, baud); |
803 | serdev_device_set_flow_control(serdev, false); |
804 | |
805 | ret = serdev_device_set_parity(serdev, parity: SERDEV_PARITY_NONE); |
806 | if (ret) { |
807 | dev_err(dev, "Failed to set parity\n" ); |
808 | return ret; |
809 | } |
810 | |
811 | ret = rave_sp_get_status(sp); |
812 | if (ret) { |
813 | dev_warn(dev, "Failed to get firmware status: %d\n" , ret); |
814 | sp->part_number_firmware = unknown; |
815 | sp->part_number_bootloader = unknown; |
816 | } |
817 | |
818 | /* |
819 | * Those strings already have a \n embedded, so there's no |
820 | * need to have one in format string. |
821 | */ |
822 | dev_info(dev, "Firmware version: %s" , sp->part_number_firmware); |
823 | dev_info(dev, "Bootloader version: %s" , sp->part_number_bootloader); |
824 | |
825 | return devm_of_platform_populate(dev); |
826 | } |
827 | |
828 | MODULE_DEVICE_TABLE(of, rave_sp_dt_ids); |
829 | |
830 | static struct serdev_device_driver rave_sp_drv = { |
831 | .probe = rave_sp_probe, |
832 | .driver = { |
833 | .name = "rave-sp" , |
834 | .of_match_table = rave_sp_dt_ids, |
835 | }, |
836 | }; |
837 | module_serdev_device_driver(rave_sp_drv); |
838 | |
839 | MODULE_LICENSE("GPL" ); |
840 | MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>" ); |
841 | MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>" ); |
842 | MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>" ); |
843 | MODULE_DESCRIPTION("RAVE SP core driver" ); |
844 | |