TTY/Serial merge for 3.8-rc1

Here's the big tty/serial tree set of changes for 3.8-rc1.
 
 Contained in here is a bunch more reworks of the tty port layer from Jiri and
 bugfixes from Alan, along with a number of other tty and serial driver updates
 by the various driver authors.
 
 Also, Jiri has been coerced^Wconvinced to be the co-maintainer of the TTY
 layer, which is much appreciated by me.
 
 All of these have been in the linux-next tree for a while.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.19 (GNU/Linux)
 
 iEYEABECAAYFAlDHhgwACgkQMUfUDdst+ynI6wCcC+YeBwncnoWHvwLAJOwAZpUL
 bysAn28o780/lOsTzp3P1Qcjvo69nldo
 =hN/g
 -----END PGP SIGNATURE-----

Merge tag 'tty-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull TTY/Serial merge from Greg Kroah-Hartman:
 "Here's the big tty/serial tree set of changes for 3.8-rc1.

  Contained in here is a bunch more reworks of the tty port layer from
  Jiri and bugfixes from Alan, along with a number of other tty and
  serial driver updates by the various driver authors.

  Also, Jiri has been coerced^Wconvinced to be the co-maintainer of the
  TTY layer, which is much appreciated by me.

  All of these have been in the linux-next tree for a while.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

Fixed up some trivial conflicts in the staging tree, due to the fwserial
driver having come in both ways (but fixed up a bit in the serial tree),
and the ioctl handling in the dgrp driver having been done slightly
differently (staging tree got that one right, and removed both
TIOCGSOFTCAR and TIOCSSOFTCAR).

* tag 'tty-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (146 commits)
  staging: sb105x: fix potential NULL pointer dereference in mp_chars_in_buffer()
  staging/fwserial: Remove superfluous free
  staging/fwserial: Use WARN_ONCE when port table is corrupted
  staging/fwserial: Destruct embedded tty_port on teardown
  staging/fwserial: Fix build breakage when !CONFIG_BUG
  staging: fwserial: Add TTY-over-Firewire serial driver
  drivers/tty/serial/serial_core.c: clean up HIGH_BITS_OFFSET usage
  staging: dgrp: dgrp_tty.c: Audit the return values of get/put_user()
  staging: dgrp: dgrp_tty.c: Remove the TIOCSSOFTCAR ioctl handler from dgrp driver
  serial: ifx6x60: Add modem power off function in the platform reboot process
  serial: mxs-auart: unmap the scatter list before we copy the data
  serial: mxs-auart: disable the Receive Timeout Interrupt when DMA is enabled
  serial: max310x: Setup missing "can_sleep" field for GPIO
  tty/serial: fix ifx6x60.c declaration warning
  serial: samsung: add devicetree properties for non-Exynos SoCs
  serial: samsung: fix potential soft lockup during uart write
  tty: vt: Remove redundant null check before kfree.
  tty/8250 Add check for pci_ioremap_bar failure
  tty/8250 Add support for Commtech's Fastcom Async-335 and Fastcom Async-PCIe cards
  tty/8250 Add XR17D15x devices to the exar_handle_irq override
  ...
This commit is contained in:
Linus Torvalds 2012-12-11 14:08:47 -08:00
commit c6bd5bcc49
166 changed files with 8146 additions and 1782 deletions

View File

@ -26,3 +26,115 @@ Description:
UART port in serial_core, that is bound to TTY like ttyS0. UART port in serial_core, that is bound to TTY like ttyS0.
uartclk = 16 * baud_base uartclk = 16 * baud_base
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/type
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Shows the current tty type for this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/line
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Shows the current tty line number for this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/port
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Shows the current tty port I/O address for this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/irq
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Shows the current primary interrupt for this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/flags
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Show the tty port status flags for this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/xmit_fifo_size
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Show the transmit FIFO size for this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/close_delay
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Show the closing delay time for this port in ms.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/closing_wait
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Show the close wait time for this port in ms.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/custom_divisor
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Show the custom divisor if any that is set on this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/io_type
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Show the I/O type that is to be used with the iomem base
address.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/iomem_base
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
The I/O memory base for this port.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.
What: /sys/class/tty/ttyS0/iomem_reg_shift
Date: October 2012
Contact: Alan Cox <alan@linux.intel.com>
Description:
Show the register shift indicating the spacing to be used
for accesses on this iomem address.
These sysfs values expose the TIOCGSERIAL interface via
sysfs rather than via ioctls.

View File

@ -6,11 +6,19 @@ Required properties:
- reg : Address and length of the register set for the device - reg : Address and length of the register set for the device
- interrupts : Should contain the auart interrupt numbers - interrupts : Should contain the auart interrupt numbers
Optional properties:
- fsl,auart-dma-channel : The DMA channels, the first is for RX, the other
is for TX. If you add this property, it also means that you
will enable the DMA support for the auart.
Note: due to the hardware bug in imx23(see errata : 2836),
only the imx28 can enable the DMA support for the auart.
Example: Example:
auart0: serial@8006a000 { auart0: serial@8006a000 {
compatible = "fsl,imx28-auart", "fsl,imx23-auart"; compatible = "fsl,imx28-auart", "fsl,imx23-auart";
reg = <0x8006a000 0x2000>; reg = <0x8006a000 0x2000>;
interrupts = <112 70 71>; interrupts = <112 70 71>;
fsl,auart-dma-channel = <8 9>;
}; };
Note: Each auart port should have an alias correctly numbered in "aliases" Note: Each auart port should have an alias correctly numbered in "aliases"

View File

@ -14,7 +14,10 @@ Required properties:
- "serial" if the port type is unknown. - "serial" if the port type is unknown.
- reg : offset and length of the register set for the device. - reg : offset and length of the register set for the device.
- interrupts : should contain uart interrupt. - interrupts : should contain uart interrupt.
- clock-frequency : the input clock frequency for the UART. - clock-frequency : the input clock frequency for the UART
or
clocks phandle to refer to the clk used as per Documentation/devicetree
/bindings/clock/clock-bindings.txt
Optional properties: Optional properties:
- current-speed : the current active speed of the UART. - current-speed : the current active speed of the UART.

View File

@ -7430,6 +7430,7 @@ K: ^Subject:.*(?i)trivial
TTY LAYER TTY LAYER
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
M: Jiri Slaby <jslaby@suse.cz>
S: Supported S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
F: drivers/tty/ F: drivers/tty/

View File

@ -95,6 +95,9 @@
#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */ #define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCVHANGUP 0x5437 #define TIOCVHANGUP 0x5437
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
#define TIOCSERCONFIG 0x5453 #define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454 #define TIOCSERGWILD 0x5454

View File

@ -205,7 +205,6 @@ static const struct tty_operations srmcons_ops = {
static int __init static int __init
srmcons_init(void) srmcons_init(void)
{ {
tty_port_init(&srmcons_singleton.port);
setup_timer(&srmcons_singleton.timer, srmcons_receive_chars, setup_timer(&srmcons_singleton.timer, srmcons_receive_chars,
(unsigned long)&srmcons_singleton); (unsigned long)&srmcons_singleton);
if (srm_is_registered_console) { if (srm_is_registered_console) {
@ -215,6 +214,9 @@ srmcons_init(void)
driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES); driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
if (!driver) if (!driver)
return -ENOMEM; return -ENOMEM;
tty_port_init(&srmcons_singleton.port);
driver->driver_name = "srm"; driver->driver_name = "srm";
driver->name = "srm"; driver->name = "srm";
driver->major = 0; /* dynamic */ driver->major = 0; /* dynamic */
@ -227,6 +229,7 @@ srmcons_init(void)
err = tty_register_driver(driver); err = tty_register_driver(driver);
if (err) { if (err) {
put_tty_driver(driver); put_tty_driver(driver);
tty_port_destroy(&srmcons_singleton.port);
return err; return err;
} }
srmcons_driver = driver; srmcons_driver = driver;

View File

@ -799,6 +799,7 @@
compatible = "fsl,imx28-auart", "fsl,imx23-auart"; compatible = "fsl,imx28-auart", "fsl,imx23-auart";
reg = <0x8006a000 0x2000>; reg = <0x8006a000 0x2000>;
interrupts = <112 70 71>; interrupts = <112 70 71>;
fsl,auart-dma-channel = <8 9>;
clocks = <&clks 45>; clocks = <&clks 45>;
status = "disabled"; status = "disabled";
}; };

View File

@ -109,15 +109,6 @@
#define OMAP5UART4 OMAP4UART4 #define OMAP5UART4 OMAP4UART4
#define ZOOM_UART 95 /* Only on zoom2/3 */ #define ZOOM_UART 95 /* Only on zoom2/3 */
/* This is only used by 8250.c for omap1510 */
#define is_omap_port(pt) ({int __ret = 0; \
if ((pt)->port.mapbase == OMAP1_UART1_BASE || \
(pt)->port.mapbase == OMAP1_UART2_BASE || \
(pt)->port.mapbase == OMAP1_UART3_BASE) \
__ret = 1; \
__ret; \
})
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
struct omap_board_data; struct omap_board_data;

View File

@ -555,6 +555,7 @@ static int __init simrs_init(void)
return 0; return 0;
err_free_tty: err_free_tty:
put_tty_driver(hp_simserial_driver); put_tty_driver(hp_simserial_driver);
tty_port_destroy(&state->port);
return retval; return retval;
} }

View File

@ -120,8 +120,6 @@ static int __init nfcon_init(void)
{ {
int res; int res;
tty_port_init(&nfcon_tty_port);
stderr_id = nf_get_id("NF_STDERR"); stderr_id = nf_get_id("NF_STDERR");
if (!stderr_id) if (!stderr_id)
return -ENODEV; return -ENODEV;
@ -130,6 +128,8 @@ static int __init nfcon_init(void)
if (!nfcon_tty_driver) if (!nfcon_tty_driver)
return -ENOMEM; return -ENOMEM;
tty_port_init(&nfcon_tty_port);
nfcon_tty_driver->driver_name = "nfcon"; nfcon_tty_driver->driver_name = "nfcon";
nfcon_tty_driver->name = "nfcon"; nfcon_tty_driver->name = "nfcon";
nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM; nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
@ -143,6 +143,7 @@ static int __init nfcon_init(void)
if (res) { if (res) {
pr_err("failed to register nfcon tty driver\n"); pr_err("failed to register nfcon tty driver\n");
put_tty_driver(nfcon_tty_driver); put_tty_driver(nfcon_tty_driver);
tty_port_destroy(&nfcon_tty_port);
return res; return res;
} }
@ -157,6 +158,7 @@ static void __exit nfcon_exit(void)
unregister_console(&nf_console); unregister_console(&nf_console);
tty_unregister_driver(nfcon_tty_driver); tty_unregister_driver(nfcon_tty_driver);
put_tty_driver(nfcon_tty_driver); put_tty_driver(nfcon_tty_driver);
tty_port_destroy(&nfcon_tty_port);
} }
module_init(nfcon_init); module_init(nfcon_init);

View File

@ -86,6 +86,9 @@
#define TIOCGDEV _IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */ #define TIOCGDEV _IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
#define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */ #define TIOCSIG _IOW('T', 0x36, int) /* Generate signal on Pty slave */
#define TIOCVHANGUP 0x5437 #define TIOCVHANGUP 0x5437
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
/* I hope the range from 0x5480 on is free ... */ /* I hope the range from 0x5480 on is free ... */
#define TIOCSCTTY 0x5480 /* become controlling tty */ #define TIOCSCTTY 0x5480 /* become controlling tty */

View File

@ -55,6 +55,9 @@
#define TIOCGDEV _IOR('T',0x32, int) /* Get primary device node of /dev/console */ #define TIOCGDEV _IOR('T',0x32, int) /* Get primary device node of /dev/console */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCVHANGUP 0x5437 #define TIOCVHANGUP 0x5437
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define FIOCLEX 0x5451 #define FIOCLEX 0x5451

View File

@ -186,13 +186,13 @@ static int __init pdc_console_tty_driver_init(void)
printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n"); printk(KERN_INFO "The PDC console driver is still registered, removing CON_BOOT flag\n");
pdc_cons.flags &= ~CON_BOOT; pdc_cons.flags &= ~CON_BOOT;
tty_port_init(&tty_port);
pdc_console_tty_driver = alloc_tty_driver(1); pdc_console_tty_driver = alloc_tty_driver(1);
if (!pdc_console_tty_driver) if (!pdc_console_tty_driver)
return -ENOMEM; return -ENOMEM;
tty_port_init(&tty_port);
pdc_console_tty_driver->driver_name = "pdc_cons"; pdc_console_tty_driver->driver_name = "pdc_cons";
pdc_console_tty_driver->name = "ttyB"; pdc_console_tty_driver->name = "ttyB";
pdc_console_tty_driver->major = MUX_MAJOR; pdc_console_tty_driver->major = MUX_MAJOR;
@ -207,6 +207,7 @@ static int __init pdc_console_tty_driver_init(void)
err = tty_register_driver(pdc_console_tty_driver); err = tty_register_driver(pdc_console_tty_driver);
if (err) { if (err) {
printk(KERN_ERR "Unable to register the PDC console TTY driver\n"); printk(KERN_ERR "Unable to register the PDC console TTY driver\n");
tty_port_destroy(&tty_port);
return err; return err;
} }

View File

@ -97,6 +97,9 @@
#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */ #define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCVHANGUP 0x5437 #define TIOCVHANGUP 0x5437
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
#define TIOCSERCONFIG 0x5453 #define TIOCSERCONFIG 0x5453
#define TIOCSERGWILD 0x5454 #define TIOCSERGWILD 0x5454

View File

@ -88,6 +88,9 @@
#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */ #define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCVHANGUP _IO('T', 0x37) #define TIOCVHANGUP _IO('T', 0x37)
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
#define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */ #define TIOCSERCONFIG _IO('T', 83) /* 0x5453 */
#define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */ #define TIOCSERGWILD _IOR('T', 84, int) /* 0x5454 */

View File

@ -21,6 +21,9 @@
#define TCSETSF2 _IOW('T', 15, struct termios2) #define TCSETSF2 _IOW('T', 15, struct termios2)
#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */ #define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
#define TIOCVHANGUP _IO('T', 0x37) #define TIOCVHANGUP _IO('T', 0x37)
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
/* Note that all the ioctls that are not available in Linux have a /* Note that all the ioctls that are not available in Linux have a
* double underscore on the front to: a) avoid some programs to * double underscore on the front to: a) avoid some programs to

View File

@ -83,21 +83,8 @@ static const struct chan_ops not_configged_ops = {
static void tty_receive_char(struct tty_struct *tty, char ch) static void tty_receive_char(struct tty_struct *tty, char ch)
{ {
if (tty == NULL) if (tty)
return; tty_insert_flip_char(tty, ch, TTY_NORMAL);
if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) {
if (ch == STOP_CHAR(tty)) {
stop_tty(tty);
return;
}
else if (ch == START_CHAR(tty)) {
start_tty(tty);
return;
}
}
tty_insert_flip_char(tty, ch, TTY_NORMAL);
} }
static int open_one_chan(struct chan *chan) static int open_one_chan(struct chan *chan)

View File

@ -584,6 +584,8 @@ int register_lines(struct line_driver *line_driver,
printk(KERN_ERR "register_lines : can't register %s driver\n", printk(KERN_ERR "register_lines : can't register %s driver\n",
line_driver->name); line_driver->name);
put_tty_driver(driver); put_tty_driver(driver);
for (i = 0; i < nlines; i++)
tty_port_destroy(&lines[i].port);
return err; return err;
} }

View File

@ -105,8 +105,11 @@ static void ce4100_serial_fixup(int port, struct uart_port *up,
up->membase = up->membase =
(void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
up->membase += up->mapbase & ~PAGE_MASK; up->membase += up->mapbase & ~PAGE_MASK;
up->mapbase += port * 0x100;
up->membase += port * 0x100;
up->iotype = UPIO_MEM32; up->iotype = UPIO_MEM32;
up->regshift = 2; up->regshift = 2;
up->irq = 4;
} }
#endif #endif
up->iobase = 0; up->iobase = 0;

View File

@ -101,6 +101,9 @@
#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */ #define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */ #define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
#define TIOCVHANGUP _IO('T', 0x37) #define TIOCVHANGUP _IO('T', 0x37)
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
#define TIOCSERCONFIG _IO('T', 83) #define TIOCSERCONFIG _IO('T', 83)
#define TIOCSERGWILD _IOR('T', 84, int) #define TIOCSERGWILD _IOR('T', 84, int)

View File

@ -221,6 +221,7 @@ static __exit void rs_exit(void)
printk("ISS_SERIAL: failed to unregister serial driver (%d)\n", printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
error); error);
put_tty_driver(serial_driver); put_tty_driver(serial_driver);
tty_port_destroy(&serial_port);
} }

View File

@ -270,15 +270,10 @@ static int hci_uart_send_frame(struct sk_buff *skb)
*/ */
static int hci_uart_tty_open(struct tty_struct *tty) static int hci_uart_tty_open(struct tty_struct *tty)
{ {
struct hci_uart *hu = (void *) tty->disc_data; struct hci_uart *hu;
BT_DBG("tty %p", tty); BT_DBG("tty %p", tty);
/* FIXME: This btw is bogus, nothing requires the old ldisc to clear
the pointer */
if (hu)
return -EEXIST;
/* Error if the tty has no write op instead of leaving an exploitable /* Error if the tty has no write op instead of leaving an exploitable
hole */ hole */
if (tty->ops->write == NULL) if (tty->ops->write == NULL)

View File

@ -549,8 +549,10 @@ static int mgslpc_probe(struct pcmcia_device *link)
/* Initialize the struct pcmcia_device structure */ /* Initialize the struct pcmcia_device structure */
ret = mgslpc_config(link); ret = mgslpc_config(link);
if (ret) if (ret) {
tty_port_destroy(&info->port);
return ret; return ret;
}
mgslpc_add_device(info); mgslpc_add_device(info);
@ -2757,6 +2759,7 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
hdlcdev_exit(info); hdlcdev_exit(info);
#endif #endif
release_resources(info); release_resources(info);
tty_port_destroy(&info->port);
kfree(info); kfree(info);
mgslpc_device_count--; mgslpc_device_count--;
return; return;

View File

@ -179,7 +179,6 @@ static int __init ttyprintk_init(void)
{ {
int ret = -ENOMEM; int ret = -ENOMEM;
tty_port_init(&tpk_port.port);
tpk_port.port.ops = &null_ops; tpk_port.port.ops = &null_ops;
mutex_init(&tpk_port.port_write_mutex); mutex_init(&tpk_port.port_write_mutex);
@ -190,6 +189,8 @@ static int __init ttyprintk_init(void)
if (IS_ERR(ttyprintk_driver)) if (IS_ERR(ttyprintk_driver))
return PTR_ERR(ttyprintk_driver); return PTR_ERR(ttyprintk_driver);
tty_port_init(&tpk_port.port);
ttyprintk_driver->driver_name = "ttyprintk"; ttyprintk_driver->driver_name = "ttyprintk";
ttyprintk_driver->name = "ttyprintk"; ttyprintk_driver->name = "ttyprintk";
ttyprintk_driver->major = TTYAUX_MAJOR; ttyprintk_driver->major = TTYAUX_MAJOR;
@ -211,6 +212,7 @@ static int __init ttyprintk_init(void)
error: error:
tty_unregister_driver(ttyprintk_driver); tty_unregister_driver(ttyprintk_driver);
put_tty_driver(ttyprintk_driver); put_tty_driver(ttyprintk_driver);
tty_port_destroy(&tpk_port.port);
ttyprintk_driver = NULL; ttyprintk_driver = NULL;
return ret; return ret;
} }

View File

@ -415,6 +415,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr,
tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL); tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
if (IS_ERR(tty_dev)) { if (IS_ERR(tty_dev)) {
dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n"); dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
tty_port_destroy(&channel->tty_port);
continue; continue;
} }
dev_set_drvdata(tty_dev, channel); dev_set_drvdata(tty_dev, channel);
@ -700,6 +701,7 @@ static void __ipoctal_remove(struct ipoctal *ipoctal)
struct ipoctal_channel *channel = &ipoctal->channel[i]; struct ipoctal_channel *channel = &ipoctal->channel[i];
tty_unregister_device(ipoctal->tty_drv, i); tty_unregister_device(ipoctal->tty_drv, i);
tty_port_free_xmit_buf(&channel->tty_port); tty_port_free_xmit_buf(&channel->tty_port);
tty_port_destroy(&channel->tty_port);
} }
tty_unregister_driver(ipoctal->tty_drv); tty_unregister_driver(ipoctal->tty_drv);

View File

@ -77,8 +77,6 @@ struct ackqueue_entry {
}; };
struct capiminor { struct capiminor {
struct kref kref;
unsigned int minor; unsigned int minor;
struct capi20_appl *ap; struct capi20_appl *ap;
@ -190,7 +188,20 @@ static void capiminor_del_all_ack(struct capiminor *mp)
/* -------- struct capiminor ---------------------------------------- */ /* -------- struct capiminor ---------------------------------------- */
static const struct tty_port_operations capiminor_port_ops; /* we have none */ static void capiminor_destroy(struct tty_port *port)
{
struct capiminor *mp = container_of(port, struct capiminor, port);
kfree_skb(mp->outskb);
skb_queue_purge(&mp->inqueue);
skb_queue_purge(&mp->outqueue);
capiminor_del_all_ack(mp);
kfree(mp);
}
static const struct tty_port_operations capiminor_port_ops = {
.destruct = capiminor_destroy,
};
static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci) static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
{ {
@ -204,8 +215,6 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
return NULL; return NULL;
} }
kref_init(&mp->kref);
mp->ap = ap; mp->ap = ap;
mp->ncci = ncci; mp->ncci = ncci;
INIT_LIST_HEAD(&mp->ackqueue); INIT_LIST_HEAD(&mp->ackqueue);
@ -247,21 +256,10 @@ err_out2:
spin_unlock(&capiminors_lock); spin_unlock(&capiminors_lock);
err_out1: err_out1:
kfree(mp); tty_port_put(&mp->port);
return NULL; return NULL;
} }
static void capiminor_destroy(struct kref *kref)
{
struct capiminor *mp = container_of(kref, struct capiminor, kref);
kfree_skb(mp->outskb);
skb_queue_purge(&mp->inqueue);
skb_queue_purge(&mp->outqueue);
capiminor_del_all_ack(mp);
kfree(mp);
}
static struct capiminor *capiminor_get(unsigned int minor) static struct capiminor *capiminor_get(unsigned int minor)
{ {
struct capiminor *mp; struct capiminor *mp;
@ -269,7 +267,7 @@ static struct capiminor *capiminor_get(unsigned int minor)
spin_lock(&capiminors_lock); spin_lock(&capiminors_lock);
mp = capiminors[minor]; mp = capiminors[minor];
if (mp) if (mp)
kref_get(&mp->kref); tty_port_get(&mp->port);
spin_unlock(&capiminors_lock); spin_unlock(&capiminors_lock);
return mp; return mp;
@ -277,7 +275,7 @@ static struct capiminor *capiminor_get(unsigned int minor)
static inline void capiminor_put(struct capiminor *mp) static inline void capiminor_put(struct capiminor *mp)
{ {
kref_put(&mp->kref, capiminor_destroy); tty_port_put(&mp->port);
} }
static void capiminor_free(struct capiminor *mp) static void capiminor_free(struct capiminor *mp)

View File

@ -507,6 +507,7 @@ void gigaset_freecs(struct cardstate *cs)
gig_dbg(DEBUG_INIT, "clearing at_state"); gig_dbg(DEBUG_INIT, "clearing at_state");
clear_at_state(&cs->at_state); clear_at_state(&cs->at_state);
dealloc_temp_at_states(cs); dealloc_temp_at_states(cs);
tty_port_destroy(&cs->port);
/* fall through */ /* fall through */
case 0: /* error in basic setup */ case 0: /* error in basic setup */

View File

@ -1849,6 +1849,8 @@ err_unregister:
kfree(info->fax); kfree(info->fax);
#endif #endif
kfree(info->port.xmit_buf - 4); kfree(info->port.xmit_buf - 4);
info->port.xmit_buf = NULL;
tty_port_destroy(&info->port);
} }
tty_unregister_driver(m->tty_modem); tty_unregister_driver(m->tty_modem);
err: err:
@ -1870,6 +1872,8 @@ isdn_tty_exit(void)
kfree(info->fax); kfree(info->fax);
#endif #endif
kfree(info->port.xmit_buf - 4); kfree(info->port.xmit_buf - 4);
info->port.xmit_buf = NULL;
tty_port_destroy(&info->port);
} }
tty_unregister_driver(dev->mdm.tty_modem); tty_unregister_driver(dev->mdm.tty_modem);
put_tty_driver(dev->mdm.tty_modem); put_tty_driver(dev->mdm.tty_modem);

View File

@ -882,11 +882,14 @@ err:
static void pti_pci_remove(struct pci_dev *pdev) static void pti_pci_remove(struct pci_dev *pdev)
{ {
struct pti_dev *drv_data = pci_get_drvdata(pdev); struct pti_dev *drv_data = pci_get_drvdata(pdev);
unsigned int a;
unregister_console(&pti_console); unregister_console(&pti_console);
tty_unregister_device(pti_tty_driver, 0); for (a = 0; a < PTITTY_MINOR_NUM; a++) {
tty_unregister_device(pti_tty_driver, 1); tty_unregister_device(pti_tty_driver, a);
tty_port_destroy(&drv_data->port[a]);
}
iounmap(drv_data->pti_ioaddr); iounmap(drv_data->pti_ioaddr);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);

View File

@ -66,8 +66,6 @@ struct uart_icount {
struct sdio_uart_port { struct sdio_uart_port {
struct tty_port port; struct tty_port port;
struct kref kref;
struct tty_struct *tty;
unsigned int index; unsigned int index;
struct sdio_func *func; struct sdio_func *func;
struct mutex func_lock; struct mutex func_lock;
@ -93,7 +91,6 @@ static int sdio_uart_add_port(struct sdio_uart_port *port)
{ {
int index, ret = -EBUSY; int index, ret = -EBUSY;
kref_init(&port->kref);
mutex_init(&port->func_lock); mutex_init(&port->func_lock);
spin_lock_init(&port->write_lock); spin_lock_init(&port->write_lock);
if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL)) if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL))
@ -123,23 +120,15 @@ static struct sdio_uart_port *sdio_uart_port_get(unsigned index)
spin_lock(&sdio_uart_table_lock); spin_lock(&sdio_uart_table_lock);
port = sdio_uart_table[index]; port = sdio_uart_table[index];
if (port) if (port)
kref_get(&port->kref); tty_port_get(&port->port);
spin_unlock(&sdio_uart_table_lock); spin_unlock(&sdio_uart_table_lock);
return port; return port;
} }
static void sdio_uart_port_destroy(struct kref *kref)
{
struct sdio_uart_port *port =
container_of(kref, struct sdio_uart_port, kref);
kfifo_free(&port->xmit_fifo);
kfree(port);
}
static void sdio_uart_port_put(struct sdio_uart_port *port) static void sdio_uart_port_put(struct sdio_uart_port *port)
{ {
kref_put(&port->kref, sdio_uart_port_destroy); tty_port_put(&port->port);
} }
static void sdio_uart_port_remove(struct sdio_uart_port *port) static void sdio_uart_port_remove(struct sdio_uart_port *port)
@ -737,6 +726,14 @@ static void sdio_uart_shutdown(struct tty_port *tport)
sdio_uart_release_func(port); sdio_uart_release_func(port);
} }
static void sdio_uart_port_destroy(struct tty_port *tport)
{
struct sdio_uart_port *port =
container_of(tport, struct sdio_uart_port, port);
kfifo_free(&port->xmit_fifo);
kfree(port);
}
/** /**
* sdio_uart_install - install method * sdio_uart_install - install method
* @driver: the driver in use (sdio_uart in our case) * @driver: the driver in use (sdio_uart in our case)
@ -1045,6 +1042,7 @@ static const struct tty_port_operations sdio_uart_port_ops = {
.carrier_raised = uart_carrier_raised, .carrier_raised = uart_carrier_raised,
.shutdown = sdio_uart_shutdown, .shutdown = sdio_uart_shutdown,
.activate = sdio_uart_activate, .activate = sdio_uart_activate,
.destruct = sdio_uart_port_destroy,
}; };
static const struct tty_operations sdio_uart_ops = { static const struct tty_operations sdio_uart_ops = {

View File

@ -2274,6 +2274,7 @@ static void hso_serial_common_free(struct hso_serial *serial)
/* unlink and free TX URB */ /* unlink and free TX URB */
usb_free_urb(serial->tx_urb); usb_free_urb(serial->tx_urb);
kfree(serial->tx_data); kfree(serial->tx_data);
tty_port_destroy(&serial->port);
} }
static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
@ -2283,12 +2284,12 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
int minor; int minor;
int i; int i;
tty_port_init(&serial->port);
minor = get_free_serial_index(); minor = get_free_serial_index();
if (minor < 0) if (minor < 0)
goto exit; goto exit;
tty_port_init(&serial->port);
/* register our minor number */ /* register our minor number */
serial->parent->dev = tty_port_register_device(&serial->port, tty_drv, serial->parent->dev = tty_port_register_device(&serial->port, tty_drv,
minor, &serial->parent->interface->dev); minor, &serial->parent->interface->dev);

View File

@ -677,6 +677,7 @@ static void raw3215_free_info(struct raw3215_info *raw)
{ {
kfree(raw->inbuf); kfree(raw->inbuf);
kfree(raw->buffer); kfree(raw->buffer);
tty_port_destroy(&raw->port);
kfree(raw); kfree(raw);
} }

View File

@ -547,7 +547,6 @@ sclp_tty_init(void)
sclp_tty_tolower = 1; sclp_tty_tolower = 1;
} }
sclp_tty_chars_count = 0; sclp_tty_chars_count = 0;
tty_port_init(&sclp_port);
rc = sclp_register(&sclp_input_event); rc = sclp_register(&sclp_input_event);
if (rc) { if (rc) {
@ -555,6 +554,8 @@ sclp_tty_init(void)
return rc; return rc;
} }
tty_port_init(&sclp_port);
driver->driver_name = "sclp_line"; driver->driver_name = "sclp_line";
driver->name = "sclp_line"; driver->name = "sclp_line";
driver->major = TTY_MAJOR; driver->major = TTY_MAJOR;
@ -571,6 +572,7 @@ sclp_tty_init(void)
rc = tty_register_driver(driver); rc = tty_register_driver(driver);
if (rc) { if (rc) {
put_tty_driver(driver); put_tty_driver(driver);
tty_port_destroy(&sclp_port);
return rc; return rc;
} }
sclp_tty_driver = driver; sclp_tty_driver = driver;

View File

@ -615,6 +615,7 @@ static void __init __sclp_vt220_cleanup(void)
return; return;
sclp_unregister(&sclp_vt220_register); sclp_unregister(&sclp_vt220_register);
__sclp_vt220_free_pages(); __sclp_vt220_free_pages();
tty_port_destroy(&sclp_vt220_port);
} }
/* Allocate buffer pages and register with sclp core. Controlled by init /* Allocate buffer pages and register with sclp core. Controlled by init
@ -650,6 +651,7 @@ out:
if (rc) { if (rc) {
__sclp_vt220_free_pages(); __sclp_vt220_free_pages();
sclp_vt220_init_count--; sclp_vt220_init_count--;
tty_port_destroy(&sclp_vt220_port);
} }
return rc; return rc;
} }

View File

@ -722,6 +722,7 @@ out_pages:
while (pages--) while (pages--)
free_pages((unsigned long) tp->freemem_pages[pages], 0); free_pages((unsigned long) tp->freemem_pages[pages], 0);
kfree(tp->freemem_pages); kfree(tp->freemem_pages);
tty_port_destroy(&tp->port);
out_tp: out_tp:
kfree(tp); kfree(tp);
out_err: out_err:
@ -744,6 +745,7 @@ tty3270_free_view(struct tty3270 *tp)
for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) for (pages = 0; pages < TTY3270_STRING_PAGES; pages++)
free_pages((unsigned long) tp->freemem_pages[pages], 0); free_pages((unsigned long) tp->freemem_pages[pages], 0);
kfree(tp->freemem_pages); kfree(tp->freemem_pages);
tty_port_destroy(&tp->port);
kfree(tp); kfree(tp);
} }

View File

@ -138,6 +138,8 @@ source "drivers/staging/imx-drm/Kconfig"
source "drivers/staging/dgrp/Kconfig" source "drivers/staging/dgrp/Kconfig"
source "drivers/staging/sb105x/Kconfig"
source "drivers/staging/fwserial/Kconfig" source "drivers/staging/fwserial/Kconfig"
endif # STAGING endif # STAGING

View File

@ -61,4 +61,5 @@ obj-$(CONFIG_NET_VENDOR_SILICOM) += silicom/
obj-$(CONFIG_CED1401) += ced1401/ obj-$(CONFIG_CED1401) += ced1401/
obj-$(CONFIG_DRM_IMX) += imx-drm/ obj-$(CONFIG_DRM_IMX) += imx-drm/
obj-$(CONFIG_DGRP) += dgrp/ obj-$(CONFIG_DGRP) += dgrp/
obj-$(CONFIG_SB105X) += sb105x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/ obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/

View File

@ -1140,8 +1140,10 @@ int gserial_setup(struct usb_gadget *g, unsigned count)
return status; return status;
fail: fail:
while (count--) while (count--) {
tty_port_destroy(&ports[count].port->port);
kfree(ports[count].port); kfree(ports[count].port);
}
put_tty_driver(gs_tty_driver); put_tty_driver(gs_tty_driver);
gs_tty_driver = NULL; gs_tty_driver = NULL;
return status; return status;
@ -1195,6 +1197,7 @@ void gserial_cleanup(void)
WARN_ON(port->port_usb != NULL); WARN_ON(port->port_usb != NULL);
tty_port_destroy(&port->port);
kfree(port); kfree(port);
} }
n_ports = 0; n_ports = 0;

View File

@ -31,7 +31,6 @@
* All global storage allocation. * All global storage allocation.
************************************************************************/ ************************************************************************/
extern int dgrp_rawreadok; /* Allow raw writing of input */
extern int dgrp_register_cudevices; /* enable legacy cu devices */ extern int dgrp_register_cudevices; /* enable legacy cu devices */
extern int dgrp_register_prdevices; /* enable transparent print devices */ extern int dgrp_register_prdevices; /* enable transparent print devices */
extern int dgrp_poll_tick; /* Poll interval - in ms */ extern int dgrp_poll_tick; /* Poll interval - in ms */

View File

@ -39,14 +39,10 @@ MODULE_VERSION(DIGI_VERSION);
struct list_head nd_struct_list; struct list_head nd_struct_list;
struct dgrp_poll_data dgrp_poll_data; struct dgrp_poll_data dgrp_poll_data;
int dgrp_rawreadok = 1; /* Bypass flipbuf on input */
int dgrp_register_cudevices = 1;/* Turn on/off registering legacy cu devices */ int dgrp_register_cudevices = 1;/* Turn on/off registering legacy cu devices */
int dgrp_register_prdevices = 1;/* Turn on/off registering transparent print */ int dgrp_register_prdevices = 1;/* Turn on/off registering transparent print */
int dgrp_poll_tick = 20; /* Poll interval - in ms */ int dgrp_poll_tick = 20; /* Poll interval - in ms */
module_param_named(rawreadok, dgrp_rawreadok, int, 0644);
MODULE_PARM_DESC(rawreadok, "Bypass flip buffers on input");
module_param_named(register_cudevices, dgrp_register_cudevices, int, 0644); module_param_named(register_cudevices, dgrp_register_cudevices, int, 0644);
MODULE_PARM_DESC(register_cudevices, "Turn on/off registering legacy cu devices"); MODULE_PARM_DESC(register_cudevices, "Turn on/off registering legacy cu devices");

View File

@ -151,20 +151,15 @@ static void dgrp_read_data_block(struct ch_struct *ch, u8 *flipbuf,
* Copys the rbuf to the flipbuf and sends to line discipline. * Copys the rbuf to the flipbuf and sends to line discipline.
* Sends input buffer data to the line discipline. * Sends input buffer data to the line discipline.
* *
* There are several modes to consider here:
* rawreadok, tty->real_raw, and IF_PARMRK
*/ */
static void dgrp_input(struct ch_struct *ch) static void dgrp_input(struct ch_struct *ch)
{ {
struct nd_struct *nd; struct nd_struct *nd;
struct tty_struct *tty; struct tty_struct *tty;
int remain;
int data_len; int data_len;
int len; int len;
int flip_len;
int tty_count; int tty_count;
ulong lock_flags; ulong lock_flags;
struct tty_ldisc *ld;
u8 *myflipbuf; u8 *myflipbuf;
u8 *myflipflagbuf; u8 *myflipflagbuf;
@ -212,37 +207,11 @@ static void dgrp_input(struct ch_struct *ch)
spin_unlock_irqrestore(&nd->nd_lock, lock_flags); spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
/* Decide how much data we can send into the tty layer */
if (dgrp_rawreadok && tty->real_raw)
flip_len = MYFLIPLEN;
else
flip_len = TTY_FLIPBUF_SIZE;
/* data_len should be the number of chars that we read in */ /* data_len should be the number of chars that we read in */
data_len = (ch->ch_rin - ch->ch_rout) & RBUF_MASK; data_len = (ch->ch_rin - ch->ch_rout) & RBUF_MASK;
remain = data_len;
/* len is the amount of data we are going to transfer here */ /* len is the amount of data we are going to transfer here */
len = min(data_len, flip_len); len = tty_buffer_request_room(tty, data_len);
/* take into consideration length of ldisc */
len = min(len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);
ld = tty_ldisc_ref(tty);
/*
* If we were unable to get a reference to the ld,
* don't flush our buffer, and act like the ld doesn't
* have any space to put the data right now.
*/
if (!ld) {
len = 0;
} else if (!ld->ops->receive_buf) {
spin_lock_irqsave(&nd->nd_lock, lock_flags);
ch->ch_rout = ch->ch_rin;
spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
len = 0;
}
/* Check DPA flow control */ /* Check DPA flow control */
if ((nd->nd_dpa_debug) && if ((nd->nd_dpa_debug) &&
@ -254,42 +223,22 @@ static void dgrp_input(struct ch_struct *ch)
dgrp_read_data_block(ch, myflipbuf, len); dgrp_read_data_block(ch, myflipbuf, len);
/* if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
* In high performance mode, we don't have to update parity_scan(ch, myflipbuf, myflipflagbuf, &len);
* flag_buf or any of the counts or pointers into flip buf. else
*/ memset(myflipflagbuf, TTY_NORMAL, len);
if (!dgrp_rawreadok || !tty->real_raw) {
if (I_PARMRK(tty) || I_BRKINT(tty) || I_INPCK(tty))
parity_scan(ch, myflipbuf, myflipflagbuf, &len);
else
memset(myflipflagbuf, TTY_NORMAL, len);
}
if ((nd->nd_dpa_debug) && if ((nd->nd_dpa_debug) &&
(nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(tty))))) (nd->nd_dpa_port == PORT_NUM(MINOR(tty_devnum(tty)))))
dgrp_dpa_data(nd, 1, myflipbuf, len); dgrp_dpa_data(nd, 1, myflipbuf, len);
/* tty_insert_flip_string_flags(tty, myflipbuf,
* If we're doing raw reads, jam it right into the myflipflagbuf, len);
* line disc bypassing the flip buffers. tty_flip_buffer_push(tty);
*/
if (dgrp_rawreadok && tty->real_raw)
ld->ops->receive_buf(tty, myflipbuf, NULL, len);
else {
len = tty_buffer_request_room(tty, len);
tty_insert_flip_string_flags(tty, myflipbuf,
myflipflagbuf, len);
/* Tell the tty layer its okay to "eat" the data now */
tty_flip_buffer_push(tty);
}
ch->ch_rxcount += len; ch->ch_rxcount += len;
} }
if (ld)
tty_ldisc_deref(ld);
/* /*
* Wake up any sleepers (maybe dgrp close) that might be waiting * Wake up any sleepers (maybe dgrp close) that might be waiting
* for a channel flag state change. * for a channel flag state change.
@ -2549,7 +2498,7 @@ data:
/* /*
* Fabricate and insert a data packet header to * Fabricate and insert a data packet header to
* preceed the remaining data when it comes in. * preced the remaining data when it comes in.
*/ */
if (remain < plen) { if (remain < plen) {
@ -2718,7 +2667,7 @@ data:
} }
/* /*
* Handle delayed response arrival preceeding * Handle delayed response arrival preceding
* the open response we are waiting for. * the open response we are waiting for.
*/ */
@ -3556,7 +3505,7 @@ void dgrp_poll_handler(unsigned long arg)
/* /*
* Decrement statistics. These are only for use with * Decrement statistics. These are only for use with
* KME, so don't worry that the operations are done * KME, so don't worry that the operations are done
* unlocked, and so the results are occassionally wrong. * unlocked, and so the results are occasionally wrong.
*/ */
nd->nd_read_count -= (nd->nd_read_count + nd->nd_read_count -= (nd->nd_read_count +

View File

@ -629,8 +629,6 @@ static int info_proc_show(struct seq_file *m, void *v)
{ {
seq_printf(m, "version: %s\n", DIGI_VERSION); seq_printf(m, "version: %s\n", DIGI_VERSION);
seq_puts(m, "register_with_sysfs: 1\n"); seq_puts(m, "register_with_sysfs: 1\n");
seq_printf(m, "rawreadok: 0x%08x\t(%d)\n",
dgrp_rawreadok, dgrp_rawreadok);
seq_printf(m, "pollrate: 0x%08x\t(%d)\n", seq_printf(m, "pollrate: 0x%08x\t(%d)\n",
dgrp_poll_tick, dgrp_poll_tick); dgrp_poll_tick, dgrp_poll_tick);
@ -754,6 +752,8 @@ static int dgrp_add_id(long id)
return 0; return 0;
/* FIXME this guy should free the tty driver stored in nd and destroy
* all channel ports */
error_out: error_out:
kfree(nd); kfree(nd);
return ret; return ret;

View File

@ -54,23 +54,6 @@ static DEVICE_ATTR(register_with_sysfs, 0400,
dgrp_class_register_with_sysfs_show, NULL); dgrp_class_register_with_sysfs_show, NULL);
static ssize_t dgrp_class_rawreadok_show(struct device *c,
struct device_attribute *attr,
char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", dgrp_rawreadok);
}
static ssize_t dgrp_class_rawreadok_store(struct device *c,
struct device_attribute *attr,
const char *buf, size_t count)
{
sscanf(buf, "0x%x\n", &dgrp_rawreadok);
return count;
}
static DEVICE_ATTR(rawreadok, 0600, dgrp_class_rawreadok_show,
dgrp_class_rawreadok_store);
static ssize_t dgrp_class_pollrate_show(struct device *c, static ssize_t dgrp_class_pollrate_show(struct device *c,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
@ -90,7 +73,6 @@ static DEVICE_ATTR(pollrate, 0600, dgrp_class_pollrate_show,
static struct attribute *dgrp_sysfs_global_settings_entries[] = { static struct attribute *dgrp_sysfs_global_settings_entries[] = {
&dev_attr_pollrate.attr, &dev_attr_pollrate.attr,
&dev_attr_rawreadok.attr,
&dev_attr_register_with_sysfs.attr, &dev_attr_register_with_sysfs.attr,
NULL NULL
}; };

View File

@ -432,7 +432,7 @@ static void drp_param(struct ch_struct *ch)
/* /*
* From the POSIX.1 spec (7.1.2.6): "If {_POSIX_VDISABLE} * From the POSIX.1 spec (7.1.2.6): "If {_POSIX_VDISABLE}
* is defined for the terminal device file, and the value * is defined for the terminal device file, and the value
* of one of the changable special control characters (see * of one of the changeable special control characters (see
* 7.1.1.9) is {_POSIX_VDISABLE}, that function shall be * 7.1.1.9) is {_POSIX_VDISABLE}, that function shall be
* disabled, that is, no input data shall be recognized as * disabled, that is, no input data shall be recognized as
* the disabled special character." * the disabled special character."
@ -2265,9 +2265,7 @@ static int get_modem_info(struct ch_struct *ch, unsigned int *value)
| ((mlast & DM_RI) ? TIOCM_RNG : 0) | ((mlast & DM_RI) ? TIOCM_RNG : 0)
| ((mlast & DM_DSR) ? TIOCM_DSR : 0) | ((mlast & DM_DSR) ? TIOCM_DSR : 0)
| ((mlast & DM_CTS) ? TIOCM_CTS : 0); | ((mlast & DM_CTS) ? TIOCM_CTS : 0);
put_user(mlast, (unsigned int __user *) value); return put_user(mlast, (unsigned int __user *) value);
return 0;
} }
/* /*
@ -2285,7 +2283,8 @@ static int set_modem_info(struct ch_struct *ch, unsigned int command,
if (error == 0) if (error == 0)
return -EFAULT; return -EFAULT;
get_user(arg, (unsigned int __user *) value); if (get_user(arg, (unsigned int __user *) value))
return -EFAULT;
mval |= ((arg & TIOCM_RTS) ? DM_RTS : 0) mval |= ((arg & TIOCM_RTS) ? DM_RTS : 0)
| ((arg & TIOCM_DTR) ? DM_DTR : 0); | ((arg & TIOCM_DTR) ? DM_DTR : 0);
@ -2684,7 +2683,7 @@ static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
- looking at the tty_ioctl code, these command all call our - looking at the tty_ioctl code, these command all call our
tty_set_termios at the driver's end, when a TCSETA* is sent, tty_set_termios at the driver's end, when a TCSETA* is sent,
it is expecting the tty to have a termio structure, it is expecting the tty to have a termio structure,
NOT a termios stucture. These two structures differ in size NOT a termios structure. These two structures differ in size
and the tty_ioctl code does a conversion before processing them both. and the tty_ioctl code does a conversion before processing them both.
- we should treat the TCSETAW TCSETAF ioctls the same, and let - we should treat the TCSETAW TCSETAF ioctls the same, and let
the tty_ioctl code do the conversion stuff. the tty_ioctl code do the conversion stuff.
@ -2836,17 +2835,16 @@ static int dgrp_tty_ioctl(struct tty_struct *tty, unsigned int cmd,
break; break;
case DIGI_GETCUSTOMBAUD: case DIGI_GETCUSTOMBAUD:
rc = access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(int)); if (put_user(ch->ch_custom_speed, (unsigned int __user *) arg))
if (rc == 0)
return -EFAULT; return -EFAULT;
put_user(ch->ch_custom_speed, (unsigned int __user *) arg);
break; break;
case DIGI_SETCUSTOMBAUD: case DIGI_SETCUSTOMBAUD:
{ {
int new_rate; int new_rate;
get_user(new_rate, (unsigned int __user *) arg); if (get_user(new_rate, (unsigned int __user *) arg))
return -EFAULT;
dgrp_set_custom_speed(ch, new_rate); dgrp_set_custom_speed(ch, new_rate);
break; break;
@ -2981,7 +2979,7 @@ static void dgrp_tty_start(struct tty_struct *tty)
} }
/* /*
* Stop the reciever * Stop the receiver
*/ */
static void dgrp_tty_input_stop(struct tty_struct *tty) static void dgrp_tty_input_stop(struct tty_struct *tty)
{ {
@ -3104,6 +3102,7 @@ static void dgrp_tty_hangup(struct tty_struct *tty)
void void
dgrp_tty_uninit(struct nd_struct *nd) dgrp_tty_uninit(struct nd_struct *nd)
{ {
unsigned int i;
char id[3]; char id[3];
ID_TO_CHAR(nd->nd_ID, id); ID_TO_CHAR(nd->nd_ID, id);
@ -3137,6 +3136,8 @@ dgrp_tty_uninit(struct nd_struct *nd)
put_tty_driver(nd->nd_xprint_ttdriver); put_tty_driver(nd->nd_xprint_ttdriver);
nd->nd_ttdriver_flags &= ~XPRINT_TTDRV_REG; nd->nd_ttdriver_flags &= ~XPRINT_TTDRV_REG;
} }
for (i = 0; i < CHAN_MAX; i++)
tty_port_destroy(&nd->nd_chan[i].port);
} }
@ -3320,7 +3321,6 @@ dgrp_tty_init(struct nd_struct *nd)
init_waitqueue_head(&(ch->ch_pun.un_open_wait)); init_waitqueue_head(&(ch->ch_pun.un_open_wait));
init_waitqueue_head(&(ch->ch_pun.un_close_wait)); init_waitqueue_head(&(ch->ch_pun.un_close_wait));
tty_port_init(&ch->port); tty_port_init(&ch->port);
tty_port_init(&ch->port);
} }
return 0; return 0;
} }

View File

@ -939,14 +939,9 @@ static void fwserial_destroy(struct kref *kref)
mutex_lock(&port_table_lock); mutex_lock(&port_table_lock);
for (j = 0; j < num_ports; ++i, ++j) { for (j = 0; j < num_ports; ++i, ++j) {
static bool once; port_table_corrupt |= port_table[i] != ports[j];
int corrupt = port_table[i] != ports[j]; WARN_ONCE(port_table_corrupt, "port_table[%d]: %p != ports[%d]: %p",
if (corrupt && !once) { i, port_table[i], j, ports[j]);
WARN(corrupt, "port_table[%d]: %p != ports[%d]: %p",
i, port_table[i], j, ports[j]);
once = true;
port_table_corrupt = true;
}
port_table[i] = NULL; port_table[i] = NULL;
} }
@ -954,7 +949,7 @@ static void fwserial_destroy(struct kref *kref)
for (j = 0; j < num_ports; ++j) { for (j = 0; j < num_ports; ++j) {
fw_core_remove_address_handler(&ports[j]->rx_handler); fw_core_remove_address_handler(&ports[j]->rx_handler);
dma_fifo_free(&ports[j]->tx_fifo); tty_port_destroy(&ports[j]->port);
kfree(ports[j]); kfree(ports[j]);
} }
kfree(serial); kfree(serial);
@ -2369,8 +2364,10 @@ unregister_ttys:
return err; return err;
free_ports: free_ports:
for (--i; i >= 0; --i) for (--i; i >= 0; --i) {
tty_port_destroy(&serial->ports[i]->port);
kfree(serial->ports[i]); kfree(serial->ports[i]);
}
kfree(serial); kfree(serial);
return err; return err;
} }

View File

@ -0,0 +1,9 @@
config SB105X
tristate "SystemBase PCI Multiport UART"
select SERIAL_CORE
depends on PCI
help
A driver for the SystemBase Multi-2/PCI serial card
To compile this driver a module, choose M here: the module
will be called "sb105x".

View File

@ -0,0 +1,3 @@
obj-$(CONFIG_SB105X) += sb105x.o
sb105x-y := sb_pci_mp.o

View File

@ -0,0 +1,295 @@
/*
* SB105X_UART.h
*
* Copyright (C) 2008 systembase
*
* UART registers.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef UART_SB105X_H
#define UART_SB105X_H
/*
* option register
*/
/* Device Infomation Register */
#define MP_OPTR_DIR0 0x04 /* port0 ~ port8 */
#define MP_OPTR_DIR1 0x05 /* port8 ~ port15 */
#define MP_OPTR_DIR2 0x06 /* port16 ~ port23 */
#define MP_OPTR_DIR3 0x07 /* port24 ~ port31 */
#define DIR_UART_16C550 0
#define DIR_UART_16C1050 1
#define DIR_UART_16C1050A 2
#define DIR_CLK_1843200 0x0 /* input clock 1843200 Hz */
#define DIR_CLK_3686400 0x1 /* input clock 3686400 Hz */
#define DIR_CLK_7372800 0x2 /* input clock 7372800 Hz */
#define DIR_CLK_14745600 0x3 /* input clock 14745600 Hz */
#define DIR_CLK_29491200 0x4 /* input clock 29491200 Hz */
#define DIR_CLK_58985400 0x5 /* input clock 58985400 Hz */
/* Interface Information Register */
#define MP_OPTR_IIR0 0x08 /* port0 ~ port8 */
#define MP_OPTR_IIR1 0x09 /* port8 ~ port15 */
#define MP_OPTR_IIR2 0x0A /* port16 ~ port23 */
#define MP_OPTR_IIR3 0x0B /* port24 ~ port31 */
#define IIR_RS232 0x00 /* RS232 type */
#define IIR_RS422 0x10 /* RS422 type */
#define IIR_RS485 0x20 /* RS485 type */
#define IIR_UNKNOWN 0x30 /* unknown type */
/* Interrrupt Mask Register */
#define MP_OPTR_IMR0 0x0C /* port0 ~ port8 */
#define MP_OPTR_IMR1 0x0D /* port8 ~ port15 */
#define MP_OPTR_IMR2 0x0E /* port16 ~ port23 */
#define MP_OPTR_IMR3 0x0F /* port24 ~ port31 */
/* Interrupt Poll Register */
#define MP_OPTR_IPR0 0x10 /* port0 ~ port8 */
#define MP_OPTR_IPR1 0x11 /* port8 ~ port15 */
#define MP_OPTR_IPR2 0x12 /* port16 ~ port23 */
#define MP_OPTR_IPR3 0x13 /* port24 ~ port31 */
/* General Purpose Output Control Register */
#define MP_OPTR_GPOCR 0x20
/* General Purpose Output Data Register */
#define MP_OPTR_GPODR 0x21
/* Parallel Additional Function Register */
#define MP_OPTR_PAFR 0x23
/*
* systembase 16c105x UART register
*/
#define PAGE_0 0
#define PAGE_1 1
#define PAGE_2 2
#define PAGE_3 3
#define PAGE_4 4
/*
* ******************************************************************
* * DLAB=0 =============== Page 0 Registers *
* ******************************************************************
*/
#define SB105X_RX 0 /* In: Receive buffer */
#define SB105X_TX 0 /* Out: Transmit buffer */
#define SB105X_IER 1 /* Out: Interrupt Enable Register */
#define SB105X_IER_CTSI 0x80 /* CTS# Interrupt Enable (Requires EFR[4] = 1) */
#define SB105X_IER_RTSI 0x40 /* RTS# Interrupt Enable (Requires EFR[4] = 1) */
#define SB105X_IER_XOI 0x20 /* Xoff Interrupt Enable (Requires EFR[4] = 1) */
#define SB105X_IER_SME 0x10 /* Sleep Mode Enable (Requires EFR[4] = 1) */
#define SB105X_IER_MSI 0x08 /* Enable Modem status interrupt */
#define SB105X_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define SB105X_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define SB105X_IER_RDI 0x01 /* Enable receiver data interrupt */
#define SB105X_ISR 2 /* In: Interrupt ID Register */
#define SB105X_ISR_NOINT 0x01 /* No interrupts pending */
#define SB105X_ISR_RLSI 0x06 /* Receiver line status interrupt (Priority = 1)*/
#define SB105X_ISR_RDAI 0x0c /* Receive Data Available interrupt */
#define SB105X_ISR_CTII 0x04 /* Character Timeout Indication interrupt */
#define SB105X_ISR_THRI 0x02 /* Transmitter holding register empty */
#define SB105X_ISR_MSI 0x00 /* Modem status interrupt */
#define SB105X_ISR_RXCI 0x10 /* Receive Xoff or Special Character interrupt */
#define SB105X_ISR_RCSI 0x20 /* RTS#, CTS# status interrupt during Auto RTS/CTS flow control */
#define SB105X_FCR 2 /* Out: FIFO Control Register */
#define SB105X_FCR_FEN 0x01 /* FIFO Enable */
#define SB105X_FCR_RXFR 0x02 /* RX FIFO Reset */
#define SB105X_FCR_TXFR 0x04 /* TX FIFO Reset */
#define SB105X_FCR_DMS 0x08 /* DMA Mode Select */
#define SB105X_FCR_RTR08 0x00 /* Receice Trigger Level set at 8 */
#define SB105X_FCR_RTR16 0x40 /* Receice Trigger Level set at 16 */
#define SB105X_FCR_RTR56 0x80 /* Receice Trigger Level set at 56 */
#define SB105X_FCR_RTR60 0xc0 /* Receice Trigger Level set at 60 */
#define SB105X_FCR_TTR08 0x00 /* Transmit Trigger Level set at 8 */
#define SB105X_FCR_TTR16 0x10 /* Transmit Trigger Level set at 16 */
#define SB105X_FCR_TTR32 0x20 /* Transmit Trigger Level set at 32 */
#define SB105X_FCR_TTR56 0x30 /* Transmit Trigger Level set at 56 */
#define SB105X_LCR 3 /* Out: Line Control Register */
/*
* * Note: if the word length is 5 bits (SB105X_LCR_WLEN5), then setting
* * SB105X_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
*/
#define SB105X_LCR_DLAB 0x80 /* Divisor Latch Enable */
#define SB105X_LCR_SBC 0x40 /* Break Enable*/
#define SB105X_LCR_SPAR 0x20 /* Set Stick parity */
#define SB105X_LCR_EPAR 0x10 /* Even parity select */
#define SB105X_LCR_PAREN 0x08 /* Parity Enable */
#define SB105X_LCR_STOP 0x04 /* Stop bits: 0->1 bit, 1->2 bits, 1 and SB105X_LCR_WLEN5 -> 1.5 bit */
#define SB105X_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
#define SB105X_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
#define SB105X_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
#define SB105X_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
#define SB105X_LCR_BF 0xBF
#define SB105X_MCR 4 /* Out: Modem Control Register */
#define SB105X_MCR_CPS 0x80 /* Clock Prescaler Select */
#define SB105X_MCR_P2S 0x40 /* Page 2 Select /Xoff Re-Transmit Access Enable */
#define SB105X_MCR_XOA 0x20 /* Xon Any Enable */
#define SB105X_MCR_ILB 0x10 /* Internal Loopback Enable */
#define SB105X_MCR_OUT2 0x08 /* Out2/Interrupt Output Enable*/
#define SB105X_MCR_OUT1 0x04 /* Out1/Interrupt Output Enable */
#define SB105X_MCR_RTS 0x02 /* RTS# Output */
#define SB105X_MCR_DTR 0x01 /* DTR# Output */
#define SB105X_LSR 5 /* In: Line Status Register */
#define SB105X_LSR_RFEI 0x80 /* Receive FIFO data error Indicator */
#define SB105X_LSR_TEMI 0x40 /* THR and TSR Empty Indicator */
#define SB105X_LSR_THRE 0x20 /* THR Empty Indicator */
#define SB105X_LSR_BII 0x10 /* Break interrupt indicator */
#define SB105X_LSR_FEI 0x08 /* Frame error indicator */
#define SB105X_LSR_PEI 0x04 /* Parity error indicator */
#define SB105X_LSR_OEI 0x02 /* Overrun error indicator */
#define SB105X_LSR_RDRI 0x01 /* Receive data ready Indicator*/
#define SB105X_MSR 6 /* In: Modem Status Register */
#define SB105X_MSR_DCD 0x80 /* Data Carrier Detect */
#define SB105X_MSR_RI 0x40 /* Ring Indicator */
#define SB105X_MSR_DSR 0x20 /* Data Set Ready */
#define SB105X_MSR_CTS 0x10 /* Clear to Send */
#define SB105X_MSR_DDCD 0x08 /* Delta DCD */
#define SB105X_MSR_DRI 0x04 /* Delta ring indicator */
#define SB105X_MSR_DDSR 0x02 /* Delta DSR */
#define SB105X_MSR_DCTS 0x01 /* Delta CTS */
#define SB105XA_MDR 6 /* Out: Multi Drop mode Register */
#define SB105XA_MDR_NPS 0x08 /* 9th Bit Polarity Select */
#define SB105XA_MDR_AME 0x02 /* Auto Multi-drop Enable */
#define SB105XA_MDR_MDE 0x01 /* Multi Drop Enable */
#define SB105X_SPR 7 /* I/O: Scratch Register */
/*
* DLAB=1
*/
#define SB105X_DLL 0 /* Out: Divisor Latch Low */
#define SB105X_DLM 1 /* Out: Divisor Latch High */
/*
* ******************************************************************
* * DLAB(LCR[7]) = 0 , MCR[6] = 1 ============= Page 2 Registers *
* ******************************************************************
*/
#define SB105X_GICR 1 /* Global Interrupt Control Register */
#define SB105X_GICR_GIM 0x01 /* Global Interrupt Mask */
#define SB105X_GISR 2 /* Global Interrupt Status Register */
#define SB105X_GISR_MGICR0 0x80 /* Mirror the content of GICR[0] */
#define SB105X_GISR_CS3IS 0x08 /* SB105X of CS3# Interrupt Status */
#define SB105X_GISR_CS2IS 0x04 /* SB105X of CS2# Interrupt Status */
#define SB105X_GISR_CS1IS 0x02 /* SB105X of CS1# Interrupt Status */
#define SB105X_GISR_CS0IS 0x01 /* SB105X of CS0# Interrupt Status */
#define SB105X_TFCR 5 /* Transmit FIFO Count Register */
#define SB105X_RFCR 6 /* Receive FIFO Count Register */
#define SB105X_FSR 7 /* Flow Control Status Register */
#define SB105X_FSR_THFS 0x20 /* Transmit Hardware Flow Control Status */
#define SB105X_FSR_TSFS 0x10 /* Transmit Software Flow Control Status */
#define SB105X_FSR_RHFS 0x02 /* Receive Hardware Flow Control Status */
#define SB105X_FSR_RSFS 0x01 /* Receive Software Flow Control Status */
/*
* ******************************************************************
* * LCR = 0xBF, PSR[0] = 0 ============= Page 3 Registers *
* ******************************************************************
*/
#define SB105X_PSR 0 /* Page Select Register */
#define SB105X_PSR_P3KEY 0xA4 /* Page 3 Select Key */
#define SB105X_PSR_P4KEY 0xA5 /* Page 5 Select Key */
#define SB105X_ATR 1 /* Auto Toggle Control Register */
#define SB105X_ATR_RPS 0x80 /* RXEN Polarity Select */
#define SB105X_ATR_RCMS 0x40 /* RXEN Control Mode Select */
#define SB105X_ATR_TPS 0x20 /* TXEN Polarity Select */
#define SB105X_ATR_TCMS 0x10 /* TXEN Control Mode Select */
#define SB105X_ATR_ATDIS 0x00 /* Auto Toggle is disabled */
#define SB105X_ATR_ART 0x01 /* RTS#/TXEN pin operates as TXEN */
#define SB105X_ATR_ADT 0x02 /* DTR#/TXEN pin operates as TXEN */
#define SB105X_ATR_A80 0x03 /* only in 80 pin use */
#define SB105X_EFR 2 /* (Auto) Enhanced Feature Register */
#define SB105X_EFR_ACTS 0x80 /* Auto-CTS Flow Control Enable */
#define SB105X_EFR_ARTS 0x40 /* Auto-RTS Flow Control Enable */
#define SB105X_EFR_SCD 0x20 /* Special Character Detect */
#define SB105X_EFR_EFBEN 0x10 /* Enhanced Function Bits Enable */
#define SB105X_XON1 4 /* Xon1 Character Register */
#define SB105X_XON2 5 /* Xon2 Character Register */
#define SB105X_XOFF1 6 /* Xoff1 Character Register */
#define SB105X_XOFF2 7 /* Xoff2 Character Register */
/*
* ******************************************************************
* * LCR = 0xBF, PSR[0] = 1 ============ Page 4 Registers *
* ******************************************************************
*/
#define SB105X_AFR 1 /* Additional Feature Register */
#define SB105X_AFR_GIPS 0x20 /* Global Interrupt Polarity Select */
#define SB105X_AFR_GIEN 0x10 /* Global Interrupt Enable */
#define SB105X_AFR_AFEN 0x01 /* 256-byte FIFO Enable */
#define SB105X_XRCR 2 /* Xoff Re-transmit Count Register */
#define SB105X_XRCR_NRC1 0x00 /* Transmits Xoff Character whenever the number of received data is 1 during XOFF status */
#define SB105X_XRCR_NRC4 0x01 /* Transmits Xoff Character whenever the number of received data is 4 during XOFF status */
#define SB105X_XRCR_NRC8 0x02 /* Transmits Xoff Character whenever the number of received data is 8 during XOFF status */
#define SB105X_XRCR_NRC16 0x03 /* Transmits Xoff Character whenever the number of received data is 16 during XOFF status */
#define SB105X_TTR 4 /* Transmit FIFO Trigger Level Register */
#define SB105X_RTR 5 /* Receive FIFO Trigger Level Register */
#define SB105X_FUR 6 /* Flow Control Upper Threshold Register */
#define SB105X_FLR 7 /* Flow Control Lower Threshold Register */
/* page 0 */
#define SB105X_GET_CHAR(port) inb((port)->iobase + SB105X_RX)
#define SB105X_GET_IER(port) inb((port)->iobase + SB105X_IER)
#define SB105X_GET_ISR(port) inb((port)->iobase + SB105X_ISR)
#define SB105X_GET_LCR(port) inb((port)->iobase + SB105X_LCR)
#define SB105X_GET_MCR(port) inb((port)->iobase + SB105X_MCR)
#define SB105X_GET_LSR(port) inb((port)->iobase + SB105X_LSR)
#define SB105X_GET_MSR(port) inb((port)->iobase + SB105X_MSR)
#define SB105X_GET_SPR(port) inb((port)->iobase + SB105X_SPR)
#define SB105X_PUT_CHAR(port,v) outb((v),(port)->iobase + SB105X_TX )
#define SB105X_PUT_IER(port,v) outb((v),(port)->iobase + SB105X_IER )
#define SB105X_PUT_FCR(port,v) outb((v),(port)->iobase + SB105X_FCR )
#define SB105X_PUT_LCR(port,v) outb((v),(port)->iobase + SB105X_LCR )
#define SB105X_PUT_MCR(port,v) outb((v),(port)->iobase + SB105X_MCR )
#define SB105X_PUT_SPR(port,v) outb((v),(port)->iobase + SB105X_SPR )
/* page 1 */
#define SB105X_GET_REG(port,reg) inb((port)->iobase + (reg))
#define SB105X_PUT_REG(port,reg,v) outb((v),(port)->iobase + (reg))
/* page 2 */
#define SB105X_PUT_PSR(port,v) outb((v),(port)->iobase + SB105X_PSR )
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,293 @@
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/tty_driver.h>
#include <linux/pci.h>
#include <linux/circ_buf.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/segment.h>
#include <asm/serial.h>
#include <linux/interrupt.h>
#include <linux/parport.h>
#include <linux/ctype.h>
#include <linux/poll.h>
#define MP_TERMIOS ktermios
#include "sb_mp_register.h"
#include "sb_ser_core.h"
#define DRIVER_VERSION "1.1"
#define DRIVER_DATE "2012/01/05"
#define DRIVER_AUTHOR "SYSTEMBASE<tech@sysbas.com>"
#define DRIVER_DESC "SystemBase PCI/PCIe Multiport Core"
#define SB_TTY_MP_MAJOR 54
#define PCI_VENDOR_ID_MULTIPORT 0x14A1
#define PCI_DEVICE_ID_MP1 0x4d01
#define PCI_DEVICE_ID_MP2 0x4d02
#define PCI_DEVICE_ID_MP4 0x4d04
#define PCI_DEVICE_ID_MP4A 0x4d54
#define PCI_DEVICE_ID_MP6 0x4d06
#define PCI_DEVICE_ID_MP6A 0x4d56
#define PCI_DEVICE_ID_MP8 0x4d08
#define PCI_DEVICE_ID_MP32 0x4d32
/* Parallel port */
#define PCI_DEVICE_ID_MP1P 0x4301
#define PCI_DEVICE_ID_MP2S1P 0x4303
#define PCIE_DEVICE_ID_MP1 0x4501
#define PCIE_DEVICE_ID_MP2 0x4502
#define PCIE_DEVICE_ID_MP4 0x4504
#define PCIE_DEVICE_ID_MP8 0x4508
#define PCIE_DEVICE_ID_MP32 0x4532
#define PCIE_DEVICE_ID_MP1E 0x4e01
#define PCIE_DEVICE_ID_MP2E 0x4e02
#define PCIE_DEVICE_ID_MP2B 0x4b02
#define PCIE_DEVICE_ID_MP4B 0x4b04
#define PCIE_DEVICE_ID_MP8B 0x4b08
#define PCI_DEVICE_ID_GT_MP4 0x0004
#define PCI_DEVICE_ID_GT_MP4A 0x0054
#define PCI_DEVICE_ID_GT_MP6 0x0006
#define PCI_DEVICE_ID_GT_MP6A 0x0056
#define PCI_DEVICE_ID_GT_MP8 0x0008
#define PCI_DEVICE_ID_GT_MP32 0x0032
#define PCIE_DEVICE_ID_GT_MP1 0x1501
#define PCIE_DEVICE_ID_GT_MP2 0x1502
#define PCIE_DEVICE_ID_GT_MP4 0x1504
#define PCIE_DEVICE_ID_GT_MP8 0x1508
#define PCIE_DEVICE_ID_GT_MP32 0x1532
#define PCI_DEVICE_ID_MP4M 0x4604 //modem
#define MAX_MP_DEV 8
#define BD_MAX_PORT 32 /* Max serial port in one board */
#define MAX_MP_PORT 256 /* Max serial port in one PC */
#define PORT_16C105XA 3
#define PORT_16C105X 2
#define PORT_16C55X 1
#define ENABLE 1
#define DISABLE 0
/* ioctls */
#define TIOCGNUMOFPORT 0x545F
#define TIOCSMULTIECHO 0x5440
#define TIOCSPTPNOECHO 0x5441
#define TIOCGOPTIONREG 0x5461
#define TIOCGDISABLEIRQ 0x5462
#define TIOCGENABLEIRQ 0x5463
#define TIOCGSOFTRESET 0x5464
#define TIOCGSOFTRESETR 0x5465
#define TIOCGREGINFO 0x5466
#define TIOCGGETLSR 0x5467
#define TIOCGGETDEVID 0x5468
#define TIOCGGETBDNO 0x5469
#define TIOCGGETINTERFACE 0x546A
#define TIOCGGETREV 0x546B
#define TIOCGGETNRPORTS 0x546C
#define TIOCGGETPORTTYPE 0x546D
#define GETDEEPFIFO 0x54AA
#define SETDEEPFIFO 0x54AB
#define SETFCR 0x54BA
#define SETTTR 0x54B1
#define SETRTR 0x54B2
#define GETTTR 0x54B3
#define GETRTR 0x54B4
/* multi-drop mode related ioctl commands */
#define TIOCSMULTIDROP 0x5470
#define TIOCSMDADDR 0x5471
#define TIOCGMDADDR 0x5472
#define TIOCSENDADDR 0x5473
/* serial interface */
#define RS232 1
#define RS422PTP 2
#define RS422MD 3
#define RS485NE 4
#define RS485ECHO 5
#define serial_inp(up, offset) serial_in(up, offset)
#define serial_outp(up, offset, value) serial_out(up, offset, value)
#define PASS_LIMIT 256
#define is_real_interrupt(irq) ((irq) != 0)
#define PROBE_ANY (~0)
static DEFINE_MUTEX(mp_mutex);
#define MP_MUTEX_LOCK(x) mutex_lock(&(x))
#define MP_MUTEX_UNLOCK(x) mutex_unlock(&(x))
#define MP_STATE_LOCK(x) mutex_lock(&((x)->mutex))
#define MP_STATE_UNLOCK(x) mutex_unlock(&((x)->mutex))
#define UART_LSR_SPECIAL 0x1E
#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0))
//#define MP_DEBUG 1
#undef MP_DEBUG
#ifdef MP_DEBUG
#define DPRINTK(x...) printk(x)
#else
#define DPRINTK(x...) do { } while (0)
#endif
#ifdef MP_DEBUG
#define DEBUG_AUTOCONF(fmt...) printk(fmt)
#else
#define DEBUG_AUTOCONF(fmt...) do { } while (0)
#endif
#ifdef MP_DEBUG
#define DEBUG_INTR(fmt...) printk(fmt)
#else
#define DEBUG_INTR(fmt...) do { } while (0)
#endif
#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
#define SERIAL_INLINE
#endif
#ifdef SERIAL_INLINE
#define _INLINE_ inline
#else
#define _INLINE_
#endif
#define TYPE_POLL 1
#define TYPE_INTERRUPT 2
struct mp_device_t {
unsigned short device_id;
unsigned char revision;
char *name;
unsigned long uart_access_addr;
unsigned long option_reg_addr;
unsigned long reserved_addr[4];
int irq;
int nr_ports;
int poll_type;
};
typedef struct mppcibrd {
char *name;
unsigned short vendor_id;
unsigned short device_id;
} mppcibrd_t;
static mppcibrd_t mp_pciboards[] = {
{ "Multi-1 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1} ,
{ "Multi-2 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2} ,
{ "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4} ,
{ "Multi-4 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4A} ,
{ "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6} ,
{ "Multi-6 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP6A} ,
{ "Multi-8 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP8} ,
{ "Multi-32 PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP32} ,
{ "Multi-1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP1P} ,
{ "Multi-2S1P PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP2S1P} ,
{ "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4} ,
{ "Multi-4(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP4A} ,
{ "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6} ,
{ "Multi-6(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP6A} ,
{ "Multi-8(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP8} ,
{ "Multi-32(GT) PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_GT_MP32} ,
{ "Multi-1 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1} ,
{ "Multi-2 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2} ,
{ "Multi-4 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4} ,
{ "Multi-8 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8} ,
{ "Multi-32 PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP32} ,
{ "Multi-1 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP1E} ,
{ "Multi-2 PCIe E", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2E} ,
{ "Multi-2 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP2B} ,
{ "Multi-4 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP4B} ,
{ "Multi-8 PCIe B", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_MP8B} ,
{ "Multi-1(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP1} ,
{ "Multi-2(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP2} ,
{ "Multi-4(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP4} ,
{ "Multi-8(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP8} ,
{ "Multi-32(GT) PCIe", PCI_VENDOR_ID_MULTIPORT , PCIE_DEVICE_ID_GT_MP32} ,
{ "Multi-4M PCI", PCI_VENDOR_ID_MULTIPORT , PCI_DEVICE_ID_MP4M} ,
};
struct mp_port {
struct sb_uart_port port;
struct timer_list timer; /* "no irq" timer */
struct list_head list; /* ports on this IRQ */
unsigned int capabilities; /* port capabilities */
unsigned short rev;
unsigned char acr;
unsigned char ier;
unsigned char lcr;
unsigned char mcr;
unsigned char mcr_mask; /* mask of user bits */
unsigned char mcr_force; /* mask of forced bits */
unsigned char lsr_break_flag;
void (*pm)(struct sb_uart_port *port,
unsigned int state, unsigned int old);
struct mp_device_t *device;
unsigned long interface_config_addr;
unsigned long option_base_addr;
unsigned char interface;
unsigned char poll_type;
};
struct irq_info {
spinlock_t lock;
struct list_head *head;
};
struct sb105x_uart_config {
char *name;
int dfl_xmit_fifo_size;
int flags;
};
static const struct sb105x_uart_config uart_config[] = {
{ "unknown", 1, 0 },
{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
{ "SB16C1050", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
{ "SB16C1050A", 128, UART_CLEAR_FIFO | UART_USE_FIFO | UART_STARTECH },
};

View File

@ -0,0 +1,368 @@
#include <linux/wait.h>
#define UART_CONFIG_TYPE (1 << 0)
#define UART_CONFIG_IRQ (1 << 1)
#define UPIO_PORT (0)
#define UPIO_HUB6 (1)
#define UPIO_MEM (2)
#define UPIO_MEM32 (3)
#define UPIO_AU (4) /* Au1x00 type IO */
#define UPIO_TSI (5) /* Tsi108/109 type IO */
#define UPF_FOURPORT (1 << 1)
#define UPF_SAK (1 << 2)
#define UPF_SPD_MASK (0x1030)
#define UPF_SPD_HI (0x0010)
#define UPF_SPD_VHI (0x0020)
#define UPF_SPD_CUST (0x0030)
#define UPF_SPD_SHI (0x1000)
#define UPF_SPD_WARP (0x1010)
#define UPF_SKIP_TEST (1 << 6)
#define UPF_AUTO_IRQ (1 << 7)
#define UPF_HARDPPS_CD (1 << 11)
#define UPF_LOW_LATENCY (1 << 13)
#define UPF_BUGGY_UART (1 << 14)
#define UPF_MAGIC_MULTIPLIER (1 << 16)
#define UPF_CONS_FLOW (1 << 23)
#define UPF_SHARE_IRQ (1 << 24)
#define UPF_BOOT_AUTOCONF (1 << 28)
#define UPF_DEAD (1 << 30)
#define UPF_IOREMAP (1 << 31)
#define UPF_CHANGE_MASK (0x17fff)
#define UPF_USR_MASK (UPF_SPD_MASK|UPF_LOW_LATENCY)
#define USF_CLOSING_WAIT_INF (0)
#define USF_CLOSING_WAIT_NONE (~0U)
#define UART_XMIT_SIZE PAGE_SIZE
#define UIF_CHECK_CD (1 << 25)
#define UIF_CTS_FLOW (1 << 26)
#define UIF_NORMAL_ACTIVE (1 << 29)
#define UIF_INITIALIZED (1 << 31)
#define UIF_SUSPENDED (1 << 30)
#define WAKEUP_CHARS 256
#define uart_circ_empty(circ) ((circ)->head == (circ)->tail)
#define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
#define uart_circ_chars_pending(circ) \
(CIRC_CNT((circ)->head, (circ)->tail, UART_XMIT_SIZE))
#define uart_circ_chars_free(circ) \
(CIRC_SPACE((circ)->head, (circ)->tail, UART_XMIT_SIZE))
#define uart_tx_stopped(port) \
((port)->info->tty->stopped || (port)->info->tty->hw_stopped)
#define UART_ENABLE_MS(port,cflag) ((port)->flags & UPF_HARDPPS_CD || \
(cflag) & CRTSCTS || \
!((cflag) & CLOCAL))
struct sb_uart_port;
struct sb_uart_info;
struct serial_struct;
struct device;
struct sb_uart_ops {
unsigned int (*tx_empty)(struct sb_uart_port *);
void (*set_mctrl)(struct sb_uart_port *, unsigned int mctrl);
unsigned int (*get_mctrl)(struct sb_uart_port *);
void (*stop_tx)(struct sb_uart_port *);
void (*start_tx)(struct sb_uart_port *);
void (*send_xchar)(struct sb_uart_port *, char ch);
void (*stop_rx)(struct sb_uart_port *);
void (*enable_ms)(struct sb_uart_port *);
void (*break_ctl)(struct sb_uart_port *, int ctl);
int (*startup)(struct sb_uart_port *);
void (*shutdown)(struct sb_uart_port *);
void (*set_termios)(struct sb_uart_port *, struct MP_TERMIOS *new,
struct MP_TERMIOS *old);
void (*pm)(struct sb_uart_port *, unsigned int state,
unsigned int oldstate);
int (*set_wake)(struct sb_uart_port *, unsigned int state);
const char *(*type)(struct sb_uart_port *);
void (*release_port)(struct sb_uart_port *);
int (*request_port)(struct sb_uart_port *);
void (*config_port)(struct sb_uart_port *, int);
int (*verify_port)(struct sb_uart_port *, struct serial_struct *);
int (*ioctl)(struct sb_uart_port *, unsigned int, unsigned long);
};
struct sb_uart_icount {
__u32 cts;
__u32 dsr;
__u32 rng;
__u32 dcd;
__u32 rx;
__u32 tx;
__u32 frame;
__u32 overrun;
__u32 parity;
__u32 brk;
__u32 buf_overrun;
};
typedef unsigned int upf_t;
struct sb_uart_port {
spinlock_t lock; /* port lock */
unsigned int iobase; /* in/out[bwl] */
unsigned char __iomem *membase; /* read/write[bwl] */
unsigned int irq; /* irq number */
unsigned int uartclk; /* base uart clock */
unsigned int fifosize; /* tx fifo size */
unsigned char x_char; /* xon/xoff char */
unsigned char regshift; /* reg offset shift */
unsigned char iotype; /* io access style */
unsigned char unused1;
unsigned int read_status_mask; /* driver specific */
unsigned int ignore_status_mask; /* driver specific */
struct sb_uart_info *info; /* pointer to parent info */
struct sb_uart_icount icount; /* statistics */
struct console *cons; /* struct console, if any */
#ifdef CONFIG_SERIAL_CORE_CONSOLE
unsigned long sysrq; /* sysrq timeout */
#endif
upf_t flags;
unsigned int mctrl; /* current modem ctrl settings */
unsigned int timeout; /* character-based timeout */
unsigned int type; /* port type */
const struct sb_uart_ops *ops;
unsigned int custom_divisor;
unsigned int line; /* port index */
unsigned long mapbase; /* for ioremap */
struct device *dev; /* parent device */
unsigned char hub6; /* this should be in the 8250 driver */
unsigned char unused[3];
};
#define mdmode unused[2]
#define MDMODE_ADDR 0x1
#define MDMODE_ENABLE 0x2
#define MDMODE_AUTO 0x4
#define MDMODE_ADDRSEND 0x8
struct sb_uart_state {
unsigned int close_delay; /* msec */
unsigned int closing_wait; /* msec */
int count;
int pm_state;
struct sb_uart_info *info;
struct sb_uart_port *port;
struct mutex mutex;
};
typedef unsigned int uif_t;
struct sb_uart_info {
struct tty_struct *tty;
struct circ_buf xmit;
uif_t flags;
int blocked_open;
struct tasklet_struct tlet;
wait_queue_head_t open_wait;
wait_queue_head_t delta_msr_wait;
};
struct module;
struct tty_driver;
struct uart_driver {
struct module *owner;
const char *driver_name;
const char *dev_name;
int major;
int minor;
int nr;
struct console *cons;
struct sb_uart_state *state;
struct tty_driver *tty_driver;
};
void sb_uart_write_wakeup(struct sb_uart_port *port)
{
struct sb_uart_info *info = port->info;
tasklet_schedule(&info->tlet);
}
void sb_uart_update_timeout(struct sb_uart_port *port, unsigned int cflag,
unsigned int baud)
{
unsigned int bits;
switch (cflag & CSIZE)
{
case CS5:
bits = 7;
break;
case CS6:
bits = 8;
break;
case CS7:
bits = 9;
break;
default:
bits = 10;
break;
}
if (cflag & CSTOPB)
{
bits++;
}
if (cflag & PARENB)
{
bits++;
}
bits = bits * port->fifosize;
port->timeout = (HZ * bits) / baud + HZ/50;
}
unsigned int sb_uart_get_baud_rate(struct sb_uart_port *port, struct MP_TERMIOS *termios,
struct MP_TERMIOS *old, unsigned int min,
unsigned int max)
{
unsigned int try, baud, altbaud = 38400;
upf_t flags = port->flags & UPF_SPD_MASK;
if (flags == UPF_SPD_HI)
altbaud = 57600;
if (flags == UPF_SPD_VHI)
altbaud = 115200;
if (flags == UPF_SPD_SHI)
altbaud = 230400;
if (flags == UPF_SPD_WARP)
altbaud = 460800;
for (try = 0; try < 2; try++) {
switch (termios->c_cflag & (CBAUD | CBAUDEX))
{
case B921600 : baud = 921600; break;
case B460800 : baud = 460800; break;
case B230400 : baud = 230400; break;
case B115200 : baud = 115200; break;
case B57600 : baud = 57600; break;
case B38400 : baud = 38400; break;
case B19200 : baud = 19200; break;
case B9600 : baud = 9600; break;
case B4800 : baud = 4800; break;
case B2400 : baud = 2400; break;
case B1800 : baud = 1800; break;
case B1200 : baud = 1200; break;
case B600 : baud = 600; break;
case B300 : baud = 300; break;
case B200 : baud = 200; break;
case B150 : baud = 150; break;
case B134 : baud = 134; break;
case B110 : baud = 110; break;
case B75 : baud = 75; break;
case B50 : baud = 50; break;
default : baud = 9600; break;
}
if (baud == 38400)
baud = altbaud;
if (baud == 0)
baud = 9600;
if (baud >= min && baud <= max)
return baud;
termios->c_cflag &= ~CBAUD;
if (old) {
termios->c_cflag |= old->c_cflag & CBAUD;
old = NULL;
continue;
}
termios->c_cflag |= B9600;
}
return 0;
}
unsigned int sb_uart_get_divisor(struct sb_uart_port *port, unsigned int baud)
{
unsigned int quot;
if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST)
quot = port->custom_divisor;
else
quot = (port->uartclk + (8 * baud)) / (16 * baud);
return quot;
}
static inline int sb_uart_handle_break(struct sb_uart_port *port)
{
struct sb_uart_info *info = port->info;
if (port->flags & UPF_SAK)
do_SAK(info->tty);
return 0;
}
static inline void sb_uart_handle_dcd_change(struct sb_uart_port *port, unsigned int status)
{
struct sb_uart_info *info = port->info;
port->icount.dcd++;
if (info->flags & UIF_CHECK_CD) {
if (status)
wake_up_interruptible(&info->open_wait);
else if (info->tty)
tty_hangup(info->tty);
}
}
static inline void sb_uart_handle_cts_change(struct sb_uart_port *port, unsigned int status)
{
struct sb_uart_info *info = port->info;
struct tty_struct *tty = info->tty;
port->icount.cts++;
if (info->flags & UIF_CTS_FLOW) {
if (tty->hw_stopped) {
if (status) {
tty->hw_stopped = 0;
port->ops->start_tx(port);
sb_uart_write_wakeup(port);
}
} else {
if (!status) {
tty->hw_stopped = 1;
port->ops->stop_tx(port);
}
}
}
}

View File

@ -1771,6 +1771,7 @@ fail_free_irq:
fail_unregister: fail_unregister:
tty_unregister_driver(serial_driver); tty_unregister_driver(serial_driver);
fail_put_tty_driver: fail_put_tty_driver:
tty_port_destroy(&state->tport);
put_tty_driver(serial_driver); put_tty_driver(serial_driver);
return error; return error;
} }
@ -1785,6 +1786,7 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
printk("SERIAL: failed to unregister serial driver (%d)\n", printk("SERIAL: failed to unregister serial driver (%d)\n",
error); error);
put_tty_driver(serial_driver); put_tty_driver(serial_driver);
tty_port_destroy(&state->tport);
free_irq(IRQ_AMIGA_TBE, state); free_irq(IRQ_AMIGA_TBE, state);
free_irq(IRQ_AMIGA_RBF, state); free_irq(IRQ_AMIGA_RBF, state);

View File

@ -240,8 +240,6 @@ static int __init bfin_jc_init(void)
{ {
int ret; int ret;
tty_port_init(&port);
bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME); bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
if (IS_ERR(bfin_jc_kthread)) if (IS_ERR(bfin_jc_kthread))
return PTR_ERR(bfin_jc_kthread); return PTR_ERR(bfin_jc_kthread);
@ -257,6 +255,8 @@ static int __init bfin_jc_init(void)
if (!bfin_jc_driver) if (!bfin_jc_driver)
goto err_driver; goto err_driver;
tty_port_init(&port);
bfin_jc_driver->driver_name = DRV_NAME; bfin_jc_driver->driver_name = DRV_NAME;
bfin_jc_driver->name = DEV_NAME; bfin_jc_driver->name = DEV_NAME;
bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL; bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL;
@ -274,6 +274,7 @@ static int __init bfin_jc_init(void)
return 0; return 0;
err: err:
tty_port_destroy(&port);
put_tty_driver(bfin_jc_driver); put_tty_driver(bfin_jc_driver);
err_driver: err_driver:
kfree(bfin_jc_write_buf.buf); kfree(bfin_jc_write_buf.buf);
@ -289,6 +290,7 @@ static void __exit bfin_jc_exit(void)
kfree(bfin_jc_write_buf.buf); kfree(bfin_jc_write_buf.buf);
tty_unregister_driver(bfin_jc_driver); tty_unregister_driver(bfin_jc_driver);
put_tty_driver(bfin_jc_driver); put_tty_driver(bfin_jc_driver);
tty_port_destroy(&port);
} }
module_exit(bfin_jc_exit); module_exit(bfin_jc_exit);

View File

@ -3099,7 +3099,7 @@ static const struct tty_port_operations cyz_port_ops = {
* --------------------------------------------------------------------- * ---------------------------------------------------------------------
*/ */
static int __devinit cy_init_card(struct cyclades_card *cinfo) static int cy_init_card(struct cyclades_card *cinfo)
{ {
struct cyclades_port *info; struct cyclades_port *info;
unsigned int channel, port; unsigned int channel, port;
@ -3196,7 +3196,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
/* initialize chips on Cyclom-Y card -- return number of valid /* initialize chips on Cyclom-Y card -- return number of valid
chips (which is number of ports/4) */ chips (which is number of ports/4) */
static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, static unsigned short cyy_init_card(void __iomem *true_base_addr,
int index) int index)
{ {
unsigned int chip_number; unsigned int chip_number;
@ -3405,7 +3405,7 @@ static int __init cy_detect_isa(void)
} /* cy_detect_isa */ } /* cy_detect_isa */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static inline int __devinit cyc_isfwstr(const char *str, unsigned int size) static inline int cyc_isfwstr(const char *str, unsigned int size)
{ {
unsigned int a; unsigned int a;
@ -3420,7 +3420,7 @@ static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
return 0; return 0;
} }
static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data, static inline void cyz_fpga_copy(void __iomem *fpga, const u8 *data,
unsigned int size) unsigned int size)
{ {
for (; size > 0; size--) { for (; size > 0; size--) {
@ -3429,7 +3429,7 @@ static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
} }
} }
static void __devinit plx_init(struct pci_dev *pdev, int irq, static void plx_init(struct pci_dev *pdev, int irq,
struct RUNTIME_9060 __iomem *addr) struct RUNTIME_9060 __iomem *addr)
{ {
/* Reset PLX */ /* Reset PLX */
@ -3449,7 +3449,7 @@ static void __devinit plx_init(struct pci_dev *pdev, int irq,
pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
} }
static int __devinit __cyz_load_fw(const struct firmware *fw, static int __cyz_load_fw(const struct firmware *fw,
const char *name, const u32 mailbox, void __iomem *base, const char *name, const u32 mailbox, void __iomem *base,
void __iomem *fpga) void __iomem *fpga)
{ {
@ -3526,7 +3526,7 @@ static int __devinit __cyz_load_fw(const struct firmware *fw,
return 0; return 0;
} }
static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, static int cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
struct RUNTIME_9060 __iomem *ctl_addr, int irq) struct RUNTIME_9060 __iomem *ctl_addr, int irq)
{ {
const struct firmware *fw; const struct firmware *fw;
@ -3692,7 +3692,7 @@ err:
return retval; return retval;
} }
static int __devinit cy_pci_probe(struct pci_dev *pdev, static int cy_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct cyclades_card *card; struct cyclades_card *card;
@ -3931,10 +3931,10 @@ err:
return retval; return retval;
} }
static void __devexit cy_pci_remove(struct pci_dev *pdev) static void cy_pci_remove(struct pci_dev *pdev)
{ {
struct cyclades_card *cinfo = pci_get_drvdata(pdev); struct cyclades_card *cinfo = pci_get_drvdata(pdev);
unsigned int i; unsigned int i, channel;
/* non-Z with old PLX */ /* non-Z with old PLX */
if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
@ -3960,9 +3960,11 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
pci_release_regions(pdev); pci_release_regions(pdev);
cinfo->base_addr = NULL; cinfo->base_addr = NULL;
for (i = cinfo->first_line; i < cinfo->first_line + for (channel = 0, i = cinfo->first_line; i < cinfo->first_line +
cinfo->nports; i++) cinfo->nports; i++, channel++) {
tty_unregister_device(cy_serial_driver, i); tty_unregister_device(cy_serial_driver, i);
tty_port_destroy(&cinfo->ports[channel].port);
}
cinfo->nports = 0; cinfo->nports = 0;
kfree(cinfo->ports); kfree(cinfo->ports);
} }
@ -3971,7 +3973,7 @@ static struct pci_driver cy_pci_driver = {
.name = "cyclades", .name = "cyclades",
.id_table = cy_pci_dev_id, .id_table = cy_pci_dev_id,
.probe = cy_pci_probe, .probe = cy_pci_probe,
.remove = __devexit_p(cy_pci_remove) .remove = cy_pci_remove
}; };
#endif #endif

View File

@ -699,7 +699,7 @@ static const struct tty_port_operations ehv_bc_tty_port_ops = {
.shutdown = ehv_bc_tty_port_shutdown, .shutdown = ehv_bc_tty_port_shutdown,
}; };
static int __devinit ehv_bc_tty_probe(struct platform_device *pdev) static int ehv_bc_tty_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct ehv_bc_data *bc; struct ehv_bc_data *bc;
@ -757,6 +757,7 @@ static int __devinit ehv_bc_tty_probe(struct platform_device *pdev)
return 0; return 0;
error: error:
tty_port_destroy(&bc->port);
irq_dispose_mapping(bc->tx_irq); irq_dispose_mapping(bc->tx_irq);
irq_dispose_mapping(bc->rx_irq); irq_dispose_mapping(bc->rx_irq);
@ -770,6 +771,7 @@ static int ehv_bc_tty_remove(struct platform_device *pdev)
tty_unregister_device(ehv_bc_driver, bc - bcs); tty_unregister_device(ehv_bc_driver, bc - bcs);
tty_port_destroy(&bc->port);
irq_dispose_mapping(bc->tx_irq); irq_dispose_mapping(bc->tx_irq);
irq_dispose_mapping(bc->rx_irq); irq_dispose_mapping(bc->rx_irq);

View File

@ -41,7 +41,7 @@
static const char hvc_opal_name[] = "hvc_opal"; static const char hvc_opal_name[] = "hvc_opal";
static struct of_device_id hvc_opal_match[] __devinitdata = { static struct of_device_id hvc_opal_match[] = {
{ .name = "serial", .compatible = "ibm,opal-console-raw" }, { .name = "serial", .compatible = "ibm,opal-console-raw" },
{ .name = "serial", .compatible = "ibm,opal-console-hvsi" }, { .name = "serial", .compatible = "ibm,opal-console-hvsi" },
{ }, { },
@ -161,7 +161,7 @@ static const struct hv_ops hvc_opal_hvsi_ops = {
.tiocmset = hvc_opal_hvsi_tiocmset, .tiocmset = hvc_opal_hvsi_tiocmset,
}; };
static int __devinit hvc_opal_probe(struct platform_device *dev) static int hvc_opal_probe(struct platform_device *dev)
{ {
const struct hv_ops *ops; const struct hv_ops *ops;
struct hvc_struct *hp; struct hvc_struct *hp;
@ -222,7 +222,7 @@ static int __devinit hvc_opal_probe(struct platform_device *dev)
return 0; return 0;
} }
static int __devexit hvc_opal_remove(struct platform_device *dev) static int hvc_opal_remove(struct platform_device *dev)
{ {
struct hvc_struct *hp = dev_get_drvdata(&dev->dev); struct hvc_struct *hp = dev_get_drvdata(&dev->dev);
int rc, termno; int rc, termno;
@ -239,7 +239,7 @@ static int __devexit hvc_opal_remove(struct platform_device *dev)
static struct platform_driver hvc_opal_driver = { static struct platform_driver hvc_opal_driver = {
.probe = hvc_opal_probe, .probe = hvc_opal_probe,
.remove = __devexit_p(hvc_opal_remove), .remove = hvc_opal_remove,
.driver = { .driver = {
.name = hvc_opal_name, .name = hvc_opal_name,
.owner = THIS_MODULE, .owner = THIS_MODULE,

View File

@ -53,7 +53,7 @@
static const char hvc_driver_name[] = "hvc_console"; static const char hvc_driver_name[] = "hvc_console";
static struct vio_device_id hvc_driver_table[] __devinitdata = { static struct vio_device_id hvc_driver_table[] = {
{"serial", "hvterm1"}, {"serial", "hvterm1"},
#ifndef HVC_OLD_HVSI #ifndef HVC_OLD_HVSI
{"serial", "hvterm-protocol"}, {"serial", "hvterm-protocol"},
@ -293,7 +293,7 @@ static int udbg_hvc_getc(void)
} }
} }
static int __devinit hvc_vio_probe(struct vio_dev *vdev, static int hvc_vio_probe(struct vio_dev *vdev,
const struct vio_device_id *id) const struct vio_device_id *id)
{ {
const struct hv_ops *ops; const struct hv_ops *ops;
@ -362,7 +362,7 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev,
return 0; return 0;
} }
static int __devexit hvc_vio_remove(struct vio_dev *vdev) static int hvc_vio_remove(struct vio_dev *vdev)
{ {
struct hvc_struct *hp = dev_get_drvdata(&vdev->dev); struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
int rc, termno; int rc, termno;

View File

@ -422,7 +422,7 @@ static int xencons_connect_backend(struct xenbus_device *dev,
return ret; return ret;
} }
static int __devinit xencons_probe(struct xenbus_device *dev, static int xencons_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id) const struct xenbus_device_id *id)
{ {
int ret, devid; int ret, devid;

View File

@ -330,12 +330,12 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp);
static void hvcs_close(struct tty_struct *tty, struct file *filp); static void hvcs_close(struct tty_struct *tty, struct file *filp);
static void hvcs_hangup(struct tty_struct * tty); static void hvcs_hangup(struct tty_struct * tty);
static int __devinit hvcs_probe(struct vio_dev *dev, static int hvcs_probe(struct vio_dev *dev,
const struct vio_device_id *id); const struct vio_device_id *id);
static int __devexit hvcs_remove(struct vio_dev *dev); static int hvcs_remove(struct vio_dev *dev);
static int __init hvcs_module_init(void); static int __init hvcs_module_init(void);
static void __exit hvcs_module_exit(void); static void __exit hvcs_module_exit(void);
static int __devinit hvcs_initialize(void); static int hvcs_initialize(void);
#define HVCS_SCHED_READ 0x00000001 #define HVCS_SCHED_READ 0x00000001
#define HVCS_QUICK_READ 0x00000002 #define HVCS_QUICK_READ 0x00000002
@ -676,7 +676,7 @@ static int khvcsd(void *unused)
return 0; return 0;
} }
static struct vio_device_id hvcs_driver_table[] __devinitdata= { static struct vio_device_id hvcs_driver_table[] = {
{"serial-server", "hvterm2"}, {"serial-server", "hvterm2"},
{ "", "" } { "", "" }
}; };
@ -756,7 +756,7 @@ static int hvcs_get_index(void)
return -1; return -1;
} }
static int __devinit hvcs_probe( static int hvcs_probe(
struct vio_dev *dev, struct vio_dev *dev,
const struct vio_device_id *id) const struct vio_device_id *id)
{ {
@ -835,7 +835,7 @@ static int __devinit hvcs_probe(
return 0; return 0;
} }
static int __devexit hvcs_remove(struct vio_dev *dev) static int hvcs_remove(struct vio_dev *dev)
{ {
struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev); struct hvcs_struct *hvcsd = dev_get_drvdata(&dev->dev);
unsigned long flags; unsigned long flags;
@ -874,7 +874,7 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
static struct vio_driver hvcs_vio_driver = { static struct vio_driver hvcs_vio_driver = {
.id_table = hvcs_driver_table, .id_table = hvcs_driver_table,
.probe = hvcs_probe, .probe = hvcs_probe,
.remove = __devexit_p(hvcs_remove), .remove = hvcs_remove,
.name = hvcs_driver_name, .name = hvcs_driver_name,
}; };
@ -1478,7 +1478,7 @@ static void hvcs_free_index_list(void)
hvcs_index_count = 0; hvcs_index_count = 0;
} }
static int __devinit hvcs_initialize(void) static int hvcs_initialize(void)
{ {
int rc, num_ttys_to_alloc; int rc, num_ttys_to_alloc;
@ -1496,8 +1496,10 @@ static int __devinit hvcs_initialize(void)
num_ttys_to_alloc = hvcs_parm_num_devs; num_ttys_to_alloc = hvcs_parm_num_devs;
hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc); hvcs_tty_driver = alloc_tty_driver(num_ttys_to_alloc);
if (!hvcs_tty_driver) if (!hvcs_tty_driver) {
mutex_unlock(&hvcs_init_mutex);
return -ENOMEM; return -ENOMEM;
}
if (hvcs_alloc_index_list(num_ttys_to_alloc)) { if (hvcs_alloc_index_list(num_ttys_to_alloc)) {
rc = -ENOMEM; rc = -ENOMEM;

View File

@ -1218,6 +1218,7 @@ static int __init hvsi_console_init(void)
if (hp->virq == 0) { if (hp->virq == 0) {
printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n", printk(KERN_ERR "%s: couldn't create irq mapping for 0x%x\n",
__func__, irq[0]); __func__, irq[0]);
tty_port_destroy(&hp->port);
continue; continue;
} }

View File

@ -352,6 +352,8 @@ static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
} }
skb = dev_alloc_skb(length + 4); skb = dev_alloc_skb(length + 4);
if (skb == NULL)
return NULL;
skb_reserve(skb, 2); skb_reserve(skb, 2);
memcpy(skb_put(skb, length), data, length); memcpy(skb_put(skb, length), data, length);
@ -397,7 +399,8 @@ void ipwireless_network_packet_received(struct ipw_network *network,
/* Send the data to the ppp_generic module. */ /* Send the data to the ppp_generic module. */
skb = ipw_packet_received_skb(data, length); skb = ipw_packet_received_skb(data, length);
ppp_input(network->ppp_channel, skb); if (skb)
ppp_input(network->ppp_channel, skb);
} else } else
spin_unlock_irqrestore(&network->lock, spin_unlock_irqrestore(&network->lock,
flags); flags);

View File

@ -566,6 +566,7 @@ void ipwireless_tty_free(struct ipw_tty *tty)
ipwireless_disassociate_network_ttys(network, ipwireless_disassociate_network_ttys(network,
ttyj->channel_idx); ttyj->channel_idx);
tty_unregister_device(ipw_tty_driver, j); tty_unregister_device(ipw_tty_driver, j);
tty_port_destroy(&ttyj->port);
ttys[j] = NULL; ttys[j] = NULL;
mutex_unlock(&ttyj->ipw_tty_mutex); mutex_unlock(&ttyj->ipw_tty_mutex);
kfree(ttyj); kfree(ttyj);

View File

@ -148,7 +148,7 @@
#endif #endif
static int isicom_probe(struct pci_dev *, const struct pci_device_id *); static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit isicom_remove(struct pci_dev *); static void isicom_remove(struct pci_dev *);
static struct pci_device_id isicom_pci_tbl[] = { static struct pci_device_id isicom_pci_tbl[] = {
{ PCI_DEVICE(VENDOR_ID, 0x2028) }, { PCI_DEVICE(VENDOR_ID, 0x2028) },
@ -168,7 +168,7 @@ static struct pci_driver isicom_driver = {
.name = "isicom", .name = "isicom",
.id_table = isicom_pci_tbl, .id_table = isicom_pci_tbl,
.probe = isicom_probe, .probe = isicom_probe,
.remove = __devexit_p(isicom_remove) .remove = isicom_remove
}; };
static int prev_card = 3; /* start servicing isi_card[0] */ static int prev_card = 3; /* start servicing isi_card[0] */
@ -603,7 +603,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id)
if (tty_port_cts_enabled(&port->port)) { if (tty_port_cts_enabled(&port->port)) {
if (tty->hw_stopped) { if (tty->hw_stopped) {
if (header & ISI_CTS) { if (header & ISI_CTS) {
port->port.tty->hw_stopped = 0; tty->hw_stopped = 0;
/* start tx ing */ /* start tx ing */
port->status |= (ISI_TXOK port->status |= (ISI_TXOK
| ISI_CTS); | ISI_CTS);
@ -1307,7 +1307,7 @@ static const struct tty_port_operations isicom_port_ops = {
.shutdown = isicom_shutdown, .shutdown = isicom_shutdown,
}; };
static int __devinit reset_card(struct pci_dev *pdev, static int reset_card(struct pci_dev *pdev,
const unsigned int card, unsigned int *signature) const unsigned int card, unsigned int *signature)
{ {
struct isi_board *board = pci_get_drvdata(pdev); struct isi_board *board = pci_get_drvdata(pdev);
@ -1368,7 +1368,7 @@ end:
return retval; return retval;
} }
static int __devinit load_firmware(struct pci_dev *pdev, static int load_firmware(struct pci_dev *pdev,
const unsigned int index, const unsigned int signature) const unsigned int index, const unsigned int signature)
{ {
struct isi_board *board = pci_get_drvdata(pdev); struct isi_board *board = pci_get_drvdata(pdev);
@ -1548,7 +1548,7 @@ end:
*/ */
static unsigned int card_count; static unsigned int card_count;
static int __devinit isicom_probe(struct pci_dev *pdev, static int isicom_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
unsigned int uninitialized_var(signature), index; unsigned int uninitialized_var(signature), index;
@ -1610,10 +1610,15 @@ static int __devinit isicom_probe(struct pci_dev *pdev,
if (retval < 0) if (retval < 0)
goto errunri; goto errunri;
for (index = 0; index < board->port_count; index++) for (index = 0; index < board->port_count; index++) {
tty_port_register_device(&board->ports[index].port, struct tty_port *tport = &board->ports[index].port;
isicom_normal, board->index * 16 + index, tty_port_init(tport);
&pdev->dev); tport->ops = &isicom_port_ops;
tport->close_delay = 50 * HZ/100;
tport->closing_wait = 3000 * HZ/100;
tty_port_register_device(tport, isicom_normal,
board->index * 16 + index, &pdev->dev);
}
return 0; return 0;
@ -1630,13 +1635,15 @@ err:
return retval; return retval;
} }
static void __devexit isicom_remove(struct pci_dev *pdev) static void isicom_remove(struct pci_dev *pdev)
{ {
struct isi_board *board = pci_get_drvdata(pdev); struct isi_board *board = pci_get_drvdata(pdev);
unsigned int i; unsigned int i;
for (i = 0; i < board->port_count; i++) for (i = 0; i < board->port_count; i++) {
tty_unregister_device(isicom_normal, board->index * 16 + i); tty_unregister_device(isicom_normal, board->index * 16 + i);
tty_port_destroy(&board->ports[i].port);
}
free_irq(board->irq, board); free_irq(board->irq, board);
pci_release_region(pdev, 3); pci_release_region(pdev, 3);
@ -1655,13 +1662,9 @@ static int __init isicom_init(void)
isi_card[idx].ports = port; isi_card[idx].ports = port;
spin_lock_init(&isi_card[idx].card_lock); spin_lock_init(&isi_card[idx].card_lock);
for (channel = 0; channel < 16; channel++, port++) { for (channel = 0; channel < 16; channel++, port++) {
tty_port_init(&port->port);
port->port.ops = &isicom_port_ops;
port->magic = ISICOM_MAGIC; port->magic = ISICOM_MAGIC;
port->card = &isi_card[idx]; port->card = &isi_card[idx];
port->channel = channel; port->channel = channel;
port->port.close_delay = 50 * HZ/100;
port->port.closing_wait = 3000 * HZ/100;
port->status = 0; port->status = 0;
/* . . . */ /* . . . */
} }

View File

@ -895,6 +895,8 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
return 0; return 0;
err_free: err_free:
for (i = 0; i < MAX_PORTS_PER_BOARD; i++)
tty_port_destroy(&brd->ports[i].port);
kfree(brd->ports); kfree(brd->ports);
err: err:
return ret; return ret;
@ -919,6 +921,8 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
tty_kref_put(tty); tty_kref_put(tty);
} }
} }
for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
tty_port_destroy(&brd->ports[a].port);
while (1) { while (1) {
opened = 0; opened = 0;
for (a = 0; a < brd->numPorts; a++) for (a = 0; a < brd->numPorts; a++)
@ -941,7 +945,7 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
} }
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static int __devinit moxa_pci_probe(struct pci_dev *pdev, static int moxa_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct moxa_board_conf *board; struct moxa_board_conf *board;
@ -1016,7 +1020,7 @@ err:
return retval; return retval;
} }
static void __devexit moxa_pci_remove(struct pci_dev *pdev) static void moxa_pci_remove(struct pci_dev *pdev)
{ {
struct moxa_board_conf *brd = pci_get_drvdata(pdev); struct moxa_board_conf *brd = pci_get_drvdata(pdev);
@ -1029,7 +1033,7 @@ static struct pci_driver moxa_pci_driver = {
.name = "moxa", .name = "moxa",
.id_table = moxa_pcibrds, .id_table = moxa_pcibrds,
.probe = moxa_pci_probe, .probe = moxa_pci_probe,
.remove = __devexit_p(moxa_pci_remove) .remove = moxa_pci_remove
}; };
#endif /* CONFIG_PCI */ #endif /* CONFIG_PCI */
@ -1370,7 +1374,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
p->DCDState = dcd; p->DCDState = dcd;
spin_unlock_irqrestore(&p->port.lock, flags); spin_unlock_irqrestore(&p->port.lock, flags);
tty = tty_port_tty_get(&p->port); tty = tty_port_tty_get(&p->port);
if (tty && C_CLOCAL(tty) && !dcd) if (tty && !C_CLOCAL(tty) && !dcd)
tty_hangup(tty); tty_hangup(tty);
tty_kref_put(tty); tty_kref_put(tty);
} }

View File

@ -487,7 +487,7 @@ static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
} }
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static int __devinit CheckIsMoxaMust(unsigned long io) static int CheckIsMoxaMust(unsigned long io)
{ {
u8 oldmcr, hwid; u8 oldmcr, hwid;
int i; int i;
@ -2369,7 +2369,7 @@ static void mxser_release_ISA_res(struct mxser_board *brd)
mxser_release_vector(brd); mxser_release_vector(brd);
} }
static int __devinit mxser_initbrd(struct mxser_board *brd, static int mxser_initbrd(struct mxser_board *brd,
struct pci_dev *pdev) struct pci_dev *pdev)
{ {
struct mxser_port *info; struct mxser_port *info;
@ -2411,14 +2411,27 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
brd); brd);
if (retval) if (retval) {
for (i = 0; i < brd->info->nports; i++)
tty_port_destroy(&brd->ports[i].port);
printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
"conflict with another device.\n", "conflict with another device.\n",
brd->info->name, brd->irq); brd->info->name, brd->irq);
}
return retval; return retval;
} }
static void mxser_board_remove(struct mxser_board *brd)
{
unsigned int i;
for (i = 0; i < brd->info->nports; i++) {
tty_unregister_device(mxvar_sdriver, brd->idx + i);
tty_port_destroy(&brd->ports[i].port);
}
}
static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
{ {
int id, i, bits, ret; int id, i, bits, ret;
@ -2534,7 +2547,7 @@ err_irqconflict:
return -EIO; return -EIO;
} }
static int __devinit mxser_probe(struct pci_dev *pdev, static int mxser_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
@ -2645,14 +2658,12 @@ err:
#endif #endif
} }
static void __devexit mxser_remove(struct pci_dev *pdev) static void mxser_remove(struct pci_dev *pdev)
{ {
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct mxser_board *brd = pci_get_drvdata(pdev); struct mxser_board *brd = pci_get_drvdata(pdev);
unsigned int i;
for (i = 0; i < brd->info->nports; i++) mxser_board_remove(brd);
tty_unregister_device(mxvar_sdriver, brd->idx + i);
free_irq(pdev->irq, brd); free_irq(pdev->irq, brd);
pci_release_region(pdev, 2); pci_release_region(pdev, 2);
@ -2666,7 +2677,7 @@ static struct pci_driver mxser_driver = {
.name = "mxser", .name = "mxser",
.id_table = mxser_pcibrds, .id_table = mxser_pcibrds,
.probe = mxser_probe, .probe = mxser_probe,
.remove = __devexit_p(mxser_remove) .remove = mxser_remove
}; };
static int __init mxser_module_init(void) static int __init mxser_module_init(void)
@ -2748,15 +2759,13 @@ err_put:
static void __exit mxser_module_exit(void) static void __exit mxser_module_exit(void)
{ {
unsigned int i, j; unsigned int i;
pci_unregister_driver(&mxser_driver); pci_unregister_driver(&mxser_driver);
for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
if (mxser_boards[i].info != NULL) if (mxser_boards[i].info != NULL)
for (j = 0; j < mxser_boards[i].info->nports; j++) mxser_board_remove(&mxser_boards[i]);
tty_unregister_device(mxvar_sdriver,
mxser_boards[i].idx + j);
tty_unregister_driver(mxvar_sdriver); tty_unregister_driver(mxvar_sdriver);
put_tty_driver(mxvar_sdriver); put_tty_driver(mxvar_sdriver);

View File

@ -134,7 +134,6 @@ struct gsm_dlci {
#define DLCI_OPENING 1 /* Sending SABM not seen UA */ #define DLCI_OPENING 1 /* Sending SABM not seen UA */
#define DLCI_OPEN 2 /* SABM/UA complete */ #define DLCI_OPEN 2 /* SABM/UA complete */
#define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */ #define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */
struct kref ref; /* freed from port or mux close */
struct mutex mutex; struct mutex mutex;
/* Link layer */ /* Link layer */
@ -1635,7 +1634,6 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
if (dlci == NULL) if (dlci == NULL)
return NULL; return NULL;
spin_lock_init(&dlci->lock); spin_lock_init(&dlci->lock);
kref_init(&dlci->ref);
mutex_init(&dlci->mutex); mutex_init(&dlci->mutex);
dlci->fifo = &dlci->_fifo; dlci->fifo = &dlci->_fifo;
if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) { if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
@ -1669,9 +1667,9 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
* *
* Can sleep. * Can sleep.
*/ */
static void gsm_dlci_free(struct kref *ref) static void gsm_dlci_free(struct tty_port *port)
{ {
struct gsm_dlci *dlci = container_of(ref, struct gsm_dlci, ref); struct gsm_dlci *dlci = container_of(port, struct gsm_dlci, port);
del_timer_sync(&dlci->t1); del_timer_sync(&dlci->t1);
dlci->gsm->dlci[dlci->addr] = NULL; dlci->gsm->dlci[dlci->addr] = NULL;
@ -1683,12 +1681,12 @@ static void gsm_dlci_free(struct kref *ref)
static inline void dlci_get(struct gsm_dlci *dlci) static inline void dlci_get(struct gsm_dlci *dlci)
{ {
kref_get(&dlci->ref); tty_port_get(&dlci->port);
} }
static inline void dlci_put(struct gsm_dlci *dlci) static inline void dlci_put(struct gsm_dlci *dlci)
{ {
kref_put(&dlci->ref, gsm_dlci_free); tty_port_put(&dlci->port);
} }
/** /**
@ -2874,6 +2872,7 @@ static void gsm_dtr_rts(struct tty_port *port, int onoff)
static const struct tty_port_operations gsm_port_ops = { static const struct tty_port_operations gsm_port_ops = {
.carrier_raised = gsm_carrier_raised, .carrier_raised = gsm_carrier_raised,
.dtr_rts = gsm_dtr_rts, .dtr_rts = gsm_dtr_rts,
.destruct = gsm_dlci_free,
}; };
static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty) static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)

File diff suppressed because it is too large Load Diff

View File

@ -400,7 +400,7 @@ struct buffer {
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Global variables */ /* Global variables */
static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = { static const struct pci_device_id nozomi_pci_tbl[] = {
{PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */ {PCI_DEVICE(0x1931, 0x000c)}, /* Nozomi HSDPA */
{}, {},
}; };
@ -1360,7 +1360,7 @@ static void remove_sysfs_files(struct nozomi *dc)
} }
/* Allocate memory for one device */ /* Allocate memory for one device */
static int __devinit nozomi_card_init(struct pci_dev *pdev, static int nozomi_card_init(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
resource_size_t start; resource_size_t start;
@ -1479,6 +1479,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
if (IS_ERR(tty_dev)) { if (IS_ERR(tty_dev)) {
ret = PTR_ERR(tty_dev); ret = PTR_ERR(tty_dev);
dev_err(&pdev->dev, "Could not allocate tty?\n"); dev_err(&pdev->dev, "Could not allocate tty?\n");
tty_port_destroy(&port->port);
goto err_free_tty; goto err_free_tty;
} }
} }
@ -1486,8 +1487,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
return 0; return 0;
err_free_tty: err_free_tty:
for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) for (i = 0; i < MAX_PORT; ++i) {
tty_unregister_device(ntty_driver, i); tty_unregister_device(ntty_driver, dc->index_start + i);
tty_port_destroy(&dc->port[i].port);
}
err_free_kfifo: err_free_kfifo:
for (i = 0; i < MAX_PORT; i++) for (i = 0; i < MAX_PORT; i++)
kfifo_free(&dc->port[i].fifo_ul); kfifo_free(&dc->port[i].fifo_ul);
@ -1504,7 +1507,7 @@ err:
return ret; return ret;
} }
static void __devexit tty_exit(struct nozomi *dc) static void tty_exit(struct nozomi *dc)
{ {
unsigned int i; unsigned int i;
@ -1520,12 +1523,14 @@ static void __devexit tty_exit(struct nozomi *dc)
complete off a hangup method ? */ complete off a hangup method ? */
while (dc->open_ttys) while (dc->open_ttys)
msleep(1); msleep(1);
for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) for (i = 0; i < MAX_PORT; ++i) {
tty_unregister_device(ntty_driver, i); tty_unregister_device(ntty_driver, dc->index_start + i);
tty_port_destroy(&dc->port[i].port);
}
} }
/* Deallocate memory for one device */ /* Deallocate memory for one device */
static void __devexit nozomi_card_exit(struct pci_dev *pdev) static void nozomi_card_exit(struct pci_dev *pdev)
{ {
int i; int i;
struct ctrl_ul ctrl; struct ctrl_ul ctrl;
@ -1903,7 +1908,7 @@ static struct pci_driver nozomi_driver = {
.name = NOZOMI_NAME, .name = NOZOMI_NAME,
.id_table = nozomi_pci_tbl, .id_table = nozomi_pci_tbl,
.probe = nozomi_card_init, .probe = nozomi_card_init,
.remove = __devexit_p(nozomi_card_exit), .remove = nozomi_card_exit,
}; };
static __init int nozomi_init(void) static __init int nozomi_init(void)

View File

@ -4,9 +4,6 @@
* Added support for a Unix98-style ptmx device. * Added support for a Unix98-style ptmx device.
* -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998 * -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
* *
* When reading this code see also fs/devpts. In particular note that the
* driver_data field is used by the devpts side as a binding to the devpts
* inode.
*/ */
#include <linux/module.h> #include <linux/module.h>
@ -59,7 +56,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
#ifdef CONFIG_UNIX98_PTYS #ifdef CONFIG_UNIX98_PTYS
if (tty->driver == ptm_driver) { if (tty->driver == ptm_driver) {
mutex_lock(&devpts_mutex); mutex_lock(&devpts_mutex);
devpts_pty_kill(tty->link); devpts_pty_kill(tty->link->driver_data);
mutex_unlock(&devpts_mutex); mutex_unlock(&devpts_mutex);
} }
#endif #endif
@ -96,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty)
static int pty_space(struct tty_struct *to) static int pty_space(struct tty_struct *to)
{ {
int n = 8192 - to->buf.memory_used; int n = 8192 - to->port->buf.memory_used;
if (n < 0) if (n < 0)
return 0; return 0;
return n; return n;
@ -174,6 +171,41 @@ static int pty_set_lock(struct tty_struct *tty, int __user *arg)
return 0; return 0;
} }
static int pty_get_lock(struct tty_struct *tty, int __user *arg)
{
int locked = test_bit(TTY_PTY_LOCK, &tty->flags);
return put_user(locked, arg);
}
/* Set the packet mode on a pty */
static int pty_set_pktmode(struct tty_struct *tty, int __user *arg)
{
unsigned long flags;
int pktmode;
if (get_user(pktmode, arg))
return -EFAULT;
spin_lock_irqsave(&tty->ctrl_lock, flags);
if (pktmode) {
if (!tty->packet) {
tty->packet = 1;
tty->link->ctrl_status = 0;
}
} else
tty->packet = 0;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
return 0;
}
/* Get the packet mode of a pty */
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
{
int pktmode = tty->packet;
return put_user(pktmode, arg);
}
/* Send a signal to the slave */ /* Send a signal to the slave */
static int pty_signal(struct tty_struct *tty, int sig) static int pty_signal(struct tty_struct *tty, int sig)
{ {
@ -245,7 +277,7 @@ static void pty_set_termios(struct tty_struct *tty,
* peform a terminal resize correctly * peform a terminal resize correctly
*/ */
int pty_resize(struct tty_struct *tty, struct winsize *ws) static int pty_resize(struct tty_struct *tty, struct winsize *ws)
{ {
struct pid *pgrp, *rpgrp; struct pid *pgrp, *rpgrp;
unsigned long flags; unsigned long flags;
@ -348,6 +380,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
tty_port_init(ports[1]); tty_port_init(ports[1]);
o_tty->port = ports[0]; o_tty->port = ports[0];
tty->port = ports[1]; tty->port = ports[1];
o_tty->port->itty = o_tty;
tty_driver_kref_get(driver); tty_driver_kref_get(driver);
tty->count++; tty->count++;
@ -366,9 +399,16 @@ err:
return retval; return retval;
} }
/* this is called once with whichever end is closed last */
static void pty_unix98_shutdown(struct tty_struct *tty)
{
devpts_kill_index(tty->driver_data, tty->index);
}
static void pty_cleanup(struct tty_struct *tty) static void pty_cleanup(struct tty_struct *tty)
{ {
kfree(tty->port); tty->port->itty = NULL;
tty_port_put(tty->port);
} }
/* Traditional BSD devices */ /* Traditional BSD devices */
@ -393,6 +433,12 @@ static int pty_bsd_ioctl(struct tty_struct *tty,
switch (cmd) { switch (cmd) {
case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
return pty_set_lock(tty, (int __user *) arg); return pty_set_lock(tty, (int __user *) arg);
case TIOCGPTLCK: /* Get PT Lock status */
return pty_get_lock(tty, (int __user *)arg);
case TIOCPKT: /* Set PT packet mode */
return pty_set_pktmode(tty, (int __user *)arg);
case TIOCGPKT: /* Get PT packet mode */
return pty_get_pktmode(tty, (int __user *)arg);
case TIOCSIG: /* Send signal to other side of pty */ case TIOCSIG: /* Send signal to other side of pty */
return pty_signal(tty, (int) arg); return pty_signal(tty, (int) arg);
} }
@ -507,6 +553,12 @@ static int pty_unix98_ioctl(struct tty_struct *tty,
switch (cmd) { switch (cmd) {
case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */
return pty_set_lock(tty, (int __user *)arg); return pty_set_lock(tty, (int __user *)arg);
case TIOCGPTLCK: /* Get PT Lock status */
return pty_get_lock(tty, (int __user *)arg);
case TIOCPKT: /* Set PT packet mode */
return pty_set_pktmode(tty, (int __user *)arg);
case TIOCGPKT: /* Get PT packet mode */
return pty_get_pktmode(tty, (int __user *)arg);
case TIOCGPTN: /* Get PT Number */ case TIOCGPTN: /* Get PT Number */
return put_user(tty->index, (unsigned int __user *)arg); return put_user(tty->index, (unsigned int __user *)arg);
case TIOCSIG: /* Send signal to other side of pty */ case TIOCSIG: /* Send signal to other side of pty */
@ -547,7 +599,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
struct tty_struct *tty; struct tty_struct *tty;
mutex_lock(&devpts_mutex); mutex_lock(&devpts_mutex);
tty = devpts_get_tty(pts_inode, idx); tty = devpts_get_priv(pts_inode);
mutex_unlock(&devpts_mutex); mutex_unlock(&devpts_mutex);
/* Master must be open before slave */ /* Master must be open before slave */
if (!tty) if (!tty)
@ -581,6 +633,7 @@ static const struct tty_operations ptm_unix98_ops = {
.set_termios = pty_set_termios, .set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl, .ioctl = pty_unix98_ioctl,
.resize = pty_resize, .resize = pty_resize,
.shutdown = pty_unix98_shutdown,
.cleanup = pty_cleanup .cleanup = pty_cleanup
}; };
@ -596,6 +649,7 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer, .chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle, .unthrottle = pty_unthrottle,
.set_termios = pty_set_termios, .set_termios = pty_set_termios,
.shutdown = pty_unix98_shutdown,
.cleanup = pty_cleanup, .cleanup = pty_cleanup,
}; };
@ -614,6 +668,7 @@ static const struct tty_operations pty_unix98_ops = {
static int ptmx_open(struct inode *inode, struct file *filp) static int ptmx_open(struct inode *inode, struct file *filp)
{ {
struct tty_struct *tty; struct tty_struct *tty;
struct inode *slave_inode;
int retval; int retval;
int index; int index;
@ -650,15 +705,21 @@ static int ptmx_open(struct inode *inode, struct file *filp)
tty_add_file(tty, filp); tty_add_file(tty, filp);
retval = devpts_pty_new(inode, tty->link); slave_inode = devpts_pty_new(inode,
if (retval) MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
tty->link);
if (IS_ERR(slave_inode)) {
retval = PTR_ERR(slave_inode);
goto err_release; goto err_release;
}
retval = ptm_driver->ops->open(tty, filp); retval = ptm_driver->ops->open(tty, filp);
if (retval) if (retval)
goto err_release; goto err_release;
tty_unlock(tty); tty_unlock(tty);
tty->driver_data = inode;
tty->link->driver_data = slave_inode;
return 0; return 0;
err_release: err_release:
tty_unlock(tty); tty_unlock(tty);

View File

@ -673,6 +673,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) { if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n", printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
board, aiop, chan); board, aiop, chan);
tty_port_destroy(&info->port);
kfree(info); kfree(info);
return; return;
} }
@ -1757,7 +1758,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static struct pci_device_id __devinitdata __used rocket_pci_ids[] = { static struct pci_device_id __used rocket_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) }, { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
{ } { }
}; };
@ -2357,6 +2358,7 @@ static void rp_cleanup_module(void)
for (i = 0; i < MAX_RP_PORTS; i++) for (i = 0; i < MAX_RP_PORTS; i++)
if (rp_table[i]) { if (rp_table[i]) {
tty_unregister_device(rocket_driver, i); tty_unregister_device(rocket_driver, i);
tty_port_destroy(&rp_table[i]->port);
kfree(rp_table[i]); kfree(rp_table[i]);
} }

View File

@ -1225,6 +1225,8 @@ rs68328_init(void)
if (tty_register_driver(serial_driver)) { if (tty_register_driver(serial_driver)) {
put_tty_driver(serial_driver); put_tty_driver(serial_driver);
for (i = 0; i < NR_PORTS; i++)
tty_port_destroy(&m68k_soft[i].tport);
printk(KERN_ERR "Couldn't register serial driver\n"); printk(KERN_ERR "Couldn't register serial driver\n");
return -ENOMEM; return -ENOMEM;
} }

View File

@ -280,7 +280,17 @@ static const struct serial8250_config uart_config[] = {
.fifo_size = 64, .fifo_size = 64,
.tx_loadsz = 64, .tx_loadsz = 64,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP,
},
[PORT_XR17V35X] = {
.name = "XR17V35X",
.fifo_size = 256,
.tx_loadsz = 256,
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
UART_FCR_T_TRIG_11,
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP,
}, },
[PORT_LPC3220] = { [PORT_LPC3220] = {
.name = "LPC3220", .name = "LPC3220",
@ -455,6 +465,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
} }
static int serial8250_default_handle_irq(struct uart_port *port); static int serial8250_default_handle_irq(struct uart_port *port);
static int exar_handle_irq(struct uart_port *port);
static void set_io_from_upio(struct uart_port *p) static void set_io_from_upio(struct uart_port *p)
{ {
@ -574,6 +585,19 @@ EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
*/ */
static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
{ {
/*
* Exar UARTs have a SLEEP register that enables or disables
* each UART to enter sleep mode separately. On the XR17V35x the
* register is accessible to each UART at the UART_EXAR_SLEEP
* offset but the UART channel may only write to the corresponding
* bit.
*/
if ((p->port.type == PORT_XR17V35X) ||
(p->port.type == PORT_XR17D15X)) {
serial_out(p, UART_EXAR_SLEEP, 0xff);
return;
}
if (p->capabilities & UART_CAP_SLEEP) { if (p->capabilities & UART_CAP_SLEEP) {
if (p->capabilities & UART_CAP_EFR) { if (p->capabilities & UART_CAP_EFR) {
serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B); serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
@ -881,6 +905,27 @@ static void autoconfig_16550a(struct uart_8250_port *up)
up->port.type = PORT_16550A; up->port.type = PORT_16550A;
up->capabilities |= UART_CAP_FIFO; up->capabilities |= UART_CAP_FIFO;
/*
* XR17V35x UARTs have an extra divisor register, DLD
* that gets enabled with when DLAB is set which will
* cause the device to incorrectly match and assign
* port type to PORT_16650. The EFR for this UART is
* found at offset 0x09. Instead check the Deice ID (DVID)
* register for a 2, 4 or 8 port UART.
*/
if (up->port.flags & UPF_EXAR_EFR) {
status1 = serial_in(up, UART_EXAR_DVID);
if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
DEBUG_AUTOCONF("Exar XR17V35x ");
up->port.type = PORT_XR17V35X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
}
}
/* /*
* Check for presence of the EFR when DLAB is set. * Check for presence of the EFR when DLAB is set.
* Only ST16C650V1 UARTs pass this test. * Only ST16C650V1 UARTs pass this test.
@ -1013,8 +1058,12 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* Exar uarts have EFR in a weird location * Exar uarts have EFR in a weird location
*/ */
if (up->port.flags & UPF_EXAR_EFR) { if (up->port.flags & UPF_EXAR_EFR) {
DEBUG_AUTOCONF("Exar XR17D15x ");
up->port.type = PORT_XR17D15X; up->port.type = PORT_XR17D15X;
up->capabilities |= UART_CAP_AFE | UART_CAP_EFR; up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
UART_CAP_SLEEP;
return;
} }
/* /*
@ -1515,6 +1564,31 @@ static int serial8250_default_handle_irq(struct uart_port *port)
return serial8250_handle_irq(port, iir); return serial8250_handle_irq(port, iir);
} }
/*
* These Exar UARTs have an extra interrupt indicator that could
* fire for a few unimplemented interrupts. One of which is a
* wakeup event when coming out of sleep. Put this here just
* to be on the safe side that these interrupts don't go unhandled.
*/
static int exar_handle_irq(struct uart_port *port)
{
unsigned char int0, int1, int2, int3;
unsigned int iir = serial_port_in(port, UART_IIR);
int ret;
ret = serial8250_handle_irq(port, iir);
if ((port->type == PORT_XR17V35X) ||
(port->type == PORT_XR17D15X)) {
int0 = serial_port_in(port, 0x80);
int1 = serial_port_in(port, 0x81);
int2 = serial_port_in(port, 0x82);
int3 = serial_port_in(port, 0x83);
}
return ret;
}
/* /*
* This is the serial driver's interrupt routine. * This is the serial driver's interrupt routine.
* *
@ -2349,16 +2423,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
serial_port_out(port, UART_EFR, efr); serial_port_out(port, UART_EFR, efr);
} }
#ifdef CONFIG_ARCH_OMAP1
/* Workaround to enable 115200 baud on OMAP1510 internal ports */ /* Workaround to enable 115200 baud on OMAP1510 internal ports */
if (cpu_is_omap1510() && is_omap_port(up)) { if (is_omap1510_8250(up)) {
if (baud == 115200) { if (baud == 115200) {
quot = 1; quot = 1;
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1); serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
} else } else
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0); serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
} }
#endif
/* /*
* For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2, * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
@ -2439,10 +2511,9 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
{ {
if (pt->port.iotype == UPIO_AU) if (pt->port.iotype == UPIO_AU)
return 0x1000; return 0x1000;
#ifdef CONFIG_ARCH_OMAP1 if (is_omap1_8250(pt))
if (is_omap_port(pt))
return 0x16 << pt->port.regshift; return 0x16 << pt->port.regshift;
#endif
return 8 << pt->port.regshift; return 8 << pt->port.regshift;
} }
@ -2617,6 +2688,11 @@ static void serial8250_config_port(struct uart_port *port, int flags)
serial8250_release_rsa_resource(up); serial8250_release_rsa_resource(up);
if (port->type == PORT_UNKNOWN) if (port->type == PORT_UNKNOWN)
serial8250_release_std_resource(up); serial8250_release_std_resource(up);
/* Fixme: probably not the best place for this */
if ((port->type == PORT_XR17V35X) ||
(port->type == PORT_XR17D15X))
port->handle_irq = exar_handle_irq;
} }
static int static int
@ -2992,7 +3068,7 @@ void serial8250_resume_port(int line)
* list is terminated with a zero flags entry, which means we expect * list is terminated with a zero flags entry, which means we expect
* all entries to have at least UPF_BOOT_AUTOCONF set. * all entries to have at least UPF_BOOT_AUTOCONF set.
*/ */
static int __devinit serial8250_probe(struct platform_device *dev) static int serial8250_probe(struct platform_device *dev)
{ {
struct plat_serial8250_port *p = dev->dev.platform_data; struct plat_serial8250_port *p = dev->dev.platform_data;
struct uart_8250_port uart; struct uart_8250_port uart;
@ -3038,7 +3114,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
/* /*
* Remove serial ports registered against a platform device. * Remove serial ports registered against a platform device.
*/ */
static int __devexit serial8250_remove(struct platform_device *dev) static int serial8250_remove(struct platform_device *dev)
{ {
int i; int i;
@ -3081,7 +3157,7 @@ static int serial8250_resume(struct platform_device *dev)
static struct platform_driver serial8250_isa_driver = { static struct platform_driver serial8250_isa_driver = {
.probe = serial8250_probe, .probe = serial8250_probe,
.remove = __devexit_p(serial8250_remove), .remove = serial8250_remove,
.suspend = serial8250_suspend, .suspend = serial8250_suspend,
.resume = serial8250_resume, .resume = serial8250_resume,
.driver = { .driver = {

View File

@ -106,3 +106,39 @@ static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { } static inline void serial8250_pnp_exit(void) { }
#endif #endif
#ifdef CONFIG_ARCH_OMAP1
static inline int is_omap1_8250(struct uart_8250_port *pt)
{
int res;
switch (pt->port.mapbase) {
case OMAP1_UART1_BASE:
case OMAP1_UART2_BASE:
case OMAP1_UART3_BASE:
res = 1;
break;
default:
res = 0;
break;
}
return res;
}
static inline int is_omap1510_8250(struct uart_8250_port *pt)
{
if (!cpu_is_omap1510())
return 0;
return is_omap1_8250(pt);
}
#else
static inline int is_omap1_8250(struct uart_8250_port *pt)
{
return 0;
}
static inline int is_omap1510_8250(struct uart_8250_port *pt)
{
return 0;
}
#endif

View File

@ -38,7 +38,7 @@ struct serial_card_info {
void __iomem *vaddr; void __iomem *vaddr;
}; };
static int __devinit static int
serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
{ {
struct serial_card_info *info; struct serial_card_info *info;
@ -80,7 +80,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
return 0; return 0;
} }
static void __devexit serial_card_remove(struct expansion_card *ec) static void serial_card_remove(struct expansion_card *ec)
{ {
struct serial_card_info *info = ecard_get_drvdata(ec); struct serial_card_info *info = ecard_get_drvdata(ec);
int i; int i;
@ -116,7 +116,7 @@ static const struct ecard_id serial_cids[] = {
static struct ecard_driver serial_card_driver = { static struct ecard_driver serial_card_driver = {
.probe = serial_card_probe, .probe = serial_card_probe,
.remove = __devexit_p(serial_card_remove), .remove = serial_card_remove,
.id_table = serial_cids, .id_table = serial_cids,
.drv = { .drv = {
.name = "8250_acorn", .name = "8250_acorn",

View File

@ -87,7 +87,7 @@ static int dw8250_handle_irq(struct uart_port *p)
return 0; return 0;
} }
static int __devinit dw8250_probe(struct platform_device *pdev) static int dw8250_probe(struct platform_device *pdev)
{ {
struct uart_8250_port uart = {}; struct uart_8250_port uart = {};
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -152,7 +152,7 @@ static int __devinit dw8250_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int __devexit dw8250_remove(struct platform_device *pdev) static int dw8250_remove(struct platform_device *pdev)
{ {
struct dw8250_data *data = platform_get_drvdata(pdev); struct dw8250_data *data = platform_get_drvdata(pdev);
@ -161,6 +161,29 @@ static int __devexit dw8250_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
serial8250_suspend_port(data->line);
return 0;
}
static int dw8250_resume(struct platform_device *pdev)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
serial8250_resume_port(data->line);
return 0;
}
#else
#define dw8250_suspend NULL
#define dw8250_resume NULL
#endif /* CONFIG_PM */
static const struct of_device_id dw8250_match[] = { static const struct of_device_id dw8250_match[] = {
{ .compatible = "snps,dw-apb-uart" }, { .compatible = "snps,dw-apb-uart" },
{ /* Sentinel */ } { /* Sentinel */ }
@ -174,7 +197,9 @@ static struct platform_driver dw8250_platform_driver = {
.of_match_table = dw8250_match, .of_match_table = dw8250_match,
}, },
.probe = dw8250_probe, .probe = dw8250_probe,
.remove = __devexit_p(dw8250_remove), .remove = dw8250_remove,
.suspend = dw8250_suspend,
.resume = dw8250_resume,
}; };
module_platform_driver(dw8250_platform_driver); module_platform_driver(dw8250_platform_driver);

View File

@ -48,7 +48,7 @@ struct early_serial8250_device {
static struct early_serial8250_device early_device; static struct early_serial8250_device early_device;
static unsigned int __init serial_in(struct uart_port *port, int offset) unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
{ {
switch (port->iotype) { switch (port->iotype) {
case UPIO_MEM: case UPIO_MEM:
@ -62,7 +62,7 @@ static unsigned int __init serial_in(struct uart_port *port, int offset)
} }
} }
static void __init serial_out(struct uart_port *port, int offset, int value) void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
{ {
switch (port->iotype) { switch (port->iotype) {
case UPIO_MEM: case UPIO_MEM:
@ -84,7 +84,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
unsigned int status; unsigned int status;
for (;;) { for (;;) {
status = serial_in(port, UART_LSR); status = serial8250_early_in(port, UART_LSR);
if ((status & BOTH_EMPTY) == BOTH_EMPTY) if ((status & BOTH_EMPTY) == BOTH_EMPTY)
return; return;
cpu_relax(); cpu_relax();
@ -94,7 +94,7 @@ static void __init wait_for_xmitr(struct uart_port *port)
static void __init serial_putc(struct uart_port *port, int c) static void __init serial_putc(struct uart_port *port, int c)
{ {
wait_for_xmitr(port); wait_for_xmitr(port);
serial_out(port, UART_TX, c); serial8250_early_out(port, UART_TX, c);
} }
static void __init early_serial8250_write(struct console *console, static void __init early_serial8250_write(struct console *console,
@ -104,14 +104,14 @@ static void __init early_serial8250_write(struct console *console,
unsigned int ier; unsigned int ier;
/* Save the IER and disable interrupts */ /* Save the IER and disable interrupts */
ier = serial_in(port, UART_IER); ier = serial8250_early_in(port, UART_IER);
serial_out(port, UART_IER, 0); serial8250_early_out(port, UART_IER, 0);
uart_console_write(port, s, count, serial_putc); uart_console_write(port, s, count, serial_putc);
/* Wait for transmitter to become empty and restore the IER */ /* Wait for transmitter to become empty and restore the IER */
wait_for_xmitr(port); wait_for_xmitr(port);
serial_out(port, UART_IER, ier); serial8250_early_out(port, UART_IER, ier);
} }
static unsigned int __init probe_baud(struct uart_port *port) static unsigned int __init probe_baud(struct uart_port *port)
@ -119,11 +119,11 @@ static unsigned int __init probe_baud(struct uart_port *port)
unsigned char lcr, dll, dlm; unsigned char lcr, dll, dlm;
unsigned int quot; unsigned int quot;
lcr = serial_in(port, UART_LCR); lcr = serial8250_early_in(port, UART_LCR);
serial_out(port, UART_LCR, lcr | UART_LCR_DLAB); serial8250_early_out(port, UART_LCR, lcr | UART_LCR_DLAB);
dll = serial_in(port, UART_DLL); dll = serial8250_early_in(port, UART_DLL);
dlm = serial_in(port, UART_DLM); dlm = serial8250_early_in(port, UART_DLM);
serial_out(port, UART_LCR, lcr); serial8250_early_out(port, UART_LCR, lcr);
quot = (dlm << 8) | dll; quot = (dlm << 8) | dll;
return (port->uartclk / 16) / quot; return (port->uartclk / 16) / quot;
@ -135,17 +135,17 @@ static void __init init_port(struct early_serial8250_device *device)
unsigned int divisor; unsigned int divisor;
unsigned char c; unsigned char c;
serial_out(port, UART_LCR, 0x3); /* 8n1 */ serial8250_early_out(port, UART_LCR, 0x3); /* 8n1 */
serial_out(port, UART_IER, 0); /* no interrupt */ serial8250_early_out(port, UART_IER, 0); /* no interrupt */
serial_out(port, UART_FCR, 0); /* no fifo */ serial8250_early_out(port, UART_FCR, 0); /* no fifo */
serial_out(port, UART_MCR, 0x3); /* DTR + RTS */ serial8250_early_out(port, UART_MCR, 0x3); /* DTR + RTS */
divisor = port->uartclk / (16 * device->baud); divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
c = serial_in(port, UART_LCR); c = serial8250_early_in(port, UART_LCR);
serial_out(port, UART_LCR, c | UART_LCR_DLAB); serial8250_early_out(port, UART_LCR, c | UART_LCR_DLAB);
serial_out(port, UART_DLL, divisor & 0xff); serial8250_early_out(port, UART_DLL, divisor & 0xff);
serial_out(port, UART_DLM, (divisor >> 8) & 0xff); serial8250_early_out(port, UART_DLM, (divisor >> 8) & 0xff);
serial_out(port, UART_LCR, c & ~UART_LCR_DLAB); serial8250_early_out(port, UART_LCR, c & ~UART_LCR_DLAB);
} }
static int __init parse_options(struct early_serial8250_device *device, static int __init parse_options(struct early_serial8250_device *device,

View File

@ -89,7 +89,7 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value)
serial_out(up, UART_DLM_EM, value >> 8 & 0xff); serial_out(up, UART_DLM_EM, value >> 8 & 0xff);
} }
static int __devinit serial8250_em_probe(struct platform_device *pdev) static int serial8250_em_probe(struct platform_device *pdev)
{ {
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@ -152,7 +152,7 @@ static int __devinit serial8250_em_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int __devexit serial8250_em_remove(struct platform_device *pdev) static int serial8250_em_remove(struct platform_device *pdev)
{ {
struct serial8250_em_priv *priv = platform_get_drvdata(pdev); struct serial8250_em_priv *priv = platform_get_drvdata(pdev);
@ -163,7 +163,7 @@ static int __devexit serial8250_em_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = { static const struct of_device_id serial8250_em_dt_ids[] = {
{ .compatible = "renesas,em-uart", }, { .compatible = "renesas,em-uart", },
{}, {},
}; };
@ -176,7 +176,7 @@ static struct platform_driver serial8250_em_platform_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}, },
.probe = serial8250_em_probe, .probe = serial8250_em_probe,
.remove = __devexit_p(serial8250_em_remove), .remove = serial8250_em_remove,
}; };
module_platform_driver(serial8250_em_platform_driver); module_platform_driver(serial8250_em_platform_driver);

View File

@ -36,9 +36,9 @@ static struct hp300_port *hp300_ports;
#ifdef CONFIG_HPDCA #ifdef CONFIG_HPDCA
static int __devinit hpdca_init_one(struct dio_dev *d, static int hpdca_init_one(struct dio_dev *d,
const struct dio_device_id *ent); const struct dio_device_id *ent);
static void __devexit hpdca_remove_one(struct dio_dev *d); static void hpdca_remove_one(struct dio_dev *d);
static struct dio_device_id hpdca_dio_tbl[] = { static struct dio_device_id hpdca_dio_tbl[] = {
{ DIO_ID_DCA0 }, { DIO_ID_DCA0 },
@ -52,7 +52,7 @@ static struct dio_driver hpdca_driver = {
.name = "hpdca", .name = "hpdca",
.id_table = hpdca_dio_tbl, .id_table = hpdca_dio_tbl,
.probe = hpdca_init_one, .probe = hpdca_init_one,
.remove = __devexit_p(hpdca_remove_one), .remove = hpdca_remove_one,
}; };
#endif #endif
@ -159,7 +159,7 @@ int __init hp300_setup_serial_console(void)
#endif /* CONFIG_SERIAL_8250_CONSOLE */ #endif /* CONFIG_SERIAL_8250_CONSOLE */
#ifdef CONFIG_HPDCA #ifdef CONFIG_HPDCA
static int __devinit hpdca_init_one(struct dio_dev *d, static int hpdca_init_one(struct dio_dev *d,
const struct dio_device_id *ent) const struct dio_device_id *ent)
{ {
struct uart_8250_port uart; struct uart_8250_port uart;
@ -288,7 +288,7 @@ static int __init hp300_8250_init(void)
} }
#ifdef CONFIG_HPDCA #ifdef CONFIG_HPDCA
static void __devexit hpdca_remove_one(struct dio_dev *d) static void hpdca_remove_one(struct dio_dev *d)
{ {
int line; int line;

View File

@ -288,7 +288,7 @@ static int pci_plx9050_init(struct pci_dev *dev)
return 0; return 0;
} }
static void __devexit pci_plx9050_exit(struct pci_dev *dev) static void pci_plx9050_exit(struct pci_dev *dev)
{ {
u8 __iomem *p; u8 __iomem *p;
@ -313,7 +313,7 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev)
#define NI8420_INT_ENABLE_REG 0x38 #define NI8420_INT_ENABLE_REG 0x38
#define NI8420_INT_ENABLE_BIT 0x2000 #define NI8420_INT_ENABLE_BIT 0x2000
static void __devexit pci_ni8420_exit(struct pci_dev *dev) static void pci_ni8420_exit(struct pci_dev *dev)
{ {
void __iomem *p; void __iomem *p;
unsigned long base, len; unsigned long base, len;
@ -345,7 +345,7 @@ static void __devexit pci_ni8420_exit(struct pci_dev *dev)
#define MITE_LCIMR2_CLR_CPU_IE (1 << 30) #define MITE_LCIMR2_CLR_CPU_IE (1 << 30)
static void __devexit pci_ni8430_exit(struct pci_dev *dev) static void pci_ni8430_exit(struct pci_dev *dev)
{ {
void __iomem *p; void __iomem *p;
unsigned long base, len; unsigned long base, len;
@ -422,7 +422,7 @@ static int sbs_init(struct pci_dev *dev)
* Disables the global interrupt of PMC-OctalPro * Disables the global interrupt of PMC-OctalPro
*/ */
static void __devexit sbs_exit(struct pci_dev *dev) static void sbs_exit(struct pci_dev *dev)
{ {
u8 __iomem *p; u8 __iomem *p;
@ -991,7 +991,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
return ret; return ret;
} }
static void __devexit pci_ite887x_exit(struct pci_dev *dev) static void pci_ite887x_exit(struct pci_dev *dev)
{ {
u32 ioport; u32 ioport;
/* the ioport is bit 0-15 in POSIO0R */ /* the ioport is bit 0-15 in POSIO0R */
@ -1068,7 +1068,7 @@ ce4100_serial_setup(struct serial_private *priv,
{ {
int ret; int ret;
ret = setup_port(priv, port, 0, 0, board->reg_shift); ret = setup_port(priv, port, idx, 0, board->reg_shift);
port->port.iotype = UPIO_MEM32; port->port.iotype = UPIO_MEM32;
port->port.type = PORT_XSCALE; port->port.type = PORT_XSCALE;
port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
@ -1164,6 +1164,94 @@ pci_xr17c154_setup(struct serial_private *priv,
return pci_default_setup(priv, board, port, idx); return pci_default_setup(priv, board, port, idx);
} }
static int
pci_xr17v35x_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
u8 __iomem *p;
p = pci_ioremap_bar(priv->dev, 0);
if (p == NULL)
return -ENOMEM;
port->port.flags |= UPF_EXAR_EFR;
/*
* Setup Multipurpose Input/Output pins.
*/
if (idx == 0) {
writeb(0x00, p + 0x8f); /*MPIOINT[7:0]*/
writeb(0x00, p + 0x90); /*MPIOLVL[7:0]*/
writeb(0x00, p + 0x91); /*MPIO3T[7:0]*/
writeb(0x00, p + 0x92); /*MPIOINV[7:0]*/
writeb(0x00, p + 0x93); /*MPIOSEL[7:0]*/
writeb(0x00, p + 0x94); /*MPIOOD[7:0]*/
writeb(0x00, p + 0x95); /*MPIOINT[15:8]*/
writeb(0x00, p + 0x96); /*MPIOLVL[15:8]*/
writeb(0x00, p + 0x97); /*MPIO3T[15:8]*/
writeb(0x00, p + 0x98); /*MPIOINV[15:8]*/
writeb(0x00, p + 0x99); /*MPIOSEL[15:8]*/
writeb(0x00, p + 0x9a); /*MPIOOD[15:8]*/
}
writeb(0x00, p + UART_EXAR_8XMODE);
writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
writeb(128, p + UART_EXAR_TXTRG);
writeb(128, p + UART_EXAR_RXTRG);
iounmap(p);
return pci_default_setup(priv, board, port, idx);
}
#define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004
#define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002
#define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a
#define PCI_DEVICE_ID_COMMTECH_2328PCI335 0x000b
static int
pci_fastcom335_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
u8 __iomem *p;
p = pci_ioremap_bar(priv->dev, 0);
if (p == NULL)
return -ENOMEM;
port->port.flags |= UPF_EXAR_EFR;
/*
* Setup Multipurpose Input/Output pins.
*/
if (idx == 0) {
switch (priv->dev->device) {
case PCI_DEVICE_ID_COMMTECH_4222PCI335:
case PCI_DEVICE_ID_COMMTECH_4224PCI335:
writeb(0x78, p + 0x90); /* MPIOLVL[7:0] */
writeb(0x00, p + 0x92); /* MPIOINV[7:0] */
writeb(0x00, p + 0x93); /* MPIOSEL[7:0] */
break;
case PCI_DEVICE_ID_COMMTECH_2324PCI335:
case PCI_DEVICE_ID_COMMTECH_2328PCI335:
writeb(0x00, p + 0x90); /* MPIOLVL[7:0] */
writeb(0xc0, p + 0x92); /* MPIOINV[7:0] */
writeb(0xc0, p + 0x93); /* MPIOSEL[7:0] */
break;
}
writeb(0x00, p + 0x8f); /* MPIOINT[7:0] */
writeb(0x00, p + 0x91); /* MPIO3T[7:0] */
writeb(0x00, p + 0x94); /* MPIOOD[7:0] */
}
writeb(0x00, p + UART_EXAR_8XMODE);
writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
writeb(32, p + UART_EXAR_TXTRG);
writeb(32, p + UART_EXAR_RXTRG);
iounmap(p);
return pci_default_setup(priv, board, port, idx);
}
static int static int
pci_wch_ch353_setup(struct serial_private *priv, pci_wch_ch353_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
@ -1213,6 +1301,10 @@ pci_wch_ch353_setup(struct serial_private *priv,
#define PCI_VENDOR_ID_AGESTAR 0x5372 #define PCI_VENDOR_ID_AGESTAR 0x5372
#define PCI_DEVICE_ID_AGESTAR_9375 0x6872 #define PCI_DEVICE_ID_AGESTAR_9375 0x6872
#define PCI_VENDOR_ID_ASIX 0x9710 #define PCI_VENDOR_ID_ASIX 0x9710
#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
#define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020
#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */ /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
@ -1314,7 +1406,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ite887x_init, .init = pci_ite887x_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ite887x_exit), .exit = pci_ite887x_exit,
}, },
/* /*
* National Instruments * National Instruments
@ -1326,7 +1418,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1335,7 +1427,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1344,7 +1436,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1353,7 +1445,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1362,7 +1454,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1371,7 +1463,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1380,7 +1472,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1389,7 +1481,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1398,7 +1490,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1407,7 +1499,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1416,7 +1508,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1425,7 +1517,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8420_init, .init = pci_ni8420_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_ni8420_exit), .exit = pci_ni8420_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_NI, .vendor = PCI_VENDOR_ID_NI,
@ -1434,7 +1526,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_ni8430_init, .init = pci_ni8430_init,
.setup = pci_ni8430_setup, .setup = pci_ni8430_setup,
.exit = __devexit_p(pci_ni8430_exit), .exit = pci_ni8430_exit,
}, },
/* /*
* Panacom * Panacom
@ -1446,7 +1538,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_plx9050_init, .init = pci_plx9050_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit), .exit = pci_plx9050_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_PANACOM, .vendor = PCI_VENDOR_ID_PANACOM,
@ -1455,7 +1547,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.init = pci_plx9050_init, .init = pci_plx9050_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit), .exit = pci_plx9050_exit,
}, },
/* /*
* PLX * PLX
@ -1474,7 +1566,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_EXSYS_4055, .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055,
.init = pci_plx9050_init, .init = pci_plx9050_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit), .exit = pci_plx9050_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_PLX, .vendor = PCI_VENDOR_ID_PLX,
@ -1483,7 +1575,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2, .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
.init = pci_plx9050_init, .init = pci_plx9050_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit), .exit = pci_plx9050_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_PLX, .vendor = PCI_VENDOR_ID_PLX,
@ -1492,7 +1584,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584, .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
.init = pci_plx9050_init, .init = pci_plx9050_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit), .exit = pci_plx9050_exit,
}, },
{ {
.vendor = PCI_VENDOR_ID_PLX, .vendor = PCI_VENDOR_ID_PLX,
@ -1501,7 +1593,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_DEVICE_ID_PLX_ROMULUS, .subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
.init = pci_plx9050_init, .init = pci_plx9050_init,
.setup = pci_default_setup, .setup = pci_default_setup,
.exit = __devexit_p(pci_plx9050_exit), .exit = pci_plx9050_exit,
}, },
/* /*
* SBS Technologies, Inc., PMC-OCTALPRO 232 * SBS Technologies, Inc., PMC-OCTALPRO 232
@ -1513,7 +1605,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_OCTPRO232, .subdevice = PCI_SUBDEVICE_ID_OCTPRO232,
.init = sbs_init, .init = sbs_init,
.setup = sbs_setup, .setup = sbs_setup,
.exit = __devexit_p(sbs_exit), .exit = sbs_exit,
}, },
/* /*
* SBS Technologies, Inc., PMC-OCTALPRO 422 * SBS Technologies, Inc., PMC-OCTALPRO 422
@ -1525,7 +1617,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_OCTPRO422, .subdevice = PCI_SUBDEVICE_ID_OCTPRO422,
.init = sbs_init, .init = sbs_init,
.setup = sbs_setup, .setup = sbs_setup,
.exit = __devexit_p(sbs_exit), .exit = sbs_exit,
}, },
/* /*
* SBS Technologies, Inc., P-Octal 232 * SBS Technologies, Inc., P-Octal 232
@ -1537,7 +1629,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_POCTAL232, .subdevice = PCI_SUBDEVICE_ID_POCTAL232,
.init = sbs_init, .init = sbs_init,
.setup = sbs_setup, .setup = sbs_setup,
.exit = __devexit_p(sbs_exit), .exit = sbs_exit,
}, },
/* /*
* SBS Technologies, Inc., P-Octal 422 * SBS Technologies, Inc., P-Octal 422
@ -1549,7 +1641,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_SUBDEVICE_ID_POCTAL422, .subdevice = PCI_SUBDEVICE_ID_POCTAL422,
.init = sbs_init, .init = sbs_init,
.setup = sbs_setup, .setup = sbs_setup,
.exit = __devexit_p(sbs_exit), .exit = sbs_exit,
}, },
/* /*
* SIIG cards - these may be called via parport_serial * SIIG cards - these may be called via parport_serial
@ -1622,6 +1714,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = pci_xr17c154_setup, .setup = pci_xr17c154_setup,
}, },
{
.vendor = PCI_VENDOR_ID_EXAR,
.device = PCI_DEVICE_ID_EXAR_XR17V352,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
{
.vendor = PCI_VENDOR_ID_EXAR,
.device = PCI_DEVICE_ID_EXAR_XR17V354,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
{
.vendor = PCI_VENDOR_ID_EXAR,
.device = PCI_DEVICE_ID_EXAR_XR17V358,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
/* /*
* Xircom cards * Xircom cards
*/ */
@ -1787,6 +1900,59 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.setup = pci_asix_setup, .setup = pci_asix_setup,
}, },
/*
* Commtech, Inc. Fastcom adapters
*
*/
{
.vendor = PCI_VENDOR_ID_COMMTECH,
.device = PCI_DEVICE_ID_COMMTECH_4222PCI335,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fastcom335_setup,
},
{
.vendor = PCI_VENDOR_ID_COMMTECH,
.device = PCI_DEVICE_ID_COMMTECH_4224PCI335,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fastcom335_setup,
},
{
.vendor = PCI_VENDOR_ID_COMMTECH,
.device = PCI_DEVICE_ID_COMMTECH_2324PCI335,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fastcom335_setup,
},
{
.vendor = PCI_VENDOR_ID_COMMTECH,
.device = PCI_DEVICE_ID_COMMTECH_2328PCI335,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_fastcom335_setup,
},
{
.vendor = PCI_VENDOR_ID_COMMTECH,
.device = PCI_DEVICE_ID_COMMTECH_4222PCIE,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
{
.vendor = PCI_VENDOR_ID_COMMTECH,
.device = PCI_DEVICE_ID_COMMTECH_4224PCIE,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
{
.vendor = PCI_VENDOR_ID_COMMTECH,
.device = PCI_DEVICE_ID_COMMTECH_4228PCIE,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_xr17v35x_setup,
},
/* /*
* Default "match everything" terminator entry * Default "match everything" terminator entry
*/ */
@ -1863,6 +2029,10 @@ enum pci_board_num_t {
pbn_b0_4_1152000, pbn_b0_4_1152000,
pbn_b0_2_1152000_200,
pbn_b0_4_1152000_200,
pbn_b0_8_1152000_200,
pbn_b0_2_1843200, pbn_b0_2_1843200,
pbn_b0_4_1843200, pbn_b0_4_1843200,
@ -1962,6 +2132,9 @@ enum pci_board_num_t {
pbn_exar_XR17C152, pbn_exar_XR17C152,
pbn_exar_XR17C154, pbn_exar_XR17C154,
pbn_exar_XR17C158, pbn_exar_XR17C158,
pbn_exar_XR17V352,
pbn_exar_XR17V354,
pbn_exar_XR17V358,
pbn_exar_ibm_saturn, pbn_exar_ibm_saturn,
pbn_pasemi_1682M, pbn_pasemi_1682M,
pbn_ni8430_2, pbn_ni8430_2,
@ -1987,7 +2160,7 @@ enum pci_board_num_t {
* see first lines of serial_in() and serial_out() in 8250.c * see first lines of serial_in() and serial_out() in 8250.c
*/ */
static struct pciserial_board pci_boards[] __devinitdata = { static struct pciserial_board pci_boards[] = {
[pbn_default] = { [pbn_default] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 1, .num_ports = 1,
@ -2057,6 +2230,27 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 8, .uart_offset = 8,
}, },
[pbn_b0_2_1152000_200] = {
.flags = FL_BASE0,
.num_ports = 2,
.base_baud = 1152000,
.uart_offset = 0x200,
},
[pbn_b0_4_1152000_200] = {
.flags = FL_BASE0,
.num_ports = 4,
.base_baud = 1152000,
.uart_offset = 0x200,
},
[pbn_b0_8_1152000_200] = {
.flags = FL_BASE0,
.num_ports = 2,
.base_baud = 1152000,
.uart_offset = 0x200,
},
[pbn_b0_2_1843200] = { [pbn_b0_2_1843200] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 2, .num_ports = 2,
@ -2580,6 +2774,30 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 921600, .base_baud = 921600,
.uart_offset = 0x200, .uart_offset = 0x200,
}, },
[pbn_exar_XR17V352] = {
.flags = FL_BASE0,
.num_ports = 2,
.base_baud = 7812500,
.uart_offset = 0x400,
.reg_shift = 0,
.first_offset = 0,
},
[pbn_exar_XR17V354] = {
.flags = FL_BASE0,
.num_ports = 4,
.base_baud = 7812500,
.uart_offset = 0x400,
.reg_shift = 0,
.first_offset = 0,
},
[pbn_exar_XR17V358] = {
.flags = FL_BASE0,
.num_ports = 8,
.base_baud = 7812500,
.uart_offset = 0x400,
.reg_shift = 0,
.first_offset = 0,
},
[pbn_exar_ibm_saturn] = { [pbn_exar_ibm_saturn] = {
.flags = FL_BASE0, .flags = FL_BASE0,
.num_ports = 1, .num_ports = 1,
@ -2658,8 +2876,8 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.first_offset = 0x1000, .first_offset = 0x1000,
}, },
[pbn_ce4100_1_115200] = { [pbn_ce4100_1_115200] = {
.flags = FL_BASE0, .flags = FL_BASE_BARS,
.num_ports = 1, .num_ports = 2,
.base_baud = 921600, .base_baud = 921600,
.reg_shift = 2, .reg_shift = 2,
}, },
@ -2691,7 +2909,7 @@ static const struct pci_device_id blacklist[] = {
* guess what the configuration might be, based on the pitiful PCI * guess what the configuration might be, based on the pitiful PCI
* serial specs. Returns 0 on success, 1 on failure. * serial specs. Returns 0 on success, 1 on failure.
*/ */
static int __devinit static int
serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
{ {
const struct pci_device_id *bldev; const struct pci_device_id *bldev;
@ -2917,7 +3135,7 @@ EXPORT_SYMBOL_GPL(pciserial_resume_ports);
* Probe one serial board. Unfortunately, there is no rhyme nor reason * Probe one serial board. Unfortunately, there is no rhyme nor reason
* to the arrangement of serial ports on a PCI card. * to the arrangement of serial ports on a PCI card.
*/ */
static int __devinit static int
pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
{ {
struct pci_serial_quirk *quirk; struct pci_serial_quirk *quirk;
@ -2988,7 +3206,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
return rc; return rc;
} }
static void __devexit pciserial_remove_one(struct pci_dev *dev) static void pciserial_remove_one(struct pci_dev *dev)
{ {
struct serial_private *priv = pci_get_drvdata(dev); struct serial_private *priv = pci_get_drvdata(dev);
@ -3826,6 +4044,21 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
0, 0,
0, pbn_exar_XR17C158 }, 0, pbn_exar_XR17C158 },
/*
* Exar Corp. XR17V35[248] Dual/Quad/Octal PCIe UARTs
*/
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V352,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V352 },
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V354,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V354 },
{ PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17V358,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V358 },
/* /*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
@ -4256,6 +4489,38 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
0, 0, pbn_b0_bt_2_115200 }, 0, 0, pbn_b0_bt_2_115200 },
/*
* Commtech, Inc. Fastcom adapters
*/
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCI335,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_b0_2_1152000_200 },
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCI335,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_b0_4_1152000_200 },
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2324PCI335,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_b0_4_1152000_200 },
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_2328PCI335,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_b0_8_1152000_200 },
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4222PCIE,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V352 },
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4224PCIE,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V354 },
{ PCI_VENDOR_ID_COMMTECH, PCI_DEVICE_ID_COMMTECH_4228PCIE,
PCI_ANY_ID, PCI_ANY_ID,
0,
0, pbn_exar_XR17V358 },
/* /*
* These entries match devices with class COMMUNICATION_SERIAL, * These entries match devices with class COMMUNICATION_SERIAL,
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
@ -4323,7 +4588,7 @@ static const struct pci_error_handlers serial8250_err_handler = {
static struct pci_driver serial_pci_driver = { static struct pci_driver serial_pci_driver = {
.name = "serial", .name = "serial",
.probe = pciserial_init_one, .probe = pciserial_init_one,
.remove = __devexit_p(pciserial_remove_one), .remove = pciserial_remove_one,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = pciserial_suspend_one, .suspend = pciserial_suspend_one,
.resume = pciserial_resume_one, .resume = pciserial_resume_one,
@ -4332,18 +4597,7 @@ static struct pci_driver serial_pci_driver = {
.err_handler = &serial8250_err_handler, .err_handler = &serial8250_err_handler,
}; };
static int __init serial8250_pci_init(void) module_pci_driver(serial_pci_driver);
{
return pci_register_driver(&serial_pci_driver);
}
static void __exit serial8250_pci_exit(void)
{
pci_unregister_driver(&serial_pci_driver);
}
module_init(serial8250_pci_init);
module_exit(serial8250_pci_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module"); MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");

View File

@ -370,14 +370,14 @@ static const struct pnp_device_id pnp_dev_table[] = {
MODULE_DEVICE_TABLE(pnp, pnp_dev_table); MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
static char *modem_names[] __devinitdata = { static char *modem_names[] = {
"MODEM", "Modem", "modem", "FAX", "Fax", "fax", "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
"56K", "56k", "K56", "33.6", "28.8", "14.4", "56K", "56k", "K56", "33.6", "28.8", "14.4",
"33,600", "28,800", "14,400", "33.600", "28.800", "14.400", "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
"33600", "28800", "14400", "V.90", "V.34", "V.32", NULL "33600", "28800", "14400", "V.90", "V.34", "V.32", NULL
}; };
static int __devinit check_name(char *name) static int check_name(char *name)
{ {
char **tmp; char **tmp;
@ -388,7 +388,7 @@ static int __devinit check_name(char *name)
return 0; return 0;
} }
static int __devinit check_resources(struct pnp_dev *dev) static int check_resources(struct pnp_dev *dev)
{ {
resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8}; resource_size_t base[] = {0x2f8, 0x3f8, 0x2e8, 0x3e8};
int i; int i;
@ -412,7 +412,7 @@ static int __devinit check_resources(struct pnp_dev *dev)
* PnP modems, alternatively we must hardcode all modems in pnp_devices[] * PnP modems, alternatively we must hardcode all modems in pnp_devices[]
* table. * table.
*/ */
static int __devinit serial_pnp_guess_board(struct pnp_dev *dev) static int serial_pnp_guess_board(struct pnp_dev *dev)
{ {
if (!(check_name(pnp_dev_name(dev)) || if (!(check_name(pnp_dev_name(dev)) ||
(dev->card && check_name(dev->card->name)))) (dev->card && check_name(dev->card->name))))
@ -424,7 +424,7 @@ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev)
return -ENODEV; return -ENODEV;
} }
static int __devinit static int
serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{ {
struct uart_8250_port uart; struct uart_8250_port uart;
@ -476,7 +476,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
return 0; return 0;
} }
static void __devexit serial_pnp_remove(struct pnp_dev *dev) static void serial_pnp_remove(struct pnp_dev *dev)
{ {
long line = (long)pnp_get_drvdata(dev); long line = (long)pnp_get_drvdata(dev);
if (line) if (line)
@ -511,7 +511,7 @@ static int serial_pnp_resume(struct pnp_dev *dev)
static struct pnp_driver serial_pnp_driver = { static struct pnp_driver serial_pnp_driver = {
.name = "serial", .name = "serial",
.probe = serial_pnp_probe, .probe = serial_pnp_probe,
.remove = __devexit_p(serial_pnp_remove), .remove = serial_pnp_remove,
.suspend = serial_pnp_suspend, .suspend = serial_pnp_suspend,
.resume = serial_pnp_resume, .resume = serial_pnp_resume,
.id_table = pnp_dev_table, .id_table = pnp_dev_table,

View File

@ -93,7 +93,7 @@ config SERIAL_SB1250_DUART_CONSOLE
config SERIAL_ATMEL config SERIAL_ATMEL
bool "AT91 / AT32 on-chip serial port support" bool "AT91 / AT32 on-chip serial port support"
depends on (ARM && ARCH_AT91) || AVR32 depends on ARCH_AT91 || AVR32
select SERIAL_CORE select SERIAL_CORE
help help
This enables the driver for the on-chip UARTs of the Atmel This enables the driver for the on-chip UARTs of the Atmel
@ -198,7 +198,7 @@ config SERIAL_CLPS711X_CONSOLE
config SERIAL_SAMSUNG config SERIAL_SAMSUNG
tristate "Samsung SoC serial support" tristate "Samsung SoC serial support"
depends on ARM && PLAT_SAMSUNG depends on PLAT_SAMSUNG
select SERIAL_CORE select SERIAL_CORE
help help
Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
@ -208,14 +208,14 @@ config SERIAL_SAMSUNG
config SERIAL_SAMSUNG_UARTS_4 config SERIAL_SAMSUNG_UARTS_4
bool bool
depends on ARM && PLAT_SAMSUNG depends on PLAT_SAMSUNG
default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442) default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
help help
Internal node for the common case of 4 Samsung compatible UARTs Internal node for the common case of 4 Samsung compatible UARTs
config SERIAL_SAMSUNG_UARTS config SERIAL_SAMSUNG_UARTS
int int
depends on ARM && PLAT_SAMSUNG depends on PLAT_SAMSUNG
default 6 if ARCH_S5P6450 default 6 if ARCH_S5P6450
default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416 default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
default 3 default 3
@ -249,7 +249,7 @@ config SERIAL_SAMSUNG_CONSOLE
config SERIAL_SIRFSOC config SERIAL_SIRFSOC
tristate "SiRF SoC Platform Serial port support" tristate "SiRF SoC Platform Serial port support"
depends on ARM && ARCH_PRIMA2 depends on ARCH_PRIMA2
select SERIAL_CORE select SERIAL_CORE
help help
Support for the on-chip UART on the CSR SiRFprimaII series, Support for the on-chip UART on the CSR SiRFprimaII series,
@ -347,7 +347,7 @@ config SERIAL_ZS_CONSOLE
config SERIAL_21285 config SERIAL_21285
tristate "DC21285 serial port support" tristate "DC21285 serial port support"
depends on ARM && FOOTBRIDGE depends on FOOTBRIDGE
select SERIAL_CORE select SERIAL_CORE
help help
If you have a machine based on a 21285 (Footbridge) StrongARM(R)/ If you have a machine based on a 21285 (Footbridge) StrongARM(R)/
@ -371,7 +371,7 @@ config SERIAL_21285_CONSOLE
config SERIAL_MPSC config SERIAL_MPSC
bool "Marvell MPSC serial port support" bool "Marvell MPSC serial port support"
depends on PPC32 && MV64X60 depends on MV64X60
select SERIAL_CORE select SERIAL_CORE
help help
Say Y here if you want to use the Marvell MPSC serial controller. Say Y here if you want to use the Marvell MPSC serial controller.
@ -408,7 +408,7 @@ config SERIAL_PXA_CONSOLE
config SERIAL_SA1100 config SERIAL_SA1100
bool "SA1100 serial port support" bool "SA1100 serial port support"
depends on ARM && ARCH_SA1100 depends on ARCH_SA1100
select SERIAL_CORE select SERIAL_CORE
help help
If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you
@ -716,7 +716,7 @@ config SERIAL_SH_SCI_DMA
config SERIAL_PNX8XXX config SERIAL_PNX8XXX
bool "Enable PNX8XXX SoCs' UART Support" bool "Enable PNX8XXX SoCs' UART Support"
depends on MIPS && (SOC_PNX8550 || SOC_PNX833X) depends on SOC_PNX8550 || SOC_PNX833X
select SERIAL_CORE select SERIAL_CORE
help help
If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330 If you have a MIPS-based Philips SoC such as PNX8550 or PNX8330
@ -1013,7 +1013,7 @@ config SERIAL_SGI_IOC3
config SERIAL_MSM config SERIAL_MSM
bool "MSM on-chip serial port support" bool "MSM on-chip serial port support"
depends on ARM && ARCH_MSM depends on ARCH_MSM
select SERIAL_CORE select SERIAL_CORE
config SERIAL_MSM_CONSOLE config SERIAL_MSM_CONSOLE
@ -1035,7 +1035,7 @@ config SERIAL_MSM_HS
config SERIAL_VT8500 config SERIAL_VT8500
bool "VIA VT8500 on-chip serial port support" bool "VIA VT8500 on-chip serial port support"
depends on ARM && ARCH_VT8500 depends on ARCH_VT8500
select SERIAL_CORE select SERIAL_CORE
config SERIAL_VT8500_CONSOLE config SERIAL_VT8500_CONSOLE
@ -1045,7 +1045,7 @@ config SERIAL_VT8500_CONSOLE
config SERIAL_NETX config SERIAL_NETX
tristate "NetX serial port support" tristate "NetX serial port support"
depends on ARM && ARCH_NETX depends on ARCH_NETX
select SERIAL_CORE select SERIAL_CORE
help help
If you have a machine based on a Hilscher NetX SoC you If you have a machine based on a Hilscher NetX SoC you
@ -1376,6 +1376,7 @@ config SERIAL_MXS_AUART_CONSOLE
config SERIAL_XILINX_PS_UART config SERIAL_XILINX_PS_UART
tristate "Xilinx PS UART support" tristate "Xilinx PS UART support"
depends on OF
select SERIAL_CORE select SERIAL_CORE
help help
This driver supports the Xilinx PS UART port. This driver supports the Xilinx PS UART port.
@ -1423,4 +1424,27 @@ config SERIAL_EFM32_UART_CONSOLE
depends on SERIAL_EFM32_UART=y depends on SERIAL_EFM32_UART=y
select SERIAL_CORE_CONSOLE select SERIAL_CORE_CONSOLE
config SERIAL_ARC
tristate "ARC UART driver support"
select SERIAL_CORE
help
Driver for on-chip UART for ARC(Synopsys) for the legacy
FPGA Boards (ML50x/ARCAngel4)
config SERIAL_ARC_CONSOLE
bool "Console on ARC UART"
depends on SERIAL_ARC=y
select SERIAL_CORE_CONSOLE
help
Enable system Console on ARC UART
config SERIAL_ARC_NR_PORTS
int "Number of ARC UART ports"
depends on SERIAL_ARC
range 1 3
default "1"
help
Set this to the number of serial ports you want the driver
to support.
endmenu endmenu

View File

@ -82,3 +82,4 @@ obj-$(CONFIG_SERIAL_XILINX_PS_UART) += xilinx_uartps.o
obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o obj-$(CONFIG_SERIAL_SIRFSOC) += sirfsoc_uart.o
obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o obj-$(CONFIG_SERIAL_AR933X) += ar933x_uart.o
obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o obj-$(CONFIG_SERIAL_EFM32_UART) += efm32-uart.o
obj-$(CONFIG_SERIAL_ARC) += arc_uart.o

View File

@ -406,7 +406,7 @@ static struct uart_driver altera_jtaguart_driver = {
.cons = ALTERA_JTAGUART_CONSOLE, .cons = ALTERA_JTAGUART_CONSOLE,
}; };
static int __devinit altera_jtaguart_probe(struct platform_device *pdev) static int altera_jtaguart_probe(struct platform_device *pdev)
{ {
struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data; struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
struct uart_port *port; struct uart_port *port;
@ -453,7 +453,7 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int __devexit altera_jtaguart_remove(struct platform_device *pdev) static int altera_jtaguart_remove(struct platform_device *pdev)
{ {
struct uart_port *port; struct uart_port *port;
int i = pdev->id; int i = pdev->id;
@ -477,7 +477,7 @@ MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
static struct platform_driver altera_jtaguart_platform_driver = { static struct platform_driver altera_jtaguart_platform_driver = {
.probe = altera_jtaguart_probe, .probe = altera_jtaguart_probe,
.remove = __devexit_p(altera_jtaguart_remove), .remove = altera_jtaguart_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,

View File

@ -532,7 +532,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev,
} }
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
static int __devinit altera_uart_probe(struct platform_device *pdev) static int altera_uart_probe(struct platform_device *pdev)
{ {
struct altera_uart_platform_uart *platp = pdev->dev.platform_data; struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
struct uart_port *port; struct uart_port *port;
@ -598,7 +598,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int __devexit altera_uart_remove(struct platform_device *pdev) static int altera_uart_remove(struct platform_device *pdev)
{ {
struct uart_port *port = platform_get_drvdata(pdev); struct uart_port *port = platform_get_drvdata(pdev);
@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, altera_uart_match);
static struct platform_driver altera_uart_platform_driver = { static struct platform_driver altera_uart_platform_driver = {
.probe = altera_uart_probe, .probe = altera_uart_probe,
.remove = __devexit_p(altera_uart_remove), .remove = altera_uart_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,

View File

@ -56,8 +56,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/pinctrl/consumer.h> #include <linux/pinctrl/consumer.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <linux/io.h>
#include <asm/io.h>
#define UART_NR 14 #define UART_NR 14
@ -1973,7 +1972,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
goto out; goto out;
} }
uap = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); uap = devm_kzalloc(&dev->dev, sizeof(struct uart_amba_port),
GFP_KERNEL);
if (uap == NULL) { if (uap == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
@ -1981,16 +1981,17 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
i = pl011_probe_dt_alias(i, &dev->dev); i = pl011_probe_dt_alias(i, &dev->dev);
base = ioremap(dev->res.start, resource_size(&dev->res)); base = devm_ioremap(&dev->dev, dev->res.start,
resource_size(&dev->res));
if (!base) { if (!base) {
ret = -ENOMEM; ret = -ENOMEM;
goto free; goto out;
} }
uap->pinctrl = devm_pinctrl_get(&dev->dev); uap->pinctrl = devm_pinctrl_get(&dev->dev);
if (IS_ERR(uap->pinctrl)) { if (IS_ERR(uap->pinctrl)) {
ret = PTR_ERR(uap->pinctrl); ret = PTR_ERR(uap->pinctrl);
goto unmap; goto out;
} }
uap->pins_default = pinctrl_lookup_state(uap->pinctrl, uap->pins_default = pinctrl_lookup_state(uap->pinctrl,
PINCTRL_STATE_DEFAULT); PINCTRL_STATE_DEFAULT);
@ -2002,10 +2003,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
if (IS_ERR(uap->pins_sleep)) if (IS_ERR(uap->pins_sleep))
dev_dbg(&dev->dev, "could not get sleep pinstate\n"); dev_dbg(&dev->dev, "could not get sleep pinstate\n");
uap->clk = clk_get(&dev->dev, NULL); uap->clk = devm_clk_get(&dev->dev, NULL);
if (IS_ERR(uap->clk)) { if (IS_ERR(uap->clk)) {
ret = PTR_ERR(uap->clk); ret = PTR_ERR(uap->clk);
goto unmap; goto out;
} }
uap->vendor = vendor; uap->vendor = vendor;
@ -2038,11 +2039,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
amba_set_drvdata(dev, NULL); amba_set_drvdata(dev, NULL);
amba_ports[i] = NULL; amba_ports[i] = NULL;
pl011_dma_remove(uap); pl011_dma_remove(uap);
clk_put(uap->clk);
unmap:
iounmap(base);
free:
kfree(uap);
} }
out: out:
return ret; return ret;
@ -2062,9 +2058,6 @@ static int pl011_remove(struct amba_device *dev)
amba_ports[i] = NULL; amba_ports[i] = NULL;
pl011_dma_remove(uap); pl011_dma_remove(uap);
iounmap(uap->port.membase);
clk_put(uap->clk);
kfree(uap);
return 0; return 0;
} }

View File

@ -554,7 +554,7 @@ static struct uart_driver grlib_apbuart_driver = {
/* OF Platform Driver */ /* OF Platform Driver */
/* ======================================================================== */ /* ======================================================================== */
static int __devinit apbuart_probe(struct platform_device *op) static int apbuart_probe(struct platform_device *op)
{ {
int i; int i;
struct uart_port *port = NULL; struct uart_port *port = NULL;

View File

@ -25,11 +25,19 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <asm/div64.h>
#include <asm/mach-ath79/ar933x_uart.h> #include <asm/mach-ath79/ar933x_uart.h>
#include <asm/mach-ath79/ar933x_uart_platform.h> #include <asm/mach-ath79/ar933x_uart_platform.h>
#define DRIVER_NAME "ar933x-uart" #define DRIVER_NAME "ar933x-uart"
#define AR933X_UART_MAX_SCALE 0xff
#define AR933X_UART_MAX_STEP 0xffff
#define AR933X_UART_MIN_BAUD 300
#define AR933X_UART_MAX_BAUD 3000000
#define AR933X_DUMMY_STATUS_RD 0x01 #define AR933X_DUMMY_STATUS_RD 0x01
static struct uart_driver ar933x_uart_driver; static struct uart_driver ar933x_uart_driver;
@ -37,6 +45,8 @@ static struct uart_driver ar933x_uart_driver;
struct ar933x_uart_port { struct ar933x_uart_port {
struct uart_port port; struct uart_port port;
unsigned int ier; /* shadow Interrupt Enable Register */ unsigned int ier; /* shadow Interrupt Enable Register */
unsigned int min_baud;
unsigned int max_baud;
}; };
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up, static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
@ -162,6 +172,57 @@ static void ar933x_uart_enable_ms(struct uart_port *port)
{ {
} }
/*
* baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
*/
static unsigned long ar933x_uart_get_baud(unsigned int clk,
unsigned int scale,
unsigned int step)
{
u64 t;
u32 div;
div = (2 << 16) * (scale + 1);
t = clk;
t *= step;
t += (div / 2);
do_div(t, div);
return t;
}
static void ar933x_uart_get_scale_step(unsigned int clk,
unsigned int baud,
unsigned int *scale,
unsigned int *step)
{
unsigned int tscale;
long min_diff;
*scale = 0;
*step = 0;
min_diff = baud;
for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
u64 tstep;
int diff;
tstep = baud * (tscale + 1);
tstep *= (2 << 16);
do_div(tstep, clk);
if (tstep > AR933X_UART_MAX_STEP)
break;
diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
if (diff < min_diff) {
min_diff = diff;
*scale = tscale;
*step = tstep;
}
}
}
static void ar933x_uart_set_termios(struct uart_port *port, static void ar933x_uart_set_termios(struct uart_port *port,
struct ktermios *new, struct ktermios *new,
struct ktermios *old) struct ktermios *old)
@ -169,7 +230,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
struct ar933x_uart_port *up = (struct ar933x_uart_port *) port; struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
unsigned int cs; unsigned int cs;
unsigned long flags; unsigned long flags;
unsigned int baud, scale; unsigned int baud, scale, step;
/* Only CS8 is supported */ /* Only CS8 is supported */
new->c_cflag &= ~CSIZE; new->c_cflag &= ~CSIZE;
@ -191,8 +252,8 @@ static void ar933x_uart_set_termios(struct uart_port *port,
/* Mark/space parity is not supported */ /* Mark/space parity is not supported */
new->c_cflag &= ~CMSPAR; new->c_cflag &= ~CMSPAR;
baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); baud = uart_get_baud_rate(port, new, old, up->min_baud, up->max_baud);
scale = (port->uartclk / (16 * baud)) - 1; ar933x_uart_get_scale_step(port->uartclk, baud, &scale, &step);
/* /*
* Ok, we're now changing the port state. Do it with * Ok, we're now changing the port state. Do it with
@ -200,6 +261,10 @@ static void ar933x_uart_set_termios(struct uart_port *port,
*/ */
spin_lock_irqsave(&up->port.lock, flags); spin_lock_irqsave(&up->port.lock, flags);
/* disable the UART */
ar933x_uart_rmw_clear(up, AR933X_UART_CS_REG,
AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S);
/* Update the per-port timeout. */ /* Update the per-port timeout. */
uart_update_timeout(port, new->c_cflag, baud); uart_update_timeout(port, new->c_cflag, baud);
@ -210,7 +275,7 @@ static void ar933x_uart_set_termios(struct uart_port *port,
up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD; up->port.ignore_status_mask |= AR933X_DUMMY_STATUS_RD;
ar933x_uart_write(up, AR933X_UART_CLOCK_REG, ar933x_uart_write(up, AR933X_UART_CLOCK_REG,
scale << AR933X_UART_CLOCK_SCALE_S | 8192); scale << AR933X_UART_CLOCK_SCALE_S | step);
/* setup configuration register */ /* setup configuration register */
ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs); ar933x_uart_rmw(up, AR933X_UART_CS_REG, AR933X_UART_CS_PARITY_M, cs);
@ -219,6 +284,11 @@ static void ar933x_uart_set_termios(struct uart_port *port,
ar933x_uart_rmw_set(up, AR933X_UART_CS_REG, ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
AR933X_UART_CS_HOST_INT_EN); AR933X_UART_CS_HOST_INT_EN);
/* reenable the UART */
ar933x_uart_rmw(up, AR933X_UART_CS_REG,
AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S);
spin_unlock_irqrestore(&up->port.lock, flags); spin_unlock_irqrestore(&up->port.lock, flags);
if (tty_termios_baud_rate(new)) if (tty_termios_baud_rate(new))
@ -401,6 +471,8 @@ static void ar933x_uart_config_port(struct uart_port *port, int flags)
static int ar933x_uart_verify_port(struct uart_port *port, static int ar933x_uart_verify_port(struct uart_port *port,
struct serial_struct *ser) struct serial_struct *ser)
{ {
struct ar933x_uart_port *up = (struct ar933x_uart_port *) port;
if (ser->type != PORT_UNKNOWN && if (ser->type != PORT_UNKNOWN &&
ser->type != PORT_AR933X) ser->type != PORT_AR933X)
return -EINVAL; return -EINVAL;
@ -408,7 +480,8 @@ static int ar933x_uart_verify_port(struct uart_port *port,
if (ser->irq < 0 || ser->irq >= NR_IRQS) if (ser->irq < 0 || ser->irq >= NR_IRQS)
return -EINVAL; return -EINVAL;
if (ser->baud_base < 28800) if (ser->baud_base < up->min_baud ||
ser->baud_base > up->max_baud)
return -EINVAL; return -EINVAL;
return 0; return 0;
@ -554,13 +627,14 @@ static struct uart_driver ar933x_uart_driver = {
.cons = AR933X_SERIAL_CONSOLE, .cons = AR933X_SERIAL_CONSOLE,
}; };
static int __devinit ar933x_uart_probe(struct platform_device *pdev) static int ar933x_uart_probe(struct platform_device *pdev)
{ {
struct ar933x_uart_platform_data *pdata; struct ar933x_uart_platform_data *pdata;
struct ar933x_uart_port *up; struct ar933x_uart_port *up;
struct uart_port *port; struct uart_port *port;
struct resource *mem_res; struct resource *mem_res;
struct resource *irq_res; struct resource *irq_res;
unsigned int baud;
int id; int id;
int ret; int ret;
@ -611,6 +685,12 @@ static int __devinit ar933x_uart_probe(struct platform_device *pdev)
port->fifosize = AR933X_UART_FIFO_SIZE; port->fifosize = AR933X_UART_FIFO_SIZE;
port->ops = &ar933x_uart_ops; port->ops = &ar933x_uart_ops;
baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);
up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD);
baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);
up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD);
ar933x_uart_add_console_port(up); ar933x_uart_add_console_port(up);
ret = uart_add_one_port(&ar933x_uart_driver, &up->port); ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
@ -627,7 +707,7 @@ err_free_up:
return ret; return ret;
} }
static int __devexit ar933x_uart_remove(struct platform_device *pdev) static int ar933x_uart_remove(struct platform_device *pdev)
{ {
struct ar933x_uart_port *up; struct ar933x_uart_port *up;
@ -645,7 +725,7 @@ static int __devexit ar933x_uart_remove(struct platform_device *pdev)
static struct platform_driver ar933x_uart_platform_driver = { static struct platform_driver ar933x_uart_platform_driver = {
.probe = ar933x_uart_probe, .probe = ar933x_uart_probe,
.remove = __devexit_p(ar933x_uart_remove), .remove = ar933x_uart_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,

View File

@ -0,0 +1,746 @@
/*
* ARC On-Chip(fpga) UART Driver
*
* Copyright (C) 2010-2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* vineetg: July 10th 2012
* -Decoupled the driver from arch/arc
* +Using platform_get_resource() for irq/membase (thx to bfin_uart.c)
* +Using early_platform_xxx() for early console (thx to mach-shmobile/xxx)
*
* Vineetg: Aug 21st 2010
* -Is uart_tx_stopped() not done in tty write path as it has already been
* taken care of, in serial core
*
* Vineetg: Aug 18th 2010
* -New Serial Core based ARC UART driver
* -Derived largely from blackfin driver albiet with some major tweaks
*
* TODO:
* -check if sysreq works
*/
#if defined(CONFIG_SERIAL_ARC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/io.h>
/*************************************
* ARC UART Hardware Specs
************************************/
#define ARC_UART_TX_FIFO_SIZE 1
/*
* UART Register set (this is not a Standards Compliant IP)
* Also each reg is Word aligned, but only 8 bits wide
*/
#define R_ID0 0
#define R_ID1 4
#define R_ID2 8
#define R_ID3 12
#define R_DATA 16
#define R_STS 20
#define R_BAUDL 24
#define R_BAUDH 28
/* Bits for UART Status Reg (R/W) */
#define RXIENB 0x04 /* Receive Interrupt Enable */
#define TXIENB 0x40 /* Transmit Interrupt Enable */
#define RXEMPTY 0x20 /* Receive FIFO Empty: No char receivede */
#define TXEMPTY 0x80 /* Transmit FIFO Empty, thus char can be written into */
#define RXFULL 0x08 /* Receive FIFO full */
#define RXFULL1 0x10 /* Receive FIFO has space for 1 char (tot space=4) */
#define RXFERR 0x01 /* Frame Error: Stop Bit not detected */
#define RXOERR 0x02 /* OverFlow Err: Char recv but RXFULL still set */
/* Uart bit fiddling helpers: lowest level */
#define RBASE(uart, reg) (uart->port.membase + reg)
#define UART_REG_SET(u, r, v) writeb((v), RBASE(u, r))
#define UART_REG_GET(u, r) readb(RBASE(u, r))
#define UART_REG_OR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) | (v))
#define UART_REG_CLR(u, r, v) UART_REG_SET(u, r, UART_REG_GET(u, r) & ~(v))
/* Uart bit fiddling helpers: API level */
#define UART_SET_DATA(uart, val) UART_REG_SET(uart, R_DATA, val)
#define UART_GET_DATA(uart) UART_REG_GET(uart, R_DATA)
#define UART_SET_BAUDH(uart, val) UART_REG_SET(uart, R_BAUDH, val)
#define UART_SET_BAUDL(uart, val) UART_REG_SET(uart, R_BAUDL, val)
#define UART_CLR_STATUS(uart, val) UART_REG_CLR(uart, R_STS, val)
#define UART_GET_STATUS(uart) UART_REG_GET(uart, R_STS)
#define UART_ALL_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB|TXIENB)
#define UART_RX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, RXIENB)
#define UART_TX_IRQ_DISABLE(uart) UART_REG_CLR(uart, R_STS, TXIENB)
#define UART_ALL_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB|TXIENB)
#define UART_RX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, RXIENB)
#define UART_TX_IRQ_ENABLE(uart) UART_REG_OR(uart, R_STS, TXIENB)
#define ARC_SERIAL_DEV_NAME "ttyARC"
struct arc_uart_port {
struct uart_port port;
unsigned long baud;
int is_emulated; /* H/w vs. Instruction Set Simulator */
};
#define to_arc_port(uport) container_of(uport, struct arc_uart_port, port)
static struct arc_uart_port arc_uart_ports[CONFIG_SERIAL_ARC_NR_PORTS];
#ifdef CONFIG_SERIAL_ARC_CONSOLE
static struct console arc_console;
#endif
#define DRIVER_NAME "arc-uart"
static struct uart_driver arc_uart_driver = {
.owner = THIS_MODULE,
.driver_name = DRIVER_NAME,
.dev_name = ARC_SERIAL_DEV_NAME,
.major = 0,
.minor = 0,
.nr = CONFIG_SERIAL_ARC_NR_PORTS,
#ifdef CONFIG_SERIAL_ARC_CONSOLE
.cons = &arc_console,
#endif
};
static void arc_serial_stop_rx(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
UART_RX_IRQ_DISABLE(uart);
}
static void arc_serial_stop_tx(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
while (!(UART_GET_STATUS(uart) & TXEMPTY))
cpu_relax();
UART_TX_IRQ_DISABLE(uart);
}
/*
* Return TIOCSER_TEMT when transmitter is not busy.
*/
static unsigned int arc_serial_tx_empty(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
unsigned int stat;
stat = UART_GET_STATUS(uart);
if (stat & TXEMPTY)
return TIOCSER_TEMT;
return 0;
}
/*
* Driver internal routine, used by both tty(serial core) as well as tx-isr
* -Called under spinlock in either cases
* -also tty->stopped / tty->hw_stopped has already been checked
* = by uart_start( ) before calling us
* = tx_ist checks that too before calling
*/
static void arc_serial_tx_chars(struct arc_uart_port *uart)
{
struct circ_buf *xmit = &uart->port.state->xmit;
int sent = 0;
unsigned char ch;
if (unlikely(uart->port.x_char)) {
UART_SET_DATA(uart, uart->port.x_char);
uart->port.icount.tx++;
uart->port.x_char = 0;
sent = 1;
} else if (xmit->tail != xmit->head) { /* TODO: uart_circ_empty */
ch = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
uart->port.icount.tx++;
while (!(UART_GET_STATUS(uart) & TXEMPTY))
cpu_relax();
UART_SET_DATA(uart, ch);
sent = 1;
}
/*
* If num chars in xmit buffer are too few, ask tty layer for more.
* By Hard ISR to schedule processing in software interrupt part
*/
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uart->port);
if (sent)
UART_TX_IRQ_ENABLE(uart);
}
/*
* port is locked and interrupts are disabled
* uart_start( ) calls us under the port spinlock irqsave
*/
static void arc_serial_start_tx(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
arc_serial_tx_chars(uart);
}
static void arc_serial_rx_chars(struct arc_uart_port *uart)
{
struct tty_struct *tty = tty_port_tty_get(&uart->port.state->port);
unsigned int status, ch, flg = 0;
if (!tty)
return;
/*
* UART has 4 deep RX-FIFO. Driver's recongnition of this fact
* is very subtle. Here's how ...
* Upon getting a RX-Intr, such that RX-EMPTY=0, meaning data available,
* driver reads the DATA Reg and keeps doing that in a loop, until
* RX-EMPTY=1. Multiple chars being avail, with a single Interrupt,
* before RX-EMPTY=0, implies some sort of buffering going on in the
* controller, which is indeed the Rx-FIFO.
*/
while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) {
ch = UART_GET_DATA(uart);
uart->port.icount.rx++;
if (unlikely(status & (RXOERR | RXFERR))) {
if (status & RXOERR) {
uart->port.icount.overrun++;
flg = TTY_OVERRUN;
UART_CLR_STATUS(uart, RXOERR);
}
if (status & RXFERR) {
uart->port.icount.frame++;
flg = TTY_FRAME;
UART_CLR_STATUS(uart, RXFERR);
}
} else
flg = TTY_NORMAL;
if (unlikely(uart_handle_sysrq_char(&uart->port, ch)))
goto done;
uart_insert_char(&uart->port, status, RXOERR, ch, flg);
done:
tty_flip_buffer_push(tty);
}
tty_kref_put(tty);
}
/*
* A note on the Interrupt handling state machine of this driver
*
* kernel printk writes funnel thru the console driver framework and in order
* to keep things simple as well as efficient, it writes to UART in polled
* mode, in one shot, and exits.
*
* OTOH, Userland output (via tty layer), uses interrupt based writes as there
* can be undeterministic delay between char writes.
*
* Thus Rx-interrupts are always enabled, while tx-interrupts are by default
* disabled.
*
* When tty has some data to send out, serial core calls driver's start_tx
* which
* -checks-if-tty-buffer-has-char-to-send
* -writes-data-to-uart
* -enable-tx-intr
*
* Once data bits are pushed out, controller raises the Tx-room-avail-Interrupt.
* The first thing Tx ISR does is disable further Tx interrupts (as this could
* be the last char to send, before settling down into the quiet polled mode).
* It then calls the exact routine used by tty layer write to send out any
* more char in tty buffer. In case of sending, it re-enables Tx-intr. In case
* of no data, it remains disabled.
* This is how the transmit state machine is dynamically switched on/off
*/
static irqreturn_t arc_serial_isr(int irq, void *dev_id)
{
struct arc_uart_port *uart = dev_id;
unsigned int status;
status = UART_GET_STATUS(uart);
/*
* Single IRQ for both Rx (data available) Tx (room available) Interrupt
* notifications from the UART Controller.
* To demultiplex between the two, we check the relevant bits
*/
if ((status & RXIENB) && !(status & RXEMPTY)) {
/* already in ISR, no need of xx_irqsave */
spin_lock(&uart->port.lock);
arc_serial_rx_chars(uart);
spin_unlock(&uart->port.lock);
}
if ((status & TXIENB) && (status & TXEMPTY)) {
/* Unconditionally disable further Tx-Interrupts.
* will be enabled by tx_chars() if needed.
*/
UART_TX_IRQ_DISABLE(uart);
spin_lock(&uart->port.lock);
if (!uart_tx_stopped(&uart->port))
arc_serial_tx_chars(uart);
spin_unlock(&uart->port.lock);
}
return IRQ_HANDLED;
}
static unsigned int arc_serial_get_mctrl(struct uart_port *port)
{
/*
* Pretend we have a Modem status reg and following bits are
* always set, to satify the serial core state machine
* (DSR) Data Set Ready
* (CTS) Clear To Send
* (CAR) Carrier Detect
*/
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
}
static void arc_serial_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
/* MCR not present */
}
/* Enable Modem Status Interrupts */
static void arc_serial_enable_ms(struct uart_port *port)
{
/* MSR not present */
}
static void arc_serial_break_ctl(struct uart_port *port, int break_state)
{
/* ARC UART doesn't support sending Break signal */
}
static int arc_serial_startup(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
/* Before we hook up the ISR, Disable all UART Interrupts */
UART_ALL_IRQ_DISABLE(uart);
if (request_irq(uart->port.irq, arc_serial_isr, 0, "arc uart rx-tx",
uart)) {
dev_warn(uart->port.dev, "Unable to attach ARC UART intr\n");
return -EBUSY;
}
UART_RX_IRQ_ENABLE(uart); /* Only Rx IRQ enabled to begin with */
return 0;
}
/* This is not really needed */
static void arc_serial_shutdown(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
free_irq(uart->port.irq, uart);
}
static void
arc_serial_set_termios(struct uart_port *port, struct ktermios *new,
struct ktermios *old)
{
struct arc_uart_port *uart = to_arc_port(port);
unsigned int baud, uartl, uarth, hw_val;
unsigned long flags;
/*
* Use the generic handler so that any specially encoded baud rates
* such as SPD_xx flags or "%B0" can be handled
* Max Baud I suppose will not be more than current 115K * 4
* Formula for ARC UART is: hw-val = ((CLK/(BAUD*4)) -1)
* spread over two 8-bit registers
*/
baud = uart_get_baud_rate(port, new, old, 0, 460800);
hw_val = port->uartclk / (uart->baud * 4) - 1;
uartl = hw_val & 0xFF;
uarth = (hw_val >> 8) & 0xFF;
/*
* UART ISS(Instruction Set simulator) emulation has a subtle bug:
* A existing value of Baudh = 0 is used as a indication to startup
* it's internal state machine.
* Thus if baudh is set to 0, 2 times, it chokes.
* This happens with BAUD=115200 and the formaula above
* Until that is fixed, when running on ISS, we will set baudh to !0
*/
if (uart->is_emulated)
uarth = 1;
spin_lock_irqsave(&port->lock, flags);
UART_ALL_IRQ_DISABLE(uart);
UART_SET_BAUDL(uart, uartl);
UART_SET_BAUDH(uart, uarth);
UART_RX_IRQ_ENABLE(uart);
/*
* UART doesn't support Parity/Hardware Flow Control;
* Only supports 8N1 character size
*/
new->c_cflag &= ~(CMSPAR|CRTSCTS|CSIZE);
new->c_cflag |= CS8;
if (old)
tty_termios_copy_hw(new, old);
/* Don't rewrite B0 */
if (tty_termios_baud_rate(new))
tty_termios_encode_baud_rate(new, baud, baud);
uart_update_timeout(port, new->c_cflag, baud);
spin_unlock_irqrestore(&port->lock, flags);
}
static const char *arc_serial_type(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
return uart->port.type == PORT_ARC ? DRIVER_NAME : NULL;
}
static void arc_serial_release_port(struct uart_port *port)
{
}
static int arc_serial_request_port(struct uart_port *port)
{
return 0;
}
/*
* Verify the new serial_struct (for TIOCSSERIAL).
*/
static int
arc_serial_verify_port(struct uart_port *port, struct serial_struct *ser)
{
if (port->type != PORT_UNKNOWN && ser->type != PORT_ARC)
return -EINVAL;
return 0;
}
/*
* Configure/autoconfigure the port.
*/
static void arc_serial_config_port(struct uart_port *port, int flags)
{
struct arc_uart_port *uart = to_arc_port(port);
if (flags & UART_CONFIG_TYPE)
uart->port.type = PORT_ARC;
}
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_ARC_CONSOLE)
static void arc_serial_poll_putchar(struct uart_port *port, unsigned char chr)
{
struct arc_uart_port *uart = to_arc_port(port);
while (!(UART_GET_STATUS(uart) & TXEMPTY))
cpu_relax();
UART_SET_DATA(uart, chr);
}
#endif
#ifdef CONFIG_CONSOLE_POLL
static int arc_serial_poll_getchar(struct uart_port *port)
{
struct arc_uart_port *uart = to_arc_port(port);
unsigned char chr;
while (!(UART_GET_STATUS(uart) & RXEMPTY))
cpu_relax();
chr = UART_GET_DATA(uart);
return chr;
}
#endif
static struct uart_ops arc_serial_pops = {
.tx_empty = arc_serial_tx_empty,
.set_mctrl = arc_serial_set_mctrl,
.get_mctrl = arc_serial_get_mctrl,
.stop_tx = arc_serial_stop_tx,
.start_tx = arc_serial_start_tx,
.stop_rx = arc_serial_stop_rx,
.enable_ms = arc_serial_enable_ms,
.break_ctl = arc_serial_break_ctl,
.startup = arc_serial_startup,
.shutdown = arc_serial_shutdown,
.set_termios = arc_serial_set_termios,
.type = arc_serial_type,
.release_port = arc_serial_release_port,
.request_port = arc_serial_request_port,
.config_port = arc_serial_config_port,
.verify_port = arc_serial_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_put_char = arc_serial_poll_putchar,
.poll_get_char = arc_serial_poll_getchar,
#endif
};
static int
arc_uart_init_one(struct platform_device *pdev, struct arc_uart_port *uart)
{
struct resource *res, *res2;
unsigned long *plat_data;
if (pdev->id < 0 || pdev->id >= CONFIG_SERIAL_ARC_NR_PORTS) {
dev_err(&pdev->dev, "Wrong uart platform device id.\n");
return -ENOENT;
}
plat_data = ((unsigned long *)(pdev->dev.platform_data));
uart->baud = plat_data[0];
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res2)
return -ENODEV;
uart->port.mapbase = res->start;
uart->port.membase = ioremap_nocache(res->start, resource_size(res));
if (!uart->port.membase)
/* No point of dev_err since UART itself is hosed here */
return -ENXIO;
uart->port.irq = res2->start;
uart->port.dev = &pdev->dev;
uart->port.iotype = UPIO_MEM;
uart->port.flags = UPF_BOOT_AUTOCONF;
uart->port.line = pdev->id;
uart->port.ops = &arc_serial_pops;
uart->port.uartclk = plat_data[1];
uart->port.fifosize = ARC_UART_TX_FIFO_SIZE;
/*
* uart_insert_char( ) uses it in decideding whether to ignore a
* char or not. Explicitly setting it here, removes the subtelty
*/
uart->port.ignore_status_mask = 0;
/* Real Hardware vs. emulated to work around a bug */
uart->is_emulated = !!plat_data[2];
return 0;
}
#ifdef CONFIG_SERIAL_ARC_CONSOLE
static int arc_serial_console_setup(struct console *co, char *options)
{
struct uart_port *port;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';
if (co->index < 0 || co->index >= CONFIG_SERIAL_ARC_NR_PORTS)
return -ENODEV;
/*
* The uart port backing the console (e.g. ttyARC1) might not have been
* init yet. If so, defer the console setup to after the port.
*/
port = &arc_uart_ports[co->index].port;
if (!port->membase)
return -ENODEV;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
/*
* Serial core will call port->ops->set_termios( )
* which will set the baud reg
*/
return uart_set_options(port, co, baud, parity, bits, flow);
}
static void arc_serial_console_putchar(struct uart_port *port, int ch)
{
arc_serial_poll_putchar(port, (unsigned char)ch);
}
/*
* Interrupts are disabled on entering
*/
static void arc_serial_console_write(struct console *co, const char *s,
unsigned int count)
{
struct uart_port *port = &arc_uart_ports[co->index].port;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
uart_console_write(port, s, count, arc_serial_console_putchar);
spin_unlock_irqrestore(&port->lock, flags);
}
static struct console arc_console = {
.name = ARC_SERIAL_DEV_NAME,
.write = arc_serial_console_write,
.device = uart_console_device,
.setup = arc_serial_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &arc_uart_driver
};
static __init void early_serial_write(struct console *con, const char *s,
unsigned int n)
{
struct uart_port *port = &arc_uart_ports[con->index].port;
unsigned int i;
for (i = 0; i < n; i++, s++) {
if (*s == '\n')
arc_serial_poll_putchar(port, '\r');
arc_serial_poll_putchar(port, *s);
}
}
static struct __initdata console arc_early_serial_console = {
.name = "early_ARCuart",
.write = early_serial_write,
.flags = CON_PRINTBUFFER | CON_BOOT,
.index = -1
};
static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
{
arc_early_serial_console.index = pdev->id;
arc_uart_init_one(pdev, &arc_uart_ports[pdev->id]);
arc_serial_console_setup(&arc_early_serial_console, NULL);
register_console(&arc_early_serial_console);
return 0;
}
#else
static int arc_serial_probe_earlyprintk(struct platform_device *pdev)
{
return -ENODEV;
}
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
static int arc_serial_probe(struct platform_device *pdev)
{
struct arc_uart_port *uart;
int rc;
if (is_early_platform_device(pdev))
return arc_serial_probe_earlyprintk(pdev);
uart = &arc_uart_ports[pdev->id];
rc = arc_uart_init_one(pdev, uart);
if (rc)
return rc;
return uart_add_one_port(&arc_uart_driver, &uart->port);
}
static int arc_serial_remove(struct platform_device *pdev)
{
/* This will never be called */
return 0;
}
static struct platform_driver arc_platform_driver = {
.probe = arc_serial_probe,
.remove = arc_serial_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
#ifdef CONFIG_SERIAL_ARC_CONSOLE
/*
* Register an early platform driver of "earlyprintk" class.
* ARCH platform code installs the driver and probes the early devices
* The installation could rely on user specifying earlyprintk=xyx in cmd line
* or it could be done independently, for all "earlyprintk" class drivers.
* [see arch/arc/plat-arcfpga/platform.c]
*/
early_platform_init("earlyprintk", &arc_platform_driver);
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
static int __init arc_serial_init(void)
{
int ret;
ret = uart_register_driver(&arc_uart_driver);
if (ret)
return ret;
ret = platform_driver_register(&arc_platform_driver);
if (ret)
uart_unregister_driver(&arc_uart_driver);
return ret;
}
static void __exit arc_serial_exit(void)
{
platform_driver_unregister(&arc_platform_driver);
uart_unregister_driver(&arc_uart_driver);
}
module_init(arc_serial_init);
module_exit(arc_serial_exit);
MODULE_LICENSE("GPL");
MODULE_ALIAS("plat-arcfpga/uart");
MODULE_AUTHOR("Vineet Gupta");
MODULE_DESCRIPTION("ARC(Synopsys) On-Chip(fpga) serial driver");

View File

@ -1424,7 +1424,7 @@ static struct uart_ops atmel_pops = {
#endif #endif
}; };
static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, static void atmel_of_init_port(struct atmel_uart_port *atmel_port,
struct device_node *np) struct device_node *np)
{ {
u32 rs485_delay[2]; u32 rs485_delay[2];
@ -1459,7 +1459,7 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
/* /*
* Configure the port from the platform device resource info. * Configure the port from the platform device resource info.
*/ */
static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, static void atmel_init_port(struct atmel_uart_port *atmel_port,
struct platform_device *pdev) struct platform_device *pdev)
{ {
struct uart_port *port = &atmel_port->uart; struct uart_port *port = &atmel_port->uart;
@ -1767,7 +1767,7 @@ static int atmel_serial_resume(struct platform_device *pdev)
#define atmel_serial_resume NULL #define atmel_serial_resume NULL
#endif #endif
static int __devinit atmel_serial_probe(struct platform_device *pdev) static int atmel_serial_probe(struct platform_device *pdev)
{ {
struct atmel_uart_port *port; struct atmel_uart_port *port;
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
@ -1859,7 +1859,7 @@ err:
return ret; return ret;
} }
static int __devexit atmel_serial_remove(struct platform_device *pdev) static int atmel_serial_remove(struct platform_device *pdev)
{ {
struct uart_port *port = platform_get_drvdata(pdev); struct uart_port *port = platform_get_drvdata(pdev);
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
@ -1884,7 +1884,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev)
static struct platform_driver atmel_serial_driver = { static struct platform_driver atmel_serial_driver = {
.probe = atmel_serial_probe, .probe = atmel_serial_probe,
.remove = __devexit_p(atmel_serial_remove), .remove = atmel_serial_remove,
.suspend = atmel_serial_suspend, .suspend = atmel_serial_suspend,
.resume = atmel_serial_resume, .resume = atmel_serial_resume,
.driver = { .driver = {

View File

@ -801,7 +801,7 @@ static struct uart_driver bcm_uart_driver = {
/* /*
* platform driver probe/remove callback * platform driver probe/remove callback
*/ */
static int __devinit bcm_uart_probe(struct platform_device *pdev) static int bcm_uart_probe(struct platform_device *pdev)
{ {
struct resource *res_mem, *res_irq; struct resource *res_mem, *res_irq;
struct uart_port *port; struct uart_port *port;
@ -848,7 +848,7 @@ static int __devinit bcm_uart_probe(struct platform_device *pdev)
return 0; return 0;
} }
static int __devexit bcm_uart_remove(struct platform_device *pdev) static int bcm_uart_remove(struct platform_device *pdev)
{ {
struct uart_port *port; struct uart_port *port;
@ -865,7 +865,7 @@ static int __devexit bcm_uart_remove(struct platform_device *pdev)
*/ */
static struct platform_driver bcm_uart_platform_driver = { static struct platform_driver bcm_uart_platform_driver = {
.probe = bcm_uart_probe, .probe = bcm_uart_probe,
.remove = __devexit_p(bcm_uart_remove), .remove = bcm_uart_remove,
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "bcm63xx_uart", .name = "bcm63xx_uart",

View File

@ -740,7 +740,7 @@ static struct dev_pm_ops bfin_sport_uart_dev_pm_ops = {
}; };
#endif #endif
static int __devinit sport_uart_probe(struct platform_device *pdev) static int sport_uart_probe(struct platform_device *pdev)
{ {
struct resource *res; struct resource *res;
struct sport_uart_port *sport; struct sport_uart_port *sport;
@ -850,7 +850,7 @@ out_error_free_mem:
return ret; return ret;
} }
static int __devexit sport_uart_remove(struct platform_device *pdev) static int sport_uart_remove(struct platform_device *pdev)
{ {
struct sport_uart_port *sport = platform_get_drvdata(pdev); struct sport_uart_port *sport = platform_get_drvdata(pdev);
@ -871,7 +871,7 @@ static int __devexit sport_uart_remove(struct platform_device *pdev)
static struct platform_driver sport_uart_driver = { static struct platform_driver sport_uart_driver = {
.probe = sport_uart_probe, .probe = sport_uart_probe,
.remove = __devexit_p(sport_uart_remove), .remove = sport_uart_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
#ifdef CONFIG_PM #ifdef CONFIG_PM

View File

@ -477,9 +477,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
{ {
int x_pos, pos; int x_pos, pos;
unsigned long flags;
dma_disable_irq_nosync(uart->rx_dma_channel); spin_lock_irqsave(&uart->rx_lock, flags);
spin_lock_bh(&uart->rx_lock);
/* 2D DMA RX buffer ring is used. Because curr_y_count and /* 2D DMA RX buffer ring is used. Because curr_y_count and
* curr_x_count can't be read as an atomic operation, * curr_x_count can't be read as an atomic operation,
@ -510,8 +510,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
uart->rx_dma_buf.tail = uart->rx_dma_buf.head; uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
} }
spin_unlock_bh(&uart->rx_lock); spin_unlock_irqrestore(&uart->rx_lock, flags);
dma_enable_irq(uart->rx_dma_channel);
mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
} }
@ -800,6 +799,7 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
unsigned long flags; unsigned long flags;
unsigned int baud, quot; unsigned int baud, quot;
unsigned int ier, lcr = 0; unsigned int ier, lcr = 0;
unsigned long timeout;
switch (termios->c_cflag & CSIZE) { switch (termios->c_cflag & CSIZE) {
case CS8: case CS8:
@ -869,6 +869,14 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15); UART_SET_ANOMALY_THRESHOLD(uart, USEC_PER_SEC / baud * 15);
/* Wait till the transfer buffer is empty */
timeout = jiffies + msecs_to_jiffies(10);
while (UART_GET_GCTL(uart) & UCEN && !(UART_GET_LSR(uart) & TEMT))
if (time_after(jiffies, timeout)) {
dev_warn(port->dev, "timeout waiting for TX buffer empty\n");
break;
}
/* Disable UART */ /* Disable UART */
ier = UART_GET_IER(uart); ier = UART_GET_IER(uart);
UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN); UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN);
@ -1390,7 +1398,7 @@ out_error_free_mem:
return ret; return ret;
} }
static int __devexit bfin_serial_remove(struct platform_device *pdev) static int bfin_serial_remove(struct platform_device *pdev)
{ {
struct bfin_serial_port *uart = platform_get_drvdata(pdev); struct bfin_serial_port *uart = platform_get_drvdata(pdev);
@ -1410,7 +1418,7 @@ static int __devexit bfin_serial_remove(struct platform_device *pdev)
static struct platform_driver bfin_serial_driver = { static struct platform_driver bfin_serial_driver = {
.probe = bfin_serial_probe, .probe = bfin_serial_probe,
.remove = __devexit_p(bfin_serial_remove), .remove = bfin_serial_remove,
.suspend = bfin_serial_suspend, .suspend = bfin_serial_suspend,
.resume = bfin_serial_resume, .resume = bfin_serial_resume,
.driver = { .driver = {

View File

@ -10,15 +10,6 @@
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@ -26,172 +17,169 @@
#endif #endif
#include <linux/module.h> #include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/spinlock.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/tty.h> #include <linux/console.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/irq.h>
#define UART_NR 2 #define UART_CLPS711X_NAME "uart-clps711x"
#define UART_CLPS711X_NR 2
#define UART_CLPS711X_MAJOR 204
#define UART_CLPS711X_MINOR 40
#define SERIAL_CLPS711X_MAJOR 204 #define UBRLCR(port) ((port)->line ? UBRLCR2 : UBRLCR1)
#define SERIAL_CLPS711X_MINOR 40 #define UARTDR(port) ((port)->line ? UARTDR2 : UARTDR1)
#define SERIAL_CLPS711X_NR UART_NR #define SYSFLG(port) ((port)->line ? SYSFLG2 : SYSFLG1)
#define SYSCON(port) ((port)->line ? SYSCON2 : SYSCON1)
#define TX_IRQ(port) ((port)->line ? IRQ_UTXINT2 : IRQ_UTXINT1)
#define RX_IRQ(port) ((port)->line ? IRQ_URXINT2 : IRQ_URXINT1)
/* struct clps711x_port {
* We use the relevant SYSCON register as a base address for these ports. struct uart_driver uart;
*/ struct clk *uart_clk;
#define UBRLCR(port) ((port)->iobase + UBRLCR1 - SYSCON1) struct uart_port port[UART_CLPS711X_NR];
#define UARTDR(port) ((port)->iobase + UARTDR1 - SYSCON1) int tx_enabled[UART_CLPS711X_NR];
#define SYSFLG(port) ((port)->iobase + SYSFLG1 - SYSCON1) #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
#define SYSCON(port) ((port)->iobase + SYSCON1 - SYSCON1) struct console console;
#endif
};
#define TX_IRQ(port) ((port)->irq) static void uart_clps711x_stop_tx(struct uart_port *port)
#define RX_IRQ(port) ((port)->irq + 1)
#define UART_ANY_ERR (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR)
#define tx_enabled(port) ((port)->unused[0])
static void clps711xuart_stop_tx(struct uart_port *port)
{ {
if (tx_enabled(port)) { struct clps711x_port *s = dev_get_drvdata(port->dev);
if (s->tx_enabled[port->line]) {
disable_irq(TX_IRQ(port)); disable_irq(TX_IRQ(port));
tx_enabled(port) = 0; s->tx_enabled[port->line] = 0;
} }
} }
static void clps711xuart_start_tx(struct uart_port *port) static void uart_clps711x_start_tx(struct uart_port *port)
{ {
if (!tx_enabled(port)) { struct clps711x_port *s = dev_get_drvdata(port->dev);
if (!s->tx_enabled[port->line]) {
enable_irq(TX_IRQ(port)); enable_irq(TX_IRQ(port));
tx_enabled(port) = 1; s->tx_enabled[port->line] = 1;
} }
} }
static void clps711xuart_stop_rx(struct uart_port *port) static void uart_clps711x_stop_rx(struct uart_port *port)
{ {
disable_irq(RX_IRQ(port)); disable_irq(RX_IRQ(port));
} }
static void clps711xuart_enable_ms(struct uart_port *port) static void uart_clps711x_enable_ms(struct uart_port *port)
{ {
/* Do nothing */
} }
static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id) static irqreturn_t uart_clps711x_int_rx(int irq, void *dev_id)
{ {
struct uart_port *port = dev_id; struct uart_port *port = dev_id;
struct tty_struct *tty = port->state->port.tty; struct tty_struct *tty = tty_port_tty_get(&port->state->port);
unsigned int status, ch, flg; unsigned int status, ch, flg;
status = clps_readl(SYSFLG(port)); if (!tty)
while (!(status & SYSFLG_URXFE)) { return IRQ_HANDLED;
ch = clps_readl(UARTDR(port));
for (;;) {
status = clps_readl(SYSFLG(port));
if (status & SYSFLG_URXFE)
break;
ch = clps_readw(UARTDR(port));
status = ch & (UARTDR_FRMERR | UARTDR_PARERR | UARTDR_OVERR);
ch &= 0xff;
port->icount.rx++; port->icount.rx++;
flg = TTY_NORMAL; flg = TTY_NORMAL;
/* if (unlikely(status)) {
* Note that the error handling code is if (status & UARTDR_PARERR)
* out of the main execution path
*/
if (unlikely(ch & UART_ANY_ERR)) {
if (ch & UARTDR_PARERR)
port->icount.parity++; port->icount.parity++;
else if (ch & UARTDR_FRMERR) else if (status & UARTDR_FRMERR)
port->icount.frame++; port->icount.frame++;
if (ch & UARTDR_OVERR) else if (status & UARTDR_OVERR)
port->icount.overrun++; port->icount.overrun++;
ch &= port->read_status_mask; status &= port->read_status_mask;
if (ch & UARTDR_PARERR) if (status & UARTDR_PARERR)
flg = TTY_PARITY; flg = TTY_PARITY;
else if (ch & UARTDR_FRMERR) else if (status & UARTDR_FRMERR)
flg = TTY_FRAME; flg = TTY_FRAME;
else if (status & UARTDR_OVERR)
#ifdef SUPPORT_SYSRQ flg = TTY_OVERRUN;
port->sysrq = 0;
#endif
} }
if (uart_handle_sysrq_char(port, ch)) if (uart_handle_sysrq_char(port, ch))
goto ignore_char; continue;
/* if (status & port->ignore_status_mask)
* CHECK: does overrun affect the current character? continue;
* ASSUMPTION: it does not.
*/
uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
ignore_char: uart_insert_char(port, status, UARTDR_OVERR, ch, flg);
status = clps_readl(SYSFLG(port));
} }
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
tty_kref_put(tty);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id) static irqreturn_t uart_clps711x_int_tx(int irq, void *dev_id)
{ {
struct uart_port *port = dev_id; struct uart_port *port = dev_id;
struct clps711x_port *s = dev_get_drvdata(port->dev);
struct circ_buf *xmit = &port->state->xmit; struct circ_buf *xmit = &port->state->xmit;
int count;
if (port->x_char) { if (port->x_char) {
clps_writel(port->x_char, UARTDR(port)); clps_writew(port->x_char, UARTDR(port));
port->icount.tx++; port->icount.tx++;
port->x_char = 0; port->x_char = 0;
return IRQ_HANDLED; return IRQ_HANDLED;
} }
if (uart_circ_empty(xmit) || uart_tx_stopped(port)) if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
goto disable_tx_irq; disable_irq_nosync(TX_IRQ(port));
s->tx_enabled[port->line] = 0;
return IRQ_HANDLED;
}
count = port->fifosize >> 1; while (!uart_circ_empty(xmit)) {
do { clps_writew(xmit->buf[xmit->tail], UARTDR(port));
clps_writel(xmit->buf[xmit->tail], UARTDR(port));
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++; port->icount.tx++;
if (uart_circ_empty(xmit)) if (clps_readl(SYSFLG(port) & SYSFLG_UTXFF))
break; break;
} while (--count > 0); }
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port); uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
disable_tx_irq:
disable_irq_nosync(TX_IRQ(port));
tx_enabled(port) = 0;
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static unsigned int clps711xuart_tx_empty(struct uart_port *port) static unsigned int uart_clps711x_tx_empty(struct uart_port *port)
{ {
unsigned int status = clps_readl(SYSFLG(port)); return (clps_readl(SYSFLG(port) & SYSFLG_UBUSY)) ? 0 : TIOCSER_TEMT;
return status & SYSFLG_UBUSY ? 0 : TIOCSER_TEMT;
} }
static unsigned int clps711xuart_get_mctrl(struct uart_port *port) static unsigned int uart_clps711x_get_mctrl(struct uart_port *port)
{ {
unsigned int port_addr; unsigned int status, result = 0;
unsigned int result = 0;
unsigned int status;
port_addr = SYSFLG(port); if (port->line == 0) {
if (port_addr == SYSFLG1) {
status = clps_readl(SYSFLG1); status = clps_readl(SYSFLG1);
if (status & SYSFLG1_DCD) if (status & SYSFLG1_DCD)
result |= TIOCM_CAR; result |= TIOCM_CAR;
@ -199,104 +187,86 @@ static unsigned int clps711xuart_get_mctrl(struct uart_port *port)
result |= TIOCM_DSR; result |= TIOCM_DSR;
if (status & SYSFLG1_CTS) if (status & SYSFLG1_CTS)
result |= TIOCM_CTS; result |= TIOCM_CTS;
} } else
result = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
return result; return result;
} }
static void static void uart_clps711x_set_mctrl(struct uart_port *port, unsigned int mctrl)
clps711xuart_set_mctrl_null(struct uart_port *port, unsigned int mctrl)
{ {
/* Do nothing */
} }
static void clps711xuart_break_ctl(struct uart_port *port, int break_state) static void uart_clps711x_break_ctl(struct uart_port *port, int break_state)
{ {
unsigned long flags; unsigned long flags;
unsigned int ubrlcr; unsigned int ubrlcr;
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
ubrlcr = clps_readl(UBRLCR(port)); ubrlcr = clps_readl(UBRLCR(port));
if (break_state == -1) if (break_state)
ubrlcr |= UBRLCR_BREAK; ubrlcr |= UBRLCR_BREAK;
else else
ubrlcr &= ~UBRLCR_BREAK; ubrlcr &= ~UBRLCR_BREAK;
clps_writel(ubrlcr, UBRLCR(port)); clps_writel(ubrlcr, UBRLCR(port));
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
} }
static int clps711xuart_startup(struct uart_port *port) static int uart_clps711x_startup(struct uart_port *port)
{ {
unsigned int syscon; struct clps711x_port *s = dev_get_drvdata(port->dev);
int retval; int ret;
tx_enabled(port) = 1; s->tx_enabled[port->line] = 1;
/* Allocate the IRQs */
ret = devm_request_irq(port->dev, TX_IRQ(port), uart_clps711x_int_tx,
0, UART_CLPS711X_NAME " TX", port);
if (ret)
return ret;
/* ret = devm_request_irq(port->dev, RX_IRQ(port), uart_clps711x_int_rx,
* Allocate the IRQs 0, UART_CLPS711X_NAME " RX", port);
*/ if (ret) {
retval = request_irq(TX_IRQ(port), clps711xuart_int_tx, 0, devm_free_irq(port->dev, TX_IRQ(port), port);
"clps711xuart_tx", port); return ret;
if (retval)
return retval;
retval = request_irq(RX_IRQ(port), clps711xuart_int_rx, 0,
"clps711xuart_rx", port);
if (retval) {
free_irq(TX_IRQ(port), port);
return retval;
} }
/* /* Disable break */
* enable the port clps_writel(clps_readl(UBRLCR(port)) & ~UBRLCR_BREAK, UBRLCR(port));
*/
syscon = clps_readl(SYSCON(port)); /* Enable the port */
syscon |= SYSCON_UARTEN; clps_writel(clps_readl(SYSCON(port)) | SYSCON_UARTEN, SYSCON(port));
clps_writel(syscon, SYSCON(port));
return 0; return 0;
} }
static void clps711xuart_shutdown(struct uart_port *port) static void uart_clps711x_shutdown(struct uart_port *port)
{ {
unsigned int ubrlcr, syscon; /* Free the interrupts */
devm_free_irq(port->dev, TX_IRQ(port), port);
devm_free_irq(port->dev, RX_IRQ(port), port);
/* /* Disable the port */
* Free the interrupt clps_writel(clps_readl(SYSCON(port)) & ~SYSCON_UARTEN, SYSCON(port));
*/
free_irq(TX_IRQ(port), port); /* TX interrupt */
free_irq(RX_IRQ(port), port); /* RX interrupt */
/*
* disable the port
*/
syscon = clps_readl(SYSCON(port));
syscon &= ~SYSCON_UARTEN;
clps_writel(syscon, SYSCON(port));
/*
* disable break condition and fifos
*/
ubrlcr = clps_readl(UBRLCR(port));
ubrlcr &= ~(UBRLCR_FIFOEN | UBRLCR_BREAK);
clps_writel(ubrlcr, UBRLCR(port));
} }
static void static void uart_clps711x_set_termios(struct uart_port *port,
clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
{ {
unsigned int ubrlcr, baud, quot; unsigned int ubrlcr, baud, quot;
unsigned long flags; unsigned long flags;
/* /* Mask termios capabilities we don't support */
* We don't implement CREAD. termios->c_cflag &= ~CMSPAR;
*/ termios->c_iflag &= ~(BRKINT | IGNBRK);
termios->c_cflag |= CREAD;
/* /* Ask the core to calculate the divisor for us */
* Ask the core to calculate the divisor for us. baud = uart_get_baud_rate(port, termios, old, port->uartclk / 4096,
*/ port->uartclk / 16);
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud); quot = uart_get_divisor(port, baud);
switch (termios->c_cflag & CSIZE) { switch (termios->c_cflag & CSIZE) {
@ -309,160 +279,117 @@ clps711xuart_set_termios(struct uart_port *port, struct ktermios *termios,
case CS7: case CS7:
ubrlcr = UBRLCR_WRDLEN7; ubrlcr = UBRLCR_WRDLEN7;
break; break;
default: // CS8 case CS8:
default:
ubrlcr = UBRLCR_WRDLEN8; ubrlcr = UBRLCR_WRDLEN8;
break; break;
} }
if (termios->c_cflag & CSTOPB) if (termios->c_cflag & CSTOPB)
ubrlcr |= UBRLCR_XSTOP; ubrlcr |= UBRLCR_XSTOP;
if (termios->c_cflag & PARENB) { if (termios->c_cflag & PARENB) {
ubrlcr |= UBRLCR_PRTEN; ubrlcr |= UBRLCR_PRTEN;
if (!(termios->c_cflag & PARODD)) if (!(termios->c_cflag & PARODD))
ubrlcr |= UBRLCR_EVENPRT; ubrlcr |= UBRLCR_EVENPRT;
} }
if (port->fifosize > 1)
ubrlcr |= UBRLCR_FIFOEN; /* Enable FIFO */
ubrlcr |= UBRLCR_FIFOEN;
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
/* /* Set read status mask */
* Update the per-port timeout.
*/
uart_update_timeout(port, termios->c_cflag, baud);
port->read_status_mask = UARTDR_OVERR; port->read_status_mask = UARTDR_OVERR;
if (termios->c_iflag & INPCK) if (termios->c_iflag & INPCK)
port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR; port->read_status_mask |= UARTDR_PARERR | UARTDR_FRMERR;
/* /* Set status ignore mask */
* Characters to ignore
*/
port->ignore_status_mask = 0; port->ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR) if (!(termios->c_cflag & CREAD))
port->ignore_status_mask |= UARTDR_FRMERR | UARTDR_PARERR; port->ignore_status_mask |= UARTDR_OVERR | UARTDR_PARERR |
if (termios->c_iflag & IGNBRK) { UARTDR_FRMERR;
/*
* If we're ignoring parity and break indicators,
* ignore overruns to (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
port->ignore_status_mask |= UARTDR_OVERR;
}
quot -= 1; uart_update_timeout(port, termios->c_cflag, baud);
clps_writel(ubrlcr | quot, UBRLCR(port)); clps_writel(ubrlcr | (quot - 1), UBRLCR(port));
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
} }
static const char *clps711xuart_type(struct uart_port *port) static const char *uart_clps711x_type(struct uart_port *port)
{ {
return port->type == PORT_CLPS711X ? "CLPS711x" : NULL; return (port->type == PORT_CLPS711X) ? "CLPS711X" : NULL;
} }
/* static void uart_clps711x_config_port(struct uart_port *port, int flags)
* Configure/autoconfigure the port.
*/
static void clps711xuart_config_port(struct uart_port *port, int flags)
{ {
if (flags & UART_CONFIG_TYPE) if (flags & UART_CONFIG_TYPE)
port->type = PORT_CLPS711X; port->type = PORT_CLPS711X;
} }
static void clps711xuart_release_port(struct uart_port *port) static void uart_clps711x_release_port(struct uart_port *port)
{ {
/* Do nothing */
} }
static int clps711xuart_request_port(struct uart_port *port) static int uart_clps711x_request_port(struct uart_port *port)
{ {
/* Do nothing */
return 0; return 0;
} }
static struct uart_ops clps711x_pops = { static const struct uart_ops uart_clps711x_ops = {
.tx_empty = clps711xuart_tx_empty, .tx_empty = uart_clps711x_tx_empty,
.set_mctrl = clps711xuart_set_mctrl_null, .set_mctrl = uart_clps711x_set_mctrl,
.get_mctrl = clps711xuart_get_mctrl, .get_mctrl = uart_clps711x_get_mctrl,
.stop_tx = clps711xuart_stop_tx, .stop_tx = uart_clps711x_stop_tx,
.start_tx = clps711xuart_start_tx, .start_tx = uart_clps711x_start_tx,
.stop_rx = clps711xuart_stop_rx, .stop_rx = uart_clps711x_stop_rx,
.enable_ms = clps711xuart_enable_ms, .enable_ms = uart_clps711x_enable_ms,
.break_ctl = clps711xuart_break_ctl, .break_ctl = uart_clps711x_break_ctl,
.startup = clps711xuart_startup, .startup = uart_clps711x_startup,
.shutdown = clps711xuart_shutdown, .shutdown = uart_clps711x_shutdown,
.set_termios = clps711xuart_set_termios, .set_termios = uart_clps711x_set_termios,
.type = clps711xuart_type, .type = uart_clps711x_type,
.config_port = clps711xuart_config_port, .config_port = uart_clps711x_config_port,
.release_port = clps711xuart_release_port, .release_port = uart_clps711x_release_port,
.request_port = clps711xuart_request_port, .request_port = uart_clps711x_request_port,
};
static struct uart_port clps711x_ports[UART_NR] = {
{
.iobase = SYSCON1,
.irq = IRQ_UTXINT1, /* IRQ_URXINT1, IRQ_UMSINT */
.uartclk = 3686400,
.fifosize = 16,
.ops = &clps711x_pops,
.line = 0,
.flags = UPF_BOOT_AUTOCONF,
},
{
.iobase = SYSCON2,
.irq = IRQ_UTXINT2, /* IRQ_URXINT2 */
.uartclk = 3686400,
.fifosize = 16,
.ops = &clps711x_pops,
.line = 1,
.flags = UPF_BOOT_AUTOCONF,
}
}; };
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE #ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
static void clps711xuart_console_putchar(struct uart_port *port, int ch) static void uart_clps711x_console_putchar(struct uart_port *port, int ch)
{ {
while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF) while (clps_readl(SYSFLG(port)) & SYSFLG_UTXFF)
barrier(); barrier();
clps_writel(ch, UARTDR(port));
clps_writew(ch, UARTDR(port));
} }
/* static void uart_clps711x_console_write(struct console *co, const char *c,
* Print a string to the serial port trying not to disturb unsigned n)
* any possible real use of the port...
*
* The console_lock must be held when we get here.
*
* Note that this is called with interrupts already disabled
*/
static void
clps711xuart_console_write(struct console *co, const char *s,
unsigned int count)
{ {
struct uart_port *port = clps711x_ports + co->index; struct clps711x_port *s = (struct clps711x_port *)co->data;
unsigned int status, syscon; struct uart_port *port = &s->port[co->index];
u32 syscon;
/* /* Ensure that the port is enabled */
* Ensure that the port is enabled.
*/
syscon = clps_readl(SYSCON(port)); syscon = clps_readl(SYSCON(port));
clps_writel(syscon | SYSCON_UARTEN, SYSCON(port)); clps_writel(syscon | SYSCON_UARTEN, SYSCON(port));
uart_console_write(port, s, count, clps711xuart_console_putchar); uart_console_write(port, c, n, uart_clps711x_console_putchar);
/* /* Wait for transmitter to become empty */
* Finally, wait for transmitter to become empty while (clps_readl(SYSFLG(port)) & SYSFLG_UBUSY)
* and restore the uart state. barrier();
*/
do {
status = clps_readl(SYSFLG(port));
} while (status & SYSFLG_UBUSY);
/* Restore the uart state */
clps_writel(syscon, SYSCON(port)); clps_writel(syscon, SYSCON(port));
} }
static void __init static void uart_clps711x_console_get_options(struct uart_port *port,
clps711xuart_console_get_options(struct uart_port *port, int *baud, int *baud, int *parity,
int *parity, int *bits) int *bits)
{ {
if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) { if (clps_readl(SYSCON(port)) & SYSCON_UARTEN) {
unsigned int ubrlcr, quot; unsigned int ubrlcr, quot;
@ -487,92 +414,124 @@ clps711xuart_console_get_options(struct uart_port *port, int *baud,
} }
} }
static int __init clps711xuart_console_setup(struct console *co, char *options) static int uart_clps711x_console_setup(struct console *co, char *options)
{ {
struct uart_port *port; int baud = 38400, bits = 8, parity = 'n', flow = 'n';
int baud = 38400; struct clps711x_port *s = (struct clps711x_port *)co->data;
int bits = 8; struct uart_port *port = &s->port[(co->index > 0) ? co->index : 0];
int parity = 'n';
int flow = 'n';
/*
* Check whether an invalid uart number has been specified, and
* if so, search for the first available port that does have
* console support.
*/
port = uart_get_console(clps711x_ports, UART_NR, co);
if (options) if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow); uart_parse_options(options, &baud, &parity, &bits, &flow);
else else
clps711xuart_console_get_options(port, &baud, &parity, &bits); uart_clps711x_console_get_options(port, &baud, &parity, &bits);
return uart_set_options(port, co, baud, parity, bits, flow); return uart_set_options(port, co, baud, parity, bits, flow);
} }
static struct uart_driver clps711x_reg;
static struct console clps711x_console = {
.name = "ttyCL",
.write = clps711xuart_console_write,
.device = uart_console_device,
.setup = clps711xuart_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &clps711x_reg,
};
static int __init clps711xuart_console_init(void)
{
register_console(&clps711x_console);
return 0;
}
console_initcall(clps711xuart_console_init);
#define CLPS711X_CONSOLE &clps711x_console
#else
#define CLPS711X_CONSOLE NULL
#endif #endif
static struct uart_driver clps711x_reg = { static int uart_clps711x_probe(struct platform_device *pdev)
.driver_name = "ttyCL",
.dev_name = "ttyCL",
.major = SERIAL_CLPS711X_MAJOR,
.minor = SERIAL_CLPS711X_MINOR,
.nr = UART_NR,
.cons = CLPS711X_CONSOLE,
};
static int __init clps711xuart_init(void)
{ {
struct clps711x_port *s;
int ret, i; int ret, i;
printk(KERN_INFO "Serial: CLPS711x driver\n"); s = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_port), GFP_KERNEL);
if (!s) {
dev_err(&pdev->dev, "Error allocating port structure\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, s);
ret = uart_register_driver(&clps711x_reg); s->uart_clk = devm_clk_get(&pdev->dev, "uart");
if (ret) if (IS_ERR(s->uart_clk)) {
return ret; dev_err(&pdev->dev, "Can't get UART clocks\n");
ret = PTR_ERR(s->uart_clk);
goto err_out;
}
for (i = 0; i < UART_NR; i++) s->uart.owner = THIS_MODULE;
uart_add_one_port(&clps711x_reg, &clps711x_ports[i]); s->uart.dev_name = "ttyCL";
s->uart.major = UART_CLPS711X_MAJOR;
s->uart.minor = UART_CLPS711X_MINOR;
s->uart.nr = UART_CLPS711X_NR;
#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE
s->uart.cons = &s->console;
s->uart.cons->device = uart_console_device;
s->uart.cons->write = uart_clps711x_console_write;
s->uart.cons->setup = uart_clps711x_console_setup;
s->uart.cons->flags = CON_PRINTBUFFER;
s->uart.cons->index = -1;
s->uart.cons->data = s;
strcpy(s->uart.cons->name, "ttyCL");
#endif
ret = uart_register_driver(&s->uart);
if (ret) {
dev_err(&pdev->dev, "Registering UART driver failed\n");
devm_clk_put(&pdev->dev, s->uart_clk);
goto err_out;
}
for (i = 0; i < UART_CLPS711X_NR; i++) {
s->port[i].line = i;
s->port[i].dev = &pdev->dev;
s->port[i].irq = TX_IRQ(&s->port[i]);
s->port[i].iobase = SYSCON(&s->port[i]);
s->port[i].type = PORT_CLPS711X;
s->port[i].fifosize = 16;
s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
s->port[i].uartclk = clk_get_rate(s->uart_clk);
s->port[i].ops = &uart_clps711x_ops;
WARN_ON(uart_add_one_port(&s->uart, &s->port[i]));
}
return 0;
err_out:
platform_set_drvdata(pdev, NULL);
return ret;
}
static int uart_clps711x_remove(struct platform_device *pdev)
{
struct clps711x_port *s = platform_get_drvdata(pdev);
int i;
for (i = 0; i < UART_CLPS711X_NR; i++)
uart_remove_one_port(&s->uart, &s->port[i]);
devm_clk_put(&pdev->dev, s->uart_clk);
uart_unregister_driver(&s->uart);
platform_set_drvdata(pdev, NULL);
return 0; return 0;
} }
static void __exit clps711xuart_exit(void) static struct platform_driver clps711x_uart_driver = {
.driver = {
.name = UART_CLPS711X_NAME,
.owner = THIS_MODULE,
},
.probe = uart_clps711x_probe,
.remove = uart_clps711x_remove,
};
module_platform_driver(clps711x_uart_driver);
static struct platform_device clps711x_uart_device = {
.name = UART_CLPS711X_NAME,
};
static int __init uart_clps711x_init(void)
{ {
int i; return platform_device_register(&clps711x_uart_device);
for (i = 0; i < UART_NR; i++)
uart_remove_one_port(&clps711x_reg, &clps711x_ports[i]);
uart_unregister_driver(&clps711x_reg);
} }
module_init(uart_clps711x_init);
module_init(clps711xuart_init); static void __exit uart_clps711x_exit(void)
module_exit(clps711xuart_exit); {
platform_device_unregister(&clps711x_uart_device);
}
module_exit(uart_clps711x_exit);
MODULE_AUTHOR("Deep Blue Solutions Ltd"); MODULE_AUTHOR("Deep Blue Solutions Ltd");
MODULE_DESCRIPTION("CLPS-711x generic serial driver"); MODULE_DESCRIPTION("CLPS711X serial driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV(SERIAL_CLPS711X_MAJOR, SERIAL_CLPS711X_MINOR);

View File

@ -1373,7 +1373,7 @@ static struct uart_driver cpm_reg = {
static int probe_index; static int probe_index;
static int __devinit cpm_uart_probe(struct platform_device *ofdev) static int cpm_uart_probe(struct platform_device *ofdev)
{ {
int index = probe_index++; int index = probe_index++;
struct uart_cpm_port *pinfo = &cpm_uart_ports[index]; struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
@ -1396,7 +1396,7 @@ static int __devinit cpm_uart_probe(struct platform_device *ofdev)
return uart_add_one_port(&cpm_reg, &pinfo->port); return uart_add_one_port(&cpm_reg, &pinfo->port);
} }
static int __devexit cpm_uart_remove(struct platform_device *ofdev) static int cpm_uart_remove(struct platform_device *ofdev)
{ {
struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev); struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
return uart_remove_one_port(&cpm_reg, &pinfo->port); return uart_remove_one_port(&cpm_reg, &pinfo->port);

View File

@ -690,7 +690,7 @@ static int efm32_uart_probe_dt(struct platform_device *pdev,
} }
static int __devinit efm32_uart_probe(struct platform_device *pdev) static int efm32_uart_probe(struct platform_device *pdev)
{ {
struct efm32_uart_port *efm_port; struct efm32_uart_port *efm_port;
struct resource *res; struct resource *res;
@ -764,7 +764,7 @@ err_get_base:
return ret; return ret;
} }
static int __devexit efm32_uart_remove(struct platform_device *pdev) static int efm32_uart_remove(struct platform_device *pdev)
{ {
struct efm32_uart_port *efm_port = platform_get_drvdata(pdev); struct efm32_uart_port *efm_port = platform_get_drvdata(pdev);
@ -791,7 +791,7 @@ MODULE_DEVICE_TABLE(of, efm32_uart_dt_ids);
static struct platform_driver efm32_uart_driver = { static struct platform_driver efm32_uart_driver = {
.probe = efm32_uart_probe, .probe = efm32_uart_probe,
.remove = __devexit_p(efm32_uart_remove), .remove = efm32_uart_remove,
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,

View File

@ -175,7 +175,7 @@ static void free_port_memory(struct icom_port *icom_port)
} }
} }
static int __devinit get_port_memory(struct icom_port *icom_port) static int get_port_memory(struct icom_port *icom_port)
{ {
int index; int index;
unsigned long stgAddr; unsigned long stgAddr;
@ -1314,7 +1314,7 @@ static struct uart_driver icom_uart_driver = {
.cons = ICOM_CONSOLE, .cons = ICOM_CONSOLE,
}; };
static int __devinit icom_init_ports(struct icom_adapter *icom_adapter) static int icom_init_ports(struct icom_adapter *icom_adapter)
{ {
u32 subsystem_id = icom_adapter->subsystem_id; u32 subsystem_id = icom_adapter->subsystem_id;
int i; int i;
@ -1381,7 +1381,7 @@ static void icom_port_active(struct icom_port *icom_port, struct icom_adapter *i
0x8024 + 2 - 2 * (icom_port->port - 2); 0x8024 + 2 - 2 * (icom_port->port - 2);
} }
} }
static int __devinit icom_load_ports(struct icom_adapter *icom_adapter) static int icom_load_ports(struct icom_adapter *icom_adapter)
{ {
struct icom_port *icom_port; struct icom_port *icom_port;
int port_num; int port_num;
@ -1407,7 +1407,7 @@ static int __devinit icom_load_ports(struct icom_adapter *icom_adapter)
return 0; return 0;
} }
static int __devinit icom_alloc_adapter(struct icom_adapter static int icom_alloc_adapter(struct icom_adapter
**icom_adapter_ref) **icom_adapter_ref)
{ {
int adapter_count = 0; int adapter_count = 0;
@ -1487,7 +1487,7 @@ static void icom_kref_release(struct kref *kref)
icom_remove_adapter(icom_adapter); icom_remove_adapter(icom_adapter);
} }
static int __devinit icom_probe(struct pci_dev *dev, static int icom_probe(struct pci_dev *dev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
int index; int index;
@ -1596,7 +1596,7 @@ probe_exit0:
return retval; return retval;
} }
static void __devexit icom_remove(struct pci_dev *dev) static void icom_remove(struct pci_dev *dev)
{ {
struct icom_adapter *icom_adapter; struct icom_adapter *icom_adapter;
struct list_head *tmp; struct list_head *tmp;
@ -1617,7 +1617,7 @@ static struct pci_driver icom_pci_driver = {
.name = ICOM_DRIVER_NAME, .name = ICOM_DRIVER_NAME,
.id_table = icom_pci_table, .id_table = icom_pci_table,
.probe = icom_probe, .probe = icom_probe,
.remove = __devexit_p(icom_remove), .remove = icom_remove,
}; };
static int __init icom_init(void) static int __init icom_init(void)

View File

@ -60,20 +60,27 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/spi/ifx_modem.h> #include <linux/spi/ifx_modem.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/reboot.h>
#include "ifx6x60.h" #include "ifx6x60.h"
#define IFX_SPI_MORE_MASK 0x10 #define IFX_SPI_MORE_MASK 0x10
#define IFX_SPI_MORE_BIT 12 /* bit position in u16 */ #define IFX_SPI_MORE_BIT 4 /* bit position in u8 */
#define IFX_SPI_CTS_BIT 13 /* bit position in u16 */ #define IFX_SPI_CTS_BIT 6 /* bit position in u8 */
#define IFX_SPI_MODE SPI_MODE_1 #define IFX_SPI_MODE SPI_MODE_1
#define IFX_SPI_TTY_ID 0 #define IFX_SPI_TTY_ID 0
#define IFX_SPI_TIMEOUT_SEC 2 #define IFX_SPI_TIMEOUT_SEC 2
#define IFX_SPI_HEADER_0 (-1) #define IFX_SPI_HEADER_0 (-1)
#define IFX_SPI_HEADER_F (-2) #define IFX_SPI_HEADER_F (-2)
#define PO_POST_DELAY 200
#define IFX_MDM_RST_PMU 4
/* forward reference */ /* forward reference */
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev); static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
static int ifx_modem_reboot_callback(struct notifier_block *nfb,
unsigned long event, void *data);
static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev);
/* local variables */ /* local variables */
static int spi_bpw = 16; /* 8, 16 or 32 bit word length */ static int spi_bpw = 16; /* 8, 16 or 32 bit word length */
@ -81,6 +88,29 @@ static struct tty_driver *tty_drv;
static struct ifx_spi_device *saved_ifx_dev; static struct ifx_spi_device *saved_ifx_dev;
static struct lock_class_key ifx_spi_key; static struct lock_class_key ifx_spi_key;
static struct notifier_block ifx_modem_reboot_notifier_block = {
.notifier_call = ifx_modem_reboot_callback,
};
static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev)
{
gpio_set_value(IFX_MDM_RST_PMU, 1);
msleep(PO_POST_DELAY);
return 0;
}
static int ifx_modem_reboot_callback(struct notifier_block *nfb,
unsigned long event, void *data)
{
if (saved_ifx_dev)
ifx_modem_power_off(saved_ifx_dev);
else
pr_warn("no ifx modem active;\n");
return NOTIFY_OK;
}
/* GPIO/GPE settings */ /* GPIO/GPE settings */
/** /**
@ -152,26 +182,67 @@ ifx_spi_power_state_clear(struct ifx_spi_device *ifx_dev, unsigned char val)
} }
/** /**
* swap_buf * swap_buf_8
* @buf: our buffer * @buf: our buffer
* @len : number of bytes (not words) in the buffer * @len : number of bytes (not words) in the buffer
* @end: end of buffer * @end: end of buffer
* *
* Swap the contents of a buffer into big endian format * Swap the contents of a buffer into big endian format
*/ */
static inline void swap_buf(u16 *buf, int len, void *end) static inline void swap_buf_8(unsigned char *buf, int len, void *end)
{
/* don't swap buffer if SPI word width is 8 bits */
return;
}
/**
* swap_buf_16
* @buf: our buffer
* @len : number of bytes (not words) in the buffer
* @end: end of buffer
*
* Swap the contents of a buffer into big endian format
*/
static inline void swap_buf_16(unsigned char *buf, int len, void *end)
{ {
int n; int n;
u16 *buf_16 = (u16 *)buf;
len = ((len + 1) >> 1); len = ((len + 1) >> 1);
if ((void *)&buf[len] > end) { if ((void *)&buf_16[len] > end) {
pr_err("swap_buf: swap exceeds boundary (%p > %p)!", pr_err("swap_buf_16: swap exceeds boundary (%p > %p)!",
&buf[len], end); &buf_16[len], end);
return; return;
} }
for (n = 0; n < len; n++) { for (n = 0; n < len; n++) {
*buf = cpu_to_be16(*buf); *buf_16 = cpu_to_be16(*buf_16);
buf++; buf_16++;
}
}
/**
* swap_buf_32
* @buf: our buffer
* @len : number of bytes (not words) in the buffer
* @end: end of buffer
*
* Swap the contents of a buffer into big endian format
*/
static inline void swap_buf_32(unsigned char *buf, int len, void *end)
{
int n;
u32 *buf_32 = (u32 *)buf;
len = (len + 3) >> 2;
if ((void *)&buf_32[len] > end) {
pr_err("swap_buf_32: swap exceeds boundary (%p > %p)!\n",
&buf_32[len], end);
return;
}
for (n = 0; n < len; n++) {
*buf_32 = cpu_to_be32(*buf_32);
buf_32++;
} }
} }
@ -190,9 +261,7 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
if (!val) { if (!val) {
if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING, if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,
&ifx_dev->flags)) { &ifx_dev->flags)) {
ifx_dev->spi_timer.expires = mod_timer(&ifx_dev->spi_timer,jiffies + IFX_SPI_TIMEOUT_SEC*HZ);
jiffies + IFX_SPI_TIMEOUT_SEC*HZ;
add_timer(&ifx_dev->spi_timer);
} }
} }
@ -449,7 +518,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
tx_count-IFX_SPI_HEADER_OVERHEAD, tx_count-IFX_SPI_HEADER_OVERHEAD,
ifx_dev->spi_more); ifx_dev->spi_more);
/* swap actual data in the buffer */ /* swap actual data in the buffer */
swap_buf((u16 *)(ifx_dev->tx_buffer), tx_count, ifx_dev->swap_buf((ifx_dev->tx_buffer), tx_count,
&ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]); &ifx_dev->tx_buffer[IFX_SPI_TRANSFER_SIZE]);
return tx_count; return tx_count;
} }
@ -469,9 +538,17 @@ static int ifx_spi_write(struct tty_struct *tty, const unsigned char *buf,
{ {
struct ifx_spi_device *ifx_dev = tty->driver_data; struct ifx_spi_device *ifx_dev = tty->driver_data;
unsigned char *tmp_buf = (unsigned char *)buf; unsigned char *tmp_buf = (unsigned char *)buf;
int tx_count = kfifo_in_locked(&ifx_dev->tx_fifo, tmp_buf, count, unsigned long flags;
&ifx_dev->fifo_lock); bool is_fifo_empty;
mrdy_assert(ifx_dev); int tx_count;
spin_lock_irqsave(&ifx_dev->fifo_lock, flags);
is_fifo_empty = kfifo_is_empty(&ifx_dev->tx_fifo);
tx_count = kfifo_in(&ifx_dev->tx_fifo, tmp_buf, count);
spin_unlock_irqrestore(&ifx_dev->fifo_lock, flags);
if (is_fifo_empty)
mrdy_assert(ifx_dev);
return tx_count; return tx_count;
} }
@ -530,12 +607,19 @@ static int ifx_port_activate(struct tty_port *port, struct tty_struct *tty)
/* clear any old data; can't do this in 'close' */ /* clear any old data; can't do this in 'close' */
kfifo_reset(&ifx_dev->tx_fifo); kfifo_reset(&ifx_dev->tx_fifo);
/* clear any flag which may be set in port shutdown procedure */
clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags);
clear_bit(IFX_SPI_STATE_IO_READY, &ifx_dev->flags);
/* put port data into this tty */ /* put port data into this tty */
tty->driver_data = ifx_dev; tty->driver_data = ifx_dev;
/* allows flip string push from int context */ /* allows flip string push from int context */
tty->low_latency = 1; tty->low_latency = 1;
/* set flag to allows data transfer */
set_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
return 0; return 0;
} }
@ -551,6 +635,7 @@ static void ifx_port_shutdown(struct tty_port *port)
struct ifx_spi_device *ifx_dev = struct ifx_spi_device *ifx_dev =
container_of(port, struct ifx_spi_device, tty_port); container_of(port, struct ifx_spi_device, tty_port);
clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
mrdy_set_low(ifx_dev); mrdy_set_low(ifx_dev);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
tasklet_kill(&ifx_dev->io_work_tasklet); tasklet_kill(&ifx_dev->io_work_tasklet);
@ -617,7 +702,7 @@ static void ifx_spi_complete(void *ctx)
if (!ifx_dev->spi_msg.status) { if (!ifx_dev->spi_msg.status) {
/* check header validity, get comm flags */ /* check header validity, get comm flags */
swap_buf((u16 *)ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD, ifx_dev->swap_buf(ifx_dev->rx_buffer, IFX_SPI_HEADER_OVERHEAD,
&ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]); &ifx_dev->rx_buffer[IFX_SPI_HEADER_OVERHEAD]);
decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer, decode_result = ifx_spi_decode_spi_header(ifx_dev->rx_buffer,
&length, &more, &cts); &length, &more, &cts);
@ -636,7 +721,8 @@ static void ifx_spi_complete(void *ctx)
actual_length = min((unsigned int)length, actual_length = min((unsigned int)length,
ifx_dev->spi_msg.actual_length); ifx_dev->spi_msg.actual_length);
swap_buf((u16 *)(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD), ifx_dev->swap_buf(
(ifx_dev->rx_buffer + IFX_SPI_HEADER_OVERHEAD),
actual_length, actual_length,
&ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]); &ifx_dev->rx_buffer[IFX_SPI_TRANSFER_SIZE]);
ifx_spi_insert_flip_string( ifx_spi_insert_flip_string(
@ -705,7 +791,8 @@ static void ifx_spi_io(unsigned long data)
int retval; int retval;
struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data; struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *) data;
if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags)) { if (!test_and_set_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &ifx_dev->flags) &&
test_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags)) {
if (ifx_dev->gpio.unack_srdy_int_nb > 0) if (ifx_dev->gpio.unack_srdy_int_nb > 0)
ifx_dev->gpio.unack_srdy_int_nb--; ifx_dev->gpio.unack_srdy_int_nb--;
@ -773,6 +860,7 @@ static void ifx_spi_free_port(struct ifx_spi_device *ifx_dev)
{ {
if (ifx_dev->tty_dev) if (ifx_dev->tty_dev)
tty_unregister_device(tty_drv, ifx_dev->minor); tty_unregister_device(tty_drv, ifx_dev->minor);
tty_port_destroy(&ifx_dev->tty_port);
kfifo_free(&ifx_dev->tx_fifo); kfifo_free(&ifx_dev->tx_fifo);
} }
@ -806,10 +894,12 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
dev_dbg(&ifx_dev->spi_dev->dev, dev_dbg(&ifx_dev->spi_dev->dev,
"%s: registering tty device failed", __func__); "%s: registering tty device failed", __func__);
ret = PTR_ERR(ifx_dev->tty_dev); ret = PTR_ERR(ifx_dev->tty_dev);
goto error_ret; goto error_port;
} }
return 0; return 0;
error_port:
tty_port_destroy(pport);
error_ret: error_ret:
ifx_spi_free_port(ifx_dev); ifx_spi_free_port(ifx_dev);
return ret; return ret;
@ -826,7 +916,7 @@ error_ret:
static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev) static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev)
{ {
if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) { if (test_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags)) {
del_timer_sync(&ifx_dev->spi_timer); del_timer(&ifx_dev->spi_timer);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
} }
@ -1001,6 +1091,14 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
return -ENODEV; return -ENODEV;
} }
/* init swap_buf function according to word width configuration */
if (spi->bits_per_word == 32)
ifx_dev->swap_buf = swap_buf_32;
else if (spi->bits_per_word == 16)
ifx_dev->swap_buf = swap_buf_16;
else
ifx_dev->swap_buf = swap_buf_8;
/* ensure SPI protocol flags are initialized to enable transfer */ /* ensure SPI protocol flags are initialized to enable transfer */
ifx_dev->spi_more = 0; ifx_dev->spi_more = 0;
ifx_dev->spi_slave_cts = 0; ifx_dev->spi_slave_cts = 0;
@ -1219,6 +1317,9 @@ static int ifx_spi_spi_remove(struct spi_device *spi)
static void ifx_spi_spi_shutdown(struct spi_device *spi) static void ifx_spi_spi_shutdown(struct spi_device *spi)
{ {
struct ifx_spi_device *ifx_dev = spi_get_drvdata(spi);
ifx_modem_power_off(ifx_dev);
} }
/* /*
@ -1338,7 +1439,7 @@ static struct spi_driver ifx_spi_driver = {
.owner = THIS_MODULE}, .owner = THIS_MODULE},
.probe = ifx_spi_spi_probe, .probe = ifx_spi_spi_probe,
.shutdown = ifx_spi_spi_shutdown, .shutdown = ifx_spi_spi_shutdown,
.remove = __devexit_p(ifx_spi_spi_remove), .remove = ifx_spi_spi_remove,
.suspend = ifx_spi_spi_suspend, .suspend = ifx_spi_spi_suspend,
.resume = ifx_spi_spi_resume, .resume = ifx_spi_spi_resume,
.id_table = ifx_id_table .id_table = ifx_id_table
@ -1354,7 +1455,9 @@ static void __exit ifx_spi_exit(void)
{ {
/* unregister */ /* unregister */
tty_unregister_driver(tty_drv); tty_unregister_driver(tty_drv);
put_tty_driver(tty_drv);
spi_unregister_driver((void *)&ifx_spi_driver); spi_unregister_driver((void *)&ifx_spi_driver);
unregister_reboot_notifier(&ifx_modem_reboot_notifier_block);
} }
/** /**
@ -1389,16 +1492,31 @@ static int __init ifx_spi_init(void)
if (result) { if (result) {
pr_err("%s: tty_register_driver failed(%d)", pr_err("%s: tty_register_driver failed(%d)",
DRVNAME, result); DRVNAME, result);
put_tty_driver(tty_drv); goto err_free_tty;
return result;
} }
result = spi_register_driver((void *)&ifx_spi_driver); result = spi_register_driver((void *)&ifx_spi_driver);
if (result) { if (result) {
pr_err("%s: spi_register_driver failed(%d)", pr_err("%s: spi_register_driver failed(%d)",
DRVNAME, result); DRVNAME, result);
tty_unregister_driver(tty_drv); goto err_unreg_tty;
} }
result = register_reboot_notifier(&ifx_modem_reboot_notifier_block);
if (result) {
pr_err("%s: register ifx modem reboot notifier failed(%d)",
DRVNAME, result);
goto err_unreg_spi;
}
return 0;
err_unreg_spi:
spi_unregister_driver((void *)&ifx_spi_driver);
err_unreg_tty:
tty_unregister_driver(tty_drv);
err_free_tty:
put_tty_driver(tty_drv);
return result; return result;
} }

View File

@ -41,6 +41,7 @@
#define IFX_SPI_STATE_IO_IN_PROGRESS 1 #define IFX_SPI_STATE_IO_IN_PROGRESS 1
#define IFX_SPI_STATE_IO_READY 2 #define IFX_SPI_STATE_IO_READY 2
#define IFX_SPI_STATE_TIMER_PENDING 3 #define IFX_SPI_STATE_TIMER_PENDING 3
#define IFX_SPI_STATE_IO_AVAILABLE 4
/* flow control bitfields */ /* flow control bitfields */
#define IFX_SPI_DCD 0 #define IFX_SPI_DCD 0
@ -124,6 +125,7 @@ struct ifx_spi_device {
#define MR_INPROGRESS 1 #define MR_INPROGRESS 1
#define MR_COMPLETE 2 #define MR_COMPLETE 2
wait_queue_head_t mdm_reset_wait; wait_queue_head_t mdm_reset_wait;
void (*swap_buf)(unsigned char *buf, int len, void *end);
}; };
#endif /* _IFX6X60_H */ #endif /* _IFX6X60_H */

View File

@ -2010,7 +2010,7 @@ static int ioc3uart_remove(struct ioc3_submodule *is,
* @idd: ioc3 driver data for this card * @idd: ioc3 driver data for this card
*/ */
static int __devinit static int
ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) ioc3uart_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd)
{ {
struct pci_dev *pdev = idd->pdev; struct pci_dev *pdev = idd->pdev;

View File

@ -57,9 +57,11 @@ enum {
DBG_CARR = 0x10000, DBG_CARR = 0x10000,
}; };
#define jsm_printk(nlevel, klevel, pdev, fmt, args...) \ #define jsm_dbg(nlevel, pdev, fmt, ...) \
if ((DBG_##nlevel & jsm_debug)) \ do { \
dev_printk(KERN_##klevel, pdev->dev, fmt, ## args) if (DBG_##nlevel & jsm_debug) \
dev_dbg(pdev->dev, fmt, ##__VA_ARGS__); \
} while (0)
#define MAXLINES 256 #define MAXLINES 256
#define MAXPORTS 8 #define MAXPORTS 8

Some files were not shown because too many files have changed in this diff Show More