mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
nvidia: serial: CH384 driver support added
CH384 is a PCI-Express bus converter chip, which converts PCIE bus to Quad serial ports and printer port, including four asynchronous serial ports compatible with 16C550 or 16C750 This VCP driver supports pci to uart chips ch382/ch384, Crystal frequency support 22.1184M Bug 3857918 Change-Id: Iae13dbbb0959178d69a93277823d8305973d66be Signed-off-by: Ankit patel <anpatel@nvidia.com> (cherry picked from commit c0239f39c89fcd11dc9a3228892e920c680ddf49) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2921009 Tested-by: Jonathan Hunter <jonathanh@nvidia.com> Reviewed-by: Jonathan Hunter <jonathanh@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
10474851f5
commit
a922b344f8
@@ -45,6 +45,9 @@ obj-m += nvpps/
|
|||||||
obj-m += nvpmodel/
|
obj-m += nvpmodel/
|
||||||
ifdef CONFIG_PCI
|
ifdef CONFIG_PCI
|
||||||
obj-m += pci/
|
obj-m += pci/
|
||||||
|
ifdef CONFIG_TTY
|
||||||
|
obj-m += tty/
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
obj-m += pinctrl/
|
obj-m += pinctrl/
|
||||||
obj-m += platform/tegra/
|
obj-m += platform/tegra/
|
||||||
@@ -72,4 +75,3 @@ obj-m += media/
|
|||||||
endif
|
endif
|
||||||
obj-m += staging/platform/tegra/gte/
|
obj-m += staging/platform/tegra/gte/
|
||||||
obj-m += staging/platform/tegra/gte_test/
|
obj-m += staging/platform/tegra/gte_test/
|
||||||
|
|
||||||
|
|||||||
1
drivers/tty/Makefile
Normal file
1
drivers/tty/Makefile
Normal file
@@ -0,0 +1 @@
|
|||||||
|
obj-m += serial/
|
||||||
1
drivers/tty/serial/Makefile
Normal file
1
drivers/tty/serial/Makefile
Normal file
@@ -0,0 +1 @@
|
|||||||
|
obj-m += wch_35x/
|
||||||
4
drivers/tty/serial/wch_35x/Makefile
Normal file
4
drivers/tty/serial/wch_35x/Makefile
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
DRIVERNAME := wch
|
||||||
|
|
||||||
|
obj-m += $(DRIVERNAME).o
|
||||||
|
$(DRIVERNAME)-m := wch_devtable.o wch_serial.o wch_main.o wch_pre_main.o
|
||||||
725
drivers/tty/serial/wch_35x/wch_common.h
Normal file
725
drivers/tty/serial/wch_35x/wch_common.h
Normal file
@@ -0,0 +1,725 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WCH_COMMON
|
||||||
|
#define WCH_COMMON
|
||||||
|
|
||||||
|
#ifdef MODVERSIONS
|
||||||
|
#ifndef MODULE
|
||||||
|
#define MODULE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MOD_INC_USE_COUNT
|
||||||
|
#define MOD_DEC_USE_COUNT
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/fcntl.h>
|
||||||
|
#include <linux/major.h>
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/serial_core.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
|
||||||
|
#ifndef PCI_ANY_ID
|
||||||
|
#define PCI_ANY_ID (~0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/serial.h>
|
||||||
|
#include <linux/serial_reg.h>
|
||||||
|
#include <linux/signal.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
#include <linux/tty_flip.h>
|
||||||
|
|
||||||
|
#include <linux/circ_buf.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/tty_driver.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
#include <asm/serial.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
|
#include <linux/console.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/moduleparam.h>
|
||||||
|
#include <linux/sysrq.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
#include <linux/kref.h>
|
||||||
|
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
#include <linux/parport.h>
|
||||||
|
#include <linux/poll.h>
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
#include <linux/sched/signal.h>
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
for wch_main.c
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------*/
|
||||||
|
/*******************************************************
|
||||||
|
WCH driver information
|
||||||
|
*******************************************************/
|
||||||
|
#define WCH_DRIVER_VERSION "1.24"
|
||||||
|
#define WCH_DRIVER_DATE "2023.02"
|
||||||
|
#define WCH_DRIVER_AUTHOR "WCH GROUP"
|
||||||
|
#define WCH_DRIVER_DESC "WCH Multi-I/O Board Driver Module"
|
||||||
|
|
||||||
|
#define WCH_TTY_MAJOR 205
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
WCH driver debug
|
||||||
|
*******************************************************/
|
||||||
|
#define WCH_DBG 0
|
||||||
|
#define WCH_DBG_SERIAL 0
|
||||||
|
#define WCH_DBG_BOARD 1
|
||||||
|
#define WCH_DBG_SERPORT 1
|
||||||
|
|
||||||
|
#if WCH_DBG_SERIAL
|
||||||
|
static void dbg_serial(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
int i, len;
|
||||||
|
va_list arglist;
|
||||||
|
|
||||||
|
va_start(arglist, fmt);
|
||||||
|
vsprintf(&buffer[0], fmt, arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
len = strlen(buffer);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
outb(buffer[i], 0x3F8);
|
||||||
|
mdelay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
* WCH board information
|
||||||
|
*******************************************************/
|
||||||
|
|
||||||
|
// for vid pid subvid subpid
|
||||||
|
#define VENDOR_ID_WCH_PCIE 0x1C00
|
||||||
|
#define SUB_VENDOR_ID_WCH_PCIE 0x1C00
|
||||||
|
#define VENDOR_ID_WCH_PCI 0x4348
|
||||||
|
#define SUB_VENDOR_ID_WCH_PCI 0x4348
|
||||||
|
#define VENDOR_ID_WCH_CH351 0x1C00
|
||||||
|
#define SUB_VENDOR_ID_WCH_CH351 0x1C00
|
||||||
|
#define DEVICE_ID_WCH_CH351_2S 0x2273
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH351_2S 0x2273
|
||||||
|
#define DEVICE_ID_WCH_CH352_1S1P 0x5053
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH352_1S1P 0x5053
|
||||||
|
#define DEVICE_ID_WCH_CH352_2S 0x3253
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH352_2S 0x3253
|
||||||
|
#define DEVICE_ID_WCH_CH353_4S 0x3453
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH353_4S 0x3453
|
||||||
|
#define DEVICE_ID_WCH_CH353_2S1P 0x7053
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH353_2S1P 0x3253
|
||||||
|
#define DEVICE_ID_WCH_CH353_2S1PAR 0x5046
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH353_2S1PAR 0x5046
|
||||||
|
#define DEVICE_ID_WCH_CH355_4S 0x7173
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH355_4S 0x3473
|
||||||
|
#define DEVICE_ID_WCH_CH356_4S1P 0x7073
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH356_4S1P 0x3473
|
||||||
|
#define DEVICE_ID_WCH_CH356_6S 0x3873
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH356_6S 0x3873
|
||||||
|
#define DEVICE_ID_WCH_CH356_8S 0x3853
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH356_8S 0x3853
|
||||||
|
#define DEVICE_ID_WCH_CH357_4S 0x5334
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH357_4S 0x5053
|
||||||
|
#define DEVICE_ID_WCH_CH358_4S1P 0x5334
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH358_4S1P 0x5334
|
||||||
|
#define DEVICE_ID_WCH_CH358_8S 0x5338
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH358_8S 0x5338
|
||||||
|
#define DEVICE_ID_WCH_CH359_16S 0x5838
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH359_16S 0x5838
|
||||||
|
#define DEVICE_ID_WCH_CH382_2S 0x3253
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH382_2S 0x3253
|
||||||
|
#define DEVICE_ID_WCH_CH382_2S1P 0x3250
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH382_2S1P 0x3250
|
||||||
|
#define DEVICE_ID_WCH_CH384_4S 0x3470
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_4S 0x3470
|
||||||
|
#define DEVICE_ID_WCH_CH384_4S1P 0x3450
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_4S1P 0x3450
|
||||||
|
#define DEVICE_ID_WCH_CH384_8S 0x3853
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_8S 0x3853
|
||||||
|
#define DEVICE_ID_WCH_CH384_28S 0x4353
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_28S 0x4353
|
||||||
|
#define DEVICE_ID_WCH_CH365_32S 0x5049
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH365_32S 0x5049
|
||||||
|
|
||||||
|
// for chip_flag
|
||||||
|
enum {
|
||||||
|
NONE_BOARD = 0,
|
||||||
|
WCH_BOARD_CH351_2S,
|
||||||
|
WCH_BOARD_CH352_2S,
|
||||||
|
WCH_BOARD_CH352_1S1P,
|
||||||
|
WCH_BOARD_CH353_4S,
|
||||||
|
WCH_BOARD_CH353_2S1P,
|
||||||
|
WCH_BOARD_CH353_2S1PAR,
|
||||||
|
WCH_BOARD_CH355_4S,
|
||||||
|
WCH_BOARD_CH356_4S1P,
|
||||||
|
WCH_BOARD_CH356_6S,
|
||||||
|
WCH_BOARD_CH356_8S,
|
||||||
|
WCH_BOARD_CH357_4S,
|
||||||
|
WCH_BOARD_CH358_4S1P,
|
||||||
|
WCH_BOARD_CH358_8S,
|
||||||
|
WCH_BOARD_CH359_16S,
|
||||||
|
WCH_BOARD_CH382_2S,
|
||||||
|
WCH_BOARD_CH382_2S1P,
|
||||||
|
WCH_BOARD_CH384_4S,
|
||||||
|
WCH_BOARD_CH384_4S1P,
|
||||||
|
WCH_BOARD_CH384_8S,
|
||||||
|
WCH_BOARD_CH384_28S,
|
||||||
|
WCH_BOARD_CH365_32S,
|
||||||
|
};
|
||||||
|
|
||||||
|
// for board_flag
|
||||||
|
#define BOARDFLAG_NONE 0x0000
|
||||||
|
#define BOARDFLAG_REMAP 0x0001
|
||||||
|
#define BOARDFLAG_CH365_04_PORTS 0x0002
|
||||||
|
#define BOARDFLAG_CH365_08_PORTS 0x0004
|
||||||
|
#define BOARDFLAG_CH365_32_PORTS 0x0008
|
||||||
|
#define BOARDFLAG_CH384_8_PORTS 0x0010
|
||||||
|
#define BOARDFLAG_CH384_28_PORTS 0x0020
|
||||||
|
|
||||||
|
// for port_flag
|
||||||
|
#define PORTFLAG_NONE 0x0000
|
||||||
|
#define PORTFLAG_REMAP 0x0001
|
||||||
|
#define PORTFLAG_CH365_04_PORTS 0x0002
|
||||||
|
#define PORTFLAG_CH365_08_PORTS 0x0004
|
||||||
|
#define PORTFLAG_CH365_32_PORTS 0x0008
|
||||||
|
#define PORTFLAG_CH384_8_PORTS 0x0010
|
||||||
|
#define PORTFLAG_CH384_28_PORTS 0x0020
|
||||||
|
|
||||||
|
// board info
|
||||||
|
#define WCH_BOARDS_MAX 0x08
|
||||||
|
#define WCH_PORT_ONBOARD_MAX 0x20
|
||||||
|
#define WCH_SER_TOTAL_MAX 0x100
|
||||||
|
|
||||||
|
extern int wch_ser_port_total_cnt;
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
* uart information
|
||||||
|
*******************************************************/
|
||||||
|
|
||||||
|
// external crystal freq
|
||||||
|
#define CRYSTAL_FREQ 22118400
|
||||||
|
|
||||||
|
// uart fifo info
|
||||||
|
#define CH351_FIFOSIZE_16 16
|
||||||
|
#define CH351_TRIGGER_LEVEL_16FIFO_01 1
|
||||||
|
#define CH351_TRIGGER_LEVEL_16FIFO_04 4
|
||||||
|
#define CH351_TRIGGER_LEVEL_16FIFO_08 8
|
||||||
|
#define CH351_TRIGGER_LEVEL_16FIFO_14 14
|
||||||
|
|
||||||
|
#define CH352_FIFOSIZE_16 16
|
||||||
|
#define CH352_TRIGGER_LEVEL_16FIFO_01 1
|
||||||
|
#define CH352_TRIGGER_LEVEL_16FIFO_04 4
|
||||||
|
#define CH352_TRIGGER_LEVEL_16FIFO_08 8
|
||||||
|
#define CH352_TRIGGER_LEVEL_16FIFO_14 14
|
||||||
|
|
||||||
|
#define CH353_FIFOSIZE_16 16
|
||||||
|
#define CH353_TRIGGER_LEVEL_16FIFO_01 1
|
||||||
|
#define CH353_TRIGGER_LEVEL_16FIFO_04 4
|
||||||
|
#define CH353_TRIGGER_LEVEL_16FIFO_08 8
|
||||||
|
#define CH353_TRIGGER_LEVEL_16FIFO_14 14
|
||||||
|
|
||||||
|
#define CH355_FIFOSIZE_16 16
|
||||||
|
#define CH355_TRIGGER_LEVEL_16FIFO_01 1
|
||||||
|
#define CH355_TRIGGER_LEVEL_16FIFO_04 4
|
||||||
|
#define CH355_TRIGGER_LEVEL_16FIFO_08 8
|
||||||
|
#define CH355_TRIGGER_LEVEL_16FIFO_14 14
|
||||||
|
|
||||||
|
#define CH356_FIFOSIZE_16 16
|
||||||
|
#define CH356_TRIGGER_LEVEL_16FIFO_01 1
|
||||||
|
#define CH356_TRIGGER_LEVEL_16FIFO_04 4
|
||||||
|
#define CH356_TRIGGER_LEVEL_16FIFO_08 8
|
||||||
|
#define CH356_TRIGGER_LEVEL_16FIFO_14 14
|
||||||
|
|
||||||
|
#define CH357_FIFOSIZE_128 128
|
||||||
|
#define CH357_TRIGGER_LEVEL_128FIFO_01 1
|
||||||
|
#define CH357_TRIGGER_LEVEL_128FIFO_32 32
|
||||||
|
#define CH357_TRIGGER_LEVEL_128FIFO_64 64
|
||||||
|
#define CH357_TRIGGER_LEVEL_128FIFO_112 112
|
||||||
|
|
||||||
|
#define CH358_FIFOSIZE_128 128
|
||||||
|
#define CH358_TRIGGER_LEVEL_128FIFO_01 1
|
||||||
|
#define CH358_TRIGGER_LEVEL_128FIFO_32 32
|
||||||
|
#define CH358_TRIGGER_LEVEL_128FIFO_64 64
|
||||||
|
#define CH358_TRIGGER_LEVEL_128FIFO_112 112
|
||||||
|
|
||||||
|
#define CH359_FIFOSIZE_128 128
|
||||||
|
#define CH359_TRIGGER_LEVEL_128FIFO_01 1
|
||||||
|
#define CH359_TRIGGER_LEVEL_128FIFO_32 32
|
||||||
|
#define CH359_TRIGGER_LEVEL_128FIFO_64 64
|
||||||
|
#define CH359_TRIGGER_LEVEL_128FIFO_112 112
|
||||||
|
|
||||||
|
#define CH382_FIFOSIZE_256 256
|
||||||
|
#define CH382_TRIGGER_LEVEL_256FIFO_01 1
|
||||||
|
#define CH382_TRIGGER_LEVEL_256FIFO_32 32
|
||||||
|
#define CH382_TRIGGER_LEVEL_256FIFO_128 128
|
||||||
|
#define CH382_TRIGGER_LEVEL_256FIFO_224 224
|
||||||
|
|
||||||
|
#define CH384_FIFOSIZE_256 256
|
||||||
|
#define CH384_TRIGGER_LEVEL_256FIFO_01 1
|
||||||
|
#define CH384_TRIGGER_LEVEL_256FIFO_32 32
|
||||||
|
#define CH384_TRIGGER_LEVEL_256FIFO_128 128
|
||||||
|
#define CH384_TRIGGER_LEVEL_256FIFO_224 224
|
||||||
|
|
||||||
|
#define CH432_FIFOSIZE_16 16
|
||||||
|
#define CH432_TRIGGER_LEVEL_16FIFO_01 1
|
||||||
|
#define CH432_TRIGGER_LEVEL_16FIFO_04 4
|
||||||
|
#define CH432_TRIGGER_LEVEL_16FIFO_08 8
|
||||||
|
#define CH432_TRIGGER_LEVEL_16FIFO_14 14
|
||||||
|
|
||||||
|
#define CH438_FIFOSIZE_128 128
|
||||||
|
#define CH438_TRIGGER_LEVEL_128FIFO_01 1
|
||||||
|
#define CH438_TRIGGER_LEVEL_128FIFO_16 16
|
||||||
|
#define CH438_TRIGGER_LEVEL_128FIFO_64 64
|
||||||
|
#define CH438_TRIGGER_LEVEL_128FIFO_112 112
|
||||||
|
|
||||||
|
// uart fifo setup
|
||||||
|
#define CH351_FIFOSIZE_SET CH351_FIFOSIZE_16
|
||||||
|
#define CH351_TRIGGER_LEVEL_SET CH351_TRIGGER_LEVEL_16FIFO_08
|
||||||
|
|
||||||
|
#define CH352_FIFOSIZE_SET CH352_FIFOSIZE_16
|
||||||
|
#define CH352_TRIGGER_LEVEL_SET CH352_TRIGGER_LEVEL_16FIFO_08
|
||||||
|
|
||||||
|
#define CH353_FIFOSIZE_SET CH353_FIFOSIZE_16
|
||||||
|
#define CH353_TRIGGER_LEVEL_SET CH353_TRIGGER_LEVEL_16FIFO_08
|
||||||
|
|
||||||
|
#define CH355_FIFOSIZE_SET CH355_FIFOSIZE_16
|
||||||
|
#define CH355_TRIGGER_LEVEL_SET CH355_TRIGGER_LEVEL_16FIFO_08
|
||||||
|
|
||||||
|
#define CH356_FIFOSIZE_SET CH356_FIFOSIZE_16
|
||||||
|
#define CH356_TRIGGER_LEVEL_SET CH356_TRIGGER_LEVEL_16FIFO_08
|
||||||
|
|
||||||
|
#define CH357_FIFOSIZE_SET CH357_FIFOSIZE_128
|
||||||
|
#define CH357_TRIGGER_LEVEL_SET CH357_TRIGGER_LEVEL_128FIFO_64
|
||||||
|
|
||||||
|
#define CH358_FIFOSIZE_SET CH358_FIFOSIZE_128
|
||||||
|
#define CH358_TRIGGER_LEVEL_SET CH358_TRIGGER_LEVEL_128FIFO_64
|
||||||
|
|
||||||
|
#define CH359_FIFOSIZE_SET CH359_FIFOSIZE_128
|
||||||
|
#define CH359_TRIGGER_LEVEL_SET CH359_TRIGGER_LEVEL_128FIFO_64
|
||||||
|
|
||||||
|
#define CH382_FIFOSIZE_SET CH382_FIFOSIZE_256
|
||||||
|
#define CH382_TRIGGER_LEVEL_SET CH382_TRIGGER_LEVEL_256FIFO_128
|
||||||
|
|
||||||
|
#define CH384_FIFOSIZE_SET CH384_FIFOSIZE_256
|
||||||
|
#define CH384_TRIGGER_LEVEL_SET CH384_TRIGGER_LEVEL_256FIFO_128
|
||||||
|
|
||||||
|
#define CH432_FIFOSIZE_SET CH432_FIFOSIZE_16
|
||||||
|
#define CH432_TRIGGER_LEVEL_SET CH432_TRIGGER_LEVEL_16FIFO_08
|
||||||
|
|
||||||
|
#define CH438_FIFOSIZE_SET CH438_FIFOSIZE_128
|
||||||
|
#define CH438_TRIGGER_LEVEL_SET CH438_TRIGGER_LEVEL_128FIFO_16
|
||||||
|
|
||||||
|
#define UART_TRIGGER00_FCR 0x00
|
||||||
|
#define UART_TRIGGER01_FCR 0x40
|
||||||
|
#define UART_TRIGGER10_FCR 0x80
|
||||||
|
#define UART_TRIGGER11_FCR 0xC0
|
||||||
|
|
||||||
|
#define UART_DEFAULT_FCR 0x00
|
||||||
|
|
||||||
|
#define DEFAULT_FIFOSIZE 1
|
||||||
|
#define DEFAULT_TRIGGER_LEVEL 1
|
||||||
|
|
||||||
|
// register status info
|
||||||
|
#define UART_LSR_ERR_IN_RFIFO 0x80
|
||||||
|
#define UART_MCR_AFE 0x20
|
||||||
|
#define UART_IIR_CTO 0x0C
|
||||||
|
|
||||||
|
// serial address length
|
||||||
|
#define WCH_SER_ADDRESS_LENGTH 0x08
|
||||||
|
|
||||||
|
// PCI configuration bar 0 ~ 5
|
||||||
|
#define WCH_PCICFG_BAR_TOTAL 0x06
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
* miscellaneous Information
|
||||||
|
*******************************************************/
|
||||||
|
#define INTERRUPT_COUNT 0x80
|
||||||
|
#define WAKEUP_CHARS_SER 0x100
|
||||||
|
#define WCHTERMIOS ktermios
|
||||||
|
|
||||||
|
// for ser_port->setserial_flag
|
||||||
|
#define WCH_SER_BAUD_SETSERIAL 0x01
|
||||||
|
#define WCH_SER_BAUD_NOTSETSER 0x00
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
struct define Information
|
||||||
|
*******************************************************/
|
||||||
|
|
||||||
|
// name length
|
||||||
|
#define WCH_BOARDNAME_LENGTH 0x0F
|
||||||
|
#define WCH_DRIVERVERSION_LENGTH 0x0F
|
||||||
|
|
||||||
|
struct ser_port_info {
|
||||||
|
char board_name_info[WCH_BOARDNAME_LENGTH];
|
||||||
|
unsigned int bus_number_info;
|
||||||
|
unsigned int dev_number_info;
|
||||||
|
unsigned int port_info;
|
||||||
|
unsigned int base_info;
|
||||||
|
unsigned int irq_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct port {
|
||||||
|
char type;
|
||||||
|
|
||||||
|
int bar1;
|
||||||
|
unsigned int offset1;
|
||||||
|
unsigned char length1;
|
||||||
|
|
||||||
|
int bar2;
|
||||||
|
unsigned int offset2;
|
||||||
|
unsigned char length2;
|
||||||
|
|
||||||
|
unsigned int chip_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pci_board {
|
||||||
|
unsigned int vendor_id;
|
||||||
|
unsigned int device_id;
|
||||||
|
unsigned int sub_vendor_id;
|
||||||
|
unsigned int sub_device_id;
|
||||||
|
|
||||||
|
unsigned int num_serport;
|
||||||
|
|
||||||
|
unsigned int intr_vector_bar;
|
||||||
|
unsigned int intr_vector_offset;
|
||||||
|
unsigned int intr_vector_offset_1;
|
||||||
|
unsigned int intr_vector_offset_2;
|
||||||
|
unsigned int intr_vector_offset_3;
|
||||||
|
|
||||||
|
char board_name[WCH_BOARDNAME_LENGTH];
|
||||||
|
unsigned int board_flag;
|
||||||
|
|
||||||
|
struct port port[WCH_PORT_ONBOARD_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wch_board;
|
||||||
|
struct wch_ser_port;
|
||||||
|
struct wch_par_port;
|
||||||
|
|
||||||
|
struct wch_board {
|
||||||
|
int board_enum;
|
||||||
|
int board_number;
|
||||||
|
unsigned int bus_number;
|
||||||
|
unsigned int dev_number;
|
||||||
|
|
||||||
|
unsigned int ser_ports;
|
||||||
|
|
||||||
|
unsigned int ser_port_index;
|
||||||
|
|
||||||
|
unsigned long bar_addr[WCH_PCICFG_BAR_TOTAL];
|
||||||
|
unsigned int irq;
|
||||||
|
void *board_membase;
|
||||||
|
unsigned int board_flag;
|
||||||
|
|
||||||
|
unsigned int vector_mask;
|
||||||
|
struct pci_board pb_info;
|
||||||
|
struct pci_dev *pdev;
|
||||||
|
int (*ser_isr)(struct wch_board *, struct wch_ser_port *);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
for wch_serial.c
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------*/
|
||||||
|
/*******************************************************
|
||||||
|
* ioctl user define
|
||||||
|
*******************************************************/
|
||||||
|
#define WCH_IOCTL 0x900
|
||||||
|
#define WCH_SER_DUMP_PORT_INFO (WCH_IOCTL + 50)
|
||||||
|
#define WCH_SER_DUMP_PORT_PERF (WCH_IOCTL + 51)
|
||||||
|
#define WCH_SER_DUMP_DRIVER_VER (WCH_IOCTL + 52)
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
* serial define
|
||||||
|
*******************************************************/
|
||||||
|
#define PORT_SER_UNKNOWN 0x00
|
||||||
|
#define PORT_SER_8250 0x01
|
||||||
|
#define PORT_SER_16450 0x02
|
||||||
|
#define PORT_SER_16550 0x03
|
||||||
|
#define PORT_SER_16550A 0x04
|
||||||
|
#define PORT_SER_CIRRUS 0x05
|
||||||
|
#define PORT_SER_16650 0x06
|
||||||
|
#define PORT_SER_16650V2 0x07
|
||||||
|
#define PORT_SER_16750 0x08
|
||||||
|
#define PORT_SER_MAX_UART 0x08
|
||||||
|
|
||||||
|
#define WCH_USF_CLOSING_WAIT_INF (0)
|
||||||
|
#define WCH_USF_CLOSING_WAIT_NONE (65535)
|
||||||
|
#define WCH_UART_CONFIG_TYPE (1 << 0)
|
||||||
|
#define WCH_UART_CONFIG_IRQ (1 << 1)
|
||||||
|
|
||||||
|
#define WCH_UART_XMIT_SIZE 0x1000
|
||||||
|
|
||||||
|
#define ser_circ_empty(circ) ((circ)->head == (circ)->tail)
|
||||||
|
#define ser_circ_clear(circ) ((circ)->head = (circ)->tail = 0)
|
||||||
|
#define ser_circ_chars_pending(circ) (CIRC_CNT((circ)->head, (circ)->tail, WCH_UART_XMIT_SIZE))
|
||||||
|
#define ser_circ_chars_free(circ) (CIRC_SPACE((circ)->head, (circ)->tail, WCH_UART_XMIT_SIZE))
|
||||||
|
#define ser_tx_stopped(port) ((port)->info->tty->flow.stopped || (port)->info->tty->hw_stopped)
|
||||||
|
|
||||||
|
#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
|
||||||
|
#define WCH_SERIAL_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WCH_SERIAL_INLINE
|
||||||
|
#define _INLINE_ inline
|
||||||
|
#else
|
||||||
|
#define _INLINE_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WCH_UPIO_PORT (0)
|
||||||
|
#define WCH_UPIO_MEM (1)
|
||||||
|
|
||||||
|
#define WCH_UPF_SAK (1 << 2)
|
||||||
|
#define WCH_UPF_SPD_MASK (0x1030)
|
||||||
|
#define WCH_UPF_SPD_HI (0x0010)
|
||||||
|
#define WCH_UPF_SPD_VHI (0x0020)
|
||||||
|
#define WCH_UPF_SPD_CUST (0x0030)
|
||||||
|
#define WCH_UPF_SPD_SHI (0x1000)
|
||||||
|
#define WCH_UPF_SPD_WARP (0x1010)
|
||||||
|
#define WCH_UPF_SKIP_TEST (1 << 6)
|
||||||
|
#define WCH_UPF_HARDPPS_CD (1 << 11)
|
||||||
|
#define WCH_UPF_LOW_LATENCY (1 << 13)
|
||||||
|
#define WCH_UPF_BUGGY_UART (1 << 14)
|
||||||
|
#define WCH_UPF_MAGIC_MULTIPLIER (1 << 16)
|
||||||
|
|
||||||
|
#define WCH_UPF_CHANGE_MASK (0x17fff)
|
||||||
|
#define WCH_UPF_USR_MASK (WCH_UPF_SPD_MASK | WCH_UPF_LOW_LATENCY)
|
||||||
|
|
||||||
|
#define WCH_UIF_CHECK_CD (1 << 25)
|
||||||
|
#define WCH_UIF_CTS_FLOW (1 << 26)
|
||||||
|
|
||||||
|
#define WCH_UIF_NORMAL_ACTIVE (1 << 29)
|
||||||
|
#define WCH_UIF_INITIALIZED (1 << 31)
|
||||||
|
|
||||||
|
#define WCH_ENABLE_MS(port, cflag) ((port)->flags & WCH_UPF_HARDPPS_CD || (cflag)&CRTSCTS || !((cflag)&CLOCAL))
|
||||||
|
|
||||||
|
#define WCH_SER_DEVNUM(x) ((x)->index)
|
||||||
|
|
||||||
|
struct ser_info;
|
||||||
|
struct ser_port;
|
||||||
|
|
||||||
|
struct ser_icount {
|
||||||
|
__u32 cts;
|
||||||
|
__u32 dsr;
|
||||||
|
__u32 rng;
|
||||||
|
__u32 dcd;
|
||||||
|
__u32 rx;
|
||||||
|
__u32 tx;
|
||||||
|
__u32 frame;
|
||||||
|
__u32 overrun;
|
||||||
|
__u32 parity;
|
||||||
|
__u32 brk;
|
||||||
|
__u32 buf_overrun;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ser_info {
|
||||||
|
struct tty_struct *tty;
|
||||||
|
struct circ_buf xmit;
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned char *tmpbuf;
|
||||||
|
struct semaphore tmpbuf_sem;
|
||||||
|
int blocked_open;
|
||||||
|
struct tasklet_struct tlet;
|
||||||
|
|
||||||
|
wait_queue_head_t open_wait;
|
||||||
|
wait_queue_head_t delta_msr_wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ser_driver {
|
||||||
|
const char *dev_name;
|
||||||
|
int major;
|
||||||
|
int minor;
|
||||||
|
int nr;
|
||||||
|
struct ser_state *state;
|
||||||
|
struct tty_driver *tty_driver;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ser_port {
|
||||||
|
spinlock_t lock;
|
||||||
|
void *port_membase;
|
||||||
|
void *board_membase;
|
||||||
|
unsigned long iobase;
|
||||||
|
unsigned int irq;
|
||||||
|
unsigned int uartclk;
|
||||||
|
unsigned int fifosize;
|
||||||
|
unsigned char x_char;
|
||||||
|
unsigned char iotype;
|
||||||
|
|
||||||
|
unsigned int read_status_mask;
|
||||||
|
unsigned int ignore_status_mask;
|
||||||
|
struct ser_info *info;
|
||||||
|
struct ser_state *state;
|
||||||
|
struct ser_icount icount;
|
||||||
|
|
||||||
|
unsigned int flags;
|
||||||
|
unsigned int mctrl;
|
||||||
|
unsigned int timeout;
|
||||||
|
unsigned int type;
|
||||||
|
unsigned int custom_divisor;
|
||||||
|
unsigned int line;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
int board_enum;
|
||||||
|
unsigned int bus_number;
|
||||||
|
unsigned int dev_number;
|
||||||
|
struct pci_board pb_info;
|
||||||
|
unsigned long vector;
|
||||||
|
unsigned int chip_iobase;
|
||||||
|
unsigned int vector_mask;
|
||||||
|
unsigned char chip_flag;
|
||||||
|
unsigned int port_flag;
|
||||||
|
unsigned int baud_base;
|
||||||
|
int rx_trigger;
|
||||||
|
bool bext1stport;
|
||||||
|
bool bspe1stport;
|
||||||
|
bool hardflow;
|
||||||
|
unsigned char ldisc_stop_rx;
|
||||||
|
|
||||||
|
unsigned int setserial_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ser_state {
|
||||||
|
struct tty_port port0;
|
||||||
|
unsigned int close_delay;
|
||||||
|
unsigned int closing_wait;
|
||||||
|
int count;
|
||||||
|
struct ser_info *info;
|
||||||
|
struct ser_port *port;
|
||||||
|
struct semaphore sem;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int ser_handle_break(struct ser_port *port)
|
||||||
|
{
|
||||||
|
struct ser_info *info = port->info;
|
||||||
|
|
||||||
|
if (info->flags & WCH_UPF_SAK) {
|
||||||
|
do_SAK(info->tty);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ser_handle_dcd_change(struct ser_port *port, unsigned int status)
|
||||||
|
{
|
||||||
|
struct ser_info *info = port->info;
|
||||||
|
|
||||||
|
port->icount.dcd++;
|
||||||
|
|
||||||
|
if (info->flags & WCH_UIF_CHECK_CD) {
|
||||||
|
if (status) {
|
||||||
|
wake_up_interruptible(&info->open_wait);
|
||||||
|
} else if (info->tty) {
|
||||||
|
tty_hangup(info->tty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <linux/tty_flip.h>
|
||||||
|
|
||||||
|
static inline void ser_insert_buffer(struct ser_port *port, unsigned int status, unsigned int overrun,
|
||||||
|
unsigned char *buf, unsigned int count, unsigned char flag)
|
||||||
|
{
|
||||||
|
struct tty_port *tty = &port->state->port0;
|
||||||
|
|
||||||
|
if ((status & port->ignore_status_mask & ~overrun) == 0) {
|
||||||
|
if (tty_insert_flip_string_fixed_flag(tty, buf, flag, count) == 0)
|
||||||
|
++port->icount.buf_overrun;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & ~port->ignore_status_mask & overrun) {
|
||||||
|
if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0)
|
||||||
|
++port->icount.buf_overrun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ser_insert_char(struct ser_port *port, unsigned int status, unsigned int overrun, unsigned int ch,
|
||||||
|
unsigned int flag)
|
||||||
|
{
|
||||||
|
struct tty_port *tty = &port->state->port0;
|
||||||
|
|
||||||
|
if ((status & port->ignore_status_mask & ~overrun) == 0) {
|
||||||
|
if (tty_insert_flip_char(tty, ch, flag) == 0)
|
||||||
|
++port->icount.buf_overrun;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status & ~port->ignore_status_mask & overrun) {
|
||||||
|
if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0)
|
||||||
|
++port->icount.buf_overrun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************
|
||||||
|
* wch serial port struct
|
||||||
|
*******************************************************/
|
||||||
|
struct wch_ser_port {
|
||||||
|
struct ser_port port;
|
||||||
|
struct timer_list timer;
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
|
unsigned int capabilities;
|
||||||
|
unsigned char ier;
|
||||||
|
unsigned char lcr;
|
||||||
|
unsigned char mcr;
|
||||||
|
unsigned char mcr_mask;
|
||||||
|
unsigned char mcr_force;
|
||||||
|
unsigned char lsr_break_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------------
|
||||||
|
* function and variable extern
|
||||||
|
-------------------------------------------------------------------------------*/
|
||||||
|
// wch_devtable.c
|
||||||
|
extern struct pci_board wch_pci_board_conf[];
|
||||||
|
extern struct pci_device_id wch_pci_board_id[];
|
||||||
|
|
||||||
|
// wch_serial.c
|
||||||
|
extern int wch_ser_register_ports(struct ser_driver *);
|
||||||
|
extern void wch_ser_unregister_ports(struct ser_driver *);
|
||||||
|
extern int wch_ser_register_driver(struct ser_driver *);
|
||||||
|
extern void wch_ser_unregister_driver(struct ser_driver *);
|
||||||
|
extern int wch_ser_interrupt(struct wch_board *, struct wch_ser_port *);
|
||||||
|
|
||||||
|
// wch_main.c
|
||||||
|
extern struct wch_board wch_board_table[WCH_BOARDS_MAX];
|
||||||
|
extern struct wch_ser_port wch_ser_table[WCH_SER_TOTAL_MAX + 1];
|
||||||
|
extern int wch_35x_init(void);
|
||||||
|
extern void wch_35x_exit(void);
|
||||||
|
extern unsigned char ch365_32s;
|
||||||
|
|
||||||
|
#endif
|
||||||
418
drivers/tty/serial/wch_35x/wch_devtable.c
Normal file
418
drivers/tty/serial/wch_35x/wch_devtable.c
Normal file
@@ -0,0 +1,418 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "wch_common.h"
|
||||||
|
|
||||||
|
#define PCIE_UART_MAX 28
|
||||||
|
|
||||||
|
struct pci_board wch_pci_board_conf[] = {
|
||||||
|
// NONE
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, "none", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 'n', -1, 0, 0, -1, 0, 0, NONE_BOARD },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH351_2S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_CH351, DEVICE_ID_WCH_CH351_2S, SUB_VENDOR_ID_WCH_CH351, SUB_DEVICE_ID_WCH_CH351_2S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, "CH351_2S", BOARDFLAG_REMAP,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH351_2S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH351_2S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH352_2S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH352_2S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH352_2S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, "CH352_2S", BOARDFLAG_REMAP,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH352_2S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH352_2S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH352_1S1P
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH352_1S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH352_1S1P,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
1, 0, 0x00, 0x00, 0x00, 0x00, "CH352_1S1P", BOARDFLAG_REMAP,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH352_1S1P },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH353_4S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH353_4S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH353_4S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
4, 3, 0x0F, 0x00, 0x00, 0x00, "CH353_4S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH353_4S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH353_4S },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH353_4S },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH353_4S },
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH353_2S1P
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH353_2S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH353_2S1P,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
2, 3, 0x0F, 0x00, 0x00, 0x00, "CH353_2S1P", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH353_2S1P },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH353_2S1P },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH353_2S1PAR
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH353_2S1PAR, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH353_2S1PAR,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
2, 3, 0x0F, 0x00, 0x00, 0x00, "CH353_2S1PAR", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH353_2S1PAR },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH353_2S1PAR },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH355_4S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH355_4S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH355_4S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
4, 4, 0x20, 0x00, 0x00, 0x00, "CH355_4S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH355_4S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH355_4S },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH355_4S },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH355_4S },
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH356_4S1P
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH356_4S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH356_4S1P,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
4, 4, 0x3F, 0x00, 0x00, 0x00, "CH356_4S1P", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH356_4S1P },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH356_4S1P },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH356_4S1P },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH356_4S1P },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH356_6S(CH356+CH432(1P))
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH356_6S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH356_6S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
6, 4, 0x3F, 0x00, 0x00, 0x00, "CH356_6S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH356_6S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH356_6S },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH356_6S },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH356_6S },
|
||||||
|
{ 's', 4, 0, 8, -1, 0, 0, WCH_BOARD_CH356_6S },
|
||||||
|
{ 's', 4, 0x08, 8, -1, 0, 0, WCH_BOARD_CH356_6S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH356_8S(CH356+CH432(2P))
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH356_8S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH356_8S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
8, 4, 0x3F, 0x00, 0x00, 0x00, "CH356_8S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
{ 's', 4, 0, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
{ 's', 4, 0x08, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
{ 's', 4, 0x10, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
{ 's', 4, 0x18, 8, -1, 0, 0, WCH_BOARD_CH356_8S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH357_4S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH357_4S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH357_4S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
4, 4, 0x6F, 0x00, 0x00, 0x00, "CH357_4S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH357_4S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH357_4S },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH357_4S },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH357_4S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH358_4S1P
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH358_4S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH358_4S1P,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
4, 4, 0x6F, 0x00, 0x00, 0x00, "CH358_4S1P", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH358_4S1P },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH358_4S1P },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH358_4S1P },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH358_4S1P },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH358_8S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH358_8S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH358_8S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
8, 4, 0x6F, 0x00, 0x00, 0x00, "CH358_8S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
{ 's', 0, 8, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
{ 's', 1, 8, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
{ 's', 2, 8, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
{ 's', 3, 8, 8, -1, 0, 0, WCH_BOARD_CH358_8S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH359_16S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH359_16S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH359_16S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
16, 4, 0x6F, 0x00, 0x00, 0x00, "CH359_16S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 1, 0, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 2, 0, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 3, 0, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 0, 8, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 1, 8, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 2, 8, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 3, 8, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
|
||||||
|
{ 's', 4, 0, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 4, 16, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 4, 32, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 4, 48, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 4, 8, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 4, 24, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 4, 40, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
{ 's', 4, 56, 8, -1, 0, 0, WCH_BOARD_CH359_16S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH382_2S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH382_2S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH382_2S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
2, 0, 0xE9, 0x00, 0x00, 0x00, "CH382_2S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0xC0, 8, -1, 0, 0, WCH_BOARD_CH382_2S },
|
||||||
|
{ 's', 0, 0xC8, 8, -1, 0, 0, WCH_BOARD_CH382_2S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH382_2S1P
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH382_2S1P, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH382_2S1P,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
2, 0, 0xE9, 0x00, 0x00, 0x00, "CH382_2S1P", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0xC0, 8, -1, 0, 0, WCH_BOARD_CH382_2S1P },
|
||||||
|
{ 's', 0, 0xC8, 8, -1, 0, 0, WCH_BOARD_CH382_2S1P },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// CH384_4S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_4S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_4S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
4, 0, 0xE9, 0x00, 0x00, 0x00, "CH384_4S", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0xC0, 8, -1, 0, 0, WCH_BOARD_CH384_4S },
|
||||||
|
{ 's', 0, 0xC8, 8, -1, 0, 0, WCH_BOARD_CH384_4S },
|
||||||
|
{ 's', 0, 0xD0, 8, -1, 0, 0, WCH_BOARD_CH384_4S },
|
||||||
|
{ 's', 0, 0xD8, 8, -1, 0, 0, WCH_BOARD_CH384_4S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH384_4S1P
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_4S1P, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_4S1P,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
4, 0, 0xE9, 0x00, 0x00, 0x00, "CH384_4S1P", BOARDFLAG_NONE,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0xC0, 8, -1, 0, 0, WCH_BOARD_CH384_4S1P },
|
||||||
|
{ 's', 0, 0xC8, 8, -1, 0, 0, WCH_BOARD_CH384_4S1P },
|
||||||
|
{ 's', 0, 0xD0, 8, -1, 0, 0, WCH_BOARD_CH384_4S1P },
|
||||||
|
{ 's', 0, 0xD8, 8, -1, 0, 0, WCH_BOARD_CH384_4S1P },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH384_8S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_8S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_8S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
8, 0, 0xE0, 0x00, 0x00, 0x00, "CH384_8S", BOARDFLAG_CH384_8_PORTS,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
{ 's', 0, 0x10, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
{ 's', 0, 0x20, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
{ 's', 0, 0x30, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
{ 's', 0, 0x08, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
{ 's', 0, 0x18, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
{ 's', 0, 0x28, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
{ 's', 0, 0x38, 8, -1, 0, 0, WCH_BOARD_CH384_8S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH384_28S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_28S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_28S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
PCIE_UART_MAX, 0, 0xE9, 0xE0, 0xE4, 0xE6, "CH384_28S", BOARDFLAG_CH384_28_PORTS,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0xC0, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0xC8, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0xD0, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0xD8, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x10, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x20, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x30, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x08, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x18, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x28, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x38, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
|
||||||
|
{ 's', 0, 0x40, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x50, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x60, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x70, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x48, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x58, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x68, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x78, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
|
||||||
|
{ 's', 0, 0x80, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x90, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0xA0, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0xB0, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x88, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0x98, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0xA8, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
{ 's', 0, 0xB8, 8, -1, 0, 0, WCH_BOARD_CH384_28S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// CH365_32S
|
||||||
|
{
|
||||||
|
// VenID DevID SubVenID SubSysID
|
||||||
|
VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH365_32S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH365_32S,
|
||||||
|
// SerPort IntrBar IntrOffset IntrOffset1 IntrOffset2 IntrOffset3 Name BoardFlag
|
||||||
|
32, 1, 0x00, 0x00, 0x00, 0x00, "CH365_32S", BOARDFLAG_CH365_32_PORTS,
|
||||||
|
{
|
||||||
|
// type bar1 ofs1 len1 bar2 ofs2 len2 flags
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 0, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
{ 's', 0, 0x00, 8, -1, 0, 0, WCH_BOARD_CH365_32S },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
931
drivers/tty/serial/wch_35x/wch_main.c
Normal file
931
drivers/tty/serial/wch_35x/wch_main.c
Normal file
@@ -0,0 +1,931 @@
|
|||||||
|
/*
|
||||||
|
* PCI/PCIE to serial driver for ch351/352/353/355/356/357/358/359/382/384, etc.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||||
|
* Web: http://wch.cn
|
||||||
|
* Author: WCH <tech@wch.cn>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Update Log:
|
||||||
|
* V1.00 - initial version
|
||||||
|
* V1.10 - fixed uart send bugs
|
||||||
|
* V1.11 - fixed the issue of serial ports number creation
|
||||||
|
* V1.12 - fixed modem signals support
|
||||||
|
* V1.13 - added automatic frequency multiplication when using baud rates higher than 115200bps
|
||||||
|
- added mutex protection in uart transmit process
|
||||||
|
* V1.14 - optimized the processing of serial ports in interruption
|
||||||
|
* V1.15 - added support for non-standard baud rate
|
||||||
|
* V1.16 - fixed uart clock frequency multiplication bugs
|
||||||
|
* V1.17 - modified uart data received process
|
||||||
|
* V1.18 - changed uart fifo trigger level
|
||||||
|
- changed uart transmission to half of the fifo size
|
||||||
|
* V1.19 - fixed ch358 uart0 setting bug
|
||||||
|
* V1.20 - added pre-load driver
|
||||||
|
* V1.21 - fixed modem setting when disable hardflow
|
||||||
|
* V1.22 - added support for rs485 configuration
|
||||||
|
* V1.23 - added supports for kernel version beyond 5.14.x
|
||||||
|
* V1.24 - fixed ch351/2/3 uart0 setting bug, merged pre-load driver
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "wch_common.h"
|
||||||
|
|
||||||
|
extern struct wch_board wch_board_table[WCH_BOARDS_MAX];
|
||||||
|
extern struct wch_ser_port wch_ser_table[WCH_SER_TOTAL_MAX + 1];
|
||||||
|
extern unsigned char ch365_32s;
|
||||||
|
|
||||||
|
struct wch_board wch_board_table[WCH_BOARDS_MAX];
|
||||||
|
struct wch_ser_port wch_ser_table[WCH_SER_TOTAL_MAX + 1];
|
||||||
|
|
||||||
|
int wch_ser_port_total_cnt;
|
||||||
|
unsigned char ch365_32s = 0;
|
||||||
|
|
||||||
|
struct pci_device_id wch_pci_board_id[] = {
|
||||||
|
{VENDOR_ID_WCH_CH351, DEVICE_ID_WCH_CH351_2S, SUB_VENDOR_ID_WCH_CH351, SUB_DEVICE_ID_WCH_CH351_2S, 0, 0,
|
||||||
|
WCH_BOARD_CH351_2S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH352_2S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH352_2S, 0, 0,
|
||||||
|
WCH_BOARD_CH352_2S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH352_1S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH352_1S1P, 0, 0,
|
||||||
|
WCH_BOARD_CH352_1S1P},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH353_4S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH353_4S, 0, 0,
|
||||||
|
WCH_BOARD_CH353_4S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH353_2S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH353_2S1P, 0, 0,
|
||||||
|
WCH_BOARD_CH353_2S1P},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH353_2S1PAR, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH353_2S1PAR, 0, 0,
|
||||||
|
WCH_BOARD_CH353_2S1PAR},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH355_4S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH355_4S, 0, 0,
|
||||||
|
WCH_BOARD_CH355_4S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH356_4S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH356_4S1P, 0, 0,
|
||||||
|
WCH_BOARD_CH356_4S1P},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH356_6S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH356_6S, 0, 0,
|
||||||
|
WCH_BOARD_CH356_6S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH356_8S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH356_8S, 0, 0,
|
||||||
|
WCH_BOARD_CH356_8S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH357_4S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH357_4S, 0, 0,
|
||||||
|
WCH_BOARD_CH357_4S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH358_4S1P, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH358_4S1P, 0, 0,
|
||||||
|
WCH_BOARD_CH358_4S1P},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH358_8S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH358_8S, 0, 0,
|
||||||
|
WCH_BOARD_CH358_8S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH359_16S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH359_16S, 0, 0,
|
||||||
|
WCH_BOARD_CH359_16S},
|
||||||
|
{VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH382_2S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH382_2S, 0, 0,
|
||||||
|
WCH_BOARD_CH382_2S},
|
||||||
|
{VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH382_2S1P, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH382_2S1P, 0, 0,
|
||||||
|
WCH_BOARD_CH382_2S1P},
|
||||||
|
{VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_4S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_4S, 0, 0,
|
||||||
|
WCH_BOARD_CH384_4S},
|
||||||
|
{VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_4S1P, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_4S1P, 0, 0,
|
||||||
|
WCH_BOARD_CH384_4S1P},
|
||||||
|
{VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_8S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_8S, 0, 0,
|
||||||
|
WCH_BOARD_CH384_8S},
|
||||||
|
{VENDOR_ID_WCH_PCIE, DEVICE_ID_WCH_CH384_28S, SUB_VENDOR_ID_WCH_PCIE, SUB_DEVICE_ID_WCH_CH384_28S, 0, 0,
|
||||||
|
WCH_BOARD_CH384_28S},
|
||||||
|
{VENDOR_ID_WCH_PCI, DEVICE_ID_WCH_CH365_32S, SUB_VENDOR_ID_WCH_PCI, SUB_DEVICE_ID_WCH_CH365_32S, 0, 0,
|
||||||
|
WCH_BOARD_CH365_32S},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(pci, wch_pci_board_id);
|
||||||
|
|
||||||
|
static irqreturn_t wch_interrupt(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct wch_ser_port *sp = NULL;
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
int i;
|
||||||
|
int status = 0;
|
||||||
|
int handled = IRQ_NONE;
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
if (dev_id == &(wch_board_table[i])) {
|
||||||
|
sb = dev_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == WCH_BOARDS_MAX) {
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sb) {
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb->board_enum <= 0) {
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sb->ser_ports > 0) && (sb->ser_isr != NULL)) {
|
||||||
|
sp = &wch_ser_table[sb->ser_port_index];
|
||||||
|
|
||||||
|
if (!sp) {
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = sb->ser_isr(sb, sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
handled = IRQ_HANDLED;
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wch_pci_board_probe(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb;
|
||||||
|
struct pci_dev *pdev = NULL;
|
||||||
|
struct pci_dev *pdev_array[4] = {NULL, NULL, NULL, NULL};
|
||||||
|
|
||||||
|
int wch_pci_board_id_cnt;
|
||||||
|
int table_cnt;
|
||||||
|
int board_cnt;
|
||||||
|
int i;
|
||||||
|
unsigned short int sub_device_id;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
printk("%s : %s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// clear and init some variable
|
||||||
|
memset(wch_board_table, 0, WCH_BOARDS_MAX * sizeof(struct wch_board));
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
wch_board_table[i].board_enum = -1;
|
||||||
|
wch_board_table[i].board_number = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wch_pci_board_id_cnt = (sizeof(wch_pci_board_id) / sizeof(wch_pci_board_id[0])) - 1;
|
||||||
|
|
||||||
|
// search wch serial and multi-I/O board
|
||||||
|
pdev = NULL;
|
||||||
|
table_cnt = 0;
|
||||||
|
board_cnt = 0;
|
||||||
|
status = 0;
|
||||||
|
|
||||||
|
while (table_cnt < wch_pci_board_id_cnt) {
|
||||||
|
pdev = pci_get_device(wch_pci_board_id[table_cnt].vendor, wch_pci_board_id[table_cnt].device, pdev);
|
||||||
|
|
||||||
|
if (pdev == NULL) {
|
||||||
|
table_cnt++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((table_cnt > 0) && ((pdev == pdev_array[0]) || (pdev == pdev_array[1]) || (pdev == pdev_array[2]) ||
|
||||||
|
(pdev == pdev_array[3]))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wch_pci_board_id[table_cnt].driver_data == WCH_BOARD_CH365_32S) {
|
||||||
|
ch365_32s = 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_read_config_word(pdev, 0x2e, &sub_device_id);
|
||||||
|
|
||||||
|
if (ch365_32s) {
|
||||||
|
} else {
|
||||||
|
if (sub_device_id == 0) {
|
||||||
|
printk("WCH Error: WCH Board (bus:%d device:%d), in configuration space,\n", pdev->bus->number,
|
||||||
|
PCI_SLOT(pdev->devfn));
|
||||||
|
printk(" subdevice id isn't vaild.\n\n");
|
||||||
|
status = -EIO;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub_device_id != wch_pci_board_id[table_cnt].subdevice) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pdev == NULL) {
|
||||||
|
printk("WCH Error: PCI device object is an NULL pointer !\n\n");
|
||||||
|
status = -EIO;
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
status = pci_enable_device(pdev);
|
||||||
|
|
||||||
|
if (status != 0) {
|
||||||
|
printk("WCH Error: WCH Board Enable Fail !\n\n");
|
||||||
|
status = -ENXIO;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
board_cnt++;
|
||||||
|
if (board_cnt > WCH_BOARDS_MAX) {
|
||||||
|
printk("\n");
|
||||||
|
printk("WCH Error: WCH Driver Module Support Four Boards In Maximum !\n\n");
|
||||||
|
status = -ENOSPC;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb = &wch_board_table[board_cnt - 1];
|
||||||
|
|
||||||
|
pdev_array[board_cnt - 1] = pdev;
|
||||||
|
sb->pdev = pdev;
|
||||||
|
sb->bus_number = pdev->bus->number;
|
||||||
|
sb->dev_number = PCI_SLOT(pdev->devfn);
|
||||||
|
|
||||||
|
sb->board_enum = (int)wch_pci_board_id[table_cnt].driver_data;
|
||||||
|
sb->pb_info = wch_pci_board_conf[sb->board_enum];
|
||||||
|
|
||||||
|
sb->board_flag = sb->pb_info.board_flag;
|
||||||
|
|
||||||
|
sb->board_number = board_cnt - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (board_cnt == 0) {
|
||||||
|
printk("WCH Info : No WCH Multi-I/O Board Found !\n\n");
|
||||||
|
status = -ENXIO;
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
if (sb->board_enum > 0) {
|
||||||
|
printk("\n");
|
||||||
|
if ((sb->pb_info.num_serport) > 0) {
|
||||||
|
printk("WCH Info : Found WCH %s Series Board (%dS),\n", sb->pb_info.board_name,
|
||||||
|
sb->pb_info.num_serport);
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(" bus number:%d, device number:%d\n\n", sb->bus_number, sb->dev_number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wch_get_pci_board_conf(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
struct pci_dev *pdev = NULL;
|
||||||
|
int status = 0;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
printk("%s : %s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
|
||||||
|
if (sb->board_enum > 0) {
|
||||||
|
pdev = sb->pdev;
|
||||||
|
sb->ser_ports = sb->pb_info.num_serport;
|
||||||
|
|
||||||
|
wch_ser_port_total_cnt = wch_ser_port_total_cnt + sb->ser_ports;
|
||||||
|
|
||||||
|
if (wch_ser_port_total_cnt > WCH_SER_TOTAL_MAX) {
|
||||||
|
printk("WCH Error: Too much serial port, maximum %d ports can be supported !\n\n", WCH_SER_TOTAL_MAX);
|
||||||
|
status = -EIO;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < WCH_PCICFG_BAR_TOTAL; j++) {
|
||||||
|
sb->bar_addr[j] = pci_resource_start(pdev, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sb->board_flag & BOARDFLAG_CH365_32_PORTS) == BOARDFLAG_CH365_32_PORTS) {
|
||||||
|
sb->board_membase = ioremap(sb->bar_addr[1], 4096);
|
||||||
|
if (!sb->board_membase) {
|
||||||
|
status = -EIO;
|
||||||
|
printk("WCH Error: ioremap failed !\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb->irq = sb->pdev->irq;
|
||||||
|
if (sb->irq <= 0) {
|
||||||
|
printk(
|
||||||
|
"WCH Error: WCH Board %s Series (bus:%d device:%d), in configuartion space, irq isn't valid !\n\n",
|
||||||
|
sb->pb_info.board_name, sb->bus_number, sb->dev_number);
|
||||||
|
|
||||||
|
status = -EIO;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wch_assign_resource(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
struct wch_ser_port *sp = NULL;
|
||||||
|
int status = 0;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int ser_n;
|
||||||
|
int ser_port_index = 0;
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
printk("%s : %s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(wch_ser_table, 0, (WCH_SER_TOTAL_MAX + 1) * sizeof(struct wch_ser_port));
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
|
||||||
|
if (sb->board_enum > 0) {
|
||||||
|
if (sb->ser_ports > 0) {
|
||||||
|
sb->vector_mask = 0;
|
||||||
|
|
||||||
|
// assign serial port resource
|
||||||
|
ser_n = sb->ser_port_index = ser_port_index;
|
||||||
|
|
||||||
|
sp = &wch_ser_table[ser_n];
|
||||||
|
|
||||||
|
if (sp == NULL) {
|
||||||
|
status = -ENXIO;
|
||||||
|
printk("WCH Error: Serial port table address error !\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < sb->ser_ports; j++, ser_n++, sp++) {
|
||||||
|
sp->port.chip_flag = sb->pb_info.port[j].chip_flag;
|
||||||
|
sp->port.iobase = sb->bar_addr[sb->pb_info.port[j].bar1] + sb->pb_info.port[j].offset1;
|
||||||
|
|
||||||
|
/* use scr reg to test io space */
|
||||||
|
outb(0x55, sp->port.iobase + UART_SCR);
|
||||||
|
if (inb(sp->port.iobase + UART_SCR) != 0x55) {
|
||||||
|
status = -ENXIO;
|
||||||
|
if (j == 0)
|
||||||
|
printk("WCH Error: pci/pcie address error !\n");
|
||||||
|
else
|
||||||
|
printk("WCH Error: ch432/ch438 communication error !\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sb->board_flag & BOARDFLAG_REMAP) == BOARDFLAG_REMAP) {
|
||||||
|
sp->port.vector = 0;
|
||||||
|
} else if ((sb->board_flag & BOARDFLAG_CH384_8_PORTS) == BOARDFLAG_CH384_8_PORTS) {
|
||||||
|
sp->port.chip_iobase = sb->bar_addr[sb->pb_info.port[j].bar1];
|
||||||
|
sp->port.vector = sb->bar_addr[sb->pb_info.intr_vector_bar] + sb->pb_info.intr_vector_offset;
|
||||||
|
} else if ((sb->board_flag & BOARDFLAG_CH384_28_PORTS) == BOARDFLAG_CH384_28_PORTS) {
|
||||||
|
sp->port.chip_iobase = sb->bar_addr[sb->pb_info.port[j].bar1];
|
||||||
|
if (j >= 0 && j < 0x04) {
|
||||||
|
sp->port.vector =
|
||||||
|
sb->bar_addr[sb->pb_info.intr_vector_bar] + sb->pb_info.intr_vector_offset;
|
||||||
|
} else if (j >= 0x04 && j < 0x0C) {
|
||||||
|
sp->port.vector =
|
||||||
|
sb->bar_addr[sb->pb_info.intr_vector_bar] + sb->pb_info.intr_vector_offset_1;
|
||||||
|
} else if (j >= 0x0C && j < 0x14) {
|
||||||
|
sp->port.vector =
|
||||||
|
sb->bar_addr[sb->pb_info.intr_vector_bar] + sb->pb_info.intr_vector_offset_2;
|
||||||
|
} else if (j >= 0x14 && j < 0x1C) {
|
||||||
|
sp->port.vector =
|
||||||
|
sb->bar_addr[sb->pb_info.intr_vector_bar] + sb->pb_info.intr_vector_offset_3;
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
} else if ((sb->board_flag & BOARDFLAG_CH365_32_PORTS) == BOARDFLAG_CH365_32_PORTS) {
|
||||||
|
sp->port.chip_iobase = sb->bar_addr[sb->pb_info.port[j].bar1];
|
||||||
|
sp->port.board_membase = sb->board_membase;
|
||||||
|
if (j >= 0 && j < 0x08) {
|
||||||
|
if (j >= 0 && j < 0x04) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + j * 0x10;
|
||||||
|
}
|
||||||
|
if (j >= 4 && j < 0x08) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + 0x08 + (j - 4) * 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j >= 0x08 && j < 0x10) {
|
||||||
|
if (j >= 0x08 && j < 0x0C) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + 0x80 + (j - 0x08) * 0x10;
|
||||||
|
}
|
||||||
|
if (j >= 0x0C && j < 0x10) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + 0x80 + 0x08 + (j - 0x0C) * 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j >= 0x10 && j < 0x18) {
|
||||||
|
if (j >= 0x10 && j < 0x14) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + 0x100 + (j - 0x10) * 0x10;
|
||||||
|
}
|
||||||
|
if (j >= 0x14 && j < 0x18) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + 0x100 + 0x08 + (j - 0x14) * 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j >= 0x18 && j < 0x20) {
|
||||||
|
if (j >= 0x18 && j < 0x1C) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + 0x180 + (j - 0x18) * 0x10;
|
||||||
|
}
|
||||||
|
if (j >= 0x1C && j < 0x20) {
|
||||||
|
sp->port.port_membase = sb->board_membase + 0x100 + 0x180 + 0x08 + (j - 0x1C) * 0x10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sp->port.vector = sb->bar_addr[sb->pb_info.intr_vector_bar] + sb->pb_info.intr_vector_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb->vector_mask = 0xffffffff;
|
||||||
|
ser_port_index = ser_port_index + sb->ser_ports;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wch_ser_port_table_init(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
struct wch_ser_port *sp = NULL;
|
||||||
|
int status = 0;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
printk("%s : %s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
|
||||||
|
if (sb == NULL) {
|
||||||
|
status = -ENXIO;
|
||||||
|
printk("WCH Error: Board table pointer error !\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sb->board_enum > 0) && (sb->ser_ports > 0)) {
|
||||||
|
n = sb->ser_port_index;
|
||||||
|
sp = &wch_ser_table[n];
|
||||||
|
|
||||||
|
if (sp == NULL) {
|
||||||
|
status = -ENXIO;
|
||||||
|
printk("WCH Error: Serial port table pointer error !\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < sb->ser_ports; j++, n++, sp++) {
|
||||||
|
sp->port.board_enum = sb->board_enum;
|
||||||
|
sp->port.bus_number = sb->bus_number;
|
||||||
|
sp->port.dev_number = sb->dev_number;
|
||||||
|
sp->port.baud_base = CRYSTAL_FREQ * 2 / 16;
|
||||||
|
sp->port.pb_info = sb->pb_info;
|
||||||
|
if (sp->port.chip_flag == WCH_BOARD_CH384_8S) {
|
||||||
|
if (n == sb->ser_port_index)
|
||||||
|
sp->port.bext1stport = true;
|
||||||
|
else
|
||||||
|
sp->port.bext1stport = false;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH384_28S) {
|
||||||
|
if ((n == sb->ser_port_index + 4) || (n == sb->ser_port_index + 12) ||
|
||||||
|
(n == sb->ser_port_index + 20))
|
||||||
|
sp->port.bext1stport = true;
|
||||||
|
else
|
||||||
|
sp->port.bext1stport = false;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH355_4S || sp->port.chip_flag == WCH_BOARD_CH356_4S1P ||
|
||||||
|
sp->port.chip_flag == WCH_BOARD_CH356_6S || sp->port.chip_flag == WCH_BOARD_CH356_8S ||
|
||||||
|
sp->port.chip_flag == WCH_BOARD_CH358_4S1P || sp->port.chip_flag == WCH_BOARD_CH358_8S) {
|
||||||
|
if (n == sb->ser_port_index)
|
||||||
|
sp->port.bext1stport = true;
|
||||||
|
else
|
||||||
|
sp->port.bext1stport = false;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH359_16S) {
|
||||||
|
if ((n == sb->ser_port_index) || (n == sb->ser_port_index + 8))
|
||||||
|
sp->port.bext1stport = true;
|
||||||
|
else
|
||||||
|
sp->port.bext1stport = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sp->port.chip_flag == WCH_BOARD_CH351_2S || sp->port.chip_flag == WCH_BOARD_CH352_1S1P ||
|
||||||
|
sp->port.chip_flag == WCH_BOARD_CH352_2S || sp->port.chip_flag == WCH_BOARD_CH353_2S1P ||
|
||||||
|
sp->port.chip_flag == WCH_BOARD_CH353_2S1PAR || sp->port.chip_flag == WCH_BOARD_CH353_4S) {
|
||||||
|
if (n == sb->ser_port_index)
|
||||||
|
sp->port.bspe1stport = true;
|
||||||
|
else
|
||||||
|
sp->port.bspe1stport = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp->port.irq = sb->irq;
|
||||||
|
sp->port.line = n;
|
||||||
|
sp->port.uartclk = CRYSTAL_FREQ * 2;
|
||||||
|
if (ch365_32s) {
|
||||||
|
sp->port.iotype = WCH_UPIO_MEM;
|
||||||
|
} else {
|
||||||
|
sp->port.iotype = WCH_UPIO_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp->port.ldisc_stop_rx = 0;
|
||||||
|
spin_lock_init(&sp->port.lock);
|
||||||
|
|
||||||
|
if (sp->port.chip_flag == WCH_BOARD_CH351_2S) {
|
||||||
|
sp->port.type = PORT_SER_16550A;
|
||||||
|
sp->port.fifosize = CH351_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH351_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH352_2S || sp->port.chip_flag == WCH_BOARD_CH352_1S1P) {
|
||||||
|
sp->port.type = PORT_SER_16550A;
|
||||||
|
sp->port.fifosize = CH352_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH352_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH353_4S || sp->port.chip_flag == WCH_BOARD_CH353_2S1P ||
|
||||||
|
sp->port.chip_flag == WCH_BOARD_CH353_2S1PAR) {
|
||||||
|
sp->port.type = PORT_SER_16550A;
|
||||||
|
sp->port.fifosize = CH353_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH353_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH355_4S) {
|
||||||
|
sp->port.type = PORT_SER_16550A;
|
||||||
|
sp->port.fifosize = CH355_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH355_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH356_4S1P || sp->port.chip_flag == WCH_BOARD_CH356_6S ||
|
||||||
|
sp->port.chip_flag == WCH_BOARD_CH356_8S) {
|
||||||
|
sp->port.type = PORT_SER_16550A;
|
||||||
|
sp->port.fifosize = CH356_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH356_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH357_4S) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
sp->port.fifosize = CH357_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH357_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH358_4S1P || sp->port.chip_flag == WCH_BOARD_CH358_8S) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
sp->port.fifosize = CH358_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH358_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH359_16S) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
sp->port.fifosize = CH359_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH359_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH382_2S || sp->port.chip_flag == WCH_BOARD_CH382_2S1P) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
sp->port.fifosize = CH382_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH382_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH384_4S || sp->port.chip_flag == WCH_BOARD_CH384_4S1P) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
sp->port.fifosize = CH384_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH384_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH384_8S) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
sp->port.fifosize = CH358_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH358_TRIGGER_LEVEL_SET;
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH384_28S) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
if (j >= 0 && j < 0x04) {
|
||||||
|
sp->port.fifosize = CH384_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH384_TRIGGER_LEVEL_SET;
|
||||||
|
} else {
|
||||||
|
sp->port.fifosize = CH358_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH358_TRIGGER_LEVEL_SET;
|
||||||
|
}
|
||||||
|
} else if (sp->port.chip_flag == WCH_BOARD_CH365_32S) {
|
||||||
|
sp->port.type = PORT_SER_16750;
|
||||||
|
sp->port.fifosize = CH438_FIFOSIZE_SET;
|
||||||
|
sp->port.rx_trigger = CH438_TRIGGER_LEVEL_SET;
|
||||||
|
} else {
|
||||||
|
sp->port.type = PORT_SER_16450;
|
||||||
|
sp->port.fifosize = DEFAULT_FIFOSIZE;
|
||||||
|
sp->port.rx_trigger = DEFAULT_TRIGGER_LEVEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sb->pb_info.board_flag & BOARDFLAG_REMAP) == BOARDFLAG_REMAP) {
|
||||||
|
sp->port.vector_mask = 0;
|
||||||
|
sp->port.port_flag = PORTFLAG_REMAP;
|
||||||
|
} else {
|
||||||
|
sp->port.vector_mask = sb->vector_mask;
|
||||||
|
sp->port.port_flag = PORTFLAG_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp->port.setserial_flag = WCH_SER_BAUD_NOTSETSER;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb->ser_isr = wch_ser_interrupt;
|
||||||
|
} else {
|
||||||
|
sb->ser_isr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
void wch_debug(void)
|
||||||
|
{
|
||||||
|
#if WCH_DBG_BOARD
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WCH_DBG_SERPORT
|
||||||
|
struct wch_ser_port *sp = NULL;
|
||||||
|
int j;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WCH_DBG_BOARD
|
||||||
|
printk("\n");
|
||||||
|
printk("======== board info ========\n");
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
if (sb->board_enum != -1) {
|
||||||
|
printk(" name : %s\n", sb->pb_info.board_name);
|
||||||
|
printk(" board_enum : %d\n", sb->board_enum);
|
||||||
|
printk(" board_number : %d\n", sb->board_number);
|
||||||
|
printk(" irq : %d\n", sb->irq);
|
||||||
|
printk(" vector_mask : 0x%x\n", sb->vector_mask);
|
||||||
|
printk(" bar[0] : 0x%lx\n", sb->bar_addr[0]);
|
||||||
|
printk(" bar[1] : 0x%lx\n", sb->bar_addr[1]);
|
||||||
|
printk(" bar[2] : 0x%lx\n", sb->bar_addr[2]);
|
||||||
|
printk(" bar[3] : 0x%lx\n", sb->bar_addr[3]);
|
||||||
|
printk(" bar[4] : 0x%lx\n", sb->bar_addr[4]);
|
||||||
|
printk(" bar[5] : 0x%lx\n", sb->bar_addr[5]);
|
||||||
|
printk("----------------------------\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printk("============================\n");
|
||||||
|
printk("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WCH_DBG_SERPORT
|
||||||
|
printk("\n");
|
||||||
|
printk("======== serial info ========\n");
|
||||||
|
for (j = 0; j < wch_ser_port_total_cnt; j++) {
|
||||||
|
sp = &wch_ser_table[j];
|
||||||
|
if (sp->port.iobase) {
|
||||||
|
printk(" number : %d\n", j);
|
||||||
|
printk(" name : %s\n", sp->port.pb_info.board_name);
|
||||||
|
printk(" iobase : 0x%lx\n", sp->port.iobase);
|
||||||
|
printk(" chip_iobase : 0x%x\n", sp->port.chip_iobase);
|
||||||
|
printk(" irq : %d\n", sp->port.irq);
|
||||||
|
printk(" vector : 0x%lx\n", sp->port.vector);
|
||||||
|
printk(" vector_mask : 0x%x\n", sp->port.vector_mask);
|
||||||
|
printk(" chip_flag : 0x%x\n", sp->port.chip_flag);
|
||||||
|
printk(" port_flag : 0x%x\n", sp->port.port_flag);
|
||||||
|
printk("----------------------------\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printk("============================\n");
|
||||||
|
printk("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WCH_DBG_SERIAL
|
||||||
|
void ch365_32s_test(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
int i;
|
||||||
|
dbg_serial("\n");
|
||||||
|
dbg_serial("======== board info ========\n");
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
if (sb->board_enum != -1) {
|
||||||
|
dbg_serial(" ch438_1_uart0 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05));
|
||||||
|
dbg_serial(" ch438_1_uart1 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x08));
|
||||||
|
dbg_serial(" ch438_1_uart2 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x10));
|
||||||
|
dbg_serial(" ch438_1_uart3 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x18));
|
||||||
|
dbg_serial(" ch438_1_uart4 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x20));
|
||||||
|
dbg_serial(" ch438_1_uart5 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x28));
|
||||||
|
dbg_serial(" ch438_1_uart6 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x30));
|
||||||
|
dbg_serial(" ch438_1_uart7 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x38));
|
||||||
|
dbg_serial("----------------------------\n");
|
||||||
|
dbg_serial(" ch438_2_uart0 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x80));
|
||||||
|
dbg_serial(" ch438_2_uart1 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x08 + 0x80));
|
||||||
|
dbg_serial(" ch438_2_uart2 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x10 + 0x80));
|
||||||
|
dbg_serial(" ch438_2_uart3 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x18 + 0x80));
|
||||||
|
dbg_serial(" ch438_2_uart4 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x20 + 0x80));
|
||||||
|
dbg_serial(" ch438_2_uart5 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x28 + 0x80));
|
||||||
|
dbg_serial(" ch438_2_uart6 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x30 + 0x80));
|
||||||
|
dbg_serial(" ch438_2_uart7 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x38 + 0x80));
|
||||||
|
dbg_serial("----------------------------\n");
|
||||||
|
dbg_serial(" ch438_3_uart0 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x100));
|
||||||
|
dbg_serial(" ch438_3_uart1 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x08 + 0x100));
|
||||||
|
dbg_serial(" ch438_3_uart2 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x10 + 0x100));
|
||||||
|
dbg_serial(" ch438_3_uart3 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x18 + 0x100));
|
||||||
|
dbg_serial(" ch438_3_uart4 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x20 + 0x100));
|
||||||
|
dbg_serial(" ch438_3_uart5 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x28 + 0x100));
|
||||||
|
dbg_serial(" ch438_3_uart6 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x30 + 0x100));
|
||||||
|
dbg_serial(" ch438_3_uart7 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x38 + 0x100));
|
||||||
|
dbg_serial("----------------------------\n");
|
||||||
|
dbg_serial(" ch438_4_uart0 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x180));
|
||||||
|
dbg_serial(" ch438_4_uart1 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x08 + 0x180));
|
||||||
|
dbg_serial(" ch438_4_uart2 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x10 + 0x180));
|
||||||
|
dbg_serial(" ch438_4_uart3 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x18 + 0x180));
|
||||||
|
dbg_serial(" ch438_4_uart4 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x20 + 0x180));
|
||||||
|
dbg_serial(" ch438_4_uart5 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x28 + 0x180));
|
||||||
|
dbg_serial(" ch438_4_uart6 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x30 + 0x180));
|
||||||
|
dbg_serial(" ch438_4_uart7 LSR = %x\n", readb(sb->board_membase + 0x100 + 0x05 + 0x38 + 0x180));
|
||||||
|
dbg_serial("----------------------------\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbg_serial("============================\n");
|
||||||
|
dbg_serial("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int wch_register_irq(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
int status = 0;
|
||||||
|
int i;
|
||||||
|
unsigned long chip_iobase;
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
printk("%s : %s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
|
||||||
|
if (sb == NULL) {
|
||||||
|
status = -ENXIO;
|
||||||
|
printk("WCH Error: Board table pointer error !\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb->board_enum > 0) {
|
||||||
|
status = request_irq(sb->irq, wch_interrupt, IRQF_SHARED, "wch", sb);
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
printk("WCH Error: WCH Multi-I/O %s Board(bus:%d device:%d), request\n", sb->pb_info.board_name,
|
||||||
|
sb->bus_number, sb->dev_number);
|
||||||
|
printk(" IRQ %d fail, IRQ %d may be conflit with another device.\n", sb->irq, sb->irq);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch365_32s) {
|
||||||
|
outb(inb(sb->bar_addr[0] + 0xF8) & 0xFE, sb->bar_addr[0] + 0xF8);
|
||||||
|
outb(((inb(sb->bar_addr[0] + 0xFA) & 0xFB) | 0x03),
|
||||||
|
sb->bar_addr[0] + 0xFA); // set read/write plus width 240ns->120ns
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((sb->board_flag & BOARDFLAG_CH384_8_PORTS) == BOARDFLAG_CH384_8_PORTS) ||
|
||||||
|
((sb->board_flag & BOARDFLAG_CH384_28_PORTS) == BOARDFLAG_CH384_28_PORTS)) {
|
||||||
|
chip_iobase = sb->bar_addr[0];
|
||||||
|
if (chip_iobase) {
|
||||||
|
outb(inb(chip_iobase + 0xEB) | 0x02, chip_iobase + 0xEB);
|
||||||
|
/* set read/write plus width 120ns->210ns */
|
||||||
|
outb(inb(chip_iobase + 0xFA) | 0x10, chip_iobase + 0xFA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wch_iounmap(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
printk("%s : %s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
|
||||||
|
if (sb->board_enum > 0) {
|
||||||
|
iounmap(sb->board_membase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wch_release_irq(void)
|
||||||
|
{
|
||||||
|
struct wch_board *sb = NULL;
|
||||||
|
int i;
|
||||||
|
unsigned long chip_iobase;
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
printk("%s : %s\n", __FILE__, __FUNCTION__);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < WCH_BOARDS_MAX; i++) {
|
||||||
|
sb = &wch_board_table[i];
|
||||||
|
|
||||||
|
if (sb->board_enum > 0) {
|
||||||
|
free_irq(sb->irq, sb);
|
||||||
|
}
|
||||||
|
if (ch365_32s) {
|
||||||
|
outb(inb(sb->bar_addr[0] + 0xF8) | 0x01, sb->bar_addr[0] + 0xF8);
|
||||||
|
}
|
||||||
|
if (((sb->board_flag & BOARDFLAG_CH384_8_PORTS) == BOARDFLAG_CH384_8_PORTS) ||
|
||||||
|
((sb->board_flag & BOARDFLAG_CH384_28_PORTS) == BOARDFLAG_CH384_28_PORTS)) {
|
||||||
|
chip_iobase = sb->bar_addr[0];
|
||||||
|
if (chip_iobase)
|
||||||
|
outb(inb(chip_iobase + 0xEB) & 0xFD, chip_iobase + 0xEB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ser_driver wch_ser_reg = {
|
||||||
|
.dev_name = "ttyWCH",
|
||||||
|
.major = WCH_TTY_MAJOR,
|
||||||
|
.minor = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
int wch_35x_init(void)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
printk("\n\n");
|
||||||
|
printk("===================== WCH Device Driver Module Install =====================\n");
|
||||||
|
printk("\n");
|
||||||
|
printk("WCH Info : Loading WCH Multi-I/O Board Driver Module\n");
|
||||||
|
printk(" -- Date : %s\n", WCH_DRIVER_DATE);
|
||||||
|
printk(" -- Version : %s\n\n", WCH_DRIVER_VERSION);
|
||||||
|
|
||||||
|
wch_ser_port_total_cnt = 0;
|
||||||
|
|
||||||
|
status = wch_pci_board_probe();
|
||||||
|
if (status != 0) {
|
||||||
|
goto step1_fail;
|
||||||
|
}
|
||||||
|
printk("------------------->pci board probe success\n");
|
||||||
|
status = wch_get_pci_board_conf();
|
||||||
|
if (status != 0) {
|
||||||
|
goto step1_fail;
|
||||||
|
}
|
||||||
|
printk("------------------->pci board conf success\n");
|
||||||
|
|
||||||
|
status = wch_assign_resource();
|
||||||
|
if (status != 0) {
|
||||||
|
goto step1_fail;
|
||||||
|
}
|
||||||
|
printk("------------------->pci assign success\n");
|
||||||
|
|
||||||
|
status = wch_ser_port_table_init();
|
||||||
|
if (status != 0) {
|
||||||
|
goto step1_fail;
|
||||||
|
}
|
||||||
|
printk("------------------->ser port table init success\n");
|
||||||
|
|
||||||
|
status = wch_register_irq();
|
||||||
|
if (status != 0) {
|
||||||
|
goto step1_fail;
|
||||||
|
}
|
||||||
|
printk("------------------->pci register irq success\n");
|
||||||
|
|
||||||
|
status = wch_ser_register_driver(&wch_ser_reg);
|
||||||
|
if (status != 0) {
|
||||||
|
goto step2_fail;
|
||||||
|
}
|
||||||
|
printk("------------------->ser register driver success\n");
|
||||||
|
|
||||||
|
status = wch_ser_register_ports(&wch_ser_reg);
|
||||||
|
if (status != 0) {
|
||||||
|
goto step3_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WCH_DBG
|
||||||
|
wch_debug();
|
||||||
|
// ch365_32s_test();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printk("================================================================================\n");
|
||||||
|
return status;
|
||||||
|
|
||||||
|
step3_fail:
|
||||||
|
|
||||||
|
wch_ser_unregister_driver(&wch_ser_reg);
|
||||||
|
|
||||||
|
step2_fail:
|
||||||
|
|
||||||
|
wch_release_irq();
|
||||||
|
|
||||||
|
step1_fail:
|
||||||
|
|
||||||
|
printk("WCH Error: Couldn't Loading WCH Multi-I/O Board Driver Module correctly,\n");
|
||||||
|
printk(" please reboot system and try again. If still can't loading driver,\n");
|
||||||
|
printk(" contact support.\n\n");
|
||||||
|
printk("================================================================================\n");
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wch_35x_exit(void)
|
||||||
|
{
|
||||||
|
printk("\n\n");
|
||||||
|
printk("==================== WCH Device Driver Module Uninstall ====================\n");
|
||||||
|
printk("\n");
|
||||||
|
|
||||||
|
wch_ser_unregister_ports(&wch_ser_reg);
|
||||||
|
printk("***********wch_ser_unregister_ports***************\n");
|
||||||
|
wch_ser_unregister_driver(&wch_ser_reg);
|
||||||
|
printk("***********wch_ser_unregister_driver_success***********\n");
|
||||||
|
wch_iounmap();
|
||||||
|
wch_release_irq();
|
||||||
|
printk("WCH Info : Unload WCH Multi-I/O Board Driver Module Done.\n");
|
||||||
|
printk("================================================================================\n");
|
||||||
|
}
|
||||||
119
drivers/tty/serial/wch_35x/wch_pre_main.c
Normal file
119
drivers/tty/serial/wch_35x/wch_pre_main.c
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* PCI/PCIe to serial driver(pre) for ch351/352/353/355/356/357/358/359/382/384, etc.
|
||||||
|
* This driver only needs to be used when the system does not assign an interrupt number for device.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||||
|
* Web: http://wch.cn
|
||||||
|
* Author: WCH <tech@wch.cn>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Update Log:
|
||||||
|
* V1.00 - initial version
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
|
#include "wch_common.h"
|
||||||
|
|
||||||
|
#define WCH_PRE_DRIVER_AUTHOR "WCH GROUP"
|
||||||
|
#define WCH_PRE_DRIVER_DESC "WCH Multi-I/O Board Driver Module(pre)"
|
||||||
|
|
||||||
|
#define VENDOR_ID_WCH_PCIE 0x1C00
|
||||||
|
#define SUB_VENDOR_ID_WCH_PCIE 0x1C00
|
||||||
|
#define VENDOR_ID_WCH_PCI 0x4348
|
||||||
|
#define SUB_VENDOR_ID_WCH_PCI 0x4348
|
||||||
|
#define VENDOR_ID_WCH_CH351 0x1C00
|
||||||
|
#define SUB_VENDOR_ID_WCH_CH351 0x1C00
|
||||||
|
#define DEVICE_ID_WCH_CH351_2S 0x2273
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH351_2S 0x2273
|
||||||
|
#define DEVICE_ID_WCH_CH352_1S1P 0x5053
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH352_1S1P 0x5053
|
||||||
|
#define DEVICE_ID_WCH_CH352_2S 0x3253
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH352_2S 0x3253
|
||||||
|
#define DEVICE_ID_WCH_CH353_4S 0x3453
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH353_4S 0x3453
|
||||||
|
#define DEVICE_ID_WCH_CH353_2S1P 0x7053
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH353_2S1P 0x3253
|
||||||
|
#define DEVICE_ID_WCH_CH353_2S1PAR 0x5046
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH353_2S1PAR 0x5046
|
||||||
|
#define DEVICE_ID_WCH_CH355_4S 0x7173
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH355_4S 0x3473
|
||||||
|
#define DEVICE_ID_WCH_CH356_4S1P 0x7073
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH356_4S1P 0x3473
|
||||||
|
#define DEVICE_ID_WCH_CH356_6S 0x3873
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH356_6S 0x3873
|
||||||
|
#define DEVICE_ID_WCH_CH356_8S 0x3853
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH356_8S 0x3853
|
||||||
|
#define DEVICE_ID_WCH_CH357_4S 0x5334
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH357_4S 0x5053
|
||||||
|
#define DEVICE_ID_WCH_CH358_4S1P 0x5334
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH358_4S1P 0x5334
|
||||||
|
#define DEVICE_ID_WCH_CH358_8S 0x5338
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH358_8S 0x5338
|
||||||
|
#define DEVICE_ID_WCH_CH359_16S 0x5838
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH359_16S 0x5838
|
||||||
|
#define DEVICE_ID_WCH_CH382_2S 0x3253
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH382_2S 0x3253
|
||||||
|
#define DEVICE_ID_WCH_CH382_2S1P 0x3250
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH382_2S1P 0x3250
|
||||||
|
#define DEVICE_ID_WCH_CH384_4S 0x3470
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_4S 0x3470
|
||||||
|
#define DEVICE_ID_WCH_CH384_4S1P 0x3450
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_4S1P 0x3450
|
||||||
|
#define DEVICE_ID_WCH_CH384_8S 0x3853
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_8S 0x3853
|
||||||
|
#define DEVICE_ID_WCH_CH384_28S 0x4353
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH384_28S 0x4353
|
||||||
|
#define DEVICE_ID_WCH_CH365_32S 0x5049
|
||||||
|
#define SUB_DEVICE_ID_WCH_CH365_32S 0x5049
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probe to serial board.
|
||||||
|
*/
|
||||||
|
static int wch_probe(struct pci_dev *dev, const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
printk("\n====================WCH Device Driver(pre) Module probe====================\n");
|
||||||
|
printk("Probe Device VID: %4x, PID: 0x%4x\n", dev->vendor, dev->device);
|
||||||
|
|
||||||
|
wch_35x_init();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wch_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
printk("\n====================WCH Device Driver(pre) Module exit====================\n");
|
||||||
|
printk("Remove Device VID: %4x, PID: 0x%4x\n", dev->vendor, dev->device);
|
||||||
|
wch_35x_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver wchserial_pci_driver = {
|
||||||
|
.name = "wchpciserial",
|
||||||
|
.probe = wch_probe,
|
||||||
|
.remove = wch_remove,
|
||||||
|
.id_table = wch_pci_board_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_pci_driver(wchserial_pci_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR(WCH_PRE_DRIVER_AUTHOR);
|
||||||
|
MODULE_DESCRIPTION(WCH_PRE_DRIVER_DESC);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
2973
drivers/tty/serial/wch_35x/wch_serial.c
Normal file
2973
drivers/tty/serial/wch_35x/wch_serial.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user