diff options
Diffstat (limited to 'drivers/net/can/usb/ucan.h')
-rw-r--r-- | drivers/net/can/usb/ucan.h | 216 |
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 |