aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ipack
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ipack')
-rw-r--r--drivers/ipack/devices/Kconfig2
-rw-r--r--drivers/ipack/devices/ipoctal.c130
2 files changed, 56 insertions, 76 deletions
diff --git a/drivers/ipack/devices/Kconfig b/drivers/ipack/devices/Kconfig
index 0b82fdc198c0..907a8cb48f2a 100644
--- a/drivers/ipack/devices/Kconfig
+++ b/drivers/ipack/devices/Kconfig
@@ -1,6 +1,6 @@
1config SERIAL_IPOCTAL 1config SERIAL_IPOCTAL
2 tristate "IndustryPack IP-OCTAL uart support" 2 tristate "IndustryPack IP-OCTAL uart support"
3 depends on IPACK_BUS 3 depends on IPACK_BUS && TTY
4 help 4 help
5 This driver supports the IPOCTAL serial port device for the IndustryPack bus. 5 This driver supports the IPOCTAL serial port device for the IndustryPack bus.
6 default n 6 default n
diff --git a/drivers/ipack/devices/ipoctal.c b/drivers/ipack/devices/ipoctal.c
index 576d53d92677..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,
@@ -133,15 +123,16 @@ static int ipoctal_get_icount(struct tty_struct *tty,
133 return 0; 123 return 0;
134} 124}
135 125
136static void ipoctal_irq_rx(struct ipoctal_channel *channel, 126static void ipoctal_irq_rx(struct ipoctal_channel *channel, u8 sr)
137 struct tty_struct *tty, u8 sr)
138{ 127{
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);
@@ -149,7 +140,7 @@ static void ipoctal_irq_rx(struct ipoctal_channel *channel,
149 if (sr & SR_OVERRUN_ERROR) { 140 if (sr & SR_OVERRUN_ERROR) {
150 channel->stats.overrun_err++; 141 channel->stats.overrun_err++;
151 /* Overrun doesn't affect the current character*/ 142 /* Overrun doesn't affect the current character*/
152 tty_insert_flip_char(tty, 0, TTY_OVERRUN); 143 tty_insert_flip_char(port, 0, TTY_OVERRUN);
153 } 144 }
154 if (sr & SR_PARITY_ERROR) { 145 if (sr & SR_PARITY_ERROR) {
155 channel->stats.parity_err++; 146 channel->stats.parity_err++;
@@ -165,7 +156,7 @@ static void ipoctal_irq_rx(struct ipoctal_channel *channel,
165 flag = TTY_BREAK; 156 flag = TTY_BREAK;
166 } 157 }
167 } 158 }
168 tty_insert_flip_char(tty, value, flag); 159 tty_insert_flip_char(port, value, flag);
169 160
170 /* Check if there are more characters in RX FIFO 161 /* Check if there are more characters in RX FIFO
171 * If there are more, the isr register for this channel 162 * If there are more, the isr register for this channel
@@ -175,7 +166,7 @@ static void ipoctal_irq_rx(struct ipoctal_channel *channel,
175 sr = ioread8(&channel->regs->r.sr); 166 sr = ioread8(&channel->regs->r.sr);
176 } while (isr & channel->isr_rx_rdy_mask); 167 } while (isr & channel->isr_rx_rdy_mask);
177 168
178 tty_flip_buffer_push(tty); 169 tty_flip_buffer_push(port);
179} 170}
180 171
181static void ipoctal_irq_tx(struct ipoctal_channel *channel) 172static void ipoctal_irq_tx(struct ipoctal_channel *channel)
@@ -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,55 +183,38 @@ 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 struct tty_struct *tty;
212 191
213 /* If there is no client, skip the check */ 192 spin_lock(&channel->lock);
214 if (!atomic_read(&channel->open))
215 return;
216
217 tty = tty_port_tty_get(&channel->tty_port);
218 if (!tty)
219 return;
220 /* 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
221 * to read from */ 194 * to read from */
222 isr = ioread8(&channel->block_regs->r.isr); 195 isr = ioread8(&channel->block_regs->r.isr);
223 sr = ioread8(&channel->regs->r.sr); 196 sr = ioread8(&channel->regs->r.sr);
224 197
225 /* In case of RS-485, change from TX to RX when finishing TX. 198 if ((sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
226 * Half-duplex. */
227 if ((channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) &&
228 (sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) {
229 iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); 199 iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
230 iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); 200 /* In case of RS-485, change from TX to RX when finishing TX.
231 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); 201 * Half-duplex. */
232 *channel->board_write = 1; 202 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) {
233 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 }
234 } 207 }
235 208
236 /* RX data */ 209 /* RX data */
237 if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY)) 210 if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY))
238 ipoctal_irq_rx(channel, tty, sr); 211 ipoctal_irq_rx(channel, sr);
239 212
240 /* TX of each character */ 213 /* TX of each character */
241 if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY)) 214 if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
242 ipoctal_irq_tx(channel); 215 ipoctal_irq_tx(channel);
243 216
244 tty_flip_buffer_push(tty); 217 spin_unlock(&channel->lock);
245 tty_kref_put(tty);
246} 218}
247 219
248static irqreturn_t ipoctal_irq_handler(void *arg) 220static irqreturn_t ipoctal_irq_handler(void *arg)
@@ -250,14 +222,14 @@ static irqreturn_t ipoctal_irq_handler(void *arg)
250 unsigned int i; 222 unsigned int i;
251 struct ipoctal *ipoctal = (struct ipoctal *) arg; 223 struct ipoctal *ipoctal = (struct ipoctal *) arg;
252 224
253 /* Check all channels */
254 for (i = 0; i < NR_CHANNELS; i++)
255 ipoctal_irq_channel(&ipoctal->channel[i]);
256
257 /* Clear the IPack device interrupt */ 225 /* Clear the IPack device interrupt */
258 readw(ipoctal->int_space + ACK_INT_REQ0); 226 readw(ipoctal->int_space + ACK_INT_REQ0);
259 readw(ipoctal->int_space + ACK_INT_REQ1); 227 readw(ipoctal->int_space + ACK_INT_REQ1);
260 228
229 /* Check all channels */
230 for (i = 0; i < NR_CHANNELS; i++)
231 ipoctal_irq_channel(&ipoctal->channel[i]);
232
261 return IRQ_HANDLED; 233 return IRQ_HANDLED;
262} 234}
263 235
@@ -311,7 +283,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
311 ipoctal->mem8_space = 283 ipoctal->mem8_space =
312 devm_ioremap_nocache(&ipoctal->dev->dev, 284 devm_ioremap_nocache(&ipoctal->dev->dev,
313 region->start, 0x8000); 285 region->start, 0x8000);
314 if (!addr) { 286 if (!ipoctal->mem8_space) {
315 dev_err(&ipoctal->dev->dev, 287 dev_err(&ipoctal->dev->dev,
316 "Unable to map slot [%d:%d] MEM8 space!\n", 288 "Unable to map slot [%d:%d] MEM8 space!\n",
317 bus_nr, slot); 289 bus_nr, slot);
@@ -324,7 +296,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
324 struct ipoctal_channel *channel = &ipoctal->channel[i]; 296 struct ipoctal_channel *channel = &ipoctal->channel[i];
325 channel->regs = chan_regs + i; 297 channel->regs = chan_regs + i;
326 channel->block_regs = block_regs + (i >> 1); 298 channel->block_regs = block_regs + (i >> 1);
327 channel->board_write = &ipoctal->write;
328 channel->board_id = ipoctal->board_id; 299 channel->board_id = ipoctal->board_id;
329 if (i & 1) { 300 if (i & 1) {
330 channel->isr_tx_rdy_mask = ISR_TxRDY_B; 301 channel->isr_tx_rdy_mask = ISR_TxRDY_B;
@@ -335,6 +306,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
335 } 306 }
336 307
337 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;
338 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); 310 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
339 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); 311 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
340 iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY, 312 iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY,
@@ -407,8 +379,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
407 379
408 ipoctal_reset_stats(&channel->stats); 380 ipoctal_reset_stats(&channel->stats);
409 channel->nb_bytes = 0; 381 channel->nb_bytes = 0;
410 init_waitqueue_head(&channel->queue);
411
412 spin_lock_init(&channel->lock); 382 spin_lock_init(&channel->lock);
413 channel->pointer_read = 0; 383 channel->pointer_read = 0;
414 channel->pointer_write = 0; 384 channel->pointer_write = 0;
@@ -419,12 +389,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
419 continue; 389 continue;
420 } 390 }
421 dev_set_drvdata(tty_dev, channel); 391 dev_set_drvdata(tty_dev, channel);
422
423 /*
424 * Enable again the RX. TX will be enabled when
425 * there is something to send
426 */
427 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
428 } 392 }
429 393
430 return 0; 394 return 0;
@@ -464,6 +428,7 @@ static int ipoctal_write_tty(struct tty_struct *tty,
464 /* 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 */
465 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { 429 if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) {
466 iowrite8(CR_DISABLE_RX, &channel->regs->w.cr); 430 iowrite8(CR_DISABLE_RX, &channel->regs->w.cr);
431 channel->rx_enable = 0;
467 iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr); 432 iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr);
468 } 433 }
469 434
@@ -472,10 +437,6 @@ static int ipoctal_write_tty(struct tty_struct *tty,
472 * operations 437 * operations
473 */ 438 */
474 iowrite8(CR_ENABLE_TX, &channel->regs->w.cr); 439 iowrite8(CR_ENABLE_TX, &channel->regs->w.cr);
475 wait_event_interruptible(channel->queue, *channel->board_write);
476 iowrite8(CR_DISABLE_TX, &channel->regs->w.cr);
477
478 *channel->board_write = 0;
479 return char_copied; 440 return char_copied;
480} 441}
481 442
@@ -627,8 +588,9 @@ static void ipoctal_set_termios(struct tty_struct *tty,
627 iowrite8(mr2, &channel->regs->w.mr); 588 iowrite8(mr2, &channel->regs->w.mr);
628 iowrite8(csr, &channel->regs->w.csr); 589 iowrite8(csr, &channel->regs->w.csr);
629 590
630 /* Enable again the RX */ 591 /* Enable again the RX, if it was before */
631 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); 592 if (channel->rx_enable)
593 iowrite8(CR_ENABLE_RX, &channel->regs->w.cr);
632} 594}
633 595
634static void ipoctal_hangup(struct tty_struct *tty) 596static void ipoctal_hangup(struct tty_struct *tty)
@@ -648,6 +610,7 @@ static void ipoctal_hangup(struct tty_struct *tty)
648 tty_port_hangup(&channel->tty_port); 610 tty_port_hangup(&channel->tty_port);
649 611
650 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;
651 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); 614 iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr);
652 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); 615 iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr);
653 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); 616 iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr);
@@ -657,6 +620,22 @@ static void ipoctal_hangup(struct tty_struct *tty)
657 wake_up_interruptible(&channel->tty_port.open_wait); 620 wake_up_interruptible(&channel->tty_port.open_wait);
658} 621}
659 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
660static const struct tty_operations ipoctal_fops = { 639static const struct tty_operations ipoctal_fops = {
661 .ioctl = NULL, 640 .ioctl = NULL,
662 .open = ipoctal_open, 641 .open = ipoctal_open,
@@ -667,6 +646,7 @@ static const struct tty_operations ipoctal_fops = {
667 .chars_in_buffer = ipoctal_chars_in_buffer, 646 .chars_in_buffer = ipoctal_chars_in_buffer,
668 .get_icount = ipoctal_get_icount, 647 .get_icount = ipoctal_get_icount,
669 .hangup = ipoctal_hangup, 648 .hangup = ipoctal_hangup,
649 .shutdown = ipoctal_shutdown,
670}; 650};
671 651
672static int ipoctal_probe(struct ipack_device *dev) 652static int ipoctal_probe(struct ipack_device *dev)