File Index
Files and directories
Sign in
FILE

hp82335.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpib/hp_82335/hp82335.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3/***************************************************************************
  4 * copyright            : (C) 2002 by Frank Mori Hess                      *
  5 ***************************************************************************/
  6
  7/*
  8 * should enable ATN interrupts (and update board->status on occurrence),
  9 * implement recovery from bus errors (if necessary)
 10 */
 11
 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 13#define dev_fmt pr_fmt
 14#define DRV_NAME KBUILD_MODNAME
 15
 16#include "hp82335.h"
 17#include <linux/io.h>
 18#include <linux/ioport.h>
 19#include <linux/sched.h>
 20#include <linux/module.h>
 21#include <linux/slab.h>
 22#include <linux/string.h>
 23#include <linux/init.h>
 24
 25MODULE_LICENSE("GPL");
 26MODULE_DESCRIPTION("GPIB driver for HP 82335 interface cards");
 27
 28static int hp82335_attach(struct gpib_board *board, const struct gpib_board_config *config);
 29static void hp82335_detach(struct gpib_board *board);
 30static irqreturn_t hp82335_interrupt(int irq, void *arg);
 31
 32// wrappers for interface functions
 33static int hp82335_read(struct gpib_board *board, u8 *buffer, size_t length,
 34			int *end, size_t *bytes_read)
 35{
 36	struct hp82335_priv *priv = board->private_data;
 37
 38	return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read);
 39}
 40
 41static int hp82335_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi,
 42			 size_t *bytes_written)
 43{
 44	struct hp82335_priv *priv = board->private_data;
 45
 46	return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written);
 47}
 48
 49static int hp82335_command(struct gpib_board *board, u8 *buffer, size_t length,
 50			   size_t *bytes_written)
 51{
 52	struct hp82335_priv *priv = board->private_data;
 53
 54	return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written);
 55}
 56
 57static int hp82335_take_control(struct gpib_board *board, int synchronous)
 58{
 59	struct hp82335_priv *priv = board->private_data;
 60
 61	return tms9914_take_control(board, &priv->tms9914_priv, synchronous);
 62}
 63
 64static int hp82335_go_to_standby(struct gpib_board *board)
 65{
 66	struct hp82335_priv *priv = board->private_data;
 67
 68	return tms9914_go_to_standby(board, &priv->tms9914_priv);
 69}
 70
 71static int hp82335_request_system_control(struct gpib_board *board, int request_control)
 72{
 73	struct hp82335_priv *priv = board->private_data;
 74
 75	return tms9914_request_system_control(board, &priv->tms9914_priv, request_control);
 76}
 77
 78static void hp82335_interface_clear(struct gpib_board *board, int assert)
 79{
 80	struct hp82335_priv *priv = board->private_data;
 81
 82	tms9914_interface_clear(board, &priv->tms9914_priv, assert);
 83}
 84
 85static void hp82335_remote_enable(struct gpib_board *board, int enable)
 86{
 87	struct hp82335_priv *priv = board->private_data;
 88
 89	tms9914_remote_enable(board, &priv->tms9914_priv, enable);
 90}
 91
 92static int hp82335_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits)
 93{
 94	struct hp82335_priv *priv = board->private_data;
 95
 96	return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits);
 97}
 98
 99static void hp82335_disable_eos(struct gpib_board *board)
100{
101	struct hp82335_priv *priv = board->private_data;
102
103	tms9914_disable_eos(board, &priv->tms9914_priv);
104}
105
106static unsigned int hp82335_update_status(struct gpib_board *board, unsigned int clear_mask)
107{
108	struct hp82335_priv *priv = board->private_data;
109
110	return tms9914_update_status(board, &priv->tms9914_priv, clear_mask);
111}
112
113static int hp82335_primary_address(struct gpib_board *board, unsigned int address)
114{
115	struct hp82335_priv *priv = board->private_data;
116
117	return tms9914_primary_address(board, &priv->tms9914_priv, address);
118}
119
120static int hp82335_secondary_address(struct gpib_board *board, unsigned int address, int enable)
121{
122	struct hp82335_priv *priv = board->private_data;
123
124	return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable);
125}
126
127static int hp82335_parallel_poll(struct gpib_board *board, u8 *result)
128{
129	struct hp82335_priv *priv = board->private_data;
130
131	return tms9914_parallel_poll(board, &priv->tms9914_priv, result);
132}
133
134static void hp82335_parallel_poll_configure(struct gpib_board *board, u8 config)
135{
136	struct hp82335_priv *priv = board->private_data;
137
138	tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config);
139}
140
141static void hp82335_parallel_poll_response(struct gpib_board *board, int ist)
142{
143	struct hp82335_priv *priv = board->private_data;
144
145	tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist);
146}
147
148static void hp82335_serial_poll_response(struct gpib_board *board, u8 status)
149{
150	struct hp82335_priv *priv = board->private_data;
151
152	tms9914_serial_poll_response(board, &priv->tms9914_priv, status);
153}
154
155static u8 hp82335_serial_poll_status(struct gpib_board *board)
156{
157	struct hp82335_priv *priv = board->private_data;
158
159	return tms9914_serial_poll_status(board, &priv->tms9914_priv);
160}
161
162static int hp82335_line_status(const struct gpib_board *board)
163{
164	struct hp82335_priv *priv = board->private_data;
165
166	return tms9914_line_status(board, &priv->tms9914_priv);
167}
168
169static int hp82335_t1_delay(struct gpib_board *board, unsigned int nano_sec)
170{
171	struct hp82335_priv *priv = board->private_data;
172
173	return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec);
174}
175
176static void hp82335_return_to_local(struct gpib_board *board)
177{
178	struct hp82335_priv *priv = board->private_data;
179
180	tms9914_return_to_local(board, &priv->tms9914_priv);
181}
182
183static struct gpib_interface hp82335_interface = {
184	.name = "hp82335",
185	.attach = hp82335_attach,
186	.detach = hp82335_detach,
187	.read = hp82335_read,
188	.write = hp82335_write,
189	.command = hp82335_command,
190	.request_system_control = hp82335_request_system_control,
191	.take_control = hp82335_take_control,
192	.go_to_standby = hp82335_go_to_standby,
193	.interface_clear = hp82335_interface_clear,
194	.remote_enable = hp82335_remote_enable,
195	.enable_eos = hp82335_enable_eos,
196	.disable_eos = hp82335_disable_eos,
197	.parallel_poll = hp82335_parallel_poll,
198	.parallel_poll_configure = hp82335_parallel_poll_configure,
199	.parallel_poll_response = hp82335_parallel_poll_response,
200	.local_parallel_poll_mode = NULL, // XXX
201	.line_status = hp82335_line_status,
202	.update_status = hp82335_update_status,
203	.primary_address = hp82335_primary_address,
204	.secondary_address = hp82335_secondary_address,
205	.serial_poll_response = hp82335_serial_poll_response,
206	.serial_poll_status = hp82335_serial_poll_status,
207	.t1_delay = hp82335_t1_delay,
208	.return_to_local = hp82335_return_to_local,
209};
210
211static int hp82335_allocate_private(struct gpib_board *board)
212{
213	board->private_data = kzalloc(sizeof(struct hp82335_priv), GFP_KERNEL);
214	if (!board->private_data)
215		return -1;
216	return 0;
217}
218
219static void hp82335_free_private(struct gpib_board *board)
220{
221	kfree(board->private_data);
222	board->private_data = NULL;
223}
224
225static inline unsigned int tms9914_to_hp82335_offset(unsigned int register_num)
226{
227	return 0x1ff8 + register_num;
228}
229
230static u8 hp82335_read_byte(struct tms9914_priv *priv, unsigned int register_num)
231{
232	return tms9914_iomem_read_byte(priv, tms9914_to_hp82335_offset(register_num));
233}
234
235static void hp82335_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num)
236{
237	tms9914_iomem_write_byte(priv, data, tms9914_to_hp82335_offset(register_num));
238}
239
240static void hp82335_clear_interrupt(struct hp82335_priv *hp_priv)
241{
242	struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
243
244	writeb(0, tms_priv->mmiobase + HPREG_INTR_CLEAR);
245}
246
247static int hp82335_attach(struct gpib_board *board, const struct gpib_board_config *config)
248{
249	struct hp82335_priv *hp_priv;
250	struct tms9914_priv *tms_priv;
251	int retval;
252	const unsigned long upper_iomem_base = config->ibbase + hp82335_rom_size;
253
254	board->status = 0;
255
256	if (hp82335_allocate_private(board))
257		return -ENOMEM;
258	hp_priv = board->private_data;
259	tms_priv = &hp_priv->tms9914_priv;
260	tms_priv->read_byte = hp82335_read_byte;
261	tms_priv->write_byte = hp82335_write_byte;
262	tms_priv->offset = 1;
263
264	switch (config->ibbase) {
265	case 0xc4000:
266	case 0xc8000:
267	case 0xcc000:
268	case 0xd0000:
269	case 0xd4000:
270	case 0xd8000:
271	case 0xdc000:
272	case 0xe0000:
273	case 0xe4000:
274	case 0xe8000:
275	case 0xec000:
276	case 0xf0000:
277	case 0xf4000:
278	case 0xf8000:
279	case 0xfc000:
280		break;
281	default:
282		dev_err(board->gpib_dev, "invalid base io address 0x%x\n", config->ibbase);
283		return -EINVAL;
284	}
285	if (!request_mem_region(upper_iomem_base, hp82335_upper_iomem_size, "hp82335")) {
286		dev_err(board->gpib_dev, "failed to allocate io memory region 0x%lx-0x%lx\n",
287			upper_iomem_base, upper_iomem_base + hp82335_upper_iomem_size - 1);
288		return -EBUSY;
289	}
290	hp_priv->raw_iobase = upper_iomem_base;
291	tms_priv->mmiobase = ioremap(upper_iomem_base, hp82335_upper_iomem_size);
292
293	retval = request_irq(config->ibirq, hp82335_interrupt, 0, DRV_NAME, board);
294	if (retval) {
295		dev_err(board->gpib_dev, "can't request IRQ %d\n", config->ibirq);
296		return retval;
297	}
298	hp_priv->irq = config->ibirq;
299
300	tms9914_board_reset(tms_priv);
301
302	hp82335_clear_interrupt(hp_priv);
303
304	writeb(INTR_ENABLE, tms_priv->mmiobase + HPREG_CCR);
305
306	tms9914_online(board, tms_priv);
307
308	return 0;
309}
310
311static void hp82335_detach(struct gpib_board *board)
312{
313	struct hp82335_priv *hp_priv = board->private_data;
314	struct tms9914_priv *tms_priv;
315
316	if (hp_priv) {
317		tms_priv = &hp_priv->tms9914_priv;
318		if (hp_priv->irq)
319			free_irq(hp_priv->irq, board);
320		if (tms_priv->mmiobase) {
321			writeb(0, tms_priv->mmiobase + HPREG_CCR);
322			tms9914_board_reset(tms_priv);
323			iounmap(tms_priv->mmiobase);
324		}
325		if (hp_priv->raw_iobase)
326			release_mem_region(hp_priv->raw_iobase, hp82335_upper_iomem_size);
327	}
328	hp82335_free_private(board);
329}
330
331static int __init hp82335_init_module(void)
332{
333	int result = gpib_register_driver(&hp82335_interface, THIS_MODULE);
334
335	if (result) {
336		pr_err("gpib_register_driver failed: error = %d\n", result);
337		return result;
338	}
339
340	return 0;
341}
342
343static void __exit hp82335_exit_module(void)
344{
345	gpib_unregister_driver(&hp82335_interface);
346}
347
348module_init(hp82335_init_module);
349module_exit(hp82335_exit_module);
350
351/*
352 * GPIB interrupt service routines
353 */
354
355static irqreturn_t hp82335_interrupt(int irq, void *arg)
356{
357	int status1, status2;
358	struct gpib_board *board = arg;
359	struct hp82335_priv *priv = board->private_data;
360	unsigned long flags;
361	irqreturn_t retval;
362
363	spin_lock_irqsave(&board->spinlock, flags);
364	status1 = read_byte(&priv->tms9914_priv, ISR0);
365	status2 = read_byte(&priv->tms9914_priv, ISR1);
366	hp82335_clear_interrupt(priv);
367	retval = tms9914_interrupt_have_status(board, &priv->tms9914_priv, status1, status2);
368	spin_unlock_irqrestore(&board->spinlock, flags);
369	return retval;
370}
371
~/ Read-only file preview.