summaryrefslogtreecommitdiff
path: root/drivers/net/can/usb/ucan.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can/usb/ucan.h')
-rw-r--r--drivers/net/can/usb/ucan.h216
1 files changed, 216 insertions, 0 deletions
diff --git a/drivers/net/can/usb/ucan.h b/drivers/net/can/usb/ucan.h
new file mode 100644
index 000000000000..dfe33088e405
--- /dev/null
+++ b/drivers/net/can/usb/ucan.h
@@ -0,0 +1,216 @@
+#ifndef __UCAN_H__
+
+/*
+ * Header file for CAN driver for uCAN
+ *
+ * Copyright (C) 2015 Theobroma Systems Design und Consulting GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.
+ *
+ * This driver is inspired by the 4.0.0 version of drivers/net/can/usb/ems_usb.c
+ *
+ */
+
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+
+#define UCAN_CLASS 0xA0
+#define UCAN_SUBCLASS 0x00
+
+/* uCAN message definitions --------------------------------------------
+ *
+ * uCAN_message_out_t and uCAN_message_in_t define the messages
+ * transmitted on the OUT and IN endpoint.
+ *
+ * Multibyte fields are transmitted with little endianess
+ *
+ * INTR Endpoint: a single uint32_t storing the current space in the fifo
+ *
+ * OUT Enpoint: single message of type uCAN_message_out_t is
+ * transmitted on the out endpoint
+ *
+ * IN Endpoint: multiple messages uCAN_message_in_t concateted in
+ * the following way:
+ *
+ * m[n].len <=> the length if message n(including the header in bytes)
+ * m[n] is is aligned to a 4 byte boundary, hence
+ * offset(m[0]) := 0;
+ * offset(m[n+1]) := offset(m[n]) + (m[n].len + 3) & 3
+ *
+ * this implies that
+ * offset(m[n]) % 4 <=> 0
+ */
+
+// UCAN Commands
+enum {
+ UCAN_COMMAND_START = 0,
+ UCAN_COMMAND_STOP = 1,
+ UCAN_COMMAND_SLEEP = 2,
+ UCAN_COMMAND_WAKEUP = 3,
+ UCAN_COMMAND_RESET = 4,
+ UCAN_COMMAND_GET = 5,
+ UCAN_COMMAND_GET_INFO = 0,
+ UCAN_COMMAND_FILTER = 6,
+ UCAN_FILTER_CLEAR = 0,
+ UCAN_FILTER_DISABLE = 1,
+};
+
+enum {
+ UCAN_MODE_LOOPBACK = (1<<0),
+ UCAN_MODE_SILENT = (1<<1),
+ UCAN_MODE_3_SAMPLES = (1<<2),
+ UCAN_MODE_ONE_SHOT = (1<<3),
+ UCAN_MODE_BERR_REPORT = (1<<4),
+};
+
+#define UCAN_OUT_COMMAND 0
+#define UCAN_OUT_SET_BITTIMING 1
+#define UCAN_OUT_TX 2
+#define UCAN_OUT_ENABLE_FILTER 3
+
+/* OUT Enpoint, outbound messages */
+struct uCAN_message_out {
+ u16 len; /* Length of the content include header */
+ u16 type; /* UCAN_OUT_COMMAND and friends */
+ union {
+ /***************************************************
+ * Device Command
+ * (type = UCAN_OUT_SET_BITTIMING)
+ ***************************************************/
+ struct {
+ u8 cmd; /* UCAN_COMMAND_START and friends */
+ u8 subcmd;
+ u16 val;
+ } __attribute__((packed)) command;
+
+ /***************************************************
+ * Set Bittiming
+ * (type = UCAN_OUT_SET_BITTIMING)
+ ***************************************************/
+ struct {
+ u32 tq; /* Time quanta (TQ) in nanoseconds */
+ u16 brp; /* TQ Prescaler */
+ u16 sample_point; /* Samplepoint on tenth percent */
+ u8 prop_seg; /* Propagation segment in TQs */
+ u8 phase_seg1; /* Phase buffer segment 1 in TQs */
+ u8 phase_seg2; /* Phase buffer segment 2 in TQs */
+ u8 sjw; /* Synchronisation jump width in TQs */
+ } __attribute__((packed)) bittiming;
+
+ /***************************************************
+ * Transmit CAN frame
+ * (type = UCAN_TX) && ((msg.can_msg.id & CAN_RTR_FLAG) == 0)
+ ***************************************************/
+ struct { /* note DLC is computed by
+ * msg.len - sizeof (msg.len)
+ * - sizeof (msg.type)
+ * - sizeof (msg.can_msg.id); */
+ u32 id;
+ u8 data[8]; // ensure data aligment to 4, by moving dlc after data
+ } __attribute__((packed)) can_msg;
+
+ /***************************************************
+ * Transmit RTR CAN frame
+ * (type = UCAN_TX) && ((msg.can_msg.id & CAN_RTR_FLAG) != 0)
+ ***************************************************/
+ struct {
+ u32 id;
+ u8 dlc;
+ } __attribute__((packed)) can_rtr_msg;
+
+ /***************************************************
+ * Enable Filter
+ * (type = UCAN_OUT_ENABLE_FILTER)
+ ***************************************************/
+ struct {
+ u32 id;
+ u32 mask;
+ u16 mbox;
+ } enable_filter;
+ } __attribute__((aligned(0x4))) msg;
+} __attribute__((packed));
+
+#define UCAN_IN_DEVICE_INFO 0
+#define UCAN_IN_RX 2
+
+/* IN Enpoint, inbound messages */
+struct uCAN_message_in {
+ u16 len; /* Length of the content include header */
+ u16 type; /* UCAN_IN_DEVICE_INFO and friends */
+
+ union {
+ /***************************************************
+ * Device Information
+ * (type = UCAN_IN_DEVICE_INFO)
+ ***************************************************/
+ struct {
+ u32 freq; /* Clock Frequency for tq
+ * generation */
+ u8 tx_fifo; /* Size of the transmission
+ * fifo */
+ u8 sjw_max;
+ u8 tseg1_min;
+ u8 tseg1_max;
+ u8 tseg2_min;
+ u8 tseg2_max;
+ u16 brp_inc;
+ u32 brp_min;
+ u32 brp_max;
+ u16 ctrlmodes; /* supported control modes
+ * ors of UCAN_MODE_* */
+ u16 hwfilter; /* Number of HW filter
+ * banks */
+ u16 rxmboxes; /* Number Receive
+ * Mailboxes */
+ } __attribute__((packed)) device_info;
+
+ /***************************************************
+ * CAN RTR Frame received
+ * (type == UCAN_IN_RX) && ((msg.can_msg.id & CAN_RTR_FLAG) == 0)
+ ***************************************************/
+ struct { /* note DLC is computed by
+ * msg.len - sizeof (msg.len)
+ * - sizeof (msg.type)
+ * - sizeof (msg.can_msg.id); */
+ u32 id;
+ u8 data[8]; // ensure data aligment to 4, by moving dlc after data
+ } __attribute__((packed)) can_msg;
+
+ /***************************************************
+ * CAN RTR Frame received
+ * (type == UCAN_IN_RX) && ((msg.can_msg.id & CAN_RTR_FLAG) != 0)
+ ***************************************************/
+ struct {
+ u32 id;
+ u8 dlc;
+ } __attribute__((packed)) can_rtr_msg;
+ } __attribute__((aligned(0x4))) msg;
+} __attribute__((packed));
+
+
+/* Macros to calculate message lengths */
+#define UCAN_OUT_HDR_SIZE offsetof(struct uCAN_message_out, msg)
+#define UCAN_OUT_LEN(member) (UCAN_OUT_HDR_SIZE + sizeof(member) )
+
+#define UCAN_IN_HDR_SIZE offsetof(struct uCAN_message_in, msg)
+#define UCAN_IN_LEN(member) (UCAN_OUT_HDR_SIZE + sizeof(member) )
+
+#endif