xref: /linux/drivers/staging/gpib/cec/cec_gpib.c (revision 91fff6fa94cbe13d28caa978ce3f600749304e11)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /***************************************************************************
4  *   copyright            : (C) 2002 by Frank Mori Hess
5  ***************************************************************************/
6 
7 #include "cec.h"
8 #include <linux/pci.h>
9 #include <linux/io.h>
10 #include <linux/bitops.h>
11 #include <asm/dma.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 
15 MODULE_LICENSE("GPL");
16 MODULE_DESCRIPTION("GPIB driver for CEC PCI and PCMCIA boards");
17 
18 /*
19  * GPIB interrupt service routines
20  */
21 
cec_interrupt(int irq,void * arg)22 irqreturn_t cec_interrupt(int irq, void *arg)
23 {
24 	gpib_board_t *board = arg;
25 	struct cec_priv *priv = board->private_data;
26 	unsigned long flags;
27 	irqreturn_t retval;
28 
29 	spin_lock_irqsave(&board->spinlock, flags);
30 	retval = nec7210_interrupt(board, &priv->nec7210_priv);
31 	spin_unlock_irqrestore(&board->spinlock, flags);
32 	return retval;
33 }
34 
35 #define CEC_VENDOR_ID 0x12fc
36 #define CEC_DEV_ID    0x5cec
37 #define CEC_SUBID 0x9050
38 
39 static int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
40 
41 static void cec_pci_detach(gpib_board_t *board);
42 
43 // wrappers for interface functions
cec_read(gpib_board_t * board,uint8_t * buffer,size_t length,int * end,size_t * bytes_read)44 int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
45 {
46 	struct cec_priv *priv = board->private_data;
47 
48 	return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
49 }
50 
cec_write(gpib_board_t * board,uint8_t * buffer,size_t length,int send_eoi,size_t * bytes_written)51 int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
52 	      size_t *bytes_written)
53 {
54 	struct cec_priv *priv = board->private_data;
55 
56 	return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
57 }
58 
cec_command(gpib_board_t * board,uint8_t * buffer,size_t length,size_t * bytes_written)59 int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
60 {
61 	struct cec_priv *priv = board->private_data;
62 
63 	return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
64 }
65 
cec_take_control(gpib_board_t * board,int synchronous)66 int cec_take_control(gpib_board_t *board, int synchronous)
67 {
68 	struct cec_priv *priv = board->private_data;
69 
70 	return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
71 }
72 
cec_go_to_standby(gpib_board_t * board)73 int cec_go_to_standby(gpib_board_t *board)
74 {
75 	struct cec_priv *priv = board->private_data;
76 
77 	return nec7210_go_to_standby(board, &priv->nec7210_priv);
78 }
79 
cec_request_system_control(gpib_board_t * board,int request_control)80 void cec_request_system_control(gpib_board_t *board, int request_control)
81 {
82 	struct cec_priv *priv = board->private_data;
83 
84 	nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
85 }
86 
cec_interface_clear(gpib_board_t * board,int assert)87 void cec_interface_clear(gpib_board_t *board, int assert)
88 {
89 	struct cec_priv *priv = board->private_data;
90 
91 	nec7210_interface_clear(board, &priv->nec7210_priv, assert);
92 }
93 
cec_remote_enable(gpib_board_t * board,int enable)94 void cec_remote_enable(gpib_board_t *board, int enable)
95 {
96 	struct cec_priv *priv = board->private_data;
97 
98 	nec7210_remote_enable(board, &priv->nec7210_priv, enable);
99 }
100 
cec_enable_eos(gpib_board_t * board,uint8_t eos_byte,int compare_8_bits)101 int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
102 {
103 	struct cec_priv *priv = board->private_data;
104 
105 	return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
106 }
107 
cec_disable_eos(gpib_board_t * board)108 void cec_disable_eos(gpib_board_t *board)
109 {
110 	struct cec_priv *priv = board->private_data;
111 
112 	nec7210_disable_eos(board, &priv->nec7210_priv);
113 }
114 
cec_update_status(gpib_board_t * board,unsigned int clear_mask)115 unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask)
116 {
117 	struct cec_priv *priv = board->private_data;
118 
119 	return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
120 }
121 
cec_primary_address(gpib_board_t * board,unsigned int address)122 int cec_primary_address(gpib_board_t *board, unsigned int address)
123 {
124 	struct cec_priv *priv = board->private_data;
125 
126 	return nec7210_primary_address(board, &priv->nec7210_priv, address);
127 }
128 
cec_secondary_address(gpib_board_t * board,unsigned int address,int enable)129 int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable)
130 {
131 	struct cec_priv *priv = board->private_data;
132 
133 	return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
134 }
135 
cec_parallel_poll(gpib_board_t * board,uint8_t * result)136 int cec_parallel_poll(gpib_board_t *board, uint8_t *result)
137 {
138 	struct cec_priv *priv = board->private_data;
139 
140 	return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
141 }
142 
cec_parallel_poll_configure(gpib_board_t * board,uint8_t config)143 void cec_parallel_poll_configure(gpib_board_t *board, uint8_t config)
144 {
145 	struct cec_priv *priv = board->private_data;
146 
147 	nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
148 }
149 
cec_parallel_poll_response(gpib_board_t * board,int ist)150 void cec_parallel_poll_response(gpib_board_t *board, int ist)
151 {
152 	struct cec_priv *priv = board->private_data;
153 
154 	nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
155 }
156 
cec_serial_poll_response(gpib_board_t * board,uint8_t status)157 void cec_serial_poll_response(gpib_board_t *board, uint8_t status)
158 {
159 	struct cec_priv *priv = board->private_data;
160 
161 	nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
162 }
163 
cec_serial_poll_status(gpib_board_t * board)164 static uint8_t cec_serial_poll_status(gpib_board_t *board)
165 {
166 	struct cec_priv *priv = board->private_data;
167 
168 	return nec7210_serial_poll_status(board, &priv->nec7210_priv);
169 }
170 
cec_t1_delay(gpib_board_t * board,unsigned int nano_sec)171 static unsigned int cec_t1_delay(gpib_board_t *board, unsigned int nano_sec)
172 {
173 	struct cec_priv *priv = board->private_data;
174 
175 	return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec);
176 }
177 
cec_return_to_local(gpib_board_t * board)178 void cec_return_to_local(gpib_board_t *board)
179 {
180 	struct cec_priv *priv = board->private_data;
181 
182 	nec7210_return_to_local(board, &priv->nec7210_priv);
183 }
184 
185 gpib_interface_t cec_pci_interface = {
186 name: "cec_pci",
187 attach : cec_pci_attach,
188 detach : cec_pci_detach,
189 read : cec_read,
190 write : cec_write,
191 command : cec_command,
192 take_control : cec_take_control,
193 go_to_standby : cec_go_to_standby,
194 request_system_control : cec_request_system_control,
195 interface_clear : cec_interface_clear,
196 remote_enable : cec_remote_enable,
197 enable_eos : cec_enable_eos,
198 disable_eos : cec_disable_eos,
199 parallel_poll : cec_parallel_poll,
200 parallel_poll_configure : cec_parallel_poll_configure,
201 parallel_poll_response : cec_parallel_poll_response,
202 local_parallel_poll_mode : NULL, // XXX
203 line_status : NULL,	//XXX
204 update_status : cec_update_status,
205 primary_address : cec_primary_address,
206 secondary_address : cec_secondary_address,
207 serial_poll_response : cec_serial_poll_response,
208 serial_poll_status : cec_serial_poll_status,
209 t1_delay : cec_t1_delay,
210 return_to_local : cec_return_to_local,
211 };
212 
cec_allocate_private(gpib_board_t * board)213 static int cec_allocate_private(gpib_board_t *board)
214 {
215 	struct cec_priv *priv;
216 
217 	board->private_data = kmalloc(sizeof(struct cec_priv), GFP_KERNEL);
218 	if (!board->private_data)
219 		return -1;
220 	priv = board->private_data;
221 	memset(priv, 0, sizeof(struct cec_priv));
222 	init_nec7210_private(&priv->nec7210_priv);
223 	return 0;
224 }
225 
cec_free_private(gpib_board_t * board)226 void cec_free_private(gpib_board_t *board)
227 {
228 	kfree(board->private_data);
229 	board->private_data = NULL;
230 }
231 
cec_generic_attach(gpib_board_t * board)232 int cec_generic_attach(gpib_board_t *board)
233 {
234 	struct cec_priv *cec_priv;
235 	struct nec7210_priv *nec_priv;
236 
237 	board->status = 0;
238 
239 	if (cec_allocate_private(board))
240 		return -ENOMEM;
241 	cec_priv = board->private_data;
242 	nec_priv = &cec_priv->nec7210_priv;
243 	nec_priv->read_byte = nec7210_ioport_read_byte;
244 	nec_priv->write_byte = nec7210_ioport_write_byte;
245 	nec_priv->offset = cec_reg_offset;
246 	nec_priv->type = NEC7210;	// guess
247 	return 0;
248 }
249 
cec_init(struct cec_priv * cec_priv,const gpib_board_t * board)250 void cec_init(struct cec_priv *cec_priv, const gpib_board_t *board)
251 {
252 	struct nec7210_priv *nec_priv = &cec_priv->nec7210_priv;
253 
254 	nec7210_board_reset(nec_priv, board);
255 
256 	/* set internal counter register for 8 MHz input clock */
257 	write_byte(nec_priv, ICR | 8, AUXMR);
258 
259 	nec7210_board_online(nec_priv, board);
260 }
261 
cec_pci_attach(gpib_board_t * board,const gpib_board_config_t * config)262 int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
263 {
264 	struct cec_priv *cec_priv;
265 	struct nec7210_priv *nec_priv;
266 	int isr_flags = 0;
267 	int retval;
268 
269 	retval = cec_generic_attach(board);
270 	if (retval)
271 		return retval;
272 
273 	cec_priv = board->private_data;
274 	nec_priv = &cec_priv->nec7210_priv;
275 
276 	// find board
277 	cec_priv->pci_device = NULL;
278 	while ((cec_priv->pci_device =
279 		gpib_pci_get_device(config, CEC_VENDOR_ID,
280 				    CEC_DEV_ID, cec_priv->pci_device)))	{
281 		// check for board with plx9050 controller
282 		if (cec_priv->pci_device->subsystem_device == CEC_SUBID)
283 			break;
284 	}
285 	if (!cec_priv->pci_device) {
286 		pr_err("gpib: no cec PCI board found\n");
287 		return -1;
288 	}
289 
290 	if (pci_enable_device(cec_priv->pci_device)) {
291 		pr_err("error enabling pci device\n");
292 		return -1;
293 	}
294 
295 	if (pci_request_regions(cec_priv->pci_device, "cec-gpib"))
296 		return -1;
297 
298 	cec_priv->plx_iobase = pci_resource_start(cec_priv->pci_device, 1);
299 	pr_info(" plx9050 base address 0x%lx\n", cec_priv->plx_iobase);
300 	nec_priv->iobase = pci_resource_start(cec_priv->pci_device, 3);
301 	pr_info(" nec7210 base address 0x%x\n", nec_priv->iobase);
302 
303 	isr_flags |= IRQF_SHARED;
304 	if (request_irq(cec_priv->pci_device->irq, cec_interrupt, isr_flags, "pci-gpib", board)) {
305 		pr_err("gpib: can't request IRQ %d\n", cec_priv->pci_device->irq);
306 		return -1;
307 	}
308 	cec_priv->irq = cec_priv->pci_device->irq;
309 	if (gpib_request_pseudo_irq(board, cec_interrupt)) {
310 		pr_err("cec: failed to allocate pseudo irq\n");
311 		return -1;
312 	}
313 	cec_init(cec_priv, board);
314 
315 	// enable interrupts on plx chip
316 	outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT,
317 	     cec_priv->plx_iobase + PLX9050_INTCSR_REG);
318 
319 	return 0;
320 }
321 
cec_pci_detach(gpib_board_t * board)322 void cec_pci_detach(gpib_board_t *board)
323 {
324 	struct cec_priv *cec_priv = board->private_data;
325 	struct nec7210_priv *nec_priv;
326 
327 	if (cec_priv) {
328 		nec_priv = &cec_priv->nec7210_priv;
329 		gpib_free_pseudo_irq(board);
330 		if (cec_priv->irq) {
331 			// disable plx9050 interrupts
332 			outl(0, cec_priv->plx_iobase + PLX9050_INTCSR_REG);
333 			free_irq(cec_priv->irq, board);
334 		}
335 		if (nec_priv->iobase) {
336 			nec7210_board_reset(nec_priv, board);
337 			pci_release_regions(cec_priv->pci_device);
338 		}
339 		if (cec_priv->pci_device)
340 			pci_dev_put(cec_priv->pci_device);
341 	}
342 	cec_free_private(board);
343 }
344 
cec_pci_probe(struct pci_dev * dev,const struct pci_device_id * id)345 static int cec_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
346 {
347 	return 0;
348 }
349 
350 static const struct pci_device_id cec_pci_table[] = {
351 	{CEC_VENDOR_ID, CEC_DEV_ID, PCI_ANY_ID, CEC_SUBID, 0, 0, 0 },
352 	{0}
353 };
354 MODULE_DEVICE_TABLE(pci, cec_pci_table);
355 
356 static struct pci_driver cec_pci_driver = {
357 	.name = "cec_gpib",
358 	.id_table = cec_pci_table,
359 	.probe = &cec_pci_probe
360 };
361 
cec_init_module(void)362 static int __init cec_init_module(void)
363 {
364 	int result;
365 
366 	result = pci_register_driver(&cec_pci_driver);
367 	if (result) {
368 		pr_err("cec_gpib: pci_driver_register failed!\n");
369 		return result;
370 	}
371 
372 	gpib_register_driver(&cec_pci_interface, THIS_MODULE);
373 
374 	return 0;
375 }
376 
cec_exit_module(void)377 static void cec_exit_module(void)
378 {
379 	gpib_unregister_driver(&cec_pci_interface);
380 
381 	pci_unregister_driver(&cec_pci_driver);
382 }
383 
384 module_init(cec_init_module);
385 module_exit(cec_exit_module);
386