From: Stephen Hurd <sh...@broadcom.com>

Add support for the UART device present in Broadcom TruManage capable NetXtreme 
chips (ie: 5761m 5762, and 5725).

This implementation has a hidden transmit FIFO, so running in single-byte 
interrupt mode results in too many interrupts.  The UART_CAP_HFIFO capability 
was added to track this.  It continues to reload the THR as long as the THRE 
and TSRE bits are set in the LSR up to a specified limit (1024 is used here).

Signed-off-by: Stephen Hurd <sh...@broadcom.com>

---

Patch against linux-2.7 from ftp.kernel.org downloaded Dec-11-2012.

I don't know anybody here off hand who does Linux work nor am I in a position 
to configure the Exchange server.  If this still isn't acceptable, I guess I 
could try emailing this patch around internally and hope it lands with someone 
has the appropriate magic available.


-- Stephen Hurd

diff -uprN linux-3.7.orig/drivers/tty/serial/8250/8250.c 
linux-3.7/drivers/tty/serial/8250/8250.c
--- linux-3.7.orig/drivers/tty/serial/8250/8250.c       2012-12-10 
19:30:57.000000000 -0800
+++ linux-3.7/drivers/tty/serial/8250/8250.c    2012-12-11 15:56:40.686343959 
-0800
@@ -290,6 +290,12 @@ static const struct serial8250_config ua
                                  UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
                .flags          = UART_CAP_FIFO,
        },
+       [PORT_BRCM_TRUMANAGE] = {
+               .name           = "TruManage",
+               .fifo_size      = 1,
+               .tx_loadsz      = 1024,
+               .flags          = UART_CAP_HFIFO,
+       },
        [PORT_8250_CIR] = {
                .name           = "CIR port"
        }
@@ -1441,6 +1447,11 @@ void serial8250_tx_chars(struct uart_825
                port->icount.tx++;
                if (uart_circ_empty(xmit))
                        break;
+               if (up->capabilities & UART_CAP_HFIFO) {
+                       if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY)
+                                       != BOTH_EMPTY)
+                               break;
+               }
        } while (--count > 0);
 
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
diff -uprN linux-3.7.orig/drivers/tty/serial/8250/8250.h 
linux-3.7/drivers/tty/serial/8250/8250.h
--- linux-3.7.orig/drivers/tty/serial/8250/8250.h       2012-12-10 
19:30:57.000000000 -0800
+++ linux-3.7/drivers/tty/serial/8250/8250.h    2012-12-11 14:57:48.641613676 
-0800
@@ -40,6 +40,7 @@ struct serial8250_config {
 #define UART_CAP_AFE   (1 << 11)       /* MCR-based hw flow control */
 #define UART_CAP_UUE   (1 << 12)       /* UART needs IER bit 6 set (Xscale) */
 #define UART_CAP_RTOIE (1 << 13)       /* UART needs IER bit 4 set (Xscale, 
Tegra) */
+#define UART_CAP_HFIFO (1 << 14)       /* UART has a "hidden" FIFO */
 
 #define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
 #define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
diff -uprN linux-3.7.orig/drivers/tty/serial/8250/8250_pci.c 
linux-3.7/drivers/tty/serial/8250/8250_pci.c
--- linux-3.7.orig/drivers/tty/serial/8250/8250_pci.c   2012-12-10 
19:30:57.000000000 -0800
+++ linux-3.7/drivers/tty/serial/8250/8250_pci.c        2012-12-11 
15:58:10.958340077 -0800
@@ -1085,6 +1085,17 @@ pci_omegapci_setup(struct serial_private
        return setup_port(priv, port, 2, idx * 8, 0);
 }
 
+static int
+pci_brcm_trumanage_setup(struct serial_private *priv,
+                     const struct pciserial_board *board,
+                     struct uart_port *port, int idx)
+{
+       int ret = pci_default_setup(priv, board, port, idx);
+       port->type = PORT_BRCM_TRUMANAGE;
+       port->flags = (port->flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+       return ret;
+}
+
 static int skip_tx_en_setup(struct serial_private *priv,
                        const struct pciserial_board *board,
                        struct uart_8250_port *port, int idx)
@@ -1213,6 +1224,7 @@ pci_wch_ch353_setup(struct serial_privat
 #define PCI_VENDOR_ID_AGESTAR          0x5372
 #define PCI_DEVICE_ID_AGESTAR_9375     0x6872
 #define PCI_VENDOR_ID_ASIX             0x9710
+#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
@@ -1788,6 +1800,17 @@ static struct pci_serial_quirk pci_seria
                .setup          = pci_asix_setup,
        },
        /*
+        * Broadcom TruManage (NetXtreme)
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_BROADCOM,
+               .device         = PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_brcm_trumanage_setup,
+       },
+
+       /*
         * Default "match everything" terminator entry
         */
        {
@@ -1975,6 +1998,7 @@ enum pci_board_num_t {
        pbn_ce4100_1_115200,
        pbn_omegapci,
        pbn_NETMOS9900_2s_115200,
+       pbn_brcm_trumanage,
 };
 
 /*
@@ -2674,6 +2698,12 @@ static struct pciserial_board pci_boards
                .num_ports      = 2,
                .base_baud      = 115200,
        },
+       [pbn_brcm_trumanage] = {
+               .flags          = FL_BASE0,
+               .num_ports      = 1,
+               .reg_shift      = 2,
+               .base_baud      = 115200,
+       },
 };
 
 static const struct pci_device_id blacklist[] = {
@@ -4238,6 +4268,13 @@ static struct pci_device_id serial_pci_t
                pbn_omegapci },
 
        /*
+        * Broadcom TruManage
+        */
+       {       PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_brcm_trumanage },
+
+       /*
         * AgeStar as-prs2-009
         */
        {       PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375,
diff -uprN linux-3.7.orig/include/uapi/linux/serial_core.h 
linux-3.7/include/uapi/linux/serial_core.h
--- linux-3.7.orig/include/uapi/linux/serial_core.h     2012-12-10 
19:30:57.000000000 -0800
+++ linux-3.7/include/uapi/linux/serial_core.h  2012-12-11 15:00:07.005618440 
-0800
@@ -49,7 +49,8 @@
 #define PORT_XR17D15X  21      /* Exar XR17D15x UART */
 #define PORT_LPC3220   22      /* NXP LPC32xx SoC "Standard" UART */
 #define PORT_8250_CIR  23      /* CIR infrared port, has its own driver */
-#define PORT_MAX_8250  23      /* max port ID */
+#define PORT_BRCM_TRUMANAGE    24
+#define PORT_MAX_8250  24      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed

Reply via email to