162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Probe module for 8250/16550-type MCHP PCI serial ports. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Based on drivers/tty/serial/8250/8250_pci.c, 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2022 Microchip Technology Inc., All Rights Reserved. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/bitfield.h> 1162306a36Sopenharmony_ci#include <linux/bitops.h> 1262306a36Sopenharmony_ci#include <linux/io.h> 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/module.h> 1562306a36Sopenharmony_ci#include <linux/pci.h> 1662306a36Sopenharmony_ci#include <linux/serial_core.h> 1762306a36Sopenharmony_ci#include <linux/slab.h> 1862306a36Sopenharmony_ci#include <linux/string.h> 1962306a36Sopenharmony_ci#include <linux/units.h> 2062306a36Sopenharmony_ci#include <linux/tty.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include <asm/byteorder.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "8250.h" 2562306a36Sopenharmony_ci#include "8250_pcilib.h" 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define PCI_DEVICE_ID_EFAR_PCI12000 0xa002 2862306a36Sopenharmony_ci#define PCI_DEVICE_ID_EFAR_PCI11010 0xa012 2962306a36Sopenharmony_ci#define PCI_DEVICE_ID_EFAR_PCI11101 0xa022 3062306a36Sopenharmony_ci#define PCI_DEVICE_ID_EFAR_PCI11400 0xa032 3162306a36Sopenharmony_ci#define PCI_DEVICE_ID_EFAR_PCI11414 0xa042 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_4p 0x0001 3462306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p012 0x0002 3562306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p013 0x0003 3662306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p023 0x0004 3762306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p123 0x0005 3862306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p01 0x0006 3962306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p02 0x0007 4062306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p03 0x0008 4162306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p12 0x0009 4262306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p13 0x000a 4362306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p23 0x000b 4462306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p0 0x000c 4562306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p1 0x000d 4662306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p2 0x000e 4762306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3 0x000f 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI12000 PCI_DEVICE_ID_EFAR_PCI12000 5062306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI11010 PCI_DEVICE_ID_EFAR_PCI11010 5162306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI11101 PCI_DEVICE_ID_EFAR_PCI11101 5262306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI11400 PCI_DEVICE_ID_EFAR_PCI11400 5362306a36Sopenharmony_ci#define PCI_SUBDEVICE_ID_EFAR_PCI11414 PCI_DEVICE_ID_EFAR_PCI11414 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define UART_ACTV_REG 0x11 5662306a36Sopenharmony_ci#define UART_BLOCK_SET_ACTIVE BIT(0) 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define UART_PCI_CTRL_REG 0x80 5962306a36Sopenharmony_ci#define UART_PCI_CTRL_SET_MULTIPLE_MSI BIT(4) 6062306a36Sopenharmony_ci#define UART_PCI_CTRL_D3_CLK_ENABLE BIT(0) 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define ADCL_CFG_REG 0x40 6362306a36Sopenharmony_ci#define ADCL_CFG_POL_SEL BIT(2) 6462306a36Sopenharmony_ci#define ADCL_CFG_PIN_SEL BIT(1) 6562306a36Sopenharmony_ci#define ADCL_CFG_EN BIT(0) 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define UART_BIT_SAMPLE_CNT 16 6862306a36Sopenharmony_ci#define BAUD_CLOCK_DIV_INT_MSK GENMASK(31, 8) 6962306a36Sopenharmony_ci#define ADCL_CFG_RTS_DELAY_MASK GENMASK(11, 8) 7062306a36Sopenharmony_ci#define UART_CLOCK_DEFAULT (62500 * HZ_PER_KHZ) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#define UART_WAKE_REG 0x8C 7362306a36Sopenharmony_ci#define UART_WAKE_MASK_REG 0x90 7462306a36Sopenharmony_ci#define UART_WAKE_N_PIN BIT(2) 7562306a36Sopenharmony_ci#define UART_WAKE_NCTS BIT(1) 7662306a36Sopenharmony_ci#define UART_WAKE_INT BIT(0) 7762306a36Sopenharmony_ci#define UART_WAKE_SRCS \ 7862306a36Sopenharmony_ci (UART_WAKE_N_PIN | UART_WAKE_NCTS | UART_WAKE_INT) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define UART_BAUD_CLK_DIVISOR_REG 0x54 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define UART_RESET_REG 0x94 8362306a36Sopenharmony_ci#define UART_RESET_D3_RESET_DISABLE BIT(16) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define MAX_PORTS 4 8662306a36Sopenharmony_ci#define PORT_OFFSET 0x100 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic const int logical_to_physical_port_idx[][MAX_PORTS] = { 8962306a36Sopenharmony_ci {0, 1, 2, 3}, /* PCI12000, PCI11010, PCI11101, PCI11400, PCI11414 */ 9062306a36Sopenharmony_ci {0, 1, 2, 3}, /* PCI4p */ 9162306a36Sopenharmony_ci {0, 1, 2, -1}, /* PCI3p012 */ 9262306a36Sopenharmony_ci {0, 1, 3, -1}, /* PCI3p013 */ 9362306a36Sopenharmony_ci {0, 2, 3, -1}, /* PCI3p023 */ 9462306a36Sopenharmony_ci {1, 2, 3, -1}, /* PCI3p123 */ 9562306a36Sopenharmony_ci {0, 1, -1, -1}, /* PCI2p01 */ 9662306a36Sopenharmony_ci {0, 2, -1, -1}, /* PCI2p02 */ 9762306a36Sopenharmony_ci {0, 3, -1, -1}, /* PCI2p03 */ 9862306a36Sopenharmony_ci {1, 2, -1, -1}, /* PCI2p12 */ 9962306a36Sopenharmony_ci {1, 3, -1, -1}, /* PCI2p13 */ 10062306a36Sopenharmony_ci {2, 3, -1, -1}, /* PCI2p23 */ 10162306a36Sopenharmony_ci {0, -1, -1, -1}, /* PCI1p0 */ 10262306a36Sopenharmony_ci {1, -1, -1, -1}, /* PCI1p1 */ 10362306a36Sopenharmony_ci {2, -1, -1, -1}, /* PCI1p2 */ 10462306a36Sopenharmony_ci {3, -1, -1, -1}, /* PCI1p3 */ 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistruct pci1xxxx_8250 { 10862306a36Sopenharmony_ci unsigned int nr; 10962306a36Sopenharmony_ci void __iomem *membase; 11062306a36Sopenharmony_ci int line[]; 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_cistatic int pci1xxxx_get_num_ports(struct pci_dev *dev) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci switch (dev->subsystem_device) { 11662306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p0: 11762306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p1: 11862306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p2: 11962306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3: 12062306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI12000: 12162306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI11010: 12262306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI11101: 12362306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI11400: 12462306a36Sopenharmony_ci default: 12562306a36Sopenharmony_ci return 1; 12662306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p01: 12762306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p02: 12862306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p03: 12962306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p12: 13062306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p13: 13162306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_2p23: 13262306a36Sopenharmony_ci return 2; 13362306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p012: 13462306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p123: 13562306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p013: 13662306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_3p023: 13762306a36Sopenharmony_ci return 3; 13862306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_4p: 13962306a36Sopenharmony_ci case PCI_SUBDEVICE_ID_EFAR_PCI11414: 14062306a36Sopenharmony_ci return 4; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci} 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic unsigned int pci1xxxx_get_divisor(struct uart_port *port, 14562306a36Sopenharmony_ci unsigned int baud, unsigned int *frac) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci unsigned int quot; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* 15062306a36Sopenharmony_ci * Calculate baud rate sampling period in nanoseconds. 15162306a36Sopenharmony_ci * Fractional part x denotes x/255 parts of a nanosecond. 15262306a36Sopenharmony_ci */ 15362306a36Sopenharmony_ci quot = NSEC_PER_SEC / (baud * UART_BIT_SAMPLE_CNT); 15462306a36Sopenharmony_ci *frac = (NSEC_PER_SEC - quot * baud * UART_BIT_SAMPLE_CNT) * 15562306a36Sopenharmony_ci 255 / UART_BIT_SAMPLE_CNT / baud; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci return quot; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic void pci1xxxx_set_divisor(struct uart_port *port, unsigned int baud, 16162306a36Sopenharmony_ci unsigned int quot, unsigned int frac) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci writel(FIELD_PREP(BAUD_CLOCK_DIV_INT_MSK, quot) | frac, 16462306a36Sopenharmony_ci port->membase + UART_BAUD_CLK_DIVISOR_REG); 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic int pci1xxxx_rs485_config(struct uart_port *port, 16862306a36Sopenharmony_ci struct ktermios *termios, 16962306a36Sopenharmony_ci struct serial_rs485 *rs485) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci u32 delay_in_baud_periods; 17262306a36Sopenharmony_ci u32 baud_period_in_ns; 17362306a36Sopenharmony_ci u32 mode_cfg = 0; 17462306a36Sopenharmony_ci u32 clock_div; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci /* 17762306a36Sopenharmony_ci * pci1xxxx's uart hardware supports only RTS delay after 17862306a36Sopenharmony_ci * Tx and in units of bit times to a maximum of 15 17962306a36Sopenharmony_ci */ 18062306a36Sopenharmony_ci if (rs485->flags & SER_RS485_ENABLED) { 18162306a36Sopenharmony_ci mode_cfg = ADCL_CFG_EN | ADCL_CFG_PIN_SEL; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (!(rs485->flags & SER_RS485_RTS_ON_SEND)) 18462306a36Sopenharmony_ci mode_cfg |= ADCL_CFG_POL_SEL; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (rs485->delay_rts_after_send) { 18762306a36Sopenharmony_ci clock_div = readl(port->membase + UART_BAUD_CLK_DIVISOR_REG); 18862306a36Sopenharmony_ci baud_period_in_ns = 18962306a36Sopenharmony_ci FIELD_GET(BAUD_CLOCK_DIV_INT_MSK, clock_div) * 19062306a36Sopenharmony_ci UART_BIT_SAMPLE_CNT; 19162306a36Sopenharmony_ci delay_in_baud_periods = 19262306a36Sopenharmony_ci rs485->delay_rts_after_send * NSEC_PER_MSEC / 19362306a36Sopenharmony_ci baud_period_in_ns; 19462306a36Sopenharmony_ci delay_in_baud_periods = 19562306a36Sopenharmony_ci min_t(u32, delay_in_baud_periods, 19662306a36Sopenharmony_ci FIELD_MAX(ADCL_CFG_RTS_DELAY_MASK)); 19762306a36Sopenharmony_ci mode_cfg |= FIELD_PREP(ADCL_CFG_RTS_DELAY_MASK, 19862306a36Sopenharmony_ci delay_in_baud_periods); 19962306a36Sopenharmony_ci rs485->delay_rts_after_send = 20062306a36Sopenharmony_ci baud_period_in_ns * delay_in_baud_periods / 20162306a36Sopenharmony_ci NSEC_PER_MSEC; 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci writel(mode_cfg, port->membase + ADCL_CFG_REG); 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic const struct serial_rs485 pci1xxxx_rs485_supported = { 20962306a36Sopenharmony_ci .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | 21062306a36Sopenharmony_ci SER_RS485_RTS_AFTER_SEND, 21162306a36Sopenharmony_ci .delay_rts_after_send = 1, 21262306a36Sopenharmony_ci /* Delay RTS before send is not supported */ 21362306a36Sopenharmony_ci}; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic bool pci1xxxx_port_suspend(int line) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci struct uart_8250_port *up = serial8250_get_port(line); 21862306a36Sopenharmony_ci struct uart_port *port = &up->port; 21962306a36Sopenharmony_ci struct tty_port *tport = &port->state->port; 22062306a36Sopenharmony_ci unsigned long flags; 22162306a36Sopenharmony_ci bool ret = false; 22262306a36Sopenharmony_ci u8 wakeup_mask; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci mutex_lock(&tport->mutex); 22562306a36Sopenharmony_ci if (port->suspended == 0 && port->dev) { 22662306a36Sopenharmony_ci wakeup_mask = readb(up->port.membase + UART_WAKE_MASK_REG); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, flags); 22962306a36Sopenharmony_ci port->mctrl &= ~TIOCM_OUT2; 23062306a36Sopenharmony_ci port->ops->set_mctrl(port, port->mctrl); 23162306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, flags); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci ret = (wakeup_mask & UART_WAKE_SRCS) != UART_WAKE_SRCS; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci writeb(UART_WAKE_SRCS, port->membase + UART_WAKE_REG); 23762306a36Sopenharmony_ci mutex_unlock(&tport->mutex); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci return ret; 24062306a36Sopenharmony_ci} 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_cistatic void pci1xxxx_port_resume(int line) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct uart_8250_port *up = serial8250_get_port(line); 24562306a36Sopenharmony_ci struct uart_port *port = &up->port; 24662306a36Sopenharmony_ci struct tty_port *tport = &port->state->port; 24762306a36Sopenharmony_ci unsigned long flags; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci mutex_lock(&tport->mutex); 25062306a36Sopenharmony_ci writeb(UART_BLOCK_SET_ACTIVE, port->membase + UART_ACTV_REG); 25162306a36Sopenharmony_ci writeb(UART_WAKE_SRCS, port->membase + UART_WAKE_REG); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci if (port->suspended == 0) { 25462306a36Sopenharmony_ci spin_lock_irqsave(&port->lock, flags); 25562306a36Sopenharmony_ci port->mctrl |= TIOCM_OUT2; 25662306a36Sopenharmony_ci port->ops->set_mctrl(port, port->mctrl); 25762306a36Sopenharmony_ci spin_unlock_irqrestore(&port->lock, flags); 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci mutex_unlock(&tport->mutex); 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic int pci1xxxx_suspend(struct device *dev) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci struct pci1xxxx_8250 *priv = dev_get_drvdata(dev); 26562306a36Sopenharmony_ci struct pci_dev *pcidev = to_pci_dev(dev); 26662306a36Sopenharmony_ci bool wakeup = false; 26762306a36Sopenharmony_ci unsigned int data; 26862306a36Sopenharmony_ci void __iomem *p; 26962306a36Sopenharmony_ci int i; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci for (i = 0; i < priv->nr; i++) { 27262306a36Sopenharmony_ci if (priv->line[i] >= 0) { 27362306a36Sopenharmony_ci serial8250_suspend_port(priv->line[i]); 27462306a36Sopenharmony_ci wakeup |= pci1xxxx_port_suspend(priv->line[i]); 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci p = pci_ioremap_bar(pcidev, 0); 27962306a36Sopenharmony_ci if (!p) { 28062306a36Sopenharmony_ci dev_err(dev, "remapping of bar 0 memory failed"); 28162306a36Sopenharmony_ci return -ENOMEM; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci data = readl(p + UART_RESET_REG); 28562306a36Sopenharmony_ci writel(data | UART_RESET_D3_RESET_DISABLE, p + UART_RESET_REG); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (wakeup) 28862306a36Sopenharmony_ci writeb(UART_PCI_CTRL_D3_CLK_ENABLE, p + UART_PCI_CTRL_REG); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci iounmap(p); 29162306a36Sopenharmony_ci device_set_wakeup_enable(dev, true); 29262306a36Sopenharmony_ci pci_wake_from_d3(pcidev, true); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci return 0; 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic int pci1xxxx_resume(struct device *dev) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci struct pci1xxxx_8250 *priv = dev_get_drvdata(dev); 30062306a36Sopenharmony_ci struct pci_dev *pcidev = to_pci_dev(dev); 30162306a36Sopenharmony_ci unsigned int data; 30262306a36Sopenharmony_ci void __iomem *p; 30362306a36Sopenharmony_ci int i; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci p = pci_ioremap_bar(pcidev, 0); 30662306a36Sopenharmony_ci if (!p) { 30762306a36Sopenharmony_ci dev_err(dev, "remapping of bar 0 memory failed"); 30862306a36Sopenharmony_ci return -ENOMEM; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci data = readl(p + UART_RESET_REG); 31262306a36Sopenharmony_ci writel(data & ~UART_RESET_D3_RESET_DISABLE, p + UART_RESET_REG); 31362306a36Sopenharmony_ci iounmap(p); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci for (i = 0; i < priv->nr; i++) { 31662306a36Sopenharmony_ci if (priv->line[i] >= 0) { 31762306a36Sopenharmony_ci pci1xxxx_port_resume(priv->line[i]); 31862306a36Sopenharmony_ci serial8250_resume_port(priv->line[i]); 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci return 0; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic int pci1xxxx_setup(struct pci_dev *pdev, 32662306a36Sopenharmony_ci struct uart_8250_port *port, int port_idx) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci int ret; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci port->port.flags |= UPF_FIXED_TYPE | UPF_SKIP_TEST; 33162306a36Sopenharmony_ci port->port.type = PORT_MCHP16550A; 33262306a36Sopenharmony_ci port->port.set_termios = serial8250_do_set_termios; 33362306a36Sopenharmony_ci port->port.get_divisor = pci1xxxx_get_divisor; 33462306a36Sopenharmony_ci port->port.set_divisor = pci1xxxx_set_divisor; 33562306a36Sopenharmony_ci port->port.rs485_config = pci1xxxx_rs485_config; 33662306a36Sopenharmony_ci port->port.rs485_supported = pci1xxxx_rs485_supported; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci ret = serial8250_pci_setup_port(pdev, port, 0, PORT_OFFSET * port_idx, 0); 33962306a36Sopenharmony_ci if (ret < 0) 34062306a36Sopenharmony_ci return ret; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci writeb(UART_BLOCK_SET_ACTIVE, port->port.membase + UART_ACTV_REG); 34362306a36Sopenharmony_ci writeb(UART_WAKE_SRCS, port->port.membase + UART_WAKE_REG); 34462306a36Sopenharmony_ci writeb(UART_WAKE_N_PIN, port->port.membase + UART_WAKE_MASK_REG); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci return 0; 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistatic unsigned int pci1xxxx_get_max_port(int subsys_dev) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci unsigned int i = MAX_PORTS; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (subsys_dev < ARRAY_SIZE(logical_to_physical_port_idx)) 35462306a36Sopenharmony_ci while (i--) { 35562306a36Sopenharmony_ci if (logical_to_physical_port_idx[subsys_dev][i] != -1) 35662306a36Sopenharmony_ci return logical_to_physical_port_idx[subsys_dev][i] + 1; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if (subsys_dev == PCI_SUBDEVICE_ID_EFAR_PCI11414) 36062306a36Sopenharmony_ci return 4; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci return 1; 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic int pci1xxxx_logical_to_physical_port_translate(int subsys_dev, int port) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci if (subsys_dev < ARRAY_SIZE(logical_to_physical_port_idx)) 36862306a36Sopenharmony_ci return logical_to_physical_port_idx[subsys_dev][port]; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci return logical_to_physical_port_idx[0][port]; 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic int pci1xxxx_serial_probe(struct pci_dev *pdev, 37462306a36Sopenharmony_ci const struct pci_device_id *id) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci struct device *dev = &pdev->dev; 37762306a36Sopenharmony_ci struct pci1xxxx_8250 *priv; 37862306a36Sopenharmony_ci struct uart_8250_port uart; 37962306a36Sopenharmony_ci unsigned int max_vec_reqd; 38062306a36Sopenharmony_ci unsigned int nr_ports, i; 38162306a36Sopenharmony_ci int num_vectors; 38262306a36Sopenharmony_ci int subsys_dev; 38362306a36Sopenharmony_ci int port_idx; 38462306a36Sopenharmony_ci int rc; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci rc = pcim_enable_device(pdev); 38762306a36Sopenharmony_ci if (rc) 38862306a36Sopenharmony_ci return rc; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci nr_ports = pci1xxxx_get_num_ports(pdev); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci priv = devm_kzalloc(dev, struct_size(priv, line, nr_ports), GFP_KERNEL); 39362306a36Sopenharmony_ci if (!priv) 39462306a36Sopenharmony_ci return -ENOMEM; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci priv->membase = pci_ioremap_bar(pdev, 0); 39762306a36Sopenharmony_ci if (!priv->membase) 39862306a36Sopenharmony_ci return -ENOMEM; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci pci_set_master(pdev); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci priv->nr = nr_ports; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci subsys_dev = pdev->subsystem_device; 40562306a36Sopenharmony_ci max_vec_reqd = pci1xxxx_get_max_port(subsys_dev); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci num_vectors = pci_alloc_irq_vectors(pdev, 1, max_vec_reqd, PCI_IRQ_ALL_TYPES); 40862306a36Sopenharmony_ci if (num_vectors < 0) { 40962306a36Sopenharmony_ci pci_iounmap(pdev, priv->membase); 41062306a36Sopenharmony_ci return num_vectors; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci memset(&uart, 0, sizeof(uart)); 41462306a36Sopenharmony_ci uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT; 41562306a36Sopenharmony_ci uart.port.uartclk = UART_CLOCK_DEFAULT; 41662306a36Sopenharmony_ci uart.port.dev = dev; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci if (num_vectors == max_vec_reqd) 41962306a36Sopenharmony_ci writeb(UART_PCI_CTRL_SET_MULTIPLE_MSI, priv->membase + UART_PCI_CTRL_REG); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci for (i = 0; i < nr_ports; i++) { 42262306a36Sopenharmony_ci priv->line[i] = -ENODEV; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci port_idx = pci1xxxx_logical_to_physical_port_translate(subsys_dev, i); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci if (num_vectors == max_vec_reqd) 42762306a36Sopenharmony_ci uart.port.irq = pci_irq_vector(pdev, port_idx); 42862306a36Sopenharmony_ci else 42962306a36Sopenharmony_ci uart.port.irq = pci_irq_vector(pdev, 0); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci rc = pci1xxxx_setup(pdev, &uart, port_idx); 43262306a36Sopenharmony_ci if (rc) { 43362306a36Sopenharmony_ci dev_warn(dev, "Failed to setup port %u\n", i); 43462306a36Sopenharmony_ci continue; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci priv->line[i] = serial8250_register_8250_port(&uart); 43862306a36Sopenharmony_ci if (priv->line[i] < 0) { 43962306a36Sopenharmony_ci dev_warn(dev, 44062306a36Sopenharmony_ci "Couldn't register serial port %lx, irq %d, type %d, error %d\n", 44162306a36Sopenharmony_ci uart.port.iobase, uart.port.irq, uart.port.iotype, 44262306a36Sopenharmony_ci priv->line[i]); 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci } 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci pci_set_drvdata(pdev, priv); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci return 0; 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_cistatic void pci1xxxx_serial_remove(struct pci_dev *dev) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci struct pci1xxxx_8250 *priv = pci_get_drvdata(dev); 45462306a36Sopenharmony_ci unsigned int i; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci for (i = 0; i < priv->nr; i++) { 45762306a36Sopenharmony_ci if (priv->line[i] >= 0) 45862306a36Sopenharmony_ci serial8250_unregister_port(priv->line[i]); 45962306a36Sopenharmony_ci } 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci pci_free_irq_vectors(dev); 46262306a36Sopenharmony_ci pci_iounmap(dev, priv->membase); 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(pci1xxxx_pm_ops, pci1xxxx_suspend, pci1xxxx_resume); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic const struct pci_device_id pci1xxxx_pci_tbl[] = { 46862306a36Sopenharmony_ci { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_PCI11010) }, 46962306a36Sopenharmony_ci { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_PCI11101) }, 47062306a36Sopenharmony_ci { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_PCI11400) }, 47162306a36Sopenharmony_ci { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_PCI11414) }, 47262306a36Sopenharmony_ci { PCI_VDEVICE(EFAR, PCI_DEVICE_ID_EFAR_PCI12000) }, 47362306a36Sopenharmony_ci {} 47462306a36Sopenharmony_ci}; 47562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, pci1xxxx_pci_tbl); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic struct pci_driver pci1xxxx_pci_driver = { 47862306a36Sopenharmony_ci .name = "pci1xxxx serial", 47962306a36Sopenharmony_ci .probe = pci1xxxx_serial_probe, 48062306a36Sopenharmony_ci .remove = pci1xxxx_serial_remove, 48162306a36Sopenharmony_ci .driver = { 48262306a36Sopenharmony_ci .pm = pm_sleep_ptr(&pci1xxxx_pm_ops), 48362306a36Sopenharmony_ci }, 48462306a36Sopenharmony_ci .id_table = pci1xxxx_pci_tbl, 48562306a36Sopenharmony_ci}; 48662306a36Sopenharmony_cimodule_pci_driver(pci1xxxx_pci_driver); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cistatic_assert((ARRAY_SIZE(logical_to_physical_port_idx) == PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3 + 1)); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ciMODULE_IMPORT_NS(SERIAL_8250_PCI); 49162306a36Sopenharmony_ciMODULE_DESCRIPTION("Microchip Technology Inc. PCIe to UART module"); 49262306a36Sopenharmony_ciMODULE_AUTHOR("Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>"); 49362306a36Sopenharmony_ciMODULE_AUTHOR("Tharun Kumar P <tharunkumar.pasumarthi@microchip.com>"); 49462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 495