drivers/net/can/spi/mcp251x.c
Source file repositories/reference/linux-study-clean/drivers/net/can/spi/mcp251x.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/can/spi/mcp251x.c- Extension
.c- Size
- 40859 bytes
- Lines
- 1573
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern 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.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- 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
linux/bitfield.hlinux/can/core.hlinux/can/dev.hlinux/clk.hlinux/completion.hlinux/delay.hlinux/device.hlinux/ethtool.hlinux/freezer.hlinux/gpio/driver.hlinux/interrupt.hlinux/io.hlinux/iopoll.hlinux/kernel.hlinux/module.hlinux/netdevice.hlinux/platform_device.hlinux/property.hlinux/regulator/consumer.hlinux/slab.hlinux/spi/spi.hlinux/uaccess.h
Detected Declarations
struct mcp251x_privenum mcp251x_modelfunction mcp251x_cleanfunction mcp251x_spi_transfunction mcp251x_spi_writefunction mcp251x_read_regfunction mcp251x_read_2regsfunction mcp251x_write_regfunction mcp251x_write_2regsfunction mcp251x_write_bitsfunction mcp251x_read_statfunction mcp251x_gpio_is_inputfunction mcp251x_gpio_requestfunction mcp251x_gpio_freefunction mcp251x_gpio_get_directionfunction mcp251x_gpio_getfunction mcp251x_gpio_get_multiplefunction mcp251x_gpio_setfunction mcp251x_gpio_set_multiplefunction mcp251x_gpio_restorefunction mcp251x_gpio_setupfunction mcp251x_gpio_restorefunction mcp251x_hw_tx_framefunction mcp251x_hw_txfunction mcp251x_hw_rx_framefunction mcp251x_hw_rxfunction mcp251x_hw_sleepfunction mcp251x_hw_wakefunction mcp251x_hard_start_xmitfunction mcp251x_do_set_modefunction mcp251x_set_normal_modefunction mcp251x_do_set_bittimingfunction mcp251x_setupfunction mcp251x_hw_resetfunction mcp251x_hw_probefunction mcp251x_power_enablefunction mcp251x_stopfunction mcp251x_error_skbfunction mcp251x_tx_work_handlerfunction mcp251x_restart_work_handlerfunction mcp251x_can_istfunction mcp251x_openfunction mcp251x_can_probefunction mcp251x_can_removefunction mcp251x_can_suspendfunction mcp251x_can_resume
Annotated Snippet
static const struct net_device_ops mcp251x_netdev_ops = {
.ndo_open = mcp251x_open,
.ndo_stop = mcp251x_stop,
.ndo_start_xmit = mcp251x_hard_start_xmit,
};
static const struct ethtool_ops mcp251x_ethtool_ops = {
.get_ts_info = ethtool_op_get_ts_info,
};
static const struct of_device_id mcp251x_of_match[] = {
{
.compatible = "microchip,mcp2510",
.data = (void *)CAN_MCP251X_MCP2510,
},
{
.compatible = "microchip,mcp2515",
.data = (void *)CAN_MCP251X_MCP2515,
},
{
.compatible = "microchip,mcp25625",
.data = (void *)CAN_MCP251X_MCP25625,
},
{ }
};
MODULE_DEVICE_TABLE(of, mcp251x_of_match);
static const struct spi_device_id mcp251x_id_table[] = {
{
.name = "mcp2510",
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2510,
},
{
.name = "mcp2515",
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515,
},
{
.name = "mcp25625",
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP25625,
},
{ }
};
MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
static int mcp251x_can_probe(struct spi_device *spi)
{
struct net_device *net;
struct mcp251x_priv *priv;
struct clk *clk;
u32 freq;
int ret;
clk = devm_clk_get_optional(&spi->dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(&spi->dev, PTR_ERR(clk), "Cannot get clock\n");
freq = clk_get_rate(clk);
if (freq == 0)
device_property_read_u32(&spi->dev, "clock-frequency", &freq);
/* Sanity check */
if (freq < 1000000 || freq > 25000000)
return dev_err_probe(&spi->dev, -ERANGE, "clock frequency out of range\n");
/* Allocate can/net device */
net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
if (!net)
return -ENOMEM;
ret = clk_prepare_enable(clk);
if (ret) {
dev_err_probe(&spi->dev, ret, "Cannot enable clock\n");
goto out_free;
}
net->netdev_ops = &mcp251x_netdev_ops;
net->ethtool_ops = &mcp251x_ethtool_ops;
net->flags |= IFF_ECHO;
priv = netdev_priv(net);
priv->can.bittiming_const = &mcp251x_bittiming_const;
priv->can.do_set_mode = mcp251x_do_set_mode;
priv->can.clock.freq = freq / 2;
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
priv->model = (enum mcp251x_model)(uintptr_t)spi_get_device_match_data(spi);
priv->net = net;
priv->clk = clk;
spi_set_drvdata(spi, priv);
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/can/core.h`, `linux/can/dev.h`, `linux/clk.h`, `linux/completion.h`, `linux/delay.h`, `linux/device.h`, `linux/ethtool.h`.
- Detected declarations: `struct mcp251x_priv`, `enum mcp251x_model`, `function mcp251x_clean`, `function mcp251x_spi_trans`, `function mcp251x_spi_write`, `function mcp251x_read_reg`, `function mcp251x_read_2regs`, `function mcp251x_write_reg`, `function mcp251x_write_2regs`, `function mcp251x_write_bits`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
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.