Author: marius
Date: Wed May 10 20:12:23 2017
New Revision: 318151
URL: https://svnweb.freebsd.org/changeset/base/318151

Log:
  MFC: r293642
  
  - Add support for Advantech PCI-1602 Rev. B1 and PCI-1603 cards. [1]
  - Add a description of Advantech PCI-1602 Rev. A boards. [1]
  - Properly set up REG_ACR also for PCI-1602 Rev. A based on what the
    Advantech-supplied Linux driver does.
  - Additionally use the macros of <dev/ic/ns16550.h> to replace existing
    magic values and get rid of trivial comments.
  - Fix the style of some comments.
  
  PR:           205359 [1]
  Submitted by: Jan Mikkelsen (original patch) [1]

Modified:
  stable/10/sys/dev/ic/ns16550.h
  stable/10/sys/dev/puc/pucdata.c

Modified: stable/10/sys/dev/ic/ns16550.h
==============================================================================
--- stable/10/sys/dev/ic/ns16550.h      Wed May 10 19:41:52 2017        
(r318150)
+++ stable/10/sys/dev/ic/ns16550.h      Wed May 10 20:12:23 2017        
(r318151)
@@ -205,6 +205,7 @@
  * requires ACR[6].
  */
 #define        com_icr         5       /* index control register (R/W) */
+#define        REG_ICR         com_icr
 
 /*
  * 16950 register #7.  It is the same as com_scr except it has a different
@@ -220,6 +221,7 @@
  */
 
 #define        com_acr         0       /* additional control register (R/W) */
+#define        REG_ACR         com_acr
 #define        ACR_ASE         0x80    /* ASR/RFL/TFL enable */
 #define        ACR_ICRE        0x40    /* ICR enable */
 #define        ACR_TLE         0x20    /* TTL/RTL enable */

Modified: stable/10/sys/dev/puc/pucdata.c
==============================================================================
--- stable/10/sys/dev/puc/pucdata.c     Wed May 10 19:41:52 2017        
(r318150)
+++ stable/10/sys/dev/puc/pucdata.c     Wed May 10 20:12:23 2017        
(r318151)
@@ -42,12 +42,16 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <sys/rman.h>
 
+#include <dev/ic/ns16550.h>
+
+#include <dev/pci/pcireg.h>
 #include <dev/pci/pcivar.h>
 
 #include <dev/puc/puc_bus.h>
 #include <dev/puc/puc_cfg.h>
 #include <dev/puc/puc_bfe.h>
 
+static puc_config_f puc_config_advantech;
 static puc_config_f puc_config_amc;
 static puc_config_f puc_config_diva;
 static puc_config_f puc_config_exar;
@@ -691,10 +695,25 @@ const struct puc_cfg puc_pci_devices[] =
            .config_function = puc_config_exar_pcie
        },
 
+       /*
+        * The Advantech PCI-1602 Rev. A use the first two ports of an Oxford
+        * Semiconductor OXuPCI954.  Note these boards have a hardware bug in
+        * that they drive the RS-422/485 transmitters after power-on until a
+        * driver initalizes the UARTs.
+        */
        {   0x13fe, 0x1600, 0x1602, 0x0002,
-           "Advantech PCI-1602",
+           "Advantech PCI-1602 Rev. A",
            DEFAULT_RCLK * 8,
            PUC_PORT_2S, 0x10, 0, 8,
+           .config_function = puc_config_advantech
+       },
+
+       /* Advantech PCI-1602 Rev. B1/PCI-1603 are also based on OXuPCI952. */
+       {   0x13fe, 0xa102, 0x13fe, 0xa102,
+           "Advantech 2-port PCI (PCI-1602 Rev. B1/PCI-1603)",
+           DEFAULT_RCLK * 8,
+           PUC_PORT_2S, 0x10, 4, 0,
+           .config_function = puc_config_advantech
        },
 
        {   0x1407, 0x0100, 0xffff, 0,
@@ -1256,6 +1275,92 @@ const struct puc_cfg puc_pci_devices[] =
 };
 
 static int
+puc_config_advantech(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
+    intptr_t *res __unused)
+{
+       const struct puc_cfg *cfg;
+       struct resource *cres;
+       struct puc_bar *bar;
+       device_t cdev, dev;
+       bus_size_t off;
+       int base, crtype, fixed, high, i, oxpcie;
+       uint8_t acr, func, mask;
+
+       if (cmd != PUC_CFG_SETUP)
+               return (ENXIO);
+
+       base = fixed = oxpcie = 0;
+       crtype = SYS_RES_IOPORT;
+       acr = mask = 0x0;
+       func = high = 1;
+       off = 0x60;
+
+       cfg = sc->sc_cfg;
+       switch (cfg->subvendor) {
+       case 0x13fe:
+               switch (cfg->device) {
+               case 0xa102:
+                       high = 0;
+                       break;
+               default:
+                       break;
+               }
+       default:
+               break;
+       }
+       if (fixed == 1)
+               goto setup;
+
+       dev = sc->sc_dev;
+       cdev = pci_find_dbsf(pci_get_domain(dev), pci_get_bus(dev),
+           pci_get_slot(dev), func);
+       if (cdev == NULL) {
+               device_printf(dev, "could not find config function\n");
+               return (ENXIO);
+       }
+
+       i = PCIR_BAR(0);
+       cres = bus_alloc_resource_any(cdev, crtype, &i, RF_ACTIVE);
+       if (cres == NULL) {
+               device_printf(dev, "could not allocate config resource\n");
+               return (ENXIO);
+       }
+
+       if (oxpcie == 0) {
+               mask = bus_read_1(cres, off);
+               if (pci_get_function(dev) == 1)
+                       base = 4;
+       }
+
+ setup:
+       for (i = 0; i < sc->sc_nports; ++i) {
+               device_printf(dev, "port %d: ", i);
+               bar = puc_get_bar(sc, cfg->rid + i * cfg->d_rid);
+               if (bar == NULL) {
+                       printf("could not get BAR\n");
+                       continue;
+               }
+
+               if (fixed == 0) {
+                       if ((mask & (1 << (base + i))) == 0) {
+                               acr = 0;
+                               printf("RS-232\n");
+                       } else {
+                               acr = (high == 1 ? 0x18 : 0x10);
+                               printf("RS-422/RS-485, active-%s auto-DTR\n",
+                                   high == 1 ? "high" : "low");
+                       }
+               }
+
+               bus_write_1(bar->b_res, REG_SPR, REG_ACR);
+               bus_write_1(bar->b_res, REG_ICR, acr);
+       }
+
+       bus_release_resource(cdev, crtype, rman_get_rid(cres), cres);
+       return (0);
+}
+
+static int
 puc_config_amc(struct puc_softc *sc __unused, enum puc_cfg_cmd cmd, int port,
     intptr_t *res)
 {
@@ -1360,24 +1465,17 @@ puc_config_quatech(struct puc_softc *sc,
                bar = puc_get_bar(sc, cfg->rid);
                if (bar == NULL)
                        return (ENXIO);
-               /* Set DLAB in the LCR register of UART 0. */
-               bus_write_1(bar->b_res, 3, 0x80);
-               /* Write 0 to the SPR register of UART 0. */
-               bus_write_1(bar->b_res, 7, 0);
-               /* Read back the contents of the SPR register of UART 0. */
-               v0 = bus_read_1(bar->b_res, 7);
-               /* Write a specific value to the SPR register of UART 0. */
-               bus_write_1(bar->b_res, 7, 0x80 + -cfg->clock);
-               /* Read back the contents of the SPR register of UART 0. */
-               v1 = bus_read_1(bar->b_res, 7);
-               /* Clear DLAB in the LCR register of UART 0. */
-               bus_write_1(bar->b_res, 3, 0);
-               /* Save the two values read-back from the SPR register. */
+               bus_write_1(bar->b_res, REG_LCR, LCR_DLAB);
+               bus_write_1(bar->b_res, REG_SPR, 0);
+               v0 = bus_read_1(bar->b_res, REG_SPR);
+               bus_write_1(bar->b_res, REG_SPR, 0x80 + -cfg->clock);
+               v1 = bus_read_1(bar->b_res, REG_SPR);
+               bus_write_1(bar->b_res, REG_LCR, 0);
                sc->sc_cfg_data = (v0 << 8) | v1;
                if (v0 == 0 && v1 == 0x80 + -cfg->clock) {
                        /*
                         * The SPR register echoed the two values written
-                        * by us. This means that the SPAD jumper is set.
+                        * by us.  This means that the SPAD jumper is set.
                         */
                        device_printf(sc->sc_dev, "warning: extra features "
                            "not usable -- SPAD compatibility enabled\n");
@@ -1385,7 +1483,7 @@ puc_config_quatech(struct puc_softc *sc,
                }
                if (v0 != 0) {
                        /*
-                        * The first value doesn't match. This can only mean
+                        * The first value doesn't match.  This can only mean
                         * that the SPAD jumper is not set and that a non-
                         * standard fixed clock multiplier jumper is set.
                         */
@@ -1399,8 +1497,8 @@ puc_config_quatech(struct puc_softc *sc,
                        return (0);
                }
                /*
-                * The first value matched, but the second didn't. We know
-                * that the SPAD jumper is not set. We also know that the
+                * The first value matched, but the second didn't.  We know
+                * that the SPAD jumper is not set.  We also know that the
                 * clock rate multiplier is software controlled *and* that
                 * we just programmed it to the maximum allowed.
                 */
@@ -1415,8 +1513,8 @@ puc_config_quatech(struct puc_softc *sc,
                        /*
                         * XXX With the SPAD jumper applied, there's no
                         * easy way of knowing if there's also a clock
-                        * rate multiplier jumper installed. Let's hope
-                        * not...
+                        * rate multiplier jumper installed.  Let's hope
+                        * not ...
                         */
                        *res = DEFAULT_RCLK;
                } else if (v0 == 0) {
@@ -1678,15 +1776,15 @@ puc_config_oxford_pcie(struct puc_softc 
        case PUC_CFG_GET_NPORTS:
                /*
                 * Check if we are being called from puc_bfe_attach()
-                * or puc_bfe_probe(). If puc_bfe_probe(), we cannot
-                * puc_get_bar(), so we return a value of 16. This has cosmetic
-                * side-effects at worst; in PUC_CFG_GET_DESC,
-                * (int)sc->sc_cfg_data will not contain the true number of
-                * ports in PUC_CFG_GET_DESC, but we are not implementing that
-                * call for this device family anyway.
+                * or puc_bfe_probe().  If puc_bfe_probe(), we cannot
+                * puc_get_bar(), so we return a value of 16.  This has
+                * cosmetic side-effects at worst; in PUC_CFG_GET_DESC,
+                * sc->sc_cfg_data will not contain the true number of
+                * ports in PUC_CFG_GET_DESC, but we are not implementing
+                * that call for this device family anyway.
                 *
-                * The check is for initialisation of sc->sc_bar[idx], which is
-                * only done in puc_bfe_attach().
+                * The check is for initialization of sc->sc_bar[idx],
+                * which is only done in puc_bfe_attach().
                 */
                idx = 0;
                do {
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to