aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ipack/devices/ipoctal.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ipack/devices/ipoctal.c')
-rw-r--r--drivers/ipack/devices/ipoctal.c113
1 files changed, 49 insertions, 64 deletions
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
index ab20a0851dd2..141094e7c06e 100644
--- a/drivers/ipack/devices/ipoctal.c
+++ b/drivers/ipack/devices/ipoctal.c
@@ -20,7 +20,6 @@
20#include <linux/serial.h> 20#include <linux/serial.h>
21#include <linux/tty_flip.h> 21#include <linux/tty_flip.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/atomic.h>
24#include <linux/io.h> 23#include <linux/io.h>
25#include <linux/ipack.h> 24#include <linux/ipack.h>
26#include "ipoctal.h" 25#include "ipoctal.h"
@@ -38,21 +37,19 @@ struct ipoctal_channel {
38 spinlock_t lock; 37 spinlock_t lock;
39 unsigned int pointer_read; 38 unsigned int pointer_read;
40 unsigned int pointer_write; 39 unsigned int pointer_write;
41 atomic_t open;
42 struct tty_port tty_port; 40 struct tty_port tty_port;
43 union scc2698_channel __iomem *regs; 41 union scc2698_channel __iomem *regs;
44 union scc2698_block __iomem *block_regs; 42 union scc2698_block __iomem *block_regs;
45 unsigned int board_id; 43 unsigned int board_id;
46 unsigned char *board_write;
47 u8 isr_rx_rdy_mask; 44 u8 isr_rx_rdy_mask;
48 u8 isr_tx_rdy_mask; 45 u8 isr_tx_rdy_mask;
46 unsigned int rx_enable;
49}; 47};
50 48
51struct ipoctal { 49struct ipoctal {
52 struct ipack_device *dev; 50 struct ipack_device *dev;
53 unsigned int board_id; 51 unsigned int board_id;
54 struct ipoctal_channel channel[NR_CHANNELS]; 52 struct ipoctal_channel channel[NR_CHANNELS];
55 unsigned char write;
56 struct tty_driver *tty_drv; 53 struct tty_driver *tty_drv;
57 u8 __iomem *mem8_space; 54 u8 __iomem *mem8_space;
58 u8 __iomem *int_space; 55 u8 __iomem *int_space;
@@ -64,28 +61,23 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty)
64 61
65 channel = dev_get_drvdata(tty->dev); 62 channel = dev_get_drvdata(tty->dev);
66 63
64 /*
65 * Enable RX. TX will be enabled when
66 * there is something to send
67 */
67 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); 68 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
69 channel->rx_enable = 1;
68 return 0; 70 return 0;
69} 71}
70 72
71static int ipoctal_open(struct tty_struct *tty, struct file *file) 73static int ipoctal_open(struct tty_struct *tty, struct file *file)
72{ 74{
73 int res;
74 struct ipoctal_channel *channel; 75 struct ipoctal_channel *channel;
75 76
76 channel = dev_get_drvdata(tty->dev); 77 channel = dev_get_drvdata(tty->dev);
77
78 if (atomic_read(&channel->open))
79 return -EBUSY;
80
81 tty->driver_data = channel; 78 tty->driver_data = channel;
82 79
83 res = tty_port_open(&channel->tty_port, tty, file); 80 return tty_port_open(&channel->tty_port, tty, file);
84 if (res)
85 return res;
86
87 atomic_inc(&channel->open);
88 return 0;
89} 81}
90 82
91static void ipoctal_reset_stats(struct ipoctal_stats *stats) 83static void ipoctal_reset_stats(struct ipoctal_stats *stats)
@@ -111,9 +103,7 @@ static void ipoctal_close(struct tty_struct *tty, struct file *filp)
111 struct ipoctal_channel *channel = tty->driver_data; 103 struct ipoctal_channel *channel = tty->driver_data;
112 104
113 tty_port_close(&channel->tty_port, tty, filp); 105 tty_port_close(&channel->tty_port, tty, filp);
114 106 ipoctal_free_channel(channel);
115 if (atomic_dec_and_test(&channel->open))
116 ipoctal_free_channel(channel);
117} 107}
118 108
119static int ipoctal_get_icount(struct tty_struct *tty, 109static int ipoctal_get_icount(struct tty_struct *tty,
@@ -137,11 +127,12 @@ static void ipoctal_irq_rx(struct ipoctal_channel *channel, u8 sr)
137{ 127{
138 struct tty_port *port = &channel->tty_port; 128 struct tty_port *port = &channel->tty_port;
139 unsigned char value; 129 unsigned char value;
140 unsigned char flag = TTY_NORMAL; 130 unsigned char flag;
141 u8 isr; 131 u8 isr;
142 132
143 do { 133 do {
144 value = ioread8(&channel->regs->r.rhr); 134 value = ioread8(&channel->regs->r.rhr);
135 flag = TTY_NORMAL;
145 /* Error: count statistics */ 136 /* Error: count statistics */
146 if (sr & SR_ERROR) { 137 if (sr & SR_ERROR) {
147 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); 138 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
@@ -183,10 +174,8 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel)
183 unsigned char value; 174 unsigned char value;
184 unsigned int *pointer_write = &channel->pointer_write; 175 unsigned int *pointer_write = &channel->pointer_write;
185 176
186 if (channel->nb_bytes <= 0) { 177 if (channel->nb_bytes == 0)
187 channel->nb_bytes = 0;
188 return; 178 return;
189 }
190 179
191 value = channel->tty_port.xmit_buf[*pointer_write]; 180 value = channel->tty_port.xmit_buf[*pointer_write];
192 iowrite8(value, &channel->regs->w.thr); 181 iowrite8(value, &channel->regs->w.thr);
@@ -194,39 +183,27 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel)
194 (*pointer_write)++; 183 (*pointer_write)++;
195 *pointer_write = *pointer_write % PAGE_SIZE; 184 *pointer_write = *pointer_write % PAGE_SIZE;
196 channel->nb_bytes--; 185 channel->nb_bytes--;
197
198 if ((channel->nb_bytes == 0) &&
199 (waitqueue_active(&channel->queue))) {
200
201 if (channel->board_id != IPACK1_DEVICE_ID_SBS_OCTAL_485) {
202 *channel->board_write = 1;
203 wake_up_interruptible(&channel->queue);
204 }
205 }
206} 186}
207 187
208static void ipoctal_irq_channel(struct ipoctal_channel *channel) 188static void ipoctal_irq_channel(struct ipoctal_channel *channel)
209{ 189{
210 u8 isr, sr; 190 u8 isr, sr;
211 191
212 /* If there is no client, skip the check */ 192 spin_lock(&channel->lock);
213 if (!atomic_read(&channel->open))
214 return;
215
216 /* The HW is organized in pair of channels. See which register we need 193 /* The HW is organized in pair of channels. See which register we need
217 * to read from */ 194 * to read from */
218 isr = ioread8(&channel->block_regs->r.isr); 195 isr = ioread8(&channel->block_regs->r.isr);
219 sr = ioread8(&channel->regs->r.sr); 196 sr = ioread8(&channel->regs->r.sr);
220 197
221 /* In case of RS-485, change from TX to RX when finishing TX. 198 if ((sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
222 * Half-duplex. */
223 if ((channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) &&
224 (sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
225 iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); 199 iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
226 iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); 200 /* In case of RS-485, change from TX to RX when finishing TX.
227 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); 201 * Half-duplex. */
228 *channel->board_write = 1; 202 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) {
229 wake_up_interruptible(&channel->queue); 203 iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr);
204 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
205 channel->rx_enable = 1;
206 }
230 } 207 }
231 208
232 /* RX data */ 209 /* RX data */
@@ -237,7 +214,7 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel)
237 if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY)) 214 if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
238 ipoctal_irq_tx(channel); 215 ipoctal_irq_tx(channel);
239 216
240 tty_flip_buffer_push(&channel->tty_port); 217 spin_unlock(&channel->lock);
241} 218}
242 219
243static irqreturn_t ipoctal_irq_handler(void *arg) 220static irqreturn_t ipoctal_irq_handler(void *arg)
@@ -245,14 +222,14 @@ static irqreturn_t ipoctal_irq_handler(void *arg)
245 unsigned int i; 222 unsigned int i;
246 struct ipoctal *ipoctal = (struct ipoctal *) arg; 223 struct ipoctal *ipoctal = (struct ipoctal *) arg;
247 224
248 /* Check all channels */
249 for (i = 0; i < NR_CHANNELS; i++)
250 ipoctal_irq_channel(&ipoctal->channel[i]);
251
252 /* Clear the IPack device interrupt */ 225 /* Clear the IPack device interrupt */
253 readw(ipoctal->int_space + ACK_INT_REQ0); 226 readw(ipoctal->int_space + ACK_INT_REQ0);
254 readw(ipoctal->int_space + ACK_INT_REQ1); 227 readw(ipoctal->int_space + ACK_INT_REQ1);
255 228
229 /* Check all channels */
230 for (i = 0; i < NR_CHANNELS; i++)
231 ipoctal_irq_channel(&ipoctal->channel[i]);
232
256 return IRQ_HANDLED; 233 return IRQ_HANDLED;
257} 234}
258 235
@@ -306,7 +283,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
306 ipoctal->mem8_space = 283 ipoctal->mem8_space =
307 devm_ioremap_nocache(&ipoctal->dev->dev, 284 devm_ioremap_nocache(&ipoctal->dev->dev,
308 region->start, 0x8000); 285 region->start, 0x8000);
309 if (!addr) { 286 if (!ipoctal->mem8_space) {
310 dev_err(&ipoctal->dev->dev, 287 dev_err(&ipoctal->dev->dev,
311 "Unable to map slot [%d:%d] MEM8 space!\n", 288 "Unable to map slot [%d:%d] MEM8 space!\n",
312 bus_nr, slot); 289 bus_nr, slot);
@@ -319,7 +296,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
319 struct ipoctal_channel *channel = &ipoctal->channel[i]; 296 struct ipoctal_channel *channel = &ipoctal->channel[i];
320 channel->regs = chan_regs + i; 297 channel->regs = chan_regs + i;
321 channel->block_regs = block_regs + (i >> 1); 298 channel->block_regs = block_regs + (i >> 1);
322 channel->board_write = &ipoctal->write;
323 channel->board_id = ipoctal->board_id; 299 channel->board_id = ipoctal->board_id;
324 if (i & 1) { 300 if (i & 1) {
325 channel->isr_tx_rdy_mask = ISR_TxRDY_B; 301 channel->isr_tx_rdy_mask = ISR_TxRDY_B;
@@ -330,6 +306,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
330 } 306 }
331 307
332 iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); 308 iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
309 channel->rx_enable = 0;
333 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); 310 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
334 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); 311 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
335 iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY, 312 iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY,
@@ -402,8 +379,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
402 379
403 ipoctal_reset_stats(&channel->stats); 380 ipoctal_reset_stats(&channel->stats);
404 channel->nb_bytes = 0; 381 channel->nb_bytes = 0;
405 init_waitqueue_head(&channel->queue);
406
407 spin_lock_init(&channel->lock); 382 spin_lock_init(&channel->lock);
408 channel->pointer_read = 0; 383 channel->pointer_read = 0;
409 channel->pointer_write = 0; 384 channel->pointer_write = 0;
@@ -414,12 +389,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
414 continue; 389 continue;
415 } 390 }
416 dev_set_drvdata(tty_dev, channel); 391 dev_set_drvdata(tty_dev, channel);
417
418 /*
419 * Enable again the RX. TX will be enabled when
420 * there is something to send
421 */
422 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
423 } 392 }
424 393
425 return 0; 394 return 0;
@@ -459,6 +428,7 @@ static int ipoctal_write_tty(struct tty_struct *tty,
459 /* As the IP-OCTAL 485 only supports half duplex, do it manually */ 428 /* As the IP-OCTAL 485 only supports half duplex, do it manually */
460 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { 429 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) {
461 iowrite8(CR_DISABLE_RX, &channel->regs->w.cr); 430 iowrite8(CR_DISABLE_RX, &channel->regs->w.cr);
431 channel->rx_enable = 0;
462 iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr); 432 iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr);
463 } 433 }
464 434
@@ -467,10 +437,6 @@ static int ipoctal_write_tty(struct tty_struct *tty,
467 * operations 437 * operations
468 */ 438 */
469 iowrite8(CR_ENABLE_TX, &channel->regs->w.cr); 439 iowrite8(CR_ENABLE_TX, &channel->regs->w.cr);
470 wait_event_interruptible(channel->queue, *channel->board_write);
471 iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
472
473 *channel->board_write = 0;
474 return char_copied; 440 return char_copied;
475} 441}
476 442
@@ -622,8 +588,9 @@ static void ipoctal_set_termios(struct tty_struct *tty,
622 iowrite8(mr2, &channel->regs->w.mr); 588 iowrite8(mr2, &channel->regs->w.mr);
623 iowrite8(csr, &channel->regs->w.csr); 589 iowrite8(csr, &channel->regs->w.csr);
624 590
625 /* Enable again the RX */ 591 /* Enable again the RX, if it was before */
626 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); 592 if (channel->rx_enable)
593 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
627} 594}
628 595
629static void ipoctal_hangup(struct tty_struct *tty) 596static void ipoctal_hangup(struct tty_struct *tty)
@@ -643,6 +610,7 @@ static void ipoctal_hangup(struct tty_struct *tty)
643 tty_port_hangup(&channel->tty_port); 610 tty_port_hangup(&channel->tty_port);
644 611
645 iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); 612 iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
613 channel->rx_enable = 0;
646 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); 614 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
647 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); 615 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
648 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); 616 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
@@ -652,6 +620,22 @@ static void ipoctal_hangup(struct tty_struct *tty)
652 wake_up_interruptible(&channel->tty_port.open_wait); 620 wake_up_interruptible(&channel->tty_port.open_wait);
653} 621}
654 622
623static void ipoctal_shutdown(struct tty_struct *tty)
624{
625 struct ipoctal_channel *channel = tty->driver_data;
626
627 if (channel == NULL)
628 return;
629
630 iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr);
631 channel->rx_enable = 0;
632 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
633 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
634 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
635 iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr);
636 clear_bit(ASYNCB_INITIALIZED, &channel->tty_port.flags);
637}
638
655static const struct tty_operations ipoctal_fops = { 639static const struct tty_operations ipoctal_fops = {
656 .ioctl = NULL, 640 .ioctl = NULL,
657 .open = ipoctal_open, 641 .open = ipoctal_open,
@@ -662,6 +646,7 @@ static const struct tty_operations ipoctal_fops = {
662 .chars_in_buffer = ipoctal_chars_in_buffer, 646 .chars_in_buffer = ipoctal_chars_in_buffer,
663 .get_icount = ipoctal_get_icount, 647 .get_icount = ipoctal_get_icount,
664 .hangup = ipoctal_hangup, 648 .hangup = ipoctal_hangup,
649 .shutdown = ipoctal_shutdown,
665}; 650};
666 651
667static int ipoctal_probe(struct ipack_device *dev) 652static int ipoctal_probe(struct ipack_device *dev)