Lines Matching +full:channel +full:-
1 // SPDX-License-Identifier: GPL-2.0-only
3 * driver for the GE IP-OCTAL boards
5 * Copyright (C) 2009-2012 CERN (www.cern.ch)
48 struct ipoctal_channel channel[NR_CHANNELS]; member
57 return container_of(chan, struct ipoctal, channel[index]); in chan_to_ipoctal()
60 static void ipoctal_reset_channel(struct ipoctal_channel *channel) in ipoctal_reset_channel() argument
62 iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); in ipoctal_reset_channel()
63 channel->rx_enable = 0; in ipoctal_reset_channel()
64 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); in ipoctal_reset_channel()
65 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); in ipoctal_reset_channel()
66 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); in ipoctal_reset_channel()
67 iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr); in ipoctal_reset_channel()
72 struct ipoctal_channel *channel; in ipoctal_port_activate() local
74 channel = dev_get_drvdata(tty->dev); in ipoctal_port_activate()
80 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); in ipoctal_port_activate()
81 channel->rx_enable = 1; in ipoctal_port_activate()
87 struct ipoctal_channel *channel = dev_get_drvdata(tty->dev); in ipoctal_install() local
88 struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); in ipoctal_install()
91 if (!ipack_get_carrier(ipoctal->dev)) in ipoctal_install()
92 return -EBUSY; in ipoctal_install()
98 tty->driver_data = channel; in ipoctal_install()
103 ipack_put_carrier(ipoctal->dev); in ipoctal_install()
110 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_open() local
112 return tty_port_open(&channel->tty_port, tty, file); in ipoctal_open()
117 stats->tx = 0; in ipoctal_reset_stats()
118 stats->rx = 0; in ipoctal_reset_stats()
119 stats->rcv_break = 0; in ipoctal_reset_stats()
120 stats->framing_err = 0; in ipoctal_reset_stats()
121 stats->overrun_err = 0; in ipoctal_reset_stats()
122 stats->parity_err = 0; in ipoctal_reset_stats()
125 static void ipoctal_free_channel(struct ipoctal_channel *channel) in ipoctal_free_channel() argument
127 ipoctal_reset_stats(&channel->stats); in ipoctal_free_channel()
128 channel->pointer_read = 0; in ipoctal_free_channel()
129 channel->pointer_write = 0; in ipoctal_free_channel()
130 channel->nb_bytes = 0; in ipoctal_free_channel()
135 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_close() local
137 tty_port_close(&channel->tty_port, tty, filp); in ipoctal_close()
138 ipoctal_free_channel(channel); in ipoctal_close()
144 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_get_icount() local
146 icount->cts = 0; in ipoctal_get_icount()
147 icount->dsr = 0; in ipoctal_get_icount()
148 icount->rng = 0; in ipoctal_get_icount()
149 icount->dcd = 0; in ipoctal_get_icount()
150 icount->rx = channel->stats.rx; in ipoctal_get_icount()
151 icount->tx = channel->stats.tx; in ipoctal_get_icount()
152 icount->frame = channel->stats.framing_err; in ipoctal_get_icount()
153 icount->parity = channel->stats.parity_err; in ipoctal_get_icount()
154 icount->brk = channel->stats.rcv_break; in ipoctal_get_icount()
158 static void ipoctal_irq_rx(struct ipoctal_channel *channel, u8 sr) in ipoctal_irq_rx() argument
160 struct tty_port *port = &channel->tty_port; in ipoctal_irq_rx()
164 value = ioread8(&channel->regs->r.rhr); in ipoctal_irq_rx()
168 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); in ipoctal_irq_rx()
171 channel->stats.overrun_err++; in ipoctal_irq_rx()
176 channel->stats.parity_err++; in ipoctal_irq_rx()
180 channel->stats.framing_err++; in ipoctal_irq_rx()
184 channel->stats.rcv_break++; in ipoctal_irq_rx()
191 * If there are more, the isr register for this channel in ipoctal_irq_rx()
194 isr = ioread8(&channel->block_regs->r.isr); in ipoctal_irq_rx()
195 sr = ioread8(&channel->regs->r.sr); in ipoctal_irq_rx()
196 } while (isr & channel->isr_rx_rdy_mask); in ipoctal_irq_rx()
201 static void ipoctal_irq_tx(struct ipoctal_channel *channel) in ipoctal_irq_tx() argument
203 unsigned int *pointer_write = &channel->pointer_write; in ipoctal_irq_tx()
206 if (channel->nb_bytes == 0) in ipoctal_irq_tx()
209 spin_lock(&channel->lock); in ipoctal_irq_tx()
210 value = channel->tty_port.xmit_buf[*pointer_write]; in ipoctal_irq_tx()
211 iowrite8(value, &channel->regs->w.thr); in ipoctal_irq_tx()
212 channel->stats.tx++; in ipoctal_irq_tx()
215 channel->nb_bytes--; in ipoctal_irq_tx()
216 spin_unlock(&channel->lock); in ipoctal_irq_tx()
219 static void ipoctal_irq_channel(struct ipoctal_channel *channel) in ipoctal_irq_channel() argument
225 isr = ioread8(&channel->block_regs->r.isr); in ipoctal_irq_channel()
226 sr = ioread8(&channel->regs->r.sr); in ipoctal_irq_channel()
229 iowrite8(CR_CMD_RESET_BREAK_CHANGE, &channel->regs->w.cr); in ipoctal_irq_channel()
231 if ((sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) { in ipoctal_irq_channel()
232 iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); in ipoctal_irq_channel()
233 /* In case of RS-485, change from TX to RX when finishing TX. in ipoctal_irq_channel()
234 * Half-duplex. */ in ipoctal_irq_channel()
235 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { in ipoctal_irq_channel()
236 iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); in ipoctal_irq_channel()
237 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); in ipoctal_irq_channel()
238 channel->rx_enable = 1; in ipoctal_irq_channel()
243 if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY)) in ipoctal_irq_channel()
244 ipoctal_irq_rx(channel, sr); in ipoctal_irq_channel()
247 if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY)) in ipoctal_irq_channel()
248 ipoctal_irq_tx(channel); in ipoctal_irq_channel()
257 readw(ipoctal->int_space + ACK_INT_REQ0); in ipoctal_irq_handler()
258 readw(ipoctal->int_space + ACK_INT_REQ1); in ipoctal_irq_handler()
262 ipoctal_irq_channel(&ipoctal->channel[i]); in ipoctal_irq_handler()
278 struct ipoctal_channel *channel; in ipoctal_inst_slot() local
284 ipoctal->board_id = ipoctal->dev->id_device; in ipoctal_inst_slot()
286 region = &ipoctal->dev->region[IPACK_IO_SPACE]; in ipoctal_inst_slot()
287 addr = devm_ioremap(&ipoctal->dev->dev, in ipoctal_inst_slot()
288 region->start, region->size); in ipoctal_inst_slot()
290 dev_err(&ipoctal->dev->dev, in ipoctal_inst_slot()
293 return -EADDRNOTAVAIL; in ipoctal_inst_slot()
301 region = &ipoctal->dev->region[IPACK_INT_SPACE]; in ipoctal_inst_slot()
302 ipoctal->int_space = in ipoctal_inst_slot()
303 devm_ioremap(&ipoctal->dev->dev, in ipoctal_inst_slot()
304 region->start, region->size); in ipoctal_inst_slot()
305 if (!ipoctal->int_space) { in ipoctal_inst_slot()
306 dev_err(&ipoctal->dev->dev, in ipoctal_inst_slot()
309 return -EADDRNOTAVAIL; in ipoctal_inst_slot()
312 region = &ipoctal->dev->region[IPACK_MEM8_SPACE]; in ipoctal_inst_slot()
313 ipoctal->mem8_space = in ipoctal_inst_slot()
314 devm_ioremap(&ipoctal->dev->dev, in ipoctal_inst_slot()
315 region->start, 0x8000); in ipoctal_inst_slot()
316 if (!ipoctal->mem8_space) { in ipoctal_inst_slot()
317 dev_err(&ipoctal->dev->dev, in ipoctal_inst_slot()
320 return -EADDRNOTAVAIL; in ipoctal_inst_slot()
326 struct ipoctal_channel *channel = &ipoctal->channel[i]; in ipoctal_inst_slot() local
327 channel->regs = chan_regs + i; in ipoctal_inst_slot()
328 channel->block_regs = block_regs + (i >> 1); in ipoctal_inst_slot()
329 channel->board_id = ipoctal->board_id; in ipoctal_inst_slot()
331 channel->isr_tx_rdy_mask = ISR_TxRDY_B; in ipoctal_inst_slot()
332 channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_B; in ipoctal_inst_slot()
334 channel->isr_tx_rdy_mask = ISR_TxRDY_A; in ipoctal_inst_slot()
335 channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A; in ipoctal_inst_slot()
338 ipoctal_reset_channel(channel); in ipoctal_inst_slot()
340 &channel->regs->w.mr); /* mr1 */ in ipoctal_inst_slot()
341 iowrite8(0, &channel->regs->w.mr); /* mr2 */ in ipoctal_inst_slot()
342 iowrite8(TX_CLK_9600 | RX_CLK_9600, &channel->regs->w.csr); in ipoctal_inst_slot()
355 iowrite8(1, ipoctal->mem8_space + 1); in ipoctal_inst_slot()
359 /* Each IP-OCTAL channel is a TTY port */ in ipoctal_inst_slot()
366 drv->owner = THIS_MODULE; in ipoctal_inst_slot()
367 drv->driver_name = KBUILD_MODNAME; in ipoctal_inst_slot()
368 drv->name = kasprintf(GFP_KERNEL, KBUILD_MODNAME ".%d.%d.", bus_nr, slot); in ipoctal_inst_slot()
369 if (!drv->name) { in ipoctal_inst_slot()
370 res = -ENOMEM; in ipoctal_inst_slot()
373 drv->major = 0; in ipoctal_inst_slot()
375 drv->minor_start = 0; in ipoctal_inst_slot()
376 drv->type = TTY_DRIVER_TYPE_SERIAL; in ipoctal_inst_slot()
377 drv->subtype = SERIAL_TYPE_NORMAL; in ipoctal_inst_slot()
378 drv->init_termios = tty_std_termios; in ipoctal_inst_slot()
379 drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; in ipoctal_inst_slot()
380 drv->init_termios.c_ispeed = 9600; in ipoctal_inst_slot()
381 drv->init_termios.c_ospeed = 9600; in ipoctal_inst_slot()
386 dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n"); in ipoctal_inst_slot()
391 ipoctal->tty_drv = drv; in ipoctal_inst_slot()
396 channel = &ipoctal->channel[i]; in ipoctal_inst_slot()
397 tty_port_init(&channel->tty_port); in ipoctal_inst_slot()
398 res = tty_port_alloc_xmit_buf(&channel->tty_port); in ipoctal_inst_slot()
401 channel->tty_port.ops = &ipoctal_tty_port_ops; in ipoctal_inst_slot()
403 ipoctal_reset_stats(&channel->stats); in ipoctal_inst_slot()
404 channel->nb_bytes = 0; in ipoctal_inst_slot()
405 spin_lock_init(&channel->lock); in ipoctal_inst_slot()
406 channel->pointer_read = 0; in ipoctal_inst_slot()
407 channel->pointer_write = 0; in ipoctal_inst_slot()
408 tty_dev = tty_port_register_device_attr(&channel->tty_port, drv, in ipoctal_inst_slot()
409 i, NULL, channel, NULL); in ipoctal_inst_slot()
411 dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n"); in ipoctal_inst_slot()
412 tty_port_free_xmit_buf(&channel->tty_port); in ipoctal_inst_slot()
413 tty_port_destroy(&channel->tty_port); in ipoctal_inst_slot()
416 channel->tty_registered = true; in ipoctal_inst_slot()
420 * IP-OCTAL has different addresses to copy its IRQ vector. in ipoctal_inst_slot()
424 ipoctal->dev->bus->ops->request_irq(ipoctal->dev, in ipoctal_inst_slot()
430 kfree(drv->name); in ipoctal_inst_slot()
437 static inline size_t ipoctal_copy_write_buffer(struct ipoctal_channel *channel, in ipoctal_copy_write_buffer() argument
442 unsigned int *pointer_read = &channel->pointer_read; in ipoctal_copy_write_buffer()
446 if (i <= (PAGE_SIZE - channel->nb_bytes)) { in ipoctal_copy_write_buffer()
447 spin_lock_irqsave(&channel->lock, flags); in ipoctal_copy_write_buffer()
448 channel->tty_port.xmit_buf[*pointer_read] = buf[i]; in ipoctal_copy_write_buffer()
450 channel->nb_bytes++; in ipoctal_copy_write_buffer()
451 spin_unlock_irqrestore(&channel->lock, flags); in ipoctal_copy_write_buffer()
462 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_write_tty() local
465 char_copied = ipoctal_copy_write_buffer(channel, buf, count); in ipoctal_write_tty()
467 /* As the IP-OCTAL 485 only supports half duplex, do it manually */ in ipoctal_write_tty()
468 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { in ipoctal_write_tty()
469 iowrite8(CR_DISABLE_RX, &channel->regs->w.cr); in ipoctal_write_tty()
470 channel->rx_enable = 0; in ipoctal_write_tty()
471 iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr); in ipoctal_write_tty()
478 iowrite8(CR_ENABLE_TX, &channel->regs->w.cr); in ipoctal_write_tty()
484 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_write_room() local
486 return PAGE_SIZE - channel->nb_bytes; in ipoctal_write_room()
491 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_chars_in_buffer() local
493 return channel->nb_bytes; in ipoctal_chars_in_buffer()
503 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_set_termios() local
506 cflag = tty->termios.c_cflag; in ipoctal_set_termios()
509 ipoctal_reset_channel(channel); in ipoctal_set_termios()
523 tty->termios.c_cflag = (cflag & ~CSIZE) | CS8; in ipoctal_set_termios()
537 tty->termios.c_cflag &= ~CMSPAR; in ipoctal_set_termios()
546 switch (channel->board_id) { in ipoctal_set_termios()
569 tty_termios_encode_baud_rate(&tty->termios, baud, baud); in ipoctal_set_termios()
613 tty_termios_encode_baud_rate(&tty->termios, 38400, 38400); in ipoctal_set_termios()
621 iowrite8(mr1, &channel->regs->w.mr); in ipoctal_set_termios()
622 iowrite8(mr2, &channel->regs->w.mr); in ipoctal_set_termios()
623 iowrite8(csr, &channel->regs->w.csr); in ipoctal_set_termios()
626 if (channel->rx_enable) in ipoctal_set_termios()
627 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); in ipoctal_set_termios()
633 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_hangup() local
635 if (channel == NULL) in ipoctal_hangup()
638 spin_lock_irqsave(&channel->lock, flags); in ipoctal_hangup()
639 channel->nb_bytes = 0; in ipoctal_hangup()
640 channel->pointer_read = 0; in ipoctal_hangup()
641 channel->pointer_write = 0; in ipoctal_hangup()
642 spin_unlock_irqrestore(&channel->lock, flags); in ipoctal_hangup()
644 tty_port_hangup(&channel->tty_port); in ipoctal_hangup()
646 ipoctal_reset_channel(channel); in ipoctal_hangup()
647 tty_port_set_initialized(&channel->tty_port, false); in ipoctal_hangup()
648 wake_up_interruptible(&channel->tty_port.open_wait); in ipoctal_hangup()
653 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_shutdown() local
655 if (channel == NULL) in ipoctal_shutdown()
658 ipoctal_reset_channel(channel); in ipoctal_shutdown()
659 tty_port_set_initialized(&channel->tty_port, false); in ipoctal_shutdown()
664 struct ipoctal_channel *channel = tty->driver_data; in ipoctal_cleanup() local
665 struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index); in ipoctal_cleanup()
668 ipack_put_carrier(ipoctal->dev); in ipoctal_cleanup()
693 return -ENOMEM; in ipoctal_probe()
695 ipoctal->dev = dev; in ipoctal_probe()
696 res = ipoctal_inst_slot(ipoctal, dev->bus->bus_nr, dev->slot); in ipoctal_probe()
700 dev_set_drvdata(&dev->dev, ipoctal); in ipoctal_probe()
712 ipoctal->dev->bus->ops->free_irq(ipoctal->dev); in __ipoctal_remove()
715 struct ipoctal_channel *channel = &ipoctal->channel[i]; in __ipoctal_remove() local
717 if (!channel->tty_registered) in __ipoctal_remove()
720 tty_unregister_device(ipoctal->tty_drv, i); in __ipoctal_remove()
721 tty_port_free_xmit_buf(&channel->tty_port); in __ipoctal_remove()
722 tty_port_destroy(&channel->tty_port); in __ipoctal_remove()
725 tty_unregister_driver(ipoctal->tty_drv); in __ipoctal_remove()
726 kfree(ipoctal->tty_drv->name); in __ipoctal_remove()
727 tty_driver_kref_put(ipoctal->tty_drv); in __ipoctal_remove()
733 __ipoctal_remove(dev_get_drvdata(&idev->dev)); in ipoctal_remove()
768 MODULE_DESCRIPTION("IP-Octal 232, 422 and 485 device driver");