Transform Fintek PCIE driver from 8250 to MFD
Subsystems (3)
v4 cover Transform Fintek PCIE driver from 8250 to MFD
The Fintek F81504/508/512 is a multi-function PCIE devices. IC function list:
F81504: Max 2x8 GPIOs and max 4 serial ports
port2/3 are multi-function
F81508: Max 6x8 GPIOs and max 8 serial ports
port2/3 are multi-function, port8/9/10/11 are gpio only
F81512: Max 6x8 GPIOs and max 12 serial ports
port2/3/8/9/10/11 are multi-function
It had implemented in 8250_pci.c with basic serial port function. We want to complete it. Alan & Andy recommend us to rewrite and spilt our driver with MFD architecture.
https://lkml.org/lkml/2016/1/19/288
Paul recommed us do less code deletion to avoid confusing problem when bisect.
https://lkml.org/lkml/2016/1/18/646
So we'll do this with following patches.
1. Add MFD core driver.
2. Add GPIOLIB driver.
3. Add serial port driver.
4. Remove old driver in 8250_pci.c and add it to blacklist
8250_pci.c will still handle the device when patches 1~3. After apply patch 4, the device will control by F81504 MFD core driver.
Changelog:
V4:
1. Fix the comment style
2. Fix the warning (.owner = THIS_MODULE) reported by kbuild bot with f81504_core.c & 8250_f81504.c
3. Remove unused Kconfig option (RATIONAL) with 8250_f81504.c
4. Remove unused variable (quot/rem) with f81504_check_baudrate() in 8250_f81504.c
V3:
1. Refactoring gpio-f81504.c with new API
(Suggested by Linus Walleij).
2. Fix wrong kfree in gpio-f81504.c (Suggested by Andy Shevchenko).
3. Get PCI resource by pci_resource_start() instead of getting PCI resource from BAR of PCI configuration space (Suggested by Alan).
V2:
1. Split F81504/508/512 from 8250_pci.c to MFD, It'll add 3 new files
1. drivers/mfd/f81504-core.c
2. drivers/gpio/gpio-f81504.c
3. drivers/tty/serial/8250/8250_f81504.c
V1:
1. Split F81504/508/512 from 8250_pci.c to 8250_fintek_pci.c. Alan & Andy recommend me to rewrite as MFD architecture.
Peter Hung (4):
mfd: f81504-core: Add Fintek F81504/508/512 PCIE-to-UART/GPIO core
support
gpio: gpio-f81504: Add Fintek F81504/508/512 PCIE-to-UART/GPIO GPIOLIB
support
8250: 8250_f81504: Add Fintek F81504/508/512 PCIE-to-UART/GPIO UART
support
serial: 8250_pci: Remove Fintek F81504/508/512 UART driver
drivers/gpio/Kconfig | 10 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-f81504.c | 241 ++++++++++++++++++++++++ drivers/mfd/Kconfig | 12 ++ drivers/mfd/Makefile | 2 + drivers/mfd/f81504-core.c | 335 ++++++++++++++++++++++++++++++++++ drivers/tty/serial/8250/8250_f81504.c | 250 +++++++++++++++++++++++++ drivers/tty/serial/8250/8250_pci.c | 206 +-------------------- drivers/tty/serial/8250/Kconfig | 10 + drivers/tty/serial/8250/Makefile | 1 + include/linux/mfd/f81504.h | 52 ++++++ 11 files changed, 919 insertions(+), 201 deletions(-) create mode 100644 drivers/gpio/gpio-f81504.c create mode 100644 drivers/mfd/f81504-core.c create mode 100644 drivers/tty/serial/8250/8250_f81504.c create mode 100644 include/linux/mfd/f81504.h
Signature · 1 line
1.9.1
PATCH v4 1/4 mfd: f81504-core: Add Fintek F81504/508/512 PCIE-to-UART/GPIO core support
The Fintek F81504/508/512 had implemented the basic serial port function in 8250_pci.c. We try to implement high baudrate & GPIOLIB with a spilt file 8250_f81504.c, but it seems too complex to add GPIOLIB.
Alan & Andy recommend us to rewrite and spilt our driver with MFD architecture.
https://lkml.org/lkml/2016/1/19/288
This driver is core driver for F81504/508/512, it'll handle the generation of UART/GPIO platform device and initialize PCIE configuration space when probe()/resume().
IC function list:
F81504: Max 2x8 GPIOs and max 4 serial ports
port2/3 are multi-function
F81508: Max 6x8 GPIOs and max 8 serial ports
port2/3 are multi-function, port8/9/10/11 are gpio only
F81512: Max 6x8 GPIOs and max 12 serial ports
port2/3/8/9/10/11 are multi-function
H/W provider could changes the PCI configure space F0/F3h values in EEPROM or ASL code to change mode.
F0h bit0~5: Enable GPIO0~5
bit6~7: Reserve
F3h bit0~5: Multi-Functional Flag (0:GPIO/1:UART)
bit0: UART2 pin out for UART2 / GPIO0
bit1: UART3 pin out for UART3 / GPIO1
bit2: UART8 pin out for UART8 / GPIO2
bit3: UART9 pin out for UART9 / GPIO3
bit4: UART10 pin out for UART10 / GPIO4
bit5: UART11 pin out for UART11 / GPIO5 bit6~7: Reserve
--- drivers/mfd/Kconfig | 12 ++ drivers/mfd/Makefile | 2 + drivers/mfd/f81504-core.c | 335 +++++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/f81504.h | 52 +++++++ 4 files changed, 401 insertions(+) create mode 100644 drivers/mfd/f81504-core.c create mode 100644 include/linux/mfd/f81504.h
drivers/mfd/Kconfig +12 -0
@@ -345,6 +345,18 @@ config HTC_I2CPLD This device provides input and output GPIOs through an I2C interface to one or more sub-chips. +config MFD_FINTEK_F81504_CORE + tristate "Fintek F81504/508/512 PCIE-to-UART/GPIO MFD support" + depends on PCI + select MFD_CORE + default SERIAL_8250 + help + This driver provides the F81504/508/512 UART & GPIO platform + devices. You should enable CONFIG_GPIO_F81504 to get GPIOLIB + support and CONFIG_8250_F81504 to get serial port support. + This driver needs to be built into the kernel to use early + console support. + config MFD_INTEL_QUARK_I2C_GPIO tristate "Intel Quark MFD I2C GPIO" depends on PCI
drivers/mfd/Makefile +2 -0
@@ -22,6 +22,8 @@ obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o +obj-$(CONFIG_MFD_FINTEK_F81504_CORE) += f81504-core.o + obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o
drivers/mfd/f81504-core.c new file +335 -0
335 lines not on this page · raw message
include/linux/mfd/f81504.h new file +52 -0
52 lines not on this page · raw message
Signature · 1 line
1.9.1
Re: [PATCH V4 1/4] mfd: f81504-core: Add Fintek F81504/508/512 PCIE-to-UART/GPIO core support
Quoted 5 lines · Peter Hung
The Fintek F81504/508/512 had implemented the basic serial port function in
8250_pci.c. We try to implement high baudrate & GPIOLIB with a spilt file8250_f81504.c, but it seems too complex to add GPIOLIB.
[...]
Quoted 4 lines
drivers/mfd/Kconfig +0
-0@@ -345,6 +345,18 @@ config HTC_I2CPLDThis device provides input and output GPIOs through an I2C
Quoted 8 lines
interface to one or more sub-chips.
+configMFD_FINTEK_F81504_CORE
+ tristate "Fintek F81504/508/512 PCIE-to-UART/GPIO MFD support"
+ depends on PCI
+ selectMFD_CORE
+ defaultSERIAL_8250
SERIAL_8250_PCI ?
Quoted 15 lines
drivers/mfd/Kconfig +7
-0+static bool f81504_is_gpio(unsigned int idx, u8 gpio_en) +{ + unsigned int i; + + /* Find every port to check is multi-function port */ + for (i = 0; i < ARRAY_SIZE(fintek_gpio_mapping); i++) { + if (fintek_gpio_mapping[i] != idx || !(gpio_en &BIT(i)))
drivers/mfd/Kconfig +4
-0+ continue; + + /* + * This port is multi-function and enabled as gpiomode.
drivers/mfd/Kconfig
Quoted 3 lines
drivers/mfd/Kconfig +3
-0+ * So we'll not configure it as serial port. + */ + return true;
Perhaps
if (fintek_gpio_mapping[i] == idx && (gpio_en & BIT(i))) return true;
?
Quoted 4 lines
drivers/mfd/Kconfig +4
-0+ } + + return false; +}
Signature · 2 lines
Andy Shevchenko <[email protected]> Intel Finland Oy
Re: [PATCH V4 1/4] mfd: f81504-core: Add Fintek F81504/508/512 PCIE-to-UART/GPIO core support
Hi Andy,
Andy Shevchenko 於 2016/2/23 下午 07:05 寫道:
Quoted 9 lines · Peter Hung
drivers/mfd/Kconfig config HTC_I2CPLD · line 352
Quoted 6 lines
(quoted diff) +2
-0+config MFD_FINTEK_F81504_CORE + tristate "Fintek F81504/508/512 PCIE-to-UART/GPIO MFDsupport"
drivers/mfd/Kconfig +3
-0+ depends on PCI + select MFD_CORE + default SERIAL_8250
SERIAL_8250_PCI?
In my opinion, 8250_pci & f81504_core are independently drivers. So I'll set the default to SERIAL_8250.
Quoted 21 lines
Quoted 15 lines
drivers/mfd/f81504-core.c new file +7
-0+static bool f81504_is_gpio (unsigned int idx,u8 gpio_en) +{ +unsigned int i; + +/* Find every port to check is multi-function port */ +for (i =0 ; i <ARRAY_SIZE (fintek_gpio_mapping); i++) { + if (fintek_gpio_mapping[i] != idx || !(gpio_en &BIT(i)))
drivers/mfd/f81504-core.c new file +4
-0+continue ; + +/* +* This port is multi-function and enabled as gpio mode.
drivers/mfd/f81504-core.c line 30
Quoted 3 lines
drivers/mfd/f81504-core.c new file +3
-0+* So we'll not configure it as serial port. +*/ +return true;Perhaps
Quoted 2 lines
if (fintek_gpio_mapping[i] == idx && (
gpio_en& BIT(i)))
return true;
Your code is more simple and readable. I'll change it for V5
Thanks for your advices.
Signature · 6 lines
With Best Regards, Peter Hung -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v4 2/4 gpio: gpio-f81504: Add Fintek F81504/508/512 PCIE-to-UART/GPIO GPIOLIB support
In reply to Peter HungThis driver is GPIOLIB driver for F81504/508/512, it'll handle the GPIOLIB operation of this device. This module will depend on MFD_FINTEK_F81504_CORE.
IC function list:
F81504: Max 2x8 GPIOs and max 4 serial ports
port2/3 are multi-function
F81508: Max 6x8 GPIOs and max 8 serial ports
port2/3 are multi-function, port8/9/10/11 are gpio only
F81512: Max 6x8 GPIOs and max 12 serial ports
port2/3/8/9/10/11 are multi-function
GPIO register:
PCI Configuration space:
F0h: bit0~5: Enable GPIO0~5
bit6~7: Reserve
F3h: bit0~5: Multi-Functional Flag (0:GPIO/1:UART)
bit0: UART2 pin out for UART2 / GPIO0
bit1: UART3 pin out for UART3 / GPIO1
bit2: UART8 pin out for UART8 / GPIO2
bit3: UART9 pin out for UART9 / GPIO3
bit4: UART10 pin out for UART10 / GPIO4
bit5: UART11 pin out for UART11 / GPIO5 bit6~7: Reserve
F1h: IO address (LSB)
F2h: IO address (MSB)
F8h + 8 * set: Direction control (bitwise)
bitx: 0 - Input mode
bitx: 1 - Output mode
F9h + 8 * set: Drive ability control (bitwise)
bitx: 0 - Open drain (default)
bitx: 1 - Push Pull
In this driver, we only implements open drain mode.
IO space:
(IO base + 0~5): GPIO-0x~5x in/out value (bitwise)
--- drivers/gpio/Kconfig | 10 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-f81504.c | 241 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 drivers/gpio/gpio-f81504.c
drivers/gpio/Kconfig +10 -0
@@ -912,6 +912,16 @@ config GPIO_WM8994 Say yes here to access the GPIO signals of WM8994 audio hub CODECs from Wolfson Microelectronics. +config GPIO_F81504 + tristate "Fintek F81504/508/512 PCIE-to-UART/GPIO support" + depends on MFD_FINTEK_F81504_CORE + select MFD_CORE + help + Say yes here to support the GPIO functionality of Fintek + F81504/508/512 PCIE-to-UART/GPIO. + + If unsure, say N. + endmenu menu "PCI GPIO expanders"
drivers/gpio/Makefile +1 -0
@@ -112,6 +112,7 @@ obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o +obj-$(CONFIG_GPIO_F81504) += gpio-f81504.o obj-$(CONFIG_GPIO_XGENE) += gpio-xgene.o obj-$(CONFIG_GPIO_XGENE_SB) += gpio-xgene-sb.o obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
drivers/gpio/gpio-f81504.c new file +241 -0
241 lines not on this page · raw message
Signature · 1 line
1.9.1
Re: [PATCH V4 2/4] gpio: gpio-f81504: Add Fintek F81504/508/512 PCIE-to-UART/GPIO GPIOLIB support
Quoted 34 lines · Peter Hung
This driver is GPIOLIB driver for F81504/508/512, it'll handle the GPIOLIB operation of this device. This module will depend on
MFD_FINTEK_F81504_CORE.IC function list:
F81504: Max 2x8 GPIOs and max 4 serial ports
port2/3 are multi-function
F81508: Max 6x8 GPIOs and max 8 serial ports
port2/3 are multi-function, port8/9/10/11 are gpio only
F81512: Max 6x8 GPIOs and max 12 serial ports
port2/3/8/9/10/11 are multi-functionGPIO register:
PCI Configuration space:
F0h: bit0~5: Enable GPIO0~5
bit6~7: Reserve
F3h: bit0~5: Multi-Functional Flag (0:GPIO/1:UART)
bit0: UART2 pin out for UART2 / GPIO0
bit1: UART3 pin out for UART3 / GPIO1
bit2: UART8 pin out for UART8 / GPIO2
bit3: UART9 pin out for UART9 / GPIO3
bit4: UART10 pin out for UART10 / GPIO4
bit5: UART11 pin out for UART11 / GPIO5 bit6~7: Reserve
F1h: IO address (LSB)
F2h: IO address (MSB)
F8h + 8 * set: Direction control (bitwise)
bitx: 0 - Input mode
bitx: 1 - Output mode
F9h + 8 * set: Drive ability control (bitwise)
bitx: 0 - Open drain (default)
bitx: 1 - Push Pull
In this driver, we only implements open drain mode.
Quoted 6 lines
IO space:
(IO base + 0~5): GPIO-0x~5x in/out value (bitwise)Suggested-by One Thousand Gnomes <[email protected]>Suggested-by Andy Shevchenko <[email protected]>Signed-off-by Peter Hung <[email protected]>
I assume this must do in through the MFD or TTY tree with the rest. There is a new devm_gpiochip_add_data() coming into the GPIO tree but we can patch it to use that later. (Note to Laxman to revisit...)
Yours,
Linus Walleij
PATCH v4 3/4 8250: 8250_f81504: Add Fintek F81504/508/512 PCIE-to-UART/GPIO UART support
In reply to Peter HungThis driver is 8250 driver for F81504/508/512, it'll handle the serial port operation of this device. This module will depend on MFD_FINTEK_F81504_CORE.
The serial ports support from 50bps to 1.5Mbps with Linux baudrate define excluding 1.0Mbps due to not support 16MHz clock source.
PCI Configuration Space Registers, set:0~11(Max):
40h + 8 * set:
bit7~6: Clock source selector
00: 1.8432MHz
01: 18.432MHz
10: 24MHz
11: 14.769MHz
bit0: UART enable
41h + 8 * set:
bit5~4: RX trigger multiple
00: 1x * trigger level
01: 2x * trigger level
10: 4x * trigger level
11: 8x * trigger level
bit1~0: FIFO Size
11: 128Bytes
44h + 8 * set: UART IO address (LSB)
45h + 8 * set: UART IO address (MSB)
47h + 8 * set:
bit5: RTS invert (bit4 must enable)
bit4: RTS auto direction enable
0: RTS control by MCR
1: RTS driven high when TX, otherwise low
--- drivers/tty/serial/8250/8250_f81504.c | 250 ++++++++++++++++++++++++++++++++++ drivers/tty/serial/8250/Kconfig | 10 ++ drivers/tty/serial/8250/Makefile | 1 + 3 files changed, 261 insertions(+) create mode 100644 drivers/tty/serial/8250/8250_f81504.c
drivers/tty/serial/8250/8250_f81504.c new file +250 -0
@@ -0,0 +1,250 @@ +#include <linux/pci.h> +#include <linux/serial_8250.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/mfd/f81504.h> + +#include "8250.h" + +static u32 baudrate_table[] = {1500000 ,1152000 ,921600 }; +static u8 clock_table[] = {F81504_CLKSEL_24_MHZ ,F81504_CLKSEL_18_46_MHZ , +F81504_CLKSEL_14_77_MHZ }; + +/* We should do proper H/W transceiver setting before change to RS485 mode */ +static int f81504_rs485_config (struct uart_port *port, +struct serial_rs485 *rs485) +{ +u8 setting; +u8 *index = port->private_data; +struct platform_device *pdev =container_of (port->dev, + struct platform_device, dev); +struct pci_dev *pci_dev =to_pci_dev (pdev->dev.parent); + +pci_read_config_byte (pci_dev,F81504_UART_START_ADDR + +F81504_UART_OFFSET * *index +F81504_UART_MODE_OFFSET , + &setting); + +if (!rs485) + rs485 = &port->rs485; +else if (rs485->flags &SER_RS485_ENABLED ) +memset (rs485->padding,0 ,sizeof (rs485->padding)); +else +memset (rs485,0 ,sizeof (*rs485)); + +/* F81504/508/512 not support RTS delay before or after send */ + rs485->flags &=SER_RS485_ENABLED |SER_RS485_RTS_ON_SEND ; + +if (rs485->flags &SER_RS485_ENABLED ) { +/* Enable RTS H/W control mode */ + setting |=F81504_RTS_CONTROL_BY_HW ; + +if (rs485->flags &SER_RS485_RTS_ON_SEND ) { +/* RTS driving high on TX */ + setting &= ~F81504_RTS_INVERT ; + }else { +/* RTS driving low on TX */ + setting |=F81504_RTS_INVERT ; + } + + rs485->delay_rts_after_send =0 ; + rs485->delay_rts_before_send =0 ; + }else { +/* Disable RTS H/W control mode */ + setting &= ~(F81504_RTS_CONTROL_BY_HW |F81504_RTS_INVERT ); + } + +pci_write_config_byte (pci_dev,F81504_UART_START_ADDR + +F81504_UART_OFFSET * *index +F81504_UART_MODE_OFFSET , + setting); + +if (rs485 != &port->rs485) + port->rs485 = *rs485; + +return 0 ; +} + +static int f81504_check_baudrate (u32 baud,size_t *idx) +{ +size_t index; + +for (index =0 ; index <ARRAY_SIZE (baudrate_table); ++index) { +/* Clock source must larger than desire baud rate */ +if (baud > baudrate_table[index]) +continue ; + +/* Find divisible clock source */ +if (!(baudrate_table[index] % baud)) { +if (idx) + *idx = index; +return 0 ; + } + } + +return -EINVAL ; +} + +static void f81504_set_termios (struct uart_port *port, +struct ktermios *termios,struct ktermios *old) +{ +struct platform_device *pdev =container_of (port->dev, + struct platform_device, dev); +struct pci_dev *dev =to_pci_dev (pdev->dev.parent); +unsigned int baud =tty_termios_baud_rate (termios); +u8 tmp, *offset = port->private_data; +size_t i; + +/* Not support for B1000000 due to haven't 16MHz clock source */ +do { +/* Read current clock source (masked with CLOCK_RATE_MASK) */ +pci_read_config_byte (dev,F81504_UART_START_ADDR + *offset * +F81504_UART_OFFSET , &tmp); + +if (baud <=115200 ) { +/* +* Direct use 1.8432MHz when baud rate smaller then or +* equal 115200bps. +*/ + port->uartclk =115200 *16 ; +pci_write_config_byte (dev,F81504_UART_START_ADDR + + *offset *F81504_UART_OFFSET , + tmp & ~F81504_CLOCK_RATE_MASK ); +break ; + } + +if (!f81504_check_baudrate (baud, &i)) { +/* Had optimize value */ + port->uartclk = baudrate_table[i] *16 ; + tmp = (tmp & ~F81504_CLOCK_RATE_MASK ) | clock_table[i]; +pci_write_config_byte (dev,F81504_UART_START_ADDR + + *offset *F81504_UART_OFFSET , tmp); +break ; + } + +if (old && !f81504_check_baudrate (tty_termios_baud_rate (old), +NULL )) { +/* +* If it can't found suitable clock source but had old +* acceptable baud rate, we'll use it. +*/ + baud =tty_termios_baud_rate (old); + }else { +/* +* If it can't found suitable clock source and not old +* config, we'll direct set 115200bps for future use. +*/ + baud =115200 ; + } + +if (tty_termios_baud_rate (termios)) +tty_termios_encode_baud_rate (termios, baud, baud); + }while (1 ); + +serial8250_do_set_termios (port, termios, old); +} + +static int f81504_register_port (struct platform_device *dev, +unsigned long address,int idx) +{ +struct pci_dev *pci_dev =to_pci_dev (dev->dev.parent); +struct uart_8250_port port; +u8 *data; + +memset (&port,0 ,sizeof (port)); + data =devm_kzalloc (&dev->dev,sizeof (u8),GFP_KERNEL ); +if (!data) +return -ENOMEM ; + + *data = idx; + port.port.iotype =UPIO_PORT ; + port.port.irq = pci_dev->irq; + port.port.flags =UPF_SKIP_TEST |UPF_FIXED_TYPE |UPF_BOOT_AUTOCONF | +UPF_SHARE_IRQ ; + port.port.uartclk =1843200 ; + port.port.dev = &dev->dev; + port.port.iobase = address; + port.port.type =PORT_16550A ; + port.port.fifosize =128 ; + port.port.rs485_config = f81504_rs485_config; + port.port.set_termios = f81504_set_termios; + port.tx_loadsz =32 ; + port.port.private_data = data;/* Save current idx */ + +return serial8250_register_8250_port (&port); +} + +static int f81504_serial_probe (struct platform_device *pdev) +{ +int line; +size_t *index = (size_t *)dev_get_platdata (&pdev->dev); +struct resource *io =platform_get_resource (pdev,IORESOURCE_IO ,0 ); + + line =f81504_register_port (pdev, io->start, *index); +if (line <0 ) +return line; + +/* +* Re-assign line to replace old port PCIE configuration space idx, +* port idx is saved in per-port private data. +*/ + *index = line; +return 0 ; +} + +static int f81504_serial_remove (struct platform_device *pdev) +{ +size_t *line = (size_t *)dev_get_platdata (&pdev->dev); + +serial8250_unregister_port (*line); +return 0 ; +} + + +#ifdef CONFIG_PM_SLEEP +static int f81504_serial_suspend (struct device *dev) +{ +struct platform_device *pdev =to_platform_device (dev); +size_t *line = (size_t *)dev_get_platdata (&pdev->dev); + +serial8250_suspend_port (*line); +return 0 ; +} + +static int f81504_serial_resume (struct device *dev) +{ +struct platform_device *pdev =to_platform_device (dev); +size_t *line = (size_t *)dev_get_platdata (&pdev->dev); +struct uart_8250_port *port =serial8250_get_port (*line); + +f81504_rs485_config (&port->port,NULL ); +serial8250_resume_port (*line); +return 0 ; +} +#endif + +static SIMPLE_DEV_PM_OPS(f81504_serial_pm_ops, f81504_serial_suspend, + f81504_serial_resume); + +static struct platform_driver f81504_serial_driver = { + .driver = { + .name =F81504_SERIAL_NAME , + .pm = &f81504_serial_pm_ops, + }, + .probe = f81504_serial_probe, + .remove = f81504_serial_remove, +}; + +static int __init f81504_serial_init (void ) +{ +return platform_driver_register (&f81504_serial_driver); +} +subsys_initcall (f81504_serial_init); + +static void __exit f81504_serial_exit(void) +{ +platform_driver_unregister (&f81504_serial_driver); +} +module_exit (f81504_serial_exit); + +MODULE_AUTHOR ("Peter Hong <[email protected]>" ); +MODULE_DESCRIPTION ("Fintek F81504/508/512 PCIE 16550A serial port driver" ); +MODULE_LICENSE ("GPL" );
drivers/tty/serial/8250/Kconfig +10 -0
@@ -116,6 +116,16 @@ config SERIAL_8250_PCI Note that serial ports on NetMos 9835 Multi-I/O cards are handled by the parport_serial driver, enabled with CONFIG_PARPORT_SERIAL. +config SERIAL_8250_F81504 + tristate "Fintek F81504/508/512 16550 PCIE device support" if EXPERT + depends on SERIAL_8250 && MFD_FINTEK_F81504_CORE + default SERIAL_8250 + help + This builds Fintek F81504/508/512 PCIE serial ports support. + You may be able to enable GPIO_F81504 to get GPIOLIB support if + the devices supported. Please enable MFD_FINTEK_F81504_CORE & + this with Y if you need a early console. + config SERIAL_8250_HP300 tristate depends on SERIAL_8250 && HP300
drivers/tty/serial/8250/Makefile +1 -0
@@ -9,6 +9,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o 8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o +obj-$(CONFIG_SERIAL_8250_F81504) += 8250_f81504.o obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
Signature · 1 line
1.9.1
PATCH v4 4/4 serial: 8250_pci: Remove Fintek F81504/508/512 UART driver
In reply to Peter HungRemove Fintek F81504/508/512 PCIE-to-UART device driver from 8250_pci.c
Paul recommed us do less code deletion to avoid confusing problem when bisect.
https://lkml.org/lkml/2016/1/18/646
But this patch is sent after with following patch.
8250: 8250_f81504: Add Fintek F81504/508/512 PCIE-to-UART/GPIO UART support
mfd: f81504-core: Add Fintek F81504/508/512 PCIE-to-UART/GPIO core support
We must remove F81504/508/512 support in 8250_pci.c and migrate to f81504-core/8250_f81504 to enable MFD support and Andy recommend me to add these this in blacklist to avoid probed by 8250_pci.c
--- drivers/tty/serial/8250/8250_pci.c | 206 +------------------------------------ 1 file changed, 5 insertions(+), 201 deletions(-)
drivers/tty/serial/8250/8250_pci.c +5 -201
@@ -1532,156 +1532,6 @@ pci_brcm_trumanage_setup(struct serial_private *priv,return ret; } -/* RTS will control by MCR if this bit is 0 */ -#define FINTEK_RTS_CONTROL_BY_HW BIT(4) -/* only worked with FINTEK_RTS_CONTROL_BY_HW on */ -#define FINTEK_RTS_INVERT BIT(5) - -/* We should do proper H/W transceiver setting before change to RS485 mode */ -static int pci_fintek_rs485_config (struct uart_port *port, -struct serial_rs485 *rs485) -{ -u8 setting; -u8 *index = (u8 *) port->private_data; - struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev, - dev); - -pci_read_config_byte (pci_dev,0x40 +8 * *index +7 , &setting); - -if (!rs485) - rs485 = &port->rs485; -else if (rs485->flags &SER_RS485_ENABLED ) -memset (rs485->padding,0 ,sizeof (rs485->padding)); -else -memset (rs485,0 ,sizeof (*rs485)); - -/* F81504/508/512 not support RTS delay before or after send */ - rs485->flags &=SER_RS485_ENABLED |SER_RS485_RTS_ON_SEND ; - -if (rs485->flags &SER_RS485_ENABLED ) { -/* Enable RTS H/W control mode */ - setting |=FINTEK_RTS_CONTROL_BY_HW ; - -if (rs485->flags &SER_RS485_RTS_ON_SEND ) { -/* RTS driving high on TX */ - setting &= ~FINTEK_RTS_INVERT ; - }else { -/* RTS driving low on TX */ - setting |=FINTEK_RTS_INVERT ; - } - - rs485->delay_rts_after_send =0 ; - rs485->delay_rts_before_send =0 ; - }else { -/* Disable RTS H/W control mode */ - setting &= ~(FINTEK_RTS_CONTROL_BY_HW |FINTEK_RTS_INVERT ); - } - -pci_write_config_byte (pci_dev,0x40 +8 * *index +7 , setting); - -if (rs485 != &port->rs485) - port->rs485 = *rs485; - -return 0 ; -} - -static int pci_fintek_setup (struct serial_private *priv, -const struct pciserial_board *board, -struct uart_8250_port *port,int idx) -{ -struct pci_dev *pdev = priv->dev; -u8 *data; -u8 config_base; -u16 iobase; - - config_base =0x40 +0x08 * idx; - -/* Get the io address from configuration space */ -pci_read_config_word (pdev, config_base +4 , &iobase); - -dev_dbg (&pdev->dev,"%s: idx=%d iobase=0x%x" , __func__, idx, iobase); - - port->port.iotype =UPIO_PORT ; - port->port.iobase = iobase; - port->port.rs485_config = pci_fintek_rs485_config; - - data =devm_kzalloc (&pdev->dev,sizeof (u8),GFP_KERNEL ); -if (!data) -return -ENOMEM ; - -/* preserve index in PCI configuration space */ - *data = idx; - port->port.private_data = data; - -return 0 ; -} - -static int pci_fintek_init (struct pci_dev *dev) -{ -unsigned long iobase; -u32 max_port, i; -u32 bar_data[3 ]; -u8 config_base; -struct serial_private *priv =pci_get_drvdata (dev); -struct uart_8250_port *port; - -switch (dev->device) { -case 0x1104 :/* 4 ports */ -case 0x1108 :/* 8 ports */ - max_port = dev->device &0xff ; -break ; -case 0x1112 :/* 12 ports */ - max_port =12 ; -break ; -default : -return -EINVAL ; - } - -/* Get the io address dispatch from the BIOS */ -pci_read_config_dword (dev,0x24 , &bar_data[0 ]); -pci_read_config_dword (dev,0x20 , &bar_data[1 ]); -pci_read_config_dword (dev,0x1c , &bar_data[2 ]); - -for (i =0 ; i < max_port; ++i) { -/* UART0 configuration offset start from 0x40 */ - config_base =0x40 +0x08 * i; - -/* Calculate Real IO Port */ - iobase = (bar_data[i /4 ] &0xffffffe0 ) + (i %4 ) *8 ; - -/* Enable UART I/O port */ -pci_write_config_byte (dev, config_base +0x00 ,0x01 ); - -/* Select 128-byte FIFO and 8x FIFO threshold */ -pci_write_config_byte (dev, config_base +0x01 ,0x33 ); - -/* LSB UART */ -pci_write_config_byte (dev, config_base +0x04 , - (u8)(iobase &0xff )); - -/* MSB UART */ -pci_write_config_byte (dev, config_base +0x05 , - (u8)((iobase &0xff00 ) >>8 )); - -pci_write_config_byte (dev, config_base +0x06 , dev->irq); - -if (priv) { -/* re-apply RS232/485 mode when -* pciserial_resume_ports() -*/ - port =serial8250_get_port (priv->line[i]); -pci_fintek_rs485_config (&port->port,NULL ); - }else { -/* First init without port data -* force init to RS232 Mode -*/ -pci_write_config_byte (dev, config_base +0x07 ,0x01 ); - } - } - -return max_port; -} -static int skip_tx_en_setup (struct serial_private *priv,const struct pciserial_board *board,struct uart_8250_port *port,int idx)
@@ -2726,31 +2576,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .subdevice = PCI_ANY_ID, .setup = pci_brcm_trumanage_setup, }, - { - .vendor = 0x1c29, - .device = 0x1104, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_fintek_setup, - .init = pci_fintek_init, - }, - { - .vendor = 0x1c29, - .device = 0x1108, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_fintek_setup, - .init = pci_fintek_init, - }, - { - .vendor = 0x1c29, - .device = 0x1112, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .setup = pci_fintek_setup, - .init = pci_fintek_init, - }, -/* * Default "match everything" terminator entry */
@@ -2952,9 +2777,6 @@ enum pci_board_num_t { pbn_omegapci, pbn_NETMOS9900_2s_115200, pbn_brcm_trumanage, - pbn_fintek_4, - pbn_fintek_8, - pbn_fintek_12, pbn_wch384_4, pbn_pericom_PI7C9X7951, pbn_pericom_PI7C9X7952,
@@ -3757,24 +3579,6 @@ static struct pciserial_board pci_boards[] = { .reg_shift = 2, .base_baud = 115200, }, - [pbn_fintek_4] = { - .num_ports = 4, - .uart_offset = 8, - .base_baud = 115200, - .first_offset = 0x40, - }, - [pbn_fintek_8] = { - .num_ports = 8, - .uart_offset = 8, - .base_baud = 115200, - .first_offset = 0x40, - }, - [pbn_fintek_12] = { - .num_ports = 12, - .uart_offset = 8, - .base_baud = 115200, - .first_offset = 0x40, - }, [pbn_wch384_4] = { .flags = FL_BASE0, .num_ports = 4,
@@ -3829,6 +3633,11 @@ static const struct pci_device_id blacklist[] = { { PCI_VDEVICE(INTEL, 0x081d), }, { PCI_VDEVICE(INTEL, 0x1191), }, { PCI_VDEVICE(INTEL, 0x19d8), }, + + /* Fintek F81504/508/512. It'll handle by MFD f81504-core.c */ + { PCI_DEVICE(0x1c29, 0x1104), }, + { PCI_DEVICE(0x1c29, 0x1108), }, + { PCI_DEVICE(0x1c29, 0x1112), }, };/*
@@ -5610,11 +5419,6 @@ static struct pci_device_id serial_pci_tbl[] = {0 , 0, pbn_exar_XR17V358 }, -/* Fintek PCI serial cards */ - { PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 }, - { PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 }, - { PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 }, -/* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
Signature · 1 line
1.9.1