Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bf4e42f authored by Jay Dolan's avatar Jay Dolan Committed by Greg Kroah-Hartman
Browse files

serial: 8250: Add support for higher baud rates to Pericom chips



The Pericom chips can achieve additional baud rates by programming the
sample clock register. The baud rates can be described as
921600 * 16 / (16 - scr) for scr values 5 to 15. The divisor is set to 1
for these baud rates.

Adds new quirk for Pericom chips other than the four port chips to use
the

Signed-off-by: default avatarJay Dolan <jay.dolan@accesio.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 4e828c3e
Loading
Loading
Loading
Loading
+79 −18
Original line number Diff line number Diff line
@@ -1326,13 +1326,66 @@ static int pci_default_setup(struct serial_private *priv,

	return setup_port(priv, port, bar, offset, board->reg_shift);
}
void
pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
			       unsigned int quot, unsigned int quot_frac)
{
	int scr;
	int lcr;
	int actual_baud;
	int tolerance;

	for (scr = 5 ; scr <= 15 ; scr++) {
		actual_baud = 921600 * 16 / scr;
		tolerance = actual_baud / 50;

		if ((baud < actual_baud + tolerance) &&
			(baud > actual_baud - tolerance)) {

			lcr = serial_port_in(port, UART_LCR);
			serial_port_out(port, UART_LCR, lcr | 0x80);

			serial_port_out(port, UART_DLL, 1);
			serial_port_out(port, UART_DLM, 0);
			serial_port_out(port, 2, 16 - scr);
			serial_port_out(port, UART_LCR, lcr);
			return;
		} else if (baud > actual_baud) {
			break;
		}
	}
	serial8250_do_set_divisor(port, baud, quot, quot_frac);
}
static int pci_pericom_setup(struct serial_private *priv,
		  const struct pciserial_board *board,
		  struct uart_8250_port *port, int idx)
{
	unsigned int bar, offset = board->first_offset, maxnr;

	bar = FL_GET_BASE(board->flags);
	if (board->flags & FL_BASE_BARS)
		bar += idx;
	else
		offset += idx * board->uart_offset;


	maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>
		(board->reg_shift + 3);

	if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
		return 1;

	port->port.set_divisor = pericom_do_set_divisor;

	return setup_port(priv, port, bar, offset, board->reg_shift);
}

static int pci_pericom_setup_four_at_eight(struct serial_private *priv,
		  const struct pciserial_board *board,
		  struct uart_8250_port *port, int idx)
{
	unsigned int bar, offset = board->first_offset, maxnr;

	bar = FL_GET_BASE(board->flags);
	if (board->flags & FL_BASE_BARS)
		bar += idx;
@@ -1348,6 +1401,8 @@ static int pci_pericom_setup(struct serial_private *priv,
	if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)
		return 1;

	port->port.set_divisor = pericom_do_set_divisor;

	return setup_port(priv, port, bar, offset, board->reg_shift);
}

@@ -1995,7 +2050,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
		.device		= PCI_DEVICE_ID_PERICOM_PI7C9X7954,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.setup		= pci_pericom_setup,
		.setup		= pci_pericom_setup_four_at_eight,
	},
	/*
	 * PLX
@@ -2032,107 +2087,113 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
		.setup      = pci_pericom_setup_four_at_eight,
	},
	/*
	{
		.vendor     = PCI_VENDOR_ID_ACCESIO,
		.device     = PCI_ANY_ID,
		.subvendor  = PCI_ANY_ID,
		.subdevice  = PCI_ANY_ID,
		.setup      = pci_pericom_setup,
	},	/*
	 * SBS Technologies, Inc., PMC-OCTALPRO 232
	 */
	{