Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
0004 //
0005 // Copyright (c) 2020 Pengutronix,
0006 //                    Marc Kleine-Budde <kernel@pengutronix.de>
0007 //
0008 // Based on:
0009 //
0010 // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
0011 //
0012 // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
0013 //
0014 
0015 #include "mcp251xfd.h"
0016 
0017 /* The standard crc16 in linux/crc16.h is unfortunately not computing
0018  * the correct results (left shift vs. right shift). So here an
0019  * implementation with a table generated with the help of:
0020  *
0021  * http://lkml.iu.edu/hypermail/linux/kernel/0508.1/1085.html
0022  */
0023 static const u16 mcp251xfd_crc16_table[] = {
0024     0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
0025     0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
0026     0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
0027     0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
0028     0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
0029     0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
0030     0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
0031     0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
0032     0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
0033     0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
0034     0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
0035     0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
0036     0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
0037     0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
0038     0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
0039     0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
0040     0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
0041     0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
0042     0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
0043     0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
0044     0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
0045     0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
0046     0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
0047     0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
0048     0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
0049     0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
0050     0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
0051     0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
0052     0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
0053     0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
0054     0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
0055     0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
0056 };
0057 
0058 static inline u16 mcp251xfd_crc16_byte(u16 crc, const u8 data)
0059 {
0060     u8 index = (crc >> 8) ^ data;
0061 
0062     return (crc << 8) ^ mcp251xfd_crc16_table[index];
0063 }
0064 
0065 static u16 mcp251xfd_crc16(u16 crc, u8 const *buffer, size_t len)
0066 {
0067     while (len--)
0068         crc = mcp251xfd_crc16_byte(crc, *buffer++);
0069 
0070     return crc;
0071 }
0072 
0073 u16 mcp251xfd_crc16_compute(const void *data, size_t data_size)
0074 {
0075     u16 crc = 0xffff;
0076 
0077     return mcp251xfd_crc16(crc, data, data_size);
0078 }
0079 
0080 u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size,
0081                  const void *data, size_t data_size)
0082 {
0083     u16 crc;
0084 
0085     crc = mcp251xfd_crc16_compute(cmd, cmd_size);
0086     crc = mcp251xfd_crc16(crc, data, data_size);
0087 
0088     return crc;
0089 }