diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 16:57:13 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 16:57:13 -0500 |
| commit | 7ed214ac2095f561a94335ca672b6c42a1ea40ff (patch) | |
| tree | da41901bff1d0d8d61170bf362384fdc61deb3ab /drivers/ipack | |
| parent | 21eaab6d19ed43e82ed39c8deb7f192134fb4a0e (diff) | |
| parent | 29e5507ae4ab34397f538f06b7070c81a4e4a2bf (diff) | |
Merge tag 'char-misc-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver patches from Greg Kroah-Hartman:
"Here's the big char/misc driver patches for 3.9-rc1.
Nothing major here, just lots of different driver updates (mei,
hyperv, ipack, extcon, vmci, etc.).
All of these have been in the linux-next tree for a while."
* tag 'char-misc-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (209 commits)
w1: w1_therm: Add force-pullup option for "broken" sensors
w1: ds2482: Added 1-Wire pull-up support to the driver
vme: add missing put_device() after device_register() fails
extcon: max8997: Use workqueue to check cable state after completing boot of platform
extcon: max8997: Set default UART/USB path on probe
extcon: max8997: Consolidate duplicate code for checking ADC/CHG cable type
extcon: max8997: Set default of ADC debounce time during initialization
extcon: max8997: Remove duplicate code related to set H/W line path
extcon: max8997: Move defined constant to header file
extcon: max77693: Make max77693_extcon_cable static
extcon: max8997: Remove unreachable code
extcon: max8997: Make max8997_extcon_cable static
extcon: max77693: Remove unnecessary goto statement to improve readability
extcon: max77693: Convert to devm_input_allocate_device()
extcon: gpio: Rename filename of extcon-gpio.c according to kernel naming style
CREDITS: update email and address of Harald Hoyer
extcon: arizona: Use MICDET for final microphone identification
extcon: arizona: Always take the first HPDET reading as the final one
extcon: arizona: Clear _trig_sts bits after jack detection
extcon: arizona: Don't HPDET magic when headphones are enabled
...
Diffstat (limited to 'drivers/ipack')
| -rw-r--r-- | drivers/ipack/devices/ipoctal.c | 113 |
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 | ||
| 51 | struct ipoctal { | 49 | struct 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 | ||
| 71 | static int ipoctal_open(struct tty_struct *tty, struct file *file) | 73 | static 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 | ||
| 91 | static void ipoctal_reset_stats(struct ipoctal_stats *stats) | 83 | static 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 | ||
| 119 | static int ipoctal_get_icount(struct tty_struct *tty, | 109 | static 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 | ||
| 208 | static void ipoctal_irq_channel(struct ipoctal_channel *channel) | 188 | static 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 | ||
| 243 | static irqreturn_t ipoctal_irq_handler(void *arg) | 220 | static 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 | ||
| 629 | static void ipoctal_hangup(struct tty_struct *tty) | 596 | static 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 | ||
| 623 | static 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 | |||
| 655 | static const struct tty_operations ipoctal_fops = { | 639 | static 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 | ||
| 667 | static int ipoctal_probe(struct ipack_device *dev) | 652 | static int ipoctal_probe(struct ipack_device *dev) |
