LCOV - code coverage report
Current view: top level - tty/serial/8250 - 8250_mid.c (source / functions) Coverage Total Hit
Test: TTY Combined Coverage Lines: 0.0 % 203 0
Test Date: 2025-08-26 15:45:50 Functions: 0.0 % 15 0

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0
       2              : /*
       3              :  * 8250_mid.c - Driver for UART on Intel Penwell and various other Intel SOCs
       4              :  *
       5              :  * Copyright (C) 2015 Intel Corporation
       6              :  * Author: Heikki Krogerus <[email protected]>
       7              :  */
       8              : 
       9              : #include <linux/bitops.h>
      10              : #include <linux/module.h>
      11              : #include <linux/pci.h>
      12              : #include <linux/rational.h>
      13              : 
      14              : #include <linux/dma/hsu.h>
      15              : 
      16              : #include "8250.h"
      17              : 
      18              : #define PCI_DEVICE_ID_INTEL_PNW_UART1   0x081b
      19              : #define PCI_DEVICE_ID_INTEL_PNW_UART2   0x081c
      20              : #define PCI_DEVICE_ID_INTEL_PNW_UART3   0x081d
      21              : #define PCI_DEVICE_ID_INTEL_TNG_UART    0x1191
      22              : #define PCI_DEVICE_ID_INTEL_CDF_UART    0x18d8
      23              : #define PCI_DEVICE_ID_INTEL_DNV_UART    0x19d8
      24              : 
      25              : /* Intel MID Specific registers */
      26              : #define INTEL_MID_UART_FISR             0x08
      27              : #define INTEL_MID_UART_PS               0x30
      28              : #define INTEL_MID_UART_MUL              0x34
      29              : #define INTEL_MID_UART_DIV              0x38
      30              : 
      31              : struct mid8250;
      32              : 
      33              : struct mid8250_board {
      34              :         unsigned long freq;
      35              :         unsigned int base_baud;
      36              :         unsigned int bar;
      37              :         int (*setup)(struct mid8250 *, struct uart_port *p);
      38              :         void (*exit)(struct mid8250 *);
      39              : };
      40              : 
      41              : struct mid8250 {
      42              :         int line;
      43              :         int dma_index;
      44              :         struct pci_dev *dma_dev;
      45              :         struct uart_8250_dma dma;
      46              :         struct mid8250_board *board;
      47              :         struct hsu_dma_chip dma_chip;
      48              : };
      49              : 
      50              : /*****************************************************************************/
      51              : 
      52            0 : static int pnw_setup(struct mid8250 *mid, struct uart_port *p)
      53              : {
      54            0 :         struct pci_dev *pdev = to_pci_dev(p->dev);
      55              : 
      56            0 :         switch (pdev->device) {
      57              :         case PCI_DEVICE_ID_INTEL_PNW_UART1:
      58            0 :                 mid->dma_index = 0;
      59            0 :                 break;
      60              :         case PCI_DEVICE_ID_INTEL_PNW_UART2:
      61            0 :                 mid->dma_index = 1;
      62            0 :                 break;
      63              :         case PCI_DEVICE_ID_INTEL_PNW_UART3:
      64            0 :                 mid->dma_index = 2;
      65            0 :                 break;
      66              :         default:
      67            0 :                 return -EINVAL;
      68              :         }
      69              : 
      70            0 :         mid->dma_dev = pci_get_slot(pdev->bus,
      71            0 :                                     PCI_DEVFN(PCI_SLOT(pdev->devfn), 3));
      72            0 :         return 0;
      73            0 : }
      74              : 
      75            0 : static void pnw_exit(struct mid8250 *mid)
      76              : {
      77            0 :         pci_dev_put(mid->dma_dev);
      78            0 : }
      79              : 
      80            0 : static int tng_handle_irq(struct uart_port *p)
      81              : {
      82            0 :         struct mid8250 *mid = p->private_data;
      83            0 :         struct uart_8250_port *up = up_to_u8250p(p);
      84            0 :         struct hsu_dma_chip *chip;
      85            0 :         u32 status;
      86            0 :         int ret = 0;
      87            0 :         int err;
      88              : 
      89            0 :         chip = pci_get_drvdata(mid->dma_dev);
      90              : 
      91              :         /* Rx DMA */
      92            0 :         err = hsu_dma_get_status(chip, mid->dma_index * 2 + 1, &status);
      93            0 :         if (err > 0) {
      94            0 :                 serial8250_rx_dma_flush(up);
      95            0 :                 ret |= 1;
      96            0 :         } else if (err == 0)
      97            0 :                 ret |= hsu_dma_do_irq(chip, mid->dma_index * 2 + 1, status);
      98              : 
      99              :         /* Tx DMA */
     100            0 :         err = hsu_dma_get_status(chip, mid->dma_index * 2, &status);
     101            0 :         if (err > 0)
     102            0 :                 ret |= 1;
     103            0 :         else if (err == 0)
     104            0 :                 ret |= hsu_dma_do_irq(chip, mid->dma_index * 2, status);
     105              : 
     106              :         /* UART */
     107            0 :         ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
     108            0 :         return IRQ_RETVAL(ret);
     109            0 : }
     110              : 
     111            0 : static int tng_setup(struct mid8250 *mid, struct uart_port *p)
     112              : {
     113            0 :         struct pci_dev *pdev = to_pci_dev(p->dev);
     114            0 :         int index = PCI_FUNC(pdev->devfn);
     115              : 
     116              :         /*
     117              :          * Device 0000:00:04.0 is not a real HSU port. It provides a global
     118              :          * register set for all HSU ports, although it has the same PCI ID.
     119              :          * Skip it here.
     120              :          */
     121            0 :         if (index-- == 0)
     122            0 :                 return -ENODEV;
     123              : 
     124            0 :         mid->dma_index = index;
     125            0 :         mid->dma_dev = pci_get_slot(pdev->bus, PCI_DEVFN(5, 0));
     126              : 
     127            0 :         p->handle_irq = tng_handle_irq;
     128            0 :         return 0;
     129            0 : }
     130              : 
     131            0 : static void tng_exit(struct mid8250 *mid)
     132              : {
     133            0 :         pci_dev_put(mid->dma_dev);
     134            0 : }
     135              : 
     136            0 : static int dnv_handle_irq(struct uart_port *p)
     137              : {
     138            0 :         struct mid8250 *mid = p->private_data;
     139            0 :         struct uart_8250_port *up = up_to_u8250p(p);
     140            0 :         unsigned int fisr = serial_port_in(p, INTEL_MID_UART_FISR);
     141            0 :         u32 status;
     142            0 :         int ret = 0;
     143            0 :         int err;
     144              : 
     145            0 :         if (fisr & BIT(2)) {
     146            0 :                 err = hsu_dma_get_status(&mid->dma_chip, 1, &status);
     147            0 :                 if (err > 0) {
     148            0 :                         serial8250_rx_dma_flush(up);
     149            0 :                         ret |= 1;
     150            0 :                 } else if (err == 0)
     151            0 :                         ret |= hsu_dma_do_irq(&mid->dma_chip, 1, status);
     152            0 :         }
     153            0 :         if (fisr & BIT(1)) {
     154            0 :                 err = hsu_dma_get_status(&mid->dma_chip, 0, &status);
     155            0 :                 if (err > 0)
     156            0 :                         ret |= 1;
     157            0 :                 else if (err == 0)
     158            0 :                         ret |= hsu_dma_do_irq(&mid->dma_chip, 0, status);
     159            0 :         }
     160            0 :         if (fisr & BIT(0))
     161            0 :                 ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
     162            0 :         return IRQ_RETVAL(ret);
     163            0 : }
     164              : 
     165              : #define DNV_DMA_CHAN_OFFSET 0x80
     166              : 
     167            0 : static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
     168              : {
     169            0 :         struct hsu_dma_chip *chip = &mid->dma_chip;
     170            0 :         struct pci_dev *pdev = to_pci_dev(p->dev);
     171            0 :         int ret;
     172              : 
     173            0 :         pci_set_master(pdev);
     174              : 
     175            0 :         ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
     176            0 :         if (ret < 0)
     177            0 :                 return ret;
     178              : 
     179            0 :         p->irq = pci_irq_vector(pdev, 0);
     180              : 
     181            0 :         chip->dev = &pdev->dev;
     182            0 :         chip->irq = pci_irq_vector(pdev, 0);
     183            0 :         chip->regs = p->membase;
     184            0 :         chip->length = pci_resource_len(pdev, mid->board->bar);
     185            0 :         chip->offset = DNV_DMA_CHAN_OFFSET;
     186              : 
     187              :         /* Falling back to PIO mode if DMA probing fails */
     188            0 :         ret = hsu_dma_probe(chip);
     189            0 :         if (ret)
     190            0 :                 return 0;
     191              : 
     192            0 :         mid->dma_dev = pdev;
     193              : 
     194            0 :         p->handle_irq = dnv_handle_irq;
     195            0 :         return 0;
     196            0 : }
     197              : 
     198            0 : static void dnv_exit(struct mid8250 *mid)
     199              : {
     200            0 :         if (!mid->dma_dev)
     201            0 :                 return;
     202            0 :         hsu_dma_remove(&mid->dma_chip);
     203            0 : }
     204              : 
     205              : /*****************************************************************************/
     206              : 
     207            0 : static void mid8250_set_termios(struct uart_port *p, struct ktermios *termios,
     208              :                                 const struct ktermios *old)
     209              : {
     210            0 :         unsigned int baud = tty_termios_baud_rate(termios);
     211            0 :         struct mid8250 *mid = p->private_data;
     212            0 :         unsigned short ps = 16;
     213            0 :         unsigned long fuart = baud * ps;
     214            0 :         unsigned long w = BIT(24) - 1;
     215            0 :         unsigned long mul, div;
     216              : 
     217              :         /* Gracefully handle the B0 case: fall back to B9600 */
     218            0 :         fuart = fuart ? fuart : 9600 * 16;
     219              : 
     220            0 :         if (mid->board->freq < fuart) {
     221              :                 /* Find prescaler value that satisfies Fuart < Fref */
     222            0 :                 if (mid->board->freq > baud)
     223            0 :                         ps = mid->board->freq / baud;     /* baud rate too high */
     224              :                 else
     225            0 :                         ps = 1;                         /* PLL case */
     226            0 :                 fuart = baud * ps;
     227            0 :         } else {
     228              :                 /* Get Fuart closer to Fref */
     229            0 :                 fuart *= rounddown_pow_of_two(mid->board->freq / fuart);
     230              :         }
     231              : 
     232            0 :         rational_best_approximation(fuart, mid->board->freq, w, w, &mul, &div);
     233            0 :         p->uartclk = fuart * 16 / ps;                /* core uses ps = 16 always */
     234              : 
     235            0 :         writel(ps, p->membase + INTEL_MID_UART_PS);          /* set PS */
     236            0 :         writel(mul, p->membase + INTEL_MID_UART_MUL);                /* set MUL */
     237            0 :         writel(div, p->membase + INTEL_MID_UART_DIV);
     238              : 
     239            0 :         serial8250_do_set_termios(p, termios, old);
     240            0 : }
     241              : 
     242            0 : static bool mid8250_dma_filter(struct dma_chan *chan, void *param)
     243              : {
     244            0 :         struct hsu_dma_slave *s = param;
     245              : 
     246            0 :         if (s->dma_dev != chan->device->dev || s->chan_id != chan->chan_id)
     247            0 :                 return false;
     248              : 
     249            0 :         chan->private = s;
     250            0 :         return true;
     251            0 : }
     252              : 
     253            0 : static int mid8250_dma_setup(struct mid8250 *mid, struct uart_8250_port *port)
     254              : {
     255            0 :         struct uart_8250_dma *dma = &mid->dma;
     256            0 :         struct device *dev = port->port.dev;
     257            0 :         struct hsu_dma_slave *rx_param;
     258            0 :         struct hsu_dma_slave *tx_param;
     259              : 
     260            0 :         if (!mid->dma_dev)
     261            0 :                 return 0;
     262              : 
     263            0 :         rx_param = devm_kzalloc(dev, sizeof(*rx_param), GFP_KERNEL);
     264            0 :         if (!rx_param)
     265            0 :                 return -ENOMEM;
     266              : 
     267            0 :         tx_param = devm_kzalloc(dev, sizeof(*tx_param), GFP_KERNEL);
     268            0 :         if (!tx_param)
     269            0 :                 return -ENOMEM;
     270              : 
     271            0 :         rx_param->chan_id = mid->dma_index * 2 + 1;
     272            0 :         tx_param->chan_id = mid->dma_index * 2;
     273              : 
     274            0 :         dma->rxconf.src_maxburst = 64;
     275            0 :         dma->txconf.dst_maxburst = 64;
     276              : 
     277            0 :         rx_param->dma_dev = &mid->dma_dev->dev;
     278            0 :         tx_param->dma_dev = &mid->dma_dev->dev;
     279              : 
     280            0 :         dma->fn = mid8250_dma_filter;
     281            0 :         dma->rx_param = rx_param;
     282            0 :         dma->tx_param = tx_param;
     283              : 
     284            0 :         port->dma = dma;
     285            0 :         return 0;
     286            0 : }
     287              : 
     288            0 : static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
     289              : {
     290            0 :         struct uart_8250_port uart;
     291            0 :         struct mid8250 *mid;
     292            0 :         int ret;
     293              : 
     294            0 :         ret = pcim_enable_device(pdev);
     295            0 :         if (ret)
     296            0 :                 return ret;
     297              : 
     298            0 :         mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL);
     299            0 :         if (!mid)
     300            0 :                 return -ENOMEM;
     301              : 
     302            0 :         mid->board = (struct mid8250_board *)id->driver_data;
     303              : 
     304            0 :         memset(&uart, 0, sizeof(struct uart_8250_port));
     305              : 
     306            0 :         uart.port.dev = &pdev->dev;
     307            0 :         uart.port.irq = pdev->irq;
     308            0 :         uart.port.private_data = mid;
     309            0 :         uart.port.type = PORT_16750;
     310            0 :         uart.port.iotype = UPIO_MEM;
     311            0 :         uart.port.uartclk = mid->board->base_baud * 16;
     312            0 :         uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
     313            0 :         uart.port.set_termios = mid8250_set_termios;
     314              : 
     315            0 :         uart.port.mapbase = pci_resource_start(pdev, mid->board->bar);
     316            0 :         uart.port.membase = pcim_iomap(pdev, mid->board->bar, 0);
     317            0 :         if (!uart.port.membase)
     318            0 :                 return -ENOMEM;
     319              : 
     320            0 :         ret = mid->board->setup(mid, &uart.port);
     321            0 :         if (ret)
     322            0 :                 return ret;
     323              : 
     324            0 :         ret = mid8250_dma_setup(mid, &uart);
     325            0 :         if (ret)
     326            0 :                 goto err;
     327              : 
     328            0 :         ret = serial8250_register_8250_port(&uart);
     329            0 :         if (ret < 0)
     330            0 :                 goto err;
     331              : 
     332            0 :         mid->line = ret;
     333              : 
     334            0 :         pci_set_drvdata(pdev, mid);
     335            0 :         return 0;
     336              : 
     337              : err:
     338            0 :         mid->board->exit(mid);
     339            0 :         return ret;
     340            0 : }
     341              : 
     342            0 : static void mid8250_remove(struct pci_dev *pdev)
     343              : {
     344            0 :         struct mid8250 *mid = pci_get_drvdata(pdev);
     345              : 
     346            0 :         serial8250_unregister_port(mid->line);
     347              : 
     348            0 :         mid->board->exit(mid);
     349            0 : }
     350              : 
     351              : static const struct mid8250_board pnw_board = {
     352              :         .freq = 50000000,
     353              :         .base_baud = 115200,
     354              :         .bar = 0,
     355              :         .setup = pnw_setup,
     356              :         .exit = pnw_exit,
     357              : };
     358              : 
     359              : static const struct mid8250_board tng_board = {
     360              :         .freq = 38400000,
     361              :         .base_baud = 1843200,
     362              :         .bar = 0,
     363              :         .setup = tng_setup,
     364              :         .exit = tng_exit,
     365              : };
     366              : 
     367              : static const struct mid8250_board dnv_board = {
     368              :         .freq = 133333333,
     369              :         .base_baud = 115200,
     370              :         .bar = 1,
     371              :         .setup = dnv_setup,
     372              :         .exit = dnv_exit,
     373              : };
     374              : 
     375              : static const struct pci_device_id pci_ids[] = {
     376              :         { PCI_DEVICE_DATA(INTEL, PNW_UART1, &pnw_board) },
     377              :         { PCI_DEVICE_DATA(INTEL, PNW_UART2, &pnw_board) },
     378              :         { PCI_DEVICE_DATA(INTEL, PNW_UART3, &pnw_board) },
     379              :         { PCI_DEVICE_DATA(INTEL, TNG_UART, &tng_board) },
     380              :         { PCI_DEVICE_DATA(INTEL, CDF_UART, &dnv_board) },
     381              :         { PCI_DEVICE_DATA(INTEL, DNV_UART, &dnv_board) },
     382              :         { }
     383              : };
     384              : MODULE_DEVICE_TABLE(pci, pci_ids);
     385              : 
     386              : static struct pci_driver mid8250_pci_driver = {
     387              :         .name           = "8250_mid",
     388              :         .id_table       = pci_ids,
     389              :         .probe          = mid8250_probe,
     390              :         .remove         = mid8250_remove,
     391              : };
     392              : 
     393            0 : module_pci_driver(mid8250_pci_driver);
     394              : 
     395              : MODULE_AUTHOR("Intel Corporation");
     396              : MODULE_LICENSE("GPL v2");
     397              : MODULE_DESCRIPTION("Intel MID UART driver");
        

Generated by: LCOV version 2.0-1