508 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/* Driver for ETAS GmbH ES58X USB CAN(-FD) Bus Interfaces.4 *5 * File es581_4.c: Adds support to ETAS ES581.4.6 *7 * Copyright (c) 2019 Robert Bosch Engineering and Business Solutions. All rights reserved.8 * Copyright (c) 2020 ETAS K.K.. All rights reserved.9 * Copyright (c) 2020-2022 Vincent Mailhol <mailhol.vincent@wanadoo.fr>10 */11 12#include <linux/unaligned.h>13#include <linux/kernel.h>14#include <linux/units.h>15 16#include "es58x_core.h"17#include "es581_4.h"18 19/**20 * es581_4_sizeof_rx_tx_msg() - Calculate the actual length of the21 * structure of a rx or tx message.22 * @msg: message of variable length, must have a dlc field.23 *24 * Even if RTR frames have actually no payload, the ES58X devices25 * still expect it. Must be a macro in order to accept several types26 * (struct es581_4_tx_can_msg and struct es581_4_rx_can_msg) as an27 * input.28 *29 * Return: length of the message.30 */31#define es581_4_sizeof_rx_tx_msg(msg) \32 offsetof(typeof(msg), data[can_cc_dlc2len((msg).dlc)])33 34static u16 es581_4_get_msg_len(const union es58x_urb_cmd *urb_cmd)35{36 return get_unaligned_le16(&urb_cmd->es581_4_urb_cmd.msg_len);37}38 39static int es581_4_echo_msg(struct es58x_device *es58x_dev,40 const struct es581_4_urb_cmd *es581_4_urb_cmd)41{42 struct net_device *netdev;43 const struct es581_4_bulk_echo_msg *bulk_echo_msg;44 const struct es581_4_echo_msg *echo_msg;45 u64 *tstamps = es58x_dev->timestamps;46 u16 msg_len;47 u32 first_packet_idx, packet_idx;48 unsigned int dropped = 0;49 int i, num_element, ret;50 51 bulk_echo_msg = &es581_4_urb_cmd->bulk_echo_msg;52 msg_len = get_unaligned_le16(&es581_4_urb_cmd->msg_len) -53 sizeof(bulk_echo_msg->channel_no);54 num_element = es58x_msg_num_element(es58x_dev->dev,55 bulk_echo_msg->echo_msg, msg_len);56 if (num_element <= 0)57 return num_element;58 59 ret = es58x_get_netdev(es58x_dev, bulk_echo_msg->channel_no,60 ES581_4_CHANNEL_IDX_OFFSET, &netdev);61 if (ret)62 return ret;63 64 echo_msg = &bulk_echo_msg->echo_msg[0];65 first_packet_idx = get_unaligned_le32(&echo_msg->packet_idx);66 packet_idx = first_packet_idx;67 for (i = 0; i < num_element; i++) {68 u32 tmp_idx;69 70 echo_msg = &bulk_echo_msg->echo_msg[i];71 tmp_idx = get_unaligned_le32(&echo_msg->packet_idx);72 if (tmp_idx == packet_idx - 1) {73 if (net_ratelimit())74 netdev_warn(netdev,75 "Received echo packet idx %u twice\n",76 packet_idx - 1);77 dropped++;78 continue;79 }80 if (tmp_idx != packet_idx) {81 netdev_err(netdev, "Echo packet idx jumped from %u to %u\n",82 packet_idx - 1, echo_msg->packet_idx);83 return -EBADMSG;84 }85 86 tstamps[i] = get_unaligned_le64(&echo_msg->timestamp);87 packet_idx++;88 }89 90 netdev->stats.tx_dropped += dropped;91 return es58x_can_get_echo_skb(netdev, first_packet_idx,92 tstamps, num_element - dropped);93}94 95static int es581_4_rx_can_msg(struct es58x_device *es58x_dev,96 const struct es581_4_urb_cmd *es581_4_urb_cmd,97 u16 msg_len)98{99 const struct device *dev = es58x_dev->dev;100 struct net_device *netdev;101 int pkts, num_element, channel_no, ret;102 103 num_element = es58x_msg_num_element(dev, es581_4_urb_cmd->rx_can_msg,104 msg_len);105 if (num_element <= 0)106 return num_element;107 108 channel_no = es581_4_urb_cmd->rx_can_msg[0].channel_no;109 ret = es58x_get_netdev(es58x_dev, channel_no,110 ES581_4_CHANNEL_IDX_OFFSET, &netdev);111 if (ret)112 return ret;113 114 if (!netif_running(netdev)) {115 if (net_ratelimit())116 netdev_info(netdev,117 "%s: %s is down, dropping %d rx packets\n",118 __func__, netdev->name, num_element);119 netdev->stats.rx_dropped += num_element;120 return 0;121 }122 123 for (pkts = 0; pkts < num_element; pkts++) {124 const struct es581_4_rx_can_msg *rx_can_msg =125 &es581_4_urb_cmd->rx_can_msg[pkts];126 u64 tstamp = get_unaligned_le64(&rx_can_msg->timestamp);127 canid_t can_id = get_unaligned_le32(&rx_can_msg->can_id);128 129 if (channel_no != rx_can_msg->channel_no)130 return -EBADMSG;131 132 ret = es58x_rx_can_msg(netdev, tstamp, rx_can_msg->data,133 can_id, rx_can_msg->flags,134 rx_can_msg->dlc);135 if (ret)136 break;137 }138 139 return ret;140}141 142static int es581_4_rx_err_msg(struct es58x_device *es58x_dev,143 const struct es581_4_rx_err_msg *rx_err_msg)144{145 struct net_device *netdev;146 enum es58x_err error = get_unaligned_le32(&rx_err_msg->error);147 int ret;148 149 ret = es58x_get_netdev(es58x_dev, rx_err_msg->channel_no,150 ES581_4_CHANNEL_IDX_OFFSET, &netdev);151 if (ret)152 return ret;153 154 return es58x_rx_err_msg(netdev, error, 0,155 get_unaligned_le64(&rx_err_msg->timestamp));156}157 158static int es581_4_rx_event_msg(struct es58x_device *es58x_dev,159 const struct es581_4_rx_event_msg *rx_event_msg)160{161 struct net_device *netdev;162 enum es58x_event event = get_unaligned_le32(&rx_event_msg->event);163 int ret;164 165 ret = es58x_get_netdev(es58x_dev, rx_event_msg->channel_no,166 ES581_4_CHANNEL_IDX_OFFSET, &netdev);167 if (ret)168 return ret;169 170 return es58x_rx_err_msg(netdev, 0, event,171 get_unaligned_le64(&rx_event_msg->timestamp));172}173 174static int es581_4_rx_cmd_ret_u32(struct es58x_device *es58x_dev,175 const struct es581_4_urb_cmd *es581_4_urb_cmd,176 enum es58x_ret_type ret_type)177{178 struct net_device *netdev;179 const struct es581_4_rx_cmd_ret *rx_cmd_ret;180 u16 msg_len = get_unaligned_le16(&es581_4_urb_cmd->msg_len);181 int ret;182 183 ret = es58x_check_msg_len(es58x_dev->dev,184 es581_4_urb_cmd->rx_cmd_ret, msg_len);185 if (ret)186 return ret;187 188 rx_cmd_ret = &es581_4_urb_cmd->rx_cmd_ret;189 190 ret = es58x_get_netdev(es58x_dev, rx_cmd_ret->channel_no,191 ES581_4_CHANNEL_IDX_OFFSET, &netdev);192 if (ret)193 return ret;194 195 return es58x_rx_cmd_ret_u32(netdev, ret_type,196 get_unaligned_le32(&rx_cmd_ret->rx_cmd_ret_le32));197}198 199static int es581_4_tx_ack_msg(struct es58x_device *es58x_dev,200 const struct es581_4_urb_cmd *es581_4_urb_cmd)201{202 struct net_device *netdev;203 const struct es581_4_tx_ack_msg *tx_ack_msg;204 u16 msg_len = get_unaligned_le16(&es581_4_urb_cmd->msg_len);205 int ret;206 207 tx_ack_msg = &es581_4_urb_cmd->tx_ack_msg;208 ret = es58x_check_msg_len(es58x_dev->dev, *tx_ack_msg, msg_len);209 if (ret)210 return ret;211 212 if (tx_ack_msg->rx_cmd_ret_u8 != ES58X_RET_U8_OK)213 return es58x_rx_cmd_ret_u8(es58x_dev->dev,214 ES58X_RET_TYPE_TX_MSG,215 tx_ack_msg->rx_cmd_ret_u8);216 217 ret = es58x_get_netdev(es58x_dev, tx_ack_msg->channel_no,218 ES581_4_CHANNEL_IDX_OFFSET, &netdev);219 if (ret)220 return ret;221 222 return es58x_tx_ack_msg(netdev,223 get_unaligned_le16(&tx_ack_msg->tx_free_entries),224 ES58X_RET_U32_OK);225}226 227static int es581_4_dispatch_rx_cmd(struct es58x_device *es58x_dev,228 const struct es581_4_urb_cmd *es581_4_urb_cmd)229{230 const struct device *dev = es58x_dev->dev;231 u16 msg_len = get_unaligned_le16(&es581_4_urb_cmd->msg_len);232 enum es581_4_rx_type rx_type = es581_4_urb_cmd->rx_can_msg[0].rx_type;233 int ret = 0;234 235 switch (rx_type) {236 case ES581_4_RX_TYPE_MESSAGE:237 return es581_4_rx_can_msg(es58x_dev, es581_4_urb_cmd, msg_len);238 239 case ES581_4_RX_TYPE_ERROR:240 ret = es58x_check_msg_len(dev, es581_4_urb_cmd->rx_err_msg,241 msg_len);242 if (ret < 0)243 return ret;244 return es581_4_rx_err_msg(es58x_dev,245 &es581_4_urb_cmd->rx_err_msg);246 247 case ES581_4_RX_TYPE_EVENT:248 ret = es58x_check_msg_len(dev, es581_4_urb_cmd->rx_event_msg,249 msg_len);250 if (ret < 0)251 return ret;252 return es581_4_rx_event_msg(es58x_dev,253 &es581_4_urb_cmd->rx_event_msg);254 255 default:256 dev_err(dev, "%s: Unknown rx_type 0x%02X\n", __func__, rx_type);257 return -EBADRQC;258 }259}260 261static int es581_4_handle_urb_cmd(struct es58x_device *es58x_dev,262 const union es58x_urb_cmd *urb_cmd)263{264 const struct es581_4_urb_cmd *es581_4_urb_cmd;265 struct device *dev = es58x_dev->dev;266 u16 msg_len = es581_4_get_msg_len(urb_cmd);267 int ret;268 269 es581_4_urb_cmd = &urb_cmd->es581_4_urb_cmd;270 271 if (es581_4_urb_cmd->cmd_type != ES581_4_CAN_COMMAND_TYPE) {272 dev_err(dev, "%s: Unknown command type (0x%02X)\n",273 __func__, es581_4_urb_cmd->cmd_type);274 return -EBADRQC;275 }276 277 switch ((enum es581_4_cmd_id)es581_4_urb_cmd->cmd_id) {278 case ES581_4_CMD_ID_SET_BITTIMING:279 return es581_4_rx_cmd_ret_u32(es58x_dev, es581_4_urb_cmd,280 ES58X_RET_TYPE_SET_BITTIMING);281 282 case ES581_4_CMD_ID_ENABLE_CHANNEL:283 return es581_4_rx_cmd_ret_u32(es58x_dev, es581_4_urb_cmd,284 ES58X_RET_TYPE_ENABLE_CHANNEL);285 286 case ES581_4_CMD_ID_TX_MSG:287 return es581_4_tx_ack_msg(es58x_dev, es581_4_urb_cmd);288 289 case ES581_4_CMD_ID_RX_MSG:290 return es581_4_dispatch_rx_cmd(es58x_dev, es581_4_urb_cmd);291 292 case ES581_4_CMD_ID_RESET_RX:293 ret = es581_4_rx_cmd_ret_u32(es58x_dev, es581_4_urb_cmd,294 ES58X_RET_TYPE_RESET_RX);295 return ret;296 297 case ES581_4_CMD_ID_RESET_TX:298 ret = es581_4_rx_cmd_ret_u32(es58x_dev, es581_4_urb_cmd,299 ES58X_RET_TYPE_RESET_TX);300 return ret;301 302 case ES581_4_CMD_ID_DISABLE_CHANNEL:303 return es581_4_rx_cmd_ret_u32(es58x_dev, es581_4_urb_cmd,304 ES58X_RET_TYPE_DISABLE_CHANNEL);305 306 case ES581_4_CMD_ID_TIMESTAMP:307 ret = es58x_check_msg_len(dev, es581_4_urb_cmd->timestamp,308 msg_len);309 if (ret < 0)310 return ret;311 es58x_rx_timestamp(es58x_dev,312 get_unaligned_le64(&es581_4_urb_cmd->timestamp));313 return 0;314 315 case ES581_4_CMD_ID_ECHO:316 return es581_4_echo_msg(es58x_dev, es581_4_urb_cmd);317 318 case ES581_4_CMD_ID_DEVICE_ERR:319 ret = es58x_check_msg_len(dev, es581_4_urb_cmd->rx_cmd_ret_u8,320 msg_len);321 if (ret)322 return ret;323 return es58x_rx_cmd_ret_u8(dev, ES58X_RET_TYPE_DEVICE_ERR,324 es581_4_urb_cmd->rx_cmd_ret_u8);325 326 default:327 dev_warn(dev, "%s: Unexpected command ID: 0x%02X\n",328 __func__, es581_4_urb_cmd->cmd_id);329 return -EBADRQC;330 }331}332 333static void es581_4_fill_urb_header(union es58x_urb_cmd *urb_cmd, u8 cmd_type,334 u8 cmd_id, u8 channel_idx, u16 msg_len)335{336 struct es581_4_urb_cmd *es581_4_urb_cmd = &urb_cmd->es581_4_urb_cmd;337 338 es581_4_urb_cmd->SOF = cpu_to_le16(es581_4_param.tx_start_of_frame);339 es581_4_urb_cmd->cmd_type = cmd_type;340 es581_4_urb_cmd->cmd_id = cmd_id;341 es581_4_urb_cmd->msg_len = cpu_to_le16(msg_len);342}343 344static int es581_4_tx_can_msg(struct es58x_priv *priv,345 const struct sk_buff *skb)346{347 struct es58x_device *es58x_dev = priv->es58x_dev;348 union es58x_urb_cmd *urb_cmd = priv->tx_urb->transfer_buffer;349 struct es581_4_urb_cmd *es581_4_urb_cmd = &urb_cmd->es581_4_urb_cmd;350 struct can_frame *cf = (struct can_frame *)skb->data;351 struct es581_4_tx_can_msg *tx_can_msg;352 u16 msg_len;353 int ret;354 355 if (can_is_canfd_skb(skb))356 return -EMSGSIZE;357 358 if (priv->tx_can_msg_cnt == 0) {359 msg_len = sizeof(es581_4_urb_cmd->bulk_tx_can_msg.num_can_msg);360 es581_4_fill_urb_header(urb_cmd, ES581_4_CAN_COMMAND_TYPE,361 ES581_4_CMD_ID_TX_MSG,362 priv->channel_idx, msg_len);363 es581_4_urb_cmd->bulk_tx_can_msg.num_can_msg = 0;364 } else {365 msg_len = es581_4_get_msg_len(urb_cmd);366 }367 368 ret = es58x_check_msg_max_len(es58x_dev->dev,369 es581_4_urb_cmd->bulk_tx_can_msg,370 msg_len + sizeof(*tx_can_msg));371 if (ret)372 return ret;373 374 /* Fill message contents. */375 tx_can_msg = (typeof(tx_can_msg))&es581_4_urb_cmd->raw_msg[msg_len];376 put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id);377 put_unaligned_le32(priv->tx_head, &tx_can_msg->packet_idx);378 put_unaligned_le16((u16)es58x_get_flags(skb), &tx_can_msg->flags);379 tx_can_msg->channel_no = priv->channel_idx + ES581_4_CHANNEL_IDX_OFFSET;380 tx_can_msg->dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);381 382 memcpy(tx_can_msg->data, cf->data, cf->len);383 384 /* Calculate new sizes. */385 es581_4_urb_cmd->bulk_tx_can_msg.num_can_msg++;386 msg_len += es581_4_sizeof_rx_tx_msg(*tx_can_msg);387 priv->tx_urb->transfer_buffer_length = es58x_get_urb_cmd_len(es58x_dev,388 msg_len);389 es581_4_urb_cmd->msg_len = cpu_to_le16(msg_len);390 391 return 0;392}393 394static int es581_4_set_bittiming(struct es58x_priv *priv)395{396 struct es581_4_tx_conf_msg tx_conf_msg = { 0 };397 struct can_bittiming *bt = &priv->can.bittiming;398 399 tx_conf_msg.bitrate = cpu_to_le32(bt->bitrate);400 /* bt->sample_point is in tenth of percent. Convert it to percent. */401 tx_conf_msg.sample_point = cpu_to_le32(bt->sample_point / 10U);402 tx_conf_msg.samples_per_bit = cpu_to_le32(ES58X_SAMPLES_PER_BIT_ONE);403 tx_conf_msg.bit_time = cpu_to_le32(can_bit_time(bt));404 tx_conf_msg.sjw = cpu_to_le32(bt->sjw);405 tx_conf_msg.sync_edge = cpu_to_le32(ES58X_SYNC_EDGE_SINGLE);406 tx_conf_msg.physical_layer =407 cpu_to_le32(ES58X_PHYSICAL_LAYER_HIGH_SPEED);408 tx_conf_msg.echo_mode = cpu_to_le32(ES58X_ECHO_ON);409 tx_conf_msg.channel_no = priv->channel_idx + ES581_4_CHANNEL_IDX_OFFSET;410 411 return es58x_send_msg(priv->es58x_dev, ES581_4_CAN_COMMAND_TYPE,412 ES581_4_CMD_ID_SET_BITTIMING, &tx_conf_msg,413 sizeof(tx_conf_msg), priv->channel_idx);414}415 416static int es581_4_enable_channel(struct es58x_priv *priv)417{418 int ret;419 u8 msg = priv->channel_idx + ES581_4_CHANNEL_IDX_OFFSET;420 421 ret = es581_4_set_bittiming(priv);422 if (ret)423 return ret;424 425 return es58x_send_msg(priv->es58x_dev, ES581_4_CAN_COMMAND_TYPE,426 ES581_4_CMD_ID_ENABLE_CHANNEL, &msg, sizeof(msg),427 priv->channel_idx);428}429 430static int es581_4_disable_channel(struct es58x_priv *priv)431{432 u8 msg = priv->channel_idx + ES581_4_CHANNEL_IDX_OFFSET;433 434 return es58x_send_msg(priv->es58x_dev, ES581_4_CAN_COMMAND_TYPE,435 ES581_4_CMD_ID_DISABLE_CHANNEL, &msg, sizeof(msg),436 priv->channel_idx);437}438 439static int es581_4_reset_device(struct es58x_device *es58x_dev)440{441 return es58x_send_msg(es58x_dev, ES581_4_CAN_COMMAND_TYPE,442 ES581_4_CMD_ID_RESET_DEVICE,443 ES58X_EMPTY_MSG, 0, ES58X_CHANNEL_IDX_NA);444}445 446static int es581_4_get_timestamp(struct es58x_device *es58x_dev)447{448 return es58x_send_msg(es58x_dev, ES581_4_CAN_COMMAND_TYPE,449 ES581_4_CMD_ID_TIMESTAMP,450 ES58X_EMPTY_MSG, 0, ES58X_CHANNEL_IDX_NA);451}452 453/* Nominal bittiming constants for ES581.4 as specified in the454 * microcontroller datasheet: "Stellaris(R) LM3S5B91 Microcontroller"455 * table 17-4 "CAN Protocol Ranges" from Texas Instruments.456 */457static const struct can_bittiming_const es581_4_bittiming_const = {458 .name = "ES581.4",459 .tseg1_min = 1,460 .tseg1_max = 8,461 .tseg2_min = 1,462 .tseg2_max = 8,463 .sjw_max = 4,464 .brp_min = 1,465 .brp_max = 128,466 .brp_inc = 1467};468 469const struct es58x_parameters es581_4_param = {470 .bittiming_const = &es581_4_bittiming_const,471 .data_bittiming_const = NULL,472 .tdc_const = NULL,473 .bitrate_max = 1 * MEGA /* BPS */,474 .clock = {.freq = 50 * MEGA /* Hz */},475 .ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC,476 .tx_start_of_frame = 0xAFAF,477 .rx_start_of_frame = 0xFAFA,478 .tx_urb_cmd_max_len = ES581_4_TX_URB_CMD_MAX_LEN,479 .rx_urb_cmd_max_len = ES581_4_RX_URB_CMD_MAX_LEN,480 /* Size of internal device TX queue is 330.481 *482 * However, we witnessed some ES58X_ERR_PROT_CRC errors from483 * the device and thus, echo_skb_max was lowered to the484 * empirical value of 75 which seems stable and then rounded485 * down to become a power of two.486 *487 * Root cause of those ES58X_ERR_PROT_CRC errors is still488 * unclear.489 */490 .fifo_mask = 63, /* echo_skb_max = 64 */491 .dql_min_limit = CAN_FRAME_LEN_MAX * 50, /* Empirical value. */492 .tx_bulk_max = ES581_4_TX_BULK_MAX,493 .urb_cmd_header_len = ES581_4_URB_CMD_HEADER_LEN,494 .rx_urb_max = ES58X_RX_URBS_MAX,495 .tx_urb_max = ES58X_TX_URBS_MAX496};497 498const struct es58x_operators es581_4_ops = {499 .get_msg_len = es581_4_get_msg_len,500 .handle_urb_cmd = es581_4_handle_urb_cmd,501 .fill_urb_header = es581_4_fill_urb_header,502 .tx_can_msg = es581_4_tx_can_msg,503 .enable_channel = es581_4_enable_channel,504 .disable_channel = es581_4_disable_channel,505 .reset_device = es581_4_reset_device,506 .get_timestamp = es581_4_get_timestamp507};508