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