mcp251xfd-chip-fifo.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: GPL-2.0
  2. //
  3. // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
  4. //
  5. // Copyright (c) 2019, 2020, 2021 Pengutronix,
  6. // Marc Kleine-Budde <[email protected]>
  7. //
  8. // Based on:
  9. //
  10. // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
  11. //
  12. // Copyright (c) 2019 Martin Sperl <[email protected]>
  13. //
  14. #include <linux/bitfield.h>
  15. #include "mcp251xfd.h"
  16. static int
  17. mcp251xfd_chip_rx_fifo_init_one(const struct mcp251xfd_priv *priv,
  18. const struct mcp251xfd_rx_ring *ring)
  19. {
  20. u32 fifo_con;
  21. /* Enable RXOVIE on _all_ RX FIFOs, not just the last one.
  22. *
  23. * FIFOs hit by a RX MAB overflow and RXOVIE enabled will
  24. * generate a RXOVIF, use this to properly detect RX MAB
  25. * overflows.
  26. */
  27. fifo_con = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK,
  28. ring->obj_num - 1) |
  29. MCP251XFD_REG_FIFOCON_RXTSEN |
  30. MCP251XFD_REG_FIFOCON_RXOVIE |
  31. MCP251XFD_REG_FIFOCON_TFNRFNIE;
  32. if (mcp251xfd_is_fd_mode(priv))
  33. fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
  34. MCP251XFD_REG_FIFOCON_PLSIZE_64);
  35. else
  36. fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
  37. MCP251XFD_REG_FIFOCON_PLSIZE_8);
  38. return regmap_write(priv->map_reg,
  39. MCP251XFD_REG_FIFOCON(ring->fifo_nr), fifo_con);
  40. }
  41. static int
  42. mcp251xfd_chip_rx_filter_init_one(const struct mcp251xfd_priv *priv,
  43. const struct mcp251xfd_rx_ring *ring)
  44. {
  45. u32 fltcon;
  46. fltcon = MCP251XFD_REG_FLTCON_FLTEN(ring->nr) |
  47. MCP251XFD_REG_FLTCON_FBP(ring->nr, ring->fifo_nr);
  48. return regmap_update_bits(priv->map_reg,
  49. MCP251XFD_REG_FLTCON(ring->nr >> 2),
  50. MCP251XFD_REG_FLTCON_FLT_MASK(ring->nr),
  51. fltcon);
  52. }
  53. int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv)
  54. {
  55. const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
  56. const struct mcp251xfd_rx_ring *rx_ring;
  57. u32 val;
  58. int err, n;
  59. /* TEF */
  60. val = FIELD_PREP(MCP251XFD_REG_TEFCON_FSIZE_MASK,
  61. tx_ring->obj_num - 1) |
  62. MCP251XFD_REG_TEFCON_TEFTSEN |
  63. MCP251XFD_REG_TEFCON_TEFOVIE |
  64. MCP251XFD_REG_TEFCON_TEFNEIE;
  65. err = regmap_write(priv->map_reg, MCP251XFD_REG_TEFCON, val);
  66. if (err)
  67. return err;
  68. /* TX FIFO */
  69. val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK,
  70. tx_ring->obj_num - 1) |
  71. MCP251XFD_REG_FIFOCON_TXEN |
  72. MCP251XFD_REG_FIFOCON_TXATIE;
  73. if (mcp251xfd_is_fd_mode(priv))
  74. val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
  75. MCP251XFD_REG_FIFOCON_PLSIZE_64);
  76. else
  77. val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
  78. MCP251XFD_REG_FIFOCON_PLSIZE_8);
  79. if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
  80. val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK,
  81. MCP251XFD_REG_FIFOCON_TXAT_ONE_SHOT);
  82. else
  83. val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK,
  84. MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED);
  85. err = regmap_write(priv->map_reg,
  86. MCP251XFD_REG_FIFOCON(priv->tx->fifo_nr),
  87. val);
  88. if (err)
  89. return err;
  90. /* RX FIFOs */
  91. mcp251xfd_for_each_rx_ring(priv, rx_ring, n) {
  92. err = mcp251xfd_chip_rx_fifo_init_one(priv, rx_ring);
  93. if (err)
  94. return err;
  95. err = mcp251xfd_chip_rx_filter_init_one(priv, rx_ring);
  96. if (err)
  97. return err;
  98. }
  99. return 0;
  100. }