xref: /openbmc/linux/drivers/mfd/rave-sp.c (revision 6c450bdf)
1538ee272SAndrey Smirnov // SPDX-License-Identifier: GPL-2.0+
2538ee272SAndrey Smirnov 
3538ee272SAndrey Smirnov /*
4538ee272SAndrey Smirnov  * Multifunction core driver for Zodiac Inflight Innovations RAVE
5538ee272SAndrey Smirnov  * Supervisory Processor(SP) MCU that is connected via dedicated UART
6538ee272SAndrey Smirnov  * port
7538ee272SAndrey Smirnov  *
8538ee272SAndrey Smirnov  * Copyright (C) 2017 Zodiac Inflight Innovations
9538ee272SAndrey Smirnov  */
10538ee272SAndrey Smirnov 
11538ee272SAndrey Smirnov #include <linux/atomic.h>
12538ee272SAndrey Smirnov #include <linux/crc-ccitt.h>
13538ee272SAndrey Smirnov #include <linux/delay.h>
14538ee272SAndrey Smirnov #include <linux/export.h>
15538ee272SAndrey Smirnov #include <linux/init.h>
16538ee272SAndrey Smirnov #include <linux/slab.h>
17538ee272SAndrey Smirnov #include <linux/kernel.h>
18538ee272SAndrey Smirnov #include <linux/mfd/rave-sp.h>
19538ee272SAndrey Smirnov #include <linux/module.h>
20538ee272SAndrey Smirnov #include <linux/of.h>
21538ee272SAndrey Smirnov #include <linux/of_device.h>
22538ee272SAndrey Smirnov #include <linux/sched.h>
23538ee272SAndrey Smirnov #include <linux/serdev.h>
24538ee272SAndrey Smirnov #include <asm/unaligned.h>
25538ee272SAndrey Smirnov 
26538ee272SAndrey Smirnov /*
27538ee272SAndrey Smirnov  * UART protocol using following entities:
28538ee272SAndrey Smirnov  *  - message to MCU => ACK response
29538ee272SAndrey Smirnov  *  - event from MCU => event ACK
30538ee272SAndrey Smirnov  *
31538ee272SAndrey Smirnov  * Frame structure:
32538ee272SAndrey Smirnov  * <STX> <DATA> <CHECKSUM> <ETX>
33538ee272SAndrey Smirnov  * Where:
34538ee272SAndrey Smirnov  * - STX - is start of transmission character
35538ee272SAndrey Smirnov  * - ETX - end of transmission
36538ee272SAndrey Smirnov  * - DATA - payload
37538ee272SAndrey Smirnov  * - CHECKSUM - checksum calculated on <DATA>
38538ee272SAndrey Smirnov  *
39538ee272SAndrey Smirnov  * If <DATA> or <CHECKSUM> contain one of control characters, then it is
40538ee272SAndrey Smirnov  * escaped using <DLE> control code. Added <DLE> does not participate in
41538ee272SAndrey Smirnov  * checksum calculation.
42538ee272SAndrey Smirnov  */
43538ee272SAndrey Smirnov #define RAVE_SP_STX			0x02
44538ee272SAndrey Smirnov #define RAVE_SP_ETX			0x03
45538ee272SAndrey Smirnov #define RAVE_SP_DLE			0x10
46538ee272SAndrey Smirnov 
47538ee272SAndrey Smirnov #define RAVE_SP_MAX_DATA_SIZE		64
487169483cSKyle Spiers #define RAVE_SP_CHECKSUM_8B2C		1
497169483cSKyle Spiers #define RAVE_SP_CHECKSUM_CCITT		2
507169483cSKyle Spiers #define RAVE_SP_CHECKSUM_SIZE		RAVE_SP_CHECKSUM_CCITT
51538ee272SAndrey Smirnov /*
52538ee272SAndrey Smirnov  * We don't store STX, ETX and unescaped bytes, so Rx is only
53538ee272SAndrey Smirnov  * DATA + CSUM
54538ee272SAndrey Smirnov  */
55538ee272SAndrey Smirnov #define RAVE_SP_RX_BUFFER_SIZE				\
56538ee272SAndrey Smirnov 	(RAVE_SP_MAX_DATA_SIZE + RAVE_SP_CHECKSUM_SIZE)
57538ee272SAndrey Smirnov 
58538ee272SAndrey Smirnov #define RAVE_SP_STX_ETX_SIZE		2
59538ee272SAndrey Smirnov /*
60538ee272SAndrey Smirnov  * For Tx we have to have space for everything, STX, EXT and
61538ee272SAndrey Smirnov  * potentially stuffed DATA + CSUM data + csum
62538ee272SAndrey Smirnov  */
63538ee272SAndrey Smirnov #define RAVE_SP_TX_BUFFER_SIZE				\
64538ee272SAndrey Smirnov 	(RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE)
65538ee272SAndrey Smirnov 
66538ee272SAndrey Smirnov /**
67538ee272SAndrey Smirnov  * enum rave_sp_deframer_state - Possible state for de-framer
68538ee272SAndrey Smirnov  *
69538ee272SAndrey Smirnov  * @RAVE_SP_EXPECT_SOF:		 Scanning input for start-of-frame marker
70538ee272SAndrey Smirnov  * @RAVE_SP_EXPECT_DATA:	 Got start of frame marker, collecting frame
71538ee272SAndrey Smirnov  * @RAVE_SP_EXPECT_ESCAPED_DATA: Got escape character, collecting escaped byte
72538ee272SAndrey Smirnov  */
73538ee272SAndrey Smirnov enum rave_sp_deframer_state {
74538ee272SAndrey Smirnov 	RAVE_SP_EXPECT_SOF,
75538ee272SAndrey Smirnov 	RAVE_SP_EXPECT_DATA,
76538ee272SAndrey Smirnov 	RAVE_SP_EXPECT_ESCAPED_DATA,
77538ee272SAndrey Smirnov };
78538ee272SAndrey Smirnov 
79538ee272SAndrey Smirnov /**
80538ee272SAndrey Smirnov  * struct rave_sp_deframer - Device protocol deframer
81538ee272SAndrey Smirnov  *
82538ee272SAndrey Smirnov  * @state:  Current state of the deframer
83538ee272SAndrey Smirnov  * @data:   Buffer used to collect deframed data
84538ee272SAndrey Smirnov  * @length: Number of bytes de-framed so far
85538ee272SAndrey Smirnov  */
86538ee272SAndrey Smirnov struct rave_sp_deframer {
87538ee272SAndrey Smirnov 	enum rave_sp_deframer_state state;
88538ee272SAndrey Smirnov 	unsigned char data[RAVE_SP_RX_BUFFER_SIZE];
89538ee272SAndrey Smirnov 	size_t length;
90538ee272SAndrey Smirnov };
91538ee272SAndrey Smirnov 
92538ee272SAndrey Smirnov /**
93538ee272SAndrey Smirnov  * struct rave_sp_reply - Reply as per RAVE device protocol
94538ee272SAndrey Smirnov  *
95538ee272SAndrey Smirnov  * @length:	Expected reply length
96538ee272SAndrey Smirnov  * @data:	Buffer to store reply payload in
97538ee272SAndrey Smirnov  * @code:	Expected reply code
98538ee272SAndrey Smirnov  * @ackid:	Expected reply ACK ID
99538ee272SAndrey Smirnov  * @completion: Successful reply reception completion
100538ee272SAndrey Smirnov  */
101538ee272SAndrey Smirnov struct rave_sp_reply {
102538ee272SAndrey Smirnov 	size_t length;
103538ee272SAndrey Smirnov 	void  *data;
104538ee272SAndrey Smirnov 	u8     code;
105538ee272SAndrey Smirnov 	u8     ackid;
106538ee272SAndrey Smirnov 	struct completion received;
107538ee272SAndrey Smirnov };
108538ee272SAndrey Smirnov 
109538ee272SAndrey Smirnov /**
110538ee272SAndrey Smirnov  * struct rave_sp_checksum - Variant specific checksum implementation details
111538ee272SAndrey Smirnov  *
112538ee272SAndrey Smirnov  * @length:	Caculated checksum length
113538ee272SAndrey Smirnov  * @subroutine:	Utilized checksum algorithm implementation
114538ee272SAndrey Smirnov  */
115538ee272SAndrey Smirnov struct rave_sp_checksum {
116538ee272SAndrey Smirnov 	size_t length;
117538ee272SAndrey Smirnov 	void (*subroutine)(const u8 *, size_t, u8 *);
118538ee272SAndrey Smirnov };
119538ee272SAndrey Smirnov 
120538ee272SAndrey Smirnov /**
121538ee272SAndrey Smirnov  * struct rave_sp_variant_cmds - Variant specific command routines
122538ee272SAndrey Smirnov  *
123538ee272SAndrey Smirnov  * @translate:	Generic to variant specific command mapping routine
124538ee272SAndrey Smirnov  *
125538ee272SAndrey Smirnov  */
126538ee272SAndrey Smirnov struct rave_sp_variant_cmds {
127538ee272SAndrey Smirnov 	int (*translate)(enum rave_sp_command);
128538ee272SAndrey Smirnov };
129538ee272SAndrey Smirnov 
130538ee272SAndrey Smirnov /**
131538ee272SAndrey Smirnov  * struct rave_sp_variant - RAVE supervisory processor core variant
132538ee272SAndrey Smirnov  *
133538ee272SAndrey Smirnov  * @checksum:	Variant specific checksum implementation
134538ee272SAndrey Smirnov  * @cmd:	Variant specific command pointer table
135538ee272SAndrey Smirnov  *
136538ee272SAndrey Smirnov  */
137538ee272SAndrey Smirnov struct rave_sp_variant {
138538ee272SAndrey Smirnov 	const struct rave_sp_checksum *checksum;
139538ee272SAndrey Smirnov 	struct rave_sp_variant_cmds cmd;
140538ee272SAndrey Smirnov };
141538ee272SAndrey Smirnov 
142538ee272SAndrey Smirnov /**
143538ee272SAndrey Smirnov  * struct rave_sp - RAVE supervisory processor core
144538ee272SAndrey Smirnov  *
145538ee272SAndrey Smirnov  * @serdev:			Pointer to underlying serdev
146538ee272SAndrey Smirnov  * @deframer:			Stored state of the protocol deframer
147538ee272SAndrey Smirnov  * @ackid:			ACK ID used in last reply sent to the device
148538ee272SAndrey Smirnov  * @bus_lock:			Lock to serialize access to the device
149538ee272SAndrey Smirnov  * @reply_lock:			Lock protecting @reply
150538ee272SAndrey Smirnov  * @reply:			Pointer to memory to store reply payload
151538ee272SAndrey Smirnov  *
152538ee272SAndrey Smirnov  * @variant:			Device variant specific information
153538ee272SAndrey Smirnov  * @event_notifier_list:	Input event notification chain
154538ee272SAndrey Smirnov  *
1556d97b6f1SAndrey Smirnov  * @part_number_firmware:	Firmware version
1566d97b6f1SAndrey Smirnov  * @part_number_bootloader:	Bootloader version
157538ee272SAndrey Smirnov  */
158538ee272SAndrey Smirnov struct rave_sp {
159538ee272SAndrey Smirnov 	struct serdev_device *serdev;
160538ee272SAndrey Smirnov 	struct rave_sp_deframer deframer;
161538ee272SAndrey Smirnov 	atomic_t ackid;
162538ee272SAndrey Smirnov 	struct mutex bus_lock;
163538ee272SAndrey Smirnov 	struct mutex reply_lock;
164538ee272SAndrey Smirnov 	struct rave_sp_reply *reply;
165538ee272SAndrey Smirnov 
166538ee272SAndrey Smirnov 	const struct rave_sp_variant *variant;
167538ee272SAndrey Smirnov 	struct blocking_notifier_head event_notifier_list;
1686d97b6f1SAndrey Smirnov 
1696d97b6f1SAndrey Smirnov 	const char *part_number_firmware;
1706d97b6f1SAndrey Smirnov 	const char *part_number_bootloader;
171538ee272SAndrey Smirnov };
172538ee272SAndrey Smirnov 
1736d97b6f1SAndrey Smirnov struct rave_sp_version {
1746d97b6f1SAndrey Smirnov 	u8     hardware;
1756d97b6f1SAndrey Smirnov 	__le16 major;
1766d97b6f1SAndrey Smirnov 	u8     minor;
1776d97b6f1SAndrey Smirnov 	u8     letter[2];
1786d97b6f1SAndrey Smirnov } __packed;
1796d97b6f1SAndrey Smirnov 
1806d97b6f1SAndrey Smirnov struct rave_sp_status {
1816d97b6f1SAndrey Smirnov 	struct rave_sp_version bootloader_version;
1826d97b6f1SAndrey Smirnov 	struct rave_sp_version firmware_version;
1836d97b6f1SAndrey Smirnov 	u16 rdu_eeprom_flag;
1846d97b6f1SAndrey Smirnov 	u16 dds_eeprom_flag;
1856d97b6f1SAndrey Smirnov 	u8  pic_flag;
1866d97b6f1SAndrey Smirnov 	u8  orientation;
1876d97b6f1SAndrey Smirnov 	u32 etc;
1886d97b6f1SAndrey Smirnov 	s16 temp[2];
1896d97b6f1SAndrey Smirnov 	u8  backlight_current[3];
1906d97b6f1SAndrey Smirnov 	u8  dip_switch;
1916d97b6f1SAndrey Smirnov 	u8  host_interrupt;
1926d97b6f1SAndrey Smirnov 	u16 voltage_28;
1936d97b6f1SAndrey Smirnov 	u8  i2c_device_status;
1946d97b6f1SAndrey Smirnov 	u8  power_status;
1956d97b6f1SAndrey Smirnov 	u8  general_status;
1966d97b6f1SAndrey Smirnov 	u8  deprecated1;
1976d97b6f1SAndrey Smirnov 	u8  power_led_status;
1986d97b6f1SAndrey Smirnov 	u8  deprecated2;
1996d97b6f1SAndrey Smirnov 	u8  periph_power_shutoff;
2006d97b6f1SAndrey Smirnov } __packed;
2016d97b6f1SAndrey Smirnov 
202538ee272SAndrey Smirnov static bool rave_sp_id_is_event(u8 code)
203538ee272SAndrey Smirnov {
204538ee272SAndrey Smirnov 	return (code & 0xF0) == RAVE_SP_EVNT_BASE;
205538ee272SAndrey Smirnov }
206538ee272SAndrey Smirnov 
207538ee272SAndrey Smirnov static void rave_sp_unregister_event_notifier(struct device *dev, void *res)
208538ee272SAndrey Smirnov {
209538ee272SAndrey Smirnov 	struct rave_sp *sp = dev_get_drvdata(dev->parent);
210538ee272SAndrey Smirnov 	struct notifier_block *nb = *(struct notifier_block **)res;
211538ee272SAndrey Smirnov 	struct blocking_notifier_head *bnh = &sp->event_notifier_list;
212538ee272SAndrey Smirnov 
213538ee272SAndrey Smirnov 	WARN_ON(blocking_notifier_chain_unregister(bnh, nb));
214538ee272SAndrey Smirnov }
215538ee272SAndrey Smirnov 
216538ee272SAndrey Smirnov int devm_rave_sp_register_event_notifier(struct device *dev,
217538ee272SAndrey Smirnov 					 struct notifier_block *nb)
218538ee272SAndrey Smirnov {
219538ee272SAndrey Smirnov 	struct rave_sp *sp = dev_get_drvdata(dev->parent);
220538ee272SAndrey Smirnov 	struct notifier_block **rcnb;
221538ee272SAndrey Smirnov 	int ret;
222538ee272SAndrey Smirnov 
223538ee272SAndrey Smirnov 	rcnb = devres_alloc(rave_sp_unregister_event_notifier,
224538ee272SAndrey Smirnov 			    sizeof(*rcnb), GFP_KERNEL);
225538ee272SAndrey Smirnov 	if (!rcnb)
226538ee272SAndrey Smirnov 		return -ENOMEM;
227538ee272SAndrey Smirnov 
228538ee272SAndrey Smirnov 	ret = blocking_notifier_chain_register(&sp->event_notifier_list, nb);
229538ee272SAndrey Smirnov 	if (!ret) {
230538ee272SAndrey Smirnov 		*rcnb = nb;
231538ee272SAndrey Smirnov 		devres_add(dev, rcnb);
232538ee272SAndrey Smirnov 	} else {
233538ee272SAndrey Smirnov 		devres_free(rcnb);
234538ee272SAndrey Smirnov 	}
235538ee272SAndrey Smirnov 
236538ee272SAndrey Smirnov 	return ret;
237538ee272SAndrey Smirnov }
238538ee272SAndrey Smirnov EXPORT_SYMBOL_GPL(devm_rave_sp_register_event_notifier);
239538ee272SAndrey Smirnov 
240538ee272SAndrey Smirnov static void csum_8b2c(const u8 *buf, size_t size, u8 *crc)
241538ee272SAndrey Smirnov {
242538ee272SAndrey Smirnov 	*crc = *buf++;
243538ee272SAndrey Smirnov 	size--;
244538ee272SAndrey Smirnov 
245538ee272SAndrey Smirnov 	while (size--)
246538ee272SAndrey Smirnov 		*crc += *buf++;
247538ee272SAndrey Smirnov 
248538ee272SAndrey Smirnov 	*crc = 1 + ~(*crc);
249538ee272SAndrey Smirnov }
250538ee272SAndrey Smirnov 
251538ee272SAndrey Smirnov static void csum_ccitt(const u8 *buf, size_t size, u8 *crc)
252538ee272SAndrey Smirnov {
253538ee272SAndrey Smirnov 	const u16 calculated = crc_ccitt_false(0xffff, buf, size);
254538ee272SAndrey Smirnov 
255538ee272SAndrey Smirnov 	/*
256538ee272SAndrey Smirnov 	 * While the rest of the wire protocol is little-endian,
257538ee272SAndrey Smirnov 	 * CCITT-16 CRC in RDU2 device is sent out in big-endian order.
258538ee272SAndrey Smirnov 	 */
259538ee272SAndrey Smirnov 	put_unaligned_be16(calculated, crc);
260538ee272SAndrey Smirnov }
261538ee272SAndrey Smirnov 
262538ee272SAndrey Smirnov static void *stuff(unsigned char *dest, const unsigned char *src, size_t n)
263538ee272SAndrey Smirnov {
264538ee272SAndrey Smirnov 	while (n--) {
265538ee272SAndrey Smirnov 		const unsigned char byte = *src++;
266538ee272SAndrey Smirnov 
267538ee272SAndrey Smirnov 		switch (byte) {
268538ee272SAndrey Smirnov 		case RAVE_SP_STX:
269538ee272SAndrey Smirnov 		case RAVE_SP_ETX:
270538ee272SAndrey Smirnov 		case RAVE_SP_DLE:
271538ee272SAndrey Smirnov 			*dest++ = RAVE_SP_DLE;
272538ee272SAndrey Smirnov 			/* FALLTHROUGH */
273538ee272SAndrey Smirnov 		default:
274538ee272SAndrey Smirnov 			*dest++ = byte;
275538ee272SAndrey Smirnov 		}
276538ee272SAndrey Smirnov 	}
277538ee272SAndrey Smirnov 
278538ee272SAndrey Smirnov 	return dest;
279538ee272SAndrey Smirnov }
280538ee272SAndrey Smirnov 
281538ee272SAndrey Smirnov static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
282538ee272SAndrey Smirnov {
283538ee272SAndrey Smirnov 	const size_t checksum_length = sp->variant->checksum->length;
284538ee272SAndrey Smirnov 	unsigned char frame[RAVE_SP_TX_BUFFER_SIZE];
285538ee272SAndrey Smirnov 	unsigned char crc[RAVE_SP_CHECKSUM_SIZE];
286538ee272SAndrey Smirnov 	unsigned char *dest = frame;
287538ee272SAndrey Smirnov 	size_t length;
288538ee272SAndrey Smirnov 
289538ee272SAndrey Smirnov 	if (WARN_ON(checksum_length > sizeof(crc)))
290538ee272SAndrey Smirnov 		return -ENOMEM;
291538ee272SAndrey Smirnov 
292538ee272SAndrey Smirnov 	if (WARN_ON(data_size > sizeof(frame)))
293538ee272SAndrey Smirnov 		return -ENOMEM;
294538ee272SAndrey Smirnov 
295538ee272SAndrey Smirnov 	sp->variant->checksum->subroutine(data, data_size, crc);
296538ee272SAndrey Smirnov 
297538ee272SAndrey Smirnov 	*dest++ = RAVE_SP_STX;
298538ee272SAndrey Smirnov 	dest = stuff(dest, data, data_size);
299538ee272SAndrey Smirnov 	dest = stuff(dest, crc, checksum_length);
300538ee272SAndrey Smirnov 	*dest++ = RAVE_SP_ETX;
301538ee272SAndrey Smirnov 
302538ee272SAndrey Smirnov 	length = dest - frame;
303538ee272SAndrey Smirnov 
30444564bc3SAndrey Smirnov 	print_hex_dump_debug("rave-sp tx: ", DUMP_PREFIX_NONE,
305538ee272SAndrey Smirnov 			     16, 1, frame, length, false);
306538ee272SAndrey Smirnov 
307538ee272SAndrey Smirnov 	return serdev_device_write(sp->serdev, frame, length, HZ);
308538ee272SAndrey Smirnov }
309538ee272SAndrey Smirnov 
310538ee272SAndrey Smirnov static u8 rave_sp_reply_code(u8 command)
311538ee272SAndrey Smirnov {
312538ee272SAndrey Smirnov 	/*
313538ee272SAndrey Smirnov 	 * There isn't a single rule that describes command code ->
314538ee272SAndrey Smirnov 	 * ACK code transformation, but, going through various
315538ee272SAndrey Smirnov 	 * versions of ICDs, there appear to be three distinct groups
316538ee272SAndrey Smirnov 	 * that can be described by simple transformation.
317538ee272SAndrey Smirnov 	 */
318538ee272SAndrey Smirnov 	switch (command) {
319538ee272SAndrey Smirnov 	case 0xA0 ... 0xBE:
320538ee272SAndrey Smirnov 		/*
321538ee272SAndrey Smirnov 		 * Commands implemented by firmware found in RDU1 and
322538ee272SAndrey Smirnov 		 * older devices all seem to obey the following rule
323538ee272SAndrey Smirnov 		 */
324538ee272SAndrey Smirnov 		return command + 0x20;
325538ee272SAndrey Smirnov 	case 0xE0 ... 0xEF:
326538ee272SAndrey Smirnov 		/*
327538ee272SAndrey Smirnov 		 * Events emitted by all versions of the firmare use
328538ee272SAndrey Smirnov 		 * least significant bit to get an ACK code
329538ee272SAndrey Smirnov 		 */
330538ee272SAndrey Smirnov 		return command | 0x01;
331538ee272SAndrey Smirnov 	default:
332538ee272SAndrey Smirnov 		/*
333538ee272SAndrey Smirnov 		 * Commands implemented by firmware found in RDU2 are
334538ee272SAndrey Smirnov 		 * similar to "old" commands, but they use slightly
335538ee272SAndrey Smirnov 		 * different offset
336538ee272SAndrey Smirnov 		 */
337538ee272SAndrey Smirnov 		return command + 0x40;
338538ee272SAndrey Smirnov 	}
339538ee272SAndrey Smirnov }
340538ee272SAndrey Smirnov 
341538ee272SAndrey Smirnov int rave_sp_exec(struct rave_sp *sp,
342538ee272SAndrey Smirnov 		 void *__data,  size_t data_size,
343538ee272SAndrey Smirnov 		 void *reply_data, size_t reply_data_size)
344538ee272SAndrey Smirnov {
345538ee272SAndrey Smirnov 	struct rave_sp_reply reply = {
346538ee272SAndrey Smirnov 		.data     = reply_data,
347538ee272SAndrey Smirnov 		.length   = reply_data_size,
348538ee272SAndrey Smirnov 		.received = COMPLETION_INITIALIZER_ONSTACK(reply.received),
349538ee272SAndrey Smirnov 	};
350538ee272SAndrey Smirnov 	unsigned char *data = __data;
351538ee272SAndrey Smirnov 	int command, ret = 0;
352538ee272SAndrey Smirnov 	u8 ackid;
353538ee272SAndrey Smirnov 
354538ee272SAndrey Smirnov 	command = sp->variant->cmd.translate(data[0]);
355538ee272SAndrey Smirnov 	if (command < 0)
356538ee272SAndrey Smirnov 		return command;
357538ee272SAndrey Smirnov 
358538ee272SAndrey Smirnov 	ackid       = atomic_inc_return(&sp->ackid);
359538ee272SAndrey Smirnov 	reply.ackid = ackid;
360538ee272SAndrey Smirnov 	reply.code  = rave_sp_reply_code((u8)command),
361538ee272SAndrey Smirnov 
362538ee272SAndrey Smirnov 	mutex_lock(&sp->bus_lock);
363538ee272SAndrey Smirnov 
364538ee272SAndrey Smirnov 	mutex_lock(&sp->reply_lock);
365538ee272SAndrey Smirnov 	sp->reply = &reply;
366538ee272SAndrey Smirnov 	mutex_unlock(&sp->reply_lock);
367538ee272SAndrey Smirnov 
368538ee272SAndrey Smirnov 	data[0] = command;
369538ee272SAndrey Smirnov 	data[1] = ackid;
370538ee272SAndrey Smirnov 
371538ee272SAndrey Smirnov 	rave_sp_write(sp, data, data_size);
372538ee272SAndrey Smirnov 
373538ee272SAndrey Smirnov 	if (!wait_for_completion_timeout(&reply.received, HZ)) {
374538ee272SAndrey Smirnov 		dev_err(&sp->serdev->dev, "Command timeout\n");
375538ee272SAndrey Smirnov 		ret = -ETIMEDOUT;
376538ee272SAndrey Smirnov 
377538ee272SAndrey Smirnov 		mutex_lock(&sp->reply_lock);
378538ee272SAndrey Smirnov 		sp->reply = NULL;
379538ee272SAndrey Smirnov 		mutex_unlock(&sp->reply_lock);
380538ee272SAndrey Smirnov 	}
381538ee272SAndrey Smirnov 
382538ee272SAndrey Smirnov 	mutex_unlock(&sp->bus_lock);
383538ee272SAndrey Smirnov 	return ret;
384538ee272SAndrey Smirnov }
385538ee272SAndrey Smirnov EXPORT_SYMBOL_GPL(rave_sp_exec);
386538ee272SAndrey Smirnov 
387538ee272SAndrey Smirnov static void rave_sp_receive_event(struct rave_sp *sp,
388538ee272SAndrey Smirnov 				  const unsigned char *data, size_t length)
389538ee272SAndrey Smirnov {
390538ee272SAndrey Smirnov 	u8 cmd[] = {
391538ee272SAndrey Smirnov 		[0] = rave_sp_reply_code(data[0]),
392538ee272SAndrey Smirnov 		[1] = data[1],
393538ee272SAndrey Smirnov 	};
394538ee272SAndrey Smirnov 
395538ee272SAndrey Smirnov 	rave_sp_write(sp, cmd, sizeof(cmd));
396538ee272SAndrey Smirnov 
397538ee272SAndrey Smirnov 	blocking_notifier_call_chain(&sp->event_notifier_list,
398538ee272SAndrey Smirnov 				     rave_sp_action_pack(data[0], data[2]),
399538ee272SAndrey Smirnov 				     NULL);
400538ee272SAndrey Smirnov }
401538ee272SAndrey Smirnov 
402538ee272SAndrey Smirnov static void rave_sp_receive_reply(struct rave_sp *sp,
403538ee272SAndrey Smirnov 				  const unsigned char *data, size_t length)
404538ee272SAndrey Smirnov {
405538ee272SAndrey Smirnov 	struct device *dev = &sp->serdev->dev;
406538ee272SAndrey Smirnov 	struct rave_sp_reply *reply;
407538ee272SAndrey Smirnov 	const  size_t payload_length = length - 2;
408538ee272SAndrey Smirnov 
409538ee272SAndrey Smirnov 	mutex_lock(&sp->reply_lock);
410538ee272SAndrey Smirnov 	reply = sp->reply;
411538ee272SAndrey Smirnov 
412538ee272SAndrey Smirnov 	if (reply) {
413538ee272SAndrey Smirnov 		if (reply->code == data[0] && reply->ackid == data[1] &&
414538ee272SAndrey Smirnov 		    payload_length >= reply->length) {
415538ee272SAndrey Smirnov 			/*
416538ee272SAndrey Smirnov 			 * We are relying on memcpy(dst, src, 0) to be a no-op
417538ee272SAndrey Smirnov 			 * when handling commands that have a no-payload reply
418538ee272SAndrey Smirnov 			 */
419538ee272SAndrey Smirnov 			memcpy(reply->data, &data[2], reply->length);
420538ee272SAndrey Smirnov 			complete(&reply->received);
421538ee272SAndrey Smirnov 			sp->reply = NULL;
422538ee272SAndrey Smirnov 		} else {
423538ee272SAndrey Smirnov 			dev_err(dev, "Ignoring incorrect reply\n");
424538ee272SAndrey Smirnov 			dev_dbg(dev, "Code:   expected = 0x%08x received = 0x%08x\n",
425538ee272SAndrey Smirnov 				reply->code, data[0]);
426538ee272SAndrey Smirnov 			dev_dbg(dev, "ACK ID: expected = 0x%08x received = 0x%08x\n",
427538ee272SAndrey Smirnov 				reply->ackid, data[1]);
428538ee272SAndrey Smirnov 			dev_dbg(dev, "Length: expected = %zu received = %zu\n",
429538ee272SAndrey Smirnov 				reply->length, payload_length);
430538ee272SAndrey Smirnov 		}
431538ee272SAndrey Smirnov 	}
432538ee272SAndrey Smirnov 
433538ee272SAndrey Smirnov 	mutex_unlock(&sp->reply_lock);
434538ee272SAndrey Smirnov }
435538ee272SAndrey Smirnov 
436538ee272SAndrey Smirnov static void rave_sp_receive_frame(struct rave_sp *sp,
437538ee272SAndrey Smirnov 				  const unsigned char *data,
438538ee272SAndrey Smirnov 				  size_t length)
439538ee272SAndrey Smirnov {
440538ee272SAndrey Smirnov 	const size_t checksum_length = sp->variant->checksum->length;
441538ee272SAndrey Smirnov 	const size_t payload_length  = length - checksum_length;
442538ee272SAndrey Smirnov 	const u8 *crc_reported       = &data[payload_length];
443538ee272SAndrey Smirnov 	struct device *dev           = &sp->serdev->dev;
4447169483cSKyle Spiers 	u8 crc_calculated[RAVE_SP_CHECKSUM_SIZE];
4457169483cSKyle Spiers 
4467169483cSKyle Spiers 	if (unlikely(checksum_length > sizeof(crc_calculated))) {
4477169483cSKyle Spiers 		dev_warn(dev, "Checksum too long, dropping\n");
4487169483cSKyle Spiers 		return;
4497169483cSKyle Spiers 	}
450538ee272SAndrey Smirnov 
45144564bc3SAndrey Smirnov 	print_hex_dump_debug("rave-sp rx: ", DUMP_PREFIX_NONE,
452538ee272SAndrey Smirnov 			     16, 1, data, length, false);
453538ee272SAndrey Smirnov 
454538ee272SAndrey Smirnov 	if (unlikely(length <= checksum_length)) {
455538ee272SAndrey Smirnov 		dev_warn(dev, "Dropping short frame\n");
456538ee272SAndrey Smirnov 		return;
457538ee272SAndrey Smirnov 	}
458538ee272SAndrey Smirnov 
459538ee272SAndrey Smirnov 	sp->variant->checksum->subroutine(data, payload_length,
460538ee272SAndrey Smirnov 					  crc_calculated);
461538ee272SAndrey Smirnov 
462538ee272SAndrey Smirnov 	if (memcmp(crc_calculated, crc_reported, checksum_length)) {
463538ee272SAndrey Smirnov 		dev_warn(dev, "Dropping bad frame\n");
464538ee272SAndrey Smirnov 		return;
465538ee272SAndrey Smirnov 	}
466538ee272SAndrey Smirnov 
467538ee272SAndrey Smirnov 	if (rave_sp_id_is_event(data[0]))
468538ee272SAndrey Smirnov 		rave_sp_receive_event(sp, data, length);
469538ee272SAndrey Smirnov 	else
470538ee272SAndrey Smirnov 		rave_sp_receive_reply(sp, data, length);
471538ee272SAndrey Smirnov }
472538ee272SAndrey Smirnov 
473538ee272SAndrey Smirnov static int rave_sp_receive_buf(struct serdev_device *serdev,
474538ee272SAndrey Smirnov 			       const unsigned char *buf, size_t size)
475538ee272SAndrey Smirnov {
476538ee272SAndrey Smirnov 	struct device *dev = &serdev->dev;
477538ee272SAndrey Smirnov 	struct rave_sp *sp = dev_get_drvdata(dev);
478538ee272SAndrey Smirnov 	struct rave_sp_deframer *deframer = &sp->deframer;
479538ee272SAndrey Smirnov 	const unsigned char *src = buf;
480538ee272SAndrey Smirnov 	const unsigned char *end = buf + size;
481538ee272SAndrey Smirnov 
482538ee272SAndrey Smirnov 	while (src < end) {
483538ee272SAndrey Smirnov 		const unsigned char byte = *src++;
484538ee272SAndrey Smirnov 
485538ee272SAndrey Smirnov 		switch (deframer->state) {
486538ee272SAndrey Smirnov 		case RAVE_SP_EXPECT_SOF:
487538ee272SAndrey Smirnov 			if (byte == RAVE_SP_STX)
488538ee272SAndrey Smirnov 				deframer->state = RAVE_SP_EXPECT_DATA;
489538ee272SAndrey Smirnov 			break;
490538ee272SAndrey Smirnov 
491538ee272SAndrey Smirnov 		case RAVE_SP_EXPECT_DATA:
492538ee272SAndrey Smirnov 			/*
493538ee272SAndrey Smirnov 			 * Treat special byte values first
494538ee272SAndrey Smirnov 			 */
495538ee272SAndrey Smirnov 			switch (byte) {
496538ee272SAndrey Smirnov 			case RAVE_SP_ETX:
497538ee272SAndrey Smirnov 				rave_sp_receive_frame(sp,
498538ee272SAndrey Smirnov 						      deframer->data,
499538ee272SAndrey Smirnov 						      deframer->length);
500538ee272SAndrey Smirnov 				/*
501538ee272SAndrey Smirnov 				 * Once we extracted a complete frame
502538ee272SAndrey Smirnov 				 * out of a stream, we call it done
503538ee272SAndrey Smirnov 				 * and proceed to bailing out while
504538ee272SAndrey Smirnov 				 * resetting the framer to initial
505538ee272SAndrey Smirnov 				 * state, regardless if we've consumed
506538ee272SAndrey Smirnov 				 * all of the stream or not.
507538ee272SAndrey Smirnov 				 */
508538ee272SAndrey Smirnov 				goto reset_framer;
509538ee272SAndrey Smirnov 			case RAVE_SP_STX:
510538ee272SAndrey Smirnov 				dev_warn(dev, "Bad frame: STX before ETX\n");
511538ee272SAndrey Smirnov 				/*
512538ee272SAndrey Smirnov 				 * If we encounter second "start of
513538ee272SAndrey Smirnov 				 * the frame" marker before seeing
514538ee272SAndrey Smirnov 				 * corresponding "end of frame", we
515538ee272SAndrey Smirnov 				 * reset the framer and ignore both:
516538ee272SAndrey Smirnov 				 * frame started by first SOF and
517538ee272SAndrey Smirnov 				 * frame started by current SOF.
518538ee272SAndrey Smirnov 				 *
519538ee272SAndrey Smirnov 				 * NOTE: The above means that only the
520538ee272SAndrey Smirnov 				 * frame started by third SOF, sent
521538ee272SAndrey Smirnov 				 * after this one will have a chance
522538ee272SAndrey Smirnov 				 * to get throught.
523538ee272SAndrey Smirnov 				 */
524538ee272SAndrey Smirnov 				goto reset_framer;
525538ee272SAndrey Smirnov 			case RAVE_SP_DLE:
526538ee272SAndrey Smirnov 				deframer->state = RAVE_SP_EXPECT_ESCAPED_DATA;
527538ee272SAndrey Smirnov 				/*
528538ee272SAndrey Smirnov 				 * If we encounter escape sequence we
529538ee272SAndrey Smirnov 				 * need to skip it and collect the
530538ee272SAndrey Smirnov 				 * byte that follows. We do it by
531538ee272SAndrey Smirnov 				 * forcing the next iteration of the
532538ee272SAndrey Smirnov 				 * encompassing while loop.
533538ee272SAndrey Smirnov 				 */
534538ee272SAndrey Smirnov 				continue;
535538ee272SAndrey Smirnov 			}
536538ee272SAndrey Smirnov 			/*
537538ee272SAndrey Smirnov 			 * For the rest of the bytes, that are not
538538ee272SAndrey Smirnov 			 * speical snoflakes, we do the same thing
539538ee272SAndrey Smirnov 			 * that we do to escaped data - collect it in
540538ee272SAndrey Smirnov 			 * deframer buffer
541538ee272SAndrey Smirnov 			 */
542538ee272SAndrey Smirnov 
543538ee272SAndrey Smirnov 			/* FALLTHROUGH */
544538ee272SAndrey Smirnov 
545538ee272SAndrey Smirnov 		case RAVE_SP_EXPECT_ESCAPED_DATA:
546538ee272SAndrey Smirnov 			if (deframer->length == sizeof(deframer->data)) {
547538ee272SAndrey Smirnov 				dev_warn(dev, "Bad frame: Too long\n");
548538ee272SAndrey Smirnov 				/*
549538ee272SAndrey Smirnov 				 * If the amount of data we've
550538ee272SAndrey Smirnov 				 * accumulated for current frame so
551538ee272SAndrey Smirnov 				 * far starts to exceed the capacity
552538ee272SAndrey Smirnov 				 * of deframer's buffer, there's
553538ee272SAndrey Smirnov 				 * nothing else we can do but to
554538ee272SAndrey Smirnov 				 * discard that data and start
555538ee272SAndrey Smirnov 				 * assemblying a new frame again
556538ee272SAndrey Smirnov 				 */
557538ee272SAndrey Smirnov 				goto reset_framer;
558538ee272SAndrey Smirnov 			}
559538ee272SAndrey Smirnov 
5605112cab3SAndrey Smirnov 			deframer->data[deframer->length++] = byte;
5615112cab3SAndrey Smirnov 
562538ee272SAndrey Smirnov 			/*
563538ee272SAndrey Smirnov 			 * We've extracted out special byte, now we
564538ee272SAndrey Smirnov 			 * can go back to regular data collecting
565538ee272SAndrey Smirnov 			 */
566538ee272SAndrey Smirnov 			deframer->state = RAVE_SP_EXPECT_DATA;
567538ee272SAndrey Smirnov 			break;
568538ee272SAndrey Smirnov 		}
569538ee272SAndrey Smirnov 	}
570538ee272SAndrey Smirnov 
571538ee272SAndrey Smirnov 	/*
572538ee272SAndrey Smirnov 	 * The only way to get out of the above loop and end up here
573538ee272SAndrey Smirnov 	 * is throught consuming all of the supplied data, so here we
574538ee272SAndrey Smirnov 	 * report that we processed it all.
575538ee272SAndrey Smirnov 	 */
576538ee272SAndrey Smirnov 	return size;
577538ee272SAndrey Smirnov 
578538ee272SAndrey Smirnov reset_framer:
579538ee272SAndrey Smirnov 	/*
580538ee272SAndrey Smirnov 	 * NOTE: A number of codepaths that will drop us here will do
581538ee272SAndrey Smirnov 	 * so before consuming all 'size' bytes of the data passed by
582538ee272SAndrey Smirnov 	 * serdev layer. We rely on the fact that serdev layer will
583538ee272SAndrey Smirnov 	 * re-execute this handler with the remainder of the Rx bytes
584538ee272SAndrey Smirnov 	 * once we report actual number of bytes that we processed.
585538ee272SAndrey Smirnov 	 */
586538ee272SAndrey Smirnov 	deframer->state  = RAVE_SP_EXPECT_SOF;
587538ee272SAndrey Smirnov 	deframer->length = 0;
588538ee272SAndrey Smirnov 
589538ee272SAndrey Smirnov 	return src - buf;
590538ee272SAndrey Smirnov }
591538ee272SAndrey Smirnov 
592538ee272SAndrey Smirnov static int rave_sp_rdu1_cmd_translate(enum rave_sp_command command)
593538ee272SAndrey Smirnov {
594538ee272SAndrey Smirnov 	if (command >= RAVE_SP_CMD_STATUS &&
595538ee272SAndrey Smirnov 	    command <= RAVE_SP_CMD_CONTROL_EVENTS)
596538ee272SAndrey Smirnov 		return command;
597538ee272SAndrey Smirnov 
598538ee272SAndrey Smirnov 	return -EINVAL;
599538ee272SAndrey Smirnov }
600538ee272SAndrey Smirnov 
601538ee272SAndrey Smirnov static int rave_sp_rdu2_cmd_translate(enum rave_sp_command command)
602538ee272SAndrey Smirnov {
603538ee272SAndrey Smirnov 	if (command >= RAVE_SP_CMD_GET_FIRMWARE_VERSION &&
604538ee272SAndrey Smirnov 	    command <= RAVE_SP_CMD_GET_GPIO_STATE)
605538ee272SAndrey Smirnov 		return command;
606538ee272SAndrey Smirnov 
607538ee272SAndrey Smirnov 	if (command == RAVE_SP_CMD_REQ_COPPER_REV) {
608538ee272SAndrey Smirnov 		/*
609538ee272SAndrey Smirnov 		 * As per RDU2 ICD 3.4.47 CMD_GET_COPPER_REV code is
610538ee272SAndrey Smirnov 		 * different from that for RDU1 and it is set to 0x28.
611538ee272SAndrey Smirnov 		 */
612538ee272SAndrey Smirnov 		return 0x28;
613538ee272SAndrey Smirnov 	}
614538ee272SAndrey Smirnov 
615538ee272SAndrey Smirnov 	return rave_sp_rdu1_cmd_translate(command);
616538ee272SAndrey Smirnov }
617538ee272SAndrey Smirnov 
618538ee272SAndrey Smirnov static int rave_sp_default_cmd_translate(enum rave_sp_command command)
619538ee272SAndrey Smirnov {
620538ee272SAndrey Smirnov 	/*
621538ee272SAndrey Smirnov 	 * All of the following command codes were taken from "Table :
622538ee272SAndrey Smirnov 	 * Communications Protocol Message Types" in section 3.3
623538ee272SAndrey Smirnov 	 * "MESSAGE TYPES" of Rave PIC24 ICD.
624538ee272SAndrey Smirnov 	 */
625538ee272SAndrey Smirnov 	switch (command) {
626538ee272SAndrey Smirnov 	case RAVE_SP_CMD_GET_FIRMWARE_VERSION:
627538ee272SAndrey Smirnov 		return 0x11;
628538ee272SAndrey Smirnov 	case RAVE_SP_CMD_GET_BOOTLOADER_VERSION:
629538ee272SAndrey Smirnov 		return 0x12;
630538ee272SAndrey Smirnov 	case RAVE_SP_CMD_BOOT_SOURCE:
631538ee272SAndrey Smirnov 		return 0x14;
632538ee272SAndrey Smirnov 	case RAVE_SP_CMD_SW_WDT:
633538ee272SAndrey Smirnov 		return 0x1C;
634538ee272SAndrey Smirnov 	case RAVE_SP_CMD_RESET:
635538ee272SAndrey Smirnov 		return 0x1E;
636538ee272SAndrey Smirnov 	case RAVE_SP_CMD_RESET_REASON:
637538ee272SAndrey Smirnov 		return 0x1F;
638538ee272SAndrey Smirnov 	default:
639538ee272SAndrey Smirnov 		return -EINVAL;
640538ee272SAndrey Smirnov 	}
641538ee272SAndrey Smirnov }
642538ee272SAndrey Smirnov 
6436d97b6f1SAndrey Smirnov static const char *devm_rave_sp_version(struct device *dev,
6446d97b6f1SAndrey Smirnov 					struct rave_sp_version *version)
6456d97b6f1SAndrey Smirnov {
6466d97b6f1SAndrey Smirnov 	/*
6476d97b6f1SAndrey Smirnov 	 * NOTE: The format string below uses %02d to display u16
6486d97b6f1SAndrey Smirnov 	 * intentionally for the sake of backwards compatibility with
6496d97b6f1SAndrey Smirnov 	 * legacy software.
6506d97b6f1SAndrey Smirnov 	 */
6516d97b6f1SAndrey Smirnov 	return devm_kasprintf(dev, GFP_KERNEL, "%02d%02d%02d.%c%c\n",
6526d97b6f1SAndrey Smirnov 			      version->hardware,
6536d97b6f1SAndrey Smirnov 			      le16_to_cpu(version->major),
6546d97b6f1SAndrey Smirnov 			      version->minor,
6556d97b6f1SAndrey Smirnov 			      version->letter[0],
6566d97b6f1SAndrey Smirnov 			      version->letter[1]);
6576d97b6f1SAndrey Smirnov }
6586d97b6f1SAndrey Smirnov 
6596d97b6f1SAndrey Smirnov static int rave_sp_get_status(struct rave_sp *sp)
6606d97b6f1SAndrey Smirnov {
6616d97b6f1SAndrey Smirnov 	struct device *dev = &sp->serdev->dev;
6626d97b6f1SAndrey Smirnov 	u8 cmd[] = {
6636d97b6f1SAndrey Smirnov 		[0] = RAVE_SP_CMD_STATUS,
6646d97b6f1SAndrey Smirnov 		[1] = 0
6656d97b6f1SAndrey Smirnov 	};
6666d97b6f1SAndrey Smirnov 	struct rave_sp_status status;
6676d97b6f1SAndrey Smirnov 	const char *version;
6686d97b6f1SAndrey Smirnov 	int ret;
6696d97b6f1SAndrey Smirnov 
6706d97b6f1SAndrey Smirnov 	ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status));
6716d97b6f1SAndrey Smirnov 	if (ret)
6726d97b6f1SAndrey Smirnov 		return ret;
6736d97b6f1SAndrey Smirnov 
6746d97b6f1SAndrey Smirnov 	version = devm_rave_sp_version(dev, &status.firmware_version);
6756d97b6f1SAndrey Smirnov 	if (!version)
6766d97b6f1SAndrey Smirnov 		return -ENOMEM;
6776d97b6f1SAndrey Smirnov 
6786d97b6f1SAndrey Smirnov 	sp->part_number_firmware = version;
6796d97b6f1SAndrey Smirnov 
6806d97b6f1SAndrey Smirnov 	version = devm_rave_sp_version(dev, &status.bootloader_version);
6816d97b6f1SAndrey Smirnov 	if (!version)
6826d97b6f1SAndrey Smirnov 		return -ENOMEM;
6836d97b6f1SAndrey Smirnov 
6846d97b6f1SAndrey Smirnov 	sp->part_number_bootloader = version;
6856d97b6f1SAndrey Smirnov 
6866d97b6f1SAndrey Smirnov 	return 0;
6876d97b6f1SAndrey Smirnov }
6886d97b6f1SAndrey Smirnov 
689538ee272SAndrey Smirnov static const struct rave_sp_checksum rave_sp_checksum_8b2c = {
690538ee272SAndrey Smirnov 	.length     = 1,
691538ee272SAndrey Smirnov 	.subroutine = csum_8b2c,
692538ee272SAndrey Smirnov };
693538ee272SAndrey Smirnov 
694538ee272SAndrey Smirnov static const struct rave_sp_checksum rave_sp_checksum_ccitt = {
695538ee272SAndrey Smirnov 	.length     = 2,
696538ee272SAndrey Smirnov 	.subroutine = csum_ccitt,
697538ee272SAndrey Smirnov };
698538ee272SAndrey Smirnov 
699538ee272SAndrey Smirnov static const struct rave_sp_variant rave_sp_legacy = {
700a6e3bb02SAndrey Smirnov 	.checksum = &rave_sp_checksum_ccitt,
701538ee272SAndrey Smirnov 	.cmd = {
702538ee272SAndrey Smirnov 		.translate = rave_sp_default_cmd_translate,
703538ee272SAndrey Smirnov 	},
704538ee272SAndrey Smirnov };
705538ee272SAndrey Smirnov 
706538ee272SAndrey Smirnov static const struct rave_sp_variant rave_sp_rdu1 = {
707538ee272SAndrey Smirnov 	.checksum = &rave_sp_checksum_8b2c,
708538ee272SAndrey Smirnov 	.cmd = {
709538ee272SAndrey Smirnov 		.translate = rave_sp_rdu1_cmd_translate,
710538ee272SAndrey Smirnov 	},
711538ee272SAndrey Smirnov };
712538ee272SAndrey Smirnov 
713538ee272SAndrey Smirnov static const struct rave_sp_variant rave_sp_rdu2 = {
714538ee272SAndrey Smirnov 	.checksum = &rave_sp_checksum_ccitt,
715538ee272SAndrey Smirnov 	.cmd = {
716538ee272SAndrey Smirnov 		.translate = rave_sp_rdu2_cmd_translate,
717538ee272SAndrey Smirnov 	},
718538ee272SAndrey Smirnov };
719538ee272SAndrey Smirnov 
720538ee272SAndrey Smirnov static const struct of_device_id rave_sp_dt_ids[] = {
721538ee272SAndrey Smirnov 	{ .compatible = "zii,rave-sp-niu",  .data = &rave_sp_legacy },
722538ee272SAndrey Smirnov 	{ .compatible = "zii,rave-sp-mezz", .data = &rave_sp_legacy },
723538ee272SAndrey Smirnov 	{ .compatible = "zii,rave-sp-esb",  .data = &rave_sp_legacy },
724538ee272SAndrey Smirnov 	{ .compatible = "zii,rave-sp-rdu1", .data = &rave_sp_rdu1   },
725538ee272SAndrey Smirnov 	{ .compatible = "zii,rave-sp-rdu2", .data = &rave_sp_rdu2   },
726538ee272SAndrey Smirnov 	{ /* sentinel */ }
727538ee272SAndrey Smirnov };
728538ee272SAndrey Smirnov 
729538ee272SAndrey Smirnov static const struct serdev_device_ops rave_sp_serdev_device_ops = {
730538ee272SAndrey Smirnov 	.receive_buf  = rave_sp_receive_buf,
731538ee272SAndrey Smirnov 	.write_wakeup = serdev_device_write_wakeup,
732538ee272SAndrey Smirnov };
733538ee272SAndrey Smirnov 
734538ee272SAndrey Smirnov static int rave_sp_probe(struct serdev_device *serdev)
735538ee272SAndrey Smirnov {
736538ee272SAndrey Smirnov 	struct device *dev = &serdev->dev;
7376d97b6f1SAndrey Smirnov 	const char *unknown = "unknown\n";
738538ee272SAndrey Smirnov 	struct rave_sp *sp;
739538ee272SAndrey Smirnov 	u32 baud;
740538ee272SAndrey Smirnov 	int ret;
741538ee272SAndrey Smirnov 
742538ee272SAndrey Smirnov 	if (of_property_read_u32(dev->of_node, "current-speed", &baud)) {
743538ee272SAndrey Smirnov 		dev_err(dev,
744538ee272SAndrey Smirnov 			"'current-speed' is not specified in device node\n");
745538ee272SAndrey Smirnov 		return -EINVAL;
746538ee272SAndrey Smirnov 	}
747538ee272SAndrey Smirnov 
748538ee272SAndrey Smirnov 	sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL);
749538ee272SAndrey Smirnov 	if (!sp)
750538ee272SAndrey Smirnov 		return -ENOMEM;
751538ee272SAndrey Smirnov 
752538ee272SAndrey Smirnov 	sp->serdev = serdev;
753538ee272SAndrey Smirnov 	dev_set_drvdata(dev, sp);
754538ee272SAndrey Smirnov 
755538ee272SAndrey Smirnov 	sp->variant = of_device_get_match_data(dev);
756538ee272SAndrey Smirnov 	if (!sp->variant)
757538ee272SAndrey Smirnov 		return -ENODEV;
758538ee272SAndrey Smirnov 
759538ee272SAndrey Smirnov 	mutex_init(&sp->bus_lock);
760538ee272SAndrey Smirnov 	mutex_init(&sp->reply_lock);
761538ee272SAndrey Smirnov 	BLOCKING_INIT_NOTIFIER_HEAD(&sp->event_notifier_list);
762538ee272SAndrey Smirnov 
763538ee272SAndrey Smirnov 	serdev_device_set_client_ops(serdev, &rave_sp_serdev_device_ops);
764538ee272SAndrey Smirnov 	ret = devm_serdev_device_open(dev, serdev);
765538ee272SAndrey Smirnov 	if (ret)
766538ee272SAndrey Smirnov 		return ret;
767538ee272SAndrey Smirnov 
768538ee272SAndrey Smirnov 	serdev_device_set_baudrate(serdev, baud);
7696c450bdfSAndrey Smirnov 	serdev_device_set_flow_control(serdev, false);
7706c450bdfSAndrey Smirnov 
7716c450bdfSAndrey Smirnov 	ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
7726c450bdfSAndrey Smirnov 	if (ret) {
7736c450bdfSAndrey Smirnov 		dev_err(dev, "Failed to set parity\n");
7746c450bdfSAndrey Smirnov 		return ret;
7756c450bdfSAndrey Smirnov 	}
776538ee272SAndrey Smirnov 
7776d97b6f1SAndrey Smirnov 	ret = rave_sp_get_status(sp);
7786d97b6f1SAndrey Smirnov 	if (ret) {
7796d97b6f1SAndrey Smirnov 		dev_warn(dev, "Failed to get firmware status: %d\n", ret);
7806d97b6f1SAndrey Smirnov 		sp->part_number_firmware   = unknown;
7816d97b6f1SAndrey Smirnov 		sp->part_number_bootloader = unknown;
7826d97b6f1SAndrey Smirnov 	}
7836d97b6f1SAndrey Smirnov 
7846d97b6f1SAndrey Smirnov 	/*
7856d97b6f1SAndrey Smirnov 	 * Those strings already have a \n embedded, so there's no
7866d97b6f1SAndrey Smirnov 	 * need to have one in format string.
7876d97b6f1SAndrey Smirnov 	 */
7886d97b6f1SAndrey Smirnov 	dev_info(dev, "Firmware version: %s",   sp->part_number_firmware);
7896d97b6f1SAndrey Smirnov 	dev_info(dev, "Bootloader version: %s", sp->part_number_bootloader);
7906d97b6f1SAndrey Smirnov 
791538ee272SAndrey Smirnov 	return devm_of_platform_populate(dev);
792538ee272SAndrey Smirnov }
793538ee272SAndrey Smirnov 
794538ee272SAndrey Smirnov MODULE_DEVICE_TABLE(of, rave_sp_dt_ids);
795538ee272SAndrey Smirnov 
796538ee272SAndrey Smirnov static struct serdev_device_driver rave_sp_drv = {
797538ee272SAndrey Smirnov 	.probe			= rave_sp_probe,
798538ee272SAndrey Smirnov 	.driver = {
799538ee272SAndrey Smirnov 		.name		= "rave-sp",
800538ee272SAndrey Smirnov 		.of_match_table	= rave_sp_dt_ids,
801538ee272SAndrey Smirnov 	},
802538ee272SAndrey Smirnov };
803538ee272SAndrey Smirnov module_serdev_device_driver(rave_sp_drv);
804538ee272SAndrey Smirnov 
805538ee272SAndrey Smirnov MODULE_LICENSE("GPL");
806538ee272SAndrey Smirnov MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
807538ee272SAndrey Smirnov MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
808538ee272SAndrey Smirnov MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
809538ee272SAndrey Smirnov MODULE_DESCRIPTION("RAVE SP core driver");
810