0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <asm/unaligned.h>
0016
0017 #include "mcp251xfd.h"
0018 #include "mcp251xfd-ram.h"
0019
0020 static inline u8
0021 mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
0022 union mcp251xfd_write_reg_buf *write_reg_buf,
0023 const u16 reg, const u32 mask, const u32 val)
0024 {
0025 u8 first_byte, last_byte, len;
0026 u8 *data;
0027 __le32 val_le32;
0028
0029 first_byte = mcp251xfd_first_byte_set(mask);
0030 last_byte = mcp251xfd_last_byte_set(mask);
0031 len = last_byte - first_byte + 1;
0032
0033 data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte);
0034 val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
0035 memcpy(data, &val_le32, len);
0036
0037 if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) {
0038 u16 crc;
0039
0040 mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd,
0041 len);
0042
0043 len += sizeof(write_reg_buf->crc.cmd);
0044 crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len);
0045 put_unaligned_be16(crc, (void *)write_reg_buf + len);
0046
0047
0048 len += sizeof(write_reg_buf->crc.crc);
0049 } else {
0050 len += sizeof(write_reg_buf->nocrc.cmd);
0051 }
0052
0053 return len;
0054 }
0055
0056 static void
0057 mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
0058 {
0059 struct mcp251xfd_tef_ring *tef_ring;
0060 struct spi_transfer *xfer;
0061 u32 val;
0062 u16 addr;
0063 u8 len;
0064 int i;
0065
0066
0067 tef_ring = priv->tef;
0068 tef_ring->head = 0;
0069 tef_ring->tail = 0;
0070
0071
0072 *base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num);
0073
0074
0075 addr = MCP251XFD_REG_TEFCON;
0076 val = MCP251XFD_REG_TEFCON_TEFOVIE | MCP251XFD_REG_TEFCON_TEFNEIE;
0077
0078 len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->irq_enable_buf,
0079 addr, val, val);
0080 tef_ring->irq_enable_xfer.tx_buf = &tef_ring->irq_enable_buf;
0081 tef_ring->irq_enable_xfer.len = len;
0082 spi_message_init_with_transfers(&tef_ring->irq_enable_msg,
0083 &tef_ring->irq_enable_xfer, 1);
0084
0085
0086 addr = MCP251XFD_REG_TEFCON;
0087 val = MCP251XFD_REG_TEFCON_UINC;
0088 len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf,
0089 addr, val, val);
0090
0091 for (i = 0; i < ARRAY_SIZE(tef_ring->uinc_xfer); i++) {
0092 xfer = &tef_ring->uinc_xfer[i];
0093 xfer->tx_buf = &tef_ring->uinc_buf;
0094 xfer->len = len;
0095 xfer->cs_change = 1;
0096 xfer->cs_change_delay.value = 0;
0097 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
0098 }
0099
0100
0101
0102
0103
0104
0105
0106
0107 xfer->cs_change = 0;
0108
0109 if (priv->tx_coalesce_usecs_irq || priv->tx_obj_num_coalesce_irq) {
0110 val = MCP251XFD_REG_TEFCON_UINC |
0111 MCP251XFD_REG_TEFCON_TEFOVIE |
0112 MCP251XFD_REG_TEFCON_TEFHIE;
0113
0114 len = mcp251xfd_cmd_prepare_write_reg(priv,
0115 &tef_ring->uinc_irq_disable_buf,
0116 addr, val, val);
0117 xfer->tx_buf = &tef_ring->uinc_irq_disable_buf;
0118 xfer->len = len;
0119 }
0120 }
0121
0122 static void
0123 mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
0124 const struct mcp251xfd_tx_ring *ring,
0125 struct mcp251xfd_tx_obj *tx_obj,
0126 const u8 rts_buf_len,
0127 const u8 n)
0128 {
0129 struct spi_transfer *xfer;
0130 u16 addr;
0131
0132
0133 addr = mcp251xfd_get_tx_obj_addr(ring, n);
0134 if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
0135 mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd,
0136 addr);
0137 else
0138 mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd,
0139 addr);
0140
0141 xfer = &tx_obj->xfer[0];
0142 xfer->tx_buf = &tx_obj->buf;
0143 xfer->len = 0;
0144 xfer->cs_change = 1;
0145 xfer->cs_change_delay.value = 0;
0146 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
0147
0148
0149 xfer = &tx_obj->xfer[1];
0150 xfer->tx_buf = &ring->rts_buf;
0151 xfer->len = rts_buf_len;
0152
0153
0154 spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer,
0155 ARRAY_SIZE(tx_obj->xfer));
0156 }
0157
0158 static void
0159 mcp251xfd_ring_init_tx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
0160 {
0161 struct mcp251xfd_tx_ring *tx_ring;
0162 struct mcp251xfd_tx_obj *tx_obj;
0163 u32 val;
0164 u16 addr;
0165 u8 len;
0166 int i;
0167
0168 tx_ring = priv->tx;
0169 tx_ring->head = 0;
0170 tx_ring->tail = 0;
0171 tx_ring->base = *base;
0172 tx_ring->nr = 0;
0173 tx_ring->fifo_nr = *fifo_nr;
0174
0175 *base = mcp251xfd_get_tx_obj_addr(tx_ring, tx_ring->obj_num);
0176 *fifo_nr += 1;
0177
0178
0179 addr = MCP251XFD_REG_FIFOCON(tx_ring->fifo_nr);
0180 val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC;
0181 len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf,
0182 addr, val, val);
0183
0184 mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i)
0185 mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i);
0186 }
0187
0188 static void
0189 mcp251xfd_ring_init_rx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
0190 {
0191 struct mcp251xfd_rx_ring *rx_ring;
0192 struct spi_transfer *xfer;
0193 u32 val;
0194 u16 addr;
0195 u8 len;
0196 int i, j;
0197
0198 mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
0199 rx_ring->head = 0;
0200 rx_ring->tail = 0;
0201 rx_ring->base = *base;
0202 rx_ring->nr = i;
0203 rx_ring->fifo_nr = *fifo_nr;
0204
0205 *base = mcp251xfd_get_rx_obj_addr(rx_ring, rx_ring->obj_num);
0206 *fifo_nr += 1;
0207
0208
0209 addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
0210 val = MCP251XFD_REG_FIFOCON_RXOVIE |
0211 MCP251XFD_REG_FIFOCON_TFNRFNIE;
0212 len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->irq_enable_buf,
0213 addr, val, val);
0214 rx_ring->irq_enable_xfer.tx_buf = &rx_ring->irq_enable_buf;
0215 rx_ring->irq_enable_xfer.len = len;
0216 spi_message_init_with_transfers(&rx_ring->irq_enable_msg,
0217 &rx_ring->irq_enable_xfer, 1);
0218
0219
0220 val = MCP251XFD_REG_FIFOCON_UINC;
0221 len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf,
0222 addr, val, val);
0223
0224 for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) {
0225 xfer = &rx_ring->uinc_xfer[j];
0226 xfer->tx_buf = &rx_ring->uinc_buf;
0227 xfer->len = len;
0228 xfer->cs_change = 1;
0229 xfer->cs_change_delay.value = 0;
0230 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240 xfer->cs_change = 0;
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258 if (rx_ring->nr == 0 && (priv->rx_coalesce_usecs_irq ||
0259 priv->rx_obj_num_coalesce_irq)) {
0260 val = MCP251XFD_REG_FIFOCON_UINC |
0261 MCP251XFD_REG_FIFOCON_RXOVIE;
0262
0263 if (priv->rx_obj_num_coalesce_irq == rx_ring->obj_num)
0264 val |= MCP251XFD_REG_FIFOCON_TFERFFIE;
0265 else if (priv->rx_obj_num_coalesce_irq)
0266 val |= MCP251XFD_REG_FIFOCON_TFHRFHIE;
0267
0268 len = mcp251xfd_cmd_prepare_write_reg(priv,
0269 &rx_ring->uinc_irq_disable_buf,
0270 addr, val, val);
0271 xfer->tx_buf = &rx_ring->uinc_irq_disable_buf;
0272 xfer->len = len;
0273 }
0274 }
0275 }
0276
0277 int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
0278 {
0279 const struct mcp251xfd_rx_ring *rx_ring;
0280 u16 base = 0, ram_used;
0281 u8 fifo_nr = 1;
0282 int i;
0283
0284 netdev_reset_queue(priv->ndev);
0285
0286 mcp251xfd_ring_init_tef(priv, &base);
0287 mcp251xfd_ring_init_rx(priv, &base, &fifo_nr);
0288 mcp251xfd_ring_init_tx(priv, &base, &fifo_nr);
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306 priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr);
0307
0308 if (priv->tx_obj_num_coalesce_irq) {
0309 netdev_dbg(priv->ndev,
0310 "FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes (coalesce)\n",
0311 mcp251xfd_get_tef_obj_addr(0),
0312 priv->tx_obj_num_coalesce_irq,
0313 sizeof(struct mcp251xfd_hw_tef_obj),
0314 priv->tx_obj_num_coalesce_irq *
0315 sizeof(struct mcp251xfd_hw_tef_obj));
0316
0317 netdev_dbg(priv->ndev,
0318 " 0x%03x: %2d*%zu bytes = %4zu bytes\n",
0319 mcp251xfd_get_tef_obj_addr(priv->tx_obj_num_coalesce_irq),
0320 priv->tx->obj_num - priv->tx_obj_num_coalesce_irq,
0321 sizeof(struct mcp251xfd_hw_tef_obj),
0322 (priv->tx->obj_num - priv->tx_obj_num_coalesce_irq) *
0323 sizeof(struct mcp251xfd_hw_tef_obj));
0324 } else {
0325 netdev_dbg(priv->ndev,
0326 "FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes\n",
0327 mcp251xfd_get_tef_obj_addr(0),
0328 priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj),
0329 priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj));
0330 }
0331
0332 mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
0333 if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) {
0334 netdev_dbg(priv->ndev,
0335 "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes (coalesce)\n",
0336 rx_ring->nr, rx_ring->fifo_nr,
0337 mcp251xfd_get_rx_obj_addr(rx_ring, 0),
0338 priv->rx_obj_num_coalesce_irq, rx_ring->obj_size,
0339 priv->rx_obj_num_coalesce_irq * rx_ring->obj_size);
0340
0341 if (priv->rx_obj_num_coalesce_irq == MCP251XFD_FIFO_DEPTH)
0342 continue;
0343
0344 netdev_dbg(priv->ndev,
0345 " 0x%03x: %2u*%u bytes = %4u bytes\n",
0346 mcp251xfd_get_rx_obj_addr(rx_ring,
0347 priv->rx_obj_num_coalesce_irq),
0348 rx_ring->obj_num - priv->rx_obj_num_coalesce_irq,
0349 rx_ring->obj_size,
0350 (rx_ring->obj_num - priv->rx_obj_num_coalesce_irq) *
0351 rx_ring->obj_size);
0352 } else {
0353 netdev_dbg(priv->ndev,
0354 "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
0355 rx_ring->nr, rx_ring->fifo_nr,
0356 mcp251xfd_get_rx_obj_addr(rx_ring, 0),
0357 rx_ring->obj_num, rx_ring->obj_size,
0358 rx_ring->obj_num * rx_ring->obj_size);
0359 }
0360 }
0361
0362 netdev_dbg(priv->ndev,
0363 "FIFO setup: TX: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
0364 priv->tx->fifo_nr,
0365 mcp251xfd_get_tx_obj_addr(priv->tx, 0),
0366 priv->tx->obj_num, priv->tx->obj_size,
0367 priv->tx->obj_num * priv->tx->obj_size);
0368
0369 netdev_dbg(priv->ndev,
0370 "FIFO setup: free: %4d bytes\n",
0371 MCP251XFD_RAM_SIZE - (base - MCP251XFD_RAM_START));
0372
0373 ram_used = base - MCP251XFD_RAM_START;
0374 if (ram_used > MCP251XFD_RAM_SIZE) {
0375 netdev_err(priv->ndev,
0376 "Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n",
0377 ram_used, MCP251XFD_RAM_SIZE);
0378 return -ENOMEM;
0379 }
0380
0381 return 0;
0382 }
0383
0384 void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
0385 {
0386 int i;
0387
0388 for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) {
0389 kfree(priv->rx[i]);
0390 priv->rx[i] = NULL;
0391 }
0392 }
0393
0394 static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t)
0395 {
0396 struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
0397 rx_irq_timer);
0398 struct mcp251xfd_rx_ring *ring = priv->rx[0];
0399
0400 if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
0401 return HRTIMER_NORESTART;
0402
0403 spi_async(priv->spi, &ring->irq_enable_msg);
0404
0405 return HRTIMER_NORESTART;
0406 }
0407
0408 static enum hrtimer_restart mcp251xfd_tx_irq_timer(struct hrtimer *t)
0409 {
0410 struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
0411 tx_irq_timer);
0412 struct mcp251xfd_tef_ring *ring = priv->tef;
0413
0414 if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
0415 return HRTIMER_NORESTART;
0416
0417 spi_async(priv->spi, &ring->irq_enable_msg);
0418
0419 return HRTIMER_NORESTART;
0420 }
0421
0422 const struct can_ram_config mcp251xfd_ram_config = {
0423 .rx = {
0424 .size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can),
0425 .size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_rx_obj_canfd),
0426 .min = MCP251XFD_RX_OBJ_NUM_MIN,
0427 .max = MCP251XFD_RX_OBJ_NUM_MAX,
0428 .def[CAN_RAM_MODE_CAN] = CAN_RAM_NUM_MAX,
0429 .def[CAN_RAM_MODE_CANFD] = CAN_RAM_NUM_MAX,
0430 .fifo_num = MCP251XFD_FIFO_RX_NUM,
0431 .fifo_depth_min = MCP251XFD_RX_FIFO_DEPTH_MIN,
0432 .fifo_depth_coalesce_min = MCP251XFD_RX_FIFO_DEPTH_COALESCE_MIN,
0433 },
0434 .tx = {
0435 .size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_tef_obj) +
0436 sizeof(struct mcp251xfd_hw_tx_obj_can),
0437 .size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_tef_obj) +
0438 sizeof(struct mcp251xfd_hw_tx_obj_canfd),
0439 .min = MCP251XFD_TX_OBJ_NUM_MIN,
0440 .max = MCP251XFD_TX_OBJ_NUM_MAX,
0441 .def[CAN_RAM_MODE_CAN] = MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT,
0442 .def[CAN_RAM_MODE_CANFD] = MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT,
0443 .fifo_num = MCP251XFD_FIFO_TX_NUM,
0444 .fifo_depth_min = MCP251XFD_TX_FIFO_DEPTH_MIN,
0445 .fifo_depth_coalesce_min = MCP251XFD_TX_FIFO_DEPTH_COALESCE_MIN,
0446 },
0447 .size = MCP251XFD_RAM_SIZE,
0448 .fifo_depth = MCP251XFD_FIFO_DEPTH,
0449 };
0450
0451 int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
0452 {
0453 const bool fd_mode = mcp251xfd_is_fd_mode(priv);
0454 struct mcp251xfd_tx_ring *tx_ring = priv->tx;
0455 struct mcp251xfd_rx_ring *rx_ring;
0456 u8 tx_obj_size, rx_obj_size;
0457 u8 rem, i;
0458
0459
0460 if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) {
0461 struct can_ram_layout layout;
0462
0463 can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode);
0464 priv->rx_obj_num = layout.default_rx;
0465 tx_ring->obj_num = layout.default_tx;
0466 }
0467
0468 if (fd_mode) {
0469 tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd);
0470 rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd);
0471 set_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
0472 } else {
0473 tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can);
0474 rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
0475 clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
0476 }
0477
0478 tx_ring->obj_size = tx_obj_size;
0479
0480 rem = priv->rx_obj_num;
0481 for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) {
0482 u8 rx_obj_num;
0483
0484 if (i == 0 && priv->rx_obj_num_coalesce_irq)
0485 rx_obj_num = min_t(u8, priv->rx_obj_num_coalesce_irq * 2,
0486 MCP251XFD_FIFO_DEPTH);
0487 else
0488 rx_obj_num = min_t(u8, rounddown_pow_of_two(rem),
0489 MCP251XFD_FIFO_DEPTH);
0490 rem -= rx_obj_num;
0491
0492 rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
0493 GFP_KERNEL);
0494 if (!rx_ring) {
0495 mcp251xfd_ring_free(priv);
0496 return -ENOMEM;
0497 }
0498
0499 rx_ring->obj_num = rx_obj_num;
0500 rx_ring->obj_size = rx_obj_size;
0501 priv->rx[i] = rx_ring;
0502 }
0503 priv->rx_ring_num = i;
0504
0505 hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
0506 priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer;
0507
0508 hrtimer_init(&priv->tx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
0509 priv->tx_irq_timer.function = mcp251xfd_tx_irq_timer;
0510
0511 return 0;
0512 }