1 /* SPDX-License-Identifier: GPL-2.0 */
2 
3 /***************************************************************************
4  *    copyright            : (C) 2002 by Frank Mori Hess
5  ***************************************************************************/
6 
7 #include "nec7210.h"
8 #include "gpibP.h"
9 #include "amccs5933.h"
10 
11 #include <linux/delay.h>
12 #include <linux/interrupt.h>
13 
14 enum {
15 	PCI_DEVICE_ID_CBOARDS_PCI_GPIB = 0x6,
16 	PCI_DEVICE_ID_CBOARDS_CPCI_GPIB = 0xe,
17 };
18 
19 enum pci_chip {
20 	PCI_CHIP_NONE = 0,
21 	PCI_CHIP_AMCC_S5933,
22 	PCI_CHIP_QUANCOM
23 };
24 
25 // struct which defines private_data for cb7210 boards
26 struct cb7210_priv {
27 	struct nec7210_priv nec7210_priv;
28 	struct pci_dev *pci_device;
29 	// base address of amccs5933 pci chip
30 	unsigned long amcc_iobase;
31 	unsigned long fifo_iobase;
32 	unsigned int irq;
33 	enum pci_chip pci_chip;
34 	u8 hs_mode_bits;
35 	unsigned out_fifo_half_empty : 1;
36 	unsigned in_fifo_half_full : 1;
37 };
38 
39 // pci-gpib register offset
40 static const int cb7210_reg_offset = 1;
41 
42 // uses 10 ioports
43 static const int cb7210_iosize = 10;
44 
45 // fifo size in bytes
46 static const int cb7210_fifo_size = 2048;
47 static const int cb7210_fifo_width = 2;
48 
49 // cb7210 specific registers and bits
50 enum cb7210_regs {
51 	BUS_STATUS = 0x7,
52 };
53 
54 enum cb7210_page_in {
55 	BUS_STATUS_PAGE = 1,
56 };
57 
58 enum hs_regs {
59 	//write registers
60 	HS_MODE = 0x8,	/* HS_MODE register */
61 	HS_INT_LEVEL = 0x9,	/* HS_INT_LEVEL register */
62 	//read registers
63 	HS_STATUS = 0x8,	/* HS_STATUS register */
64 };
65 
nec7210_iobase(const struct cb7210_priv * cb_priv)66 static inline u32 nec7210_iobase(const struct cb7210_priv *cb_priv)
67 {
68 	return cb_priv->nec7210_priv.iobase;
69 }
70 
cb7210_page_in_bits(unsigned int page)71 static inline int cb7210_page_in_bits(unsigned int page)
72 {
73 	return 0x50 | (page & 0xf);
74 }
75 
cb7210_paged_read_byte(struct cb7210_priv * cb_priv,unsigned int register_num,unsigned int page)76 static inline u8 cb7210_paged_read_byte(struct cb7210_priv *cb_priv,
77 					unsigned int register_num, unsigned int page)
78 {
79 	struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
80 	u8 retval;
81 	unsigned long flags;
82 
83 	spin_lock_irqsave(&nec_priv->register_page_lock, flags);
84 	outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
85 	udelay(1);
86 	retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
87 	spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
88 	return retval;
89 }
90 
91 // don't use for register_num < 8, since it doesn't lock
cb7210_read_byte(const struct cb7210_priv * cb_priv,enum hs_regs register_num)92 static inline u8 cb7210_read_byte(const struct cb7210_priv *cb_priv,
93 				  enum hs_regs register_num)
94 {
95 	const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
96 	u8 retval;
97 
98 	retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
99 	return retval;
100 }
101 
cb7210_paged_write_byte(struct cb7210_priv * cb_priv,u8 data,unsigned int register_num,unsigned int page)102 static inline void cb7210_paged_write_byte(struct cb7210_priv *cb_priv, u8 data,
103 					   unsigned int register_num, unsigned int page)
104 {
105 	struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
106 	unsigned long flags;
107 
108 	spin_lock_irqsave(&nec_priv->register_page_lock, flags);
109 	outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
110 	udelay(1);
111 	outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
112 	spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
113 }
114 
115 // don't use for register_num < 8, since it doesn't lock
cb7210_write_byte(const struct cb7210_priv * cb_priv,u8 data,enum hs_regs register_num)116 static inline void cb7210_write_byte(const struct cb7210_priv *cb_priv, u8 data,
117 				     enum hs_regs register_num)
118 {
119 	const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
120 
121 	outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
122 }
123 
124 enum bus_status_bits {
125 	BSR_ATN_BIT = 0x1,
126 	BSR_EOI_BIT = 0x2,
127 	BSR_SRQ_BIT = 0x4,
128 	BSR_IFC_BIT = 0x8,
129 	BSR_REN_BIT = 0x10,
130 	BSR_DAV_BIT = 0x20,
131 	BSR_NRFD_BIT = 0x40,
132 	BSR_NDAC_BIT = 0x80,
133 };
134 
135 /* CBI 488.2 HS control */
136 
137 /*
138  * when both bit 0 and 1 are set, it
139  *   1 clears the transmit state machine to an initial condition
140  *   2 clears any residual interrupts left latched on cbi488.2
141  *   3 resets all control bits in HS_MODE to zero
142  *   4 enables TX empty interrupts
143  * when both bit 0 and 1 are zero, then the high speed mode is disabled
144  */
145 enum hs_mode_bits {
146 	HS_ENABLE_MASK = 0x3,
147 	HS_TX_ENABLE = (1 << 0),
148 	HS_RX_ENABLE = (1 << 1),
149 	HS_HF_INT_EN = (1 << 3),
150 	HS_CLR_SRQ_INT = (1 << 4),
151 	HS_CLR_EOI_EMPTY_INT = (1 << 5),
152 	HS_CLR_HF_INT = (1 << 6),
153 	HS_SYS_CONTROL = (1 << 7),
154 };
155 
156 /* CBI 488.2 status */
157 enum hs_status_bits {
158 	HS_FIFO_FULL = (1 << 0),
159 	HS_HALF_FULL = (1 << 1),
160 	HS_SRQ_INT = (1 << 2),
161 	HS_EOI_INT = (1 << 3),
162 	HS_TX_MSB_NOT_EMPTY = (1 << 4),
163 	HS_RX_MSB_NOT_EMPTY = (1 << 5),
164 	HS_TX_LSB_NOT_EMPTY = (1 << 6),
165 	HS_RX_LSB_NOT_EMPTY = (1 << 7),
166 };
167 
168 /* CBI488.2 hs_int_level register */
169 enum hs_int_level_bits {
170 	HS_RESET7210 = (1 << 7),
171 };
172 
irq_bits(unsigned int irq)173 static inline unsigned int irq_bits(unsigned int irq)
174 {
175 	switch (irq) {
176 	case 2:
177 	case 3:
178 	case 4:
179 	case 5:
180 		return irq - 1;
181 	case 7:
182 		return 0x5;
183 	case 10:
184 		return 0x6;
185 	case 11:
186 		return 0x7;
187 	default:
188 		return 0;
189 	}
190 }
191 
192 enum cb7210_aux_cmds {
193 /*
194  * AUX_RTL2 is an undocumented aux command which causes cb7210 to assert
195  * (and keep asserted) local rtl message.  This is used in conjunction
196  * with the (stupid) cb7210 implementation
197  * of the normal nec7210 AUX_RTL aux command, which
198  * causes the rtl message to toggle between on and off.
199  */
200 	AUX_RTL2 = 0xd,
201 	AUX_LO_SPEED = 0x40,
202 	AUX_HI_SPEED = 0x41,
203 };
204