1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * driver for the GE IP-OCTAL boards |
4 | * |
5 | * Copyright (C) 2009-2012 CERN (www.cern.ch) |
6 | * Author: Nicolas Serafini, EIC2 SA |
7 | * Author: Samuel Iglesias Gonsalvez <siglesias@igalia.com> |
8 | */ |
9 | |
10 | #include <linux/device.h> |
11 | #include <linux/module.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/sched.h> |
14 | #include <linux/tty.h> |
15 | #include <linux/serial.h> |
16 | #include <linux/tty_flip.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/io.h> |
19 | #include <linux/ipack.h> |
20 | #include "ipoctal.h" |
21 | #include "scc2698.h" |
22 | |
23 | #define IP_OCTAL_ID_SPACE_VECTOR 0x41 |
24 | #define IP_OCTAL_NB_BLOCKS 4 |
25 | |
26 | static const struct tty_operations ipoctal_fops; |
27 | |
28 | struct ipoctal_channel { |
29 | struct ipoctal_stats stats; |
30 | unsigned int nb_bytes; |
31 | wait_queue_head_t queue; |
32 | spinlock_t lock; |
33 | unsigned int pointer_read; |
34 | unsigned int pointer_write; |
35 | struct tty_port tty_port; |
36 | bool tty_registered; |
37 | union scc2698_channel __iomem *regs; |
38 | union scc2698_block __iomem *block_regs; |
39 | unsigned int board_id; |
40 | u8 isr_rx_rdy_mask; |
41 | u8 isr_tx_rdy_mask; |
42 | unsigned int rx_enable; |
43 | }; |
44 | |
45 | struct ipoctal { |
46 | struct ipack_device *dev; |
47 | unsigned int board_id; |
48 | struct ipoctal_channel channel[NR_CHANNELS]; |
49 | struct tty_driver *tty_drv; |
50 | u8 __iomem *mem8_space; |
51 | u8 __iomem *int_space; |
52 | }; |
53 | |
54 | static inline struct ipoctal *chan_to_ipoctal(struct ipoctal_channel *chan, |
55 | unsigned int index) |
56 | { |
57 | return container_of(chan, struct ipoctal, channel[index]); |
58 | } |
59 | |
60 | static void ipoctal_reset_channel(struct ipoctal_channel *channel) |
61 | { |
62 | iowrite8(CR_DISABLE_RX | CR_DISABLE_TX, &channel->regs->w.cr); |
63 | channel->rx_enable = 0; |
64 | iowrite8(CR_CMD_RESET_RX, &channel->regs->w.cr); |
65 | iowrite8(CR_CMD_RESET_TX, &channel->regs->w.cr); |
66 | iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); |
67 | iowrite8(CR_CMD_RESET_MR, &channel->regs->w.cr); |
68 | } |
69 | |
70 | static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) |
71 | { |
72 | struct ipoctal_channel *channel; |
73 | |
74 | channel = dev_get_drvdata(dev: tty->dev); |
75 | |
76 | /* |
77 | * Enable RX. TX will be enabled when |
78 | * there is something to send |
79 | */ |
80 | iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); |
81 | channel->rx_enable = 1; |
82 | return 0; |
83 | } |
84 | |
85 | static int ipoctal_install(struct tty_driver *driver, struct tty_struct *tty) |
86 | { |
87 | struct ipoctal_channel *channel = dev_get_drvdata(dev: tty->dev); |
88 | struct ipoctal *ipoctal = chan_to_ipoctal(chan: channel, index: tty->index); |
89 | int res; |
90 | |
91 | if (!ipack_get_carrier(dev: ipoctal->dev)) |
92 | return -EBUSY; |
93 | |
94 | res = tty_standard_install(driver, tty); |
95 | if (res) |
96 | goto err_put_carrier; |
97 | |
98 | tty->driver_data = channel; |
99 | |
100 | return 0; |
101 | |
102 | err_put_carrier: |
103 | ipack_put_carrier(dev: ipoctal->dev); |
104 | |
105 | return res; |
106 | } |
107 | |
108 | static int ipoctal_open(struct tty_struct *tty, struct file *file) |
109 | { |
110 | struct ipoctal_channel *channel = tty->driver_data; |
111 | |
112 | return tty_port_open(port: &channel->tty_port, tty, filp: file); |
113 | } |
114 | |
115 | static void ipoctal_reset_stats(struct ipoctal_stats *stats) |
116 | { |
117 | stats->tx = 0; |
118 | stats->rx = 0; |
119 | stats->rcv_break = 0; |
120 | stats->framing_err = 0; |
121 | stats->overrun_err = 0; |
122 | stats->parity_err = 0; |
123 | } |
124 | |
125 | static void ipoctal_free_channel(struct ipoctal_channel *channel) |
126 | { |
127 | ipoctal_reset_stats(stats: &channel->stats); |
128 | channel->pointer_read = 0; |
129 | channel->pointer_write = 0; |
130 | channel->nb_bytes = 0; |
131 | } |
132 | |
133 | static void ipoctal_close(struct tty_struct *tty, struct file *filp) |
134 | { |
135 | struct ipoctal_channel *channel = tty->driver_data; |
136 | |
137 | tty_port_close(port: &channel->tty_port, tty, filp); |
138 | ipoctal_free_channel(channel); |
139 | } |
140 | |
141 | static int ipoctal_get_icount(struct tty_struct *tty, |
142 | struct serial_icounter_struct *icount) |
143 | { |
144 | struct ipoctal_channel *channel = tty->driver_data; |
145 | |
146 | icount->cts = 0; |
147 | icount->dsr = 0; |
148 | icount->rng = 0; |
149 | icount->dcd = 0; |
150 | icount->rx = channel->stats.rx; |
151 | icount->tx = channel->stats.tx; |
152 | icount->frame = channel->stats.framing_err; |
153 | icount->parity = channel->stats.parity_err; |
154 | icount->brk = channel->stats.rcv_break; |
155 | return 0; |
156 | } |
157 | |
158 | static void ipoctal_irq_rx(struct ipoctal_channel *channel, u8 sr) |
159 | { |
160 | struct tty_port *port = &channel->tty_port; |
161 | unsigned char value; |
162 | unsigned char flag; |
163 | u8 isr; |
164 | |
165 | do { |
166 | value = ioread8(&channel->regs->r.rhr); |
167 | flag = TTY_NORMAL; |
168 | /* Error: count statistics */ |
169 | if (sr & SR_ERROR) { |
170 | iowrite8(CR_CMD_RESET_ERR_STATUS, &channel->regs->w.cr); |
171 | |
172 | if (sr & SR_OVERRUN_ERROR) { |
173 | channel->stats.overrun_err++; |
174 | /* Overrun doesn't affect the current character*/ |
175 | tty_insert_flip_char(port, ch: 0, TTY_OVERRUN); |
176 | } |
177 | if (sr & SR_PARITY_ERROR) { |
178 | channel->stats.parity_err++; |
179 | flag = TTY_PARITY; |
180 | } |
181 | if (sr & SR_FRAMING_ERROR) { |
182 | channel->stats.framing_err++; |
183 | flag = TTY_FRAME; |
184 | } |
185 | if (sr & SR_RECEIVED_BREAK) { |
186 | channel->stats.rcv_break++; |
187 | flag = TTY_BREAK; |
188 | } |
189 | } |
190 | tty_insert_flip_char(port, ch: value, flag); |
191 | |
192 | /* Check if there are more characters in RX FIFO |
193 | * If there are more, the isr register for this channel |
194 | * has enabled the RxRDY|FFULL bit. |
195 | */ |
196 | isr = ioread8(&channel->block_regs->r.isr); |
197 | sr = ioread8(&channel->regs->r.sr); |
198 | } while (isr & channel->isr_rx_rdy_mask); |
199 | |
200 | tty_flip_buffer_push(port); |
201 | } |
202 | |
203 | static void ipoctal_irq_tx(struct ipoctal_channel *channel) |
204 | { |
205 | unsigned char value; |
206 | unsigned int *pointer_write = &channel->pointer_write; |
207 | |
208 | if (channel->nb_bytes == 0) |
209 | return; |
210 | |
211 | spin_lock(lock: &channel->lock); |
212 | value = channel->tty_port.xmit_buf[*pointer_write]; |
213 | iowrite8(value, &channel->regs->w.thr); |
214 | channel->stats.tx++; |
215 | (*pointer_write)++; |
216 | *pointer_write = *pointer_write % PAGE_SIZE; |
217 | channel->nb_bytes--; |
218 | spin_unlock(lock: &channel->lock); |
219 | } |
220 | |
221 | static void ipoctal_irq_channel(struct ipoctal_channel *channel) |
222 | { |
223 | u8 isr, sr; |
224 | |
225 | /* The HW is organized in pair of channels. See which register we need |
226 | * to read from */ |
227 | isr = ioread8(&channel->block_regs->r.isr); |
228 | sr = ioread8(&channel->regs->r.sr); |
229 | |
230 | if (isr & (IMR_DELTA_BREAK_A | IMR_DELTA_BREAK_B)) |
231 | iowrite8(CR_CMD_RESET_BREAK_CHANGE, &channel->regs->w.cr); |
232 | |
233 | if ((sr & SR_TX_EMPTY) && (channel->nb_bytes == 0)) { |
234 | iowrite8(CR_DISABLE_TX, &channel->regs->w.cr); |
235 | /* In case of RS-485, change from TX to RX when finishing TX. |
236 | * Half-duplex. */ |
237 | if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { |
238 | iowrite8(CR_CMD_NEGATE_RTSN, &channel->regs->w.cr); |
239 | iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); |
240 | channel->rx_enable = 1; |
241 | } |
242 | } |
243 | |
244 | /* RX data */ |
245 | if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY)) |
246 | ipoctal_irq_rx(channel, sr); |
247 | |
248 | /* TX of each character */ |
249 | if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY)) |
250 | ipoctal_irq_tx(channel); |
251 | } |
252 | |
253 | static irqreturn_t ipoctal_irq_handler(void *arg) |
254 | { |
255 | unsigned int i; |
256 | struct ipoctal *ipoctal = arg; |
257 | |
258 | /* Clear the IPack device interrupt */ |
259 | readw(addr: ipoctal->int_space + ACK_INT_REQ0); |
260 | readw(addr: ipoctal->int_space + ACK_INT_REQ1); |
261 | |
262 | /* Check all channels */ |
263 | for (i = 0; i < NR_CHANNELS; i++) |
264 | ipoctal_irq_channel(channel: &ipoctal->channel[i]); |
265 | |
266 | return IRQ_HANDLED; |
267 | } |
268 | |
269 | static const struct tty_port_operations ipoctal_tty_port_ops = { |
270 | .dtr_rts = NULL, |
271 | .activate = ipoctal_port_activate, |
272 | }; |
273 | |
274 | static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, |
275 | unsigned int slot) |
276 | { |
277 | int res; |
278 | int i; |
279 | struct tty_driver *drv; |
280 | struct ipoctal_channel *channel; |
281 | struct ipack_region *region; |
282 | void __iomem *addr; |
283 | union scc2698_channel __iomem *chan_regs; |
284 | union scc2698_block __iomem *block_regs; |
285 | |
286 | ipoctal->board_id = ipoctal->dev->id_device; |
287 | |
288 | region = &ipoctal->dev->region[IPACK_IO_SPACE]; |
289 | addr = devm_ioremap(dev: &ipoctal->dev->dev, |
290 | offset: region->start, size: region->size); |
291 | if (!addr) { |
292 | dev_err(&ipoctal->dev->dev, |
293 | "Unable to map slot [%d:%d] IO space!\n" , |
294 | bus_nr, slot); |
295 | return -EADDRNOTAVAIL; |
296 | } |
297 | /* Save the virtual address to access the registers easily */ |
298 | chan_regs = |
299 | (union scc2698_channel __iomem *) addr; |
300 | block_regs = |
301 | (union scc2698_block __iomem *) addr; |
302 | |
303 | region = &ipoctal->dev->region[IPACK_INT_SPACE]; |
304 | ipoctal->int_space = |
305 | devm_ioremap(dev: &ipoctal->dev->dev, |
306 | offset: region->start, size: region->size); |
307 | if (!ipoctal->int_space) { |
308 | dev_err(&ipoctal->dev->dev, |
309 | "Unable to map slot [%d:%d] INT space!\n" , |
310 | bus_nr, slot); |
311 | return -EADDRNOTAVAIL; |
312 | } |
313 | |
314 | region = &ipoctal->dev->region[IPACK_MEM8_SPACE]; |
315 | ipoctal->mem8_space = |
316 | devm_ioremap(dev: &ipoctal->dev->dev, |
317 | offset: region->start, size: 0x8000); |
318 | if (!ipoctal->mem8_space) { |
319 | dev_err(&ipoctal->dev->dev, |
320 | "Unable to map slot [%d:%d] MEM8 space!\n" , |
321 | bus_nr, slot); |
322 | return -EADDRNOTAVAIL; |
323 | } |
324 | |
325 | |
326 | /* Disable RX and TX before touching anything */ |
327 | for (i = 0; i < NR_CHANNELS ; i++) { |
328 | struct ipoctal_channel *channel = &ipoctal->channel[i]; |
329 | channel->regs = chan_regs + i; |
330 | channel->block_regs = block_regs + (i >> 1); |
331 | channel->board_id = ipoctal->board_id; |
332 | if (i & 1) { |
333 | channel->isr_tx_rdy_mask = ISR_TxRDY_B; |
334 | channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_B; |
335 | } else { |
336 | channel->isr_tx_rdy_mask = ISR_TxRDY_A; |
337 | channel->isr_rx_rdy_mask = ISR_RxRDY_FFULL_A; |
338 | } |
339 | |
340 | ipoctal_reset_channel(channel); |
341 | iowrite8(MR1_CHRL_8_BITS | MR1_ERROR_CHAR | MR1_RxINT_RxRDY, |
342 | &channel->regs->w.mr); /* mr1 */ |
343 | iowrite8(0, &channel->regs->w.mr); /* mr2 */ |
344 | iowrite8(TX_CLK_9600 | RX_CLK_9600, &channel->regs->w.csr); |
345 | } |
346 | |
347 | for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) { |
348 | iowrite8(ACR_BRG_SET2, &block_regs[i].w.acr); |
349 | iowrite8(OPCR_MPP_OUTPUT | OPCR_MPOa_RTSN | OPCR_MPOb_RTSN, |
350 | &block_regs[i].w.opcr); |
351 | iowrite8(IMR_TxRDY_A | IMR_RxRDY_FFULL_A | IMR_DELTA_BREAK_A | |
352 | IMR_TxRDY_B | IMR_RxRDY_FFULL_B | IMR_DELTA_BREAK_B, |
353 | &block_regs[i].w.imr); |
354 | } |
355 | |
356 | /* Dummy write */ |
357 | iowrite8(1, ipoctal->mem8_space + 1); |
358 | |
359 | /* Register the TTY device */ |
360 | |
361 | /* Each IP-OCTAL channel is a TTY port */ |
362 | drv = tty_alloc_driver(NR_CHANNELS, TTY_DRIVER_REAL_RAW | |
363 | TTY_DRIVER_DYNAMIC_DEV); |
364 | if (IS_ERR(ptr: drv)) |
365 | return PTR_ERR(ptr: drv); |
366 | |
367 | /* Fill struct tty_driver with ipoctal data */ |
368 | drv->owner = THIS_MODULE; |
369 | drv->driver_name = KBUILD_MODNAME; |
370 | drv->name = kasprintf(GFP_KERNEL, KBUILD_MODNAME ".%d.%d." , bus_nr, slot); |
371 | if (!drv->name) { |
372 | res = -ENOMEM; |
373 | goto err_put_driver; |
374 | } |
375 | drv->major = 0; |
376 | |
377 | drv->minor_start = 0; |
378 | drv->type = TTY_DRIVER_TYPE_SERIAL; |
379 | drv->subtype = SERIAL_TYPE_NORMAL; |
380 | drv->init_termios = tty_std_termios; |
381 | drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
382 | drv->init_termios.c_ispeed = 9600; |
383 | drv->init_termios.c_ospeed = 9600; |
384 | |
385 | tty_set_operations(driver: drv, op: &ipoctal_fops); |
386 | res = tty_register_driver(driver: drv); |
387 | if (res) { |
388 | dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n" ); |
389 | goto err_free_name; |
390 | } |
391 | |
392 | /* Save struct tty_driver for use it when uninstalling the device */ |
393 | ipoctal->tty_drv = drv; |
394 | |
395 | for (i = 0; i < NR_CHANNELS; i++) { |
396 | struct device *tty_dev; |
397 | |
398 | channel = &ipoctal->channel[i]; |
399 | tty_port_init(port: &channel->tty_port); |
400 | res = tty_port_alloc_xmit_buf(port: &channel->tty_port); |
401 | if (res) |
402 | continue; |
403 | channel->tty_port.ops = &ipoctal_tty_port_ops; |
404 | |
405 | ipoctal_reset_stats(stats: &channel->stats); |
406 | channel->nb_bytes = 0; |
407 | spin_lock_init(&channel->lock); |
408 | channel->pointer_read = 0; |
409 | channel->pointer_write = 0; |
410 | tty_dev = tty_port_register_device_attr(port: &channel->tty_port, driver: drv, |
411 | index: i, NULL, drvdata: channel, NULL); |
412 | if (IS_ERR(ptr: tty_dev)) { |
413 | dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n" ); |
414 | tty_port_free_xmit_buf(port: &channel->tty_port); |
415 | tty_port_destroy(port: &channel->tty_port); |
416 | continue; |
417 | } |
418 | channel->tty_registered = true; |
419 | } |
420 | |
421 | /* |
422 | * IP-OCTAL has different addresses to copy its IRQ vector. |
423 | * Depending of the carrier these addresses are accesible or not. |
424 | * More info in the datasheet. |
425 | */ |
426 | ipoctal->dev->bus->ops->request_irq(ipoctal->dev, |
427 | ipoctal_irq_handler, ipoctal); |
428 | |
429 | return 0; |
430 | |
431 | err_free_name: |
432 | kfree(objp: drv->name); |
433 | err_put_driver: |
434 | tty_driver_kref_put(driver: drv); |
435 | |
436 | return res; |
437 | } |
438 | |
439 | static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel, |
440 | const u8 *buf, int count) |
441 | { |
442 | unsigned long flags; |
443 | int i; |
444 | unsigned int *pointer_read = &channel->pointer_read; |
445 | |
446 | /* Copy the bytes from the user buffer to the internal one */ |
447 | for (i = 0; i < count; i++) { |
448 | if (i <= (PAGE_SIZE - channel->nb_bytes)) { |
449 | spin_lock_irqsave(&channel->lock, flags); |
450 | channel->tty_port.xmit_buf[*pointer_read] = buf[i]; |
451 | *pointer_read = (*pointer_read + 1) % PAGE_SIZE; |
452 | channel->nb_bytes++; |
453 | spin_unlock_irqrestore(lock: &channel->lock, flags); |
454 | } else { |
455 | break; |
456 | } |
457 | } |
458 | return i; |
459 | } |
460 | |
461 | static ssize_t ipoctal_write_tty(struct tty_struct *tty, const u8 *buf, |
462 | size_t count) |
463 | { |
464 | struct ipoctal_channel *channel = tty->driver_data; |
465 | unsigned int char_copied; |
466 | |
467 | char_copied = ipoctal_copy_write_buffer(channel, buf, count); |
468 | |
469 | /* As the IP-OCTAL 485 only supports half duplex, do it manually */ |
470 | if (channel->board_id == IPACK1_DEVICE_ID_SBS_OCTAL_485) { |
471 | iowrite8(CR_DISABLE_RX, &channel->regs->w.cr); |
472 | channel->rx_enable = 0; |
473 | iowrite8(CR_CMD_ASSERT_RTSN, &channel->regs->w.cr); |
474 | } |
475 | |
476 | /* |
477 | * Send a packet and then disable TX to avoid failure after several send |
478 | * operations |
479 | */ |
480 | iowrite8(CR_ENABLE_TX, &channel->regs->w.cr); |
481 | return char_copied; |
482 | } |
483 | |
484 | static unsigned int ipoctal_write_room(struct tty_struct *tty) |
485 | { |
486 | struct ipoctal_channel *channel = tty->driver_data; |
487 | |
488 | return PAGE_SIZE - channel->nb_bytes; |
489 | } |
490 | |
491 | static unsigned int ipoctal_chars_in_buffer(struct tty_struct *tty) |
492 | { |
493 | struct ipoctal_channel *channel = tty->driver_data; |
494 | |
495 | return channel->nb_bytes; |
496 | } |
497 | |
498 | static void ipoctal_set_termios(struct tty_struct *tty, |
499 | const struct ktermios *old_termios) |
500 | { |
501 | unsigned int cflag; |
502 | unsigned char mr1 = 0; |
503 | unsigned char mr2 = 0; |
504 | unsigned char csr = 0; |
505 | struct ipoctal_channel *channel = tty->driver_data; |
506 | speed_t baud; |
507 | |
508 | cflag = tty->termios.c_cflag; |
509 | |
510 | /* Disable and reset everything before change the setup */ |
511 | ipoctal_reset_channel(channel); |
512 | |
513 | /* Set Bits per chars */ |
514 | switch (cflag & CSIZE) { |
515 | case CS6: |
516 | mr1 |= MR1_CHRL_6_BITS; |
517 | break; |
518 | case CS7: |
519 | mr1 |= MR1_CHRL_7_BITS; |
520 | break; |
521 | case CS8: |
522 | default: |
523 | mr1 |= MR1_CHRL_8_BITS; |
524 | /* By default, select CS8 */ |
525 | tty->termios.c_cflag = (cflag & ~CSIZE) | CS8; |
526 | break; |
527 | } |
528 | |
529 | /* Set Parity */ |
530 | if (cflag & PARENB) |
531 | if (cflag & PARODD) |
532 | mr1 |= MR1_PARITY_ON | MR1_PARITY_ODD; |
533 | else |
534 | mr1 |= MR1_PARITY_ON | MR1_PARITY_EVEN; |
535 | else |
536 | mr1 |= MR1_PARITY_OFF; |
537 | |
538 | /* Mark or space parity is not supported */ |
539 | tty->termios.c_cflag &= ~CMSPAR; |
540 | |
541 | /* Set stop bits */ |
542 | if (cflag & CSTOPB) |
543 | mr2 |= MR2_STOP_BITS_LENGTH_2; |
544 | else |
545 | mr2 |= MR2_STOP_BITS_LENGTH_1; |
546 | |
547 | /* Set the flow control */ |
548 | switch (channel->board_id) { |
549 | case IPACK1_DEVICE_ID_SBS_OCTAL_232: |
550 | if (cflag & CRTSCTS) { |
551 | mr1 |= MR1_RxRTS_CONTROL_ON; |
552 | mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON; |
553 | } else { |
554 | mr1 |= MR1_RxRTS_CONTROL_OFF; |
555 | mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; |
556 | } |
557 | break; |
558 | case IPACK1_DEVICE_ID_SBS_OCTAL_422: |
559 | mr1 |= MR1_RxRTS_CONTROL_OFF; |
560 | mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; |
561 | break; |
562 | case IPACK1_DEVICE_ID_SBS_OCTAL_485: |
563 | mr1 |= MR1_RxRTS_CONTROL_OFF; |
564 | mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF; |
565 | break; |
566 | default: |
567 | return; |
568 | } |
569 | |
570 | baud = tty_get_baud_rate(tty); |
571 | tty_termios_encode_baud_rate(termios: &tty->termios, ibaud: baud, obaud: baud); |
572 | |
573 | /* Set baud rate */ |
574 | switch (baud) { |
575 | case 75: |
576 | csr |= TX_CLK_75 | RX_CLK_75; |
577 | break; |
578 | case 110: |
579 | csr |= TX_CLK_110 | RX_CLK_110; |
580 | break; |
581 | case 150: |
582 | csr |= TX_CLK_150 | RX_CLK_150; |
583 | break; |
584 | case 300: |
585 | csr |= TX_CLK_300 | RX_CLK_300; |
586 | break; |
587 | case 600: |
588 | csr |= TX_CLK_600 | RX_CLK_600; |
589 | break; |
590 | case 1200: |
591 | csr |= TX_CLK_1200 | RX_CLK_1200; |
592 | break; |
593 | case 1800: |
594 | csr |= TX_CLK_1800 | RX_CLK_1800; |
595 | break; |
596 | case 2000: |
597 | csr |= TX_CLK_2000 | RX_CLK_2000; |
598 | break; |
599 | case 2400: |
600 | csr |= TX_CLK_2400 | RX_CLK_2400; |
601 | break; |
602 | case 4800: |
603 | csr |= TX_CLK_4800 | RX_CLK_4800; |
604 | break; |
605 | case 9600: |
606 | csr |= TX_CLK_9600 | RX_CLK_9600; |
607 | break; |
608 | case 19200: |
609 | csr |= TX_CLK_19200 | RX_CLK_19200; |
610 | break; |
611 | case 38400: |
612 | default: |
613 | csr |= TX_CLK_38400 | RX_CLK_38400; |
614 | /* In case of default, we establish 38400 bps */ |
615 | tty_termios_encode_baud_rate(termios: &tty->termios, ibaud: 38400, obaud: 38400); |
616 | break; |
617 | } |
618 | |
619 | mr1 |= MR1_ERROR_CHAR; |
620 | mr1 |= MR1_RxINT_RxRDY; |
621 | |
622 | /* Write the control registers */ |
623 | iowrite8(mr1, &channel->regs->w.mr); |
624 | iowrite8(mr2, &channel->regs->w.mr); |
625 | iowrite8(csr, &channel->regs->w.csr); |
626 | |
627 | /* Enable again the RX, if it was before */ |
628 | if (channel->rx_enable) |
629 | iowrite8(CR_ENABLE_RX, &channel->regs->w.cr); |
630 | } |
631 | |
632 | static void ipoctal_hangup(struct tty_struct *tty) |
633 | { |
634 | unsigned long flags; |
635 | struct ipoctal_channel *channel = tty->driver_data; |
636 | |
637 | if (channel == NULL) |
638 | return; |
639 | |
640 | spin_lock_irqsave(&channel->lock, flags); |
641 | channel->nb_bytes = 0; |
642 | channel->pointer_read = 0; |
643 | channel->pointer_write = 0; |
644 | spin_unlock_irqrestore(lock: &channel->lock, flags); |
645 | |
646 | tty_port_hangup(port: &channel->tty_port); |
647 | |
648 | ipoctal_reset_channel(channel); |
649 | tty_port_set_initialized(port: &channel->tty_port, val: false); |
650 | wake_up_interruptible(&channel->tty_port.open_wait); |
651 | } |
652 | |
653 | static void ipoctal_shutdown(struct tty_struct *tty) |
654 | { |
655 | struct ipoctal_channel *channel = tty->driver_data; |
656 | |
657 | if (channel == NULL) |
658 | return; |
659 | |
660 | ipoctal_reset_channel(channel); |
661 | tty_port_set_initialized(port: &channel->tty_port, val: false); |
662 | } |
663 | |
664 | static void ipoctal_cleanup(struct tty_struct *tty) |
665 | { |
666 | struct ipoctal_channel *channel = tty->driver_data; |
667 | struct ipoctal *ipoctal = chan_to_ipoctal(chan: channel, index: tty->index); |
668 | |
669 | /* release the carrier driver */ |
670 | ipack_put_carrier(dev: ipoctal->dev); |
671 | } |
672 | |
673 | static const struct tty_operations ipoctal_fops = { |
674 | .ioctl = NULL, |
675 | .install = ipoctal_install, |
676 | .open = ipoctal_open, |
677 | .close = ipoctal_close, |
678 | .write = ipoctal_write_tty, |
679 | .set_termios = ipoctal_set_termios, |
680 | .write_room = ipoctal_write_room, |
681 | .chars_in_buffer = ipoctal_chars_in_buffer, |
682 | .get_icount = ipoctal_get_icount, |
683 | .hangup = ipoctal_hangup, |
684 | .shutdown = ipoctal_shutdown, |
685 | .cleanup = ipoctal_cleanup, |
686 | }; |
687 | |
688 | static int ipoctal_probe(struct ipack_device *dev) |
689 | { |
690 | int res; |
691 | struct ipoctal *ipoctal; |
692 | |
693 | ipoctal = kzalloc(size: sizeof(struct ipoctal), GFP_KERNEL); |
694 | if (ipoctal == NULL) |
695 | return -ENOMEM; |
696 | |
697 | ipoctal->dev = dev; |
698 | res = ipoctal_inst_slot(ipoctal, bus_nr: dev->bus->bus_nr, slot: dev->slot); |
699 | if (res) |
700 | goto out_uninst; |
701 | |
702 | dev_set_drvdata(dev: &dev->dev, data: ipoctal); |
703 | return 0; |
704 | |
705 | out_uninst: |
706 | kfree(objp: ipoctal); |
707 | return res; |
708 | } |
709 | |
710 | static void __ipoctal_remove(struct ipoctal *ipoctal) |
711 | { |
712 | int i; |
713 | |
714 | ipoctal->dev->bus->ops->free_irq(ipoctal->dev); |
715 | |
716 | for (i = 0; i < NR_CHANNELS; i++) { |
717 | struct ipoctal_channel *channel = &ipoctal->channel[i]; |
718 | |
719 | if (!channel->tty_registered) |
720 | continue; |
721 | |
722 | tty_unregister_device(driver: ipoctal->tty_drv, index: i); |
723 | tty_port_free_xmit_buf(port: &channel->tty_port); |
724 | tty_port_destroy(port: &channel->tty_port); |
725 | } |
726 | |
727 | tty_unregister_driver(driver: ipoctal->tty_drv); |
728 | kfree(objp: ipoctal->tty_drv->name); |
729 | tty_driver_kref_put(driver: ipoctal->tty_drv); |
730 | kfree(objp: ipoctal); |
731 | } |
732 | |
733 | static void ipoctal_remove(struct ipack_device *idev) |
734 | { |
735 | __ipoctal_remove(ipoctal: dev_get_drvdata(dev: &idev->dev)); |
736 | } |
737 | |
738 | static DEFINE_IPACK_DEVICE_TABLE(ipoctal_ids) = { |
739 | { IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS, |
740 | IPACK1_DEVICE_ID_SBS_OCTAL_232) }, |
741 | { IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS, |
742 | IPACK1_DEVICE_ID_SBS_OCTAL_422) }, |
743 | { IPACK_DEVICE(IPACK_ID_VERSION_1, IPACK1_VENDOR_ID_SBS, |
744 | IPACK1_DEVICE_ID_SBS_OCTAL_485) }, |
745 | { 0, }, |
746 | }; |
747 | |
748 | MODULE_DEVICE_TABLE(ipack, ipoctal_ids); |
749 | |
750 | static const struct ipack_driver_ops ipoctal_drv_ops = { |
751 | .probe = ipoctal_probe, |
752 | .remove = ipoctal_remove, |
753 | }; |
754 | |
755 | static struct ipack_driver driver = { |
756 | .ops = &ipoctal_drv_ops, |
757 | .id_table = ipoctal_ids, |
758 | }; |
759 | |
760 | static int __init ipoctal_init(void) |
761 | { |
762 | return ipack_driver_register(edrv: &driver, THIS_MODULE, KBUILD_MODNAME); |
763 | } |
764 | |
765 | static void __exit ipoctal_exit(void) |
766 | { |
767 | ipack_driver_unregister(edrv: &driver); |
768 | } |
769 | |
770 | MODULE_DESCRIPTION("IP-Octal 232, 422 and 485 device driver" ); |
771 | MODULE_LICENSE("GPL" ); |
772 | |
773 | module_init(ipoctal_init); |
774 | module_exit(ipoctal_exit); |
775 | |