LCOV - code coverage report
Current view: top level - drivers/tty/serial/8250 - 8250_exar.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 1 247 0.4 %
Date: 2022-04-01 14:58:12 Functions: 1 22 4.5 %
Branches: 0 113 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  *  Probe module for 8250/16550-type Exar chips PCI serial ports.
       4                 :            :  *
       5                 :            :  *  Based on drivers/tty/serial/8250/8250_pci.c,
       6                 :            :  *
       7                 :            :  *  Copyright (C) 2017 Sudip Mukherjee, All Rights Reserved.
       8                 :            :  */
       9                 :            : #include <linux/acpi.h>
      10                 :            : #include <linux/dmi.h>
      11                 :            : #include <linux/io.h>
      12                 :            : #include <linux/kernel.h>
      13                 :            : #include <linux/module.h>
      14                 :            : #include <linux/pci.h>
      15                 :            : #include <linux/property.h>
      16                 :            : #include <linux/serial_core.h>
      17                 :            : #include <linux/serial_reg.h>
      18                 :            : #include <linux/slab.h>
      19                 :            : #include <linux/string.h>
      20                 :            : #include <linux/tty.h>
      21                 :            : #include <linux/8250_pci.h>
      22                 :            : #include <linux/delay.h>
      23                 :            : 
      24                 :            : #include <asm/byteorder.h>
      25                 :            : 
      26                 :            : #include "8250.h"
      27                 :            : 
      28                 :            : #define PCI_DEVICE_ID_ACCES_COM_2S              0x1052
      29                 :            : #define PCI_DEVICE_ID_ACCES_COM_4S              0x105d
      30                 :            : #define PCI_DEVICE_ID_ACCES_COM_8S              0x106c
      31                 :            : #define PCI_DEVICE_ID_ACCES_COM232_8            0x10a8
      32                 :            : #define PCI_DEVICE_ID_ACCES_COM_2SM             0x10d2
      33                 :            : #define PCI_DEVICE_ID_ACCES_COM_4SM             0x10db
      34                 :            : #define PCI_DEVICE_ID_ACCES_COM_8SM             0x10ea
      35                 :            : 
      36                 :            : #define PCI_DEVICE_ID_COMMTECH_4224PCI335       0x0002
      37                 :            : #define PCI_DEVICE_ID_COMMTECH_4222PCI335       0x0004
      38                 :            : #define PCI_DEVICE_ID_COMMTECH_2324PCI335       0x000a
      39                 :            : #define PCI_DEVICE_ID_COMMTECH_2328PCI335       0x000b
      40                 :            : #define PCI_DEVICE_ID_COMMTECH_4224PCIE         0x0020
      41                 :            : #define PCI_DEVICE_ID_COMMTECH_4228PCIE         0x0021
      42                 :            : #define PCI_DEVICE_ID_COMMTECH_4222PCIE         0x0022
      43                 :            : #define PCI_DEVICE_ID_EXAR_XR17V4358            0x4358
      44                 :            : #define PCI_DEVICE_ID_EXAR_XR17V8358            0x8358
      45                 :            : 
      46                 :            : #define UART_EXAR_INT0          0x80
      47                 :            : #define UART_EXAR_8XMODE        0x88    /* 8X sampling rate select */
      48                 :            : #define UART_EXAR_SLEEP         0x8b    /* Sleep mode */
      49                 :            : #define UART_EXAR_DVID          0x8d    /* Device identification */
      50                 :            : 
      51                 :            : #define UART_EXAR_FCTR          0x08    /* Feature Control Register */
      52                 :            : #define UART_FCTR_EXAR_IRDA     0x10    /* IrDa data encode select */
      53                 :            : #define UART_FCTR_EXAR_485      0x20    /* Auto 485 half duplex dir ctl */
      54                 :            : #define UART_FCTR_EXAR_TRGA     0x00    /* FIFO trigger table A */
      55                 :            : #define UART_FCTR_EXAR_TRGB     0x60    /* FIFO trigger table B */
      56                 :            : #define UART_FCTR_EXAR_TRGC     0x80    /* FIFO trigger table C */
      57                 :            : #define UART_FCTR_EXAR_TRGD     0xc0    /* FIFO trigger table D programmable */
      58                 :            : 
      59                 :            : #define UART_EXAR_TXTRG         0x0a    /* Tx FIFO trigger level write-only */
      60                 :            : #define UART_EXAR_RXTRG         0x0b    /* Rx FIFO trigger level write-only */
      61                 :            : 
      62                 :            : #define UART_EXAR_MPIOINT_7_0   0x8f    /* MPIOINT[7:0] */
      63                 :            : #define UART_EXAR_MPIOLVL_7_0   0x90    /* MPIOLVL[7:0] */
      64                 :            : #define UART_EXAR_MPIO3T_7_0    0x91    /* MPIO3T[7:0] */
      65                 :            : #define UART_EXAR_MPIOINV_7_0   0x92    /* MPIOINV[7:0] */
      66                 :            : #define UART_EXAR_MPIOSEL_7_0   0x93    /* MPIOSEL[7:0] */
      67                 :            : #define UART_EXAR_MPIOOD_7_0    0x94    /* MPIOOD[7:0] */
      68                 :            : #define UART_EXAR_MPIOINT_15_8  0x95    /* MPIOINT[15:8] */
      69                 :            : #define UART_EXAR_MPIOLVL_15_8  0x96    /* MPIOLVL[15:8] */
      70                 :            : #define UART_EXAR_MPIO3T_15_8   0x97    /* MPIO3T[15:8] */
      71                 :            : #define UART_EXAR_MPIOINV_15_8  0x98    /* MPIOINV[15:8] */
      72                 :            : #define UART_EXAR_MPIOSEL_15_8  0x99    /* MPIOSEL[15:8] */
      73                 :            : #define UART_EXAR_MPIOOD_15_8   0x9a    /* MPIOOD[15:8] */
      74                 :            : 
      75                 :            : #define UART_EXAR_RS485_DLY(x)  ((x) << 4)
      76                 :            : 
      77                 :            : /*
      78                 :            :  * IOT2040 MPIO wiring semantics:
      79                 :            :  *
      80                 :            :  * MPIO         Port    Function
      81                 :            :  * ----         ----    --------
      82                 :            :  * 0            2       Mode bit 0
      83                 :            :  * 1            2       Mode bit 1
      84                 :            :  * 2            2       Terminate bus
      85                 :            :  * 3            -       <reserved>
      86                 :            :  * 4            3       Mode bit 0
      87                 :            :  * 5            3       Mode bit 1
      88                 :            :  * 6            3       Terminate bus
      89                 :            :  * 7            -       <reserved>
      90                 :            :  * 8            2       Enable
      91                 :            :  * 9            3       Enable
      92                 :            :  * 10           -       Red LED
      93                 :            :  * 11..15       -       <unused>
      94                 :            :  */
      95                 :            : 
      96                 :            : /* IOT2040 MPIOs 0..7 */
      97                 :            : #define IOT2040_UART_MODE_RS232         0x01
      98                 :            : #define IOT2040_UART_MODE_RS485         0x02
      99                 :            : #define IOT2040_UART_MODE_RS422         0x03
     100                 :            : #define IOT2040_UART_TERMINATE_BUS      0x04
     101                 :            : 
     102                 :            : #define IOT2040_UART1_MASK              0x0f
     103                 :            : #define IOT2040_UART2_SHIFT             4
     104                 :            : 
     105                 :            : #define IOT2040_UARTS_DEFAULT_MODE      0x11    /* both RS232 */
     106                 :            : #define IOT2040_UARTS_GPIO_LO_MODE      0x88    /* reserved pins as input */
     107                 :            : 
     108                 :            : /* IOT2040 MPIOs 8..15 */
     109                 :            : #define IOT2040_UARTS_ENABLE            0x03
     110                 :            : #define IOT2040_UARTS_GPIO_HI_MODE      0xF8    /* enable & LED as outputs */
     111                 :            : 
     112                 :            : struct exar8250;
     113                 :            : 
     114                 :            : struct exar8250_platform {
     115                 :            :         int (*rs485_config)(struct uart_port *, struct serial_rs485 *);
     116                 :            :         int (*register_gpio)(struct pci_dev *, struct uart_8250_port *);
     117                 :            : };
     118                 :            : 
     119                 :            : /**
     120                 :            :  * struct exar8250_board - board information
     121                 :            :  * @num_ports: number of serial ports
     122                 :            :  * @reg_shift: describes UART register mapping in PCI memory
     123                 :            :  * @setup: quirk run at ->probe() stage
     124                 :            :  * @exit: quirk run at ->remove() stage
     125                 :            :  */
     126                 :            : struct exar8250_board {
     127                 :            :         unsigned int num_ports;
     128                 :            :         unsigned int reg_shift;
     129                 :            :         int     (*setup)(struct exar8250 *, struct pci_dev *,
     130                 :            :                          struct uart_8250_port *, int);
     131                 :            :         void    (*exit)(struct pci_dev *pcidev);
     132                 :            : };
     133                 :            : 
     134                 :            : struct exar8250 {
     135                 :            :         unsigned int            nr;
     136                 :            :         struct exar8250_board   *board;
     137                 :            :         void __iomem            *virt;
     138                 :            :         int                     line[0];
     139                 :            : };
     140                 :            : 
     141                 :          0 : static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old)
     142                 :            : {
     143                 :            :         /*
     144                 :            :          * Exar UARTs have a SLEEP register that enables or disables each UART
     145                 :            :          * to enter sleep mode separately. On the XR17V35x the register
     146                 :            :          * is accessible to each UART at the UART_EXAR_SLEEP offset, but
     147                 :            :          * the UART channel may only write to the corresponding bit.
     148                 :            :          */
     149         [ #  # ]:          0 :         serial_port_out(port, UART_EXAR_SLEEP, state ? 0xff : 0);
     150                 :          0 : }
     151                 :            : 
     152                 :            : /*
     153                 :            :  * XR17V35x UARTs have an extra fractional divisor register (DLD)
     154                 :            :  * Calculate divisor with extra 4-bit fractional portion
     155                 :            :  */
     156                 :          0 : static unsigned int xr17v35x_get_divisor(struct uart_port *p, unsigned int baud,
     157                 :            :                                          unsigned int *frac)
     158                 :            : {
     159                 :          0 :         unsigned int quot_16;
     160                 :            : 
     161                 :          0 :         quot_16 = DIV_ROUND_CLOSEST(p->uartclk, baud);
     162                 :          0 :         *frac = quot_16 & 0x0f;
     163                 :            : 
     164                 :          0 :         return quot_16 >> 4;
     165                 :            : }
     166                 :            : 
     167                 :          0 : static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud,
     168                 :            :                                  unsigned int quot, unsigned int quot_frac)
     169                 :            : {
     170                 :          0 :         serial8250_do_set_divisor(p, baud, quot, quot_frac);
     171                 :            : 
     172                 :            :         /* Preserve bits not related to baudrate; DLD[7:4]. */
     173                 :          0 :         quot_frac |= serial_port_in(p, 0x2) & 0xf0;
     174                 :          0 :         serial_port_out(p, 0x2, quot_frac);
     175                 :          0 : }
     176                 :            : 
     177                 :          0 : static int xr17v35x_startup(struct uart_port *port)
     178                 :            : {
     179                 :            :         /*
     180                 :            :          * First enable access to IER [7:5], ISR [5:4], FCR [5:4],
     181                 :            :          * MCR [7:5] and MSR [7:0]
     182                 :            :          */
     183                 :          0 :         serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
     184                 :            : 
     185                 :            :         /*
     186                 :            :          * Make sure all interrups are masked until initialization is
     187                 :            :          * complete and the FIFOs are cleared
     188                 :            :          */
     189                 :          0 :         serial_port_out(port, UART_IER, 0);
     190                 :            : 
     191                 :          0 :         return serial8250_do_startup(port);
     192                 :            : }
     193                 :            : 
     194                 :          0 : static void exar_shutdown(struct uart_port *port)
     195                 :            : {
     196                 :          0 :         unsigned char lsr;
     197                 :          0 :         bool tx_complete = false;
     198                 :          0 :         struct uart_8250_port *up = up_to_u8250p(port);
     199                 :          0 :         struct circ_buf *xmit = &port->state->xmit;
     200                 :          0 :         int i = 0;
     201                 :            : 
     202                 :          0 :         do {
     203                 :          0 :                 lsr = serial_in(up, UART_LSR);
     204         [ #  # ]:          0 :                 if (lsr & (UART_LSR_TEMT | UART_LSR_THRE))
     205                 :            :                         tx_complete = true;
     206                 :            :                 else
     207                 :          0 :                         tx_complete = false;
     208                 :          0 :                 usleep_range(1000, 1100);
     209   [ #  #  #  #  :          0 :         } while (!uart_circ_empty(xmit) && !tx_complete && i++ < 1000);
                   #  # ]
     210                 :            : 
     211                 :          0 :         serial8250_do_shutdown(port);
     212                 :          0 : }
     213                 :            : 
     214                 :          0 : static int default_setup(struct exar8250 *priv, struct pci_dev *pcidev,
     215                 :            :                          int idx, unsigned int offset,
     216                 :            :                          struct uart_8250_port *port)
     217                 :            : {
     218                 :          0 :         const struct exar8250_board *board = priv->board;
     219                 :          0 :         unsigned int bar = 0;
     220                 :          0 :         unsigned char status;
     221                 :            : 
     222                 :          0 :         port->port.iotype = UPIO_MEM;
     223                 :          0 :         port->port.mapbase = pci_resource_start(pcidev, bar) + offset;
     224                 :          0 :         port->port.membase = priv->virt + offset;
     225                 :          0 :         port->port.regshift = board->reg_shift;
     226                 :            : 
     227                 :            :         /*
     228                 :            :          * XR17V35x UARTs have an extra divisor register, DLD that gets enabled
     229                 :            :          * with when DLAB is set which will cause the device to incorrectly match
     230                 :            :          * and assign port type to PORT_16650. The EFR for this UART is found
     231                 :            :          * at offset 0x09. Instead check the Deice ID (DVID) register
     232                 :            :          * for a 2, 4 or 8 port UART.
     233                 :            :          */
     234                 :          0 :         status = readb(port->port.membase + UART_EXAR_DVID);
     235   [ #  #  #  #  :          0 :         if (status == 0x82 || status == 0x84 || status == 0x88) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     236                 :          0 :                 port->port.type = PORT_XR17V35X;
     237                 :            : 
     238                 :          0 :                 port->port.get_divisor = xr17v35x_get_divisor;
     239                 :          0 :                 port->port.set_divisor = xr17v35x_set_divisor;
     240                 :            : 
     241                 :          0 :                 port->port.startup = xr17v35x_startup;
     242                 :            :         } else {
     243                 :          0 :                 port->port.type = PORT_XR17D15X;
     244                 :            :         }
     245                 :            : 
     246                 :          0 :         port->port.pm = exar_pm;
     247                 :          0 :         port->port.shutdown = exar_shutdown;
     248                 :            : 
     249                 :          0 :         return 0;
     250                 :            : }
     251                 :            : 
     252                 :            : static int
     253                 :          0 : pci_fastcom335_setup(struct exar8250 *priv, struct pci_dev *pcidev,
     254                 :            :                      struct uart_8250_port *port, int idx)
     255                 :            : {
     256                 :          0 :         unsigned int offset = idx * 0x200;
     257                 :          0 :         unsigned int baud = 1843200;
     258                 :          0 :         u8 __iomem *p;
     259                 :          0 :         int err;
     260                 :            : 
     261                 :          0 :         port->port.uartclk = baud * 16;
     262                 :            : 
     263                 :          0 :         err = default_setup(priv, pcidev, idx, offset, port);
     264                 :          0 :         if (err)
     265                 :            :                 return err;
     266                 :            : 
     267                 :          0 :         p = port->port.membase;
     268                 :            : 
     269                 :          0 :         writeb(0x00, p + UART_EXAR_8XMODE);
     270                 :          0 :         writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
     271                 :          0 :         writeb(32, p + UART_EXAR_TXTRG);
     272                 :          0 :         writeb(32, p + UART_EXAR_RXTRG);
     273                 :            : 
     274                 :            :         /*
     275                 :            :          * Setup Multipurpose Input/Output pins.
     276                 :            :          */
     277         [ #  # ]:          0 :         if (idx == 0) {
     278      [ #  #  # ]:          0 :                 switch (pcidev->device) {
     279                 :          0 :                 case PCI_DEVICE_ID_COMMTECH_4222PCI335:
     280                 :            :                 case PCI_DEVICE_ID_COMMTECH_4224PCI335:
     281                 :          0 :                         writeb(0x78, p + UART_EXAR_MPIOLVL_7_0);
     282                 :          0 :                         writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
     283                 :          0 :                         writeb(0x00, p + UART_EXAR_MPIOSEL_7_0);
     284                 :            :                         break;
     285                 :          0 :                 case PCI_DEVICE_ID_COMMTECH_2324PCI335:
     286                 :            :                 case PCI_DEVICE_ID_COMMTECH_2328PCI335:
     287                 :          0 :                         writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
     288                 :          0 :                         writeb(0xc0, p + UART_EXAR_MPIOINV_7_0);
     289                 :          0 :                         writeb(0xc0, p + UART_EXAR_MPIOSEL_7_0);
     290                 :            :                         break;
     291                 :            :                 }
     292                 :          0 :                 writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
     293                 :          0 :                 writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
     294                 :          0 :                 writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
     295                 :            :         }
     296                 :            : 
     297                 :          0 :         return 0;
     298                 :            : }
     299                 :            : 
     300                 :            : static int
     301                 :          0 : pci_connect_tech_setup(struct exar8250 *priv, struct pci_dev *pcidev,
     302                 :            :                        struct uart_8250_port *port, int idx)
     303                 :            : {
     304                 :          0 :         unsigned int offset = idx * 0x200;
     305                 :          0 :         unsigned int baud = 1843200;
     306                 :            : 
     307                 :          0 :         port->port.uartclk = baud * 16;
     308                 :          0 :         return default_setup(priv, pcidev, idx, offset, port);
     309                 :            : }
     310                 :            : 
     311                 :            : static int
     312                 :          0 : pci_xr17c154_setup(struct exar8250 *priv, struct pci_dev *pcidev,
     313                 :            :                    struct uart_8250_port *port, int idx)
     314                 :            : {
     315                 :          0 :         unsigned int offset = idx * 0x200;
     316                 :          0 :         unsigned int baud = 921600;
     317                 :            : 
     318                 :          0 :         port->port.uartclk = baud * 16;
     319                 :          0 :         return default_setup(priv, pcidev, idx, offset, port);
     320                 :            : }
     321                 :            : 
     322                 :            : static void setup_gpio(struct pci_dev *pcidev, u8 __iomem *p)
     323                 :            : {
     324                 :            :         /*
     325                 :            :          * The Commtech adapters required the MPIOs to be driven low. The Exar
     326                 :            :          * devices will export them as GPIOs, so we pre-configure them safely
     327                 :            :          * as inputs.
     328                 :            :          */
     329                 :            :         u8 dir = pcidev->vendor == PCI_VENDOR_ID_EXAR ? 0xff : 0x00;
     330                 :            : 
     331                 :            :         writeb(0x00, p + UART_EXAR_MPIOINT_7_0);
     332                 :            :         writeb(0x00, p + UART_EXAR_MPIOLVL_7_0);
     333                 :            :         writeb(0x00, p + UART_EXAR_MPIO3T_7_0);
     334                 :            :         writeb(0x00, p + UART_EXAR_MPIOINV_7_0);
     335                 :            :         writeb(dir,  p + UART_EXAR_MPIOSEL_7_0);
     336                 :            :         writeb(0x00, p + UART_EXAR_MPIOOD_7_0);
     337                 :            :         writeb(0x00, p + UART_EXAR_MPIOINT_15_8);
     338                 :            :         writeb(0x00, p + UART_EXAR_MPIOLVL_15_8);
     339                 :            :         writeb(0x00, p + UART_EXAR_MPIO3T_15_8);
     340                 :            :         writeb(0x00, p + UART_EXAR_MPIOINV_15_8);
     341                 :            :         writeb(dir,  p + UART_EXAR_MPIOSEL_15_8);
     342                 :            :         writeb(0x00, p + UART_EXAR_MPIOOD_15_8);
     343                 :            : }
     344                 :            : 
     345                 :            : static void *
     346                 :          0 : __xr17v35x_register_gpio(struct pci_dev *pcidev,
     347                 :            :                          const struct property_entry *properties)
     348                 :            : {
     349                 :          0 :         struct platform_device *pdev;
     350                 :            : 
     351                 :          0 :         pdev = platform_device_alloc("gpio_exar", PLATFORM_DEVID_AUTO);
     352         [ #  # ]:          0 :         if (!pdev)
     353                 :            :                 return NULL;
     354                 :            : 
     355                 :          0 :         pdev->dev.parent = &pcidev->dev;
     356   [ #  #  #  #  :          0 :         ACPI_COMPANION_SET(&pdev->dev, ACPI_COMPANION(&pcidev->dev));
                   #  # ]
     357                 :            : 
     358   [ #  #  #  # ]:          0 :         if (platform_device_add_properties(pdev, properties) < 0 ||
     359                 :          0 :             platform_device_add(pdev) < 0) {
     360                 :          0 :                 platform_device_put(pdev);
     361                 :          0 :                 return NULL;
     362                 :            :         }
     363                 :            : 
     364                 :            :         return pdev;
     365                 :            : }
     366                 :            : 
     367                 :            : static const struct property_entry exar_gpio_properties[] = {
     368                 :            :         PROPERTY_ENTRY_U32("exar,first-pin", 0),
     369                 :            :         PROPERTY_ENTRY_U32("ngpios", 16),
     370                 :            :         { }
     371                 :            : };
     372                 :            : 
     373                 :          0 : static int xr17v35x_register_gpio(struct pci_dev *pcidev,
     374                 :            :                                   struct uart_8250_port *port)
     375                 :            : {
     376         [ #  # ]:          0 :         if (pcidev->vendor == PCI_VENDOR_ID_EXAR)
     377                 :          0 :                 port->port.private_data =
     378                 :          0 :                         __xr17v35x_register_gpio(pcidev, exar_gpio_properties);
     379                 :            : 
     380                 :          0 :         return 0;
     381                 :            : }
     382                 :            : 
     383                 :          0 : static int generic_rs485_config(struct uart_port *port,
     384                 :            :                                 struct serial_rs485 *rs485)
     385                 :            : {
     386                 :          0 :         bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED);
     387                 :          0 :         u8 __iomem *p = port->membase;
     388                 :          0 :         u8 value;
     389                 :            : 
     390                 :          0 :         value = readb(p + UART_EXAR_FCTR);
     391   [ #  #  #  # ]:          0 :         if (is_rs485)
     392                 :          0 :                 value |= UART_FCTR_EXAR_485;
     393                 :            :         else
     394                 :          0 :                 value &= ~UART_FCTR_EXAR_485;
     395                 :            : 
     396                 :          0 :         writeb(value, p + UART_EXAR_FCTR);
     397                 :            : 
     398   [ #  #  #  # ]:          0 :         if (is_rs485)
     399                 :          0 :                 writeb(UART_EXAR_RS485_DLY(4), p + UART_MSR);
     400                 :            : 
     401                 :          0 :         port->rs485 = *rs485;
     402                 :            : 
     403                 :          0 :         return 0;
     404                 :            : }
     405                 :            : 
     406                 :            : static const struct exar8250_platform exar8250_default_platform = {
     407                 :            :         .register_gpio = xr17v35x_register_gpio,
     408                 :            :         .rs485_config = generic_rs485_config,
     409                 :            : };
     410                 :            : 
     411                 :          0 : static int iot2040_rs485_config(struct uart_port *port,
     412                 :            :                                 struct serial_rs485 *rs485)
     413                 :            : {
     414                 :          0 :         bool is_rs485 = !!(rs485->flags & SER_RS485_ENABLED);
     415                 :          0 :         u8 __iomem *p = port->membase;
     416                 :          0 :         u8 mask = IOT2040_UART1_MASK;
     417                 :          0 :         u8 mode, value;
     418                 :            : 
     419         [ #  # ]:          0 :         if (is_rs485) {
     420         [ #  # ]:          0 :                 if (rs485->flags & SER_RS485_RX_DURING_TX)
     421                 :            :                         mode = IOT2040_UART_MODE_RS422;
     422                 :            :                 else
     423                 :          0 :                         mode = IOT2040_UART_MODE_RS485;
     424                 :            : 
     425         [ #  # ]:          0 :                 if (rs485->flags & SER_RS485_TERMINATE_BUS)
     426                 :          0 :                         mode |= IOT2040_UART_TERMINATE_BUS;
     427                 :            :         } else {
     428                 :            :                 mode = IOT2040_UART_MODE_RS232;
     429                 :            :         }
     430                 :            : 
     431         [ #  # ]:          0 :         if (port->line == 3) {
     432                 :          0 :                 mask <<= IOT2040_UART2_SHIFT;
     433                 :          0 :                 mode <<= IOT2040_UART2_SHIFT;
     434                 :            :         }
     435                 :            : 
     436                 :          0 :         value = readb(p + UART_EXAR_MPIOLVL_7_0);
     437                 :          0 :         value &= ~mask;
     438                 :          0 :         value |= mode;
     439                 :          0 :         writeb(value, p + UART_EXAR_MPIOLVL_7_0);
     440                 :            : 
     441                 :          0 :         return generic_rs485_config(port, rs485);
     442                 :            : }
     443                 :            : 
     444                 :            : static const struct property_entry iot2040_gpio_properties[] = {
     445                 :            :         PROPERTY_ENTRY_U32("exar,first-pin", 10),
     446                 :            :         PROPERTY_ENTRY_U32("ngpios", 1),
     447                 :            :         { }
     448                 :            : };
     449                 :            : 
     450                 :          0 : static int iot2040_register_gpio(struct pci_dev *pcidev,
     451                 :            :                               struct uart_8250_port *port)
     452                 :            : {
     453                 :          0 :         u8 __iomem *p = port->port.membase;
     454                 :            : 
     455                 :          0 :         writeb(IOT2040_UARTS_DEFAULT_MODE, p + UART_EXAR_MPIOLVL_7_0);
     456                 :          0 :         writeb(IOT2040_UARTS_GPIO_LO_MODE, p + UART_EXAR_MPIOSEL_7_0);
     457                 :          0 :         writeb(IOT2040_UARTS_ENABLE, p + UART_EXAR_MPIOLVL_15_8);
     458                 :          0 :         writeb(IOT2040_UARTS_GPIO_HI_MODE, p + UART_EXAR_MPIOSEL_15_8);
     459                 :            : 
     460                 :          0 :         port->port.private_data =
     461                 :          0 :                 __xr17v35x_register_gpio(pcidev, iot2040_gpio_properties);
     462                 :            : 
     463                 :          0 :         return 0;
     464                 :            : }
     465                 :            : 
     466                 :            : static const struct exar8250_platform iot2040_platform = {
     467                 :            :         .rs485_config = iot2040_rs485_config,
     468                 :            :         .register_gpio = iot2040_register_gpio,
     469                 :            : };
     470                 :            : 
     471                 :            : /*
     472                 :            :  * For SIMATIC IOT2000, only IOT2040 and its variants have the Exar device,
     473                 :            :  * IOT2020 doesn't have. Therefore it is sufficient to match on the common
     474                 :            :  * board name after the device was found.
     475                 :            :  */
     476                 :            : static const struct dmi_system_id exar_platforms[] = {
     477                 :            :         {
     478                 :            :                 .matches = {
     479                 :            :                         DMI_EXACT_MATCH(DMI_BOARD_NAME, "SIMATIC IOT2000"),
     480                 :            :                 },
     481                 :            :                 .driver_data = (void *)&iot2040_platform,
     482                 :            :         },
     483                 :            :         {}
     484                 :            : };
     485                 :            : 
     486                 :            : static int
     487                 :          0 : pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,
     488                 :            :                    struct uart_8250_port *port, int idx)
     489                 :            : {
     490                 :          0 :         const struct exar8250_platform *platform;
     491                 :          0 :         const struct dmi_system_id *dmi_match;
     492                 :          0 :         unsigned int offset = idx * 0x400;
     493                 :          0 :         unsigned int baud = 7812500;
     494                 :          0 :         u8 __iomem *p;
     495                 :          0 :         int ret;
     496                 :            : 
     497                 :          0 :         dmi_match = dmi_first_match(exar_platforms);
     498         [ #  # ]:          0 :         if (dmi_match)
     499                 :          0 :                 platform = dmi_match->driver_data;
     500                 :            :         else
     501                 :            :                 platform = &exar8250_default_platform;
     502                 :            : 
     503                 :          0 :         port->port.uartclk = baud * 16;
     504                 :          0 :         port->port.rs485_config = platform->rs485_config;
     505                 :            : 
     506                 :            :         /*
     507                 :            :          * Setup the UART clock for the devices on expansion slot to
     508                 :            :          * half the clock speed of the main chip (which is 125MHz)
     509                 :            :          */
     510         [ #  # ]:          0 :         if (idx >= 8)
     511                 :          0 :                 port->port.uartclk /= 2;
     512                 :            : 
     513                 :          0 :         ret = default_setup(priv, pcidev, idx, offset, port);
     514                 :          0 :         if (ret)
     515                 :            :                 return ret;
     516                 :            : 
     517                 :          0 :         p = port->port.membase;
     518                 :            : 
     519                 :          0 :         writeb(0x00, p + UART_EXAR_8XMODE);
     520                 :          0 :         writeb(UART_FCTR_EXAR_TRGD, p + UART_EXAR_FCTR);
     521                 :          0 :         writeb(128, p + UART_EXAR_TXTRG);
     522                 :          0 :         writeb(128, p + UART_EXAR_RXTRG);
     523                 :            : 
     524         [ #  # ]:          0 :         if (idx == 0) {
     525                 :            :                 /* Setup Multipurpose Input/Output pins. */
     526                 :          0 :                 setup_gpio(pcidev, p);
     527                 :            : 
     528                 :          0 :                 ret = platform->register_gpio(pcidev, port);
     529                 :            :         }
     530                 :            : 
     531                 :          0 :         return ret;
     532                 :            : }
     533                 :            : 
     534                 :          0 : static void pci_xr17v35x_exit(struct pci_dev *pcidev)
     535                 :            : {
     536                 :          0 :         struct exar8250 *priv = pci_get_drvdata(pcidev);
     537                 :          0 :         struct uart_8250_port *port = serial8250_get_port(priv->line[0]);
     538                 :          0 :         struct platform_device *pdev = port->port.private_data;
     539                 :            : 
     540                 :          0 :         platform_device_unregister(pdev);
     541                 :          0 :         port->port.private_data = NULL;
     542                 :          0 : }
     543                 :            : 
     544                 :          0 : static inline void exar_misc_clear(struct exar8250 *priv)
     545                 :            : {
     546                 :            :         /* Clear all PCI interrupts by reading INT0. No effect on IIR */
     547                 :          0 :         readb(priv->virt + UART_EXAR_INT0);
     548                 :            : 
     549                 :            :         /* Clear INT0 for Expansion Interface slave ports, too */
     550   [ #  #  #  #  :          0 :         if (priv->board->num_ports > 8)
                   #  # ]
     551                 :          0 :                 readb(priv->virt + 0x2000 + UART_EXAR_INT0);
     552                 :            : }
     553                 :            : 
     554                 :            : /*
     555                 :            :  * These Exar UARTs have an extra interrupt indicator that could fire for a
     556                 :            :  * few interrupts that are not presented/cleared through IIR.  One of which is
     557                 :            :  * a wakeup interrupt when coming out of sleep.  These interrupts are only
     558                 :            :  * cleared by reading global INT0 or INT1 registers as interrupts are
     559                 :            :  * associated with channel 0. The INT[3:0] registers _are_ accessible from each
     560                 :            :  * channel's address space, but for the sake of bus efficiency we register a
     561                 :            :  * dedicated handler at the PCI device level to handle them.
     562                 :            :  */
     563                 :          0 : static irqreturn_t exar_misc_handler(int irq, void *data)
     564                 :            : {
     565                 :          0 :         exar_misc_clear(data);
     566                 :            : 
     567                 :          0 :         return IRQ_HANDLED;
     568                 :            : }
     569                 :            : 
     570                 :            : static int
     571                 :          0 : exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
     572                 :            : {
     573                 :          0 :         unsigned int nr_ports, i, bar = 0, maxnr;
     574                 :          0 :         struct exar8250_board *board;
     575                 :          0 :         struct uart_8250_port uart;
     576                 :          0 :         struct exar8250 *priv;
     577                 :          0 :         int rc;
     578                 :            : 
     579                 :          0 :         board = (struct exar8250_board *)ent->driver_data;
     580         [ #  # ]:          0 :         if (!board)
     581                 :            :                 return -EINVAL;
     582                 :            : 
     583                 :          0 :         rc = pcim_enable_device(pcidev);
     584         [ #  # ]:          0 :         if (rc)
     585                 :            :                 return rc;
     586                 :            : 
     587   [ #  #  #  # ]:          0 :         maxnr = pci_resource_len(pcidev, bar) >> (board->reg_shift + 3);
     588                 :            : 
     589         [ #  # ]:          0 :         nr_ports = board->num_ports ? board->num_ports : pcidev->device & 0x0f;
     590                 :            : 
     591         [ #  # ]:          0 :         priv = devm_kzalloc(&pcidev->dev, struct_size(priv, line, nr_ports), GFP_KERNEL);
     592         [ #  # ]:          0 :         if (!priv)
     593                 :            :                 return -ENOMEM;
     594                 :            : 
     595                 :          0 :         priv->board = board;
     596                 :          0 :         priv->virt = pcim_iomap(pcidev, bar, 0);
     597         [ #  # ]:          0 :         if (!priv->virt)
     598                 :            :                 return -ENOMEM;
     599                 :            : 
     600                 :          0 :         pci_set_master(pcidev);
     601                 :            : 
     602                 :          0 :         rc = pci_alloc_irq_vectors(pcidev, 1, 1, PCI_IRQ_ALL_TYPES);
     603         [ #  # ]:          0 :         if (rc < 0)
     604                 :            :                 return rc;
     605                 :            : 
     606                 :          0 :         memset(&uart, 0, sizeof(uart));
     607                 :          0 :         uart.port.flags = UPF_SHARE_IRQ | UPF_EXAR_EFR | UPF_FIXED_TYPE | UPF_FIXED_PORT;
     608                 :          0 :         uart.port.irq = pci_irq_vector(pcidev, 0);
     609                 :          0 :         uart.port.dev = &pcidev->dev;
     610                 :            : 
     611                 :          0 :         rc = devm_request_irq(&pcidev->dev, uart.port.irq, exar_misc_handler,
     612                 :            :                          IRQF_SHARED, "exar_uart", priv);
     613         [ #  # ]:          0 :         if (rc)
     614                 :            :                 return rc;
     615                 :            : 
     616                 :            :         /* Clear interrupts */
     617                 :          0 :         exar_misc_clear(priv);
     618                 :            : 
     619         [ #  # ]:          0 :         for (i = 0; i < nr_ports && i < maxnr; i++) {
     620                 :          0 :                 rc = board->setup(priv, pcidev, &uart, i);
     621         [ #  # ]:          0 :                 if (rc) {
     622                 :          0 :                         dev_err(&pcidev->dev, "Failed to setup port %u\n", i);
     623                 :          0 :                         break;
     624                 :            :                 }
     625                 :            : 
     626                 :          0 :                 dev_dbg(&pcidev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
     627                 :            :                         uart.port.iobase, uart.port.irq, uart.port.iotype);
     628                 :            : 
     629                 :          0 :                 priv->line[i] = serial8250_register_8250_port(&uart);
     630         [ #  # ]:          0 :                 if (priv->line[i] < 0) {
     631                 :          0 :                         dev_err(&pcidev->dev,
     632                 :            :                                 "Couldn't register serial port %lx, irq %d, type %d, error %d\n",
     633                 :            :                                 uart.port.iobase, uart.port.irq,
     634                 :            :                                 uart.port.iotype, priv->line[i]);
     635                 :          0 :                         break;
     636                 :            :                 }
     637                 :            :         }
     638                 :          0 :         priv->nr = i;
     639                 :          0 :         pci_set_drvdata(pcidev, priv);
     640                 :          0 :         return 0;
     641                 :            : }
     642                 :            : 
     643                 :          0 : static void exar_pci_remove(struct pci_dev *pcidev)
     644                 :            : {
     645                 :          0 :         struct exar8250 *priv = pci_get_drvdata(pcidev);
     646                 :          0 :         unsigned int i;
     647                 :            : 
     648         [ #  # ]:          0 :         for (i = 0; i < priv->nr; i++)
     649                 :          0 :                 serial8250_unregister_port(priv->line[i]);
     650                 :            : 
     651         [ #  # ]:          0 :         if (priv->board->exit)
     652                 :          0 :                 priv->board->exit(pcidev);
     653                 :          0 : }
     654                 :            : 
     655                 :          0 : static int __maybe_unused exar_suspend(struct device *dev)
     656                 :            : {
     657                 :          0 :         struct pci_dev *pcidev = to_pci_dev(dev);
     658                 :          0 :         struct exar8250 *priv = pci_get_drvdata(pcidev);
     659                 :          0 :         unsigned int i;
     660                 :            : 
     661         [ #  # ]:          0 :         for (i = 0; i < priv->nr; i++)
     662         [ #  # ]:          0 :                 if (priv->line[i] >= 0)
     663                 :          0 :                         serial8250_suspend_port(priv->line[i]);
     664                 :            : 
     665                 :            :         /* Ensure that every init quirk is properly torn down */
     666         [ #  # ]:          0 :         if (priv->board->exit)
     667                 :          0 :                 priv->board->exit(pcidev);
     668                 :            : 
     669                 :          0 :         return 0;
     670                 :            : }
     671                 :            : 
     672                 :          0 : static int __maybe_unused exar_resume(struct device *dev)
     673                 :            : {
     674                 :          0 :         struct exar8250 *priv = dev_get_drvdata(dev);
     675                 :          0 :         unsigned int i;
     676                 :            : 
     677                 :          0 :         exar_misc_clear(priv);
     678                 :            : 
     679         [ #  # ]:          0 :         for (i = 0; i < priv->nr; i++)
     680         [ #  # ]:          0 :                 if (priv->line[i] >= 0)
     681                 :          0 :                         serial8250_resume_port(priv->line[i]);
     682                 :            : 
     683                 :          0 :         return 0;
     684                 :            : }
     685                 :            : 
     686                 :            : static SIMPLE_DEV_PM_OPS(exar_pci_pm, exar_suspend, exar_resume);
     687                 :            : 
     688                 :            : static const struct exar8250_board acces_com_2x = {
     689                 :            :         .num_ports      = 2,
     690                 :            :         .setup          = pci_xr17c154_setup,
     691                 :            : };
     692                 :            : 
     693                 :            : static const struct exar8250_board acces_com_4x = {
     694                 :            :         .num_ports      = 4,
     695                 :            :         .setup          = pci_xr17c154_setup,
     696                 :            : };
     697                 :            : 
     698                 :            : static const struct exar8250_board acces_com_8x = {
     699                 :            :         .num_ports      = 8,
     700                 :            :         .setup          = pci_xr17c154_setup,
     701                 :            : };
     702                 :            : 
     703                 :            : 
     704                 :            : static const struct exar8250_board pbn_fastcom335_2 = {
     705                 :            :         .num_ports      = 2,
     706                 :            :         .setup          = pci_fastcom335_setup,
     707                 :            : };
     708                 :            : 
     709                 :            : static const struct exar8250_board pbn_fastcom335_4 = {
     710                 :            :         .num_ports      = 4,
     711                 :            :         .setup          = pci_fastcom335_setup,
     712                 :            : };
     713                 :            : 
     714                 :            : static const struct exar8250_board pbn_fastcom335_8 = {
     715                 :            :         .num_ports      = 8,
     716                 :            :         .setup          = pci_fastcom335_setup,
     717                 :            : };
     718                 :            : 
     719                 :            : static const struct exar8250_board pbn_connect = {
     720                 :            :         .setup          = pci_connect_tech_setup,
     721                 :            : };
     722                 :            : 
     723                 :            : static const struct exar8250_board pbn_exar_ibm_saturn = {
     724                 :            :         .num_ports      = 1,
     725                 :            :         .setup          = pci_xr17c154_setup,
     726                 :            : };
     727                 :            : 
     728                 :            : static const struct exar8250_board pbn_exar_XR17C15x = {
     729                 :            :         .setup          = pci_xr17c154_setup,
     730                 :            : };
     731                 :            : 
     732                 :            : static const struct exar8250_board pbn_exar_XR17V35x = {
     733                 :            :         .setup          = pci_xr17v35x_setup,
     734                 :            :         .exit           = pci_xr17v35x_exit,
     735                 :            : };
     736                 :            : 
     737                 :            : static const struct exar8250_board pbn_exar_XR17V4358 = {
     738                 :            :         .num_ports      = 12,
     739                 :            :         .setup          = pci_xr17v35x_setup,
     740                 :            :         .exit           = pci_xr17v35x_exit,
     741                 :            : };
     742                 :            : 
     743                 :            : static const struct exar8250_board pbn_exar_XR17V8358 = {
     744                 :            :         .num_ports      = 16,
     745                 :            :         .setup          = pci_xr17v35x_setup,
     746                 :            :         .exit           = pci_xr17v35x_exit,
     747                 :            : };
     748                 :            : 
     749                 :            : #define CONNECT_DEVICE(devid, sdevid, bd) {                             \
     750                 :            :         PCI_DEVICE_SUB(                                                 \
     751                 :            :                 PCI_VENDOR_ID_EXAR,                                     \
     752                 :            :                 PCI_DEVICE_ID_EXAR_##devid,                             \
     753                 :            :                 PCI_SUBVENDOR_ID_CONNECT_TECH,                          \
     754                 :            :                 PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_##sdevid), 0, 0,      \
     755                 :            :                 (kernel_ulong_t)&bd                                 \
     756                 :            :         }
     757                 :            : 
     758                 :            : #define EXAR_DEVICE(vend, devid, bd) {                                  \
     759                 :            :         PCI_VDEVICE(vend, PCI_DEVICE_ID_##devid), (kernel_ulong_t)&bd       \
     760                 :            :         }
     761                 :            : 
     762                 :            : #define IBM_DEVICE(devid, sdevid, bd) {                 \
     763                 :            :         PCI_DEVICE_SUB(                                 \
     764                 :            :                 PCI_VENDOR_ID_EXAR,                     \
     765                 :            :                 PCI_DEVICE_ID_EXAR_##devid,             \
     766                 :            :                 PCI_VENDOR_ID_IBM,                      \
     767                 :            :                 PCI_SUBDEVICE_ID_IBM_##sdevid), 0, 0,   \
     768                 :            :                 (kernel_ulong_t)&bd                 \
     769                 :            :         }
     770                 :            : 
     771                 :            : static const struct pci_device_id exar_pci_tbl[] = {
     772                 :            :         EXAR_DEVICE(ACCESSIO, ACCES_COM_2S, acces_com_2x),
     773                 :            :         EXAR_DEVICE(ACCESSIO, ACCES_COM_4S, acces_com_4x),
     774                 :            :         EXAR_DEVICE(ACCESSIO, ACCES_COM_8S, acces_com_8x),
     775                 :            :         EXAR_DEVICE(ACCESSIO, ACCES_COM232_8, acces_com_8x),
     776                 :            :         EXAR_DEVICE(ACCESSIO, ACCES_COM_2SM, acces_com_2x),
     777                 :            :         EXAR_DEVICE(ACCESSIO, ACCES_COM_4SM, acces_com_4x),
     778                 :            :         EXAR_DEVICE(ACCESSIO, ACCES_COM_8SM, acces_com_8x),
     779                 :            : 
     780                 :            : 
     781                 :            :         CONNECT_DEVICE(XR17C152, UART_2_232, pbn_connect),
     782                 :            :         CONNECT_DEVICE(XR17C154, UART_4_232, pbn_connect),
     783                 :            :         CONNECT_DEVICE(XR17C158, UART_8_232, pbn_connect),
     784                 :            :         CONNECT_DEVICE(XR17C152, UART_1_1, pbn_connect),
     785                 :            :         CONNECT_DEVICE(XR17C154, UART_2_2, pbn_connect),
     786                 :            :         CONNECT_DEVICE(XR17C158, UART_4_4, pbn_connect),
     787                 :            :         CONNECT_DEVICE(XR17C152, UART_2, pbn_connect),
     788                 :            :         CONNECT_DEVICE(XR17C154, UART_4, pbn_connect),
     789                 :            :         CONNECT_DEVICE(XR17C158, UART_8, pbn_connect),
     790                 :            :         CONNECT_DEVICE(XR17C152, UART_2_485, pbn_connect),
     791                 :            :         CONNECT_DEVICE(XR17C154, UART_4_485, pbn_connect),
     792                 :            :         CONNECT_DEVICE(XR17C158, UART_8_485, pbn_connect),
     793                 :            : 
     794                 :            :         IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn),
     795                 :            : 
     796                 :            :         /* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */
     797                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17C152, pbn_exar_XR17C15x),
     798                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17C154, pbn_exar_XR17C15x),
     799                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17C158, pbn_exar_XR17C15x),
     800                 :            : 
     801                 :            :         /* Exar Corp. XR17V[48]35[248] Dual/Quad/Octal/Hexa PCIe UARTs */
     802                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17V352, pbn_exar_XR17V35x),
     803                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17V354, pbn_exar_XR17V35x),
     804                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17V358, pbn_exar_XR17V35x),
     805                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17V4358, pbn_exar_XR17V4358),
     806                 :            :         EXAR_DEVICE(EXAR, EXAR_XR17V8358, pbn_exar_XR17V8358),
     807                 :            :         EXAR_DEVICE(COMMTECH, COMMTECH_4222PCIE, pbn_exar_XR17V35x),
     808                 :            :         EXAR_DEVICE(COMMTECH, COMMTECH_4224PCIE, pbn_exar_XR17V35x),
     809                 :            :         EXAR_DEVICE(COMMTECH, COMMTECH_4228PCIE, pbn_exar_XR17V35x),
     810                 :            : 
     811                 :            :         EXAR_DEVICE(COMMTECH, COMMTECH_4222PCI335, pbn_fastcom335_2),
     812                 :            :         EXAR_DEVICE(COMMTECH, COMMTECH_4224PCI335, pbn_fastcom335_4),
     813                 :            :         EXAR_DEVICE(COMMTECH, COMMTECH_2324PCI335, pbn_fastcom335_4),
     814                 :            :         EXAR_DEVICE(COMMTECH, COMMTECH_2328PCI335, pbn_fastcom335_8),
     815                 :            :         { 0, }
     816                 :            : };
     817                 :            : MODULE_DEVICE_TABLE(pci, exar_pci_tbl);
     818                 :            : 
     819                 :            : static struct pci_driver exar_pci_driver = {
     820                 :            :         .name           = "exar_serial",
     821                 :            :         .probe          = exar_pci_probe,
     822                 :            :         .remove         = exar_pci_remove,
     823                 :            :         .driver         = {
     824                 :            :                 .pm     = &exar_pci_pm,
     825                 :            :         },
     826                 :            :         .id_table       = exar_pci_tbl,
     827                 :            : };
     828                 :          3 : module_pci_driver(exar_pci_driver);
     829                 :            : 
     830                 :            : MODULE_LICENSE("GPL");
     831                 :            : MODULE_DESCRIPTION("Exar Serial Driver");
     832                 :            : MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");

Generated by: LCOV version 1.14