File Index
Files and directories
Sign in
FILE

mcp251xfd-chip-fifo.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/can/spi/mcp251xfd/mcp251xfd-chip-fifo.c C
  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 <kernel@pengutronix.de>
  7//
  8// Based on:
  9//
 10// CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
 11//
 12// Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
 13//
 14
 15#include <linux/bitfield.h>
 16
 17#include "mcp251xfd.h"
 18
 19static int
 20mcp251xfd_chip_rx_fifo_init_one(const struct mcp251xfd_priv *priv,
 21				const struct mcp251xfd_rx_ring *ring)
 22{
 23	u32 fifo_con;
 24
 25	/* Enable RXOVIE on _all_ RX FIFOs, not just the last one.
 26	 *
 27	 * FIFOs hit by a RX MAB overflow and RXOVIE enabled will
 28	 * generate a RXOVIF, use this to properly detect RX MAB
 29	 * overflows.
 30	 */
 31	fifo_con = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK,
 32			      ring->obj_num - 1) |
 33		MCP251XFD_REG_FIFOCON_RXTSEN |
 34		MCP251XFD_REG_FIFOCON_RXOVIE |
 35		MCP251XFD_REG_FIFOCON_TFNRFNIE;
 36
 37	if (mcp251xfd_is_fd_mode(priv))
 38		fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
 39				       MCP251XFD_REG_FIFOCON_PLSIZE_64);
 40	else
 41		fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
 42				       MCP251XFD_REG_FIFOCON_PLSIZE_8);
 43
 44	return regmap_write(priv->map_reg,
 45			    MCP251XFD_REG_FIFOCON(ring->fifo_nr), fifo_con);
 46}
 47
 48static int
 49mcp251xfd_chip_rx_filter_init_one(const struct mcp251xfd_priv *priv,
 50				  const struct mcp251xfd_rx_ring *ring)
 51{
 52	u32 fltcon;
 53
 54	fltcon = MCP251XFD_REG_FLTCON_FLTEN(ring->nr) |
 55		MCP251XFD_REG_FLTCON_FBP(ring->nr, ring->fifo_nr);
 56
 57	return regmap_update_bits(priv->map_reg,
 58				  MCP251XFD_REG_FLTCON(ring->nr >> 2),
 59				  MCP251XFD_REG_FLTCON_FLT_MASK(ring->nr),
 60				  fltcon);
 61}
 62
 63int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv)
 64{
 65	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
 66	const struct mcp251xfd_rx_ring *rx_ring;
 67	u32 val;
 68	int err, n;
 69
 70	/* TEF */
 71	val = FIELD_PREP(MCP251XFD_REG_TEFCON_FSIZE_MASK,
 72			 tx_ring->obj_num - 1) |
 73		MCP251XFD_REG_TEFCON_TEFTSEN |
 74		MCP251XFD_REG_TEFCON_TEFOVIE |
 75		MCP251XFD_REG_TEFCON_TEFNEIE;
 76
 77	err = regmap_write(priv->map_reg, MCP251XFD_REG_TEFCON, val);
 78	if (err)
 79		return err;
 80
 81	/* TX FIFO */
 82	val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK,
 83			 tx_ring->obj_num - 1) |
 84		MCP251XFD_REG_FIFOCON_TXEN |
 85		MCP251XFD_REG_FIFOCON_TXATIE;
 86
 87	if (mcp251xfd_is_fd_mode(priv))
 88		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
 89				  MCP251XFD_REG_FIFOCON_PLSIZE_64);
 90	else
 91		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
 92				  MCP251XFD_REG_FIFOCON_PLSIZE_8);
 93
 94	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
 95		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK,
 96				  MCP251XFD_REG_FIFOCON_TXAT_ONE_SHOT);
 97	else
 98		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK,
 99				  MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED);
100
101	err = regmap_write(priv->map_reg,
102			   MCP251XFD_REG_FIFOCON(priv->tx->fifo_nr),
103			   val);
104	if (err)
105		return err;
106
107	/* RX FIFOs */
108	mcp251xfd_for_each_rx_ring(priv, rx_ring, n) {
109		err = mcp251xfd_chip_rx_fifo_init_one(priv, rx_ring);
110		if (err)
111			return err;
112
113		err = mcp251xfd_chip_rx_filter_init_one(priv, rx_ring);
114		if (err)
115			return err;
116	}
117
118	return 0;
119}
~/ Read-only file preview.