// SPDX-License-Identifier: GPL-2.0-only /* Copyright (C) 2015 - 2016 Thomas Körper, esd electronic system design gmbh * Copyright (C) 2017 - 2023 Stefan Mätje, esd electronics gmbh */ #include "esdacc.h" #include <linux/bitfield.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/ktime.h> /* esdACC ID register layout */ #define ACC_ID_ID_MASK … #define ACC_ID_EFF_FLAG … /* esdACC DLC register layout */ #define ACC_DLC_DLC_MASK … #define ACC_DLC_RTR_FLAG … #define ACC_DLC_SSTX_FLAG … /* esdACC DLC in struct acc_bmmsg_rxtxdone::acc_dlc.len only! */ #define ACC_DLC_TXD_FLAG … /* ecc value of esdACC equals SJA1000's ECC register */ #define ACC_ECC_SEG … #define ACC_ECC_DIR … #define ACC_ECC_BIT … #define ACC_ECC_FORM … #define ACC_ECC_STUFF … #define ACC_ECC_MASK … /* esdACC Status Register bits. Unused bits not documented. */ #define ACC_REG_STATUS_MASK_STATUS_ES … #define ACC_REG_STATUS_MASK_STATUS_EP … #define ACC_REG_STATUS_MASK_STATUS_BS … /* esdACC Overview Module BM_IRQ_Mask register related defines */ /* Two bit wide command masks to mask or unmask a single core IRQ */ #define ACC_BM_IRQ_UNMASK … #define ACC_BM_IRQ_MASK … /* Command to unmask all IRQ sources. Created by shifting * and oring the two bit wide ACC_BM_IRQ_UNMASK 16 times. */ #define ACC_BM_IRQ_UNMASK_ALL … static void acc_resetmode_enter(struct acc_core *core) { … } static void acc_resetmode_leave(struct acc_core *core) { … } static void acc_txq_put(struct acc_core *core, u32 acc_id, u32 acc_dlc, const void *data) { … } static u8 acc_tx_fifo_next(struct acc_core *core, u8 tx_fifo_idx) { … } /* Convert timestamp from esdACC time stamp ticks to ns * * The conversion factor ts2ns from time stamp counts to ns is basically * ts2ns = NSEC_PER_SEC / timestamp_frequency * * We handle here only a fixed timestamp frequency of 80MHz. The * resulting ts2ns factor would be 12.5. * * At the end we multiply by 12 and add the half of the HW timestamp * to get a multiplication by 12.5. This way any overflow is * avoided until ktime_t itself overflows. */ #define ACC_TS_FACTOR … #define ACC_TS_80MHZ_SHIFT … static ktime_t acc_ts2ktime(struct acc_ov *ov, u64 ts) { … } #undef ACC_TS_FACTOR #undef ACC_TS_80MHZ_SHIFT void acc_init_ov(struct acc_ov *ov, struct device *dev) { … } void acc_init_bm_ptr(struct acc_ov *ov, struct acc_core *cores, const void *mem) { … } int acc_open(struct net_device *netdev) { … } int acc_close(struct net_device *netdev) { … } netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev) { … } int acc_get_berr_counter(const struct net_device *netdev, struct can_berr_counter *bec) { … } int acc_set_mode(struct net_device *netdev, enum can_mode mode) { … } int acc_set_bittiming(struct net_device *netdev) { … } static void handle_core_msg_rxtxdone(struct acc_core *core, const struct acc_bmmsg_rxtxdone *msg) { … } static void handle_core_msg_txabort(struct acc_core *core, const struct acc_bmmsg_txabort *msg) { … } static void handle_core_msg_overrun(struct acc_core *core, const struct acc_bmmsg_overrun *msg) { … } static void handle_core_msg_buserr(struct acc_core *core, const struct acc_bmmsg_buserr *msg) { … } static void handle_core_msg_errstatechange(struct acc_core *core, const struct acc_bmmsg_errstatechange *msg) { … } static void handle_core_interrupt(struct acc_core *core) { … } /** * acc_card_interrupt() - handle the interrupts of an esdACC FPGA * * @ov: overview module structure * @cores: array of core structures * * This function handles all interrupts pending for the overview module and the * CAN cores of the esdACC FPGA. * * It examines for all cores (the overview module core and the CAN cores) * the bmfifo.irq_cnt and compares it with the previously saved * bmfifo.local_irq_cnt. An IRQ is pending if they differ. The esdACC FPGA * updates the bmfifo.irq_cnt values by DMA. * * The pending interrupts are masked by writing to the IRQ mask register at * ACC_OV_OF_BM_IRQ_MASK. This register has for each core a two bit command * field evaluated as follows: * * Define, bit pattern: meaning * 00: no action * ACC_BM_IRQ_UNMASK, 01: unmask interrupt * ACC_BM_IRQ_MASK, 10: mask interrupt * 11: no action * * For each CAN core with a pending IRQ handle_core_interrupt() handles all * busmaster messages from the message FIFO. The last handled message (FIFO * index) is written to the CAN core to acknowledge its handling. * * Last step is to unmask all interrupts in the FPGA using * ACC_BM_IRQ_UNMASK_ALL. * * Return: * IRQ_HANDLED, if card generated an interrupt that was handled * IRQ_NONE, if the interrupt is not ours */ irqreturn_t acc_card_interrupt(struct acc_ov *ov, struct acc_core *cores) { … }