/* SPDX-License-Identifier: GPL-2.0 */ /*************************************************************************** * Author: Frank Mori Hess * Copyright: (C) 2006, 2010, 2015 Fluke Corporation * (C) 2017 Frank Mori Hess ***************************************************************************/ #include #include #include #include #include "nec7210.h" static const int fifo_reg_offset = 2; static const int gpib_control_status_pci_resource_index; static const int gpib_fifo_pci_resource_index = 1; /* We don't have a real pci vendor/device id, the following will need to be * patched to match prototype hardware. */ #define BOGUS_PCI_VENDOR_ID_FLUKE 0xffff #define BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER 0x0 struct fmh_priv { struct nec7210_priv nec7210_priv; struct resource *gpib_iomem_res; struct resource *write_transfer_counter_res; struct resource *dma_port_res; int irq; struct dma_chan *dma_channel; u8 *dma_buffer; int dma_buffer_size; int dma_burst_length; void __iomem *fifo_base; unsigned supports_fifo_interrupts : 1; }; static inline int fmh_gpib_half_fifo_size(struct fmh_priv *priv) { return priv->dma_burst_length; } // registers beyond the nec7210 register set enum fmh_gpib_regs { EXT_STATUS_1_REG = 0x9, STATE1_REG = 0xc, ISR0_IMR0_REG = 0xe, BUS_STATUS_REG = 0xf }; /* IMR0 -- Interrupt Mode Register 0 */ enum imr0_bits { ATN_INTERRUPT_ENABLE_BIT = 0x4, IFC_INTERRUPT_ENABLE_BIT = 0x8 }; /* ISR0 -- Interrupt Status Register 0 */ enum isr0_bits { ATN_INTERRUPT_BIT = 0x4, IFC_INTERRUPT_BIT = 0x8 }; enum state1_bits { SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */ SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */ SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */ SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */ SOURCE_HANDSHAKE_MASK = 0x7 }; enum fmh_gpib_auxmr_bits { AUX_I_REG = 0xe0, }; enum aux_reg_i_bits { LOCAL_PPOLL_MODE_BIT = 0x4 }; enum ext_status_1_bits { DATA_IN_STATUS_BIT = 0x01, DATA_OUT_STATUS_BIT = 0x02, COMMAND_OUT_STATUS_BIT = 0x04, RFD_HOLDOFF_STATUS_BIT = 0x08, END_STATUS_BIT = 0x10 }; /* dma fifo reg and bits */ enum dma_fifo_regs { FIFO_DATA_REG = 0x0, FIFO_CONTROL_STATUS_REG = 0x1, FIFO_XFER_COUNTER_REG = 0x2, FIFO_MAX_BURST_LENGTH_REG = 0x3 }; enum fifo_data_bits { FIFO_DATA_EOI_FLAG = 0x100 }; enum fifo_control_bits { TX_FIFO_DMA_REQUEST_ENABLE = 0x0001, TX_FIFO_CLEAR = 0x0002, TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE = 0x0008, RX_FIFO_DMA_REQUEST_ENABLE = 0x0100, RX_FIFO_CLEAR = 0x0200, RX_FIFO_HALF_FULL_INTERRUPT_ENABLE = 0x0800 }; enum fifo_status_bits { TX_FIFO_EMPTY = 0x0001, TX_FIFO_FULL = 0x0002, TX_FIFO_HALF_EMPTY = 0x0004, TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED = 0x0008, TX_FIFO_DMA_REQUEST_IS_ENABLED = 0x0010, RX_FIFO_EMPTY = 0x0100, RX_FIFO_FULL = 0x0200, RX_FIFO_HALF_FULL = 0x0400, RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED = 0x0800, RX_FIFO_DMA_REQUEST_IS_ENABLED = 0x1000 }; static const unsigned int fifo_data_mask = 0x00ff; static const unsigned int fifo_xfer_counter_mask = 0x0fff; static const unsigned int fifo_max_burst_length_mask = 0x00ff; static inline u8 gpib_cs_read_byte(struct nec7210_priv *nec_priv, unsigned int register_num) { return readb(nec_priv->mmiobase + register_num * nec_priv->offset); } static inline void gpib_cs_write_byte(struct nec7210_priv *nec_priv, u8 data, unsigned int register_num) { writeb(data, nec_priv->mmiobase + register_num * nec_priv->offset); } static inline uint16_t fifos_read(struct fmh_priv *fmh_priv, int register_num) { if (!fmh_priv->fifo_base) return 0; return readw(fmh_priv->fifo_base + register_num * fifo_reg_offset); } static inline void fifos_write(struct fmh_priv *fmh_priv, uint16_t data, int register_num) { if (!fmh_priv->fifo_base) return; writew(data, fmh_priv->fifo_base + register_num * fifo_reg_offset); } enum bus_status_bits { BSR_ATN_BIT = 0x01, BSR_EOI_BIT = 0x02, BSR_SRQ_BIT = 0x04, BSR_IFC_BIT = 0x08, BSR_REN_BIT = 0x10, BSR_DAV_BIT = 0x20, BSR_NRFD_BIT = 0x40, BSR_NDAC_BIT = 0x80, }; enum fmh_gpib_aux_cmds { /* AUX_RTL2 is an auxiliary command which causes the cb7210 to assert * (and keep asserted) the local rtl message. This is used in conjunction * with the normal nec7210 AUX_RTL command, which * pulses the rtl message, having the effect of clearing rtl if it was left * asserted by AUX_RTL2. */ AUX_RTL2 = 0x0d, AUX_RFD_HOLDOFF_ASAP = 0x15, AUX_REQT = 0x18, AUX_REQF = 0x19, AUX_LO_SPEED = 0x40, AUX_HI_SPEED = 0x41 };