mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-18 04:09:08 +08:00
Merge tag 'tty-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty / serial updates from Greg KH: "Here is a small set of tty and serial driver updates for 6.11-rc1. Not much happened this cycle, unlike the previous kernel release which had lots of "excitement" in this part of the kernel. Included in here are the following changes: - dt binding updates for new platforms - 8250 driver updates - various small serial driver fixes and updates - printk/console naming and matching attempt #2 (was reverted for 6.10-final, should be good to go this time around, acked by the relevant maintainers). All of these have been in linux-next for a while with no reported issues" * tag 'tty-6.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (22 commits) Documentation: kernel-parameters: Add DEVNAME:0.0 format for serial ports serial: core: Add serial_base_match_and_update_preferred_console() printk: Add match_devname_and_update_preferred_console() serial: sc16is7xx: hardware reset chip if reset-gpios is defined in DT dt-bindings: serial: sc16is7xx: add reset-gpios dt-bindings: serial: vt8500-uart: convert to json-schema serial: 8250_platform: Explicitly show we initialise ISA ports only once tty: add missing MODULE_DESCRIPTION() macros dt-bindings: serial: mediatek,uart: add MT7988 serial: sh-sci: Add support for RZ/V2H(P) SoC dt-bindings: serial: Add documentation for Renesas RZ/V2H(P) (R9A09G057) SCIF support dt-bindings: serial: renesas,scif: Make 'interrupt-names' property as required dt-bindings: serial: renesas,scif: Validate 'interrupts' and 'interrupt-names' dt-bindings: serial: renesas,scif: Move ref for serial.yaml at the end riscv: dts: starfive: jh7110: Add the core reset and jh7110 compatible for uarts serial: 8250_dw: Use reset array API to get resets dt-bindings: serial: snps-dw-apb-uart: Add one more reset signal for StarFive JH7110 SoC serial: 8250: Extract platform driver serial: 8250: Extract RSA bits serial: imx: stop casting struct uart_port to struct imx_port ...
This commit is contained in:
@@ -792,6 +792,25 @@
|
||||
Documentation/networking/netconsole.rst for an
|
||||
alternative.
|
||||
|
||||
<DEVNAME>:<n>.<n>[,options]
|
||||
Use the specified serial port on the serial core bus.
|
||||
The addressing uses DEVNAME of the physical serial port
|
||||
device, followed by the serial core controller instance,
|
||||
and the serial port instance. The options are the same
|
||||
as documented for the ttyS addressing above.
|
||||
|
||||
The mapping of the serial ports to the tty instances
|
||||
can be viewed with:
|
||||
|
||||
$ ls -d /sys/bus/serial-base/devices/*:*.*/tty/*
|
||||
/sys/bus/serial-base/devices/00:04:0.0/tty/ttyS0
|
||||
|
||||
In the above example, the console can be addressed with
|
||||
console=00:04:0.0. Note that a console addressed this
|
||||
way will only get added when the related device driver
|
||||
is ready. The use of an earlycon parameter in addition to
|
||||
the console may be desired for console output early on.
|
||||
|
||||
uart[8250],io,<addr>[,options]
|
||||
uart[8250],mmio,<addr>[,options]
|
||||
uart[8250],mmio16,<addr>[,options]
|
||||
|
||||
@@ -37,6 +37,7 @@ properties:
|
||||
- mediatek,mt7623-uart
|
||||
- mediatek,mt7629-uart
|
||||
- mediatek,mt7986-uart
|
||||
- mediatek,mt7988-uart
|
||||
- mediatek,mt8127-uart
|
||||
- mediatek,mt8135-uart
|
||||
- mediatek,mt8173-uart
|
||||
|
||||
@@ -28,6 +28,9 @@ properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
clock-frequency:
|
||||
description:
|
||||
When there is no clock provider visible to the platform, this
|
||||
@@ -91,6 +94,7 @@ unevaluatedProperties: false
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
@@ -120,6 +124,7 @@ examples:
|
||||
compatible = "nxp,sc16is752";
|
||||
reg = <0x54>;
|
||||
clocks = <&clk20m>;
|
||||
reset-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||
nxp,modem-control-line-ports = <0 1>; /* Ports 0 and 1 as modem control lines */
|
||||
|
||||
@@ -9,9 +9,6 @@ title: Renesas Serial Communication Interface with FIFO (SCIF)
|
||||
maintainers:
|
||||
- Geert Uytterhoeven <geert+renesas@glider.be>
|
||||
|
||||
allOf:
|
||||
- $ref: serial.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
@@ -83,6 +80,8 @@ properties:
|
||||
- renesas,scif-r9a08g045 # RZ/G3S
|
||||
- const: renesas,scif-r9a07g044 # RZ/G2{L,LC} fallback
|
||||
|
||||
- const: renesas,scif-r9a09g057 # RZ/V2H(P)
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -90,11 +89,6 @@ properties:
|
||||
oneOf:
|
||||
- items:
|
||||
- description: A combined interrupt
|
||||
- items:
|
||||
- description: Error interrupt
|
||||
- description: Receive buffer full interrupt
|
||||
- description: Transmit buffer empty interrupt
|
||||
- description: Break interrupt
|
||||
- items:
|
||||
- description: Error interrupt
|
||||
- description: Receive buffer full interrupt
|
||||
@@ -102,21 +96,23 @@ properties:
|
||||
- description: Break interrupt
|
||||
- description: Data Ready interrupt
|
||||
- description: Transmit End interrupt
|
||||
- description: Transmit End/Data Ready interrupt
|
||||
- description: Receive buffer full interrupt (EDGE trigger)
|
||||
- description: Transmit buffer empty interrupt (EDGE trigger)
|
||||
minItems: 4
|
||||
|
||||
interrupt-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: eri
|
||||
- const: rxi
|
||||
- const: txi
|
||||
- const: bri
|
||||
- items:
|
||||
- const: eri
|
||||
- const: rxi
|
||||
- const: txi
|
||||
- const: bri
|
||||
- const: dri
|
||||
- const: tei
|
||||
minItems: 4
|
||||
items:
|
||||
- const: eri
|
||||
- const: rxi
|
||||
- const: txi
|
||||
- const: bri
|
||||
- const: dri
|
||||
- const: tei
|
||||
- const: tei-dri
|
||||
- const: rxi-edge
|
||||
- const: txi-edge
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
@@ -161,18 +157,92 @@ required:
|
||||
- clock-names
|
||||
- power-domains
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,rcar-gen2-scif
|
||||
- renesas,rcar-gen3-scif
|
||||
- renesas,rcar-gen4-scif
|
||||
- renesas,scif-r9a07g044
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
allOf:
|
||||
- $ref: serial.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,rcar-gen2-scif
|
||||
- renesas,rcar-gen3-scif
|
||||
- renesas,rcar-gen4-scif
|
||||
- renesas,scif-r9a07g044
|
||||
- renesas,scif-r9a09g057
|
||||
then:
|
||||
required:
|
||||
- resets
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,rcar-gen1-scif
|
||||
- renesas,rcar-gen2-scif
|
||||
- renesas,rcar-gen3-scif
|
||||
- renesas,rcar-gen4-scif
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
interrupt-names: false
|
||||
else:
|
||||
required:
|
||||
- interrupt-names
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,scif-r7s72100
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
|
||||
interrupt-names:
|
||||
maxItems: 4
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,scif-r7s9210
|
||||
- renesas,scif-r9a07g044
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
|
||||
interrupt-names:
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,scif-r9a09g057
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 9
|
||||
|
||||
interrupt-names:
|
||||
minItems: 9
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -13,6 +13,20 @@ allOf:
|
||||
- $ref: serial.yaml#
|
||||
- $ref: rs485.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: starfive,jh7110-uart
|
||||
then:
|
||||
properties:
|
||||
resets:
|
||||
minItems: 2
|
||||
else:
|
||||
properties:
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
@@ -48,6 +62,7 @@ properties:
|
||||
- enum:
|
||||
- starfive,jh7100-hsuart
|
||||
- starfive,jh7100-uart
|
||||
- starfive,jh7110-uart
|
||||
- const: snps,dw-apb-uart
|
||||
- const: snps,dw-apb-uart
|
||||
|
||||
@@ -82,7 +97,8 @@ properties:
|
||||
type: boolean
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reg-shift: true
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/serial/via,vt8500-uart.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: VIA VT8500 and WonderMedia WM8xxx UART Controller
|
||||
|
||||
maintainers:
|
||||
- Alexey Charkov <alchark@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: serial.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- via,vt8500-uart # up to WM8850/WM8950
|
||||
- wm,wm8880-uart # for WM8880 and later
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
- interrupts
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
serial@d8200000 {
|
||||
compatible = "via,vt8500-uart";
|
||||
reg = <0xd8200000 0x1040>;
|
||||
interrupts = <32>;
|
||||
clocks = <&clkuart0>;
|
||||
};
|
||||
@@ -1,27 +0,0 @@
|
||||
* VIA VT8500 and WonderMedia WM8xxx UART Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "via,vt8500-uart" (for VIA/WonderMedia chips up to and
|
||||
including WM8850/WM8950), or "wm,wm8880-uart" (for WM8880 and later)
|
||||
|
||||
- reg: base physical address of the controller and length of memory mapped
|
||||
region.
|
||||
|
||||
- interrupts: hardware interrupt number
|
||||
|
||||
- clocks: shall be the input parent clock phandle for the clock. This should
|
||||
be the 24Mhz reference clock.
|
||||
|
||||
Aliases may be defined to ensure the correct ordering of the uarts.
|
||||
|
||||
Example:
|
||||
aliases {
|
||||
serial0 = &uart0;
|
||||
};
|
||||
|
||||
uart0: serial@d8200000 {
|
||||
compatible = "via,vt8500-uart";
|
||||
reg = <0xd8200000 0x1040>;
|
||||
interrupts = <32>;
|
||||
clocks = <&clkuart0>;
|
||||
};
|
||||
@@ -387,12 +387,13 @@
|
||||
};
|
||||
|
||||
uart0: serial@10000000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
|
||||
reg = <0x0 0x10000000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_UART0_CORE>,
|
||||
<&syscrg JH7110_SYSCLK_UART0_APB>;
|
||||
clock-names = "baudclk", "apb_pclk";
|
||||
resets = <&syscrg JH7110_SYSRST_UART0_APB>;
|
||||
resets = <&syscrg JH7110_SYSRST_UART0_APB>,
|
||||
<&syscrg JH7110_SYSRST_UART0_CORE>;
|
||||
interrupts = <32>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
@@ -400,12 +401,13 @@
|
||||
};
|
||||
|
||||
uart1: serial@10010000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
|
||||
reg = <0x0 0x10010000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_UART1_CORE>,
|
||||
<&syscrg JH7110_SYSCLK_UART1_APB>;
|
||||
clock-names = "baudclk", "apb_pclk";
|
||||
resets = <&syscrg JH7110_SYSRST_UART1_APB>;
|
||||
resets = <&syscrg JH7110_SYSRST_UART1_APB>,
|
||||
<&syscrg JH7110_SYSRST_UART1_CORE>;
|
||||
interrupts = <33>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
@@ -413,12 +415,13 @@
|
||||
};
|
||||
|
||||
uart2: serial@10020000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
|
||||
reg = <0x0 0x10020000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_UART2_CORE>,
|
||||
<&syscrg JH7110_SYSCLK_UART2_APB>;
|
||||
clock-names = "baudclk", "apb_pclk";
|
||||
resets = <&syscrg JH7110_SYSRST_UART2_APB>;
|
||||
resets = <&syscrg JH7110_SYSRST_UART2_APB>,
|
||||
<&syscrg JH7110_SYSRST_UART2_CORE>;
|
||||
interrupts = <34>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
@@ -642,12 +645,13 @@
|
||||
};
|
||||
|
||||
uart3: serial@12000000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
|
||||
reg = <0x0 0x12000000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_UART3_CORE>,
|
||||
<&syscrg JH7110_SYSCLK_UART3_APB>;
|
||||
clock-names = "baudclk", "apb_pclk";
|
||||
resets = <&syscrg JH7110_SYSRST_UART3_APB>;
|
||||
resets = <&syscrg JH7110_SYSRST_UART3_APB>,
|
||||
<&syscrg JH7110_SYSRST_UART3_CORE>;
|
||||
interrupts = <45>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
@@ -655,12 +659,13 @@
|
||||
};
|
||||
|
||||
uart4: serial@12010000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
|
||||
reg = <0x0 0x12010000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_UART4_CORE>,
|
||||
<&syscrg JH7110_SYSCLK_UART4_APB>;
|
||||
clock-names = "baudclk", "apb_pclk";
|
||||
resets = <&syscrg JH7110_SYSRST_UART4_APB>;
|
||||
resets = <&syscrg JH7110_SYSRST_UART4_APB>,
|
||||
<&syscrg JH7110_SYSRST_UART4_CORE>;
|
||||
interrupts = <46>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
@@ -668,12 +673,13 @@
|
||||
};
|
||||
|
||||
uart5: serial@12020000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
compatible = "starfive,jh7110-uart", "snps,dw-apb-uart";
|
||||
reg = <0x0 0x12020000 0x0 0x10000>;
|
||||
clocks = <&syscrg JH7110_SYSCLK_UART5_CORE>,
|
||||
<&syscrg JH7110_SYSCLK_UART5_APB>;
|
||||
clock-names = "baudclk", "apb_pclk";
|
||||
resets = <&syscrg JH7110_SYSRST_UART5_APB>;
|
||||
resets = <&syscrg JH7110_SYSRST_UART5_APB>,
|
||||
<&syscrg JH7110_SYSRST_UART5_CORE>;
|
||||
interrupts = <47>;
|
||||
reg-io-width = <4>;
|
||||
reg-shift = <2>;
|
||||
|
||||
@@ -1660,5 +1660,6 @@ console_initcall(amiserial_console_init);
|
||||
|
||||
#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
|
||||
|
||||
MODULE_DESCRIPTION("Serial driver for the amiga builtin port");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:amiga-serial");
|
||||
|
||||
@@ -470,4 +470,5 @@ static struct platform_driver goldfish_tty_platform_driver = {
|
||||
|
||||
module_platform_driver(goldfish_tty_platform_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Goldfish TTY Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -4634,5 +4634,6 @@ module_init(gsm_init);
|
||||
module_exit(gsm_exit);
|
||||
|
||||
|
||||
MODULE_DESCRIPTION("GSM 0710 tty multiplexor");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_LDISC(N_GSM0710);
|
||||
|
||||
@@ -822,6 +822,7 @@ static void __exit n_hdlc_exit(void)
|
||||
module_init(n_hdlc_init);
|
||||
module_exit(n_hdlc_exit);
|
||||
|
||||
MODULE_DESCRIPTION("HDLC line discipline support");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Paul Fulghum paulkf@microgate.com");
|
||||
module_param(maxframe, int, 0);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
#include "../serial_mctrl_gpio.h"
|
||||
@@ -93,6 +93,10 @@ struct serial8250_config {
|
||||
#define UART_BUG_THRE BIT(3) /* UART has buggy THRE reassertion */
|
||||
#define UART_BUG_TXRACE BIT(5) /* UART Tx fails to set remote DR */
|
||||
|
||||
/* Module parameters */
|
||||
#define UART_NR CONFIG_SERIAL_8250_NR_UARTS
|
||||
|
||||
extern unsigned int nr_uarts;
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
|
||||
#define SERIAL8250_SHARE_IRQS 1
|
||||
@@ -100,6 +104,9 @@ struct serial8250_config {
|
||||
#define SERIAL8250_SHARE_IRQS 0
|
||||
#endif
|
||||
|
||||
extern unsigned int share_irqs;
|
||||
extern unsigned int skip_txen_test;
|
||||
|
||||
#define SERIAL8250_PORT_FLAGS(_base, _irq, _flags) \
|
||||
{ \
|
||||
.iobase = _base, \
|
||||
@@ -111,6 +118,19 @@ struct serial8250_config {
|
||||
|
||||
#define SERIAL8250_PORT(_base, _irq) SERIAL8250_PORT_FLAGS(_base, _irq, 0)
|
||||
|
||||
extern struct uart_driver serial8250_reg;
|
||||
void serial8250_register_ports(struct uart_driver *drv, struct device *dev);
|
||||
|
||||
/* Legacy ISA bus related APIs */
|
||||
typedef void (*serial8250_isa_config_fn)(int, struct uart_port *, u32 *);
|
||||
extern serial8250_isa_config_fn serial8250_isa_config;
|
||||
|
||||
void serial8250_isa_init_ports(void);
|
||||
|
||||
extern struct platform_device *serial8250_isa_devs;
|
||||
|
||||
extern const struct uart_ops *univ8250_port_base_ops;
|
||||
extern struct uart_ops univ8250_port_ops;
|
||||
|
||||
static inline int serial_in(struct uart_8250_port *up, int offset)
|
||||
{
|
||||
@@ -200,6 +220,7 @@ static inline bool serial8250_clear_THRI(struct uart_8250_port *up)
|
||||
return true;
|
||||
}
|
||||
|
||||
struct uart_8250_port *serial8250_setup_port(int index);
|
||||
struct uart_8250_port *serial8250_get_port(int line);
|
||||
|
||||
void serial8250_rpm_get(struct uart_8250_port *p);
|
||||
@@ -301,6 +322,12 @@ static inline int serial8250_pnp_init(void) { return 0; }
|
||||
static inline void serial8250_pnp_exit(void) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_RSA
|
||||
void univ8250_rsa_support(struct uart_ops *ops);
|
||||
#else
|
||||
static inline void univ8250_rsa_support(struct uart_ops *ops) { }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_FINTEK
|
||||
int fintek_8250_probe(struct uart_8250_port *uart);
|
||||
#else
|
||||
|
||||
@@ -6,11 +6,9 @@
|
||||
*
|
||||
* Copyright (C) 2001 Russell King.
|
||||
*
|
||||
* Supports: ISA-compatible 8250/16550 ports
|
||||
* PNP 8250/16550 ports
|
||||
* Supports:
|
||||
* early_serial_setup() ports
|
||||
* userspace-configurable "phantom" ports
|
||||
* "serial8250" platform devices
|
||||
* serial8250_register_8250_port() ports
|
||||
*/
|
||||
|
||||
@@ -35,52 +33,13 @@
|
||||
#include <linux/string_helpers.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#ifdef CONFIG_SPARC
|
||||
#include <linux/sunserialcore.h>
|
||||
#endif
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
/*
|
||||
* Configuration:
|
||||
* share_irqs - whether we pass IRQF_SHARED to request_irq(). This option
|
||||
* is unsafe when used on edge-triggered interrupts.
|
||||
*/
|
||||
static unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
|
||||
|
||||
static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
|
||||
|
||||
static struct uart_driver serial8250_reg;
|
||||
|
||||
static unsigned int skip_txen_test; /* force skip of txen test at init time */
|
||||
|
||||
#define PASS_LIMIT 512
|
||||
|
||||
#include <asm/serial.h>
|
||||
/*
|
||||
* SERIAL_PORT_DFNS tells us about built-in ports that have no
|
||||
* standard enumeration mechanism. Platforms that can find all
|
||||
* serial ports via mechanisms like ACPI or PCI need not supply it.
|
||||
*/
|
||||
#ifndef SERIAL_PORT_DFNS
|
||||
#define SERIAL_PORT_DFNS
|
||||
#endif
|
||||
|
||||
static const struct old_serial_port old_serial_port[] = {
|
||||
SERIAL_PORT_DFNS /* defined in asm/serial.h */
|
||||
};
|
||||
|
||||
#define UART_NR CONFIG_SERIAL_8250_NR_UARTS
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_RSA
|
||||
|
||||
#define PORT_RSA_MAX 4
|
||||
static unsigned long probe_rsa[PORT_RSA_MAX];
|
||||
static unsigned int probe_rsa_count;
|
||||
#endif /* CONFIG_SERIAL_8250_RSA */
|
||||
|
||||
struct irq_info {
|
||||
struct hlist_node node;
|
||||
int irq;
|
||||
@@ -345,45 +304,8 @@ static void univ8250_release_irq(struct uart_8250_port *up)
|
||||
serial_unlink_irq_chain(up);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_RSA
|
||||
static int serial8250_request_rsa_resource(struct uart_8250_port *up)
|
||||
{
|
||||
unsigned long start = UART_RSA_BASE << up->port.regshift;
|
||||
unsigned int size = 8 << up->port.regshift;
|
||||
struct uart_port *port = &up->port;
|
||||
int ret = -EINVAL;
|
||||
|
||||
switch (port->iotype) {
|
||||
case UPIO_HUB6:
|
||||
case UPIO_PORT:
|
||||
start += port->iobase;
|
||||
if (request_region(start, size, "serial-rsa"))
|
||||
ret = 0;
|
||||
else
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void serial8250_release_rsa_resource(struct uart_8250_port *up)
|
||||
{
|
||||
unsigned long offset = UART_RSA_BASE << up->port.regshift;
|
||||
unsigned int size = 8 << up->port.regshift;
|
||||
struct uart_port *port = &up->port;
|
||||
|
||||
switch (port->iotype) {
|
||||
case UPIO_HUB6:
|
||||
case UPIO_PORT:
|
||||
release_region(port->iobase + offset, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct uart_ops *base_ops;
|
||||
static struct uart_ops univ8250_port_ops;
|
||||
const struct uart_ops *univ8250_port_base_ops = NULL;
|
||||
struct uart_ops univ8250_port_ops;
|
||||
|
||||
static const struct uart_8250_ops univ8250_driver_ops = {
|
||||
.setup_irq = univ8250_setup_irq,
|
||||
@@ -411,85 +333,12 @@ struct uart_8250_port *serial8250_get_port(int line)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(serial8250_get_port);
|
||||
|
||||
static void (*serial8250_isa_config)(int port, struct uart_port *up,
|
||||
u32 *capabilities);
|
||||
|
||||
void serial8250_set_isa_configurator(
|
||||
void (*v)(int port, struct uart_port *up, u32 *capabilities))
|
||||
{
|
||||
serial8250_isa_config = v;
|
||||
}
|
||||
EXPORT_SYMBOL(serial8250_set_isa_configurator);
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_RSA
|
||||
|
||||
static void univ8250_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
|
||||
up->probe &= ~UART_PROBE_RSA;
|
||||
if (port->type == PORT_RSA) {
|
||||
if (serial8250_request_rsa_resource(up) == 0)
|
||||
up->probe |= UART_PROBE_RSA;
|
||||
} else if (flags & UART_CONFIG_TYPE) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < probe_rsa_count; i++) {
|
||||
if (probe_rsa[i] == up->port.iobase) {
|
||||
if (serial8250_request_rsa_resource(up) == 0)
|
||||
up->probe |= UART_PROBE_RSA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base_ops->config_port(port, flags);
|
||||
|
||||
if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA)
|
||||
serial8250_release_rsa_resource(up);
|
||||
}
|
||||
|
||||
static int univ8250_request_port(struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
int ret;
|
||||
|
||||
ret = base_ops->request_port(port);
|
||||
if (ret == 0 && port->type == PORT_RSA) {
|
||||
ret = serial8250_request_rsa_resource(up);
|
||||
if (ret < 0)
|
||||
base_ops->release_port(port);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void univ8250_release_port(struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
|
||||
if (port->type == PORT_RSA)
|
||||
serial8250_release_rsa_resource(up);
|
||||
base_ops->release_port(port);
|
||||
}
|
||||
|
||||
static void univ8250_rsa_support(struct uart_ops *ops)
|
||||
{
|
||||
ops->config_port = univ8250_config_port;
|
||||
ops->request_port = univ8250_request_port;
|
||||
ops->release_port = univ8250_release_port;
|
||||
}
|
||||
|
||||
#else
|
||||
#define univ8250_rsa_support(x) do { } while (0)
|
||||
#endif /* CONFIG_SERIAL_8250_RSA */
|
||||
|
||||
static inline void serial8250_apply_quirks(struct uart_8250_port *up)
|
||||
{
|
||||
up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0;
|
||||
}
|
||||
|
||||
static struct uart_8250_port *serial8250_setup_port(int index)
|
||||
struct uart_8250_port *serial8250_setup_port(int index)
|
||||
{
|
||||
struct uart_8250_port *up;
|
||||
|
||||
@@ -501,8 +350,8 @@ static struct uart_8250_port *serial8250_setup_port(int index)
|
||||
up->port.port_id = index;
|
||||
|
||||
serial8250_init_port(up);
|
||||
if (!base_ops)
|
||||
base_ops = up->port.ops;
|
||||
if (!univ8250_port_base_ops)
|
||||
univ8250_port_base_ops = up->port.ops;
|
||||
up->port.ops = &univ8250_port_ops;
|
||||
|
||||
timer_setup(&up->timer, serial8250_timeout, 0);
|
||||
@@ -514,57 +363,7 @@ static struct uart_8250_port *serial8250_setup_port(int index)
|
||||
return up;
|
||||
}
|
||||
|
||||
static void __init serial8250_isa_init_ports(void)
|
||||
{
|
||||
struct uart_8250_port *up;
|
||||
static int first = 1;
|
||||
int i, irqflag = 0;
|
||||
|
||||
if (!first)
|
||||
return;
|
||||
first = 0;
|
||||
|
||||
if (nr_uarts > UART_NR)
|
||||
nr_uarts = UART_NR;
|
||||
|
||||
/*
|
||||
* Set up initial isa ports based on nr_uart module param, or else
|
||||
* default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not
|
||||
* need to increase nr_uarts when setting up the initial isa ports.
|
||||
*/
|
||||
for (i = 0; i < nr_uarts; i++)
|
||||
serial8250_setup_port(i);
|
||||
|
||||
/* chain base port ops to support Remote Supervisor Adapter */
|
||||
univ8250_port_ops = *base_ops;
|
||||
univ8250_rsa_support(&univ8250_port_ops);
|
||||
|
||||
if (share_irqs)
|
||||
irqflag = IRQF_SHARED;
|
||||
|
||||
for (i = 0, up = serial8250_ports;
|
||||
i < ARRAY_SIZE(old_serial_port) && i < nr_uarts;
|
||||
i++, up++) {
|
||||
struct uart_port *port = &up->port;
|
||||
|
||||
port->iobase = old_serial_port[i].port;
|
||||
port->irq = irq_canonicalize(old_serial_port[i].irq);
|
||||
port->irqflags = 0;
|
||||
port->uartclk = old_serial_port[i].baud_base * 16;
|
||||
port->flags = old_serial_port[i].flags;
|
||||
port->hub6 = 0;
|
||||
port->membase = old_serial_port[i].iomem_base;
|
||||
port->iotype = old_serial_port[i].io_type;
|
||||
port->regshift = old_serial_port[i].iomem_reg_shift;
|
||||
|
||||
port->irqflags |= irqflag;
|
||||
if (serial8250_isa_config != NULL)
|
||||
serial8250_isa_config(i, &up->port, &up->capabilities);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init
|
||||
serial8250_register_ports(struct uart_driver *drv, struct device *dev)
|
||||
void __init serial8250_register_ports(struct uart_driver *drv, struct device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -721,7 +520,7 @@ console_initcall(univ8250_console_init);
|
||||
#define SERIAL8250_CONSOLE NULL
|
||||
#endif
|
||||
|
||||
static struct uart_driver serial8250_reg = {
|
||||
struct uart_driver serial8250_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "serial",
|
||||
.dev_name = "ttyS",
|
||||
@@ -822,120 +621,6 @@ void serial8250_resume_port(int line)
|
||||
}
|
||||
EXPORT_SYMBOL(serial8250_resume_port);
|
||||
|
||||
/*
|
||||
* Register a set of serial devices attached to a platform device. The
|
||||
* list is terminated with a zero flags entry, which means we expect
|
||||
* all entries to have at least UPF_BOOT_AUTOCONF set.
|
||||
*/
|
||||
static int serial8250_probe(struct platform_device *dev)
|
||||
{
|
||||
struct plat_serial8250_port *p = dev_get_platdata(&dev->dev);
|
||||
struct uart_8250_port uart;
|
||||
int ret, i, irqflag = 0;
|
||||
|
||||
memset(&uart, 0, sizeof(uart));
|
||||
|
||||
if (share_irqs)
|
||||
irqflag = IRQF_SHARED;
|
||||
|
||||
for (i = 0; p && p->flags != 0; p++, i++) {
|
||||
uart.port.iobase = p->iobase;
|
||||
uart.port.membase = p->membase;
|
||||
uart.port.irq = p->irq;
|
||||
uart.port.irqflags = p->irqflags;
|
||||
uart.port.uartclk = p->uartclk;
|
||||
uart.port.regshift = p->regshift;
|
||||
uart.port.iotype = p->iotype;
|
||||
uart.port.flags = p->flags;
|
||||
uart.port.mapbase = p->mapbase;
|
||||
uart.port.mapsize = p->mapsize;
|
||||
uart.port.hub6 = p->hub6;
|
||||
uart.port.has_sysrq = p->has_sysrq;
|
||||
uart.port.private_data = p->private_data;
|
||||
uart.port.type = p->type;
|
||||
uart.bugs = p->bugs;
|
||||
uart.port.serial_in = p->serial_in;
|
||||
uart.port.serial_out = p->serial_out;
|
||||
uart.dl_read = p->dl_read;
|
||||
uart.dl_write = p->dl_write;
|
||||
uart.port.handle_irq = p->handle_irq;
|
||||
uart.port.handle_break = p->handle_break;
|
||||
uart.port.set_termios = p->set_termios;
|
||||
uart.port.set_ldisc = p->set_ldisc;
|
||||
uart.port.get_mctrl = p->get_mctrl;
|
||||
uart.port.pm = p->pm;
|
||||
uart.port.dev = &dev->dev;
|
||||
uart.port.irqflags |= irqflag;
|
||||
ret = serial8250_register_8250_port(&uart);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "unable to register port at index %d "
|
||||
"(IO%lx MEM%llx IRQ%d): %d\n", i,
|
||||
p->iobase, (unsigned long long)p->mapbase,
|
||||
p->irq, ret);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove serial ports registered against a platform device.
|
||||
*/
|
||||
static void serial8250_remove(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_uarts; i++) {
|
||||
struct uart_8250_port *up = &serial8250_ports[i];
|
||||
|
||||
if (up->port.dev == &dev->dev)
|
||||
serial8250_unregister_port(i);
|
||||
}
|
||||
}
|
||||
|
||||
static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++) {
|
||||
struct uart_8250_port *up = &serial8250_ports[i];
|
||||
|
||||
if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
|
||||
uart_suspend_port(&serial8250_reg, &up->port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial8250_resume(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++) {
|
||||
struct uart_8250_port *up = &serial8250_ports[i];
|
||||
|
||||
if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
|
||||
serial8250_resume_port(i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver serial8250_isa_driver = {
|
||||
.probe = serial8250_probe,
|
||||
.remove_new = serial8250_remove,
|
||||
.suspend = serial8250_suspend,
|
||||
.resume = serial8250_resume,
|
||||
.driver = {
|
||||
.name = "serial8250",
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* This "device" covers _all_ ISA 8250-compatible serial devices listed
|
||||
* in the table in include/asm/serial.h
|
||||
*/
|
||||
static struct platform_device *serial8250_isa_devs;
|
||||
|
||||
/*
|
||||
* serial8250_register_8250_port and serial8250_unregister_port allows for
|
||||
* 16x50 serial ports to be configured at run-time, to support PCMCIA
|
||||
@@ -1212,134 +897,5 @@ void serial8250_unregister_port(int line)
|
||||
}
|
||||
EXPORT_SYMBOL(serial8250_unregister_port);
|
||||
|
||||
static int __init serial8250_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (nr_uarts == 0)
|
||||
return -ENODEV;
|
||||
|
||||
serial8250_isa_init_ports();
|
||||
|
||||
pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %s\n",
|
||||
nr_uarts, str_enabled_disabled(share_irqs));
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
ret = sunserial_register_minors(&serial8250_reg, UART_NR);
|
||||
#else
|
||||
serial8250_reg.nr = UART_NR;
|
||||
ret = uart_register_driver(&serial8250_reg);
|
||||
#endif
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = serial8250_pnp_init();
|
||||
if (ret)
|
||||
goto unreg_uart_drv;
|
||||
|
||||
serial8250_isa_devs = platform_device_alloc("serial8250",
|
||||
PLAT8250_DEV_LEGACY);
|
||||
if (!serial8250_isa_devs) {
|
||||
ret = -ENOMEM;
|
||||
goto unreg_pnp;
|
||||
}
|
||||
|
||||
ret = platform_device_add(serial8250_isa_devs);
|
||||
if (ret)
|
||||
goto put_dev;
|
||||
|
||||
serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
|
||||
|
||||
ret = platform_driver_register(&serial8250_isa_driver);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
platform_device_del(serial8250_isa_devs);
|
||||
put_dev:
|
||||
platform_device_put(serial8250_isa_devs);
|
||||
unreg_pnp:
|
||||
serial8250_pnp_exit();
|
||||
unreg_uart_drv:
|
||||
#ifdef CONFIG_SPARC
|
||||
sunserial_unregister_minors(&serial8250_reg, UART_NR);
|
||||
#else
|
||||
uart_unregister_driver(&serial8250_reg);
|
||||
#endif
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit serial8250_exit(void)
|
||||
{
|
||||
struct platform_device *isa_dev = serial8250_isa_devs;
|
||||
|
||||
/*
|
||||
* This tells serial8250_unregister_port() not to re-register
|
||||
* the ports (thereby making serial8250_isa_driver permanently
|
||||
* in use.)
|
||||
*/
|
||||
serial8250_isa_devs = NULL;
|
||||
|
||||
platform_driver_unregister(&serial8250_isa_driver);
|
||||
platform_device_unregister(isa_dev);
|
||||
|
||||
serial8250_pnp_exit();
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
sunserial_unregister_minors(&serial8250_reg, UART_NR);
|
||||
#else
|
||||
uart_unregister_driver(&serial8250_reg);
|
||||
#endif
|
||||
}
|
||||
|
||||
module_init(serial8250_init);
|
||||
module_exit(serial8250_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
|
||||
|
||||
module_param_hw(share_irqs, uint, other, 0644);
|
||||
MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)");
|
||||
|
||||
module_param(nr_uarts, uint, 0644);
|
||||
MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
|
||||
|
||||
module_param(skip_txen_test, uint, 0644);
|
||||
MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_RSA
|
||||
module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444);
|
||||
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
|
||||
#endif
|
||||
MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
|
||||
#ifndef MODULE
|
||||
/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name
|
||||
* working as well for the module options so we don't break people. We
|
||||
* need to keep the names identical and the convenient macros will happily
|
||||
* refuse to let us do that by failing the build with redefinition errors
|
||||
* of global variables. So we stick them inside a dummy function to avoid
|
||||
* those conflicts. The options still get parsed, and the redefined
|
||||
* MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
|
||||
*
|
||||
* This is hacky. I'm sorry.
|
||||
*/
|
||||
static void __used s8250_options(void)
|
||||
{
|
||||
#undef MODULE_PARAM_PREFIX
|
||||
#define MODULE_PARAM_PREFIX "8250_core."
|
||||
|
||||
module_param_cb(share_irqs, ¶m_ops_uint, &share_irqs, 0644);
|
||||
module_param_cb(nr_uarts, ¶m_ops_uint, &nr_uarts, 0644);
|
||||
module_param_cb(skip_txen_test, ¶m_ops_uint, &skip_txen_test, 0644);
|
||||
#ifdef CONFIG_SERIAL_8250_RSA
|
||||
__module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
|
||||
¶m_array_ops, .arr = &__param_arr_probe_rsa,
|
||||
0444, -1, 0);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
MODULE_ALIAS("8250_core");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -616,7 +616,7 @@ static int dw8250_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(data->pclk))
|
||||
return PTR_ERR(data->pclk);
|
||||
|
||||
data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
|
||||
data->rst = devm_reset_control_array_get_optional_exclusive(dev);
|
||||
if (IS_ERR(data->rst))
|
||||
return PTR_ERR(data->rst);
|
||||
|
||||
|
||||
@@ -127,4 +127,5 @@ static int __init probe_serial_gsc(void)
|
||||
|
||||
module_init(probe_serial_gsc);
|
||||
|
||||
MODULE_DESCRIPTION("Serial Device Initialisation for Lasi/Asp/Wax/Dino");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -37,4 +37,5 @@ int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(serial8250_pci_setup_port, SERIAL_8250_PCI);
|
||||
MODULE_DESCRIPTION("8250 PCI library");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
337
drivers/tty/serial/8250/8250_platform.c
Normal file
337
drivers/tty/serial/8250/8250_platform.c
Normal file
@@ -0,0 +1,337 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Universal/legacy platform driver for 8250/16550-type serial ports
|
||||
*
|
||||
* Supports: ISA-compatible 8250/16550 ports
|
||||
* PNP 8250/16550 ports
|
||||
* "serial8250" platform devices
|
||||
*/
|
||||
#include <linux/array_size.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/once.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
#include <linux/sunserialcore.h>
|
||||
#endif
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
/*
|
||||
* Configuration:
|
||||
* share_irqs Whether we pass IRQF_SHARED to request_irq().
|
||||
* This option is unsafe when used on edge-triggered interrupts.
|
||||
* skip_txen_test Force skip of txen test at init time.
|
||||
*/
|
||||
unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
|
||||
unsigned int skip_txen_test;
|
||||
|
||||
unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS;
|
||||
|
||||
#include <asm/serial.h>
|
||||
|
||||
/*
|
||||
* SERIAL_PORT_DFNS tells us about built-in ports that have no
|
||||
* standard enumeration mechanism. Platforms that can find all
|
||||
* serial ports via mechanisms like ACPI or PCI need not supply it.
|
||||
*/
|
||||
#ifndef SERIAL_PORT_DFNS
|
||||
#define SERIAL_PORT_DFNS
|
||||
#endif
|
||||
|
||||
static const struct old_serial_port old_serial_port[] = {
|
||||
SERIAL_PORT_DFNS /* defined in asm/serial.h */
|
||||
};
|
||||
|
||||
serial8250_isa_config_fn serial8250_isa_config;
|
||||
void serial8250_set_isa_configurator(serial8250_isa_config_fn v)
|
||||
{
|
||||
serial8250_isa_config = v;
|
||||
}
|
||||
EXPORT_SYMBOL(serial8250_set_isa_configurator);
|
||||
|
||||
static void __init __serial8250_isa_init_ports(void)
|
||||
{
|
||||
int i, irqflag = 0;
|
||||
|
||||
if (nr_uarts > UART_NR)
|
||||
nr_uarts = UART_NR;
|
||||
|
||||
/*
|
||||
* Set up initial isa ports based on nr_uart module param, or else
|
||||
* default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not
|
||||
* need to increase nr_uarts when setting up the initial isa ports.
|
||||
*/
|
||||
for (i = 0; i < nr_uarts; i++)
|
||||
serial8250_setup_port(i);
|
||||
|
||||
/* chain base port ops to support Remote Supervisor Adapter */
|
||||
univ8250_port_ops = *univ8250_port_base_ops;
|
||||
univ8250_rsa_support(&univ8250_port_ops);
|
||||
|
||||
if (share_irqs)
|
||||
irqflag = IRQF_SHARED;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++) {
|
||||
struct uart_8250_port *up = serial8250_get_port(i);
|
||||
struct uart_port *port = &up->port;
|
||||
|
||||
port->iobase = old_serial_port[i].port;
|
||||
port->irq = irq_canonicalize(old_serial_port[i].irq);
|
||||
port->irqflags = 0;
|
||||
port->uartclk = old_serial_port[i].baud_base * 16;
|
||||
port->flags = old_serial_port[i].flags;
|
||||
port->hub6 = 0;
|
||||
port->membase = old_serial_port[i].iomem_base;
|
||||
port->iotype = old_serial_port[i].io_type;
|
||||
port->regshift = old_serial_port[i].iomem_reg_shift;
|
||||
|
||||
port->irqflags |= irqflag;
|
||||
if (serial8250_isa_config != NULL)
|
||||
serial8250_isa_config(i, &up->port, &up->capabilities);
|
||||
}
|
||||
}
|
||||
|
||||
void __init serial8250_isa_init_ports(void)
|
||||
{
|
||||
DO_ONCE(__serial8250_isa_init_ports);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a set of serial devices attached to a platform device. The
|
||||
* list is terminated with a zero flags entry, which means we expect
|
||||
* all entries to have at least UPF_BOOT_AUTOCONF set.
|
||||
*/
|
||||
static int serial8250_probe(struct platform_device *dev)
|
||||
{
|
||||
struct plat_serial8250_port *p = dev_get_platdata(&dev->dev);
|
||||
struct uart_8250_port uart;
|
||||
int ret, i, irqflag = 0;
|
||||
|
||||
memset(&uart, 0, sizeof(uart));
|
||||
|
||||
if (share_irqs)
|
||||
irqflag = IRQF_SHARED;
|
||||
|
||||
for (i = 0; p && p->flags != 0; p++, i++) {
|
||||
uart.port.iobase = p->iobase;
|
||||
uart.port.membase = p->membase;
|
||||
uart.port.irq = p->irq;
|
||||
uart.port.irqflags = p->irqflags;
|
||||
uart.port.uartclk = p->uartclk;
|
||||
uart.port.regshift = p->regshift;
|
||||
uart.port.iotype = p->iotype;
|
||||
uart.port.flags = p->flags;
|
||||
uart.port.mapbase = p->mapbase;
|
||||
uart.port.mapsize = p->mapsize;
|
||||
uart.port.hub6 = p->hub6;
|
||||
uart.port.has_sysrq = p->has_sysrq;
|
||||
uart.port.private_data = p->private_data;
|
||||
uart.port.type = p->type;
|
||||
uart.bugs = p->bugs;
|
||||
uart.port.serial_in = p->serial_in;
|
||||
uart.port.serial_out = p->serial_out;
|
||||
uart.dl_read = p->dl_read;
|
||||
uart.dl_write = p->dl_write;
|
||||
uart.port.handle_irq = p->handle_irq;
|
||||
uart.port.handle_break = p->handle_break;
|
||||
uart.port.set_termios = p->set_termios;
|
||||
uart.port.set_ldisc = p->set_ldisc;
|
||||
uart.port.get_mctrl = p->get_mctrl;
|
||||
uart.port.pm = p->pm;
|
||||
uart.port.dev = &dev->dev;
|
||||
uart.port.irqflags |= irqflag;
|
||||
ret = serial8250_register_8250_port(&uart);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "unable to register port at index %d "
|
||||
"(IO%lx MEM%llx IRQ%d): %d\n", i,
|
||||
p->iobase, (unsigned long long)p->mapbase,
|
||||
p->irq, ret);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove serial ports registered against a platform device.
|
||||
*/
|
||||
static void serial8250_remove(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr_uarts; i++) {
|
||||
struct uart_8250_port *up = serial8250_get_port(i);
|
||||
|
||||
if (up->port.dev == &dev->dev)
|
||||
serial8250_unregister_port(i);
|
||||
}
|
||||
}
|
||||
|
||||
static int serial8250_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++) {
|
||||
struct uart_8250_port *up = serial8250_get_port(i);
|
||||
|
||||
if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
|
||||
uart_suspend_port(&serial8250_reg, &up->port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serial8250_resume(struct platform_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < UART_NR; i++) {
|
||||
struct uart_8250_port *up = serial8250_get_port(i);
|
||||
|
||||
if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
|
||||
serial8250_resume_port(i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver serial8250_isa_driver = {
|
||||
.probe = serial8250_probe,
|
||||
.remove_new = serial8250_remove,
|
||||
.suspend = serial8250_suspend,
|
||||
.resume = serial8250_resume,
|
||||
.driver = {
|
||||
.name = "serial8250",
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* This "device" covers _all_ ISA 8250-compatible serial devices listed
|
||||
* in the table in include/asm/serial.h
|
||||
*/
|
||||
struct platform_device *serial8250_isa_devs;
|
||||
|
||||
static int __init serial8250_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (nr_uarts == 0)
|
||||
return -ENODEV;
|
||||
|
||||
serial8250_isa_init_ports();
|
||||
|
||||
pr_info("Serial: 8250/16550 driver, %d ports, IRQ sharing %s\n",
|
||||
nr_uarts, str_enabled_disabled(share_irqs));
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
ret = sunserial_register_minors(&serial8250_reg, UART_NR);
|
||||
#else
|
||||
serial8250_reg.nr = UART_NR;
|
||||
ret = uart_register_driver(&serial8250_reg);
|
||||
#endif
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = serial8250_pnp_init();
|
||||
if (ret)
|
||||
goto unreg_uart_drv;
|
||||
|
||||
serial8250_isa_devs = platform_device_alloc("serial8250",
|
||||
PLAT8250_DEV_LEGACY);
|
||||
if (!serial8250_isa_devs) {
|
||||
ret = -ENOMEM;
|
||||
goto unreg_pnp;
|
||||
}
|
||||
|
||||
ret = platform_device_add(serial8250_isa_devs);
|
||||
if (ret)
|
||||
goto put_dev;
|
||||
|
||||
serial8250_register_ports(&serial8250_reg, &serial8250_isa_devs->dev);
|
||||
|
||||
ret = platform_driver_register(&serial8250_isa_driver);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
platform_device_del(serial8250_isa_devs);
|
||||
put_dev:
|
||||
platform_device_put(serial8250_isa_devs);
|
||||
unreg_pnp:
|
||||
serial8250_pnp_exit();
|
||||
unreg_uart_drv:
|
||||
#ifdef CONFIG_SPARC
|
||||
sunserial_unregister_minors(&serial8250_reg, UART_NR);
|
||||
#else
|
||||
uart_unregister_driver(&serial8250_reg);
|
||||
#endif
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
module_init(serial8250_init);
|
||||
|
||||
static void __exit serial8250_exit(void)
|
||||
{
|
||||
struct platform_device *isa_dev = serial8250_isa_devs;
|
||||
|
||||
/*
|
||||
* This tells serial8250_unregister_port() not to re-register
|
||||
* the ports (thereby making serial8250_isa_driver permanently
|
||||
* in use.)
|
||||
*/
|
||||
serial8250_isa_devs = NULL;
|
||||
|
||||
platform_driver_unregister(&serial8250_isa_driver);
|
||||
platform_device_unregister(isa_dev);
|
||||
|
||||
serial8250_pnp_exit();
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
sunserial_unregister_minors(&serial8250_reg, UART_NR);
|
||||
#else
|
||||
uart_unregister_driver(&serial8250_reg);
|
||||
#endif
|
||||
}
|
||||
module_exit(serial8250_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Generic 8250/16x50 serial platform driver");
|
||||
|
||||
module_param_hw(share_irqs, uint, other, 0644);
|
||||
MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)");
|
||||
|
||||
module_param(nr_uarts, uint, 0644);
|
||||
MODULE_PARM_DESC(nr_uarts, "Maximum number of UARTs supported. (1-" __MODULE_STRING(CONFIG_SERIAL_8250_NR_UARTS) ")");
|
||||
|
||||
module_param(skip_txen_test, uint, 0644);
|
||||
MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
|
||||
|
||||
MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
|
||||
#ifndef MODULE
|
||||
/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name
|
||||
* working as well for the module options so we don't break people. We
|
||||
* need to keep the names identical and the convenient macros will happily
|
||||
* refuse to let us do that by failing the build with redefinition errors
|
||||
* of global variables. So we stick them inside a dummy function to avoid
|
||||
* those conflicts. The options still get parsed, and the redefined
|
||||
* MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
|
||||
*
|
||||
* This is hacky. I'm sorry.
|
||||
*/
|
||||
static void __used s8250_options(void)
|
||||
{
|
||||
#undef MODULE_PARAM_PREFIX
|
||||
#define MODULE_PARAM_PREFIX "8250_core."
|
||||
|
||||
module_param_cb(share_irqs, ¶m_ops_uint, &share_irqs, 0644);
|
||||
module_param_cb(nr_uarts, ¶m_ops_uint, &nr_uarts, 0644);
|
||||
module_param_cb(skip_txen_test, ¶m_ops_uint, &skip_txen_test, 0644);
|
||||
}
|
||||
#else
|
||||
MODULE_ALIAS("8250_core");
|
||||
#endif
|
||||
#endif
|
||||
@@ -3473,4 +3473,5 @@ int serial8250_console_exit(struct uart_port *port)
|
||||
|
||||
#endif /* CONFIG_SERIAL_8250_CONSOLE */
|
||||
|
||||
MODULE_DESCRIPTION("Base port operations for 8250/16550-type serial ports");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -182,5 +182,6 @@ OF_EARLYCON_DECLARE(mmp, "mrvl,mmp-uart", early_serial_pxa_setup);
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Sergei Ianovich");
|
||||
MODULE_DESCRIPTION("driver for PXA on-board UARTS");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:pxa2xx-uart");
|
||||
|
||||
133
drivers/tty/serial/8250/8250_rsa.c
Normal file
133
drivers/tty/serial/8250/8250_rsa.c
Normal file
@@ -0,0 +1,133 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_8250.h>
|
||||
|
||||
#include "8250.h"
|
||||
|
||||
#define PORT_RSA_MAX 4
|
||||
static unsigned long probe_rsa[PORT_RSA_MAX];
|
||||
static unsigned int probe_rsa_count;
|
||||
|
||||
static int rsa8250_request_resource(struct uart_8250_port *up)
|
||||
{
|
||||
unsigned long start = UART_RSA_BASE << up->port.regshift;
|
||||
unsigned int size = 8 << up->port.regshift;
|
||||
struct uart_port *port = &up->port;
|
||||
int ret = -EINVAL;
|
||||
|
||||
switch (port->iotype) {
|
||||
case UPIO_HUB6:
|
||||
case UPIO_PORT:
|
||||
start += port->iobase;
|
||||
if (request_region(start, size, "serial-rsa"))
|
||||
ret = 0;
|
||||
else
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rsa8250_release_resource(struct uart_8250_port *up)
|
||||
{
|
||||
unsigned long offset = UART_RSA_BASE << up->port.regshift;
|
||||
unsigned int size = 8 << up->port.regshift;
|
||||
struct uart_port *port = &up->port;
|
||||
|
||||
switch (port->iotype) {
|
||||
case UPIO_HUB6:
|
||||
case UPIO_PORT:
|
||||
release_region(port->iobase + offset, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void univ8250_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
unsigned int i;
|
||||
|
||||
up->probe &= ~UART_PROBE_RSA;
|
||||
if (port->type == PORT_RSA) {
|
||||
if (rsa8250_request_resource(up) == 0)
|
||||
up->probe |= UART_PROBE_RSA;
|
||||
} else if (flags & UART_CONFIG_TYPE) {
|
||||
for (i = 0; i < probe_rsa_count; i++) {
|
||||
if (probe_rsa[i] == up->port.iobase) {
|
||||
if (rsa8250_request_resource(up) == 0)
|
||||
up->probe |= UART_PROBE_RSA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
univ8250_port_base_ops->config_port(port, flags);
|
||||
|
||||
if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA)
|
||||
rsa8250_release_resource(up);
|
||||
}
|
||||
|
||||
static int univ8250_request_port(struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
int ret;
|
||||
|
||||
ret = univ8250_port_base_ops->request_port(port);
|
||||
if (ret == 0 && port->type == PORT_RSA) {
|
||||
ret = rsa8250_request_resource(up);
|
||||
if (ret < 0)
|
||||
univ8250_port_base_ops->release_port(port);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void univ8250_release_port(struct uart_port *port)
|
||||
{
|
||||
struct uart_8250_port *up = up_to_u8250p(port);
|
||||
|
||||
if (port->type == PORT_RSA)
|
||||
rsa8250_release_resource(up);
|
||||
univ8250_port_base_ops->release_port(port);
|
||||
}
|
||||
|
||||
void univ8250_rsa_support(struct uart_ops *ops)
|
||||
{
|
||||
ops->config_port = univ8250_config_port;
|
||||
ops->request_port = univ8250_request_port;
|
||||
ops->release_port = univ8250_release_port;
|
||||
}
|
||||
|
||||
module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444);
|
||||
MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
|
||||
#ifndef MODULE
|
||||
/*
|
||||
* Keep the old "8250" name working as well for the module options so we don't
|
||||
* break people. We need to keep the names identical and the convenient macros
|
||||
* will happily refuse to let us do that by failing the build with redefinition
|
||||
* errors of global variables. So we stick them inside a dummy function to
|
||||
* avoid those conflicts. The options still get parsed, and the redefined
|
||||
* MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
|
||||
*
|
||||
* This is hacky. I'm sorry.
|
||||
*/
|
||||
static void __used rsa8250_options(void)
|
||||
{
|
||||
#undef MODULE_PARAM_PREFIX
|
||||
#define MODULE_PARAM_PREFIX "8250_core."
|
||||
|
||||
__module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
|
||||
¶m_array_ops, .arr = &__param_arr_probe_rsa,
|
||||
0444, -1, 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -3,9 +3,13 @@
|
||||
# Makefile for the 8250 serial device drivers.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o
|
||||
obj-$(CONFIG_SERIAL_8250) += 8250.o
|
||||
8250-y := 8250_core.o
|
||||
8250-y += 8250_platform.o
|
||||
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
|
||||
8250-$(CONFIG_SERIAL_8250_RSA) += 8250_rsa.o
|
||||
|
||||
obj-$(CONFIG_SERIAL_8250) += 8250_base.o
|
||||
8250_base-y := 8250_port.o
|
||||
8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
|
||||
8250_base-$(CONFIG_SERIAL_8250_DWLIB) += 8250_dwlib.o
|
||||
|
||||
@@ -864,4 +864,5 @@ static struct pcmcia_driver serial_cs_driver = {
|
||||
};
|
||||
module_pcmcia_driver(serial_cs_driver);
|
||||
|
||||
MODULE_DESCRIPTION("driver for PCMCIA serial devices");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -455,4 +455,5 @@ module_init(esp32s3_acm_init);
|
||||
module_exit(esp32s3_acm_exit);
|
||||
|
||||
MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
|
||||
MODULE_DESCRIPTION("Espressif ESP32 USB ACM gadget support");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -775,4 +775,5 @@ module_init(esp32_uart_init);
|
||||
module_exit(esp32_uart_exit);
|
||||
|
||||
MODULE_AUTHOR("Max Filippov <jcmvbkbc@gmail.com>");
|
||||
MODULE_DESCRIPTION("Espressif ESP32 UART support");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -265,6 +265,11 @@ static const struct of_device_id imx_uart_dt_ids[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx_uart_dt_ids);
|
||||
|
||||
static inline struct imx_port *to_imx_port(struct uart_port *port)
|
||||
{
|
||||
return container_of(port, struct imx_port, port);
|
||||
}
|
||||
|
||||
static inline void imx_uart_writel(struct imx_port *sport, u32 val, u32 offset)
|
||||
{
|
||||
writel(val, sport->port.membase + offset);
|
||||
@@ -378,7 +383,7 @@ static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
|
||||
/* called with port.lock taken and irqs off */
|
||||
static void imx_uart_start_rx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned int ucr1, ucr2;
|
||||
|
||||
ucr1 = imx_uart_readl(sport, UCR1);
|
||||
@@ -402,7 +407,7 @@ static void imx_uart_start_rx(struct uart_port *port)
|
||||
/* called with port.lock taken and irqs off */
|
||||
static void imx_uart_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
u32 ucr1, ucr4, usr2;
|
||||
|
||||
if (sport->tx_state == OFF)
|
||||
@@ -467,7 +472,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
|
||||
|
||||
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
u32 ucr1, ucr2, ucr4, uts;
|
||||
|
||||
ucr1 = imx_uart_readl(sport, UCR1);
|
||||
@@ -512,7 +517,7 @@ static void imx_uart_stop_rx(struct uart_port *port)
|
||||
/* called with port.lock taken and irqs off */
|
||||
static void imx_uart_enable_ms(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
|
||||
mod_timer(&sport->timer, jiffies);
|
||||
|
||||
@@ -663,7 +668,7 @@ static void imx_uart_dma_tx(struct imx_port *sport)
|
||||
/* called with port.lock taken and irqs off */
|
||||
static void imx_uart_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
struct tty_port *tport = &sport->port.state->port;
|
||||
u32 ucr1;
|
||||
|
||||
@@ -1044,7 +1049,7 @@ static irqreturn_t imx_uart_int(int irq, void *dev_id)
|
||||
*/
|
||||
static unsigned int imx_uart_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned int ret;
|
||||
|
||||
ret = (imx_uart_readl(sport, USR2) & USR2_TXDC) ? TIOCSER_TEMT : 0;
|
||||
@@ -1059,7 +1064,7 @@ static unsigned int imx_uart_tx_empty(struct uart_port *port)
|
||||
/* called with port.lock taken and irqs off */
|
||||
static unsigned int imx_uart_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned int ret = imx_uart_get_hwmctrl(sport);
|
||||
|
||||
mctrl_gpio_get(sport->gpios, &ret);
|
||||
@@ -1070,7 +1075,7 @@ static unsigned int imx_uart_get_mctrl(struct uart_port *port)
|
||||
/* called with port.lock taken and irqs off */
|
||||
static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
u32 ucr3, uts;
|
||||
|
||||
if (!(port->rs485.flags & SER_RS485_ENABLED)) {
|
||||
@@ -1113,7 +1118,7 @@ static void imx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
*/
|
||||
static void imx_uart_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned long flags;
|
||||
u32 ucr1;
|
||||
|
||||
@@ -1435,7 +1440,7 @@ static void imx_uart_disable_dma(struct imx_port *sport)
|
||||
|
||||
static int imx_uart_startup(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
int retval;
|
||||
unsigned long flags;
|
||||
int dma_is_inited = 0;
|
||||
@@ -1549,7 +1554,7 @@ static int imx_uart_startup(struct uart_port *port)
|
||||
|
||||
static void imx_uart_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned long flags;
|
||||
u32 ucr1, ucr2, ucr4, uts;
|
||||
int loops;
|
||||
@@ -1674,7 +1679,7 @@ static void imx_uart_shutdown(struct uart_port *port)
|
||||
/* called with port.lock taken and irqs off */
|
||||
static void imx_uart_flush_buffer(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
struct scatterlist *sgl = &sport->tx_sgl[0];
|
||||
|
||||
if (!sport->dma_chan_tx)
|
||||
@@ -1701,7 +1706,7 @@ static void
|
||||
imx_uart_set_termios(struct uart_port *port, struct ktermios *termios,
|
||||
const struct ktermios *old)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned long flags;
|
||||
u32 ucr2, old_ucr2, ufcr;
|
||||
unsigned int baud, quot;
|
||||
@@ -1904,7 +1909,7 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||
|
||||
static int imx_uart_poll_init(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned long flags;
|
||||
u32 ucr1, ucr2;
|
||||
int retval;
|
||||
@@ -1953,7 +1958,7 @@ static int imx_uart_poll_init(struct uart_port *port)
|
||||
|
||||
static int imx_uart_poll_get_char(struct uart_port *port)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
if (!(imx_uart_readl(sport, USR2) & USR2_RDR))
|
||||
return NO_POLL_CHAR;
|
||||
|
||||
@@ -1962,7 +1967,7 @@ static int imx_uart_poll_get_char(struct uart_port *port)
|
||||
|
||||
static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
unsigned int status;
|
||||
|
||||
/* drain */
|
||||
@@ -1984,7 +1989,7 @@ static void imx_uart_poll_put_char(struct uart_port *port, unsigned char c)
|
||||
static int imx_uart_rs485_config(struct uart_port *port, struct ktermios *termios,
|
||||
struct serial_rs485 *rs485conf)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
u32 ucr2, ufcr;
|
||||
|
||||
if (rs485conf->flags & SER_RS485_ENABLED) {
|
||||
@@ -2043,7 +2048,7 @@ static struct imx_port *imx_uart_ports[UART_NR];
|
||||
#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
|
||||
static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
|
||||
{
|
||||
struct imx_port *sport = (struct imx_port *)port;
|
||||
struct imx_port *sport = to_imx_port(port);
|
||||
|
||||
while (imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)
|
||||
barrier();
|
||||
|
||||
@@ -761,4 +761,5 @@ static void __exit owl_uart_exit(void)
|
||||
module_init(owl_uart_init);
|
||||
module_exit(owl_uart_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Actions Semi Owl family serial console");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/kthread.h>
|
||||
@@ -1467,6 +1468,29 @@ static const struct serial_rs485 sc16is7xx_rs485_supported = {
|
||||
.delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */
|
||||
};
|
||||
|
||||
/* Reset device, purging any pending irq / data */
|
||||
static int sc16is7xx_reset(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
struct gpio_desc *reset_gpio;
|
||||
|
||||
/* Assert reset GPIO if defined and valid. */
|
||||
reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(reset_gpio), "Failed to get reset GPIO\n");
|
||||
|
||||
if (reset_gpio) {
|
||||
/* The minimum reset pulse width is 3 us. */
|
||||
fsleep(5);
|
||||
gpiod_set_value_cansleep(reset_gpio, 0); /* Deassert GPIO */
|
||||
} else {
|
||||
/* Software reset */
|
||||
regmap_write(regmap, SC16IS7XX_IOCONTROL_REG,
|
||||
SC16IS7XX_IOCONTROL_SRESET_BIT);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
|
||||
struct regmap *regmaps[], int irq)
|
||||
{
|
||||
@@ -1536,9 +1560,9 @@ int sc16is7xx_probe(struct device *dev, const struct sc16is7xx_devtype *devtype,
|
||||
}
|
||||
sched_set_fifo(s->kworker_task);
|
||||
|
||||
/* reset device, purging any pending irq / data */
|
||||
regmap_write(regmaps[0], SC16IS7XX_IOCONTROL_REG,
|
||||
SC16IS7XX_IOCONTROL_SRESET_BIT);
|
||||
ret = sc16is7xx_reset(dev, regmaps[0]);
|
||||
if (ret)
|
||||
goto out_kthread;
|
||||
|
||||
/* Mark each port line and status as uninitialised. */
|
||||
for (i = 0; i < devtype->nr_uart; ++i) {
|
||||
@@ -1663,6 +1687,7 @@ out_ports:
|
||||
uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
|
||||
}
|
||||
|
||||
out_kthread:
|
||||
kthread_stop(s->kworker_task);
|
||||
|
||||
out_clk:
|
||||
|
||||
@@ -49,3 +49,19 @@ void serial_ctrl_unregister_port(struct uart_driver *drv, struct uart_port *port
|
||||
|
||||
int serial_core_register_port(struct uart_driver *drv, struct uart_port *port);
|
||||
void serial_core_unregister_port(struct uart_driver *drv, struct uart_port *port);
|
||||
|
||||
#ifdef CONFIG_SERIAL_CORE_CONSOLE
|
||||
|
||||
int serial_base_match_and_update_preferred_console(struct uart_driver *drv,
|
||||
struct uart_port *port);
|
||||
|
||||
#else
|
||||
|
||||
static inline
|
||||
int serial_base_match_and_update_preferred_console(struct uart_driver *drv,
|
||||
struct uart_port *port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* The serial core bus manages the serial core controller instances.
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/container_of.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/idr.h>
|
||||
@@ -204,6 +205,42 @@ void serial_base_port_device_remove(struct serial_port_device *port_dev)
|
||||
put_device(&port_dev->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_CORE_CONSOLE
|
||||
|
||||
/**
|
||||
* serial_base_match_and_update_preferred_console - Match and update a preferred console
|
||||
* @drv: Serial port device driver
|
||||
* @port: Serial port instance
|
||||
*
|
||||
* Tries to match and update the preferred console for a serial port for
|
||||
* the kernel command line option console=DEVNAME:0.0.
|
||||
*
|
||||
* Cannot be called early for ISA ports, depends on struct device.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int serial_base_match_and_update_preferred_console(struct uart_driver *drv,
|
||||
struct uart_port *port)
|
||||
{
|
||||
const char *port_match __free(kfree) = NULL;
|
||||
int ret;
|
||||
|
||||
port_match = kasprintf(GFP_KERNEL, "%s:%d.%d", dev_name(port->dev),
|
||||
port->ctrl_id, port->port_id);
|
||||
if (!port_match)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = match_devname_and_update_preferred_console(port_match,
|
||||
drv->dev_name,
|
||||
port->line);
|
||||
if (ret == -ENOENT)
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int serial_base_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -3422,6 +3422,10 @@ int serial_core_register_port(struct uart_driver *drv, struct uart_port *port)
|
||||
if (ret)
|
||||
goto err_unregister_ctrl_dev;
|
||||
|
||||
ret = serial_base_match_and_update_preferred_console(drv, port);
|
||||
if (ret)
|
||||
goto err_unregister_port_dev;
|
||||
|
||||
ret = serial_core_add_one_port(drv, port);
|
||||
if (ret)
|
||||
goto err_unregister_port_dev;
|
||||
|
||||
@@ -385,4 +385,5 @@ void mctrl_gpio_disable_irq_wake(struct mctrl_gpios *gpios)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mctrl_gpio_disable_irq_wake);
|
||||
|
||||
MODULE_DESCRIPTION("Helpers for controlling modem lines via GPIO");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -317,6 +317,37 @@ static const struct sci_port_params sci_port_params[SCIx_NR_REGTYPES] = {
|
||||
.error_clear = SCIF_ERROR_CLEAR,
|
||||
},
|
||||
|
||||
/*
|
||||
* The "SCIF" that is in RZ/V2H(P) SoC is similar to one found on RZ/G2L SoC
|
||||
* with below differences,
|
||||
* - Break out of interrupts are different: ERI, BRI, RXI, TXI, TEI, DRI,
|
||||
* TEI-DRI, RXI-EDGE and TXI-EDGE.
|
||||
* - SCSMR register does not have CM bit (BIT(7)) ie it does not support synchronous mode.
|
||||
* - SCFCR register does not have SCFCR_MCE bit.
|
||||
* - SCSPTR register has only bits SCSPTR_SPB2DT and SCSPTR_SPB2IO.
|
||||
*/
|
||||
[SCIx_RZV2H_SCIF_REGTYPE] = {
|
||||
.regs = {
|
||||
[SCSMR] = { 0x00, 16 },
|
||||
[SCBRR] = { 0x02, 8 },
|
||||
[SCSCR] = { 0x04, 16 },
|
||||
[SCxTDR] = { 0x06, 8 },
|
||||
[SCxSR] = { 0x08, 16 },
|
||||
[SCxRDR] = { 0x0a, 8 },
|
||||
[SCFCR] = { 0x0c, 16 },
|
||||
[SCFDR] = { 0x0e, 16 },
|
||||
[SCSPTR] = { 0x10, 16 },
|
||||
[SCLSR] = { 0x12, 16 },
|
||||
[SEMR] = { 0x14, 8 },
|
||||
},
|
||||
.fifosize = 16,
|
||||
.overrun_reg = SCLSR,
|
||||
.overrun_mask = SCLSR_ORER,
|
||||
.sampling_rate_mask = SCI_SR(32),
|
||||
.error_mask = SCIF_DEFAULT_ERROR_MASK,
|
||||
.error_clear = SCIF_ERROR_CLEAR,
|
||||
},
|
||||
|
||||
/*
|
||||
* Common SH-3 SCIF definitions.
|
||||
*/
|
||||
@@ -757,7 +788,7 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
||||
}
|
||||
sci_serial_out(port, SCPDR, data);
|
||||
sci_serial_out(port, SCPCR, ctrl);
|
||||
} else if (sci_getreg(port, SCSPTR)->size) {
|
||||
} else if (sci_getreg(port, SCSPTR)->size && s->cfg->regtype != SCIx_RZV2H_SCIF_REGTYPE) {
|
||||
u16 status = sci_serial_in(port, SCSPTR);
|
||||
|
||||
/* RTS# is always output; and active low, unless autorts */
|
||||
@@ -2124,8 +2155,9 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
|
||||
if (!(mctrl & TIOCM_RTS)) {
|
||||
/* Disable Auto RTS */
|
||||
sci_serial_out(port, SCFCR,
|
||||
sci_serial_in(port, SCFCR) & ~SCFCR_MCE);
|
||||
if (s->cfg->regtype != SCIx_RZV2H_SCIF_REGTYPE)
|
||||
sci_serial_out(port, SCFCR,
|
||||
sci_serial_in(port, SCFCR) & ~SCFCR_MCE);
|
||||
|
||||
/* Clear RTS */
|
||||
sci_set_rts(port, 0);
|
||||
@@ -2137,8 +2169,9 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||
}
|
||||
|
||||
/* Enable Auto RTS */
|
||||
sci_serial_out(port, SCFCR,
|
||||
sci_serial_in(port, SCFCR) | SCFCR_MCE);
|
||||
if (s->cfg->regtype != SCIx_RZV2H_SCIF_REGTYPE)
|
||||
sci_serial_out(port, SCFCR,
|
||||
sci_serial_in(port, SCFCR) | SCFCR_MCE);
|
||||
} else {
|
||||
/* Set RTS */
|
||||
sci_set_rts(port, 1);
|
||||
@@ -3225,6 +3258,10 @@ static const struct of_device_id of_sci_match[] __maybe_unused = {
|
||||
.compatible = "renesas,scif-r9a07g044",
|
||||
.data = SCI_OF_DATA(PORT_SCIF, SCIx_RZ_SCIFA_REGTYPE),
|
||||
},
|
||||
{
|
||||
.compatible = "renesas,scif-r9a09g057",
|
||||
.data = SCI_OF_DATA(PORT_SCIF, SCIx_RZV2H_SCIF_REGTYPE),
|
||||
},
|
||||
/* Family-specific types */
|
||||
{
|
||||
.compatible = "renesas,rcar-gen1-scif",
|
||||
@@ -3533,6 +3570,13 @@ static int __init rzscifa_early_console_setup(struct earlycon_device *device,
|
||||
return early_console_setup(device, PORT_SCIF);
|
||||
}
|
||||
|
||||
static int __init rzv2hscif_early_console_setup(struct earlycon_device *device,
|
||||
const char *opt)
|
||||
{
|
||||
port_cfg.regtype = SCIx_RZV2H_SCIF_REGTYPE;
|
||||
return early_console_setup(device, PORT_SCIF);
|
||||
}
|
||||
|
||||
static int __init scifa_early_console_setup(struct earlycon_device *device,
|
||||
const char *opt)
|
||||
{
|
||||
@@ -3553,6 +3597,7 @@ OF_EARLYCON_DECLARE(sci, "renesas,sci", sci_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(scif, "renesas,scif", scif_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(scif, "renesas,scif-r7s9210", rzscifa_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(scif, "renesas,scif-r9a07g044", rzscifa_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(scif, "renesas,scif-r9a09g057", rzv2hscif_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(scifa, "renesas,scifa", scifa_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(scifb, "renesas,scifb", scifb_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(hscif, "renesas,hscif", hscif_early_console_setup);
|
||||
|
||||
@@ -1382,44 +1382,29 @@ static inline struct console *SUNSU_CONSOLE(void)
|
||||
|
||||
static enum su_type su_get_type(struct device_node *dp)
|
||||
{
|
||||
struct device_node *ap = of_find_node_by_path("/aliases");
|
||||
enum su_type rc = SU_PORT_PORT;
|
||||
struct device_node *ap __free(device_node) =
|
||||
of_find_node_by_path("/aliases");
|
||||
|
||||
if (ap) {
|
||||
const char *keyb = of_get_property(ap, "keyboard", NULL);
|
||||
const char *ms = of_get_property(ap, "mouse", NULL);
|
||||
struct device_node *match;
|
||||
|
||||
if (keyb) {
|
||||
match = of_find_node_by_path(keyb);
|
||||
struct device_node *match __free(device_node) =
|
||||
of_find_node_by_path(keyb);
|
||||
|
||||
/*
|
||||
* The pointer is used as an identifier not
|
||||
* as a pointer, we can drop the refcount on
|
||||
* the of__node immediately after getting it.
|
||||
*/
|
||||
of_node_put(match);
|
||||
|
||||
if (dp == match) {
|
||||
rc = SU_PORT_KBD;
|
||||
goto out;
|
||||
}
|
||||
if (dp == match)
|
||||
return SU_PORT_KBD;
|
||||
}
|
||||
if (ms) {
|
||||
match = of_find_node_by_path(ms);
|
||||
struct device_node *match __free(device_node) =
|
||||
of_find_node_by_path(ms);
|
||||
|
||||
of_node_put(match);
|
||||
|
||||
if (dp == match) {
|
||||
rc = SU_PORT_MS;
|
||||
goto out;
|
||||
}
|
||||
if (dp == match)
|
||||
return SU_PORT_MS;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
of_node_put(ap);
|
||||
return rc;
|
||||
return SU_PORT_PORT;
|
||||
}
|
||||
|
||||
static int su_probe(struct platform_device *op)
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
*/
|
||||
static const char driver_name[] = "SyncLink GT";
|
||||
static const char tty_dev_prefix[] = "ttySLG";
|
||||
MODULE_DESCRIPTION("Device driver for Microgate SyncLink GT serial adapters");
|
||||
MODULE_LICENSE("GPL");
|
||||
#define MAX_DEVICES 32
|
||||
|
||||
|
||||
@@ -106,4 +106,5 @@ static void __exit ttynull_exit(void)
|
||||
module_init(ttynull_init);
|
||||
module_exit(ttynull_exit);
|
||||
|
||||
MODULE_DESCRIPTION("NULL TTY driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -1033,9 +1033,7 @@ static int kbd_led_trigger_activate(struct led_classdev *cdev)
|
||||
|
||||
tasklet_disable(&keyboard_tasklet);
|
||||
if (ledstate != -1U)
|
||||
led_trigger_event(&trigger->trigger,
|
||||
ledstate & trigger->mask ?
|
||||
LED_FULL : LED_OFF);
|
||||
led_set_brightness(cdev, ledstate & trigger->mask ? LED_FULL : LED_OFF);
|
||||
tasklet_enable(&keyboard_tasklet);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -60,6 +60,10 @@ static inline const char *printk_skip_headers(const char *buffer)
|
||||
#define CONSOLE_LOGLEVEL_DEFAULT CONFIG_CONSOLE_LOGLEVEL_DEFAULT
|
||||
#define CONSOLE_LOGLEVEL_QUIET CONFIG_CONSOLE_LOGLEVEL_QUIET
|
||||
|
||||
int match_devname_and_update_preferred_console(const char *match,
|
||||
const char *name,
|
||||
const short idx);
|
||||
|
||||
extern int console_printk[];
|
||||
|
||||
#define console_loglevel (console_printk[0])
|
||||
|
||||
@@ -37,6 +37,7 @@ enum {
|
||||
SCIx_SH7705_SCIF_REGTYPE,
|
||||
SCIx_HSCIF_REGTYPE,
|
||||
SCIx_RZ_SCIFA_REGTYPE,
|
||||
SCIx_RZV2H_SCIF_REGTYPE,
|
||||
|
||||
SCIx_NR_REGTYPES,
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ struct console_cmdline
|
||||
{
|
||||
char name[16]; /* Name of the driver */
|
||||
int index; /* Minor dev. to use */
|
||||
char devname[32]; /* DEVNAME:0.0 style device name */
|
||||
bool user_specified; /* Specified by command line vs. platform */
|
||||
char *options; /* Options for the driver */
|
||||
#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
|
||||
|
||||
@@ -2429,18 +2429,23 @@ static void set_user_specified(struct console_cmdline *c, bool user_specified)
|
||||
console_set_on_cmdline = 1;
|
||||
}
|
||||
|
||||
static int __add_preferred_console(const char *name, const short idx, char *options,
|
||||
static int __add_preferred_console(const char *name, const short idx,
|
||||
const char *devname, char *options,
|
||||
char *brl_options, bool user_specified)
|
||||
{
|
||||
struct console_cmdline *c;
|
||||
int i;
|
||||
|
||||
if (!name && !devname)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* We use a signed short index for struct console for device drivers to
|
||||
* indicate a not yet assigned index or port. However, a negative index
|
||||
* value is not valid for preferred console.
|
||||
* value is not valid when the console name and index are defined on
|
||||
* the command line.
|
||||
*/
|
||||
if (idx < 0)
|
||||
if (name && idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
@@ -2448,9 +2453,10 @@ static int __add_preferred_console(const char *name, const short idx, char *opti
|
||||
* if we have a slot free.
|
||||
*/
|
||||
for (i = 0, c = console_cmdline;
|
||||
i < MAX_CMDLINECONSOLES && c->name[0];
|
||||
i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
|
||||
i++, c++) {
|
||||
if (strcmp(c->name, name) == 0 && c->index == idx) {
|
||||
if ((name && strcmp(c->name, name) == 0 && c->index == idx) ||
|
||||
(devname && strcmp(c->devname, devname) == 0)) {
|
||||
if (!brl_options)
|
||||
preferred_console = i;
|
||||
set_user_specified(c, user_specified);
|
||||
@@ -2461,7 +2467,10 @@ static int __add_preferred_console(const char *name, const short idx, char *opti
|
||||
return -E2BIG;
|
||||
if (!brl_options)
|
||||
preferred_console = i;
|
||||
strscpy(c->name, name, sizeof(c->name));
|
||||
if (name)
|
||||
strscpy(c->name, name);
|
||||
if (devname)
|
||||
strscpy(c->devname, devname);
|
||||
c->options = options;
|
||||
set_user_specified(c, user_specified);
|
||||
braille_set_options(c, brl_options);
|
||||
@@ -2486,8 +2495,13 @@ __setup("console_msg_format=", console_msg_format_setup);
|
||||
*/
|
||||
static int __init console_setup(char *str)
|
||||
{
|
||||
char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
|
||||
char *s, *options, *brl_options = NULL;
|
||||
static_assert(sizeof(console_cmdline[0].devname) >= sizeof(console_cmdline[0].name) + 4);
|
||||
char buf[sizeof(console_cmdline[0].devname)];
|
||||
char *brl_options = NULL;
|
||||
char *ttyname = NULL;
|
||||
char *devname = NULL;
|
||||
char *options;
|
||||
char *s;
|
||||
int idx;
|
||||
|
||||
/*
|
||||
@@ -2496,17 +2510,23 @@ static int __init console_setup(char *str)
|
||||
* for exactly this purpose.
|
||||
*/
|
||||
if (str[0] == 0 || strcmp(str, "null") == 0) {
|
||||
__add_preferred_console("ttynull", 0, NULL, NULL, true);
|
||||
__add_preferred_console("ttynull", 0, NULL, NULL, NULL, true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (_braille_console_setup(&str, &brl_options))
|
||||
return 1;
|
||||
|
||||
/* For a DEVNAME:0.0 style console the character device is unknown early */
|
||||
if (strchr(str, ':'))
|
||||
devname = buf;
|
||||
else
|
||||
ttyname = buf;
|
||||
|
||||
/*
|
||||
* Decode str into name, index, options.
|
||||
*/
|
||||
if (isdigit(str[0]))
|
||||
if (ttyname && isdigit(str[0]))
|
||||
scnprintf(buf, sizeof(buf), "ttyS%s", str);
|
||||
else
|
||||
strscpy(buf, str);
|
||||
@@ -2523,12 +2543,18 @@ static int __init console_setup(char *str)
|
||||
#endif
|
||||
|
||||
for (s = buf; *s; s++)
|
||||
if (isdigit(*s) || *s == ',')
|
||||
if ((ttyname && isdigit(*s)) || *s == ',')
|
||||
break;
|
||||
idx = simple_strtoul(s, NULL, 10);
|
||||
|
||||
/* @idx will get defined when devname matches. */
|
||||
if (devname)
|
||||
idx = -1;
|
||||
else
|
||||
idx = simple_strtoul(s, NULL, 10);
|
||||
|
||||
*s = 0;
|
||||
|
||||
__add_preferred_console(buf, idx, options, brl_options, true);
|
||||
__add_preferred_console(ttyname, idx, devname, options, brl_options, true);
|
||||
return 1;
|
||||
}
|
||||
__setup("console=", console_setup);
|
||||
@@ -2548,7 +2574,51 @@ __setup("console=", console_setup);
|
||||
*/
|
||||
int add_preferred_console(const char *name, const short idx, char *options)
|
||||
{
|
||||
return __add_preferred_console(name, idx, options, NULL, false);
|
||||
return __add_preferred_console(name, idx, NULL, options, NULL, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* match_devname_and_update_preferred_console - Update a preferred console
|
||||
* when matching devname is found.
|
||||
* @devname: DEVNAME:0.0 style device name
|
||||
* @name: Name of the corresponding console driver, e.g. "ttyS"
|
||||
* @idx: Console index, e.g. port number.
|
||||
*
|
||||
* The function checks whether a device with the given @devname is
|
||||
* preferred via the console=DEVNAME:0.0 command line option.
|
||||
* It fills the missing console driver name and console index
|
||||
* so that a later register_console() call could find (match)
|
||||
* and enable this device.
|
||||
*
|
||||
* It might be used when a driver subsystem initializes particular
|
||||
* devices with already known DEVNAME:0.0 style names. And it
|
||||
* could predict which console driver name and index this device
|
||||
* would later get associated with.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int match_devname_and_update_preferred_console(const char *devname,
|
||||
const char *name,
|
||||
const short idx)
|
||||
{
|
||||
struct console_cmdline *c = console_cmdline;
|
||||
int i;
|
||||
|
||||
if (!devname || !strlen(devname) || !name || !strlen(name) || idx < 0)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
|
||||
i++, c++) {
|
||||
if (!strcmp(devname, c->devname)) {
|
||||
pr_info("associate the preferred console \"%s\" with \"%s%d\"\n",
|
||||
devname, name, idx);
|
||||
strscpy(c->name, name);
|
||||
c->index = idx;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
bool console_suspend_enabled = true;
|
||||
@@ -3318,8 +3388,11 @@ static int try_enable_preferred_console(struct console *newcon,
|
||||
int i, err;
|
||||
|
||||
for (i = 0, c = console_cmdline;
|
||||
i < MAX_CMDLINECONSOLES && c->name[0];
|
||||
i < MAX_CMDLINECONSOLES && (c->name[0] || c->devname[0]);
|
||||
i++, c++) {
|
||||
/* Console not yet initialized? */
|
||||
if (!c->name[0])
|
||||
continue;
|
||||
if (c->user_specified != user_specified)
|
||||
continue;
|
||||
if (!newcon->match ||
|
||||
|
||||
Reference in New Issue
Block a user