TTY/Serial driver patches for 3.12-rc1

Here's the big tty/serial driver pull request for 3.12-rc1.
 
 Lots of n_tty reworks to resolve some very long-standing issues, removing the
 3-4 different locks that were taken for every character.  This code has been
 beaten on for a long time in linux-next with no reported regressions.
 
 Other than that, a range of serial and tty driver updates and revisions.  Full
 details in the shortlog.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.21 (GNU/Linux)
 
 iEYEABECAAYFAlIlI6UACgkQMUfUDdst+ym7kgCgmysv/TVeqsdvmkiO2eEB4+xs
 ddwAoMqkJ/enCJ2f+fC8y2Wz+5+kDrU7
 =CiCp
 -----END PGP SIGNATURE-----

Merge tag 'tty-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial driver patches from Greg KH:
 "Here's the big tty/serial driver pull request for 3.12-rc1.

  Lots of n_tty reworks to resolve some very long-standing issues,
  removing the 3-4 different locks that were taken for every character.
  This code has been beaten on for a long time in linux-next with no
  reported regressions.

  Other than that, a range of serial and tty driver updates and
  revisions.  Full details in the shortlog"

* tag 'tty-3.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (226 commits)
  hvc_xen: Remove unnecessary __GFP_ZERO from kzalloc
  serial: imx: initialize the local variable
  tty: ar933x_uart: add device tree support and binding documentation
  tty: ar933x_uart: allow to build the driver as a module
  ARM: dts: msm: Update uartdm compatible strings
  devicetree: serial: Document msm_serial bindings
  serial: unify serial bindings into a single dir
  serial: fsl-imx-uart: Cleanup duplicate device tree binding
  tty: ar933x_uart: use config_enabled() macro to clean up ifdefs
  tty: ar933x_uart: remove superfluous assignment of ar933x_uart_driver.nr
  tty: ar933x_uart: use the clk API to get the uart clock
  tty: serial: cpm_uart: Adding proper request of GPIO used by cpm_uart driver
  serial: sirf: fix the amount of serial ports
  serial: sirf: define macro for some magic numbers of USP
  serial: icom: move array overflow checks earlier
  TTY: amiserial, remove unnecessary platform_set_drvdata()
  serial: st-asc: remove unnecessary platform_set_drvdata()
  msm_serial: Send more than 1 character on the console w/ UARTDM
  msm_serial: Add support for non-GSBI UARTDM devices
  msm_serial: Switch clock consumer strings and simplify code
  ...
This commit is contained in:
Linus Torvalds 2013-09-03 11:38:36 -07:00
Родитель 751144271f 2d1d3f3ae9
Коммит 2f01ea908b
120 изменённых файлов: 6782 добавлений и 3049 удалений

Просмотреть файл

@ -10,13 +10,18 @@ Required properties:
Optional properties:
- atmel,use-dma-rx: use of PDC or DMA for receiving data
- atmel,use-dma-tx: use of PDC or DMA for transmitting data
- add dma bindings for dma transfer:
- dmas: DMA specifier, consisting of a phandle to DMA controller node,
memory peripheral interface and USART DMA channel ID, FIFO configuration.
Refer to dma.txt and atmel-dma.txt for details.
- dma-names: "rx" for RX channel, "tx" for TX channel.
<chip> compatible description:
- at91rm9200: legacy USART support
- at91sam9260: generic USART implementation for SAM9 SoCs
Example:
- use PDC:
usart0: serial@fff8c000 {
compatible = "atmel,at91sam9260-usart";
reg = <0xfff8c000 0x4000>;
@ -25,3 +30,14 @@ Example:
atmel,use-dma-tx;
};
- use DMA:
usart0: serial@f001c000 {
compatible = "atmel,at91sam9260-usart";
reg = <0xf001c000 0x100>;
interrupts = <12 4 5>;
atmel,use-dma-rx;
atmel,use-dma-tx;
dmas = <&dma0 2 0x3>,
<&dma0 2 0x204>;
dma-names = "tx", "rx";
};

Просмотреть файл

@ -1,35 +1,29 @@
* Freescale i.MX UART controller
* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
Required properties:
- compatible : should be "fsl,imx21-uart"
- compatible : Should be "fsl,<soc>-uart"
- reg : Address and length of the register set for the device
- interrupts : Should contain UART interrupt number
- interrupts : Should contain uart interrupt
Optional properties:
- fsl,uart-has-rtscts: indicate that RTS/CTS signals are used
- fsl,uart-has-rtscts : Indicate the uart has rts and cts
- fsl,irda-mode : Indicate the uart supports irda mode
- fsl,dte-mode : Indicate the uart works in DTE mode. The uart works
is DCE mode by default.
Note: Each uart controller should have an alias correctly numbered
in "aliases" node.
Example:
- From imx51.dtsi:
aliases {
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
};
uart1: serial@73fbc000 {
compatible = "fsl,imx51-uart", "fsl,imx21-uart";
reg = <0x73fbc000 0x4000>;
interrupts = <31>;
status = "disabled";
}
- From imx51-babbage.dts:
uart1: serial@73fbc000 {
fsl,uart-has-rtscts;
status = "okay";
fsl,dte-mode;
};

Просмотреть файл

@ -10,6 +10,10 @@ Required properties:
Refer to dma.txt and fsl-mxs-dma.txt for details.
- dma-names: "rx" for RX channel, "tx" for TX channel.
Optional properties:
- fsl,uart-has-rtscts : Indicate the UART has RTS and CTS lines,
it also means you enable the DMA support for this UART.
Example:
auart0: serial@8006a000 {
compatible = "fsl,imx28-auart", "fsl,imx23-auart";

Просмотреть файл

@ -0,0 +1,25 @@
* MSM Serial UART
The MSM serial UART hardware is designed for low-speed use cases where a
dma-engine isn't needed. From a software perspective it's mostly compatible
with the MSM serial UARTDM except that it only supports reading and writing one
character at a time.
Required properties:
- compatible: Should contain "qcom,msm-uart"
- reg: Should contain UART register location and length.
- interrupts: Should contain UART interrupt.
- clocks: Should contain the core clock.
- clock-names: Should be "core".
Example:
A uart device at 0xa9c00000 with interrupt 11.
serial@a9c00000 {
compatible = "qcom,msm-uart";
reg = <0xa9c00000 0x1000>;
interrupts = <11>;
clocks = <&uart_cxc>;
clock-names = "core";
};

Просмотреть файл

@ -0,0 +1,53 @@
* MSM Serial UARTDM
The MSM serial UARTDM hardware is designed for high-speed use cases where the
transmit and/or receive channels can be offloaded to a dma-engine. From a
software perspective it's mostly compatible with the MSM serial UART except
that it supports reading and writing multiple characters at a time.
Required properties:
- compatible: Should contain at least "qcom,msm-uartdm".
A more specific property should be specified as follows depending
on the version:
"qcom,msm-uartdm-v1.1"
"qcom,msm-uartdm-v1.2"
"qcom,msm-uartdm-v1.3"
"qcom,msm-uartdm-v1.4"
- reg: Should contain UART register locations and lengths. The first
register shall specify the main control registers. An optional second
register location shall specify the GSBI control region.
"qcom,msm-uartdm-v1.3" is the only compatible value that might
need the GSBI control region.
- interrupts: Should contain UART interrupt.
- clocks: Should contain the core clock and the AHB clock.
- clock-names: Should be "core" for the core clock and "iface" for the
AHB clock.
Optional properties:
- dmas: Should contain dma specifiers for transmit and receive channels
- dma-names: Should contain "tx" for transmit and "rx" for receive channels
Examples:
A uartdm v1.4 device with dma capabilities.
serial@f991e000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0xf991e000 0x1000>;
interrupts = <0 108 0x0>;
clocks = <&blsp1_uart2_apps_cxc>, <&blsp1_ahb_cxc>;
clock-names = "core", "iface";
dmas = <&dma0 0>, <&dma0 1>;
dma-names = "tx", "rx";
};
A uartdm v1.3 device without dma capabilities and part of a GSBI complex.
serial@19c40000 {
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x19c40000 0x1000>,
<0x19c00000 0x1000>;
interrupts = <0 195 0x0>;
clocks = <&gsbi5_uart_cxc>, <&gsbi5_ahb_cxc>;
clock-names = "core", "iface";
};

Просмотреть файл

@ -0,0 +1,33 @@
* CSR SiRFprimaII/atlasVI Universal Synchronous Asynchronous Receiver/Transmitter *
Required properties:
- compatible : Should be "sirf,prima2-uart" or "sirf, prima2-usp-uart"
- reg : Offset and length of the register set for the device
- interrupts : Should contain uart interrupt
- fifosize : Should define hardware rx/tx fifo size
- clocks : Should contain uart clock number
Optional properties:
- sirf,uart-has-rtscts: we have hardware flow controller pins in hardware
- rts-gpios: RTS pin for USP-based UART if sirf,uart-has-rtscts is true
- cts-gpios: CTS pin for USP-based UART if sirf,uart-has-rtscts is true
Example:
uart0: uart@b0050000 {
cell-index = <0>;
compatible = "sirf,prima2-uart";
reg = <0xb0050000 0x1000>;
interrupts = <17>;
fifosize = <128>;
clocks = <&clks 13>;
};
On the board-specific dts, we can put rts-gpios and cts-gpios like
usp@b0090000 {
compatible = "sirf,prima2-usp-uart";
sirf,uart-has-rtscts;
rts-gpios = <&gpio 15 0>;
cts-gpios = <&gpio 46 0>;
};

Просмотреть файл

@ -0,0 +1,18 @@
*st-asc(Serial Port)
Required properties:
- compatible : Should be "st,asc".
- reg, reg-names, interrupts, interrupt-names : Standard way to define device
resources with names. look in
Documentation/devicetree/bindings/resource-names.txt
Optional properties:
- st,hw-flow-ctrl bool flag to enable hardware flow control.
- st,force-m1 bool flat to force asc to be in Mode-1 recommeded
for high bit rates (above 19.2K)
Example:
serial@fe440000{
compatible = "st,asc";
reg = <0xfe440000 0x2c>;
interrupts = <0 209 0>;
};

Просмотреть файл

@ -1,22 +0,0 @@
* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
Required properties:
- compatible : Should be "fsl,<soc>-uart"
- reg : Address and length of the register set for the device
- interrupts : Should contain uart interrupt
Optional properties:
- fsl,uart-has-rtscts : Indicate the uart has rts and cts
- fsl,irda-mode : Indicate the uart supports irda mode
- fsl,dte-mode : Indicate the uart works in DTE mode. The uart works
is DCE mode by default.
Example:
serial@73fbc000 {
compatible = "fsl,imx51-uart", "fsl,imx21-uart";
reg = <0x73fbc000 0x4000>;
interrupts = <31>;
fsl,uart-has-rtscts;
fsl,dte-mode;
};

Просмотреть файл

@ -1,27 +0,0 @@
* Qualcomm MSM UART
Required properties:
- compatible :
- "qcom,msm-uart", and one of "qcom,msm-hsuart" or
"qcom,msm-lsuart".
- reg : offset and length of the register set for the device
for the hsuart operating in compatible mode, there should be a
second pair describing the gsbi registers.
- interrupts : should contain the uart interrupt.
There are two different UART blocks used in MSM devices,
"qcom,msm-hsuart" and "qcom,msm-lsuart". The msm-serial driver is
able to handle both of these, and matches against the "qcom,msm-uart"
as the compatibility.
The registers for the "qcom,msm-hsuart" device need to specify both
register blocks, even for the common driver.
Example:
uart@19c400000 {
compatible = "qcom,msm-hsuart", "qcom,msm-uart";
reg = <0x19c40000 0x1000>,
<0x19c00000 0x1000>;
interrupts = <195>;
};

Просмотреть файл

@ -0,0 +1,34 @@
* Qualcomm Atheros AR9330 High-Speed UART
Required properties:
- compatible: Must be "qca,ar9330-uart"
- reg: Specifies the physical base address of the controller and
the length of the memory mapped region.
- interrupt-parent: The phandle for the interrupt controller that
services interrupts for this device.
- interrupts: Specifies the interrupt source of the parent interrupt
controller. The format of the interrupt specifier depends on the
parent interrupt controller.
Additional requirements:
Each UART port must have an alias correctly numbered in "aliases"
node.
Example:
aliases {
serial0 = &uart0;
};
uart0: uart@18020000 {
compatible = "qca,ar9330-uart";
reg = <0x18020000 0x14>;
interrupt-parent = <&intc>;
interrupts = <3>;
};

Просмотреть файл

@ -3322,6 +3322,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
them quite hard to use for exploits but
might break your system.
vt.color= [VT] Default text color.
Format: 0xYX, X = foreground, Y = background.
Default: 0x07 = light gray on black.
vt.cur_default= [VT] Default cursor shape.
Format: 0xCCBBAA, where AA, BB, and CC are the same as
the parameters of the <Esc>[?A;B;Cc escape sequence;
@ -3361,6 +3365,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
overridden by individual drivers. 0 will hide
cursors, 1 will display them.
vt.italic= [VT] Default color for italic text; 0-15.
Default: 2 = green.
vt.underline= [VT] Default color for underlined text; 0-15.
Default: 3 = cyan.
watchdog timers [HW,WDT] For information on watchdog timers,
see Documentation/watchdog/watchdog-parameters.txt
or other driver-specific files in the

Просмотреть файл

@ -220,6 +220,7 @@
auart0: serial@8006a000 {
pinctrl-names = "default";
pinctrl-0 = <&auart0_pins_a>;
fsl,uart-has-rtscts;
status = "okay";
};

Просмотреть файл

@ -38,7 +38,7 @@
};
serial@19c40000 {
compatible = "qcom,msm-hsuart", "qcom,msm-uart";
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x19c40000 0x1000>,
<0x19c00000 0x1000>;
interrupts = <0 195 0x0>;

Просмотреть файл

@ -38,7 +38,7 @@
};
serial@16440000 {
compatible = "qcom,msm-hsuart", "qcom,msm-uart";
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x16440000 0x1000>,
<0x16400000 0x1000>;
interrupts = <0 154 0x0>;

Просмотреть файл

@ -456,9 +456,9 @@ static struct clk_pcom_desc msm_clocks_7x01a[] = {
CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0),
CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0),
CLK_PCOM("uart_clk", UART1_CLK, "msm_serial.0", OFF),
CLK_PCOM("uart_clk", UART2_CLK, "msm_serial.1", 0),
CLK_PCOM("uart_clk", UART3_CLK, "msm_serial.2", OFF),
CLK_PCOM("core", UART1_CLK, "msm_serial.0", OFF),
CLK_PCOM("core", UART2_CLK, "msm_serial.1", 0),
CLK_PCOM("core", UART3_CLK, "msm_serial.2", OFF),
CLK_PCOM("uart1dm_clk", UART1DM_CLK, NULL, OFF),
CLK_PCOM("uart2dm_clk", UART2DM_CLK, NULL, 0),
CLK_PCOM("usb_hs_clk", USB_HS_CLK, "msm_hsusb", OFF),

Просмотреть файл

@ -211,7 +211,7 @@ static struct clk_pcom_desc msm_clocks_7x30[] = {
CLK_PCOM("spi_pclk", SPI_P_CLK, NULL, 0),
CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0),
CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0),
CLK_PCOM("uart_clk", UART2_CLK, "msm_serial.1", 0),
CLK_PCOM("core", UART2_CLK, "msm_serial.1", 0),
CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0),
CLK_PCOM("usb_hs_clk", USB_HS_CLK, NULL, OFF),
CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, NULL, OFF),

Просмотреть файл

@ -358,9 +358,9 @@ static struct clk_pcom_desc msm_clocks_8x50[] = {
CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0),
CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0),
CLK_PCOM("uart_clk", UART1_CLK, NULL, OFF),
CLK_PCOM("uart_clk", UART2_CLK, NULL, 0),
CLK_PCOM("uart_clk", UART3_CLK, "msm_serial.2", OFF),
CLK_PCOM("core", UART1_CLK, NULL, OFF),
CLK_PCOM("core", UART2_CLK, NULL, 0),
CLK_PCOM("core", UART3_CLK, "msm_serial.2", OFF),
CLK_PCOM("uartdm_clk", UART1DM_CLK, NULL, OFF),
CLK_PCOM("uartdm_clk", UART2DM_CLK, NULL, 0),
CLK_PCOM("usb_hs_clk", USB_HS_CLK, NULL, OFF),

Просмотреть файл

@ -122,7 +122,6 @@ static struct resource sc26xx_rsrc[] = {
static struct sccnxp_pdata sccnxp_data = {
.reg_shift = 2,
.frequency = 3686400,
.mctrl_cfg[0] = MCTRL_SIG(DTR_OP, LINE_OP7) |
MCTRL_SIG(RTS_OP, LINE_OP3) |
MCTRL_SIG(DSR_IP, LINE_IP5) |

Просмотреть файл

@ -123,14 +123,14 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
tty = priv->tty;
mutex_lock(&tty->termios_mutex);
down_write(&tty->termios_rwsem);
old_termios = tty->termios;
cflag = tty->termios.c_cflag;
tty_encode_baud_rate(tty, speed, speed);
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
priv->io.speed = speed;
mutex_unlock(&tty->termios_mutex);
up_write(&tty->termios_rwsem);
return 0;
}
@ -280,7 +280,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
struct ktermios old_termios;
int cflag;
mutex_lock(&tty->termios_mutex);
down_write(&tty->termios_rwsem);
old_termios = tty->termios;
cflag = tty->termios.c_cflag;
@ -292,7 +292,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
tty->termios.c_cflag = cflag;
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old_termios);
mutex_unlock(&tty->termios_mutex);
up_write(&tty->termios_rwsem);
}
/*****************************************************************/

Просмотреть файл

@ -32,6 +32,7 @@ struct device_node *of_allnodes;
EXPORT_SYMBOL(of_allnodes);
struct device_node *of_chosen;
struct device_node *of_aliases;
static struct device_node *of_stdout;
DEFINE_MUTEX(of_aliases_mutex);
@ -1595,6 +1596,15 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
of_chosen = of_find_node_by_path("/chosen");
if (of_chosen == NULL)
of_chosen = of_find_node_by_path("/chosen@0");
if (of_chosen) {
const char *name;
name = of_get_property(of_chosen, "linux,stdout-path", NULL);
if (name)
of_stdout = of_find_node_by_path(name);
}
of_aliases = of_find_node_by_path("/aliases");
if (!of_aliases)
return;
@ -1703,3 +1713,19 @@ const char *of_prop_next_string(struct property *prop, const char *cur)
return curv;
}
EXPORT_SYMBOL_GPL(of_prop_next_string);
/**
* of_device_is_stdout_path - check if a device node matches the
* linux,stdout-path property
*
* Check if this device node matches the linux,stdout-path property
* in the chosen node. return true if yes, false otherwise.
*/
int of_device_is_stdout_path(struct device_node *dn)
{
if (!of_stdout)
return false;
return of_stdout == dn;
}
EXPORT_SYMBOL_GPL(of_device_is_stdout_path);

Просмотреть файл

@ -390,7 +390,6 @@ void comedi_driver_unregister(struct comedi_driver *);
*/
#define PCI_VENDOR_ID_KOLTER 0x1001
#define PCI_VENDOR_ID_ICP 0x104c
#define PCI_VENDOR_ID_AMCC 0x10e8
#define PCI_VENDOR_ID_DT 0x1116
#define PCI_VENDOR_ID_IOTECH 0x1616
#define PCI_VENDOR_ID_CONTEC 0x1221

Просмотреть файл

@ -1120,7 +1120,9 @@ static void dgrp_tty_close(struct tty_struct *tty, struct file *file)
if (!sent_printer_offstr)
dgrp_tty_flush_buffer(tty);
spin_unlock_irqrestore(&nd->nd_lock, lock_flags);
tty_ldisc_flush(tty);
spin_lock_irqsave(&nd->nd_lock, lock_flags);
break;
}

Просмотреть файл

@ -1785,8 +1785,6 @@ static int __exit amiga_serial_remove(struct platform_device *pdev)
free_irq(IRQ_AMIGA_TBE, state);
free_irq(IRQ_AMIGA_RBF, state);
platform_set_drvdata(pdev, NULL);
return error;
}

Просмотреть файл

@ -361,7 +361,12 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
tty->driver_data = NULL;
tty_port_put(&hp->port);
printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
}
} else
/* We are ready... raise DTR/RTS */
if (C_BAUD(tty))
if (hp->ops->dtr_rts)
hp->ops->dtr_rts(hp, 1);
/* Force wakeup of the polling thread */
hvc_kick();
@ -393,6 +398,10 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
/* We are done with the tty pointer now. */
tty_port_tty_set(&hp->port, NULL);
if (C_HUPCL(tty))
if (hp->ops->dtr_rts)
hp->ops->dtr_rts(hp, 0);
if (hp->ops->notifier_del)
hp->ops->notifier_del(hp, hp->data);

Просмотреть файл

@ -75,6 +75,9 @@ struct hv_ops {
/* tiocmget/set implementation */
int (*tiocmget)(struct hvc_struct *hp);
int (*tiocmset)(struct hvc_struct *hp, unsigned int set, unsigned int clear);
/* Callbacks to handle tty ports */
void (*dtr_rts)(struct hvc_struct *hp, int raise);
};
/* Register a vterm and a slot index for use as a console (console_init) */

Просмотреть файл

@ -655,6 +655,49 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id)
spin_unlock_bh(&priv->lock);
}
/**
* hvc_iucv_dtr_rts() - HVC notifier for handling DTR/RTS
* @hp: Pointer the HVC device (struct hvc_struct)
* @raise: Non-zero to raise or zero to lower DTR/RTS lines
*
* This routine notifies the HVC back-end to raise or lower DTR/RTS
* lines. Raising DTR/RTS is ignored. Lowering DTR/RTS indicates to
* drop the IUCV connection (similar to hang up the modem).
*/
static void hvc_iucv_dtr_rts(struct hvc_struct *hp, int raise)
{
struct hvc_iucv_private *priv;
struct iucv_path *path;
/* Raising the DTR/RTS is ignored as IUCV connections can be
* established at any times.
*/
if (raise)
return;
priv = hvc_iucv_get_private(hp->vtermno);
if (!priv)
return;
/* Lowering the DTR/RTS lines disconnects an established IUCV
* connection.
*/
flush_sndbuf_sync(priv);
spin_lock_bh(&priv->lock);
path = priv->path; /* save reference to IUCV path */
priv->path = NULL;
priv->iucv_state = IUCV_DISCONN;
spin_unlock_bh(&priv->lock);
/* Sever IUCV path outside of priv->lock due to lock ordering of:
* priv->lock <--> iucv_table_lock */
if (path) {
iucv_path_sever(path, NULL);
iucv_path_free(path);
}
}
/**
* hvc_iucv_notifier_del() - HVC notifier for closing a TTY for the last time.
* @hp: Pointer to the HVC device (struct hvc_struct)
@ -662,15 +705,15 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id)
* the index of an struct hvc_iucv_private instance.
*
* This routine notifies the HVC back-end that the last tty device fd has been
* closed. The function calls hvc_iucv_cleanup() to clean up the struct
* hvc_iucv_private instance.
* closed. The function cleans up tty resources. The clean-up of the IUCV
* connection is done in hvc_iucv_dtr_rts() and depends on the HUPCL termios
* control setting.
*
* Locking: struct hvc_iucv_private->lock
*/
static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
{
struct hvc_iucv_private *priv;
struct iucv_path *path;
priv = hvc_iucv_get_private(id);
if (!priv)
@ -679,17 +722,11 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id)
flush_sndbuf_sync(priv);
spin_lock_bh(&priv->lock);
path = priv->path; /* save reference to IUCV path */
priv->path = NULL;
hvc_iucv_cleanup(priv);
destroy_tty_buffer_list(&priv->tty_outqueue);
destroy_tty_buffer_list(&priv->tty_inqueue);
priv->tty_state = TTY_CLOSED;
priv->sndbuf_len = 0;
spin_unlock_bh(&priv->lock);
/* sever IUCV path outside of priv->lock due to lock ordering of:
* priv->lock <--> iucv_table_lock */
if (path) {
iucv_path_sever(path, NULL);
iucv_path_free(path);
}
}
/**
@ -931,6 +968,7 @@ static const struct hv_ops hvc_iucv_ops = {
.notifier_add = hvc_iucv_notifier_add,
.notifier_del = hvc_iucv_notifier_del,
.notifier_hangup = hvc_iucv_notifier_hangup,
.dtr_rts = hvc_iucv_dtr_rts,
};
/* Suspend / resume device operations */

Просмотреть файл

@ -208,7 +208,7 @@ static int xen_hvm_console_init(void)
info = vtermno_to_xencons(HVC_COOKIE);
if (!info) {
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO);
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
} else if (info->intf != NULL) {
@ -257,7 +257,7 @@ static int xen_pv_console_init(void)
info = vtermno_to_xencons(HVC_COOKIE);
if (!info) {
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO);
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
} else if (info->intf != NULL) {
@ -284,7 +284,7 @@ static int xen_initial_domain_console_init(void)
info = vtermno_to_xencons(HVC_COOKIE);
if (!info) {
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO);
info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
}

Просмотреть файл

@ -807,7 +807,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
int h = dlci->adaption - 1;
total_size = 0;
while(1) {
while (1) {
len = kfifo_len(dlci->fifo);
if (len == 0)
return total_size;
@ -827,8 +827,8 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)
switch (dlci->adaption) {
case 1: /* Unstructured */
break;
case 2: /* Unstructed with modem bits. Always one byte as we never
send inline break data */
case 2: /* Unstructed with modem bits.
Always one byte as we never send inline break data */
*dp++ = gsm_encode_modem(dlci);
break;
}
@ -968,7 +968,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
unsigned long flags;
int sweep;
if (dlci->constipated)
if (dlci->constipated)
return;
spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
@ -981,7 +981,7 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
gsm_dlci_data_output(dlci->gsm, dlci);
}
if (sweep)
gsm_dlci_data_sweep(dlci->gsm);
gsm_dlci_data_sweep(dlci->gsm);
spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
}
@ -1138,7 +1138,7 @@ static void gsm_control_modem(struct gsm_mux *gsm, u8 *data, int clen)
static void gsm_control_rls(struct gsm_mux *gsm, u8 *data, int clen)
{
struct tty_port *port;
unsigned int addr = 0 ;
unsigned int addr = 0;
u8 bits;
int len = clen;
u8 *dp = data;
@ -1740,10 +1740,11 @@ static void gsm_queue(struct gsm_mux *gsm)
if ((gsm->control & ~PF) == UI)
gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf, gsm->len);
if (gsm->encoding == 0){
/* WARNING: gsm->received_fcs is used for gsm->encoding = 0 only.
In this case it contain the last piece of data
required to generate final CRC */
if (gsm->encoding == 0) {
/* WARNING: gsm->received_fcs is used for
gsm->encoding = 0 only.
In this case it contain the last piece of data
required to generate final CRC */
gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->received_fcs);
}
if (gsm->fcs != GOOD_FCS) {
@ -2904,9 +2905,11 @@ static int gsmtty_install(struct tty_driver *driver, struct tty_struct *tty)
gsm = gsm_mux[mux];
if (gsm->dead)
return -EL2HLT;
/* If DLCI 0 is not yet fully open return an error. This is ok from a locking
perspective as we don't have to worry about this if DLCI0 is lost */
if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
/* If DLCI 0 is not yet fully open return an error.
This is ok from a locking
perspective as we don't have to worry about this
if DLCI0 is lost */
if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN)
return -EL2NSYNC;
dlci = gsm->dlci[line];
if (dlci == NULL) {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -89,17 +89,13 @@ static void pty_unthrottle(struct tty_struct *tty)
* pty_space - report space left for writing
* @to: tty we are writing into
*
* The tty buffers allow 64K but we sneak a peak and clip at 8K this
* allows a lot of overspill room for echo and other fun messes to
* be handled properly
* Limit the buffer space used by ptys to 8k.
*/
static int pty_space(struct tty_struct *to)
{
int n = 8192 - to->port->buf.memory_used;
if (n < 0)
return 0;
return n;
int n = tty_buffer_space_avail(to->port);
return min(n, 8192);
}
/**
@ -125,10 +121,8 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c)
/* Stuff the data into the input queue of the other end */
c = tty_insert_flip_string(to->port, buf, c);
/* And shovel */
if (c) {
if (c)
tty_flip_buffer_push(to->port);
tty_wakeup(tty);
}
}
return c;
}
@ -287,7 +281,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws)
struct tty_struct *pty = tty->link;
/* For a PTY we need to lock the tty side */
mutex_lock(&tty->termios_mutex);
mutex_lock(&tty->winsize_mutex);
if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;
@ -314,7 +308,7 @@ static int pty_resize(struct tty_struct *tty, struct winsize *ws)
tty->winsize = *ws;
pty->winsize = *ws; /* Never used so will go away soon */
done:
mutex_unlock(&tty->termios_mutex);
mutex_unlock(&tty->winsize_mutex);
return 0;
}

Просмотреть файл

@ -3062,7 +3062,7 @@ void serial8250_resume_port(int line)
*/
static int serial8250_probe(struct platform_device *dev)
{
struct plat_serial8250_port *p = dev->dev.platform_data;
struct plat_serial8250_port *p = dev_get_platdata(&dev->dev);
struct uart_8250_port uart;
int ret, i, irqflag = 0;

Просмотреть файл

@ -57,11 +57,25 @@
struct dw8250_data {
int last_lcr;
int last_mcr;
int line;
struct clk *clk;
u8 usr_reg;
};
static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
/* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */
if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) {
value |= UART_MSR_CTS;
value &= ~UART_MSR_DCTS;
}
return value;
}
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
{
struct dw8250_data *d = p->private_data;
@ -69,15 +83,17 @@ static void dw8250_serial_out(struct uart_port *p, int offset, int value)
if (offset == UART_LCR)
d->last_lcr = value;
offset <<= p->regshift;
writeb(value, p->membase + offset);
if (offset == UART_MCR)
d->last_mcr = value;
writeb(value, p->membase + (offset << p->regshift));
}
static unsigned int dw8250_serial_in(struct uart_port *p, int offset)
{
offset <<= p->regshift;
unsigned int value = readb(p->membase + (offset << p->regshift));
return readb(p->membase + offset);
return dw8250_modify_msr(p, offset, value);
}
/* Read Back (rb) version to ensure register access ording. */
@ -94,15 +110,17 @@ static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
if (offset == UART_LCR)
d->last_lcr = value;
offset <<= p->regshift;
writel(value, p->membase + offset);
if (offset == UART_MCR)
d->last_mcr = value;
writel(value, p->membase + (offset << p->regshift));
}
static unsigned int dw8250_serial_in32(struct uart_port *p, int offset)
{
offset <<= p->regshift;
unsigned int value = readl(p->membase + (offset << p->regshift));
return readl(p->membase + offset);
return dw8250_modify_msr(p, offset, value);
}
static int dw8250_handle_irq(struct uart_port *p)

Просмотреть файл

@ -194,7 +194,7 @@ static int __init parse_options(struct early_serial8250_device *device,
options++;
device->baud = simple_strtoul(options, NULL, 0);
length = min(strcspn(options, " ") + 1,
sizeof(device->options));
(size_t)(sizeof(device->options)));
strlcpy(device->options, options, length);
} else {
device->baud = probe_baud(port);

Просмотреть файл

@ -95,25 +95,23 @@ static int serial8250_em_probe(struct platform_device *pdev)
struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
struct serial8250_em_priv *priv;
struct uart_8250_port up;
int ret = -EINVAL;
int ret;
if (!regs || !irq) {
dev_err(&pdev->dev, "missing registers or irq\n");
goto err0;
return -EINVAL;
}
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "unable to allocate private data\n");
ret = -ENOMEM;
goto err0;
return -ENOMEM;
}
priv->sclk = clk_get(&pdev->dev, "sclk");
priv->sclk = devm_clk_get(&pdev->dev, "sclk");
if (IS_ERR(priv->sclk)) {
dev_err(&pdev->dev, "unable to get clock\n");
ret = PTR_ERR(priv->sclk);
goto err1;
return PTR_ERR(priv->sclk);
}
memset(&up, 0, sizeof(up));
@ -136,20 +134,13 @@ static int serial8250_em_probe(struct platform_device *pdev)
ret = serial8250_register_8250_port(&up);
if (ret < 0) {
dev_err(&pdev->dev, "unable to register 8250 port\n");
goto err2;
clk_disable(priv->sclk);
return ret;
}
priv->line = ret;
platform_set_drvdata(pdev, priv);
return 0;
err2:
clk_disable(priv->sclk);
clk_put(priv->sclk);
err1:
kfree(priv);
err0:
return ret;
}
static int serial8250_em_remove(struct platform_device *pdev)
@ -158,8 +149,6 @@ static int serial8250_em_remove(struct platform_device *pdev)
serial8250_unregister_port(priv->line);
clk_disable(priv->sclk);
clk_put(priv->sclk);
kfree(priv);
return 0;
}

Просмотреть файл

@ -1565,6 +1565,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021
#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022
#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e
#define PCI_VENDOR_ID_SUNIX 0x1fd4
#define PCI_DEVICE_ID_SUNIX_1999 0x1999
@ -1587,8 +1588,8 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
* ADDI-DATA GmbH communication cards <info@addi-data.com>
*/
{
.vendor = PCI_VENDOR_ID_ADDIDATA_OLD,
.device = PCI_DEVICE_ID_ADDIDATA_APCI7800,
.vendor = PCI_VENDOR_ID_AMCC,
.device = PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = addidata_apci7800_setup,
@ -4697,8 +4698,8 @@ static struct pci_device_id serial_pci_tbl[] = {
0,
pbn_b0_1_115200 },
{ PCI_VENDOR_ID_ADDIDATA_OLD,
PCI_DEVICE_ID_ADDIDATA_APCI7800,
{ PCI_VENDOR_ID_AMCC,
PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800,
PCI_ANY_ID,
PCI_ANY_ID,
0,
@ -4797,6 +4798,12 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_VENDOR_ID_IBM, 0x0299,
0, 0, pbn_b0_bt_2_115200 },
/*
* other NetMos 9835 devices are most likely handled by the
* parport_serial driver, check drivers/parport/parport_serial.c
* before adding them here.
*/
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
0xA000, 0x1000,
0, 0, pbn_b0_1_115200 },

Просмотреть файл

@ -116,6 +116,8 @@ config SERIAL_8250_PCI
This builds standard PCI serial support. You may be able to
disable this feature if you only need legacy serial support.
Saves about 9K.
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_HP300
tristate

Просмотреть файл

@ -291,13 +291,13 @@ config SERIAL_MAX3100
config SERIAL_MAX310X
bool "MAX310X support"
depends on SPI
depends on SPI_MASTER
select SERIAL_CORE
select REGMAP_SPI if SPI
select REGMAP_SPI if SPI_MASTER
default n
help
This selects support for an advanced UART from Maxim (Dallas).
Supported ICs are MAX3107, MAX3108.
Supported ICs are MAX3107, MAX3108, MAX3109, MAX14830.
Each IC contains 128 words each of receive and transmit FIFO
that can be controlled through I2C or high-speed SPI.
@ -1401,13 +1401,16 @@ config SERIAL_XILINX_PS_UART_CONSOLE
Enable a Xilinx PS UART port to be the system console.
config SERIAL_AR933X
bool "AR933X serial port support"
depends on SOC_AR933X
tristate "AR933X serial port support"
depends on HAVE_CLK && SOC_AR933X
select SERIAL_CORE
help
If you have an Atheros AR933X SOC based board and want to use the
built-in UART of the SoC, say Y to this option.
To compile this driver as a module, choose M here: the
module will be called ar933x_uart.
config SERIAL_AR933X_CONSOLE
bool "Console on AR933X serial port"
depends on SERIAL_AR933X=y
@ -1424,8 +1427,8 @@ config SERIAL_AR933X_NR_UARTS
to support.
config SERIAL_EFM32_UART
tristate "EFM32 UART/USART port."
depends on ARCH_EFM32
tristate "EFM32 UART/USART port"
depends on ARM && (ARCH_EFM32 || COMPILE_TEST)
select SERIAL_CORE
help
This driver support the USART and UART ports on
@ -1497,6 +1500,22 @@ config SERIAL_FSL_LPUART_CONSOLE
If you have enabled the lpuart serial port on the Freescale SoCs,
you can make it the console by answering Y to this option.
config SERIAL_ST_ASC
tristate "ST ASC serial port support"
select SERIAL_CORE
help
This driver is for the on-chip Asychronous Serial Controller on
STMicroelectronics STi SoCs.
ASC is embedded in ST COMMS IP block. It supports Rx & Tx functionality.
It support all industry standard baud rates.
If unsure, say N.
config SERIAL_ST_ASC_CONSOLE
bool "Support for console on ST ASC"
depends on SERIAL_ST_ASC=y
select SERIAL_CORE_CONSOLE
endmenu
endif # TTY

Просмотреть файл

@ -65,6 +65,7 @@ obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o

Просмотреть файл

@ -139,7 +139,9 @@ static void altera_jtaguart_rx_chars(struct altera_jtaguart *pp)
uart_insert_char(port, 0, 0, ch, flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static void altera_jtaguart_tx_chars(struct altera_jtaguart *pp)
@ -408,7 +410,8 @@ static struct uart_driver altera_jtaguart_driver = {
static int altera_jtaguart_probe(struct platform_device *pdev)
{
struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
struct altera_jtaguart_platform_uart *platp =
dev_get_platdata(&pdev->dev);
struct uart_port *port;
struct resource *res_irq, *res_mem;
int i = pdev->id;

Просмотреть файл

@ -231,7 +231,9 @@ static void altera_uart_rx_chars(struct altera_uart *pp)
flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static void altera_uart_tx_chars(struct altera_uart *pp)
@ -534,7 +536,7 @@ static int altera_uart_get_of_uartclk(struct platform_device *pdev,
static int altera_uart_probe(struct platform_device *pdev)
{
struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
struct altera_uart_platform_uart *platp = dev_get_platdata(&pdev->dev);
struct uart_port *port;
struct resource *res_mem;
struct resource *res_irq;

Просмотреть файл

@ -721,7 +721,7 @@ static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = i;
uap->dev = dev;
uap->data = dev->dev.platform_data;
uap->data = dev_get_platdata(&dev->dev);
amba_ports[i] = uap;

Просмотреть файл

@ -265,7 +265,7 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
{
/* DMA is the sole user of the platform data right now */
struct amba_pl011_data *plat = uap->port.dev->platform_data;
struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
struct dma_slave_config tx_conf = {
.dst_addr = uap->port.mapbase + UART01x_DR,
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@ -677,6 +677,8 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
* Locking: called with port lock held and IRQs disabled.
*/
static void pl011_dma_flush_buffer(struct uart_port *port)
__releases(&uap->port.lock)
__acquires(&uap->port.lock)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
@ -1198,6 +1200,8 @@ static void pl011_enable_ms(struct uart_port *port)
}
static void pl011_rx_chars(struct uart_amba_port *uap)
__releases(&uap->port.lock)
__acquires(&uap->port.lock)
{
pl011_fifo_to_tty(uap);
@ -1497,10 +1501,10 @@ static int pl011_hwinit(struct uart_port *port)
uap->im = readw(uap->port.membase + UART011_IMSC);
writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC);
if (uap->port.dev->platform_data) {
if (dev_get_platdata(uap->port.dev)) {
struct amba_pl011_data *plat;
plat = uap->port.dev->platform_data;
plat = dev_get_platdata(uap->port.dev);
if (plat->init)
plat->init();
}
@ -1645,10 +1649,10 @@ static void pl011_shutdown(struct uart_port *port)
/* Optionally let pins go into sleep states */
pinctrl_pm_select_sleep_state(port->dev);
if (uap->port.dev->platform_data) {
if (dev_get_platdata(uap->port.dev)) {
struct amba_pl011_data *plat;
plat = uap->port.dev->platform_data;
plat = dev_get_platdata(uap->port.dev);
if (plat->exit)
plat->exit();
}
@ -2002,10 +2006,10 @@ static int __init pl011_console_setup(struct console *co, char *options)
if (ret)
return ret;
if (uap->port.dev->platform_data) {
if (dev_get_platdata(uap->port.dev)) {
struct amba_pl011_data *plat;
plat = uap->port.dev->platform_data;
plat = dev_get_platdata(uap->port.dev);
if (plat->init)
plat->init();
}

Просмотреть файл

@ -125,7 +125,9 @@ static void apbuart_rx_chars(struct uart_port *port)
status = UART_GET_STATUS(port);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
static void apbuart_tx_chars(struct uart_port *port)

Просмотреть файл

@ -17,6 +17,8 @@
#include <linux/sysrq.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
@ -24,11 +26,11 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/clk.h>
#include <asm/div64.h>
#include <asm/mach-ath79/ar933x_uart.h>
#include <asm/mach-ath79/ar933x_uart_platform.h>
#define DRIVER_NAME "ar933x-uart"
@ -47,8 +49,14 @@ struct ar933x_uart_port {
unsigned int ier; /* shadow Interrupt Enable Register */
unsigned int min_baud;
unsigned int max_baud;
struct clk *clk;
};
static inline bool ar933x_uart_console_enabled(void)
{
return config_enabled(CONFIG_SERIAL_AR933X_CONSOLE);
}
static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up,
int offset)
{
@ -322,7 +330,9 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)
tty_insert_flip_char(port, ch, TTY_NORMAL);
} while (max_count-- > 0);
spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
spin_lock(&up->port.lock);
}
static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)
@ -497,8 +507,6 @@ static struct uart_ops ar933x_uart_ops = {
.verify_port = ar933x_uart_verify_port,
};
#ifdef CONFIG_SERIAL_AR933X_CONSOLE
static struct ar933x_uart_port *
ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS];
@ -597,80 +605,88 @@ static struct console ar933x_uart_console = {
static void ar933x_uart_add_console_port(struct ar933x_uart_port *up)
{
if (!ar933x_uart_console_enabled())
return;
ar933x_console_ports[up->port.line] = up;
}
#define AR933X_SERIAL_CONSOLE (&ar933x_uart_console)
#else
static inline void ar933x_uart_add_console_port(struct ar933x_uart_port *up) {}
#define AR933X_SERIAL_CONSOLE NULL
#endif /* CONFIG_SERIAL_AR933X_CONSOLE */
static struct uart_driver ar933x_uart_driver = {
.owner = THIS_MODULE,
.driver_name = DRIVER_NAME,
.dev_name = "ttyATH",
.nr = CONFIG_SERIAL_AR933X_NR_UARTS,
.cons = AR933X_SERIAL_CONSOLE,
.cons = NULL, /* filled in runtime */
};
static int ar933x_uart_probe(struct platform_device *pdev)
{
struct ar933x_uart_platform_data *pdata;
struct ar933x_uart_port *up;
struct uart_port *port;
struct resource *mem_res;
struct resource *irq_res;
struct device_node *np;
unsigned int baud;
int id;
int ret;
pdata = pdev->dev.platform_data;
if (!pdata)
return -EINVAL;
id = pdev->id;
if (id == -1)
id = 0;
np = pdev->dev.of_node;
if (config_enabled(CONFIG_OF) && np) {
id = of_alias_get_id(np, "serial");
if (id < 0) {
dev_err(&pdev->dev, "unable to get alias id, err=%d\n",
id);
return id;
}
} else {
id = pdev->id;
if (id == -1)
id = 0;
}
if (id > CONFIG_SERIAL_AR933X_NR_UARTS)
return -EINVAL;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem_res) {
dev_err(&pdev->dev, "no MEM resource\n");
return -EINVAL;
}
irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!irq_res) {
dev_err(&pdev->dev, "no IRQ resource\n");
return -EINVAL;
}
up = kzalloc(sizeof(struct ar933x_uart_port), GFP_KERNEL);
up = devm_kzalloc(&pdev->dev, sizeof(struct ar933x_uart_port),
GFP_KERNEL);
if (!up)
return -ENOMEM;
port = &up->port;
port->mapbase = mem_res->start;
port->membase = ioremap(mem_res->start, AR933X_UART_REGS_SIZE);
if (!port->membase) {
ret = -ENOMEM;
goto err_free_up;
up->clk = devm_clk_get(&pdev->dev, "uart");
if (IS_ERR(up->clk)) {
dev_err(&pdev->dev, "unable to get UART clock\n");
return PTR_ERR(up->clk);
}
port = &up->port;
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, mem_res);
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
ret = clk_prepare_enable(up->clk);
if (ret)
return ret;
port->uartclk = clk_get_rate(up->clk);
if (!port->uartclk) {
ret = -EINVAL;
goto err_disable_clk;
}
port->mapbase = mem_res->start;
port->line = id;
port->irq = irq_res->start;
port->dev = &pdev->dev;
port->type = PORT_AR933X;
port->iotype = UPIO_MEM32;
port->uartclk = pdata->uartclk;
port->regshift = 2;
port->fifosize = AR933X_UART_FIFO_SIZE;
@ -686,15 +702,13 @@ static int ar933x_uart_probe(struct platform_device *pdev)
ret = uart_add_one_port(&ar933x_uart_driver, &up->port);
if (ret)
goto err_unmap;
goto err_disable_clk;
platform_set_drvdata(pdev, up);
return 0;
err_unmap:
iounmap(up->port.membase);
err_free_up:
kfree(up);
err_disable_clk:
clk_disable_unprepare(up->clk);
return ret;
}
@ -703,23 +717,30 @@ static int ar933x_uart_remove(struct platform_device *pdev)
struct ar933x_uart_port *up;
up = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
if (up) {
uart_remove_one_port(&ar933x_uart_driver, &up->port);
iounmap(up->port.membase);
kfree(up);
clk_disable_unprepare(up->clk);
}
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id ar933x_uart_of_ids[] = {
{ .compatible = "qca,ar9330-uart" },
{},
};
MODULE_DEVICE_TABLE(of, ar933x_uart_of_ids);
#endif
static struct platform_driver ar933x_uart_platform_driver = {
.probe = ar933x_uart_probe,
.remove = ar933x_uart_remove,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(ar933x_uart_of_ids),
},
};
@ -727,7 +748,9 @@ static int __init ar933x_uart_init(void)
{
int ret;
ar933x_uart_driver.nr = CONFIG_SERIAL_AR933X_NR_UARTS;
if (ar933x_uart_console_enabled())
ar933x_uart_driver.cons = &ar933x_uart_console;
ret = uart_register_driver(&ar933x_uart_driver);
if (ret)
goto err_out;

Просмотреть файл

@ -209,9 +209,9 @@ static void arc_serial_start_tx(struct uart_port *port)
arc_serial_tx_chars(uart);
}
static void arc_serial_rx_chars(struct arc_uart_port *uart)
static void arc_serial_rx_chars(struct arc_uart_port *uart, unsigned int status)
{
unsigned int status, ch, flg = 0;
unsigned int ch, flg = 0;
/*
* UART has 4 deep RX-FIFO. Driver's recongnition of this fact
@ -222,11 +222,11 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart)
* before RX-EMPTY=0, implies some sort of buffering going on in the
* controller, which is indeed the Rx-FIFO.
*/
while (!((status = UART_GET_STATUS(uart)) & RXEMPTY)) {
ch = UART_GET_DATA(uart);
uart->port.icount.rx++;
do {
/*
* This could be an Rx Intr for err (no data),
* so check err and clear that Intr first
*/
if (unlikely(status & (RXOERR | RXFERR))) {
if (status & RXOERR) {
uart->port.icount.overrun++;
@ -242,14 +242,19 @@ static void arc_serial_rx_chars(struct arc_uart_port *uart)
} else
flg = TTY_NORMAL;
if (unlikely(uart_handle_sysrq_char(&uart->port, ch)))
goto done;
if (status & RXEMPTY)
continue;
uart_insert_char(&uart->port, status, RXOERR, ch, flg);
ch = UART_GET_DATA(uart);
uart->port.icount.rx++;
done:
if (!(uart_handle_sysrq_char(&uart->port, ch)))
uart_insert_char(&uart->port, status, RXOERR, ch, flg);
spin_unlock(&uart->port.lock);
tty_flip_buffer_push(&uart->port.state->port);
}
spin_lock(&uart->port.lock);
} while (!((status = UART_GET_STATUS(uart)) & RXEMPTY));
}
/*
@ -292,11 +297,11 @@ static irqreturn_t arc_serial_isr(int irq, void *dev_id)
* notifications from the UART Controller.
* To demultiplex between the two, we check the relevant bits
*/
if ((status & RXIENB) && !(status & RXEMPTY)) {
if (status & RXIENB) {
/* already in ISR, no need of xx_irqsave */
spin_lock(&uart->port.lock);
arc_serial_rx_chars(uart);
arc_serial_rx_chars(uart, status);
spin_unlock(&uart->port.lock);
}
@ -528,7 +533,7 @@ arc_uart_init_one(struct platform_device *pdev, int dev_id)
unsigned long *plat_data;
struct arc_uart_port *uart = &arc_uart_ports[dev_id];
plat_data = ((unsigned long *)(pdev->dev.platform_data));
plat_data = (unsigned long *)dev_get_platdata(&pdev->dev);
if (!plat_data)
return -ENODEV;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -302,7 +302,9 @@ static void bcm_uart_do_rx(struct uart_port *port)
} while (--max_count);
spin_unlock(&port->lock);
tty_flip_buffer_push(tty_port);
spin_lock(&port->lock);
}
/*
@ -852,7 +854,6 @@ static int bcm_uart_remove(struct platform_device *pdev)
port = platform_get_drvdata(pdev);
uart_remove_one_port(&bcm_uart_driver, port);
platform_set_drvdata(pdev, NULL);
/* mark port as free */
ports[pdev->id].membase = 0;
return 0;

Просмотреть файл

@ -161,11 +161,12 @@ static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id)
if (!uart_handle_sysrq_char(&up->port, ch))
tty_insert_flip_char(port, ch, TTY_NORMAL);
}
/* XXX this won't deadlock with lowlat? */
tty_flip_buffer_push(port);
spin_unlock(&up->port.lock);
/* XXX this won't deadlock with lowlat? */
tty_flip_buffer_push(port);
return IRQ_HANDLED;
}
@ -766,7 +767,8 @@ static int sport_uart_probe(struct platform_device *pdev)
}
ret = peripheral_request_list(
(unsigned short *)pdev->dev.platform_data, DRV_NAME);
(unsigned short *)dev_get_platdata(&pdev->dev),
DRV_NAME);
if (ret) {
dev_err(&pdev->dev,
"Fail to request SPORT peripherals\n");
@ -843,7 +845,7 @@ out_error_unmap:
iounmap(sport->port.membase);
out_error_free_peripherals:
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
(unsigned short *)dev_get_platdata(&pdev->dev));
out_error_free_mem:
kfree(sport);
bfin_sport_uart_ports[pdev->id] = NULL;
@ -863,7 +865,7 @@ static int sport_uart_remove(struct platform_device *pdev)
uart_remove_one_port(&sport_uart_reg, &sport->port);
iounmap(sport->port.membase);
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
(unsigned short *)dev_get_platdata(&pdev->dev));
kfree(sport);
bfin_sport_uart_ports[pdev->id] = NULL;
}
@ -883,7 +885,7 @@ static struct platform_driver sport_uart_driver = {
};
#ifdef CONFIG_SERIAL_BFIN_SPORT_CONSOLE
static __initdata struct early_platform_driver early_sport_uart_driver = {
static struct early_platform_driver early_sport_uart_driver __initdata = {
.class_str = CLASS_BFIN_SPORT_CONSOLE,
.pdrv = &sport_uart_driver,
.requested_id = EARLY_PLATFORM_ID_UNSET,

Просмотреть файл

@ -41,10 +41,6 @@
# undef CONFIG_EARLY_PRINTK
#endif
#ifdef CONFIG_SERIAL_BFIN_MODULE
# undef CONFIG_EARLY_PRINTK
#endif
/* UART name and device definitions */
#define BFIN_SERIAL_DEV_NAME "ttyBF"
#define BFIN_SERIAL_MAJOR 204
@ -1180,7 +1176,7 @@ bfin_earlyprintk_console_write(struct console *co, const char *s, unsigned int c
* don't let the common infrastructure play with things. (see calls to setup
* & earlysetup in ./kernel/printk.c:register_console()
*/
static struct __initdata console bfin_early_serial_console = {
static struct console bfin_early_serial_console __initdata = {
.name = "early_BFuart",
.write = bfin_earlyprintk_console_write,
.device = uart_console_device,
@ -1244,7 +1240,8 @@ static int bfin_serial_probe(struct platform_device *pdev)
*/
#endif
ret = peripheral_request_list(
(unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
(unsigned short *)dev_get_platdata(&pdev->dev),
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev,
"fail to request bfin serial peripherals\n");
@ -1362,7 +1359,7 @@ out_error_unmap:
iounmap(uart->port.membase);
out_error_free_peripherals:
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
(unsigned short *)dev_get_platdata(&pdev->dev));
out_error_free_mem:
kfree(uart);
bfin_serial_ports[pdev->id] = NULL;
@ -1381,7 +1378,7 @@ static int bfin_serial_remove(struct platform_device *pdev)
uart_remove_one_port(&bfin_serial_reg, &uart->port);
iounmap(uart->port.membase);
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
(unsigned short *)dev_get_platdata(&pdev->dev));
kfree(uart);
bfin_serial_ports[pdev->id] = NULL;
}
@ -1401,7 +1398,7 @@ static struct platform_driver bfin_serial_driver = {
};
#if defined(CONFIG_SERIAL_BFIN_CONSOLE)
static __initdata struct early_platform_driver early_bfin_serial_driver = {
static struct early_platform_driver early_bfin_serial_driver __initdata = {
.class_str = CLASS_BFIN_CONSOLE,
.pdrv = &bfin_serial_driver,
.requested_id = EARLY_PLATFORM_ID_UNSET,
@ -1436,7 +1433,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
}
ret = peripheral_request_list(
(unsigned short *)pdev->dev.platform_data, DRIVER_NAME);
(unsigned short *)dev_get_platdata(&pdev->dev), DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev,
"fail to request bfin serial peripherals\n");
@ -1467,7 +1464,7 @@ static int bfin_earlyprintk_probe(struct platform_device *pdev)
out_error_free_peripherals:
peripheral_free_list(
(unsigned short *)pdev->dev.platform_data);
(unsigned short *)dev_get_platdata(&pdev->dev));
return ret;
}
@ -1480,7 +1477,7 @@ static struct platform_driver bfin_earlyprintk_driver = {
},
};
static __initdata struct early_platform_driver early_bfin_earlyprintk_driver = {
static struct early_platform_driver early_bfin_earlyprintk_driver __initdata = {
.class_str = CLASS_BFIN_EARLYPRINTK,
.pdrv = &bfin_earlyprintk_driver,
.requested_id = EARLY_PLATFORM_ID_UNSET,

Просмотреть файл

@ -438,8 +438,7 @@ static int uart_clps711x_probe(struct platform_device *pdev)
s->uart_clk = devm_clk_get(&pdev->dev, "uart");
if (IS_ERR(s->uart_clk)) {
dev_err(&pdev->dev, "Can't get UART clocks\n");
ret = PTR_ERR(s->uart_clk);
goto err_out;
return PTR_ERR(s->uart_clk);
}
s->uart.owner = THIS_MODULE;
@ -461,7 +460,7 @@ static int uart_clps711x_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "Registering UART driver failed\n");
devm_clk_put(&pdev->dev, s->uart_clk);
goto err_out;
return ret;
}
for (i = 0; i < UART_CLPS711X_NR; i++) {
@ -478,11 +477,6 @@ static int uart_clps711x_probe(struct platform_device *pdev)
}
return 0;
err_out:
platform_set_drvdata(pdev, NULL);
return ret;
}
static int uart_clps711x_remove(struct platform_device *pdev)
@ -495,7 +489,6 @@ static int uart_clps711x_remove(struct platform_device *pdev)
devm_clk_put(&pdev->dev, s->uart_clk);
uart_unregister_driver(&s->uart);
platform_set_drvdata(pdev, NULL);
return 0;
}

Просмотреть файл

@ -1213,8 +1213,32 @@ static int cpm_uart_init_port(struct device_node *np,
goto out_pram;
}
for (i = 0; i < NUM_GPIOS; i++)
pinfo->gpios[i] = of_get_gpio(np, i);
for (i = 0; i < NUM_GPIOS; i++) {
int gpio;
pinfo->gpios[i] = -1;
gpio = of_get_gpio(np, i);
if (gpio_is_valid(gpio)) {
ret = gpio_request(gpio, "cpm_uart");
if (ret) {
pr_err("can't request gpio #%d: %d\n", i, ret);
continue;
}
if (i == GPIO_RTS || i == GPIO_DTR)
ret = gpio_direction_output(gpio, 0);
else
ret = gpio_direction_input(gpio);
if (ret) {
pr_err("can't set direction for gpio #%d: %d\n",
i, ret);
gpio_free(gpio);
continue;
}
pinfo->gpios[i] = gpio;
}
}
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
udbg_putc = NULL;

Просмотреть файл

@ -268,10 +268,10 @@ static irqreturn_t efm32_uart_rxirq(int irq, void *data)
handled = IRQ_HANDLED;
}
tty_flip_buffer_push(tport);
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
return handled;
}
@ -698,6 +698,7 @@ static int efm32_uart_probe(struct platform_device *pdev)
{
struct efm32_uart_port *efm_port;
struct resource *res;
unsigned int line;
int ret;
efm_port = kzalloc(sizeof(*efm_port), GFP_KERNEL);
@ -750,18 +751,21 @@ static int efm32_uart_probe(struct platform_device *pdev)
if (pdata)
efm_port->pdata = *pdata;
}
} else if (ret < 0)
goto err_probe_dt;
if (efm_port->port.line >= 0 &&
efm_port->port.line < ARRAY_SIZE(efm32_uart_ports))
efm32_uart_ports[efm_port->port.line] = efm_port;
line = efm_port->port.line;
if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports))
efm32_uart_ports[line] = efm_port;
ret = uart_add_one_port(&efm32_uart_reg, &efm_port->port);
if (ret) {
dev_dbg(&pdev->dev, "failed to add port: %d\n", ret);
if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports))
efm32_uart_ports[pdev->id] = NULL;
if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports))
efm32_uart_ports[line] = NULL;
err_probe_dt:
err_get_rxirq:
err_too_small:
err_get_base:
@ -777,20 +781,19 @@ err_get_base:
static int efm32_uart_remove(struct platform_device *pdev)
{
struct efm32_uart_port *efm_port = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
unsigned int line = efm_port->port.line;
uart_remove_one_port(&efm32_uart_reg, &efm_port->port);
if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(efm32_uart_ports))
efm32_uart_ports[pdev->id] = NULL;
if (line >= 0 && line < ARRAY_SIZE(efm32_uart_ports))
efm32_uart_ports[line] = NULL;
kfree(efm_port);
return 0;
}
static struct of_device_id efm32_uart_dt_ids[] = {
static const struct of_device_id efm32_uart_dt_ids[] = {
{
.compatible = "efm32,uart",
}, {

Просмотреть файл

@ -342,8 +342,10 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state)
static void lpuart_setup_watermark(struct lpuart_port *sport)
{
unsigned char val, cr2;
unsigned char cr2_saved;
cr2 = readb(sport->port.membase + UARTCR2);
cr2_saved = cr2;
cr2 &= ~(UARTCR2_TIE | UARTCR2_TCIE | UARTCR2_TE |
UARTCR2_RIE | UARTCR2_RE);
writeb(cr2, sport->port.membase + UARTCR2);
@ -366,6 +368,9 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
writeb(2, sport->port.membase + UARTTWFIFO);
writeb(1, sport->port.membase + UARTRWFIFO);
/* Restore cr2 */
writeb(cr2_saved, sport->port.membase + UARTCR2);
}
static int lpuart_startup(struct uart_port *port)
@ -858,7 +863,7 @@ static int __init lpuart_serial_init(void)
if (ret)
uart_unregister_driver(&lpuart_reg);
return 0;
return ret;
}
static void __exit lpuart_serial_exit(void)

Просмотреть файл

@ -105,7 +105,7 @@ static const struct pci_device_id icom_pci_table[] = {
{}
};
struct lookup_proc_table start_proc[4] = {
static struct lookup_proc_table start_proc[4] = {
{NULL, ICOM_CONTROL_START_A},
{NULL, ICOM_CONTROL_START_B},
{NULL, ICOM_CONTROL_START_C},
@ -113,14 +113,14 @@ struct lookup_proc_table start_proc[4] = {
};
struct lookup_proc_table stop_proc[4] = {
static struct lookup_proc_table stop_proc[4] = {
{NULL, ICOM_CONTROL_STOP_A},
{NULL, ICOM_CONTROL_STOP_B},
{NULL, ICOM_CONTROL_STOP_C},
{NULL, ICOM_CONTROL_STOP_D}
};
struct lookup_int_table int_mask_tbl[4] = {
static struct lookup_int_table int_mask_tbl[4] = {
{NULL, ICOM_INT_MASK_PRC_A},
{NULL, ICOM_INT_MASK_PRC_B},
{NULL, ICOM_INT_MASK_PRC_C},
@ -297,25 +297,25 @@ static void stop_processor(struct icom_port *icom_port)
spin_lock_irqsave(&icom_lock, flags);
port = icom_port->port;
if (port >= ARRAY_SIZE(stop_proc)) {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
goto unlock;
}
if (port == 0 || port == 1)
stop_proc[port].global_control_reg = &icom_port->global_reg->control;
else
stop_proc[port].global_control_reg = &icom_port->global_reg->control_2;
temp = readl(stop_proc[port].global_control_reg);
temp = (temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
writel(temp, stop_proc[port].global_control_reg);
if (port < 4) {
temp = readl(stop_proc[port].global_control_reg);
temp =
(temp & ~start_proc[port].processor_id) | stop_proc[port].processor_id;
writel(temp, stop_proc[port].global_control_reg);
/* write flush */
readl(stop_proc[port].global_control_reg);
} else {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
}
/* write flush */
readl(stop_proc[port].global_control_reg);
unlock:
spin_unlock_irqrestore(&icom_lock, flags);
}
@ -328,23 +328,25 @@ static void start_processor(struct icom_port *icom_port)
spin_lock_irqsave(&icom_lock, flags);
port = icom_port->port;
if (port >= ARRAY_SIZE(start_proc)) {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
goto unlock;
}
if (port == 0 || port == 1)
start_proc[port].global_control_reg = &icom_port->global_reg->control;
else
start_proc[port].global_control_reg = &icom_port->global_reg->control_2;
if (port < 4) {
temp = readl(start_proc[port].global_control_reg);
temp =
(temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
writel(temp, start_proc[port].global_control_reg);
/* write flush */
readl(start_proc[port].global_control_reg);
} else {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
}
temp = readl(start_proc[port].global_control_reg);
temp = (temp & ~stop_proc[port].processor_id) | start_proc[port].processor_id;
writel(temp, start_proc[port].global_control_reg);
/* write flush */
readl(start_proc[port].global_control_reg);
unlock:
spin_unlock_irqrestore(&icom_lock, flags);
}
@ -557,6 +559,12 @@ static int startup(struct icom_port *icom_port)
*/
spin_lock_irqsave(&icom_lock, flags);
port = icom_port->port;
if (port >= ARRAY_SIZE(int_mask_tbl)) {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
goto unlock;
}
if (port == 0 || port == 1)
int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
else
@ -566,17 +574,14 @@ static int startup(struct icom_port *icom_port)
writew(0x00FF, icom_port->int_reg);
else
writew(0x3F00, icom_port->int_reg);
if (port < 4) {
temp = readl(int_mask_tbl[port].global_int_mask);
writel(temp & ~int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
/* write flush */
readl(int_mask_tbl[port].global_int_mask);
} else {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
}
temp = readl(int_mask_tbl[port].global_int_mask);
writel(temp & ~int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
/* write flush */
readl(int_mask_tbl[port].global_int_mask);
unlock:
spin_unlock_irqrestore(&icom_lock, flags);
return 0;
}
@ -595,21 +600,23 @@ static void shutdown(struct icom_port *icom_port)
* disable all interrupts
*/
port = icom_port->port;
if (port >= ARRAY_SIZE(int_mask_tbl)) {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
goto unlock;
}
if (port == 0 || port == 1)
int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask;
else
int_mask_tbl[port].global_int_mask = &icom_port->global_reg->int_mask_2;
if (port < 4) {
temp = readl(int_mask_tbl[port].global_int_mask);
writel(temp | int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
temp = readl(int_mask_tbl[port].global_int_mask);
writel(temp | int_mask_tbl[port].processor_id, int_mask_tbl[port].global_int_mask);
/* write flush */
readl(int_mask_tbl[port].global_int_mask);
} else {
dev_err(&icom_port->adapter->pci_dev->dev,
"Invalid port assignment\n");
}
/* write flush */
readl(int_mask_tbl[port].global_int_mask);
unlock:
spin_unlock_irqrestore(&icom_lock, flags);
/*
@ -834,7 +841,10 @@ ignore_char:
status = cpu_to_le16(icom_port->statStg->rcv[rcv_buff].flags);
}
icom_port->next_rcv = rcv_buff;
spin_unlock(&icom_port->uart_port.lock);
tty_flip_buffer_push(port);
spin_lock(&icom_port->uart_port.lock);
}
static void process_interrupt(u16 port_int_reg,
@ -1087,8 +1097,7 @@ static void icom_close(struct uart_port *port)
/* stop receiver */
cmdReg = readb(&ICOM_PORT->dram->CmdReg);
writeb(cmdReg & (unsigned char) ~CMD_RCV_ENABLE,
&ICOM_PORT->dram->CmdReg);
writeb(cmdReg & ~CMD_RCV_ENABLE, &ICOM_PORT->dram->CmdReg);
shutdown(ICOM_PORT);
@ -1567,7 +1576,7 @@ static int icom_probe(struct pci_dev *dev,
icom_port->uart_port.type = PORT_ICOM;
icom_port->uart_port.iotype = UPIO_MEM;
icom_port->uart_port.membase =
(char *) icom_adapter->base_addr_pci;
(unsigned char __iomem *)icom_adapter->base_addr_pci;
icom_port->uart_port.fifosize = 16;
icom_port->uart_port.ops = &icom_ops;
icom_port->uart_port.line =

Просмотреть файл

@ -1008,7 +1008,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
return -ENODEV;
}
pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data;
pl_data = (struct ifx_modem_platform_data *)dev_get_platdata(&spi->dev);
if (!pl_data) {
dev_err(&spi->dev, "missing platform data!");
return -ENODEV;

Просмотреть файл

@ -47,11 +47,12 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <asm/irq.h>
#include <linux/platform_data/serial-imx.h>
#include <linux/platform_data/dma-imx.h>
/* Register definitions */
#define URXD0 0x0 /* Receiver Register */
@ -83,6 +84,7 @@
#define UCR1_ADBR (1<<14) /* Auto detect baud rate */
#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
#define UCR1_IDEN (1<<12) /* Idle condition interrupt */
#define UCR1_ICD_REG(x) (((x) & 3) << 10) /* idle condition detect */
#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
#define UCR1_IREN (1<<7) /* Infrared interface enable */
@ -91,6 +93,7 @@
#define UCR1_SNDBRK (1<<4) /* Send break */
#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
#define IMX1_UCR1_UARTCLKEN (1<<2) /* UART clock enabled, i.mx1 only */
#define UCR1_ATDMAEN (1<<2) /* Aging DMA Timer Enable */
#define UCR1_DOZE (1<<1) /* Doze */
#define UCR1_UARTEN (1<<0) /* UART enabled */
#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
@ -126,6 +129,7 @@
#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
#define UCR4_WKEN (1<<7) /* Wake interrupt enable */
#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */
#define UCR4_IDDMAEN (1<<6) /* DMA IDLE Condition Detected */
#define UCR4_IRSC (1<<5) /* IR special case */
#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */
#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */
@ -187,6 +191,7 @@
enum imx_uart_type {
IMX1_UART,
IMX21_UART,
IMX6Q_UART,
};
/* device type dependent stuff */
@ -209,6 +214,19 @@ struct imx_port {
struct clk *clk_ipg;
struct clk *clk_per;
const struct imx_uart_data *devdata;
/* DMA fields */
unsigned int dma_is_inited:1;
unsigned int dma_is_enabled:1;
unsigned int dma_is_rxing:1;
unsigned int dma_is_txing:1;
struct dma_chan *dma_chan_rx, *dma_chan_tx;
struct scatterlist rx_sgl, tx_sgl[2];
void *rx_buf;
unsigned int rx_bytes, tx_bytes;
struct work_struct tsk_dma_rx, tsk_dma_tx;
unsigned int dma_tx_nents;
wait_queue_head_t dma_wait;
};
struct imx_port_ucrs {
@ -232,6 +250,10 @@ static struct imx_uart_data imx_uart_devdata[] = {
.uts_reg = IMX21_UTS,
.devtype = IMX21_UART,
},
[IMX6Q_UART] = {
.uts_reg = IMX21_UTS,
.devtype = IMX6Q_UART,
},
};
static struct platform_device_id imx_uart_devtype[] = {
@ -241,6 +263,9 @@ static struct platform_device_id imx_uart_devtype[] = {
}, {
.name = "imx21-uart",
.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX21_UART],
}, {
.name = "imx6q-uart",
.driver_data = (kernel_ulong_t) &imx_uart_devdata[IMX6Q_UART],
}, {
/* sentinel */
}
@ -248,6 +273,7 @@ static struct platform_device_id imx_uart_devtype[] = {
MODULE_DEVICE_TABLE(platform, imx_uart_devtype);
static struct of_device_id imx_uart_dt_ids[] = {
{ .compatible = "fsl,imx6q-uart", .data = &imx_uart_devdata[IMX6Q_UART], },
{ .compatible = "fsl,imx1-uart", .data = &imx_uart_devdata[IMX1_UART], },
{ .compatible = "fsl,imx21-uart", .data = &imx_uart_devdata[IMX21_UART], },
{ /* sentinel */ }
@ -269,6 +295,10 @@ static inline int is_imx21_uart(struct imx_port *sport)
return sport->devdata->devtype == IMX21_UART;
}
static inline int is_imx6q_uart(struct imx_port *sport)
{
return sport->devdata->devtype == IMX6Q_UART;
}
/*
* Save and restore functions for UCR1, UCR2 and UCR3 registers
*/
@ -387,6 +417,13 @@ static void imx_stop_tx(struct uart_port *port)
return;
}
/*
* We are maybe in the SMP context, so if the DMA TX thread is running
* on other cpu, we have to wait for it to finish.
*/
if (sport->dma_is_enabled && sport->dma_is_txing)
return;
temp = readl(sport->port.membase + UCR1);
writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1);
}
@ -399,6 +436,13 @@ static void imx_stop_rx(struct uart_port *port)
struct imx_port *sport = (struct imx_port *)port;
unsigned long temp;
/*
* We are maybe in the SMP context, so if the DMA TX thread is running
* on other cpu, we have to wait for it to finish.
*/
if (sport->dma_is_enabled && sport->dma_is_rxing)
return;
temp = readl(sport->port.membase + UCR2);
writel(temp & ~UCR2_RXEN, sport->port.membase + UCR2);
}
@ -434,6 +478,95 @@ static inline void imx_transmit_buffer(struct imx_port *sport)
imx_stop_tx(&sport->port);
}
static void dma_tx_callback(void *data)
{
struct imx_port *sport = data;
struct scatterlist *sgl = &sport->tx_sgl[0];
struct circ_buf *xmit = &sport->port.state->xmit;
unsigned long flags;
dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
sport->dma_is_txing = 0;
/* update the stat */
spin_lock_irqsave(&sport->port.lock, flags);
xmit->tail = (xmit->tail + sport->tx_bytes) & (UART_XMIT_SIZE - 1);
sport->port.icount.tx += sport->tx_bytes;
spin_unlock_irqrestore(&sport->port.lock, flags);
dev_dbg(sport->port.dev, "we finish the TX DMA.\n");
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&sport->port);
if (waitqueue_active(&sport->dma_wait)) {
wake_up(&sport->dma_wait);
dev_dbg(sport->port.dev, "exit in %s.\n", __func__);
return;
}
schedule_work(&sport->tsk_dma_tx);
}
static void dma_tx_work(struct work_struct *w)
{
struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_tx);
struct circ_buf *xmit = &sport->port.state->xmit;
struct scatterlist *sgl = sport->tx_sgl;
struct dma_async_tx_descriptor *desc;
struct dma_chan *chan = sport->dma_chan_tx;
struct device *dev = sport->port.dev;
enum dma_status status;
unsigned long flags;
int ret;
status = chan->device->device_tx_status(chan, (dma_cookie_t)0, NULL);
if (DMA_IN_PROGRESS == status)
return;
spin_lock_irqsave(&sport->port.lock, flags);
sport->tx_bytes = uart_circ_chars_pending(xmit);
if (sport->tx_bytes == 0) {
spin_unlock_irqrestore(&sport->port.lock, flags);
return;
}
if (xmit->tail > xmit->head) {
sport->dma_tx_nents = 2;
sg_init_table(sgl, 2);
sg_set_buf(sgl, xmit->buf + xmit->tail,
UART_XMIT_SIZE - xmit->tail);
sg_set_buf(sgl + 1, xmit->buf, xmit->head);
} else {
sport->dma_tx_nents = 1;
sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
}
spin_unlock_irqrestore(&sport->port.lock, flags);
ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE);
if (ret == 0) {
dev_err(dev, "DMA mapping error for TX.\n");
return;
}
desc = dmaengine_prep_slave_sg(chan, sgl, sport->dma_tx_nents,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!desc) {
dev_err(dev, "We cannot prepare for the TX slave dma!\n");
return;
}
desc->callback = dma_tx_callback;
desc->callback_param = sport;
dev_dbg(dev, "TX: prepare to send %lu bytes by DMA.\n",
uart_circ_chars_pending(xmit));
/* fire it */
sport->dma_is_txing = 1;
dmaengine_submit(desc);
dma_async_issue_pending(chan);
return;
}
/*
* interrupts disabled on entry
*/
@ -460,8 +593,10 @@ static void imx_start_tx(struct uart_port *port)
temp |= UCR4_OREN;
writel(temp, sport->port.membase + UCR4);
temp = readl(sport->port.membase + UCR1);
writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
if (!sport->dma_is_enabled) {
temp = readl(sport->port.membase + UCR1);
writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1);
}
if (USE_IRDA(sport)) {
temp = readl(sport->port.membase + UCR1);
@ -473,6 +608,15 @@ static void imx_start_tx(struct uart_port *port)
writel(temp, sport->port.membase + UCR4);
}
if (sport->dma_is_enabled) {
/*
* We may in the interrupt context, so arise a work_struct to
* do the real job.
*/
schedule_work(&sport->tsk_dma_tx);
return;
}
if (readl(sport->port.membase + uts_reg(sport)) & UTS_TXEMPTY)
imx_transmit_buffer(sport);
}
@ -588,6 +732,28 @@ out:
return IRQ_HANDLED;
}
/*
* If the RXFIFO is filled with some data, and then we
* arise a DMA operation to receive them.
*/
static void imx_dma_rxint(struct imx_port *sport)
{
unsigned long temp;
temp = readl(sport->port.membase + USR2);
if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
sport->dma_is_rxing = 1;
/* disable the `Recerver Ready Interrrupt` */
temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_RRDYEN);
writel(temp, sport->port.membase + UCR1);
/* tell the DMA to receive the data. */
schedule_work(&sport->tsk_dma_rx);
}
}
static irqreturn_t imx_int(int irq, void *dev_id)
{
struct imx_port *sport = dev_id;
@ -596,8 +762,12 @@ static irqreturn_t imx_int(int irq, void *dev_id)
sts = readl(sport->port.membase + USR1);
if (sts & USR1_RRDY)
imx_rxint(irq, dev_id);
if (sts & USR1_RRDY) {
if (sport->dma_is_enabled)
imx_dma_rxint(sport);
else
imx_rxint(irq, dev_id);
}
if (sts & USR1_TRDY &&
readl(sport->port.membase + UCR1) & UCR1_TXMPTYEN)
@ -654,7 +824,8 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
if (mctrl & TIOCM_RTS)
temp |= UCR2_CTS;
if (!sport->dma_is_enabled)
temp |= UCR2_CTS;
writel(temp, sport->port.membase + UCR2);
}
@ -693,6 +864,226 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
return 0;
}
#define RX_BUF_SIZE (PAGE_SIZE)
static int start_rx_dma(struct imx_port *sport);
static void dma_rx_work(struct work_struct *w)
{
struct imx_port *sport = container_of(w, struct imx_port, tsk_dma_rx);
struct tty_port *port = &sport->port.state->port;
if (sport->rx_bytes) {
tty_insert_flip_string(port, sport->rx_buf, sport->rx_bytes);
tty_flip_buffer_push(port);
sport->rx_bytes = 0;
}
if (sport->dma_is_rxing)
start_rx_dma(sport);
}
static void imx_rx_dma_done(struct imx_port *sport)
{
unsigned long temp;
/* Enable this interrupt when the RXFIFO is empty. */
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN;
writel(temp, sport->port.membase + UCR1);
sport->dma_is_rxing = 0;
/* Is the shutdown waiting for us? */
if (waitqueue_active(&sport->dma_wait))
wake_up(&sport->dma_wait);
}
/*
* There are three kinds of RX DMA interrupts(such as in the MX6Q):
* [1] the RX DMA buffer is full.
* [2] the Aging timer expires(wait for 8 bytes long)
* [3] the Idle Condition Detect(enabled the UCR4_IDDMAEN).
*
* The [2] is trigger when a character was been sitting in the FIFO
* meanwhile [3] can wait for 32 bytes long when the RX line is
* on IDLE state and RxFIFO is empty.
*/
static void dma_rx_callback(void *data)
{
struct imx_port *sport = data;
struct dma_chan *chan = sport->dma_chan_rx;
struct scatterlist *sgl = &sport->rx_sgl;
struct dma_tx_state state;
enum dma_status status;
unsigned int count;
/* unmap it first */
dma_unmap_sg(sport->port.dev, sgl, 1, DMA_FROM_DEVICE);
status = chan->device->device_tx_status(chan, (dma_cookie_t)0, &state);
count = RX_BUF_SIZE - state.residue;
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (count) {
sport->rx_bytes = count;
schedule_work(&sport->tsk_dma_rx);
} else
imx_rx_dma_done(sport);
}
static int start_rx_dma(struct imx_port *sport)
{
struct scatterlist *sgl = &sport->rx_sgl;
struct dma_chan *chan = sport->dma_chan_rx;
struct device *dev = sport->port.dev;
struct dma_async_tx_descriptor *desc;
int ret;
sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
if (ret == 0) {
dev_err(dev, "DMA mapping error for RX.\n");
return -EINVAL;
}
desc = dmaengine_prep_slave_sg(chan, sgl, 1, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT);
if (!desc) {
dev_err(dev, "We cannot prepare for the RX slave dma!\n");
return -EINVAL;
}
desc->callback = dma_rx_callback;
desc->callback_param = sport;
dev_dbg(dev, "RX: prepare for the DMA.\n");
dmaengine_submit(desc);
dma_async_issue_pending(chan);
return 0;
}
static void imx_uart_dma_exit(struct imx_port *sport)
{
if (sport->dma_chan_rx) {
dma_release_channel(sport->dma_chan_rx);
sport->dma_chan_rx = NULL;
kfree(sport->rx_buf);
sport->rx_buf = NULL;
}
if (sport->dma_chan_tx) {
dma_release_channel(sport->dma_chan_tx);
sport->dma_chan_tx = NULL;
}
sport->dma_is_inited = 0;
}
static int imx_uart_dma_init(struct imx_port *sport)
{
struct dma_slave_config slave_config = {};
struct device *dev = sport->port.dev;
int ret;
/* Prepare for RX : */
sport->dma_chan_rx = dma_request_slave_channel(dev, "rx");
if (!sport->dma_chan_rx) {
dev_dbg(dev, "cannot get the DMA channel.\n");
ret = -EINVAL;
goto err;
}
slave_config.direction = DMA_DEV_TO_MEM;
slave_config.src_addr = sport->port.mapbase + URXD0;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave_config.src_maxburst = RXTL;
ret = dmaengine_slave_config(sport->dma_chan_rx, &slave_config);
if (ret) {
dev_err(dev, "error in RX dma configuration.\n");
goto err;
}
sport->rx_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!sport->rx_buf) {
dev_err(dev, "cannot alloc DMA buffer.\n");
ret = -ENOMEM;
goto err;
}
sport->rx_bytes = 0;
/* Prepare for TX : */
sport->dma_chan_tx = dma_request_slave_channel(dev, "tx");
if (!sport->dma_chan_tx) {
dev_err(dev, "cannot get the TX DMA channel!\n");
ret = -EINVAL;
goto err;
}
slave_config.direction = DMA_MEM_TO_DEV;
slave_config.dst_addr = sport->port.mapbase + URTX0;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave_config.dst_maxburst = TXTL;
ret = dmaengine_slave_config(sport->dma_chan_tx, &slave_config);
if (ret) {
dev_err(dev, "error in TX dma configuration.");
goto err;
}
sport->dma_is_inited = 1;
return 0;
err:
imx_uart_dma_exit(sport);
return ret;
}
static void imx_enable_dma(struct imx_port *sport)
{
unsigned long temp;
struct tty_port *port = &sport->port.state->port;
port->low_latency = 1;
INIT_WORK(&sport->tsk_dma_tx, dma_tx_work);
INIT_WORK(&sport->tsk_dma_rx, dma_rx_work);
init_waitqueue_head(&sport->dma_wait);
/* set UCR1 */
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN |
/* wait for 32 idle frames for IDDMA interrupt */
UCR1_ICD_REG(3);
writel(temp, sport->port.membase + UCR1);
/* set UCR4 */
temp = readl(sport->port.membase + UCR4);
temp |= UCR4_IDDMAEN;
writel(temp, sport->port.membase + UCR4);
sport->dma_is_enabled = 1;
}
static void imx_disable_dma(struct imx_port *sport)
{
unsigned long temp;
struct tty_port *port = &sport->port.state->port;
/* clear UCR1 */
temp = readl(sport->port.membase + UCR1);
temp &= ~(UCR1_RDMAEN | UCR1_TDMAEN | UCR1_ATDMAEN);
writel(temp, sport->port.membase + UCR1);
/* clear UCR2 */
temp = readl(sport->port.membase + UCR2);
temp &= ~(UCR2_CTSC | UCR2_CTS);
writel(temp, sport->port.membase + UCR2);
/* clear UCR4 */
temp = readl(sport->port.membase + UCR4);
temp &= ~UCR4_IDDMAEN;
writel(temp, sport->port.membase + UCR4);
sport->dma_is_enabled = 0;
port->low_latency = 0;
}
/* half the RX buffer size */
#define CTSTL 16
@ -702,15 +1093,13 @@ static int imx_startup(struct uart_port *port)
int retval;
unsigned long flags, temp;
if (!uart_console(port)) {
retval = clk_prepare_enable(sport->clk_per);
if (retval)
goto error_out1;
retval = clk_prepare_enable(sport->clk_ipg);
if (retval) {
clk_disable_unprepare(sport->clk_per);
goto error_out1;
}
retval = clk_prepare_enable(sport->clk_per);
if (retval)
goto error_out1;
retval = clk_prepare_enable(sport->clk_ipg);
if (retval) {
clk_disable_unprepare(sport->clk_per);
goto error_out1;
}
imx_setup_ufcr(sport, 0);
@ -803,7 +1192,7 @@ static int imx_startup(struct uart_port *port)
}
}
if (is_imx21_uart(sport)) {
if (!is_imx1_uart(sport)) {
temp = readl(sport->port.membase + UCR3);
temp |= IMX21_UCR3_RXDMUXSEL;
writel(temp, sport->port.membase + UCR3);
@ -833,7 +1222,7 @@ static int imx_startup(struct uart_port *port)
if (USE_IRDA(sport)) {
struct imxuart_platform_data *pdata;
pdata = sport->port.dev->platform_data;
pdata = dev_get_platdata(sport->port.dev);
sport->irda_inv_rx = pdata->irda_inv_rx;
sport->irda_inv_tx = pdata->irda_inv_tx;
sport->trcv_delay = pdata->transceiver_delay;
@ -859,6 +1248,15 @@ static void imx_shutdown(struct uart_port *port)
unsigned long temp;
unsigned long flags;
if (sport->dma_is_enabled) {
/* We have to wait for the DMA to finish. */
wait_event(sport->dma_wait,
!sport->dma_is_rxing && !sport->dma_is_txing);
imx_stop_rx(port);
imx_disable_dma(sport);
imx_uart_dma_exit(sport);
}
spin_lock_irqsave(&sport->port.lock, flags);
temp = readl(sport->port.membase + UCR2);
temp &= ~(UCR2_TXEN);
@ -867,7 +1265,7 @@ static void imx_shutdown(struct uart_port *port)
if (USE_IRDA(sport)) {
struct imxuart_platform_data *pdata;
pdata = sport->port.dev->platform_data;
pdata = dev_get_platdata(sport->port.dev);
if (pdata->irda_enable)
pdata->irda_enable(0);
}
@ -901,10 +1299,8 @@ static void imx_shutdown(struct uart_port *port)
writel(temp, sport->port.membase + UCR1);
spin_unlock_irqrestore(&sport->port.lock, flags);
if (!uart_console(&sport->port)) {
clk_disable_unprepare(sport->clk_per);
clk_disable_unprepare(sport->clk_ipg);
}
clk_disable_unprepare(sport->clk_per);
clk_disable_unprepare(sport->clk_ipg);
}
static void
@ -947,6 +1343,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
if (sport->have_rtscts) {
ucr2 &= ~UCR2_IRTS;
ucr2 |= UCR2_CTSC;
/* Can we enable the DMA support? */
if (is_imx6q_uart(sport) && !uart_console(port)
&& !sport->dma_is_inited)
imx_uart_dma_init(sport);
} else {
termios->c_cflag &= ~CRTSCTS;
}
@ -1020,6 +1421,11 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
*/
div = 1;
} else {
/* custom-baudrate handling */
div = sport->port.uartclk / (baud * 16);
if (baud == 38400 && quot != div)
baud = sport->port.uartclk / (quot * 16);
div = sport->port.uartclk / (baud * 16);
if (div > 7)
div = 7;
@ -1048,7 +1454,7 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
writel(num, sport->port.membase + UBIR);
writel(denom, sport->port.membase + UBMR);
if (is_imx21_uart(sport))
if (!is_imx1_uart(sport))
writel(sport->port.uartclk / div / 1000,
sport->port.membase + IMX21_ONEMS);
@ -1060,6 +1466,8 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
imx_enable_ms(&sport->port);
if (sport->dma_is_inited && !sport->dma_is_enabled)
imx_enable_dma(sport);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
@ -1251,6 +1659,16 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
unsigned int ucr1;
unsigned long flags = 0;
int locked = 1;
int retval;
retval = clk_enable(sport->clk_per);
if (retval)
return;
retval = clk_enable(sport->clk_ipg);
if (retval) {
clk_disable(sport->clk_per);
return;
}
if (sport->port.sysrq)
locked = 0;
@ -1286,6 +1704,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
if (locked)
spin_unlock_irqrestore(&sport->port.lock, flags);
clk_disable(sport->clk_ipg);
clk_disable(sport->clk_per);
}
/*
@ -1359,6 +1780,7 @@ imx_console_setup(struct console *co, char *options)
int bits = 8;
int parity = 'n';
int flow = 'n';
int retval;
/*
* Check whether an invalid uart number has been specified, and
@ -1371,6 +1793,11 @@ imx_console_setup(struct console *co, char *options)
if (sport == NULL)
return -ENODEV;
/* For setting the registers, we only need to enable the ipg clock. */
retval = clk_prepare_enable(sport->clk_ipg);
if (retval)
goto error_console;
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
@ -1378,7 +1805,20 @@ imx_console_setup(struct console *co, char *options)
imx_setup_ufcr(sport, 0);
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
clk_disable(sport->clk_ipg);
if (retval) {
clk_unprepare(sport->clk_ipg);
goto error_console;
}
retval = clk_prepare(sport->clk_per);
if (retval)
clk_disable_unprepare(sport->clk_ipg);
error_console:
return retval;
}
static struct uart_driver imx_reg;
@ -1472,6 +1912,9 @@ static int serial_imx_probe_dt(struct imx_port *sport,
sport->devdata = of_id->data;
if (of_device_is_stdout_path(np))
add_preferred_console(imx_reg.cons->name, sport->port.line, 0);
return 0;
}
#else
@ -1485,7 +1928,7 @@ static inline int serial_imx_probe_dt(struct imx_port *sport,
static void serial_imx_probe_pdata(struct imx_port *sport,
struct platform_device *pdev)
{
struct imxuart_platform_data *pdata = pdev->dev.platform_data;
struct imxuart_platform_data *pdata = dev_get_platdata(&pdev->dev);
sport->port.line = pdev->id;
sport->devdata = (struct imx_uart_data *) pdev->id_entry->driver_data;
@ -1507,7 +1950,6 @@ static int serial_imx_probe(struct platform_device *pdev)
void __iomem *base;
int ret = 0;
struct resource *res;
struct pinctrl *pinctrl;
sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
if (!sport)
@ -1543,13 +1985,6 @@ static int serial_imx_probe(struct platform_device *pdev)
sport->timer.function = imx_timeout;
sport->timer.data = (unsigned long)sport;
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) {
ret = PTR_ERR(pinctrl);
dev_err(&pdev->dev, "failed to get default pinctrl: %d\n", ret);
return ret;
}
sport->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
if (IS_ERR(sport->clk_ipg)) {
ret = PTR_ERR(sport->clk_ipg);
@ -1564,18 +1999,15 @@ static int serial_imx_probe(struct platform_device *pdev)
return ret;
}
clk_prepare_enable(sport->clk_per);
clk_prepare_enable(sport->clk_ipg);
sport->port.uartclk = clk_get_rate(sport->clk_per);
imx_ports[sport->port.line] = sport;
pdata = pdev->dev.platform_data;
pdata = dev_get_platdata(&pdev->dev);
if (pdata && pdata->init) {
ret = pdata->init(pdev);
if (ret)
goto clkput;
return ret;
}
ret = uart_add_one_port(&imx_reg, &sport->port);
@ -1583,18 +2015,10 @@ static int serial_imx_probe(struct platform_device *pdev)
goto deinit;
platform_set_drvdata(pdev, sport);
if (!uart_console(&sport->port)) {
clk_disable_unprepare(sport->clk_per);
clk_disable_unprepare(sport->clk_ipg);
}
return 0;
deinit:
if (pdata && pdata->exit)
pdata->exit(pdev);
clkput:
clk_disable_unprepare(sport->clk_per);
clk_disable_unprepare(sport->clk_ipg);
return ret;
}
@ -1603,9 +2027,7 @@ static int serial_imx_remove(struct platform_device *pdev)
struct imxuart_platform_data *pdata;
struct imx_port *sport = platform_get_drvdata(pdev);
pdata = pdev->dev.platform_data;
platform_set_drvdata(pdev, NULL);
pdata = dev_get_platdata(&pdev->dev);
uart_remove_one_port(&imx_reg, &sport->port);

Просмотреть файл

@ -297,7 +297,7 @@ struct ioc4_serial {
struct ioc4_uartregs uart_1;
struct ioc4_uartregs uart_2;
struct ioc4_uartregs uart_3;
} ioc4_serial;
};
/* UART clock speed */
#define IOC4_SER_XIN_CLK_66 66666667
@ -2767,7 +2767,7 @@ ioc4_serial_core_attach(struct pci_dev *pdev, int port_type)
* called per card found from IOC4 master module.
* @idd: Master module data for this IOC4
*/
int
static int
ioc4_serial_attach_one(struct ioc4_driver_data *idd)
{
unsigned long tmp_addr1;

Просмотреть файл

@ -318,7 +318,7 @@ lqasc_startup(struct uart_port *port)
struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
int retval;
if (ltq_port->clk)
if (!IS_ERR(ltq_port->clk))
clk_enable(ltq_port->clk);
port->uartclk = clk_get_rate(ltq_port->fpiclk);
@ -386,7 +386,7 @@ lqasc_shutdown(struct uart_port *port)
port->membase + LTQ_ASC_RXFCON);
ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
port->membase + LTQ_ASC_TXFCON);
if (ltq_port->clk)
if (!IS_ERR(ltq_port->clk))
clk_disable(ltq_port->clk);
}
@ -636,6 +636,9 @@ lqasc_console_setup(struct console *co, char *options)
port = &ltq_port->port;
if (!IS_ERR(ltq_port->clk))
clk_enable(ltq_port->clk);
port->uartclk = clk_get_rate(ltq_port->fpiclk);
if (options)

Просмотреть файл

@ -279,7 +279,10 @@ static void __serial_lpc32xx_rx(struct uart_port *port)
tmp = readl(LPC32XX_HSUART_FIFO(port->membase));
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
}
static void __serial_lpc32xx_tx(struct uart_port *port)
@ -351,10 +354,8 @@ static irqreturn_t serial_lpc32xx_interrupt(int irq, void *dev_id)
}
/* Data received? */
if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT)) {
if (status & (LPC32XX_HSU_RX_TIMEOUT_INT | LPC32XX_HSU_RX_TRIG_INT))
__serial_lpc32xx_rx(port);
tty_flip_buffer_push(tport);
}
/* Transmit data request? */
if ((status & LPC32XX_HSU_TX_INT) && (!uart_tx_stopped(port))) {

Просмотреть файл

@ -368,7 +368,10 @@ static void receive_chars(struct uart_sio_port *up, int *status)
ignore_char:
*status = serial_in(up, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
spin_lock(&up->port.lock);
}
static void transmit_chars(struct uart_sio_port *up)

Просмотреть файл

@ -779,7 +779,7 @@ static int max3100_probe(struct spi_device *spi)
max3100s[i]->irq = spi->irq;
spin_lock_init(&max3100s[i]->conf_lock);
spi_set_drvdata(spi, max3100s[i]);
pdata = spi->dev.platform_data;
pdata = dev_get_platdata(&spi->dev);
max3100s[i]->crystal = pdata->crystal;
max3100s[i]->loopback = pdata->loopback;
max3100s[i]->poll_time = pdata->poll_time * HZ / 1000;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -24,6 +24,7 @@
#include <linux/serial_core.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfuart.h>
@ -324,7 +325,9 @@ static void mcf_rx_chars(struct mcf_uart *pp)
uart_insert_char(port, status, MCFUART_USR_RXOVERRUN, ch, flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(&port->state->port);
spin_lock(&port->lock);
}
/****************************************************************************/
@ -644,7 +647,7 @@ static struct uart_driver mcf_driver = {
static int mcf_probe(struct platform_device *pdev)
{
struct mcf_platform_uart *platp = pdev->dev.platform_data;
struct mcf_platform_uart *platp = dev_get_platdata(&pdev->dev);
struct uart_port *port;
int i;

Просмотреть файл

@ -386,7 +386,7 @@ static void serial_hsu_stop_tx(struct uart_port *port)
/* This is always called in spinlock protected mode, so
* modify timeout timer is safe here */
void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts, unsigned long *flags)
{
struct hsu_dma_buffer *dbuf = &up->rxbuf;
struct hsu_dma_chan *chan = up->rxc;
@ -438,7 +438,9 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
| (0x1 << 16)
| (0x1 << 24) /* timeout bit, see HSU Errata 1 */
);
spin_unlock_irqrestore(&up->port.lock, *flags);
tty_flip_buffer_push(tport);
spin_lock_irqsave(&up->port.lock, *flags);
chan_writel(chan, HSU_CH_CR, 0x3);
@ -459,7 +461,8 @@ static void serial_hsu_stop_rx(struct uart_port *port)
}
}
static inline void receive_chars(struct uart_hsu_port *up, int *status)
static inline void receive_chars(struct uart_hsu_port *up, int *status,
unsigned long *flags)
{
unsigned int ch, flag;
unsigned int max_count = 256;
@ -519,7 +522,10 @@ static inline void receive_chars(struct uart_hsu_port *up, int *status)
ignore_char:
*status = serial_in(up, UART_LSR);
} while ((*status & UART_LSR_DR) && max_count--);
spin_unlock_irqrestore(&up->port.lock, *flags);
tty_flip_buffer_push(&up->port.state->port);
spin_lock_irqsave(&up->port.lock, *flags);
}
static void transmit_chars(struct uart_hsu_port *up)
@ -613,7 +619,7 @@ static irqreturn_t port_irq(int irq, void *dev_id)
lsr = serial_in(up, UART_LSR);
if (lsr & UART_LSR_DR)
receive_chars(up, &lsr);
receive_chars(up, &lsr, &flags);
check_modem_status(up);
/* lsr will be renewed during the receive_chars */
@ -643,7 +649,7 @@ static inline void dma_chan_irq(struct hsu_dma_chan *chan)
/* Rx channel */
if (chan->dirt == DMA_FROM_DEVICE)
hsu_dma_rx(up, int_sts);
hsu_dma_rx(up, int_sts, &flags);
/* Tx channel */
if (chan->dirt == DMA_TO_DEVICE) {

Просмотреть файл

@ -934,7 +934,7 @@ static int serial_polled;
******************************************************************************
*/
static int mpsc_rx_intr(struct mpsc_port_info *pi)
static int mpsc_rx_intr(struct mpsc_port_info *pi, unsigned long *flags)
{
struct mpsc_rx_desc *rxre;
struct tty_port *port = &pi->port.state->port;
@ -969,8 +969,11 @@ static int mpsc_rx_intr(struct mpsc_port_info *pi)
#endif
/* Following use of tty struct directly is deprecated */
if (tty_buffer_request_room(port, bytes_in) < bytes_in) {
if (port->low_latency)
if (port->low_latency) {
spin_unlock_irqrestore(&pi->port.lock, *flags);
tty_flip_buffer_push(port);
spin_lock_irqsave(&pi->port.lock, *flags);
}
/*
* If this failed then we will throw away the bytes
* but must do so to clear interrupts.
@ -1080,7 +1083,9 @@ next_frame:
if ((readl(pi->sdma_base + SDMA_SDCM) & SDMA_SDCM_ERD) == 0)
mpsc_start_rx(pi);
spin_unlock_irqrestore(&pi->port.lock, *flags);
tty_flip_buffer_push(port);
spin_lock_irqsave(&pi->port.lock, *flags);
return rc;
}
@ -1222,7 +1227,7 @@ static irqreturn_t mpsc_sdma_intr(int irq, void *dev_id)
spin_lock_irqsave(&pi->port.lock, iflags);
mpsc_sdma_intr_ack(pi);
if (mpsc_rx_intr(pi))
if (mpsc_rx_intr(pi, &iflags))
rc = IRQ_HANDLED;
if (mpsc_tx_intr(pi))
rc = IRQ_HANDLED;
@ -1884,7 +1889,7 @@ static int mpsc_shared_drv_probe(struct platform_device *dev)
if (dev->id == 0) {
if (!(rc = mpsc_shared_map_regs(dev))) {
pdata = (struct mpsc_shared_pdata *)
dev->dev.platform_data;
dev_get_platdata(&dev->dev);
mpsc_shared_regs.MPSC_MRR_m = pdata->mrr_val;
mpsc_shared_regs.MPSC_RCRR_m= pdata->rcrr_val;
@ -2025,7 +2030,7 @@ static void mpsc_drv_get_platform_data(struct mpsc_port_info *pi,
{
struct mpsc_pdata *pdata;
pdata = (struct mpsc_pdata *)pd->dev.platform_data;
pdata = (struct mpsc_pdata *)dev_get_platdata(&pd->dev);
pi->port.uartclk = pdata->brg_clk_freq;
pi->port.iotype = UPIO_MEM;

Просмотреть файл

@ -713,7 +713,7 @@ static void serial_m3110_enable_ms(struct uart_port *port)
{
}
struct uart_ops serial_m3110_ops = {
static struct uart_ops serial_m3110_ops = {
.tx_empty = serial_m3110_tx_empty,
.set_mctrl = serial_m3110_set_mctrl,
.get_mctrl = serial_m3110_get_mctrl,
@ -844,7 +844,7 @@ static int serial_m3110_probe(struct spi_device *spi)
pmax = max;
/* Give membase a psudo value to pass serial_core's check */
max->port.membase = (void *)0xff110000;
max->port.membase = (unsigned char __iomem *)0xff110000;
uart_add_one_port(&serial_m3110_reg, &max->port);
return 0;

Просмотреть файл

@ -45,16 +45,19 @@ struct msm_port {
struct clk *clk;
struct clk *pclk;
unsigned int imr;
unsigned int *gsbi_base;
void __iomem *gsbi_base;
int is_uartdm;
unsigned int old_snap_state;
};
static inline void wait_for_xmitr(struct uart_port *port, int bits)
static inline void wait_for_xmitr(struct uart_port *port)
{
if (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY))
while ((msm_read(port, UART_ISR) & bits) != bits)
cpu_relax();
while (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY)) {
if (msm_read(port, UART_ISR) & UART_ISR_TX_READY)
break;
udelay(1);
}
msm_write(port, UART_CR_CMD_RESET_TX_READY, UART_CR);
}
static void msm_stop_tx(struct uart_port *port)
@ -137,7 +140,10 @@ static void handle_rx_dm(struct uart_port *port, unsigned int misr)
count -= 4;
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
if (misr & (UART_IMR_RXSTALE))
msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
msm_write(port, 0xFFFFFF, UARTDM_DMRX);
@ -189,52 +195,69 @@ static void handle_rx(struct uart_port *port)
tty_insert_flip_char(tport, c, flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
}
static void reset_dm_count(struct uart_port *port)
static void reset_dm_count(struct uart_port *port, int count)
{
wait_for_xmitr(port, UART_ISR_TX_READY);
msm_write(port, 1, UARTDM_NCF_TX);
wait_for_xmitr(port);
msm_write(port, count, UARTDM_NCF_TX);
msm_read(port, UARTDM_NCF_TX);
}
static void handle_tx(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
struct msm_port *msm_port = UART_TO_MSM(port);
int sent_tx;
unsigned int tx_count, num_chars;
unsigned int tf_pointer = 0;
tx_count = uart_circ_chars_pending(xmit);
tx_count = min3(tx_count, (unsigned int)UART_XMIT_SIZE - xmit->tail,
port->fifosize);
if (port->x_char) {
if (msm_port->is_uartdm)
reset_dm_count(port);
reset_dm_count(port, tx_count + 1);
msm_write(port, port->x_char,
msm_port->is_uartdm ? UARTDM_TF : UART_TF);
port->icount.tx++;
port->x_char = 0;
} else if (tx_count && msm_port->is_uartdm) {
reset_dm_count(port, tx_count);
}
if (msm_port->is_uartdm)
reset_dm_count(port);
while (tf_pointer < tx_count) {
int i;
char buf[4] = { 0 };
unsigned int *bf = (unsigned int *)&buf;
while (msm_read(port, UART_SR) & UART_SR_TX_READY) {
if (uart_circ_empty(xmit)) {
/* disable tx interrupts */
msm_port->imr &= ~UART_IMR_TXLEV;
msm_write(port, msm_port->imr, UART_IMR);
if (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
break;
}
msm_write(port, xmit->buf[xmit->tail],
msm_port->is_uartdm ? UARTDM_TF : UART_TF);
if (msm_port->is_uartdm)
reset_dm_count(port);
num_chars = min(tx_count - tf_pointer,
(unsigned int)sizeof(buf));
else
num_chars = 1;
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
sent_tx = 1;
for (i = 0; i < num_chars; i++) {
buf[i] = xmit->buf[xmit->tail + i];
port->icount.tx++;
}
msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
xmit->tail = (xmit->tail + num_chars) & (UART_XMIT_SIZE - 1);
tf_pointer += num_chars;
}
/* disable tx interrupts if nothing more to send */
if (uart_circ_empty(xmit))
msm_stop_tx(port);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
}
@ -295,7 +318,7 @@ static void msm_reset(struct uart_port *port)
msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
}
void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
unsigned int mr;
mr = msm_read(port, UART_MR1);
@ -318,70 +341,60 @@ static void msm_break_ctl(struct uart_port *port, int break_ctl)
msm_write(port, UART_CR_CMD_STOP_BREAK, UART_CR);
}
struct msm_baud_map {
u16 divisor;
u8 code;
u8 rxstale;
};
static const struct msm_baud_map *
msm_find_best_baud(struct uart_port *port, unsigned int baud)
{
unsigned int i, divisor;
const struct msm_baud_map *entry;
static const struct msm_baud_map table[] = {
{ 1536, 0x00, 1 },
{ 768, 0x11, 1 },
{ 384, 0x22, 1 },
{ 192, 0x33, 1 },
{ 96, 0x44, 1 },
{ 48, 0x55, 1 },
{ 32, 0x66, 1 },
{ 24, 0x77, 1 },
{ 16, 0x88, 1 },
{ 12, 0x99, 6 },
{ 8, 0xaa, 6 },
{ 6, 0xbb, 6 },
{ 4, 0xcc, 6 },
{ 3, 0xdd, 8 },
{ 2, 0xee, 16 },
{ 1, 0xff, 31 },
};
divisor = uart_get_divisor(port, baud);
for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++)
if (entry->divisor <= divisor)
break;
return entry; /* Default to smallest divider */
}
static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
{
unsigned int baud_code, rxstale, watermark;
unsigned int rxstale, watermark;
struct msm_port *msm_port = UART_TO_MSM(port);
const struct msm_baud_map *entry;
switch (baud) {
case 300:
baud_code = UART_CSR_300;
rxstale = 1;
break;
case 600:
baud_code = UART_CSR_600;
rxstale = 1;
break;
case 1200:
baud_code = UART_CSR_1200;
rxstale = 1;
break;
case 2400:
baud_code = UART_CSR_2400;
rxstale = 1;
break;
case 4800:
baud_code = UART_CSR_4800;
rxstale = 1;
break;
case 9600:
baud_code = UART_CSR_9600;
rxstale = 2;
break;
case 14400:
baud_code = UART_CSR_14400;
rxstale = 3;
break;
case 19200:
baud_code = UART_CSR_19200;
rxstale = 4;
break;
case 28800:
baud_code = UART_CSR_28800;
rxstale = 6;
break;
case 38400:
baud_code = UART_CSR_38400;
rxstale = 8;
break;
case 57600:
baud_code = UART_CSR_57600;
rxstale = 16;
break;
case 115200:
default:
baud_code = UART_CSR_115200;
baud = 115200;
rxstale = 31;
break;
}
entry = msm_find_best_baud(port, baud);
if (msm_port->is_uartdm)
msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
msm_write(port, baud_code, UART_CSR);
msm_write(port, entry->code, UART_CSR);
/* RX stale watermark */
rxstale = entry->rxstale;
watermark = UART_IPR_STALE_LSB & rxstale;
watermark |= UART_IPR_RXSTALE_LAST;
watermark |= UART_IPR_STALE_TIMEOUT_MSB & (rxstale << 2);
@ -409,8 +422,7 @@ static void msm_init_clock(struct uart_port *port)
struct msm_port *msm_port = UART_TO_MSM(port);
clk_prepare_enable(msm_port->clk);
if (!IS_ERR(msm_port->pclk))
clk_prepare_enable(msm_port->pclk);
clk_prepare_enable(msm_port->pclk);
msm_serial_set_mnd_regs(port);
}
@ -589,12 +601,10 @@ static void msm_release_port(struct uart_port *port)
port->membase = NULL;
if (msm_port->gsbi_base) {
iowrite32(GSBI_PROTOCOL_IDLE, msm_port->gsbi_base +
GSBI_CONTROL);
gsbi_resource = platform_get_resource(pdev,
IORESOURCE_MEM, 1);
writel_relaxed(GSBI_PROTOCOL_IDLE,
msm_port->gsbi_base + GSBI_CONTROL);
gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (unlikely(!gsbi_resource))
return;
@ -637,7 +647,7 @@ static int msm_request_port(struct uart_port *port)
if (!request_mem_region(gsbi_resource->start, size,
"msm_serial")) {
ret = -EBUSY;
goto fail_release_port;
goto fail_release_port_membase;
}
msm_port->gsbi_base = ioremap(gsbi_resource->start, size);
@ -651,6 +661,8 @@ static int msm_request_port(struct uart_port *port)
fail_release_gsbi:
release_mem_region(gsbi_resource->start, size);
fail_release_port_membase:
iounmap(port->membase);
fail_release_port:
release_mem_region(port->mapbase, size);
return ret;
@ -666,10 +678,9 @@ static void msm_config_port(struct uart_port *port, int flags)
if (ret)
return;
}
if (msm_port->is_uartdm)
iowrite32(GSBI_PROTOCOL_UART, msm_port->gsbi_base +
GSBI_CONTROL);
if (msm_port->gsbi_base)
writel_relaxed(GSBI_PROTOCOL_UART,
msm_port->gsbi_base + GSBI_CONTROL);
}
static int msm_verify_port(struct uart_port *port, struct serial_struct *ser)
@ -689,13 +700,11 @@ static void msm_power(struct uart_port *port, unsigned int state,
switch (state) {
case 0:
clk_prepare_enable(msm_port->clk);
if (!IS_ERR(msm_port->pclk))
clk_prepare_enable(msm_port->pclk);
clk_prepare_enable(msm_port->pclk);
break;
case 3:
clk_disable_unprepare(msm_port->clk);
if (!IS_ERR(msm_port->pclk))
clk_disable_unprepare(msm_port->pclk);
clk_disable_unprepare(msm_port->pclk);
break;
default:
printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state);
@ -760,32 +769,63 @@ static inline struct uart_port *get_port_from_line(unsigned int line)
}
#ifdef CONFIG_SERIAL_MSM_CONSOLE
static void msm_console_putchar(struct uart_port *port, int c)
{
struct msm_port *msm_port = UART_TO_MSM(port);
if (msm_port->is_uartdm)
reset_dm_count(port);
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
;
msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
}
static void msm_console_write(struct console *co, const char *s,
unsigned int count)
{
int i;
struct uart_port *port;
struct msm_port *msm_port;
int num_newlines = 0;
bool replaced = false;
BUG_ON(co->index < 0 || co->index >= UART_NR);
port = get_port_from_line(co->index);
msm_port = UART_TO_MSM(port);
/* Account for newlines that will get a carriage return added */
for (i = 0; i < count; i++)
if (s[i] == '\n')
num_newlines++;
count += num_newlines;
spin_lock(&port->lock);
uart_console_write(port, s, count, msm_console_putchar);
if (msm_port->is_uartdm)
reset_dm_count(port, count);
i = 0;
while (i < count) {
int j;
unsigned int num_chars;
char buf[4] = { 0 };
unsigned int *bf = (unsigned int *)&buf;
if (msm_port->is_uartdm)
num_chars = min(count - i, (unsigned int)sizeof(buf));
else
num_chars = 1;
for (j = 0; j < num_chars; j++) {
char c = *s;
if (c == '\n' && !replaced) {
buf[j] = '\r';
j++;
replaced = true;
}
if (j < num_chars) {
buf[j] = c;
s++;
replaced = false;
}
}
while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
cpu_relax();
msm_write(port, *bf, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
i += num_chars;
}
spin_unlock(&port->lock);
}
@ -859,6 +899,11 @@ static struct uart_driver msm_uart_driver = {
static atomic_t msm_uart_next_id = ATOMIC_INIT(0);
static const struct of_device_id msm_uartdm_table[] = {
{ .compatible = "qcom,msm-uartdm" },
{ }
};
static int __init msm_serial_probe(struct platform_device *pdev)
{
struct msm_port *msm_port;
@ -878,23 +923,17 @@ static int __init msm_serial_probe(struct platform_device *pdev)
port->dev = &pdev->dev;
msm_port = UART_TO_MSM(port);
if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
if (of_match_device(msm_uartdm_table, &pdev->dev))
msm_port->is_uartdm = 1;
else
msm_port->is_uartdm = 0;
if (msm_port->is_uartdm) {
msm_port->clk = devm_clk_get(&pdev->dev, "gsbi_uart_clk");
msm_port->pclk = devm_clk_get(&pdev->dev, "gsbi_pclk");
} else {
msm_port->clk = devm_clk_get(&pdev->dev, "uart_clk");
msm_port->pclk = ERR_PTR(-ENOENT);
}
msm_port->clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(msm_port->clk))
return PTR_ERR(msm_port->clk);
if (msm_port->is_uartdm) {
msm_port->pclk = devm_clk_get(&pdev->dev, "iface");
if (IS_ERR(msm_port->pclk))
return PTR_ERR(msm_port->pclk);
@ -931,6 +970,7 @@ static int msm_serial_remove(struct platform_device *pdev)
static struct of_device_id msm_match_table[] = {
{ .compatible = "qcom,msm-uart" },
{ .compatible = "qcom,msm-uartdm" },
{}
};

Просмотреть файл

@ -38,19 +38,7 @@
#define UART_MR2_PARITY_MODE_SPACE 0x3
#define UART_MR2_PARITY_MODE 0x3
#define UART_CSR 0x0008
#define UART_CSR_115200 0xFF
#define UART_CSR_57600 0xEE
#define UART_CSR_38400 0xDD
#define UART_CSR_28800 0xCC
#define UART_CSR_19200 0xBB
#define UART_CSR_14400 0xAA
#define UART_CSR_9600 0x99
#define UART_CSR_4800 0x77
#define UART_CSR_2400 0x55
#define UART_CSR_1200 0x44
#define UART_CSR_600 0x33
#define UART_CSR_300 0x22
#define UART_CSR 0x0008
#define UART_TF 0x000C
#define UARTDM_TF 0x0070
@ -71,6 +59,7 @@
#define UART_CR_CMD_RESET_RFR (14 << 4)
#define UART_CR_CMD_PROTECTION_EN (16 << 4)
#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
#define UART_CR_CMD_RESET_TX_READY (3 << 8)
#define UART_CR_TX_DISABLE (1 << 3)
#define UART_CR_TX_ENABLE (1 << 2)
#define UART_CR_RX_DISABLE (1 << 1)
@ -151,6 +140,7 @@ static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
msm_write(port, 0xF1, UART_NREG);
msm_write(port, 0x0F, UART_DREG);
msm_write(port, 0x1A, UART_MNDREG);
port->uartclk = 1843200;
}
/*
@ -162,6 +152,7 @@ static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
msm_write(port, 0xF6, UART_NREG);
msm_write(port, 0x0F, UART_DREG);
msm_write(port, 0x0A, UART_MNDREG);
port->uartclk = 1843200;
}
static inline
@ -169,7 +160,7 @@ void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
{
if (port->uartclk == 19200000)
msm_serial_set_mnd_regs_tcxo(port);
else
else if (port->uartclk == 4800000)
msm_serial_set_mnd_regs_tcxoby4(port);
}

Просмотреть файл

@ -1618,7 +1618,7 @@ static int msm_hs_probe(struct platform_device *pdev)
struct msm_hs_port *msm_uport;
struct resource *resource;
const struct msm_serial_hs_platform_data *pdata =
pdev->dev.platform_data;
dev_get_platdata(&pdev->dev);
if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);

Просмотреть файл

@ -32,7 +32,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of_device.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
@ -134,10 +133,10 @@ enum mxs_auart_type {
struct mxs_auart_port {
struct uart_port port;
#define MXS_AUART_DMA_CONFIG 0x1
#define MXS_AUART_DMA_ENABLED 0x2
#define MXS_AUART_DMA_TX_SYNC 2 /* bit 2 */
#define MXS_AUART_DMA_RX_READY 3 /* bit 3 */
#define MXS_AUART_RTSCTS 4 /* bit 4 */
unsigned long flags;
unsigned int ctrl;
enum mxs_auart_type devtype;
@ -640,7 +639,8 @@ static void mxs_auart_settermios(struct uart_port *u,
* we can only implement the DMA support for auart
* in mx28.
*/
if (is_imx28_auart(s) && (s->flags & MXS_AUART_DMA_CONFIG)) {
if (is_imx28_auart(s)
&& test_bit(MXS_AUART_RTSCTS, &s->flags)) {
if (!mxs_auart_dma_init(s))
/* enable DMA tranfer */
ctrl2 |= AUART_CTRL2_TXDMAE | AUART_CTRL2_RXDMAE
@ -1008,7 +1008,8 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
}
s->port.line = ret;
s->flags |= MXS_AUART_DMA_CONFIG;
if (of_get_property(np, "fsl,uart-has-rtscts", NULL))
set_bit(MXS_AUART_RTSCTS, &s->flags);
return 0;
}
@ -1021,7 +1022,6 @@ static int mxs_auart_probe(struct platform_device *pdev)
u32 version;
int ret = 0;
struct resource *r;
struct pinctrl *pinctrl;
s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
if (!s) {
@ -1035,12 +1035,6 @@ static int mxs_auart_probe(struct platform_device *pdev)
else if (ret < 0)
goto out_free;
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(pinctrl)) {
ret = PTR_ERR(pinctrl);
goto out_free;
}
if (of_id) {
pdev->id_entry = of_id->data;
s->devtype = pdev->id_entry->driver_data;

Просмотреть файл

@ -196,7 +196,7 @@ static void netx_txint(struct uart_port *port)
uart_write_wakeup(port);
}
static void netx_rxint(struct uart_port *port)
static void netx_rxint(struct uart_port *port, unsigned long *flags)
{
unsigned char rx, flg, status;
@ -236,7 +236,9 @@ static void netx_rxint(struct uart_port *port)
uart_insert_char(port, status, SR_OE, rx, flg);
}
spin_unlock_irqrestore(&port->lock, *flags);
tty_flip_buffer_push(&port->state->port);
spin_lock_irqsave(&port->lock, *flags);
}
static irqreturn_t netx_int(int irq, void *dev_id)
@ -250,7 +252,7 @@ static irqreturn_t netx_int(int irq, void *dev_id)
status = readl(port->membase + UART_IIR) & IIR_MASK;
while (status) {
if (status & IIR_RIS)
netx_rxint(port);
netx_rxint(port, &flags);
if (status & IIR_TIS)
netx_txint(port);
if (status & IIR_MIS) {
@ -693,8 +695,6 @@ static int serial_netx_remove(struct platform_device *pdev)
{
struct netx_port *sport = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
if (sport)
uart_remove_one_port(&netx_reg, &sport->port);

Просмотреть файл

@ -149,7 +149,10 @@ static irqreturn_t nwpserial_interrupt(int irq, void *dev_id)
tty_insert_flip_char(port, ch, TTY_NORMAL);
} while (dcr_read(up->dcr_host, UART_LSR) & UART_LSR_DR);
spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
spin_lock(&up->port.lock);
ret = IRQ_HANDLED;
/* clear interrupt */

Просмотреть файл

@ -40,9 +40,11 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/gpio.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/serial-omap.h>
#include <dt-bindings/gpio/gpio.h>
#define OMAP_MAX_HSUART_PORTS 6
#define UART_BUILD_REVISION(x, y) (((x) << 8) | (y))
@ -52,6 +54,11 @@
#define OMAP_UART_REV_52 0x0502
#define OMAP_UART_REV_63 0x0603
#define OMAP_UART_TX_WAKEUP_EN BIT(7)
/* Feature flags */
#define OMAP_UART_WER_HAS_TX_WAKEUP BIT(0)
#define UART_ERRATA_i202_MDR1_ACCESS BIT(0)
#define UART_ERRATA_i291_DMA_FORCEIDLE BIT(1)
@ -137,6 +144,7 @@ struct uart_omap_port {
unsigned char dlh;
unsigned char mdr1;
unsigned char scr;
unsigned char wer;
int use_dma;
/*
@ -151,16 +159,19 @@ struct uart_omap_port {
int context_loss_cnt;
u32 errata;
u8 wakeups_enabled;
u32 features;
int DTR_gpio;
int DTR_inverted;
int DTR_active;
struct serial_rs485 rs485;
int rts_gpio;
struct pm_qos_request pm_qos_request;
u32 latency;
u32 calc_latency;
struct work_struct qos_work;
struct pinctrl *pins;
bool is_suspending;
};
@ -195,7 +206,7 @@ static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
if (!pdata || !pdata->get_context_loss_count)
return -EINVAL;
@ -205,7 +216,7 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
struct omap_uart_port_info *pdata = dev_get_platdata(up->dev);
if (!pdata || !pdata->enable_wakeup)
return;
@ -272,13 +283,42 @@ static void serial_omap_enable_ms(struct uart_port *port)
static void serial_omap_stop_tx(struct uart_port *port)
{
struct uart_omap_port *up = to_uart_omap_port(port);
struct circ_buf *xmit = &up->port.state->xmit;
int res;
pm_runtime_get_sync(up->dev);
/* handle rs485 */
if (up->rs485.flags & SER_RS485_ENABLED) {
/* do nothing if current tx not yet completed */
res = serial_in(up, UART_LSR) & UART_LSR_TEMT;
if (!res)
return;
/* if there's no more data to send, turn off rts */
if (uart_circ_empty(xmit)) {
/* if rts not already disabled */
res = (up->rs485.flags & SER_RS485_RTS_AFTER_SEND) ? 1 : 0;
if (gpio_get_value(up->rts_gpio) != res) {
if (up->rs485.delay_rts_after_send > 0) {
mdelay(up->rs485.delay_rts_after_send);
}
gpio_set_value(up->rts_gpio, res);
}
}
}
if (up->ier & UART_IER_THRI) {
up->ier &= ~UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
if ((up->rs485.flags & SER_RS485_ENABLED) &&
!(up->rs485.flags & SER_RS485_RX_DURING_TX)) {
up->ier = UART_IER_RLSI | UART_IER_RDI;
serial_out(up, UART_IER, up->ier);
}
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
@ -340,8 +380,26 @@ static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
static void serial_omap_start_tx(struct uart_port *port)
{
struct uart_omap_port *up = to_uart_omap_port(port);
int res;
pm_runtime_get_sync(up->dev);
/* handle rs485 */
if (up->rs485.flags & SER_RS485_ENABLED) {
/* if rts not already enabled */
res = (up->rs485.flags & SER_RS485_RTS_ON_SEND) ? 1 : 0;
if (gpio_get_value(up->rts_gpio) != res) {
gpio_set_value(up->rts_gpio, res);
if (up->rs485.delay_rts_before_send > 0) {
mdelay(up->rs485.delay_rts_before_send);
}
}
}
if ((up->rs485.flags & SER_RS485_ENABLED) &&
!(up->rs485.flags & SER_RS485_RX_DURING_TX))
serial_omap_stop_rx(port);
serial_omap_enable_ier_thri(up);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
@ -683,7 +741,11 @@ static int serial_omap_startup(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
/* Enable module level wake up */
serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
up->wer = OMAP_UART_WER_MOD_WKUP;
if (up->features & OMAP_UART_WER_HAS_TX_WAKEUP)
up->wer |= OMAP_UART_TX_WAKEUP_EN;
serial_out(up, UART_OMAP_WER, up->wer);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
@ -1254,6 +1316,76 @@ static inline void serial_omap_add_console_port(struct uart_omap_port *up)
#endif
/* Enable or disable the rs485 support */
static void
serial_omap_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
{
struct uart_omap_port *up = to_uart_omap_port(port);
unsigned long flags;
unsigned int mode;
int val;
pm_runtime_get_sync(up->dev);
spin_lock_irqsave(&up->port.lock, flags);
/* Disable interrupts from this port */
mode = up->ier;
up->ier = 0;
serial_out(up, UART_IER, 0);
/* store new config */
up->rs485 = *rs485conf;
/*
* Just as a precaution, only allow rs485
* to be enabled if the gpio pin is valid
*/
if (gpio_is_valid(up->rts_gpio)) {
/* enable / disable rts */
val = (up->rs485.flags & SER_RS485_ENABLED) ?
SER_RS485_RTS_AFTER_SEND : SER_RS485_RTS_ON_SEND;
val = (up->rs485.flags & val) ? 1 : 0;
gpio_set_value(up->rts_gpio, val);
} else
up->rs485.flags &= ~SER_RS485_ENABLED;
/* Enable interrupts */
up->ier = mode;
serial_out(up, UART_IER, up->ier);
spin_unlock_irqrestore(&up->port.lock, flags);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
static int
serial_omap_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg)
{
struct serial_rs485 rs485conf;
switch (cmd) {
case TIOCSRS485:
if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg,
sizeof(rs485conf)))
return -EFAULT;
serial_omap_config_rs485(port, &rs485conf);
break;
case TIOCGRS485:
if (copy_to_user((struct serial_rs485 *) arg,
&(to_uart_omap_port(port)->rs485),
sizeof(rs485conf)))
return -EFAULT;
break;
default:
return -ENOIOCTLCMD;
}
return 0;
}
static struct uart_ops serial_omap_pops = {
.tx_empty = serial_omap_tx_empty,
.set_mctrl = serial_omap_set_mctrl,
@ -1275,6 +1407,7 @@ static struct uart_ops serial_omap_pops = {
.request_port = serial_omap_request_port,
.config_port = serial_omap_config_port,
.verify_port = serial_omap_verify_port,
.ioctl = serial_omap_ioctl,
#ifdef CONFIG_CONSOLE_POLL
.poll_put_char = serial_omap_poll_put_char,
.poll_get_char = serial_omap_poll_get_char,
@ -1334,7 +1467,7 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
u32 mvr, scheme;
u16 revision, major, minor;
mvr = serial_in(up, UART_OMAP_MVER);
mvr = readl(up->port.membase + (UART_OMAP_MVER << up->port.regshift));
/* Check revision register scheme */
scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT;
@ -1373,9 +1506,11 @@ static void omap_serial_fill_features_erratas(struct uart_omap_port *up)
case OMAP_UART_REV_52:
up->errata |= (UART_ERRATA_i202_MDR1_ACCESS |
UART_ERRATA_i291_DMA_FORCEIDLE);
up->features |= OMAP_UART_WER_HAS_TX_WAKEUP;
break;
case OMAP_UART_REV_63:
up->errata |= UART_ERRATA_i202_MDR1_ACCESS;
up->features |= OMAP_UART_WER_HAS_TX_WAKEUP;
break;
default:
break;
@ -1395,15 +1530,64 @@ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
return omap_up_info;
}
static int serial_omap_probe_rs485(struct uart_omap_port *up,
struct device_node *np)
{
struct serial_rs485 *rs485conf = &up->rs485;
u32 rs485_delay[2];
enum of_gpio_flags flags;
int ret;
rs485conf->flags = 0;
up->rts_gpio = -EINVAL;
if (!np)
return 0;
if (of_property_read_bool(np, "rs485-rts-active-high"))
rs485conf->flags |= SER_RS485_RTS_ON_SEND;
else
rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
/* check for tx enable gpio */
up->rts_gpio = of_get_named_gpio_flags(np, "rts-gpio", 0, &flags);
if (gpio_is_valid(up->rts_gpio)) {
ret = gpio_request(up->rts_gpio, "omap-serial");
if (ret < 0)
return ret;
ret = gpio_direction_output(up->rts_gpio,
flags & SER_RS485_RTS_AFTER_SEND);
if (ret < 0)
return ret;
} else
up->rts_gpio = -EINVAL;
if (of_property_read_u32_array(np, "rs485-rts-delay",
rs485_delay, 2) == 0) {
rs485conf->delay_rts_before_send = rs485_delay[0];
rs485conf->delay_rts_after_send = rs485_delay[1];
}
if (of_property_read_bool(np, "rs485-rx-during-tx"))
rs485conf->flags |= SER_RS485_RX_DURING_TX;
if (of_property_read_bool(np, "linux,rs485-enabled-at-boot-time"))
rs485conf->flags |= SER_RS485_ENABLED;
return 0;
}
static int serial_omap_probe(struct platform_device *pdev)
{
struct uart_omap_port *up;
struct resource *mem, *irq;
struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
struct omap_uart_port_info *omap_up_info = dev_get_platdata(&pdev->dev);
int ret;
if (pdev->dev.of_node)
if (pdev->dev.of_node) {
omap_up_info = of_get_uart_port_info(&pdev->dev);
pdev->dev.platform_data = omap_up_info;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
@ -1468,12 +1652,9 @@ static int serial_omap_probe(struct platform_device *pdev)
goto err_port_line;
}
up->pins = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(up->pins)) {
dev_warn(&pdev->dev, "did not get pins for uart%i error: %li\n",
up->port.line, PTR_ERR(up->pins));
up->pins = NULL;
}
ret = serial_omap_probe_rs485(up, pdev->dev.of_node);
if (ret < 0)
goto err_rs485;
sprintf(up->name, "OMAP UART%d", up->port.line);
up->port.mapbase = mem->start;
@ -1501,7 +1682,6 @@ static int serial_omap_probe(struct platform_device *pdev)
INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
platform_set_drvdata(pdev, up);
pm_runtime_enable(&pdev->dev);
if (omap_up_info->autosuspend_timeout == 0)
omap_up_info->autosuspend_timeout = -1;
device_init_wakeup(up->dev, true);
@ -1510,6 +1690,8 @@ static int serial_omap_probe(struct platform_device *pdev)
omap_up_info->autosuspend_timeout);
pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
omap_serial_fill_features_erratas(up);
@ -1529,6 +1711,7 @@ err_add_port:
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
err_ioremap:
err_rs485:
err_port_line:
dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
pdev->id, __func__, ret);
@ -1609,6 +1792,7 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
serial_omap_mdr1_errataset(up, up->mdr1);
else
serial_out(up, UART_OMAP_MDR1, up->mdr1);
serial_out(up, UART_OMAP_WER, up->wer);
}
static int serial_omap_runtime_suspend(struct device *dev)

Просмотреть файл

@ -232,7 +232,7 @@ struct eg20t_port {
unsigned int iobase;
struct pci_dev *pdev;
int fifo_size;
int uartclk;
unsigned int uartclk;
int start_tx;
int start_rx;
int tx_empty;
@ -373,35 +373,62 @@ static const struct file_operations port_regs_ops = {
};
#endif /* CONFIG_DEBUG_FS */
static struct dmi_system_id pch_uart_dmi_table[] = {
{
.ident = "CM-iTC",
{
DMI_MATCH(DMI_BOARD_NAME, "CM-iTC"),
},
(void *)CMITC_UARTCLK,
},
{
.ident = "FRI2",
{
DMI_MATCH(DMI_BIOS_VERSION, "FRI2"),
},
(void *)FRI2_64_UARTCLK,
},
{
.ident = "Fish River Island II",
{
DMI_MATCH(DMI_PRODUCT_NAME, "Fish River Island II"),
},
(void *)FRI2_48_UARTCLK,
},
{
.ident = "COMe-mTT",
{
DMI_MATCH(DMI_BOARD_NAME, "COMe-mTT"),
},
(void *)NTC1_UARTCLK,
},
{
.ident = "nanoETXexpress-TT",
{
DMI_MATCH(DMI_BOARD_NAME, "nanoETXexpress-TT"),
},
(void *)NTC1_UARTCLK,
},
{
.ident = "MinnowBoard",
{
DMI_MATCH(DMI_BOARD_NAME, "MinnowBoard"),
},
(void *)MINNOW_UARTCLK,
},
};
/* Return UART clock, checking for board specific clocks. */
static int pch_uart_get_uartclk(void)
static unsigned int pch_uart_get_uartclk(void)
{
const char *cmp;
const struct dmi_system_id *d;
if (user_uartclk)
return user_uartclk;
cmp = dmi_get_system_info(DMI_BOARD_NAME);
if (cmp && strstr(cmp, "CM-iTC"))
return CMITC_UARTCLK;
cmp = dmi_get_system_info(DMI_BIOS_VERSION);
if (cmp && strnstr(cmp, "FRI2", 4))
return FRI2_64_UARTCLK;
cmp = dmi_get_system_info(DMI_PRODUCT_NAME);
if (cmp && strstr(cmp, "Fish River Island II"))
return FRI2_48_UARTCLK;
/* Kontron COMe-mTT10 (nanoETXexpress-TT) */
cmp = dmi_get_system_info(DMI_BOARD_NAME);
if (cmp && (strstr(cmp, "COMe-mTT") ||
strstr(cmp, "nanoETXexpress-TT")))
return NTC1_UARTCLK;
cmp = dmi_get_system_info(DMI_BOARD_NAME);
if (cmp && strstr(cmp, "MinnowBoard"))
return MINNOW_UARTCLK;
d = dmi_first_match(pch_uart_dmi_table);
if (d)
return (unsigned long)d->driver_data;
return DEFAULT_UARTCLK;
}
@ -422,7 +449,7 @@ static void pch_uart_hal_disable_interrupt(struct eg20t_port *priv,
iowrite8(ier, priv->membase + UART_IER);
}
static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
static int pch_uart_hal_set_line(struct eg20t_port *priv, unsigned int baud,
unsigned int parity, unsigned int bits,
unsigned int stb)
{
@ -457,7 +484,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
lcr |= bits;
lcr |= stb;
dev_dbg(priv->port.dev, "%s:baud = %d, div = %04x, lcr = %02x (%lu)\n",
dev_dbg(priv->port.dev, "%s:baud = %u, div = %04x, lcr = %02x (%lu)\n",
__func__, baud, div, lcr, jiffies);
iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
iowrite8(dll, priv->membase + PCH_UART_DLL);
@ -1363,9 +1390,8 @@ static void pch_uart_shutdown(struct uart_port *port)
static void pch_uart_set_termios(struct uart_port *port,
struct ktermios *termios, struct ktermios *old)
{
int baud;
int rtn;
unsigned int parity, bits, stb;
unsigned int baud, parity, bits, stb;
struct eg20t_port *priv;
unsigned long flags;
@ -1498,6 +1524,7 @@ static int pch_uart_verify_port(struct uart_port *port,
return 0;
}
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_PCH_UART_CONSOLE)
/*
* Wait for transmitter & holding register to empty
*/
@ -1528,6 +1555,7 @@ static void wait_for_xmitr(struct eg20t_port *up, int bits)
}
}
}
#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_PCH_UART_CONSOLE */
#ifdef CONFIG_CONSOLE_POLL
/*

Просмотреть файл

@ -1798,7 +1798,6 @@ static int __exit pmz_detach(struct platform_device *pdev)
uart_remove_one_port(&pmz_uart_reg, &uap->port);
platform_set_drvdata(pdev, NULL);
uap->port.dev = NULL;
return 0;

Просмотреть файл

@ -237,7 +237,10 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
}
spin_unlock(&sport->port.lock);
tty_flip_buffer_push(&sport->port.state->port);
spin_lock(&sport->port.lock);
}
static void pnx8xxx_tx_chars(struct pnx8xxx_port *sport)
@ -801,8 +804,6 @@ static int pnx8xxx_serial_remove(struct platform_device *pdev)
{
struct pnx8xxx_port *sport = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
if (sport)
uart_remove_one_port(&pnx8xxx_reg, &sport->port);

Просмотреть файл

@ -332,31 +332,6 @@ static void serial_pxa_break_ctl(struct uart_port *port, int break_state)
spin_unlock_irqrestore(&up->port.lock, flags);
}
#if 0
static void serial_pxa_dma_init(struct pxa_uart *up)
{
up->rxdma =
pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_receive_dma, up);
if (up->rxdma < 0)
goto out;
up->txdma =
pxa_request_dma(up->name, DMA_PRIO_LOW, pxa_transmit_dma, up);
if (up->txdma < 0)
goto err_txdma;
up->dmadesc = kmalloc(4 * sizeof(pxa_dma_desc), GFP_KERNEL);
if (!up->dmadesc)
goto err_alloc;
/* ... */
err_alloc:
pxa_free_dma(up->txdma);
err_rxdma:
pxa_free_dma(up->rxdma);
out:
return;
}
#endif
static int serial_pxa_startup(struct uart_port *port)
{
struct uart_pxa_port *up = (struct uart_pxa_port *)port;
@ -790,7 +765,7 @@ static struct console serial_pxa_console = {
#define PXA_CONSOLE NULL
#endif
struct uart_ops serial_pxa_pops = {
static struct uart_ops serial_pxa_pops = {
.tx_empty = serial_pxa_tx_empty,
.set_mctrl = serial_pxa_set_mctrl,
.get_mctrl = serial_pxa_get_mctrl,
@ -945,8 +920,6 @@ static int serial_pxa_remove(struct platform_device *dev)
{
struct uart_pxa_port *sport = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
uart_remove_one_port(&serial_pxa_reg, &sport->port);
clk_unprepare(sport->clk);
@ -970,7 +943,7 @@ static struct platform_driver serial_pxa_driver = {
},
};
int __init serial_pxa_init(void)
static int __init serial_pxa_init(void)
{
int ret;
@ -985,7 +958,7 @@ int __init serial_pxa_init(void)
return ret;
}
void __exit serial_pxa_exit(void)
static void __exit serial_pxa_exit(void)
{
platform_driver_unregister(&serial_pxa_driver);
uart_unregister_driver(&serial_pxa_reg);

Просмотреть файл

@ -427,7 +427,9 @@ static void rp2_rx_chars(struct rp2_uart_port *up)
up->port.icount.rx++;
}
spin_unlock(&up->port.lock);
tty_flip_buffer_push(port);
spin_lock(&up->port.lock);
}
static void rp2_tx_chars(struct rp2_uart_port *up)

Просмотреть файл

@ -232,7 +232,10 @@ sa1100_rx_chars(struct sa1100_port *sport)
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
UTSR0_TO_SM(UART_GET_UTSR0(sport));
}
spin_unlock(&sport->port.lock);
tty_flip_buffer_push(&sport->port.state->port);
spin_lock(&sport->port.lock);
}
static void sa1100_tx_chars(struct sa1100_port *sport)
@ -864,8 +867,6 @@ static int sa1100_serial_remove(struct platform_device *pdev)
{
struct sa1100_port *sport = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
if (sport)
uart_remove_one_port(&sa1100_reg, &sport->port);

Просмотреть файл

@ -249,6 +249,8 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
ufcon |= S3C2410_UFCON_RESETRX;
wr_regl(port, S3C2410_UFCON, ufcon);
rx_enabled(port) = 1;
spin_unlock_irqrestore(&port->lock,
flags);
goto out;
}
continue;
@ -297,10 +299,11 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id)
ignore_char:
continue;
}
spin_unlock_irqrestore(&port->lock, flags);
tty_flip_buffer_push(&port->state->port);
out:
spin_unlock_irqrestore(&port->lock, flags);
return IRQ_HANDLED;
}
@ -1250,8 +1253,8 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
ourport->baudclk = ERR_PTR(-EINVAL);
ourport->info = ourport->drv_data->info;
ourport->cfg = (pdev->dev.platform_data) ?
(struct s3c2410_uartcfg *)pdev->dev.platform_data :
ourport->cfg = (dev_get_platdata(&pdev->dev)) ?
(struct s3c2410_uartcfg *)dev_get_platdata(&pdev->dev) :
ourport->drv_data->def_cfg;
ourport->port.fifosize = (ourport->info->fifosize) ?

Просмотреть файл

@ -68,7 +68,8 @@ struct s3c24xx_uart_port {
/* register access controls */
#define portaddr(port, reg) ((port)->membase + (reg))
#define portaddrl(port, reg) ((unsigned long *)((port)->membase + (reg)))
#define portaddrl(port, reg) \
((unsigned long *)(unsigned long)((port)->membase + (reg)))
#define rd_regb(port, reg) (__raw_readb(portaddr(port, reg)))
#define rd_regl(port, reg) (__raw_readl(portaddr(port, reg)))

Просмотреть файл

@ -637,7 +637,7 @@ static int sc26xx_probe(struct platform_device *dev)
{
struct resource *res;
struct uart_sc26xx_port *up;
unsigned int *sc26xx_data = dev->dev.platform_data;
unsigned int *sc26xx_data = dev_get_platdata(&dev->dev);
int err;
res = platform_get_resource(dev, IORESOURCE_MEM, 0);

Просмотреть файл

@ -15,6 +15,7 @@
#define SUPPORT_SYSRQ
#endif
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/device.h>
@ -94,16 +95,17 @@
#define MCTRL_IBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_IP0)
#define MCTRL_OBIT(cfg, sig) ((((cfg) >> (sig)) & 0xf) - LINE_OP0)
/* Supported chip types */
enum {
SCCNXP_TYPE_SC2681 = 2681,
SCCNXP_TYPE_SC2691 = 2691,
SCCNXP_TYPE_SC2692 = 2692,
SCCNXP_TYPE_SC2891 = 2891,
SCCNXP_TYPE_SC2892 = 2892,
SCCNXP_TYPE_SC28202 = 28202,
SCCNXP_TYPE_SC68681 = 68681,
SCCNXP_TYPE_SC68692 = 68692,
#define SCCNXP_HAVE_IO 0x00000001
#define SCCNXP_HAVE_MR0 0x00000002
struct sccnxp_chip {
const char *name;
unsigned int nr;
unsigned long freq_min;
unsigned long freq_std;
unsigned long freq_max;
unsigned int flags;
unsigned int fifosize;
};
struct sccnxp_port {
@ -111,16 +113,10 @@ struct sccnxp_port {
struct uart_port port[SCCNXP_MAX_UARTS];
bool opened[SCCNXP_MAX_UARTS];
const char *name;
int irq;
u8 imr;
u8 addr_mask;
int freq_std;
int flags;
#define SCCNXP_HAVE_IO 0x00000001
#define SCCNXP_HAVE_MR0 0x00000002
struct sccnxp_chip *chip;
#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
struct console console;
@ -136,29 +132,94 @@ struct sccnxp_port {
struct regulator *regulator;
};
static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift)
{
return readb(base + (reg << shift));
}
static const struct sccnxp_chip sc2681 = {
.name = "SC2681",
.nr = 2,
.freq_min = 1000000,
.freq_std = 3686400,
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
};
static inline void sccnxp_raw_write(void __iomem *base, u8 reg, u8 shift, u8 v)
{
writeb(v, base + (reg << shift));
}
static const struct sccnxp_chip sc2691 = {
.name = "SC2691",
.nr = 1,
.freq_min = 1000000,
.freq_std = 3686400,
.freq_max = 4000000,
.flags = 0,
.fifosize = 3,
};
static const struct sccnxp_chip sc2692 = {
.name = "SC2692",
.nr = 2,
.freq_min = 1000000,
.freq_std = 3686400,
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
};
static const struct sccnxp_chip sc2891 = {
.name = "SC2891",
.nr = 1,
.freq_min = 100000,
.freq_std = 3686400,
.freq_max = 8000000,
.flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
.fifosize = 16,
};
static const struct sccnxp_chip sc2892 = {
.name = "SC2892",
.nr = 2,
.freq_min = 100000,
.freq_std = 3686400,
.freq_max = 8000000,
.flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
.fifosize = 16,
};
static const struct sccnxp_chip sc28202 = {
.name = "SC28202",
.nr = 2,
.freq_min = 1000000,
.freq_std = 14745600,
.freq_max = 50000000,
.flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0,
.fifosize = 256,
};
static const struct sccnxp_chip sc68681 = {
.name = "SC68681",
.nr = 2,
.freq_min = 1000000,
.freq_std = 3686400,
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
};
static const struct sccnxp_chip sc68692 = {
.name = "SC68692",
.nr = 2,
.freq_min = 1000000,
.freq_std = 3686400,
.freq_max = 4000000,
.flags = SCCNXP_HAVE_IO,
.fifosize = 3,
};
static inline u8 sccnxp_read(struct uart_port *port, u8 reg)
{
struct sccnxp_port *s = dev_get_drvdata(port->dev);
return sccnxp_raw_read(port->membase, reg & s->addr_mask,
port->regshift);
return readb(port->membase + (reg << port->regshift));
}
static inline void sccnxp_write(struct uart_port *port, u8 reg, u8 v)
{
struct sccnxp_port *s = dev_get_drvdata(port->dev);
sccnxp_raw_write(port->membase, reg & s->addr_mask, port->regshift, v);
writeb(v, port->membase + (reg << port->regshift));
}
static inline u8 sccnxp_port_read(struct uart_port *port, u8 reg)
@ -224,13 +285,14 @@ static int sccnxp_set_baud(struct uart_port *port, int baud)
{
struct sccnxp_port *s = dev_get_drvdata(port->dev);
int div_std, tmp_baud, bestbaud = baud, besterr = -1;
struct sccnxp_chip *chip = s->chip;
u8 i, acr = 0, csr = 0, mr0 = 0;
/* Find best baud from table */
for (i = 0; baud_std[i].baud && besterr; i++) {
if (baud_std[i].mr0 && !(s->flags & SCCNXP_HAVE_MR0))
if (baud_std[i].mr0 && !(chip->flags & SCCNXP_HAVE_MR0))
continue;
div_std = DIV_ROUND_CLOSEST(s->freq_std, baud_std[i].baud);
div_std = DIV_ROUND_CLOSEST(chip->freq_std, baud_std[i].baud);
tmp_baud = DIV_ROUND_CLOSEST(port->uartclk, div_std);
if (!sccnxp_update_best_err(baud, tmp_baud, &besterr)) {
acr = baud_std[i].acr;
@ -240,7 +302,7 @@ static int sccnxp_set_baud(struct uart_port *port, int baud)
}
}
if (s->flags & SCCNXP_HAVE_MR0) {
if (chip->flags & SCCNXP_HAVE_MR0) {
/* Enable FIFO, set half level for TX */
mr0 |= MR0_FIFO | MR0_TXLVL;
/* Update MR0 */
@ -363,7 +425,7 @@ static void sccnxp_handle_tx(struct uart_port *port)
sccnxp_disable_irq(port, IMR_TXRDY);
/* Set direction to input */
if (s->flags & SCCNXP_HAVE_IO)
if (s->chip->flags & SCCNXP_HAVE_IO)
sccnxp_set_bit(port, DIR_OP, 0);
}
return;
@ -437,7 +499,7 @@ static void sccnxp_start_tx(struct uart_port *port)
spin_lock_irqsave(&s->lock, flags);
/* Set direction to output */
if (s->flags & SCCNXP_HAVE_IO)
if (s->chip->flags & SCCNXP_HAVE_IO)
sccnxp_set_bit(port, DIR_OP, 1);
sccnxp_enable_irq(port, IMR_TXRDY);
@ -483,7 +545,7 @@ static void sccnxp_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct sccnxp_port *s = dev_get_drvdata(port->dev);
unsigned long flags;
if (!(s->flags & SCCNXP_HAVE_IO))
if (!(s->chip->flags & SCCNXP_HAVE_IO))
return;
spin_lock_irqsave(&s->lock, flags);
@ -501,7 +563,7 @@ static unsigned int sccnxp_get_mctrl(struct uart_port *port)
struct sccnxp_port *s = dev_get_drvdata(port->dev);
unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR;
if (!(s->flags & SCCNXP_HAVE_IO))
if (!(s->chip->flags & SCCNXP_HAVE_IO))
return mctrl;
spin_lock_irqsave(&s->lock, flags);
@ -617,7 +679,7 @@ static void sccnxp_set_termios(struct uart_port *port,
/* Setup baudrate */
baud = uart_get_baud_rate(port, termios, old, 50,
(s->flags & SCCNXP_HAVE_MR0) ?
(s->chip->flags & SCCNXP_HAVE_MR0) ?
230400 : 38400);
baud = sccnxp_set_baud(port, baud);
@ -641,7 +703,7 @@ static int sccnxp_startup(struct uart_port *port)
spin_lock_irqsave(&s->lock, flags);
if (s->flags & SCCNXP_HAVE_IO) {
if (s->chip->flags & SCCNXP_HAVE_IO) {
/* Outputs are controlled manually */
sccnxp_write(port, SCCNXP_OPCR_REG, 0);
}
@ -681,7 +743,7 @@ static void sccnxp_shutdown(struct uart_port *port)
sccnxp_port_write(port, SCCNXP_CR_REG, CR_RX_DISABLE | CR_TX_DISABLE);
/* Leave direction to input */
if (s->flags & SCCNXP_HAVE_IO)
if (s->chip->flags & SCCNXP_HAVE_IO)
sccnxp_set_bit(port, DIR_OP, 0);
spin_unlock_irqrestore(&s->lock, flags);
@ -691,7 +753,7 @@ static const char *sccnxp_type(struct uart_port *port)
{
struct sccnxp_port *s = dev_get_drvdata(port->dev);
return (port->type == PORT_SC26XX) ? s->name : NULL;
return (port->type == PORT_SC26XX) ? s->chip->name : NULL;
}
static void sccnxp_release_port(struct uart_port *port)
@ -778,19 +840,31 @@ static int sccnxp_console_setup(struct console *co, char *options)
}
#endif
static const struct platform_device_id sccnxp_id_table[] = {
{ .name = "sc2681", .driver_data = (kernel_ulong_t)&sc2681, },
{ .name = "sc2691", .driver_data = (kernel_ulong_t)&sc2691, },
{ .name = "sc2692", .driver_data = (kernel_ulong_t)&sc2692, },
{ .name = "sc2891", .driver_data = (kernel_ulong_t)&sc2891, },
{ .name = "sc2892", .driver_data = (kernel_ulong_t)&sc2892, },
{ .name = "sc28202", .driver_data = (kernel_ulong_t)&sc28202, },
{ .name = "sc68681", .driver_data = (kernel_ulong_t)&sc68681, },
{ .name = "sc68692", .driver_data = (kernel_ulong_t)&sc68692, },
{ }
};
MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
static int sccnxp_probe(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int chiptype = pdev->id_entry->driver_data;
struct sccnxp_pdata *pdata = dev_get_platdata(&pdev->dev);
int i, ret, fifosize, freq_min, freq_max;
int i, ret, uartclk;
struct sccnxp_port *s;
void __iomem *membase;
struct clk *clk;
if (!res) {
dev_err(&pdev->dev, "Missing memory resource data\n");
return -EADDRNOTAVAIL;
}
membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(membase))
return PTR_ERR(membase);
s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL);
if (!s) {
@ -801,99 +875,38 @@ static int sccnxp_probe(struct platform_device *pdev)
spin_lock_init(&s->lock);
/* Individual chip settings */
switch (chiptype) {
case SCCNXP_TYPE_SC2681:
s->name = "SC2681";
s->uart.nr = 2;
s->freq_std = 3686400;
s->addr_mask = 0x0f;
s->flags = SCCNXP_HAVE_IO;
fifosize = 3;
freq_min = 1000000;
freq_max = 4000000;
break;
case SCCNXP_TYPE_SC2691:
s->name = "SC2691";
s->uart.nr = 1;
s->freq_std = 3686400;
s->addr_mask = 0x07;
s->flags = 0;
fifosize = 3;
freq_min = 1000000;
freq_max = 4000000;
break;
case SCCNXP_TYPE_SC2692:
s->name = "SC2692";
s->uart.nr = 2;
s->freq_std = 3686400;
s->addr_mask = 0x0f;
s->flags = SCCNXP_HAVE_IO;
fifosize = 3;
freq_min = 1000000;
freq_max = 4000000;
break;
case SCCNXP_TYPE_SC2891:
s->name = "SC2891";
s->uart.nr = 1;
s->freq_std = 3686400;
s->addr_mask = 0x0f;
s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
fifosize = 16;
freq_min = 100000;
freq_max = 8000000;
break;
case SCCNXP_TYPE_SC2892:
s->name = "SC2892";
s->uart.nr = 2;
s->freq_std = 3686400;
s->addr_mask = 0x0f;
s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
fifosize = 16;
freq_min = 100000;
freq_max = 8000000;
break;
case SCCNXP_TYPE_SC28202:
s->name = "SC28202";
s->uart.nr = 2;
s->freq_std = 14745600;
s->addr_mask = 0x7f;
s->flags = SCCNXP_HAVE_IO | SCCNXP_HAVE_MR0;
fifosize = 256;
freq_min = 1000000;
freq_max = 50000000;
break;
case SCCNXP_TYPE_SC68681:
s->name = "SC68681";
s->uart.nr = 2;
s->freq_std = 3686400;
s->addr_mask = 0x0f;
s->flags = SCCNXP_HAVE_IO;
fifosize = 3;
freq_min = 1000000;
freq_max = 4000000;
break;
case SCCNXP_TYPE_SC68692:
s->name = "SC68692";
s->uart.nr = 2;
s->freq_std = 3686400;
s->addr_mask = 0x0f;
s->flags = SCCNXP_HAVE_IO;
fifosize = 3;
freq_min = 1000000;
freq_max = 4000000;
break;
default:
dev_err(&pdev->dev, "Unsupported chip type %i\n", chiptype);
ret = -ENOTSUPP;
s->chip = (struct sccnxp_chip *)pdev->id_entry->driver_data;
s->regulator = devm_regulator_get(&pdev->dev, "vcc");
if (!IS_ERR(s->regulator)) {
ret = regulator_enable(s->regulator);
if (ret) {
dev_err(&pdev->dev,
"Failed to enable regulator: %i\n", ret);
return ret;
}
} else if (PTR_ERR(s->regulator) == -EPROBE_DEFER)
return -EPROBE_DEFER;
clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(clk)) {
if (PTR_ERR(clk) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto err_out;
}
dev_notice(&pdev->dev, "Using default clock frequency\n");
uartclk = s->chip->freq_std;
} else
uartclk = clk_get_rate(clk);
/* Check input frequency */
if ((uartclk < s->chip->freq_min) || (uartclk > s->chip->freq_max)) {
dev_err(&pdev->dev, "Frequency out of bounds\n");
ret = -EINVAL;
goto err_out;
}
if (!pdata) {
dev_warn(&pdev->dev,
"No platform data supplied, using defaults\n");
s->pdata.frequency = s->freq_std;
} else
if (pdata)
memcpy(&s->pdata, pdata, sizeof(struct sccnxp_pdata));
if (s->pdata.poll_time_us) {
@ -911,34 +924,11 @@ static int sccnxp_probe(struct platform_device *pdev)
}
}
/* Check input frequency */
if ((s->pdata.frequency < freq_min) ||
(s->pdata.frequency > freq_max)) {
dev_err(&pdev->dev, "Frequency out of bounds\n");
ret = -EINVAL;
goto err_out;
}
s->regulator = devm_regulator_get(&pdev->dev, "VCC");
if (!IS_ERR(s->regulator)) {
ret = regulator_enable(s->regulator);
if (ret) {
dev_err(&pdev->dev,
"Failed to enable regulator: %i\n", ret);
return ret;
}
}
membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(membase)) {
ret = PTR_ERR(membase);
goto err_out;
}
s->uart.owner = THIS_MODULE;
s->uart.dev_name = "ttySC";
s->uart.major = SCCNXP_MAJOR;
s->uart.minor = SCCNXP_MINOR;
s->uart.nr = s->chip->nr;
#ifdef CONFIG_SERIAL_SCCNXP_CONSOLE
s->uart.cons = &s->console;
s->uart.cons->device = uart_console_device;
@ -960,17 +950,17 @@ static int sccnxp_probe(struct platform_device *pdev)
s->port[i].dev = &pdev->dev;
s->port[i].irq = s->irq;
s->port[i].type = PORT_SC26XX;
s->port[i].fifosize = fifosize;
s->port[i].fifosize = s->chip->fifosize;
s->port[i].flags = UPF_SKIP_TEST | UPF_FIXED_TYPE;
s->port[i].iotype = UPIO_MEM;
s->port[i].mapbase = res->start;
s->port[i].membase = membase;
s->port[i].regshift = s->pdata.reg_shift;
s->port[i].uartclk = s->pdata.frequency;
s->port[i].uartclk = uartclk;
s->port[i].ops = &sccnxp_ops;
uart_add_one_port(&s->uart, &s->port[i]);
/* Set direction to input */
if (s->flags & SCCNXP_HAVE_IO)
if (s->chip->flags & SCCNXP_HAVE_IO)
sccnxp_set_bit(&s->port[i], DIR_OP, 0);
}
@ -997,7 +987,8 @@ static int sccnxp_probe(struct platform_device *pdev)
}
err_out:
platform_set_drvdata(pdev, NULL);
if (!IS_ERR(s->regulator))
return regulator_disable(s->regulator);
return ret;
}
@ -1016,7 +1007,6 @@ static int sccnxp_remove(struct platform_device *pdev)
uart_remove_one_port(&s->uart, &s->port[i]);
uart_unregister_driver(&s->uart);
platform_set_drvdata(pdev, NULL);
if (!IS_ERR(s->regulator))
return regulator_disable(s->regulator);
@ -1024,19 +1014,6 @@ static int sccnxp_remove(struct platform_device *pdev)
return 0;
}
static const struct platform_device_id sccnxp_id_table[] = {
{ "sc2681", SCCNXP_TYPE_SC2681 },
{ "sc2691", SCCNXP_TYPE_SC2691 },
{ "sc2692", SCCNXP_TYPE_SC2692 },
{ "sc2891", SCCNXP_TYPE_SC2891 },
{ "sc2892", SCCNXP_TYPE_SC2892 },
{ "sc28202", SCCNXP_TYPE_SC28202 },
{ "sc68681", SCCNXP_TYPE_SC68681 },
{ "sc68692", SCCNXP_TYPE_SC68692 },
{ },
};
MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
static struct platform_driver sccnxp_uart_driver = {
.driver = {
.name = SCCNXP_NAME,

Просмотреть файл

@ -571,7 +571,9 @@ static void tegra_uart_rx_dma_complete(void *args)
tegra_uart_handle_rx_pio(tup, port);
if (tty) {
spin_unlock_irqrestore(&u->lock, flags);
tty_flip_buffer_push(port);
spin_lock_irqsave(&u->lock, flags);
tty_kref_put(tty);
}
tegra_uart_start_rx_dma(tup);
@ -583,11 +585,13 @@ static void tegra_uart_rx_dma_complete(void *args)
spin_unlock_irqrestore(&u->lock, flags);
}
static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup)
static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup,
unsigned long *flags)
{
struct dma_tx_state state;
struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
struct tty_port *port = &tup->uport.state->port;
struct uart_port *u = &tup->uport;
int count;
/* Deactivate flow control to stop sender */
@ -604,7 +608,9 @@ static void tegra_uart_handle_rx_dma(struct tegra_uart_port *tup)
tegra_uart_handle_rx_pio(tup, port);
if (tty) {
spin_unlock_irqrestore(&u->lock, *flags);
tty_flip_buffer_push(port);
spin_lock_irqsave(&u->lock, *flags);
tty_kref_put(tty);
}
tegra_uart_start_rx_dma(tup);
@ -671,7 +677,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data)
iir = tegra_uart_read(tup, UART_IIR);
if (iir & UART_IIR_NO_INT) {
if (is_rx_int) {
tegra_uart_handle_rx_dma(tup);
tegra_uart_handle_rx_dma(tup, &flags);
if (tup->rx_in_progress) {
ier = tup->ier_shadow;
ier |= (UART_IER_RLSI | UART_IER_RTOIE |
@ -1206,7 +1212,7 @@ static struct uart_driver tegra_uart_driver = {
.owner = THIS_MODULE,
.driver_name = "tegra_hsuart",
.dev_name = "ttyTHS",
.cons = 0,
.cons = NULL,
.nr = TEGRA_UART_MAXIMUM,
};
@ -1237,13 +1243,13 @@ static int tegra_uart_parse_dt(struct platform_device *pdev,
return 0;
}
struct tegra_uart_chip_data tegra20_uart_chip_data = {
static struct tegra_uart_chip_data tegra20_uart_chip_data = {
.tx_fifo_full_status = false,
.allow_txfifo_reset_fifo_mode = true,
.support_clk_src_div = false,
};
struct tegra_uart_chip_data tegra30_uart_chip_data = {
static struct tegra_uart_chip_data tegra30_uart_chip_data = {
.tx_fifo_full_status = true,
.allow_txfifo_reset_fifo_mode = false,
.support_clk_src_div = true,

Просмотреть файл

@ -2095,12 +2095,12 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
break;
}
printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n",
printk(KERN_INFO "%s%s%s%d at %s (irq = %d, base_baud = %d) is a %s\n",
port->dev ? dev_name(port->dev) : "",
port->dev ? ": " : "",
drv->dev_name,
drv->tty_driver->name_base + port->line,
address, port->irq, uart_type(port));
address, port->irq, port->uartclk / 16, uart_type(port));
}
static void

Просмотреть файл

@ -1097,7 +1097,7 @@ static void serial_txx9_unregister_port(int line)
*/
static int serial_txx9_probe(struct platform_device *dev)
{
struct uart_port *p = dev->dev.platform_data;
struct uart_port *p = dev_get_platdata(&dev->dev);
struct uart_port port;
int ret, i;

Просмотреть файл

@ -2380,7 +2380,7 @@ static char early_serial_buf[32];
static int sci_probe_earlyprintk(struct platform_device *pdev)
{
struct plat_sci_port *cfg = pdev->dev.platform_data;
struct plat_sci_port *cfg = dev_get_platdata(&pdev->dev);
if (early_serial_console.data)
return -EEXIST;
@ -2469,7 +2469,7 @@ static int sci_probe_single(struct platform_device *dev,
static int sci_probe(struct platform_device *dev)
{
struct plat_sci_port *p = dev->dev.platform_data;
struct plat_sci_port *p = dev_get_platdata(&dev->dev);
struct sci_port *sp = &sci_ports[dev->id];
int ret;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -6,31 +6,260 @@
* Licensed under GPLv2 or later.
*/
#include <linux/bitops.h>
struct sirfsoc_uart_param {
const char *uart_name;
const char *port_name;
u32 uart_nr;
u32 register_uart_nr;
};
/* UART Register Offset Define */
#define SIRFUART_LINE_CTRL 0x0040
#define SIRFUART_TX_RX_EN 0x004c
#define SIRFUART_DIVISOR 0x0050
#define SIRFUART_INT_EN 0x0054
#define SIRFUART_INT_STATUS 0x0058
#define SIRFUART_TX_DMA_IO_CTRL 0x0100
#define SIRFUART_TX_DMA_IO_LEN 0x0104
#define SIRFUART_TX_FIFO_CTRL 0x0108
#define SIRFUART_TX_FIFO_LEVEL_CHK 0x010C
#define SIRFUART_TX_FIFO_OP 0x0110
#define SIRFUART_TX_FIFO_STATUS 0x0114
#define SIRFUART_TX_FIFO_DATA 0x0118
#define SIRFUART_RX_DMA_IO_CTRL 0x0120
#define SIRFUART_RX_DMA_IO_LEN 0x0124
#define SIRFUART_RX_FIFO_CTRL 0x0128
#define SIRFUART_RX_FIFO_LEVEL_CHK 0x012C
#define SIRFUART_RX_FIFO_OP 0x0130
#define SIRFUART_RX_FIFO_STATUS 0x0134
#define SIRFUART_RX_FIFO_DATA 0x0138
#define SIRFUART_AFC_CTRL 0x0140
#define SIRFUART_SWH_DMA_IO 0x0148
struct sirfsoc_register {
/* hardware uart specific */
u32 sirfsoc_line_ctrl;
u32 sirfsoc_divisor;
/* uart - usp common */
u32 sirfsoc_tx_rx_en;
u32 sirfsoc_int_en_reg;
u32 sirfsoc_int_st_reg;
u32 sirfsoc_tx_dma_io_ctrl;
u32 sirfsoc_tx_dma_io_len;
u32 sirfsoc_tx_fifo_ctrl;
u32 sirfsoc_tx_fifo_level_chk;
u32 sirfsoc_tx_fifo_op;
u32 sirfsoc_tx_fifo_status;
u32 sirfsoc_tx_fifo_data;
u32 sirfsoc_rx_dma_io_ctrl;
u32 sirfsoc_rx_dma_io_len;
u32 sirfsoc_rx_fifo_ctrl;
u32 sirfsoc_rx_fifo_level_chk;
u32 sirfsoc_rx_fifo_op;
u32 sirfsoc_rx_fifo_status;
u32 sirfsoc_rx_fifo_data;
u32 sirfsoc_afc_ctrl;
u32 sirfsoc_swh_dma_io;
/* hardware usp specific */
u32 sirfsoc_mode1;
u32 sirfsoc_mode2;
u32 sirfsoc_tx_frame_ctrl;
u32 sirfsoc_rx_frame_ctrl;
u32 sirfsoc_async_param_reg;
};
/* UART Line Control Register */
typedef u32 (*fifo_full_mask)(int line);
typedef u32 (*fifo_empty_mask)(int line);
struct sirfsoc_fifo_status {
fifo_full_mask ff_full;
fifo_empty_mask ff_empty;
};
struct sirfsoc_int_en {
u32 sirfsoc_rx_done_en;
u32 sirfsoc_tx_done_en;
u32 sirfsoc_rx_oflow_en;
u32 sirfsoc_tx_allout_en;
u32 sirfsoc_rx_io_dma_en;
u32 sirfsoc_tx_io_dma_en;
u32 sirfsoc_rxfifo_full_en;
u32 sirfsoc_txfifo_empty_en;
u32 sirfsoc_rxfifo_thd_en;
u32 sirfsoc_txfifo_thd_en;
u32 sirfsoc_frm_err_en;
u32 sirfsoc_rxd_brk_en;
u32 sirfsoc_rx_timeout_en;
u32 sirfsoc_parity_err_en;
u32 sirfsoc_cts_en;
u32 sirfsoc_rts_en;
};
struct sirfsoc_int_status {
u32 sirfsoc_rx_done;
u32 sirfsoc_tx_done;
u32 sirfsoc_rx_oflow;
u32 sirfsoc_tx_allout;
u32 sirfsoc_rx_io_dma;
u32 sirfsoc_tx_io_dma;
u32 sirfsoc_rxfifo_full;
u32 sirfsoc_txfifo_empty;
u32 sirfsoc_rxfifo_thd;
u32 sirfsoc_txfifo_thd;
u32 sirfsoc_frm_err;
u32 sirfsoc_rxd_brk;
u32 sirfsoc_rx_timeout;
u32 sirfsoc_parity_err;
u32 sirfsoc_cts;
u32 sirfsoc_rts;
};
enum sirfsoc_uart_type {
SIRF_REAL_UART,
SIRF_USP_UART,
};
struct sirfsoc_uart_register {
struct sirfsoc_register uart_reg;
struct sirfsoc_int_en uart_int_en;
struct sirfsoc_int_status uart_int_st;
struct sirfsoc_fifo_status fifo_status;
struct sirfsoc_uart_param uart_param;
enum sirfsoc_uart_type uart_type;
};
u32 usp_ff_full(int line)
{
return 0x80;
}
u32 usp_ff_empty(int line)
{
return 0x100;
}
u32 uart_ff_full(int line)
{
return (line == 1) ? (0x20) : (0x80);
}
u32 uart_ff_empty(int line)
{
return (line == 1) ? (0x40) : (0x100);
}
struct sirfsoc_uart_register sirfsoc_usp = {
.uart_reg = {
.sirfsoc_mode1 = 0x0000,
.sirfsoc_mode2 = 0x0004,
.sirfsoc_tx_frame_ctrl = 0x0008,
.sirfsoc_rx_frame_ctrl = 0x000c,
.sirfsoc_tx_rx_en = 0x0010,
.sirfsoc_int_en_reg = 0x0014,
.sirfsoc_int_st_reg = 0x0018,
.sirfsoc_async_param_reg = 0x0024,
.sirfsoc_tx_dma_io_ctrl = 0x0100,
.sirfsoc_tx_dma_io_len = 0x0104,
.sirfsoc_tx_fifo_ctrl = 0x0108,
.sirfsoc_tx_fifo_level_chk = 0x010c,
.sirfsoc_tx_fifo_op = 0x0110,
.sirfsoc_tx_fifo_status = 0x0114,
.sirfsoc_tx_fifo_data = 0x0118,
.sirfsoc_rx_dma_io_ctrl = 0x0120,
.sirfsoc_rx_dma_io_len = 0x0124,
.sirfsoc_rx_fifo_ctrl = 0x0128,
.sirfsoc_rx_fifo_level_chk = 0x012c,
.sirfsoc_rx_fifo_op = 0x0130,
.sirfsoc_rx_fifo_status = 0x0134,
.sirfsoc_rx_fifo_data = 0x0138,
},
.uart_int_en = {
.sirfsoc_rx_done_en = BIT(0),
.sirfsoc_tx_done_en = BIT(1),
.sirfsoc_rx_oflow_en = BIT(2),
.sirfsoc_tx_allout_en = BIT(3),
.sirfsoc_rx_io_dma_en = BIT(4),
.sirfsoc_tx_io_dma_en = BIT(5),
.sirfsoc_rxfifo_full_en = BIT(6),
.sirfsoc_txfifo_empty_en = BIT(7),
.sirfsoc_rxfifo_thd_en = BIT(8),
.sirfsoc_txfifo_thd_en = BIT(9),
.sirfsoc_frm_err_en = BIT(10),
.sirfsoc_rx_timeout_en = BIT(11),
.sirfsoc_rxd_brk_en = BIT(15),
},
.uart_int_st = {
.sirfsoc_rx_done = BIT(0),
.sirfsoc_tx_done = BIT(1),
.sirfsoc_rx_oflow = BIT(2),
.sirfsoc_tx_allout = BIT(3),
.sirfsoc_rx_io_dma = BIT(4),
.sirfsoc_tx_io_dma = BIT(5),
.sirfsoc_rxfifo_full = BIT(6),
.sirfsoc_txfifo_empty = BIT(7),
.sirfsoc_rxfifo_thd = BIT(8),
.sirfsoc_txfifo_thd = BIT(9),
.sirfsoc_frm_err = BIT(10),
.sirfsoc_rx_timeout = BIT(11),
.sirfsoc_rxd_brk = BIT(15),
},
.fifo_status = {
.ff_full = usp_ff_full,
.ff_empty = usp_ff_empty,
},
.uart_param = {
.uart_name = "ttySiRF",
.port_name = "sirfsoc-uart",
.uart_nr = 2,
.register_uart_nr = 3,
},
};
struct sirfsoc_uart_register sirfsoc_uart = {
.uart_reg = {
.sirfsoc_line_ctrl = 0x0040,
.sirfsoc_tx_rx_en = 0x004c,
.sirfsoc_divisor = 0x0050,
.sirfsoc_int_en_reg = 0x0054,
.sirfsoc_int_st_reg = 0x0058,
.sirfsoc_tx_dma_io_ctrl = 0x0100,
.sirfsoc_tx_dma_io_len = 0x0104,
.sirfsoc_tx_fifo_ctrl = 0x0108,
.sirfsoc_tx_fifo_level_chk = 0x010c,
.sirfsoc_tx_fifo_op = 0x0110,
.sirfsoc_tx_fifo_status = 0x0114,
.sirfsoc_tx_fifo_data = 0x0118,
.sirfsoc_rx_dma_io_ctrl = 0x0120,
.sirfsoc_rx_dma_io_len = 0x0124,
.sirfsoc_rx_fifo_ctrl = 0x0128,
.sirfsoc_rx_fifo_level_chk = 0x012c,
.sirfsoc_rx_fifo_op = 0x0130,
.sirfsoc_rx_fifo_status = 0x0134,
.sirfsoc_rx_fifo_data = 0x0138,
.sirfsoc_afc_ctrl = 0x0140,
.sirfsoc_swh_dma_io = 0x0148,
},
.uart_int_en = {
.sirfsoc_rx_done_en = BIT(0),
.sirfsoc_tx_done_en = BIT(1),
.sirfsoc_rx_oflow_en = BIT(2),
.sirfsoc_tx_allout_en = BIT(3),
.sirfsoc_rx_io_dma_en = BIT(4),
.sirfsoc_tx_io_dma_en = BIT(5),
.sirfsoc_rxfifo_full_en = BIT(6),
.sirfsoc_txfifo_empty_en = BIT(7),
.sirfsoc_rxfifo_thd_en = BIT(8),
.sirfsoc_txfifo_thd_en = BIT(9),
.sirfsoc_frm_err_en = BIT(10),
.sirfsoc_rxd_brk_en = BIT(11),
.sirfsoc_rx_timeout_en = BIT(12),
.sirfsoc_parity_err_en = BIT(13),
.sirfsoc_cts_en = BIT(14),
.sirfsoc_rts_en = BIT(15),
},
.uart_int_st = {
.sirfsoc_rx_done = BIT(0),
.sirfsoc_tx_done = BIT(1),
.sirfsoc_rx_oflow = BIT(2),
.sirfsoc_tx_allout = BIT(3),
.sirfsoc_rx_io_dma = BIT(4),
.sirfsoc_tx_io_dma = BIT(5),
.sirfsoc_rxfifo_full = BIT(6),
.sirfsoc_txfifo_empty = BIT(7),
.sirfsoc_rxfifo_thd = BIT(8),
.sirfsoc_txfifo_thd = BIT(9),
.sirfsoc_frm_err = BIT(10),
.sirfsoc_rxd_brk = BIT(11),
.sirfsoc_rx_timeout = BIT(12),
.sirfsoc_parity_err = BIT(13),
.sirfsoc_cts = BIT(14),
.sirfsoc_rts = BIT(15),
},
.fifo_status = {
.ff_full = uart_ff_full,
.ff_empty = uart_ff_empty,
},
.uart_param = {
.uart_name = "ttySiRF",
.port_name = "sirfsoc_uart",
.uart_nr = 3,
.register_uart_nr = 0,
},
};
/* uart io ctrl */
#define SIRFUART_DATA_BIT_LEN_MASK 0x3
#define SIRFUART_DATA_BIT_LEN_5 BIT(0)
#define SIRFUART_DATA_BIT_LEN_6 1
@ -50,96 +279,93 @@
#define SIRFUART_LOOP_BACK BIT(7)
#define SIRFUART_PARITY_MASK (7 << 3)
#define SIRFUART_DUMMY_READ BIT(16)
#define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
#define SIRFUART_RECV_TIMEOUT_MASK (0xFFFF << 16)
#define SIRFUART_RECV_TIMEOUT(x) (((x) & 0xFFFF) << 16)
/* UART Auto Flow Control */
#define SIRFUART_AFC_RX_THD_MASK 0x000000FF
#define SIRFUART_AFC_CTRL_RX_THD 0x70
#define SIRFUART_AFC_RX_EN BIT(8)
#define SIRFUART_AFC_TX_EN BIT(9)
#define SIRFUART_CTS_CTRL BIT(10)
#define SIRFUART_RTS_CTRL BIT(11)
#define SIRFUART_CTS_IN_STATUS BIT(12)
#define SIRFUART_RTS_OUT_STATUS BIT(13)
/* UART Interrupt Enable Register */
#define SIRFUART_RX_DONE_INT BIT(0)
#define SIRFUART_TX_DONE_INT BIT(1)
#define SIRFUART_RX_OFLOW_INT BIT(2)
#define SIRFUART_TX_ALLOUT_INT BIT(3)
#define SIRFUART_RX_IO_DMA_INT BIT(4)
#define SIRFUART_TX_IO_DMA_INT BIT(5)
#define SIRFUART_RXFIFO_FULL_INT BIT(6)
#define SIRFUART_TXFIFO_EMPTY_INT BIT(7)
#define SIRFUART_RXFIFO_THD_INT BIT(8)
#define SIRFUART_TXFIFO_THD_INT BIT(9)
#define SIRFUART_FRM_ERR_INT BIT(10)
#define SIRFUART_RXD_BREAK_INT BIT(11)
#define SIRFUART_RX_TIMEOUT_INT BIT(12)
#define SIRFUART_PARITY_ERR_INT BIT(13)
#define SIRFUART_CTS_INT_EN BIT(14)
#define SIRFUART_RTS_INT_EN BIT(15)
/* UART Interrupt Status Register */
#define SIRFUART_RX_DONE BIT(0)
#define SIRFUART_TX_DONE BIT(1)
#define SIRFUART_RX_OFLOW BIT(2)
#define SIRFUART_TX_ALL_EMPTY BIT(3)
#define SIRFUART_DMA_IO_RX_DONE BIT(4)
#define SIRFUART_DMA_IO_TX_DONE BIT(5)
#define SIRFUART_RXFIFO_FULL BIT(6)
#define SIRFUART_TXFIFO_EMPTY BIT(7)
#define SIRFUART_RXFIFO_THD_REACH BIT(8)
#define SIRFUART_TXFIFO_THD_REACH BIT(9)
#define SIRFUART_FRM_ERR BIT(10)
#define SIRFUART_RXD_BREAK BIT(11)
#define SIRFUART_RX_TIMEOUT BIT(12)
#define SIRFUART_PARITY_ERR BIT(13)
#define SIRFUART_CTS_CHANGE BIT(14)
#define SIRFUART_RTS_CHANGE BIT(15)
#define SIRFUART_PLUG_IN BIT(16)
#define SIRFUART_ERR_INT_STAT \
(SIRFUART_RX_OFLOW | \
SIRFUART_FRM_ERR | \
SIRFUART_RXD_BREAK | \
SIRFUART_PARITY_ERR)
#define SIRFUART_ERR_INT_EN \
(SIRFUART_RX_OFLOW_INT | \
SIRFUART_FRM_ERR_INT | \
SIRFUART_RXD_BREAK_INT | \
SIRFUART_PARITY_ERR_INT)
#define SIRFUART_TX_INT_EN SIRFUART_TXFIFO_EMPTY_INT
#define SIRFUART_RX_IO_INT_EN \
(SIRFUART_RX_TIMEOUT_INT | \
SIRFUART_RXFIFO_THD_INT | \
SIRFUART_RXFIFO_FULL_INT | \
SIRFUART_ERR_INT_EN)
#define SIRFUART_AFC_CTS_CTRL BIT(10)
#define SIRFUART_AFC_RTS_CTRL BIT(11)
#define SIRFUART_AFC_CTS_STATUS BIT(12)
#define SIRFUART_AFC_RTS_STATUS BIT(13)
/* UART FIFO Register */
#define SIRFUART_TX_FIFO_STOP 0x0
#define SIRFUART_TX_FIFO_RESET 0x1
#define SIRFUART_TX_FIFO_START 0x2
#define SIRFUART_RX_FIFO_STOP 0x0
#define SIRFUART_RX_FIFO_RESET 0x1
#define SIRFUART_RX_FIFO_START 0x2
#define SIRFUART_TX_MODE_DMA 0
#define SIRFUART_TX_MODE_IO 1
#define SIRFUART_RX_MODE_DMA 0
#define SIRFUART_RX_MODE_IO 1
#define SIRFUART_FIFO_STOP 0x0
#define SIRFUART_FIFO_RESET BIT(0)
#define SIRFUART_FIFO_START BIT(1)
#define SIRFUART_RX_EN 0x1
#define SIRFUART_TX_EN 0x2
#define SIRFUART_RX_EN BIT(0)
#define SIRFUART_TX_EN BIT(1)
#define SIRFUART_IO_MODE BIT(0)
#define SIRFUART_DMA_MODE 0x0
/* Macro Specific*/
#define SIRFUART_INT_EN_CLR 0x0060
/* Baud Rate Calculation */
#define SIRF_MIN_SAMPLE_DIV 0xf
#define SIRF_MAX_SAMPLE_DIV 0x3f
#define SIRF_IOCLK_DIV_MAX 0xffff
#define SIRF_SAMPLE_DIV_SHIFT 16
#define SIRF_IOCLK_DIV_MASK 0xffff
#define SIRF_SAMPLE_DIV_MASK 0x3f0000
#define SIRF_BAUD_RATE_SUPPORT_NR 18
/* USP SPEC */
#define SIRFSOC_USP_ENDIAN_CTRL_LSBF BIT(4)
#define SIRFSOC_USP_EN BIT(5)
#define SIRFSOC_USP_MODE2_RXD_DELAY_OFFSET 0
#define SIRFSOC_USP_MODE2_TXD_DELAY_OFFSET 8
#define SIRFSOC_USP_MODE2_CLK_DIVISOR_MASK 0x3ff
#define SIRFSOC_USP_MODE2_CLK_DIVISOR_OFFSET 21
#define SIRFSOC_USP_TX_DATA_LEN_OFFSET 0
#define SIRFSOC_USP_TX_SYNC_LEN_OFFSET 8
#define SIRFSOC_USP_TX_FRAME_LEN_OFFSET 16
#define SIRFSOC_USP_TX_SHIFTER_LEN_OFFSET 24
#define SIRFSOC_USP_TX_CLK_DIVISOR_OFFSET 30
#define SIRFSOC_USP_RX_DATA_LEN_OFFSET 0
#define SIRFSOC_USP_RX_FRAME_LEN_OFFSET 8
#define SIRFSOC_USP_RX_SHIFTER_LEN_OFFSET 16
#define SIRFSOC_USP_RX_CLK_DIVISOR_OFFSET 24
#define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f
#define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16
/* USP-UART Common */
#define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
#define SIRFUART_RECV_TIMEOUT_VALUE(x) \
(((x) > 0xFFFF) ? 0xFFFF : ((x) & 0xFFFF))
#define SIRFUART_RECV_TIMEOUT(port, x) \
(((port)->line > 2) ? (x & 0xFFFF) : ((x) & 0xFFFF) << 16)
#define SIRFUART_FIFO_THD(port) ((port->line) == 1 ? 16 : 64)
#define SIRFUART_ERR_INT_STAT(port, unit_st) \
(uint_st->sirfsoc_rx_oflow | \
uint_st->sirfsoc_frm_err | \
uint_st->sirfsoc_rxd_brk | \
((port->line > 2) ? 0 : uint_st->sirfsoc_parity_err))
#define SIRFUART_RX_IO_INT_EN(port, uint_en) \
(uint_en->sirfsoc_rx_timeout_en |\
uint_en->sirfsoc_rxfifo_thd_en |\
uint_en->sirfsoc_rxfifo_full_en |\
uint_en->sirfsoc_frm_err_en |\
uint_en->sirfsoc_rx_oflow_en |\
uint_en->sirfsoc_rxd_brk_en |\
((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en))
#define SIRFUART_RX_IO_INT_ST(uint_st) \
(uint_st->sirfsoc_rx_timeout |\
uint_st->sirfsoc_rxfifo_thd |\
uint_st->sirfsoc_rxfifo_full)
#define SIRFUART_CTS_INT_ST(uint_st) (uint_st->sirfsoc_cts)
#define SIRFUART_RX_DMA_INT_EN(port, uint_en) \
(uint_en->sirfsoc_rx_timeout_en |\
uint_en->sirfsoc_frm_err_en |\
uint_en->sirfsoc_rx_oflow_en |\
uint_en->sirfsoc_rxd_brk_en |\
((port->line > 2) ? 0 : uint_en->sirfsoc_parity_err_en))
/* Generic Definitions */
#define SIRFSOC_UART_NAME "ttySiRF"
#define SIRFSOC_UART_MAJOR 0
#define SIRFSOC_UART_MINOR 0
#define SIRFUART_PORT_NAME "sirfsoc-uart"
#define SIRFUART_MAP_SIZE 0x200
#define SIRFSOC_UART_NR 5
#define SIRFSOC_UART_NR 6
#define SIRFSOC_PORT_TYPE 0xa5
/* Baud Rate Calculation */
@ -151,19 +377,80 @@
#define SIRF_SAMPLE_DIV_MASK 0x3f0000
#define SIRF_BAUD_RATE_SUPPORT_NR 18
/* Uart Common Use Macro*/
#define SIRFSOC_RX_DMA_BUF_SIZE 256
#define BYTES_TO_ALIGN(dma_addr) ((unsigned long)(dma_addr) & 0x3)
#define LOOP_DMA_BUFA_FILL 1
#define LOOP_DMA_BUFB_FILL 2
#define TX_TRAN_PIO 1
#define TX_TRAN_DMA 2
/* Uart Fifo Level Chk */
#define SIRFUART_TX_FIFO_SC_OFFSET 0
#define SIRFUART_TX_FIFO_LC_OFFSET 10
#define SIRFUART_TX_FIFO_HC_OFFSET 20
#define SIRFUART_TX_FIFO_CHK_SC(line, value) ((((line) == 1) ? (value & 0x3) :\
(value & 0x1f)) << SIRFUART_TX_FIFO_SC_OFFSET)
#define SIRFUART_TX_FIFO_CHK_LC(line, value) ((((line) == 1) ? (value & 0x3) :\
(value & 0x1f)) << SIRFUART_TX_FIFO_LC_OFFSET)
#define SIRFUART_TX_FIFO_CHK_HC(line, value) ((((line) == 1) ? (value & 0x3) :\
(value & 0x1f)) << SIRFUART_TX_FIFO_HC_OFFSET)
#define SIRFUART_RX_FIFO_CHK_SC SIRFUART_TX_FIFO_CHK_SC
#define SIRFUART_RX_FIFO_CHK_LC SIRFUART_TX_FIFO_CHK_LC
#define SIRFUART_RX_FIFO_CHK_HC SIRFUART_TX_FIFO_CHK_HC
/* Indicate how many buffers used */
#define SIRFSOC_RX_LOOP_BUF_CNT 2
/* Indicate if DMA channel valid */
#define IS_DMA_CHAN_VALID(x) ((x) != -1)
#define UNVALID_DMA_CHAN -1
/* For Fast Baud Rate Calculation */
struct sirfsoc_baudrate_to_regv {
unsigned int baud_rate;
unsigned int reg_val;
};
enum sirfsoc_tx_state {
TX_DMA_IDLE,
TX_DMA_RUNNING,
TX_DMA_PAUSE,
};
struct sirfsoc_loop_buffer {
struct circ_buf xmit;
dma_cookie_t cookie;
struct dma_async_tx_descriptor *desc;
dma_addr_t dma_addr;
};
struct sirfsoc_uart_port {
unsigned char hw_flow_ctrl;
unsigned char ms_enabled;
bool hw_flow_ctrl;
bool ms_enabled;
struct uart_port port;
struct pinctrl *p;
struct clk *clk;
/* for SiRFmarco, there are SET/CLR for UART_INT_EN */
bool is_marco;
struct sirfsoc_uart_register *uart_reg;
int rx_dma_no;
int tx_dma_no;
struct dma_chan *rx_dma_chan;
struct dma_chan *tx_dma_chan;
dma_addr_t tx_dma_addr;
struct dma_async_tx_descriptor *tx_dma_desc;
spinlock_t rx_lock;
spinlock_t tx_lock;
struct tasklet_struct rx_dma_complete_tasklet;
struct tasklet_struct rx_tmo_process_tasklet;
unsigned int rx_io_count;
unsigned long transfer_size;
enum sirfsoc_tx_state tx_dma_state;
unsigned int cts_gpio;
unsigned int rts_gpio;
struct sirfsoc_loop_buffer rx_dma_items[SIRFSOC_RX_LOOP_BUF_CNT];
int rx_completed;
int rx_issued;
};
/* Hardware Flow Control */

932
drivers/tty/serial/st-asc.c Normal file
Просмотреть файл

@ -0,0 +1,932 @@
/*
* st-asc.c: ST Asynchronous serial controller (ASC) driver
*
* Copyright (C) 2003-2013 STMicroelectronics (R&D) Limited
*
* 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.
*
*/
#if defined(CONFIG_SERIAL_ST_ASC_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
#include <linux/module.h>
#include <linux/serial.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/serial_core.h>
#include <linux/clk.h>
#define DRIVER_NAME "st-asc"
#define ASC_SERIAL_NAME "ttyAS"
#define ASC_FIFO_SIZE 16
#define ASC_MAX_PORTS 8
struct asc_port {
struct uart_port port;
struct clk *clk;
unsigned int hw_flow_control:1;
unsigned int force_m1:1;
};
static struct asc_port asc_ports[ASC_MAX_PORTS];
static struct uart_driver asc_uart_driver;
/*---- UART Register definitions ------------------------------*/
/* Register offsets */
#define ASC_BAUDRATE 0x00
#define ASC_TXBUF 0x04
#define ASC_RXBUF 0x08
#define ASC_CTL 0x0C
#define ASC_INTEN 0x10
#define ASC_STA 0x14
#define ASC_GUARDTIME 0x18
#define ASC_TIMEOUT 0x1C
#define ASC_TXRESET 0x20
#define ASC_RXRESET 0x24
#define ASC_RETRIES 0x28
/* ASC_RXBUF */
#define ASC_RXBUF_PE 0x100
#define ASC_RXBUF_FE 0x200
/**
* Some of status comes from higher bits of the character and some come from
* the status register. Combining both of them in to single status using dummy
* bits.
*/
#define ASC_RXBUF_DUMMY_RX 0x10000
#define ASC_RXBUF_DUMMY_BE 0x20000
#define ASC_RXBUF_DUMMY_OE 0x40000
/* ASC_CTL */
#define ASC_CTL_MODE_MSK 0x0007
#define ASC_CTL_MODE_8BIT 0x0001
#define ASC_CTL_MODE_7BIT_PAR 0x0003
#define ASC_CTL_MODE_9BIT 0x0004
#define ASC_CTL_MODE_8BIT_WKUP 0x0005
#define ASC_CTL_MODE_8BIT_PAR 0x0007
#define ASC_CTL_STOP_MSK 0x0018
#define ASC_CTL_STOP_HALFBIT 0x0000
#define ASC_CTL_STOP_1BIT 0x0008
#define ASC_CTL_STOP_1_HALFBIT 0x0010
#define ASC_CTL_STOP_2BIT 0x0018
#define ASC_CTL_PARITYODD 0x0020
#define ASC_CTL_LOOPBACK 0x0040
#define ASC_CTL_RUN 0x0080
#define ASC_CTL_RXENABLE 0x0100
#define ASC_CTL_SCENABLE 0x0200
#define ASC_CTL_FIFOENABLE 0x0400
#define ASC_CTL_CTSENABLE 0x0800
#define ASC_CTL_BAUDMODE 0x1000
/* ASC_GUARDTIME */
#define ASC_GUARDTIME_MSK 0x00FF
/* ASC_INTEN */
#define ASC_INTEN_RBE 0x0001
#define ASC_INTEN_TE 0x0002
#define ASC_INTEN_THE 0x0004
#define ASC_INTEN_PE 0x0008
#define ASC_INTEN_FE 0x0010
#define ASC_INTEN_OE 0x0020
#define ASC_INTEN_TNE 0x0040
#define ASC_INTEN_TOI 0x0080
#define ASC_INTEN_RHF 0x0100
/* ASC_RETRIES */
#define ASC_RETRIES_MSK 0x00FF
/* ASC_RXBUF */
#define ASC_RXBUF_MSK 0x03FF
/* ASC_STA */
#define ASC_STA_RBF 0x0001
#define ASC_STA_TE 0x0002
#define ASC_STA_THE 0x0004
#define ASC_STA_PE 0x0008
#define ASC_STA_FE 0x0010
#define ASC_STA_OE 0x0020
#define ASC_STA_TNE 0x0040
#define ASC_STA_TOI 0x0080
#define ASC_STA_RHF 0x0100
#define ASC_STA_TF 0x0200
#define ASC_STA_NKD 0x0400
/* ASC_TIMEOUT */
#define ASC_TIMEOUT_MSK 0x00FF
/* ASC_TXBUF */
#define ASC_TXBUF_MSK 0x01FF
/*---- Inline function definitions ---------------------------*/
static inline struct asc_port *to_asc_port(struct uart_port *port)
{
return container_of(port, struct asc_port, port);
}
static inline u32 asc_in(struct uart_port *port, u32 offset)
{
return readl(port->membase + offset);
}
static inline void asc_out(struct uart_port *port, u32 offset, u32 value)
{
writel(value, port->membase + offset);
}
/*
* Some simple utility functions to enable and disable interrupts.
* Note that these need to be called with interrupts disabled.
*/
static inline void asc_disable_tx_interrupts(struct uart_port *port)
{
u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_THE;
asc_out(port, ASC_INTEN, intenable);
(void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
}
static inline void asc_enable_tx_interrupts(struct uart_port *port)
{
u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_THE;
asc_out(port, ASC_INTEN, intenable);
}
static inline void asc_disable_rx_interrupts(struct uart_port *port)
{
u32 intenable = asc_in(port, ASC_INTEN) & ~ASC_INTEN_RBE;
asc_out(port, ASC_INTEN, intenable);
(void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
}
static inline void asc_enable_rx_interrupts(struct uart_port *port)
{
u32 intenable = asc_in(port, ASC_INTEN) | ASC_INTEN_RBE;
asc_out(port, ASC_INTEN, intenable);
}
static inline u32 asc_txfifo_is_empty(struct uart_port *port)
{
return asc_in(port, ASC_STA) & ASC_STA_TE;
}
static inline int asc_txfifo_is_full(struct uart_port *port)
{
return asc_in(port, ASC_STA) & ASC_STA_TF;
}
static inline const char *asc_port_name(struct uart_port *port)
{
return to_platform_device(port->dev)->name;
}
/*----------------------------------------------------------------------*/
/*
* This section contains code to support the use of the ASC as a
* generic serial port.
*/
static inline unsigned asc_hw_txroom(struct uart_port *port)
{
u32 status = asc_in(port, ASC_STA);
if (status & ASC_STA_THE)
return port->fifosize / 2;
else if (!(status & ASC_STA_TF))
return 1;
return 0;
}
/*
* Start transmitting chars.
* This is called from both interrupt and task level.
* Either way interrupts are disabled.
*/
static void asc_transmit_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
int txroom;
unsigned char c;
txroom = asc_hw_txroom(port);
if ((txroom != 0) && port->x_char) {
c = port->x_char;
port->x_char = 0;
asc_out(port, ASC_TXBUF, c);
port->icount.tx++;
txroom = asc_hw_txroom(port);
}
if (uart_tx_stopped(port)) {
/*
* We should try and stop the hardware here, but I
* don't think the ASC has any way to do that.
*/
asc_disable_tx_interrupts(port);
return;
}
if (uart_circ_empty(xmit)) {
asc_disable_tx_interrupts(port);
return;
}
if (txroom == 0)
return;
do {
c = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
asc_out(port, ASC_TXBUF, c);
port->icount.tx++;
txroom--;
} while ((txroom > 0) && (!uart_circ_empty(xmit)));
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit))
asc_disable_tx_interrupts(port);
}
static void asc_receive_chars(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
unsigned long status;
unsigned long c = 0;
char flag;
if (port->irq_wake)
pm_wakeup_event(tport->tty->dev, 0);
while ((status = asc_in(port, ASC_STA)) & ASC_STA_RBF) {
c = asc_in(port, ASC_RXBUF) | ASC_RXBUF_DUMMY_RX;
flag = TTY_NORMAL;
port->icount.rx++;
if ((c & (ASC_RXBUF_FE | ASC_RXBUF_PE)) ||
status & ASC_STA_OE) {
if (c & ASC_RXBUF_FE) {
if (c == ASC_RXBUF_FE) {
port->icount.brk++;
if (uart_handle_break(port))
continue;
c |= ASC_RXBUF_DUMMY_BE;
} else {
port->icount.frame++;
}
} else if (c & ASC_RXBUF_PE) {
port->icount.parity++;
}
/*
* Reading any data from the RX FIFO clears the
* overflow error condition.
*/
if (status & ASC_STA_OE) {
port->icount.overrun++;
c |= ASC_RXBUF_DUMMY_OE;
}
c &= port->read_status_mask;
if (c & ASC_RXBUF_DUMMY_BE)
flag = TTY_BREAK;
else if (c & ASC_RXBUF_PE)
flag = TTY_PARITY;
else if (c & ASC_RXBUF_FE)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(port, c))
continue;
uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag);
}
/* Tell the rest of the system the news. New characters! */
tty_flip_buffer_push(tport);
}
static irqreturn_t asc_interrupt(int irq, void *ptr)
{
struct uart_port *port = ptr;
u32 status;
spin_lock(&port->lock);
status = asc_in(port, ASC_STA);
if (status & ASC_STA_RBF) {
/* Receive FIFO not empty */
asc_receive_chars(port);
}
if ((status & ASC_STA_THE) &&
(asc_in(port, ASC_INTEN) & ASC_INTEN_THE)) {
/* Transmitter FIFO at least half empty */
asc_transmit_chars(port);
}
spin_unlock(&port->lock);
return IRQ_HANDLED;
}
/*----------------------------------------------------------------------*/
/*
* UART Functions
*/
static unsigned int asc_tx_empty(struct uart_port *port)
{
return asc_txfifo_is_empty(port) ? TIOCSER_TEMT : 0;
}
static void asc_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
/*
* This routine is used for seting signals of: DTR, DCD, CTS/RTS
* We use ASC's hardware for CTS/RTS, so don't need any for that.
* Some boards have DTR and DCD implemented using PIO pins,
* code to do this should be hooked in here.
*/
}
static unsigned int asc_get_mctrl(struct uart_port *port)
{
/*
* This routine is used for geting signals of: DTR, DCD, DSR, RI,
* and CTS/RTS
*/
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
}
/* There are probably characters waiting to be transmitted. */
static void asc_start_tx(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
if (!uart_circ_empty(xmit))
asc_enable_tx_interrupts(port);
}
/* Transmit stop */
static void asc_stop_tx(struct uart_port *port)
{
asc_disable_tx_interrupts(port);
}
/* Receive stop */
static void asc_stop_rx(struct uart_port *port)
{
asc_disable_rx_interrupts(port);
}
/* Force modem status interrupts on */
static void asc_enable_ms(struct uart_port *port)
{
/* Nothing here yet .. */
}
/* Handle breaks - ignored by us */
static void asc_break_ctl(struct uart_port *port, int break_state)
{
/* Nothing here yet .. */
}
/*
* Enable port for reception.
*/
static int asc_startup(struct uart_port *port)
{
if (request_irq(port->irq, asc_interrupt, IRQF_NO_SUSPEND,
asc_port_name(port), port)) {
dev_err(port->dev, "cannot allocate irq.\n");
return -ENODEV;
}
asc_transmit_chars(port);
asc_enable_rx_interrupts(port);
return 0;
}
static void asc_shutdown(struct uart_port *port)
{
asc_disable_tx_interrupts(port);
asc_disable_rx_interrupts(port);
free_irq(port->irq, port);
}
static void asc_pm(struct uart_port *port, unsigned int state,
unsigned int oldstate)
{
struct asc_port *ascport = to_asc_port(port);
unsigned long flags = 0;
u32 ctl;
switch (state) {
case UART_PM_STATE_ON:
clk_prepare_enable(ascport->clk);
break;
case UART_PM_STATE_OFF:
/*
* Disable the ASC baud rate generator, which is as close as
* we can come to turning it off. Note this is not called with
* the port spinlock held.
*/
spin_lock_irqsave(&port->lock, flags);
ctl = asc_in(port, ASC_CTL) & ~ASC_CTL_RUN;
asc_out(port, ASC_CTL, ctl);
spin_unlock_irqrestore(&port->lock, flags);
clk_disable_unprepare(ascport->clk);
break;
}
}
static void asc_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct asc_port *ascport = to_asc_port(port);
unsigned int baud;
u32 ctrl_val;
tcflag_t cflag;
unsigned long flags;
/* Update termios to reflect hardware capabilities */
termios->c_cflag &= ~(CMSPAR |
(ascport->hw_flow_control ? 0 : CRTSCTS));
port->uartclk = clk_get_rate(ascport->clk);
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
cflag = termios->c_cflag;
spin_lock_irqsave(&port->lock, flags);
/* read control register */
ctrl_val = asc_in(port, ASC_CTL);
/* stop serial port and reset value */
asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN));
ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE;
/* reset fifo rx & tx */
asc_out(port, ASC_TXRESET, 1);
asc_out(port, ASC_RXRESET, 1);
/* set character length */
if ((cflag & CSIZE) == CS7) {
ctrl_val |= ASC_CTL_MODE_7BIT_PAR;
} else {
ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR :
ASC_CTL_MODE_8BIT;
}
/* set stop bit */
ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT;
/* odd parity */
if (cflag & PARODD)
ctrl_val |= ASC_CTL_PARITYODD;
/* hardware flow control */
if ((cflag & CRTSCTS))
ctrl_val |= ASC_CTL_CTSENABLE;
if ((baud < 19200) && !ascport->force_m1) {
asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud)));
} else {
/*
* MODE 1: recommended for high bit rates (above 19.2K)
*
* baudrate * 16 * 2^16
* ASCBaudRate = ------------------------
* inputclock
*
* However to keep the maths inside 32bits we divide top and
* bottom by 64. The +1 is to avoid a divide by zero if the
* input clock rate is something unexpected.
*/
u32 counter = (baud * 16384) / ((port->uartclk / 64) + 1);
asc_out(port, ASC_BAUDRATE, counter);
ctrl_val |= ASC_CTL_BAUDMODE;
}
uart_update_timeout(port, cflag, baud);
ascport->port.read_status_mask = ASC_RXBUF_DUMMY_OE;
if (termios->c_iflag & INPCK)
ascport->port.read_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE;
if (termios->c_iflag & (BRKINT | PARMRK))
ascport->port.read_status_mask |= ASC_RXBUF_DUMMY_BE;
/*
* Characters to ignore
*/
ascport->port.ignore_status_mask = 0;
if (termios->c_iflag & IGNPAR)
ascport->port.ignore_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE;
if (termios->c_iflag & IGNBRK) {
ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_BE;
/*
* If we're ignoring parity and break indicators,
* ignore overruns too (for real raw support).
*/
if (termios->c_iflag & IGNPAR)
ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_OE;
}
/*
* Ignore all characters if CREAD is not set.
*/
if (!(termios->c_cflag & CREAD))
ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_RX;
/* Set the timeout */
asc_out(port, ASC_TIMEOUT, 20);
/* write final value and enable port */
asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN));
spin_unlock_irqrestore(&port->lock, flags);
}
static const char *asc_type(struct uart_port *port)
{
return (port->type == PORT_ASC) ? DRIVER_NAME : NULL;
}
static void asc_release_port(struct uart_port *port)
{
}
static int asc_request_port(struct uart_port *port)
{
return 0;
}
/*
* Called when the port is opened, and UPF_BOOT_AUTOCONF flag is set
* Set type field if successful
*/
static void asc_config_port(struct uart_port *port, int flags)
{
if ((flags & UART_CONFIG_TYPE))
port->type = PORT_ASC;
}
static int
asc_verify_port(struct uart_port *port, struct serial_struct *ser)
{
/* No user changeable parameters */
return -EINVAL;
}
#ifdef CONFIG_CONSOLE_POLL
/*
* Console polling routines for writing and reading from the uart while
* in an interrupt or debug context (i.e. kgdb).
*/
static int asc_get_poll_char(struct uart_port *port)
{
if (!(asc_in(port, ASC_STA) & ASC_STA_RBF))
return NO_POLL_CHAR;
return asc_in(port, ASC_RXBUF);
}
static void asc_put_poll_char(struct uart_port *port, unsigned char c)
{
while (asc_txfifo_is_full(port))
cpu_relax();
asc_out(port, ASC_TXBUF, c);
}
#endif /* CONFIG_CONSOLE_POLL */
/*---------------------------------------------------------------------*/
static struct uart_ops asc_uart_ops = {
.tx_empty = asc_tx_empty,
.set_mctrl = asc_set_mctrl,
.get_mctrl = asc_get_mctrl,
.start_tx = asc_start_tx,
.stop_tx = asc_stop_tx,
.stop_rx = asc_stop_rx,
.enable_ms = asc_enable_ms,
.break_ctl = asc_break_ctl,
.startup = asc_startup,
.shutdown = asc_shutdown,
.set_termios = asc_set_termios,
.type = asc_type,
.release_port = asc_release_port,
.request_port = asc_request_port,
.config_port = asc_config_port,
.verify_port = asc_verify_port,
.pm = asc_pm,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = asc_get_poll_char,
.poll_put_char = asc_put_poll_char,
#endif /* CONFIG_CONSOLE_POLL */
};
static int asc_init_port(struct asc_port *ascport,
struct platform_device *pdev)
{
struct uart_port *port = &ascport->port;
struct resource *res;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &asc_uart_ops;
port->fifosize = ASC_FIFO_SIZE;
port->dev = &pdev->dev;
port->irq = platform_get_irq(pdev, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
port->mapbase = res->start;
spin_lock_init(&port->lock);
ascport->clk = devm_clk_get(&pdev->dev, NULL);
if (WARN_ON(IS_ERR(ascport->clk)))
return -EINVAL;
/* ensure that clk rate is correct by enabling the clk */
clk_prepare_enable(ascport->clk);
ascport->port.uartclk = clk_get_rate(ascport->clk);
WARN_ON(ascport->port.uartclk == 0);
clk_disable_unprepare(ascport->clk);
return 0;
}
static struct asc_port *asc_of_get_asc_port(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int id;
if (!np)
return NULL;
id = of_alias_get_id(np, ASC_SERIAL_NAME);
if (id < 0)
id = 0;
if (WARN_ON(id >= ASC_MAX_PORTS))
return NULL;
asc_ports[id].hw_flow_control = of_property_read_bool(np,
"st,hw-flow-control");
asc_ports[id].force_m1 = of_property_read_bool(np, "st,force_m1");
asc_ports[id].port.line = id;
return &asc_ports[id];
}
#ifdef CONFIG_OF
static struct of_device_id asc_match[] = {
{ .compatible = "st,asc", },
{},
};
MODULE_DEVICE_TABLE(of, asc_match);
#endif
static int asc_serial_probe(struct platform_device *pdev)
{
int ret;
struct asc_port *ascport;
ascport = asc_of_get_asc_port(pdev);
if (!ascport)
return -ENODEV;
ret = asc_init_port(ascport, pdev);
if (ret)
return ret;
ret = uart_add_one_port(&asc_uart_driver, &ascport->port);
if (ret)
return ret;
platform_set_drvdata(pdev, &ascport->port);
return 0;
}
static int asc_serial_remove(struct platform_device *pdev)
{
struct uart_port *port = platform_get_drvdata(pdev);
return uart_remove_one_port(&asc_uart_driver, port);
}
#ifdef CONFIG_PM_SLEEP
static int asc_serial_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct uart_port *port = platform_get_drvdata(pdev);
return uart_suspend_port(&asc_uart_driver, port);
}
static int asc_serial_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct uart_port *port = platform_get_drvdata(pdev);
return uart_resume_port(&asc_uart_driver, port);
}
#endif /* CONFIG_PM_SLEEP */
/*----------------------------------------------------------------------*/
#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
static void asc_console_putchar(struct uart_port *port, int ch)
{
unsigned int timeout = 1000000;
/* Wait for upto 1 second in case flow control is stopping us. */
while (--timeout && asc_txfifo_is_full(port))
udelay(1);
asc_out(port, ASC_TXBUF, ch);
}
/*
* Print a string to the serial port trying not to disturb
* any possible real use of the port...
*/
static void asc_console_write(struct console *co, const char *s, unsigned count)
{
struct uart_port *port = &asc_ports[co->index].port;
unsigned long flags;
unsigned long timeout = 1000000;
int locked = 1;
u32 intenable;
local_irq_save(flags);
if (port->sysrq)
locked = 0; /* asc_interrupt has already claimed the lock */
else if (oops_in_progress)
locked = spin_trylock(&port->lock);
else
spin_lock(&port->lock);
/*
* Disable interrupts so we don't get the IRQ line bouncing
* up and down while interrupts are disabled.
*/
intenable = asc_in(port, ASC_INTEN);
asc_out(port, ASC_INTEN, 0);
(void)asc_in(port, ASC_INTEN); /* Defeat bus write posting */
uart_console_write(port, s, count, asc_console_putchar);
while (--timeout && !asc_txfifo_is_empty(port))
udelay(1);
asc_out(port, ASC_INTEN, intenable);
if (locked)
spin_unlock(&port->lock);
local_irq_restore(flags);
}
static int asc_console_setup(struct console *co, char *options)
{
struct asc_port *ascport;
int baud = 9600;
int bits = 8;
int parity = 'n';
int flow = 'n';
if (co->index >= ASC_MAX_PORTS)
return -ENODEV;
ascport = &asc_ports[co->index];
/*
* This driver does not support early console initialization
* (use ARM early printk support instead), so we only expect
* this to be called during the uart port registration when the
* driver gets probed and the port should be mapped at that point.
*/
BUG_ON(ascport->port.mapbase == 0 || ascport->port.membase == NULL);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
return uart_set_options(&ascport->port, co, baud, parity, bits, flow);
}
static struct console asc_console = {
.name = ASC_SERIAL_NAME,
.device = uart_console_device,
.write = asc_console_write,
.setup = asc_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &asc_uart_driver,
};
#define ASC_SERIAL_CONSOLE (&asc_console)
#else
#define ASC_SERIAL_CONSOLE NULL
#endif /* CONFIG_SERIAL_ST_ASC_CONSOLE */
static struct uart_driver asc_uart_driver = {
.owner = THIS_MODULE,
.driver_name = DRIVER_NAME,
.dev_name = ASC_SERIAL_NAME,
.major = 0,
.minor = 0,
.nr = ASC_MAX_PORTS,
.cons = ASC_SERIAL_CONSOLE,
};
static const struct dev_pm_ops asc_serial_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume)
};
static struct platform_driver asc_serial_driver = {
.probe = asc_serial_probe,
.remove = asc_serial_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &asc_serial_pm_ops,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(asc_match),
},
};
static int __init asc_init(void)
{
int ret;
static char banner[] __initdata =
KERN_INFO "STMicroelectronics ASC driver initialized\n";
printk(banner);
ret = uart_register_driver(&asc_uart_driver);
if (ret)
return ret;
ret = platform_driver_register(&asc_serial_driver);
if (ret)
uart_unregister_driver(&asc_uart_driver);
return ret;
}
static void __exit asc_exit(void)
{
platform_driver_unregister(&asc_serial_driver);
uart_unregister_driver(&asc_uart_driver);
}
module_init(asc_init);
module_exit(asc_exit);
MODULE_ALIAS("platform:" DRIVER_NAME);
MODULE_AUTHOR("STMicroelectronics (R&D) Limited");
MODULE_DESCRIPTION("STMicroelectronics ASC serial port driver");
MODULE_LICENSE("GPL");

Просмотреть файл

@ -162,7 +162,7 @@ static void timbuart_handle_tx_port(struct uart_port *port, u32 isr, u32 *ier)
dev_dbg(port->dev, "%s - leaving\n", __func__);
}
void timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier)
static void timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier)
{
if (isr & RXFLAGS) {
/* Some RX status is set */
@ -184,7 +184,7 @@ void timbuart_handle_rx_port(struct uart_port *port, u32 isr, u32 *ier)
dev_dbg(port->dev, "%s - leaving\n", __func__);
}
void timbuart_tasklet(unsigned long arg)
static void timbuart_tasklet(unsigned long arg)
{
struct timbuart_port *uart = (struct timbuart_port *)arg;
u32 isr, ier = 0;

Просмотреть файл

@ -705,7 +705,7 @@ static int siu_init_ports(struct platform_device *pdev)
{
struct uart_port *port;
struct resource *res;
int *type = pdev->dev.platform_data;
int *type = dev_get_platdata(&pdev->dev);
int i;
if (!type)

Просмотреть файл

@ -170,7 +170,9 @@ static void handle_rx(struct uart_port *port)
tty_insert_flip_char(tport, c, flag);
}
spin_unlock(&port->lock);
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
}
static void handle_tx(struct uart_port *port)
@ -630,7 +632,6 @@ static int vt8500_serial_remove(struct platform_device *pdev)
{
struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
clk_disable_unprepare(vt8500_port->clk);
uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart);

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше