summaryrefslogtreecommitdiff
path: root/drivers/gpib/fmh_gpib/fmh_gpib.h
blob: e7602d7e14012dd51a2d709d43dbaf9002b0ca0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* SPDX-License-Identifier: GPL-2.0 */

/***************************************************************************
 *    Author: Frank Mori Hess <fmh6jj@gmail.com>
 *   Copyright: (C) 2006, 2010, 2015 Fluke Corporation
 *	(C) 2017 Frank Mori Hess
 ***************************************************************************/

#include <linux/dmaengine.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/io.h>
#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
};