drivers/net/can/esd/esd_402_pci-core.c

Source file repositories/reference/linux-study-clean/drivers/net/can/esd/esd_402_pci-core.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/esd/esd_402_pci-core.c
Extension
.c
Size
12662 bytes
Lines
516
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.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops pci402_acc_netdev_ops = {
	.ndo_open = acc_open,
	.ndo_stop = acc_close,
	.ndo_start_xmit = acc_start_xmit,
	.ndo_hwtstamp_get = can_hwtstamp_get,
	.ndo_hwtstamp_set = can_hwtstamp_set,
};

static const struct ethtool_ops pci402_acc_ethtool_ops = {
	.get_ts_info = can_ethtool_op_get_ts_info_hwts,
};

static irqreturn_t pci402_interrupt(int irq, void *dev_id)
{
	struct pci_dev *pdev = dev_id;
	struct pci402_card *card = pci_get_drvdata(pdev);
	irqreturn_t irq_status;

	irq_status = acc_card_interrupt(&card->ov, card->cores);

	return irq_status;
}

static int pci402_set_msiconfig(struct pci_dev *pdev)
{
	struct pci402_card *card = pci_get_drvdata(pdev);
	u32 addr_lo_offs = 0;
	u32 addr_lo = 0;
	u32 addr_hi = 0;
	u32 data = 0;
	u16 csr = 0;
	int err;

	/* The FPGA hard IP PCIe core implements a 64-bit MSI Capability
	 * Register Format
	 */
	err = pci_read_config_word(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_FLAGS, &csr);
	if (err)
		goto failed;

	err = pci_read_config_dword(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_ADDRESS_LO,
				    &addr_lo);
	if (err)
		goto failed;
	err = pci_read_config_dword(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_ADDRESS_HI,
				    &addr_hi);
	if (err)
		goto failed;

	err = pci_read_config_dword(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_DATA_64,
				    &data);
	if (err)
		goto failed;

	addr_lo_offs = addr_lo & 0x0000ffff;
	addr_lo &= 0xffff0000;

	if (addr_hi)
		addr_lo |= 1; /* To enable 64-Bit addressing in PCIe endpoint */

	if (!(csr & PCI_MSI_FLAGS_ENABLE)) {
		err = -EINVAL;
		goto failed;
	}

	iowrite32(addr_lo, card->addr_pciep + PCI402_PCIEP_OF_MSI_ADDR_LO);
	iowrite32(addr_hi, card->addr_pciep + PCI402_PCIEP_OF_MSI_ADDR_HI);
	acc_ov_write32(&card->ov, ACC_OV_OF_MSI_ADDRESSOFFSET, addr_lo_offs);
	acc_ov_write32(&card->ov, ACC_OV_OF_MSI_DATA, data);

	return 0;

failed:
	pci_warn(pdev, "Error while setting MSI configuration:\n"
		 "CSR: 0x%.4x, addr: 0x%.8x%.8x, offs: 0x%.4x, data: 0x%.8x\n",
		 csr, addr_hi, addr_lo, addr_lo_offs, data);

	return err;
}

static int pci402_init_card(struct pci_dev *pdev)
{
	struct pci402_card *card = pci_get_drvdata(pdev);

	card->ov.addr = card->addr + PCI402_IO_OV_OFFS;
	card->addr_pciep = card->addr + PCI402_IO_PCIEP_OFFS;

	acc_reset_fpga(&card->ov);
	acc_init_ov(&card->ov, &pdev->dev);

Annotation

Implementation Notes