drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
Source file repositories/reference/linux-study-clean/drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/can/spi/mcp251xfd/mcp251xfd-regmap.c- Extension
.c- Size
- 19157 bytes
- Lines
- 688
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
mcp251xfd.hlinux/unaligned.h
Detected Declarations
function _mcp251xfd_regmap_nocrc_gather_writefunction mcp251xfd_regmap_nocrc_gather_writefunction mcp251xfd_regmap_nocrc_writefunction mcp251xfd_update_bits_read_regfunction mcp251xfd_for_each_rx_ringfunction mcp251xfd_regmap_nocrc_update_bitsfunction mcp251xfd_regmap_nocrc_readfunction _mcp251xfd_regmap_crc_gather_writefunction mcp251xfd_regmap_crc_gather_writefunction mcp251xfd_regmap_crc_writefunction mcp251xfd_regmap_crc_read_check_crcfunction mcp251xfd_regmap_crc_read_onefunction mcp251xfd_regmap_crc_readfunction bytefunction mcp251xfd_regmap_use_nocrcfunction mcp251xfd_regmap_use_crcfunction mcp251xfd_regmap_init_nocrcfunction mcp251xfd_regmap_destroy_nocrcfunction mcp251xfd_regmap_init_crcfunction mcp251xfd_regmap_destroy_crcfunction mcp251xfd_regmap_init
Annotated Snippet
mcp251xfd_for_each_rx_ring(priv, ring, n) {
if (reg == MCP251XFD_REG_FIFOCON(ring->fifo_nr))
return false;
if (reg == MCP251XFD_REG_FIFOSTA(ring->fifo_nr))
return true;
}
WARN(1, "Status of reg 0x%04x unknown.\n", reg);
}
return true;
}
static int
mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
unsigned int mask, unsigned int val)
{
struct spi_device *spi = context;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
__le32 orig_le32 = 0, mask_le32, val_le32, tmp_le32;
u8 first_byte, last_byte, len;
int err;
BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16));
BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
mask == 0)
return -EINVAL;
first_byte = mcp251xfd_first_byte_set(mask);
last_byte = mcp251xfd_last_byte_set(mask);
len = last_byte - first_byte + 1;
if (mcp251xfd_update_bits_read_reg(priv, reg)) {
struct spi_transfer xfer[2] = { };
struct spi_message msg;
spi_message_init(&msg);
spi_message_add_tail(&xfer[0], &msg);
if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
xfer[0].tx_buf = buf_tx;
xfer[0].len = sizeof(buf_tx->cmd);
xfer[1].rx_buf = buf_rx->data;
xfer[1].len = len;
spi_message_add_tail(&xfer[1], &msg);
} else {
xfer[0].tx_buf = buf_tx;
xfer[0].rx_buf = buf_rx;
xfer[0].len = sizeof(buf_tx->cmd) + len;
if (MCP251XFD_SANITIZE_SPI)
memset(buf_tx->data, 0x0, len);
}
mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, reg + first_byte);
err = spi_sync(spi, &msg);
if (err)
return err;
memcpy(&orig_le32, buf_rx->data, len);
}
mask_le32 = cpu_to_le32(mask >> BITS_PER_BYTE * first_byte);
val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
tmp_le32 = orig_le32 & ~mask_le32;
tmp_le32 |= val_le32 & mask_le32;
reg += first_byte;
mcp251xfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg);
return mcp251xfd_regmap_nocrc_gather_write(context, &buf_tx->cmd, 2, &tmp_le32, len);
}
static int
mcp251xfd_regmap_nocrc_read(void *context,
const void *reg, size_t reg_len,
void *val_buf, size_t val_len)
{
struct spi_device *spi = context;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
struct spi_transfer xfer[2] = { };
struct spi_message msg;
int err;
Annotation
- Immediate include surface: `mcp251xfd.h`, `linux/unaligned.h`.
- Detected declarations: `function _mcp251xfd_regmap_nocrc_gather_write`, `function mcp251xfd_regmap_nocrc_gather_write`, `function mcp251xfd_regmap_nocrc_write`, `function mcp251xfd_update_bits_read_reg`, `function mcp251xfd_for_each_rx_ring`, `function mcp251xfd_regmap_nocrc_update_bits`, `function mcp251xfd_regmap_nocrc_read`, `function _mcp251xfd_regmap_crc_gather_write`, `function mcp251xfd_regmap_crc_gather_write`, `function mcp251xfd_regmap_crc_write`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.