es581_4.c (15582B)
1// SPDX-License-Identifier: GPL-2.0 2 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, 2021 Vincent Mailhol <mailhol.vincent@wanadoo.fr> 10 */ 11 12#include <linux/kernel.h> 13#include <linux/units.h> 14#include <asm/unaligned.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 the 21 * 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 devices 25 * still expect it. Must be a macro in order to accept several types 26 * (struct es581_4_tx_can_msg and struct es581_4_rx_can_msg) as an 27 * 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 the 454 * 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 = 1 467}; 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 from 483 * the device and thus, echo_skb_max was lowered to the 484 * empirical value of 75 which seems stable and then rounded 485 * down to become a power of two. 486 * 487 * Root cause of those ES58X_ERR_PROT_CRC errors is still 488 * 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_MAX 496}; 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_timestamp 507};