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