From b96cd8b05ead8939b972192c4f4ac2fc2dffceb7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Apr 2022 13:01:38 +0200 Subject: Documentation: move tty to driver-api Based on discussion starting as 87mthw2o93.fsf@meer.lwn.net, let's move the tty documentation to driver-api. It's more appropriate there. Cc: Jonathan Corbet Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220411110143.10019-2-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/index.rst | 1 + Documentation/driver-api/serial/driver.rst | 2 +- Documentation/driver-api/tty/index.rst | 62 ++++++++++++ Documentation/driver-api/tty/n_tty.rst | 22 +++++ Documentation/driver-api/tty/tty_buffer.rst | 46 +++++++++ Documentation/driver-api/tty/tty_driver.rst | 128 +++++++++++++++++++++++++ Documentation/driver-api/tty/tty_internals.rst | 31 ++++++ Documentation/driver-api/tty/tty_ldisc.rst | 85 ++++++++++++++++ Documentation/driver-api/tty/tty_port.rst | 70 ++++++++++++++ Documentation/driver-api/tty/tty_struct.rst | 81 ++++++++++++++++ Documentation/index.rst | 1 - Documentation/tty/index.rst | 63 ------------ Documentation/tty/n_tty.rst | 22 ----- Documentation/tty/tty_buffer.rst | 46 --------- Documentation/tty/tty_driver.rst | 128 ------------------------- Documentation/tty/tty_internals.rst | 31 ------ Documentation/tty/tty_ldisc.rst | 85 ---------------- Documentation/tty/tty_port.rst | 70 -------------- Documentation/tty/tty_struct.rst | 81 ---------------- 19 files changed, 527 insertions(+), 528 deletions(-) create mode 100644 Documentation/driver-api/tty/index.rst create mode 100644 Documentation/driver-api/tty/n_tty.rst create mode 100644 Documentation/driver-api/tty/tty_buffer.rst create mode 100644 Documentation/driver-api/tty/tty_driver.rst create mode 100644 Documentation/driver-api/tty/tty_internals.rst create mode 100644 Documentation/driver-api/tty/tty_ldisc.rst create mode 100644 Documentation/driver-api/tty/tty_port.rst create mode 100644 Documentation/driver-api/tty/tty_struct.rst delete mode 100644 Documentation/tty/index.rst delete mode 100644 Documentation/tty/n_tty.rst delete mode 100644 Documentation/tty/tty_buffer.rst delete mode 100644 Documentation/tty/tty_driver.rst delete mode 100644 Documentation/tty/tty_internals.rst delete mode 100644 Documentation/tty/tty_ldisc.rst delete mode 100644 Documentation/tty/tty_port.rst delete mode 100644 Documentation/tty/tty_struct.rst (limited to 'Documentation') diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index a7b0223e2886..bbbbcf20b7ce 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -101,6 +101,7 @@ available subsections can be seen below. surface_aggregator/index switchtec sync_file + tty vfio-mediated-device vfio vfio-pci-device-specific-driver-acceptance diff --git a/Documentation/driver-api/serial/driver.rst b/Documentation/driver-api/serial/driver.rst index 06ec04ba086f..7ef83fd3917b 100644 --- a/Documentation/driver-api/serial/driver.rst +++ b/Documentation/driver-api/serial/driver.rst @@ -311,7 +311,7 @@ hardware. This call must not sleep set_ldisc(port,termios) - Notifier for discipline change. See Documentation/tty/tty_ldisc.rst. + Notifier for discipline change. See ../tty/tty_ldisc.rst. Locking: caller holds tty_port->mutex diff --git a/Documentation/driver-api/tty/index.rst b/Documentation/driver-api/tty/index.rst new file mode 100644 index 000000000000..2240e52203d6 --- /dev/null +++ b/Documentation/driver-api/tty/index.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=== +TTY +=== + +Teletypewriter (TTY) layer takes care of all those serial devices. Including +the virtual ones like pseudoterminal (PTY). + +TTY structures +============== + +There are several major TTY structures. Every TTY device in a system has a +corresponding struct tty_port. These devices are maintained by a TTY driver +which is struct tty_driver. This structure describes the driver but also +contains a reference to operations which could be performed on the TTYs. It is +struct tty_operations. Then, upon open, a struct tty_struct is allocated and +lives until the final close. During this time, several callbacks from struct +tty_operations are invoked by the TTY layer. + +Every character received by the kernel (both from devices and users) is passed +through a preselected :doc:`tty_ldisc` (in +short ldisc; in C, struct tty_ldisc_ops). Its task is to transform characters +as defined by a particular ldisc or by user too. The default one is n_tty, +implementing echoes, signal handling, jobs control, special characters +processing, and more. The transformed characters are passed further to +user/device, depending on the source. + +In-detail description of the named TTY structures is in separate documents: + +.. toctree:: + :maxdepth: 2 + + tty_driver + tty_port + tty_struct + tty_ldisc + tty_buffer + n_tty + tty_internals + +Writing TTY Driver +================== + +Before one starts writing a TTY driver, they must consider +:doc:`Serial <../serial/driver>` and :doc:`USB Serial <../../usb/usb-serial>` +layers first. Drivers for serial devices can often use one of these specific +layers to implement a serial driver. Only special devices should be handled +directly by the TTY Layer. If you are about to write such a driver, read on. + +A *typical* sequence a TTY driver performs is as follows: + +#. Allocate and register a TTY driver (module init) +#. Create and register TTY devices as they are probed (probe function) +#. Handle TTY operations and events like interrupts (TTY core invokes the + former, the device the latter) +#. Remove devices as they are going away (remove function) +#. Unregister and free the TTY driver (module exit) + +Steps regarding driver, i.e. 1., 3., and 5. are described in detail in +:doc:`tty_driver`. For the other two (devices handling), look into +:doc:`tty_port`. diff --git a/Documentation/driver-api/tty/n_tty.rst b/Documentation/driver-api/tty/n_tty.rst new file mode 100644 index 000000000000..15b70faee72d --- /dev/null +++ b/Documentation/driver-api/tty/n_tty.rst @@ -0,0 +1,22 @@ +.. SPDX-License-Identifier: GPL-2.0 + +===== +N_TTY +===== + +.. contents:: :local: + +The default (and fallback) :doc:`TTY line discipline `. It tries to +handle characters as per POSIX. + +External Functions +================== + +.. kernel-doc:: drivers/tty/n_tty.c + :export: + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/n_tty.c + :internal: diff --git a/Documentation/driver-api/tty/tty_buffer.rst b/Documentation/driver-api/tty/tty_buffer.rst new file mode 100644 index 000000000000..a39d4781e0d2 --- /dev/null +++ b/Documentation/driver-api/tty/tty_buffer.rst @@ -0,0 +1,46 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========== +TTY Buffer +========== + +.. contents:: :local: + +Here, we document functions for taking care of tty buffer and their flipping. +Drivers are supposed to fill the buffer by one of those functions below and +then flip the buffer, so that the data are passed to :doc:`line discipline +` for further processing. + +Flip Buffer Management +====================== + +.. kernel-doc:: drivers/tty/tty_buffer.c + :identifiers: tty_prepare_flip_string tty_insert_flip_string_fixed_flag + tty_insert_flip_string_flags __tty_insert_flip_char + tty_flip_buffer_push tty_ldisc_receive_buf + +---- + +Other Functions +=============== + +.. kernel-doc:: drivers/tty/tty_buffer.c + :identifiers: tty_buffer_space_avail tty_buffer_set_limit + +---- + +Buffer Locking +============== + +These are used only in special circumstances. Avoid them. + +.. kernel-doc:: drivers/tty/tty_buffer.c + :identifiers: tty_buffer_lock_exclusive tty_buffer_unlock_exclusive + +---- + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/tty_buffer.c + :internal: diff --git a/Documentation/driver-api/tty/tty_driver.rst b/Documentation/driver-api/tty/tty_driver.rst new file mode 100644 index 000000000000..cc529f863406 --- /dev/null +++ b/Documentation/driver-api/tty/tty_driver.rst @@ -0,0 +1,128 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================= +TTY Driver and TTY Operations +============================= + +.. contents:: :local: + +Allocation +========== + +The first thing a driver needs to do is to allocate a struct tty_driver. This +is done by tty_alloc_driver() (or __tty_alloc_driver()). Next, the newly +allocated structure is filled with information. See `TTY Driver Reference`_ at +the end of this document on what actually shall be filled in. + +The allocation routines expect a number of devices the driver can handle at +most and flags. Flags are those starting ``TTY_DRIVER_`` listed and described +in `TTY Driver Flags`_ below. + +When the driver is about to be freed, tty_driver_kref_put() is called on that. +It will decrements the reference count and if it reaches zero, the driver is +freed. + +For reference, both allocation and deallocation functions are explained here in +detail: + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: __tty_alloc_driver tty_driver_kref_put + +TTY Driver Flags +---------------- + +Here comes the documentation of flags accepted by tty_alloc_driver() (or +__tty_alloc_driver()): + +.. kernel-doc:: include/linux/tty_driver.h + :doc: TTY Driver Flags + +---- + +Registration +============ + +When a struct tty_driver is allocated and filled in, it can be registered using +tty_register_driver(). It is recommended to pass ``TTY_DRIVER_DYNAMIC_DEV`` in +flags of tty_alloc_driver(). If it is not passed, *all* devices are also +registered during tty_register_driver() and the following paragraph of +registering devices can be skipped for such drivers. However, the struct +tty_port part in `Registering Devices`_ is still relevant there. + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_register_driver tty_unregister_driver + +Registering Devices +------------------- + +Every TTY device shall be backed by a struct tty_port. Usually, TTY drivers +embed tty_port into device's private structures. Further details about handling +tty_port can be found in :doc:`tty_port`. The driver is also recommended to use +tty_port's reference counting by tty_port_get() and tty_port_put(). The final +put is supposed to free the tty_port including the device's private struct. + +Unless ``TTY_DRIVER_DYNAMIC_DEV`` was passed as flags to tty_alloc_driver(), +TTY driver is supposed to register every device discovered in the system +(the latter is preferred). This is performed by tty_register_device(). Or by +tty_register_device_attr() if the driver wants to expose some information +through struct attribute_group. Both of them register ``index``'th device and +upon return, the device can be opened. There are also preferred tty_port +variants described in `Linking Devices to Ports`_ later. It is up to driver to +manage free indices and choosing the right one. The TTY layer only refuses to +register more devices than passed to tty_alloc_driver(). + +When the device is opened, the TTY layer allocates struct tty_struct and starts +calling operations from :c:member:`tty_driver.ops`, see `TTY Operations +Reference`_. + +The registration routines are documented as follows: + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_register_device tty_register_device_attr + tty_unregister_device + +---- + +Linking Devices to Ports +------------------------ +As stated earlier, every TTY device shall have a struct tty_port assigned to +it. It must be known to the TTY layer at :c:member:`tty_driver.ops.install()` +at latest. There are few helpers to *link* the two. Ideally, the driver uses +tty_port_register_device() or tty_port_register_device_attr() instead of +tty_register_device() and tty_register_device_attr() at the registration time. +This way, the driver needs not care about linking later on. + +If that is not possible, the driver still can link the tty_port to a specific +index *before* the actual registration by tty_port_link_device(). If it still +does not fit, tty_port_install() can be used from the +:c:member:`tty_driver.ops.install` hook as a last resort. The last one is +dedicated mostly for in-memory devices like PTY where tty_ports are allocated +on demand. + +The linking routines are documented here: + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_link_device tty_port_register_device + tty_port_register_device_attr + +---- + +TTY Driver Reference +==================== + +All members of struct tty_driver are documented here. The required members are +noted at the end. struct tty_operations are documented next. + +.. kernel-doc:: include/linux/tty_driver.h + :identifiers: tty_driver + +---- + +TTY Operations Reference +======================== + +When a TTY is registered, these driver hooks can be invoked by the TTY layer: + +.. kernel-doc:: include/linux/tty_driver.h + :identifiers: tty_operations + diff --git a/Documentation/driver-api/tty/tty_internals.rst b/Documentation/driver-api/tty/tty_internals.rst new file mode 100644 index 000000000000..d0d415820300 --- /dev/null +++ b/Documentation/driver-api/tty/tty_internals.rst @@ -0,0 +1,31 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============= +TTY Internals +============= + +.. contents:: :local: + +Kopen +===== + +These functions serve for opening a TTY from the kernelspace: + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_kopen_exclusive tty_kopen_shared tty_kclose + +---- + +Exported Internal Functions +=========================== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_release_struct tty_dev_name_to_number tty_get_icount + +---- + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/tty_io.c + :internal: diff --git a/Documentation/driver-api/tty/tty_ldisc.rst b/Documentation/driver-api/tty/tty_ldisc.rst new file mode 100644 index 000000000000..5144751be804 --- /dev/null +++ b/Documentation/driver-api/tty/tty_ldisc.rst @@ -0,0 +1,85 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +TTY Line Discipline +=================== + +.. contents:: :local: + +TTY line discipline process all incoming and outgoing character from/to a tty +device. The default line discipline is :doc:`N_TTY `. It is also a +fallback if establishing any other discipline for a tty fails. If even N_TTY +fails, N_NULL takes over. That never fails, but also does not process any +characters -- it throws them away. + +Registration +============ + +Line disciplines are registered with tty_register_ldisc() passing the ldisc +structure. At the point of registration the discipline must be ready to use and +it is possible it will get used before the call returns success. If the call +returns an error then it won’t get called. Do not re-use ldisc numbers as they +are part of the userspace ABI and writing over an existing ldisc will cause +demons to eat your computer. You must not re-register over the top of the line +discipline even with the same data or your computer again will be eaten by +demons. In order to remove a line discipline call tty_unregister_ldisc(). + +Heed this warning: the reference count field of the registered copies of the +tty_ldisc structure in the ldisc table counts the number of lines using this +discipline. The reference count of the tty_ldisc structure within a tty counts +the number of active users of the ldisc at this instant. In effect it counts +the number of threads of execution within an ldisc method (plus those about to +enter and exit although this detail matters not). + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :identifiers: tty_register_ldisc tty_unregister_ldisc + +Other Functions +=============== + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :identifiers: tty_set_ldisc tty_ldisc_flush + +Line Discipline Operations Reference +==================================== + +.. kernel-doc:: include/linux/tty_ldisc.h + :identifiers: tty_ldisc_ops + +Driver Access +============= + +Line discipline methods can call the methods of the underlying hardware driver. +These are documented as a part of struct tty_operations. + +TTY Flags +========= + +Line discipline methods have access to :c:member:`tty_struct.flags` field. See +:doc:`tty_struct`. + +Locking +======= + +Callers to the line discipline functions from the tty layer are required to +take line discipline locks. The same is true of calls from the driver side +but not yet enforced. + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :identifiers: tty_ldisc_ref_wait tty_ldisc_ref tty_ldisc_deref + +While these functions are slightly slower than the old code they should have +minimal impact as most receive logic uses the flip buffers and they only +need to take a reference when they push bits up through the driver. + +A caution: The :c:member:`tty_ldisc_ops.open()`, +:c:member:`tty_ldisc_ops.close()` and :c:member:`tty_driver.set_ldisc()` +functions are called with the ldisc unavailable. Thus tty_ldisc_ref() will fail +in this situation if used within these functions. Ldisc and driver code +calling its own functions must be careful in this case. + +Internal Functions +================== + +.. kernel-doc:: drivers/tty/tty_ldisc.c + :internal: diff --git a/Documentation/driver-api/tty/tty_port.rst b/Documentation/driver-api/tty/tty_port.rst new file mode 100644 index 000000000000..5cb90e954fcf --- /dev/null +++ b/Documentation/driver-api/tty/tty_port.rst @@ -0,0 +1,70 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======== +TTY Port +======== + +.. contents:: :local: + +The TTY drivers are advised to use struct tty_port helpers as much as possible. +If the drivers implement :c:member:`tty_port.ops.activate()` and +:c:member:`tty_port.ops.shutdown()`, they can use tty_port_open(), +tty_port_close(), and tty_port_hangup() in respective +:c:member:`tty_struct.ops` hooks. + +The reference and details are contained in the `TTY Port Reference`_ and `TTY +Port Operations Reference`_ sections at the bottom. + +TTY Port Functions +================== + +Init & Destroy +-------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_init tty_port_destroy + tty_port_get tty_port_put + +Open/Close/Hangup Helpers +------------------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_install tty_port_open tty_port_block_til_ready + tty_port_close tty_port_close_start tty_port_close_end tty_port_hangup + tty_port_shutdown + +TTY Refcounting +--------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_tty_get tty_port_tty_set + +TTY Helpers +----------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_tty_hangup tty_port_tty_wakeup + + +Modem Signals +------------- + +.. kernel-doc:: drivers/tty/tty_port.c + :identifiers: tty_port_carrier_raised tty_port_raise_dtr_rts + tty_port_lower_dtr_rts + +---- + +TTY Port Reference +================== + +.. kernel-doc:: include/linux/tty_port.h + :identifiers: tty_port + +---- + +TTY Port Operations Reference +============================= + +.. kernel-doc:: include/linux/tty_port.h + :identifiers: tty_port_operations diff --git a/Documentation/driver-api/tty/tty_struct.rst b/Documentation/driver-api/tty/tty_struct.rst new file mode 100644 index 000000000000..c72f5a4293b2 --- /dev/null +++ b/Documentation/driver-api/tty/tty_struct.rst @@ -0,0 +1,81 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========== +TTY Struct +========== + +.. contents:: :local: + +struct tty_struct is allocated by the TTY layer upon the first open of the TTY +device and released after the last close. The TTY layer passes this structure +to most of struct tty_operation's hooks. Members of tty_struct are documented +in `TTY Struct Reference`_ at the bottom. + +Initialization +============== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_init_termios + +Name +==== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_name + +Reference counting +================== + +.. kernel-doc:: include/linux/tty.h + :identifiers: tty_kref_get + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_kref_put + +Install +======= + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_standard_install + +Read & Write +============ + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_put_char + +Start & Stop +============ + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: start_tty stop_tty + +Wakeup +====== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_wakeup + +Hangup +====== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_hangup tty_vhangup tty_hung_up_p + +Misc +==== + +.. kernel-doc:: drivers/tty/tty_io.c + :identifiers: tty_do_resize + +TTY Struct Flags +================ + +.. kernel-doc:: include/linux/tty.h + :doc: TTY Struct Flags + +TTY Struct Reference +==================== + +.. kernel-doc:: include/linux/tty.h + :identifiers: tty_struct diff --git a/Documentation/index.rst b/Documentation/index.rst index 1988c19d9daf..5a5acac985f3 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -137,7 +137,6 @@ needed). misc-devices/index scheduler/index mhi/index - tty/index peci/index Architecture-agnostic documentation diff --git a/Documentation/tty/index.rst b/Documentation/tty/index.rst deleted file mode 100644 index 21ea0cb21e55..000000000000 --- a/Documentation/tty/index.rst +++ /dev/null @@ -1,63 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -=== -TTY -=== - -Teletypewriter (TTY) layer takes care of all those serial devices. Including -the virtual ones like pseudoterminal (PTY). - -TTY structures -============== - -There are several major TTY structures. Every TTY device in a system has a -corresponding struct tty_port. These devices are maintained by a TTY driver -which is struct tty_driver. This structure describes the driver but also -contains a reference to operations which could be performed on the TTYs. It is -struct tty_operations. Then, upon open, a struct tty_struct is allocated and -lives until the final close. During this time, several callbacks from struct -tty_operations are invoked by the TTY layer. - -Every character received by the kernel (both from devices and users) is passed -through a preselected :doc:`tty_ldisc` (in -short ldisc; in C, struct tty_ldisc_ops). Its task is to transform characters -as defined by a particular ldisc or by user too. The default one is n_tty, -implementing echoes, signal handling, jobs control, special characters -processing, and more. The transformed characters are passed further to -user/device, depending on the source. - -In-detail description of the named TTY structures is in separate documents: - -.. toctree:: - :maxdepth: 2 - - tty_driver - tty_port - tty_struct - tty_ldisc - tty_buffer - n_tty - tty_internals - -Writing TTY Driver -================== - -Before one starts writing a TTY driver, they must consider -:doc:`Serial <../driver-api/serial/driver>` and :doc:`USB Serial -<../usb/usb-serial>` layers -first. Drivers for serial devices can often use one of these specific layers to -implement a serial driver. Only special devices should be handled directly by -the TTY Layer. If you are about to write such a driver, read on. - -A *typical* sequence a TTY driver performs is as follows: - -#. Allocate and register a TTY driver (module init) -#. Create and register TTY devices as they are probed (probe function) -#. Handle TTY operations and events like interrupts (TTY core invokes the - former, the device the latter) -#. Remove devices as they are going away (remove function) -#. Unregister and free the TTY driver (module exit) - -Steps regarding driver, i.e. 1., 3., and 5. are described in detail in -:doc:`tty_driver`. For the other two (devices handling), look into -:doc:`tty_port`. diff --git a/Documentation/tty/n_tty.rst b/Documentation/tty/n_tty.rst deleted file mode 100644 index 15b70faee72d..000000000000 --- a/Documentation/tty/n_tty.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -===== -N_TTY -===== - -.. contents:: :local: - -The default (and fallback) :doc:`TTY line discipline `. It tries to -handle characters as per POSIX. - -External Functions -================== - -.. kernel-doc:: drivers/tty/n_tty.c - :export: - -Internal Functions -================== - -.. kernel-doc:: drivers/tty/n_tty.c - :internal: diff --git a/Documentation/tty/tty_buffer.rst b/Documentation/tty/tty_buffer.rst deleted file mode 100644 index a39d4781e0d2..000000000000 --- a/Documentation/tty/tty_buffer.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -========== -TTY Buffer -========== - -.. contents:: :local: - -Here, we document functions for taking care of tty buffer and their flipping. -Drivers are supposed to fill the buffer by one of those functions below and -then flip the buffer, so that the data are passed to :doc:`line discipline -` for further processing. - -Flip Buffer Management -====================== - -.. kernel-doc:: drivers/tty/tty_buffer.c - :identifiers: tty_prepare_flip_string tty_insert_flip_string_fixed_flag - tty_insert_flip_string_flags __tty_insert_flip_char - tty_flip_buffer_push tty_ldisc_receive_buf - ----- - -Other Functions -=============== - -.. kernel-doc:: drivers/tty/tty_buffer.c - :identifiers: tty_buffer_space_avail tty_buffer_set_limit - ----- - -Buffer Locking -============== - -These are used only in special circumstances. Avoid them. - -.. kernel-doc:: drivers/tty/tty_buffer.c - :identifiers: tty_buffer_lock_exclusive tty_buffer_unlock_exclusive - ----- - -Internal Functions -================== - -.. kernel-doc:: drivers/tty/tty_buffer.c - :internal: diff --git a/Documentation/tty/tty_driver.rst b/Documentation/tty/tty_driver.rst deleted file mode 100644 index cc529f863406..000000000000 --- a/Documentation/tty/tty_driver.rst +++ /dev/null @@ -1,128 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -============================= -TTY Driver and TTY Operations -============================= - -.. contents:: :local: - -Allocation -========== - -The first thing a driver needs to do is to allocate a struct tty_driver. This -is done by tty_alloc_driver() (or __tty_alloc_driver()). Next, the newly -allocated structure is filled with information. See `TTY Driver Reference`_ at -the end of this document on what actually shall be filled in. - -The allocation routines expect a number of devices the driver can handle at -most and flags. Flags are those starting ``TTY_DRIVER_`` listed and described -in `TTY Driver Flags`_ below. - -When the driver is about to be freed, tty_driver_kref_put() is called on that. -It will decrements the reference count and if it reaches zero, the driver is -freed. - -For reference, both allocation and deallocation functions are explained here in -detail: - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: __tty_alloc_driver tty_driver_kref_put - -TTY Driver Flags ----------------- - -Here comes the documentation of flags accepted by tty_alloc_driver() (or -__tty_alloc_driver()): - -.. kernel-doc:: include/linux/tty_driver.h - :doc: TTY Driver Flags - ----- - -Registration -============ - -When a struct tty_driver is allocated and filled in, it can be registered using -tty_register_driver(). It is recommended to pass ``TTY_DRIVER_DYNAMIC_DEV`` in -flags of tty_alloc_driver(). If it is not passed, *all* devices are also -registered during tty_register_driver() and the following paragraph of -registering devices can be skipped for such drivers. However, the struct -tty_port part in `Registering Devices`_ is still relevant there. - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_register_driver tty_unregister_driver - -Registering Devices -------------------- - -Every TTY device shall be backed by a struct tty_port. Usually, TTY drivers -embed tty_port into device's private structures. Further details about handling -tty_port can be found in :doc:`tty_port`. The driver is also recommended to use -tty_port's reference counting by tty_port_get() and tty_port_put(). The final -put is supposed to free the tty_port including the device's private struct. - -Unless ``TTY_DRIVER_DYNAMIC_DEV`` was passed as flags to tty_alloc_driver(), -TTY driver is supposed to register every device discovered in the system -(the latter is preferred). This is performed by tty_register_device(). Or by -tty_register_device_attr() if the driver wants to expose some information -through struct attribute_group. Both of them register ``index``'th device and -upon return, the device can be opened. There are also preferred tty_port -variants described in `Linking Devices to Ports`_ later. It is up to driver to -manage free indices and choosing the right one. The TTY layer only refuses to -register more devices than passed to tty_alloc_driver(). - -When the device is opened, the TTY layer allocates struct tty_struct and starts -calling operations from :c:member:`tty_driver.ops`, see `TTY Operations -Reference`_. - -The registration routines are documented as follows: - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_register_device tty_register_device_attr - tty_unregister_device - ----- - -Linking Devices to Ports ------------------------- -As stated earlier, every TTY device shall have a struct tty_port assigned to -it. It must be known to the TTY layer at :c:member:`tty_driver.ops.install()` -at latest. There are few helpers to *link* the two. Ideally, the driver uses -tty_port_register_device() or tty_port_register_device_attr() instead of -tty_register_device() and tty_register_device_attr() at the registration time. -This way, the driver needs not care about linking later on. - -If that is not possible, the driver still can link the tty_port to a specific -index *before* the actual registration by tty_port_link_device(). If it still -does not fit, tty_port_install() can be used from the -:c:member:`tty_driver.ops.install` hook as a last resort. The last one is -dedicated mostly for in-memory devices like PTY where tty_ports are allocated -on demand. - -The linking routines are documented here: - -.. kernel-doc:: drivers/tty/tty_port.c - :identifiers: tty_port_link_device tty_port_register_device - tty_port_register_device_attr - ----- - -TTY Driver Reference -==================== - -All members of struct tty_driver are documented here. The required members are -noted at the end. struct tty_operations are documented next. - -.. kernel-doc:: include/linux/tty_driver.h - :identifiers: tty_driver - ----- - -TTY Operations Reference -======================== - -When a TTY is registered, these driver hooks can be invoked by the TTY layer: - -.. kernel-doc:: include/linux/tty_driver.h - :identifiers: tty_operations - diff --git a/Documentation/tty/tty_internals.rst b/Documentation/tty/tty_internals.rst deleted file mode 100644 index d0d415820300..000000000000 --- a/Documentation/tty/tty_internals.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -============= -TTY Internals -============= - -.. contents:: :local: - -Kopen -===== - -These functions serve for opening a TTY from the kernelspace: - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_kopen_exclusive tty_kopen_shared tty_kclose - ----- - -Exported Internal Functions -=========================== - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_release_struct tty_dev_name_to_number tty_get_icount - ----- - -Internal Functions -================== - -.. kernel-doc:: drivers/tty/tty_io.c - :internal: diff --git a/Documentation/tty/tty_ldisc.rst b/Documentation/tty/tty_ldisc.rst deleted file mode 100644 index 5144751be804..000000000000 --- a/Documentation/tty/tty_ldisc.rst +++ /dev/null @@ -1,85 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -=================== -TTY Line Discipline -=================== - -.. contents:: :local: - -TTY line discipline process all incoming and outgoing character from/to a tty -device. The default line discipline is :doc:`N_TTY `. It is also a -fallback if establishing any other discipline for a tty fails. If even N_TTY -fails, N_NULL takes over. That never fails, but also does not process any -characters -- it throws them away. - -Registration -============ - -Line disciplines are registered with tty_register_ldisc() passing the ldisc -structure. At the point of registration the discipline must be ready to use and -it is possible it will get used before the call returns success. If the call -returns an error then it won’t get called. Do not re-use ldisc numbers as they -are part of the userspace ABI and writing over an existing ldisc will cause -demons to eat your computer. You must not re-register over the top of the line -discipline even with the same data or your computer again will be eaten by -demons. In order to remove a line discipline call tty_unregister_ldisc(). - -Heed this warning: the reference count field of the registered copies of the -tty_ldisc structure in the ldisc table counts the number of lines using this -discipline. The reference count of the tty_ldisc structure within a tty counts -the number of active users of the ldisc at this instant. In effect it counts -the number of threads of execution within an ldisc method (plus those about to -enter and exit although this detail matters not). - -.. kernel-doc:: drivers/tty/tty_ldisc.c - :identifiers: tty_register_ldisc tty_unregister_ldisc - -Other Functions -=============== - -.. kernel-doc:: drivers/tty/tty_ldisc.c - :identifiers: tty_set_ldisc tty_ldisc_flush - -Line Discipline Operations Reference -==================================== - -.. kernel-doc:: include/linux/tty_ldisc.h - :identifiers: tty_ldisc_ops - -Driver Access -============= - -Line discipline methods can call the methods of the underlying hardware driver. -These are documented as a part of struct tty_operations. - -TTY Flags -========= - -Line discipline methods have access to :c:member:`tty_struct.flags` field. See -:doc:`tty_struct`. - -Locking -======= - -Callers to the line discipline functions from the tty layer are required to -take line discipline locks. The same is true of calls from the driver side -but not yet enforced. - -.. kernel-doc:: drivers/tty/tty_ldisc.c - :identifiers: tty_ldisc_ref_wait tty_ldisc_ref tty_ldisc_deref - -While these functions are slightly slower than the old code they should have -minimal impact as most receive logic uses the flip buffers and they only -need to take a reference when they push bits up through the driver. - -A caution: The :c:member:`tty_ldisc_ops.open()`, -:c:member:`tty_ldisc_ops.close()` and :c:member:`tty_driver.set_ldisc()` -functions are called with the ldisc unavailable. Thus tty_ldisc_ref() will fail -in this situation if used within these functions. Ldisc and driver code -calling its own functions must be careful in this case. - -Internal Functions -================== - -.. kernel-doc:: drivers/tty/tty_ldisc.c - :internal: diff --git a/Documentation/tty/tty_port.rst b/Documentation/tty/tty_port.rst deleted file mode 100644 index 5cb90e954fcf..000000000000 --- a/Documentation/tty/tty_port.rst +++ /dev/null @@ -1,70 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -======== -TTY Port -======== - -.. contents:: :local: - -The TTY drivers are advised to use struct tty_port helpers as much as possible. -If the drivers implement :c:member:`tty_port.ops.activate()` and -:c:member:`tty_port.ops.shutdown()`, they can use tty_port_open(), -tty_port_close(), and tty_port_hangup() in respective -:c:member:`tty_struct.ops` hooks. - -The reference and details are contained in the `TTY Port Reference`_ and `TTY -Port Operations Reference`_ sections at the bottom. - -TTY Port Functions -================== - -Init & Destroy --------------- - -.. kernel-doc:: drivers/tty/tty_port.c - :identifiers: tty_port_init tty_port_destroy - tty_port_get tty_port_put - -Open/Close/Hangup Helpers -------------------------- - -.. kernel-doc:: drivers/tty/tty_port.c - :identifiers: tty_port_install tty_port_open tty_port_block_til_ready - tty_port_close tty_port_close_start tty_port_close_end tty_port_hangup - tty_port_shutdown - -TTY Refcounting ---------------- - -.. kernel-doc:: drivers/tty/tty_port.c - :identifiers: tty_port_tty_get tty_port_tty_set - -TTY Helpers ------------ - -.. kernel-doc:: drivers/tty/tty_port.c - :identifiers: tty_port_tty_hangup tty_port_tty_wakeup - - -Modem Signals -------------- - -.. kernel-doc:: drivers/tty/tty_port.c - :identifiers: tty_port_carrier_raised tty_port_raise_dtr_rts - tty_port_lower_dtr_rts - ----- - -TTY Port Reference -================== - -.. kernel-doc:: include/linux/tty_port.h - :identifiers: tty_port - ----- - -TTY Port Operations Reference -============================= - -.. kernel-doc:: include/linux/tty_port.h - :identifiers: tty_port_operations diff --git a/Documentation/tty/tty_struct.rst b/Documentation/tty/tty_struct.rst deleted file mode 100644 index c72f5a4293b2..000000000000 --- a/Documentation/tty/tty_struct.rst +++ /dev/null @@ -1,81 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -========== -TTY Struct -========== - -.. contents:: :local: - -struct tty_struct is allocated by the TTY layer upon the first open of the TTY -device and released after the last close. The TTY layer passes this structure -to most of struct tty_operation's hooks. Members of tty_struct are documented -in `TTY Struct Reference`_ at the bottom. - -Initialization -============== - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_init_termios - -Name -==== - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_name - -Reference counting -================== - -.. kernel-doc:: include/linux/tty.h - :identifiers: tty_kref_get - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_kref_put - -Install -======= - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_standard_install - -Read & Write -============ - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_put_char - -Start & Stop -============ - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: start_tty stop_tty - -Wakeup -====== - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_wakeup - -Hangup -====== - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_hangup tty_vhangup tty_hung_up_p - -Misc -==== - -.. kernel-doc:: drivers/tty/tty_io.c - :identifiers: tty_do_resize - -TTY Struct Flags -================ - -.. kernel-doc:: include/linux/tty.h - :doc: TTY Struct Flags - -TTY Struct Reference -==================== - -.. kernel-doc:: include/linux/tty.h - :identifiers: tty_struct -- cgit v1.2.3 From 1a4a8f6bbac07e3270805009c69e89c7de801df1 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Apr 2022 13:01:39 +0200 Subject: Documentation: tty: introduce "Other Documentation" So far only n_tty belongs here, but in the next patches, more will come. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220411110143.10019-3-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/tty/index.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/driver-api/tty/index.rst b/Documentation/driver-api/tty/index.rst index 2240e52203d6..e6a7f717a9a5 100644 --- a/Documentation/driver-api/tty/index.rst +++ b/Documentation/driver-api/tty/index.rst @@ -36,7 +36,6 @@ In-detail description of the named TTY structures is in separate documents: tty_struct tty_ldisc tty_buffer - n_tty tty_internals Writing TTY Driver @@ -60,3 +59,13 @@ A *typical* sequence a TTY driver performs is as follows: Steps regarding driver, i.e. 1., 3., and 5. are described in detail in :doc:`tty_driver`. For the other two (devices handling), look into :doc:`tty_port`. + +Other Documentation +=================== + +Miscellaneous documentation can be further found in these documents: + +.. toctree:: + :maxdepth: 2 + + n_tty -- cgit v1.2.3 From e26595034dada8a1e6c10f0e0187f43edec72698 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Apr 2022 13:01:40 +0200 Subject: Documentation: tty: move n_gsm to tty We have n_tty documented in Documentation/driver-api/tty/. n_gsm belongs there too, so move from serial/ to tty/ too. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220411110143.10019-4-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/index.rst | 1 - Documentation/driver-api/serial/n_gsm.rst | 159 ------------------------------ Documentation/driver-api/tty/index.rst | 1 + Documentation/driver-api/tty/n_gsm.rst | 159 ++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+), 160 deletions(-) delete mode 100644 Documentation/driver-api/serial/n_gsm.rst create mode 100644 Documentation/driver-api/tty/n_gsm.rst (limited to 'Documentation') diff --git a/Documentation/driver-api/serial/index.rst b/Documentation/driver-api/serial/index.rst index 7eb21a695fc3..4ebdb86cd6b6 100644 --- a/Documentation/driver-api/serial/index.rst +++ b/Documentation/driver-api/serial/index.rst @@ -17,7 +17,6 @@ Serial drivers :maxdepth: 1 moxa-smartio - n_gsm serial-iso7816 serial-rs485 diff --git a/Documentation/driver-api/serial/n_gsm.rst b/Documentation/driver-api/serial/n_gsm.rst deleted file mode 100644 index 49956509ad73..000000000000 --- a/Documentation/driver-api/serial/n_gsm.rst +++ /dev/null @@ -1,159 +0,0 @@ -============================== -GSM 0710 tty multiplexor HOWTO -============================== - -This line discipline implements the GSM 07.10 multiplexing protocol -detailed in the following 3GPP document: - - https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip - -This document give some hints on how to use this driver with GPRS and 3G -modems connected to a physical serial port. - -How to use it -------------- -1. config initiator -^^^^^^^^^^^^^^^^^^^^^ - -1.1 initialize the modem in 0710 mux mode (usually AT+CMUX= command) through - its serial port. Depending on the modem used, you can pass more or less - parameters to this command. - -1.2 switch the serial line to using the n_gsm line discipline by using - TIOCSETD ioctl. - -1.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. - -1.4 obtain base gsmtty number for the used serial port. - -Major parts of the initialization program : -(a good starting point is util-linux-ng/sys-utils/ldattach.c):: - - #include - #include - #include - #include - #define DEFAULT_SPEED B115200 - #define SERIAL_PORT /dev/ttyS0 - - int ldisc = N_GSM0710; - struct gsm_config c; - struct termios configuration; - uint32_t first; - - /* open the serial port connected to the modem */ - fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); - - /* configure the serial port : speed, flow control ... */ - - /* send the AT commands to switch the modem to CMUX mode - and check that it's successful (should return OK) */ - write(fd, "AT+CMUX=0\r", 10); - - /* experience showed that some modems need some time before - being able to answer to the first MUX packet so a delay - may be needed here in some case */ - sleep(3); - - /* use n_gsm line discipline */ - ioctl(fd, TIOCSETD, &ldisc); - - /* get n_gsm configuration */ - ioctl(fd, GSMIOC_GETCONF, &c); - /* we are initiator and need encoding 0 (basic) */ - c.initiator = 1; - c.encapsulation = 0; - /* our modem defaults to a maximum size of 127 bytes */ - c.mru = 127; - c.mtu = 127; - /* set the new configuration */ - ioctl(fd, GSMIOC_SETCONF, &c); - /* get first gsmtty device node */ - ioctl(fd, GSMIOC_GETFIRST, &first); - printf("first muxed line: /dev/gsmtty%i\n", first); - - /* and wait for ever to keep the line discipline enabled */ - daemon(0,0); - pause(); - -1.5 use these devices as plain serial ports. - - for example, it's possible: - - - and to use gnokii to send / receive SMS on ttygsm1 - - to use ppp to establish a datalink on ttygsm2 - -1.6 first close all virtual ports before closing the physical port. - - Note that after closing the physical port the modem is still in multiplexing - mode. This may prevent a successful re-opening of the port later. To avoid - this situation either reset the modem if your hardware allows that or send - a disconnect command frame manually before initializing the multiplexing mode - for the second time. The byte sequence for the disconnect command frame is:: - - 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9. - -2. config requester -^^^^^^^^^^^^^^^^^^^^^ - -2.1 receive string "AT+CMUX= command" through its serial port,initialize - mux mode config - -2.2 switch the serial line to using the n_gsm line discipline by using - TIOCSETD ioctl. - -2.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. - -2.4 obtain base gsmtty number for the used serial port:: - - #include - #include - #include - #include - #define DEFAULT_SPEED B115200 - #define SERIAL_PORT /dev/ttyS0 - - int ldisc = N_GSM0710; - struct gsm_config c; - struct termios configuration; - uint32_t first; - - /* open the serial port */ - fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); - - /* configure the serial port : speed, flow control ... */ - - /* get serial data and check "AT+CMUX=command" parameter ... */ - - /* use n_gsm line discipline */ - ioctl(fd, TIOCSETD, &ldisc); - - /* get n_gsm configuration */ - ioctl(fd, GSMIOC_GETCONF, &c); - /* we are requester and need encoding 0 (basic) */ - c.initiator = 0; - c.encapsulation = 0; - /* our modem defaults to a maximum size of 127 bytes */ - c.mru = 127; - c.mtu = 127; - /* set the new configuration */ - ioctl(fd, GSMIOC_SETCONF, &c); - /* get first gsmtty device node */ - ioctl(fd, GSMIOC_GETFIRST, &first); - printf("first muxed line: /dev/gsmtty%i\n", first); - - /* and wait for ever to keep the line discipline enabled */ - daemon(0,0); - pause(); - -Additional Documentation ------------------------- -More practical details on the protocol and how it's supported by industrial -modems can be found in the following documents : - -- http://www.telit.com/module/infopool/download.php?id=616 -- http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf -- http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx -- http://wm.sim.com/sim/News/photo/2010721161442.pdf - -11-03-08 - Eric Bénard - diff --git a/Documentation/driver-api/tty/index.rst b/Documentation/driver-api/tty/index.rst index e6a7f717a9a5..85eaac76a971 100644 --- a/Documentation/driver-api/tty/index.rst +++ b/Documentation/driver-api/tty/index.rst @@ -68,4 +68,5 @@ Miscellaneous documentation can be further found in these documents: .. toctree:: :maxdepth: 2 + n_gsm n_tty diff --git a/Documentation/driver-api/tty/n_gsm.rst b/Documentation/driver-api/tty/n_gsm.rst new file mode 100644 index 000000000000..49956509ad73 --- /dev/null +++ b/Documentation/driver-api/tty/n_gsm.rst @@ -0,0 +1,159 @@ +============================== +GSM 0710 tty multiplexor HOWTO +============================== + +This line discipline implements the GSM 07.10 multiplexing protocol +detailed in the following 3GPP document: + + https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip + +This document give some hints on how to use this driver with GPRS and 3G +modems connected to a physical serial port. + +How to use it +------------- +1. config initiator +^^^^^^^^^^^^^^^^^^^^^ + +1.1 initialize the modem in 0710 mux mode (usually AT+CMUX= command) through + its serial port. Depending on the modem used, you can pass more or less + parameters to this command. + +1.2 switch the serial line to using the n_gsm line discipline by using + TIOCSETD ioctl. + +1.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. + +1.4 obtain base gsmtty number for the used serial port. + +Major parts of the initialization program : +(a good starting point is util-linux-ng/sys-utils/ldattach.c):: + + #include + #include + #include + #include + #define DEFAULT_SPEED B115200 + #define SERIAL_PORT /dev/ttyS0 + + int ldisc = N_GSM0710; + struct gsm_config c; + struct termios configuration; + uint32_t first; + + /* open the serial port connected to the modem */ + fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); + + /* configure the serial port : speed, flow control ... */ + + /* send the AT commands to switch the modem to CMUX mode + and check that it's successful (should return OK) */ + write(fd, "AT+CMUX=0\r", 10); + + /* experience showed that some modems need some time before + being able to answer to the first MUX packet so a delay + may be needed here in some case */ + sleep(3); + + /* use n_gsm line discipline */ + ioctl(fd, TIOCSETD, &ldisc); + + /* get n_gsm configuration */ + ioctl(fd, GSMIOC_GETCONF, &c); + /* we are initiator and need encoding 0 (basic) */ + c.initiator = 1; + c.encapsulation = 0; + /* our modem defaults to a maximum size of 127 bytes */ + c.mru = 127; + c.mtu = 127; + /* set the new configuration */ + ioctl(fd, GSMIOC_SETCONF, &c); + /* get first gsmtty device node */ + ioctl(fd, GSMIOC_GETFIRST, &first); + printf("first muxed line: /dev/gsmtty%i\n", first); + + /* and wait for ever to keep the line discipline enabled */ + daemon(0,0); + pause(); + +1.5 use these devices as plain serial ports. + + for example, it's possible: + + - and to use gnokii to send / receive SMS on ttygsm1 + - to use ppp to establish a datalink on ttygsm2 + +1.6 first close all virtual ports before closing the physical port. + + Note that after closing the physical port the modem is still in multiplexing + mode. This may prevent a successful re-opening of the port later. To avoid + this situation either reset the modem if your hardware allows that or send + a disconnect command frame manually before initializing the multiplexing mode + for the second time. The byte sequence for the disconnect command frame is:: + + 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9. + +2. config requester +^^^^^^^^^^^^^^^^^^^^^ + +2.1 receive string "AT+CMUX= command" through its serial port,initialize + mux mode config + +2.2 switch the serial line to using the n_gsm line discipline by using + TIOCSETD ioctl. + +2.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. + +2.4 obtain base gsmtty number for the used serial port:: + + #include + #include + #include + #include + #define DEFAULT_SPEED B115200 + #define SERIAL_PORT /dev/ttyS0 + + int ldisc = N_GSM0710; + struct gsm_config c; + struct termios configuration; + uint32_t first; + + /* open the serial port */ + fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); + + /* configure the serial port : speed, flow control ... */ + + /* get serial data and check "AT+CMUX=command" parameter ... */ + + /* use n_gsm line discipline */ + ioctl(fd, TIOCSETD, &ldisc); + + /* get n_gsm configuration */ + ioctl(fd, GSMIOC_GETCONF, &c); + /* we are requester and need encoding 0 (basic) */ + c.initiator = 0; + c.encapsulation = 0; + /* our modem defaults to a maximum size of 127 bytes */ + c.mru = 127; + c.mtu = 127; + /* set the new configuration */ + ioctl(fd, GSMIOC_SETCONF, &c); + /* get first gsmtty device node */ + ioctl(fd, GSMIOC_GETFIRST, &first); + printf("first muxed line: /dev/gsmtty%i\n", first); + + /* and wait for ever to keep the line discipline enabled */ + daemon(0,0); + pause(); + +Additional Documentation +------------------------ +More practical details on the protocol and how it's supported by industrial +modems can be found in the following documents : + +- http://www.telit.com/module/infopool/download.php?id=616 +- http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf +- http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx +- http://wm.sim.com/sim/News/photo/2010721161442.pdf + +11-03-08 - Eric Bénard - -- cgit v1.2.3 From 5b437ae9fcbb22fe6de3c715534515209207a092 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Apr 2022 13:01:41 +0200 Subject: Documentation: tty: move moxa-smartio.rst to tty It is a tty_driver, not serial -- uart_driver. So move it to the tty docs dir too. (The same as the driver itself.) Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220411110143.10019-5-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/serial/index.rst | 1 - Documentation/driver-api/serial/moxa-smartio.rst | 197 ----------------------- Documentation/driver-api/tty/index.rst | 1 + Documentation/driver-api/tty/moxa-smartio.rst | 197 +++++++++++++++++++++++ 4 files changed, 198 insertions(+), 198 deletions(-) delete mode 100644 Documentation/driver-api/serial/moxa-smartio.rst create mode 100644 Documentation/driver-api/tty/moxa-smartio.rst (limited to 'Documentation') diff --git a/Documentation/driver-api/serial/index.rst b/Documentation/driver-api/serial/index.rst index 4ebdb86cd6b6..03a55b987a1d 100644 --- a/Documentation/driver-api/serial/index.rst +++ b/Documentation/driver-api/serial/index.rst @@ -16,7 +16,6 @@ Serial drivers .. toctree:: :maxdepth: 1 - moxa-smartio serial-iso7816 serial-rs485 diff --git a/Documentation/driver-api/serial/moxa-smartio.rst b/Documentation/driver-api/serial/moxa-smartio.rst deleted file mode 100644 index af25bc5cc3e6..000000000000 --- a/Documentation/driver-api/serial/moxa-smartio.rst +++ /dev/null @@ -1,197 +0,0 @@ -============================================================= -MOXA Smartio/Industio Family Device Driver Installation Guide -============================================================= - -Copyright (C) 2008, Moxa Inc. -Copyright (C) 2021, Jiri Slaby - -.. Content - - 1. Introduction - 2. System Requirement - 3. Installation - 3.1 Hardware installation - 3.2 Device naming convention - 4. Utilities - 5. Setserial - 6. Troubleshooting - -1. Introduction -^^^^^^^^^^^^^^^ - - The Smartio/Industio/UPCI family Linux driver supports following multiport - boards: - - - 2 ports multiport board - CP-102U, CP-102UL, CP-102UF - CP-132U-I, CP-132UL, - CP-132, CP-132I, CP132S, CP-132IS, - (CP-102, CP-102S) - - - 4 ports multiport board - CP-104EL, - CP-104UL, CP-104JU, - CP-134U, CP-134U-I, - C104H/PCI, C104HS/PCI, - CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL, - (C114HI, CT-114I), - POS-104UL, - CB-114, - CB-134I - - - 8 ports multiport board - CP-118EL, CP-168EL, - CP-118U, CP-168U, - C168H/PCI, - CB-108 - - If a compatibility problem occurs, please contact Moxa at - support@moxa.com.tw. - - In addition to device driver, useful utilities are also provided in this - version. They are: - - - msdiag - Diagnostic program for displaying installed Moxa - Smartio/Industio boards. - - msmon - Monitor program to observe data count and line status signals. - - msterm A simple terminal program which is useful in testing serial - ports. - - All the drivers and utilities are published in form of source code under - GNU General Public License in this version. Please refer to GNU General - Public License announcement in each source code file for more detail. - - In Moxa's Web sites, you may always find the latest driver at - https://www.moxa.com/. - - This version of driver can be installed as a Loadable Module (Module driver) - or built-in into kernel (Static driver). Before you install the driver, - please refer to hardware installation procedure in the User's Manual. - - We assume the user should be familiar with following documents: - - - Serial-HOWTO - - Kernel-HOWTO - -2. System Requirement -^^^^^^^^^^^^^^^^^^^^^ - - - Maximum 4 boards can be installed in combination - -3. Installation -^^^^^^^^^^^^^^^ - -3.1 Hardware installation -========================= - -PCI/UPCI board --------------- - - You may need to adjust IRQ usage in BIOS to avoid IRQ conflict with other - ISA devices. Please refer to hardware installation procedure in User's - Manual in advance. - -PCI IRQ Sharing ---------------- - - Each port within the same multiport board shares the same IRQ. Up to - 4 Moxa Smartio/Industio PCI Family multiport boards can be installed - together on one system and they can share the same IRQ. - - - -3.2 Device naming convention -============================ - - The device node is named "ttyMxx". - -Device naming when more than 2 boards installed ------------------------------------------------ - - Naming convention for each Smartio/Industio multiport board is - pre-defined as below. - - ============ =============== - Board Num. Device node - 1st board ttyM0 - ttyM7 - 2nd board ttyM8 - ttyM15 - 3rd board ttyM16 - ttyM23 - 4th board ttyM24 - ttyM31 - ============ =============== - -4. Utilities -^^^^^^^^^^^^ - - There are 3 utilities contained in this driver. They are msdiag, msmon and - msterm. These 3 utilities are released in form of source code. They should - be compiled into executable file and copied into /usr/bin. - -msdiag - Diagnostic -=================== - - This utility provides the function to display what Moxa Smartio/Industio - board was found by the driver in the system. - -msmon - Port Monitoring -======================= - - This utility gives the user a quick view about all the MOXA ports' - activities. One can easily learn each port's total received/transmitted - (Rx/Tx) character count since the time when the monitoring is started. - - Rx/Tx throughputs per second are also reported in interval basis (e.g. - the last 5 seconds) and in average basis (since the time the monitoring - is started). You can reset all ports' count by key. <+> <-> - (plus/minus) keys to change the displaying time interval. Press - on the port, that cursor stay, to view the port's communication - parameters, signal status, and input/output queue. - -msterm - Terminal Emulation -=========================== - - This utility provides data sending and receiving ability of all tty ports, - especially for MOXA ports. It is quite useful for testing simple - application, for example, sending AT command to a modem connected to the - port or used as a terminal for login purpose. Note that this is only a - dumb terminal emulation without handling full screen operation. - -5. Setserial -^^^^^^^^^^^^ - - Supported Setserial parameters are listed as below. - - ============== ============================================================= - uart set UART type(16450 --> disable FIFO, 16550A --> enable FIFO) - close_delay set the amount of time (in 1/100 of a second) that DTR - should be kept low while being closed. - closing_wait set the amount of time (in 1/100 of a second) that the - serial port should wait for data to be drained while - being closed, before the receiver is disabled. - spd_hi Use 57.6kb when the application requests 38.4kb. - spd_vhi Use 115.2kb when the application requests 38.4kb. - spd_shi Use 230.4kb when the application requests 38.4kb. - spd_warp Use 460.8kb when the application requests 38.4kb. - spd_normal Use 38.4kb when the application requests 38.4kb. - spd_cust Use the custom divisor to set the speed when the - application requests 38.4kb. - divisor This option sets the custom division. - baud_base This option sets the base baud rate. - ============== ============================================================= - -6. Troubleshooting -^^^^^^^^^^^^^^^^^^ - - The boot time error messages and solutions are stated as clearly as - possible. If all the possible solutions fail, please contact our technical - support team to get more help. - - - Error msg: - More than 4 Moxa Smartio/Industio family boards found. Fifth board - and after are ignored. - - Solution: - To avoid this problem, please unplug fifth and after board, because Moxa - driver supports up to 4 boards. diff --git a/Documentation/driver-api/tty/index.rst b/Documentation/driver-api/tty/index.rst index 85eaac76a971..2d32606a4278 100644 --- a/Documentation/driver-api/tty/index.rst +++ b/Documentation/driver-api/tty/index.rst @@ -68,5 +68,6 @@ Miscellaneous documentation can be further found in these documents: .. toctree:: :maxdepth: 2 + moxa-smartio n_gsm n_tty diff --git a/Documentation/driver-api/tty/moxa-smartio.rst b/Documentation/driver-api/tty/moxa-smartio.rst new file mode 100644 index 000000000000..af25bc5cc3e6 --- /dev/null +++ b/Documentation/driver-api/tty/moxa-smartio.rst @@ -0,0 +1,197 @@ +============================================================= +MOXA Smartio/Industio Family Device Driver Installation Guide +============================================================= + +Copyright (C) 2008, Moxa Inc. +Copyright (C) 2021, Jiri Slaby + +.. Content + + 1. Introduction + 2. System Requirement + 3. Installation + 3.1 Hardware installation + 3.2 Device naming convention + 4. Utilities + 5. Setserial + 6. Troubleshooting + +1. Introduction +^^^^^^^^^^^^^^^ + + The Smartio/Industio/UPCI family Linux driver supports following multiport + boards: + + - 2 ports multiport board + CP-102U, CP-102UL, CP-102UF + CP-132U-I, CP-132UL, + CP-132, CP-132I, CP132S, CP-132IS, + (CP-102, CP-102S) + + - 4 ports multiport board + CP-104EL, + CP-104UL, CP-104JU, + CP-134U, CP-134U-I, + C104H/PCI, C104HS/PCI, + CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL, + (C114HI, CT-114I), + POS-104UL, + CB-114, + CB-134I + + - 8 ports multiport board + CP-118EL, CP-168EL, + CP-118U, CP-168U, + C168H/PCI, + CB-108 + + If a compatibility problem occurs, please contact Moxa at + support@moxa.com.tw. + + In addition to device driver, useful utilities are also provided in this + version. They are: + + - msdiag + Diagnostic program for displaying installed Moxa + Smartio/Industio boards. + - msmon + Monitor program to observe data count and line status signals. + - msterm A simple terminal program which is useful in testing serial + ports. + + All the drivers and utilities are published in form of source code under + GNU General Public License in this version. Please refer to GNU General + Public License announcement in each source code file for more detail. + + In Moxa's Web sites, you may always find the latest driver at + https://www.moxa.com/. + + This version of driver can be installed as a Loadable Module (Module driver) + or built-in into kernel (Static driver). Before you install the driver, + please refer to hardware installation procedure in the User's Manual. + + We assume the user should be familiar with following documents: + + - Serial-HOWTO + - Kernel-HOWTO + +2. System Requirement +^^^^^^^^^^^^^^^^^^^^^ + + - Maximum 4 boards can be installed in combination + +3. Installation +^^^^^^^^^^^^^^^ + +3.1 Hardware installation +========================= + +PCI/UPCI board +-------------- + + You may need to adjust IRQ usage in BIOS to avoid IRQ conflict with other + ISA devices. Please refer to hardware installation procedure in User's + Manual in advance. + +PCI IRQ Sharing +--------------- + + Each port within the same multiport board shares the same IRQ. Up to + 4 Moxa Smartio/Industio PCI Family multiport boards can be installed + together on one system and they can share the same IRQ. + + + +3.2 Device naming convention +============================ + + The device node is named "ttyMxx". + +Device naming when more than 2 boards installed +----------------------------------------------- + + Naming convention for each Smartio/Industio multiport board is + pre-defined as below. + + ============ =============== + Board Num. Device node + 1st board ttyM0 - ttyM7 + 2nd board ttyM8 - ttyM15 + 3rd board ttyM16 - ttyM23 + 4th board ttyM24 - ttyM31 + ============ =============== + +4. Utilities +^^^^^^^^^^^^ + + There are 3 utilities contained in this driver. They are msdiag, msmon and + msterm. These 3 utilities are released in form of source code. They should + be compiled into executable file and copied into /usr/bin. + +msdiag - Diagnostic +=================== + + This utility provides the function to display what Moxa Smartio/Industio + board was found by the driver in the system. + +msmon - Port Monitoring +======================= + + This utility gives the user a quick view about all the MOXA ports' + activities. One can easily learn each port's total received/transmitted + (Rx/Tx) character count since the time when the monitoring is started. + + Rx/Tx throughputs per second are also reported in interval basis (e.g. + the last 5 seconds) and in average basis (since the time the monitoring + is started). You can reset all ports' count by key. <+> <-> + (plus/minus) keys to change the displaying time interval. Press + on the port, that cursor stay, to view the port's communication + parameters, signal status, and input/output queue. + +msterm - Terminal Emulation +=========================== + + This utility provides data sending and receiving ability of all tty ports, + especially for MOXA ports. It is quite useful for testing simple + application, for example, sending AT command to a modem connected to the + port or used as a terminal for login purpose. Note that this is only a + dumb terminal emulation without handling full screen operation. + +5. Setserial +^^^^^^^^^^^^ + + Supported Setserial parameters are listed as below. + + ============== ============================================================= + uart set UART type(16450 --> disable FIFO, 16550A --> enable FIFO) + close_delay set the amount of time (in 1/100 of a second) that DTR + should be kept low while being closed. + closing_wait set the amount of time (in 1/100 of a second) that the + serial port should wait for data to be drained while + being closed, before the receiver is disabled. + spd_hi Use 57.6kb when the application requests 38.4kb. + spd_vhi Use 115.2kb when the application requests 38.4kb. + spd_shi Use 230.4kb when the application requests 38.4kb. + spd_warp Use 460.8kb when the application requests 38.4kb. + spd_normal Use 38.4kb when the application requests 38.4kb. + spd_cust Use the custom divisor to set the speed when the + application requests 38.4kb. + divisor This option sets the custom division. + baud_base This option sets the base baud rate. + ============== ============================================================= + +6. Troubleshooting +^^^^^^^^^^^^^^^^^^ + + The boot time error messages and solutions are stated as clearly as + possible. If all the possible solutions fail, please contact our technical + support team to get more help. + + + Error msg: + More than 4 Moxa Smartio/Industio family boards found. Fifth board + and after are ignored. + + Solution: + To avoid this problem, please unplug fifth and after board, because Moxa + driver supports up to 4 boards. -- cgit v1.2.3 From e937eb43b8791cd55bd518d1ffc747d3430d8ec9 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Apr 2022 13:01:42 +0200 Subject: Documentation: tty: n_gsm, delete "Additional Documentation" All of the URLs give 404. There is a little point to preserve them. If really need be, we could try archive.org if the documents are not there by a chance. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220411110143.10019-6-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/tty/n_gsm.rst | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/driver-api/tty/n_gsm.rst b/Documentation/driver-api/tty/n_gsm.rst index 49956509ad73..04308a7a194a 100644 --- a/Documentation/driver-api/tty/n_gsm.rst +++ b/Documentation/driver-api/tty/n_gsm.rst @@ -146,14 +146,4 @@ Major parts of the initialization program : daemon(0,0); pause(); -Additional Documentation ------------------------- -More practical details on the protocol and how it's supported by industrial -modems can be found in the following documents : - -- http://www.telit.com/module/infopool/download.php?id=616 -- http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf -- http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx -- http://wm.sim.com/sim/News/photo/2010721161442.pdf - 11-03-08 - Eric Bénard - -- cgit v1.2.3 From 7fb4028fbb97d6c71c30556e81eb8ce07eef7b8b Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Apr 2022 13:01:43 +0200 Subject: Documentation: tty: n_gsm, use power of ReST Reformat the whole document, so that automatic numbering and TOC is properly generated. Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220411110143.10019-7-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/tty/n_gsm.rst | 144 +++++++++++++++++---------------- 1 file changed, 74 insertions(+), 70 deletions(-) (limited to 'Documentation') diff --git a/Documentation/driver-api/tty/n_gsm.rst b/Documentation/driver-api/tty/n_gsm.rst index 04308a7a194a..35d7381515b0 100644 --- a/Documentation/driver-api/tty/n_gsm.rst +++ b/Documentation/driver-api/tty/n_gsm.rst @@ -2,6 +2,8 @@ GSM 0710 tty multiplexor HOWTO ============================== +.. contents:: :local: + This line discipline implements the GSM 07.10 multiplexing protocol detailed in the following 3GPP document: @@ -11,79 +13,81 @@ This document give some hints on how to use this driver with GPRS and 3G modems connected to a physical serial port. How to use it -------------- -1. config initiator -^^^^^^^^^^^^^^^^^^^^^ +============= -1.1 initialize the modem in 0710 mux mode (usually AT+CMUX= command) through - its serial port. Depending on the modem used, you can pass more or less - parameters to this command. +Config Initiator +---------------- -1.2 switch the serial line to using the n_gsm line discipline by using - TIOCSETD ioctl. +#. Initialize the modem in 0710 mux mode (usually ``AT+CMUX=`` command) through + its serial port. Depending on the modem used, you can pass more or less + parameters to this command. -1.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. +#. Switch the serial line to using the n_gsm line discipline by using + ``TIOCSETD`` ioctl. -1.4 obtain base gsmtty number for the used serial port. +#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. -Major parts of the initialization program : -(a good starting point is util-linux-ng/sys-utils/ldattach.c):: +#. Obtain base gsmtty number for the used serial port. - #include - #include - #include - #include - #define DEFAULT_SPEED B115200 - #define SERIAL_PORT /dev/ttyS0 + Major parts of the initialization program + (a good starting point is util-linux-ng/sys-utils/ldattach.c):: - int ldisc = N_GSM0710; - struct gsm_config c; - struct termios configuration; - uint32_t first; + #include + #include + #include + #include - /* open the serial port connected to the modem */ - fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); + #define DEFAULT_SPEED B115200 + #define SERIAL_PORT /dev/ttyS0 - /* configure the serial port : speed, flow control ... */ + int ldisc = N_GSM0710; + struct gsm_config c; + struct termios configuration; + uint32_t first; - /* send the AT commands to switch the modem to CMUX mode - and check that it's successful (should return OK) */ - write(fd, "AT+CMUX=0\r", 10); + /* open the serial port connected to the modem */ + fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY); - /* experience showed that some modems need some time before - being able to answer to the first MUX packet so a delay - may be needed here in some case */ - sleep(3); + /* configure the serial port : speed, flow control ... */ - /* use n_gsm line discipline */ - ioctl(fd, TIOCSETD, &ldisc); + /* send the AT commands to switch the modem to CMUX mode + and check that it's successful (should return OK) */ + write(fd, "AT+CMUX=0\r", 10); - /* get n_gsm configuration */ - ioctl(fd, GSMIOC_GETCONF, &c); - /* we are initiator and need encoding 0 (basic) */ - c.initiator = 1; - c.encapsulation = 0; - /* our modem defaults to a maximum size of 127 bytes */ - c.mru = 127; - c.mtu = 127; - /* set the new configuration */ - ioctl(fd, GSMIOC_SETCONF, &c); - /* get first gsmtty device node */ - ioctl(fd, GSMIOC_GETFIRST, &first); - printf("first muxed line: /dev/gsmtty%i\n", first); + /* experience showed that some modems need some time before + being able to answer to the first MUX packet so a delay + may be needed here in some case */ + sleep(3); - /* and wait for ever to keep the line discipline enabled */ - daemon(0,0); - pause(); + /* use n_gsm line discipline */ + ioctl(fd, TIOCSETD, &ldisc); + + /* get n_gsm configuration */ + ioctl(fd, GSMIOC_GETCONF, &c); + /* we are initiator and need encoding 0 (basic) */ + c.initiator = 1; + c.encapsulation = 0; + /* our modem defaults to a maximum size of 127 bytes */ + c.mru = 127; + c.mtu = 127; + /* set the new configuration */ + ioctl(fd, GSMIOC_SETCONF, &c); + /* get first gsmtty device node */ + ioctl(fd, GSMIOC_GETFIRST, &first); + printf("first muxed line: /dev/gsmtty%i\n", first); + + /* and wait for ever to keep the line discipline enabled */ + daemon(0,0); + pause(); -1.5 use these devices as plain serial ports. +#. Use these devices as plain serial ports. - for example, it's possible: + For example, it's possible: - - and to use gnokii to send / receive SMS on ttygsm1 - - to use ppp to establish a datalink on ttygsm2 + - to use *gnokii* to send / receive SMS on ``ttygsm1`` + - to use *ppp* to establish a datalink on ``ttygsm2`` -1.6 first close all virtual ports before closing the physical port. +#. First close all virtual ports before closing the physical port. Note that after closing the physical port the modem is still in multiplexing mode. This may prevent a successful re-opening of the port later. To avoid @@ -91,27 +95,27 @@ Major parts of the initialization program : a disconnect command frame manually before initializing the multiplexing mode for the second time. The byte sequence for the disconnect command frame is:: - 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9. + 0xf9, 0x03, 0xef, 0x03, 0xc3, 0x16, 0xf9 -2. config requester -^^^^^^^^^^^^^^^^^^^^^ +Config Requester +---------------- -2.1 receive string "AT+CMUX= command" through its serial port,initialize - mux mode config +#. Receive ``AT+CMUX=`` command through its serial port, initialize mux mode + config. -2.2 switch the serial line to using the n_gsm line discipline by using - TIOCSETD ioctl. +#. Switch the serial line to using the *n_gsm* line discipline by using + ``TIOCSETD`` ioctl. -2.3 configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl. +#. Configure the mux using ``GSMIOC_GETCONF``/``GSMIOC_SETCONF`` ioctl. -2.4 obtain base gsmtty number for the used serial port:: +#. Obtain base gsmtty number for the used serial port:: - #include - #include - #include - #include - #define DEFAULT_SPEED B115200 - #define SERIAL_PORT /dev/ttyS0 + #include + #include + #include + #include + #define DEFAULT_SPEED B115200 + #define SERIAL_PORT /dev/ttyS0 int ldisc = N_GSM0710; struct gsm_config c; -- cgit v1.2.3 From ef9a23f358383376009bac2a0262be1fff3eda70 Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Wed, 30 Mar 2022 14:15:37 +0900 Subject: dt-bindings: serial: uniphier: Use maxItems for a single clock 'maxItems' is preferred for a single entry, not 'minItems'. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1648617338-8600-2-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml index d490c7c4b967..06353028b274 100644 --- a/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml +++ b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml @@ -20,7 +20,7 @@ properties: maxItems: 1 clocks: - minItems: 1 + maxItems: 1 auto-flow-control: description: enable automatic flow control support. -- cgit v1.2.3 From e5fe471f7156c96a9da34b25f955dae5b0dfb46a Mon Sep 17 00:00:00 2001 From: Kunihiko Hayashi Date: Wed, 30 Mar 2022 14:15:38 +0900 Subject: dt-bindings: serial: uniphier: Add "resets" property as optional UniPhier UART controller has a reset lines from system controller. Add "resets" property to fix the following warning. uniphier-ld11-global.dtb: serial@54006800: 'resets' does not match any of the regexes: 'pinctrl-[0-9]+' From schema: Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml Reviewed-by: Krzysztof Kozlowski Signed-off-by: Kunihiko Hayashi Link: https://lore.kernel.org/r/1648617338-8600-3-git-send-email-hayashi.kunihiko@socionext.com Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml index 06353028b274..3d01cc355778 100644 --- a/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml +++ b/Documentation/devicetree/bindings/serial/socionext,uniphier-uart.yaml @@ -22,6 +22,9 @@ properties: clocks: maxItems: 1 + resets: + maxItems: 1 + auto-flow-control: description: enable automatic flow control support. $ref: /schemas/types.yaml#/definitions/flag -- cgit v1.2.3 From 77edd0de002813629bb3b6efd336a630fab68aa0 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Wed, 23 Mar 2022 17:36:59 +0800 Subject: dt-bindings: serial: fsl-lpuart: Add imx93 compatible string The lpuart on i.MX93 is derived from i.MX7ULP with some industrial enhancements, it uses two compatible strings, so update the compatible string for i.MX93. Acked-by: Rob Herring Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20220323093659.1722463-1-peng.fan@oss.nxp.com Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/fsl-lpuart.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml index ff364bd0fbac..30eaa62e1aed 100644 --- a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml +++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml @@ -23,7 +23,9 @@ properties: - fsl,imx8qxp-lpuart - fsl,imxrt1050-lpuart - items: - - const: fsl,imx8ulp-lpuart + - enum: + - fsl,imx93-lpuart + - fsl,imx8ulp-lpuart - const: fsl,imx7ulp-lpuart - items: - enum: -- cgit v1.2.3 From 7bb301812b62809903e07ceaf5c176f20798e3c6 Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Wed, 30 Mar 2022 16:40:13 +0100 Subject: dt-bindings: serial: renesas,em-uart: Document r9a09g011 bindings The Renesas RZ/V2M (r9a09g011) SoC uses a uart that is compatible with the EMMA Mobile SoC. Signed-off-by: Phil Edworthy Reviewed-by: Biju Das Link: https://lore.kernel.org/r/20220330154024.112270-3-phil.edworthy@renesas.com Acked-by: Rob Herring Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/renesas,em-uart.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml index e98ec48fee46..332c385618e1 100644 --- a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml +++ b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml @@ -14,7 +14,14 @@ allOf: properties: compatible: - const: renesas,em-uart + oneOf: + - items: + - enum: + - renesas,r9a09g011-uart # RZ/V2M + - const: renesas,em-uart # generic EMMA Mobile compatible UART + + - items: + - const: renesas,em-uart # generic EMMA Mobile compatible UART reg: maxItems: 1 -- cgit v1.2.3 From 19401e9755313ba681e9c8f41e8c176cd95663bb Mon Sep 17 00:00:00 2001 From: Kuldeep Singh Date: Mon, 4 Apr 2022 23:59:36 +0530 Subject: dt-bindings: serial: Update Qualcomm geni based QUP UART bindings Similar to I2C controller, move geni based QUP UART controller binding out from parent schema to an individual binding and let parent refer to child schema later on. UART binding also stand incomplete right now similar to I2C, complete it along this process. Signed-off-by: Kuldeep Singh Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220404182938.29492-4-singh.kuldeep87k@gmail.com Signed-off-by: Greg Kroah-Hartman --- .../bindings/serial/qcom,serial-geni-qcom.yaml | 86 ++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml b/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml new file mode 100644 index 000000000000..05a6999808d1 --- /dev/null +++ b/Documentation/devicetree/bindings/serial/qcom,serial-geni-qcom.yaml @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/serial/qcom,serial-geni-qcom.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Qualcomm Geni based QUP UART interface + +maintainers: + - Andy Gross + - Bjorn Andersson + +allOf: + - $ref: /schemas/serial/serial.yaml# + +properties: + compatible: + enum: + - qcom,geni-uart + - qcom,geni-debug-uart + + clocks: + maxItems: 1 + + clock-names: + const: se + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: qup-core + - const: qup-config + + interrupts: + minItems: 1 + items: + - description: UART core irq + - description: Wakeup irq (RX GPIO) + + operating-points-v2: true + + pinctrl-0: true + pinctrl-1: true + + pinctrl-names: + minItems: 1 + items: + - const: default + - const: sleep + + power-domains: + maxItems: 1 + + reg: + maxItems: 1 + +required: + - compatible + - clocks + - clock-names + - interrupts + - reg + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + + serial@a88000 { + compatible = "qcom,geni-uart"; + reg = <0xa88000 0x7000>; + interrupts = ; + clock-names = "se"; + clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>; + pinctrl-0 = <&qup_uart0_default>; + pinctrl-names = "default"; + interconnects = <&qup_virt MASTER_QUP_CORE_0 0 &qup_virt SLAVE_QUP_CORE_0 0>, + <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_QUP_0 0>; + interconnect-names = "qup-core", "qup-config"; + }; +... -- cgit v1.2.3 From 2a72b1b2db9dbe12c730754009196a132500f007 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 19 Apr 2022 09:43:02 +0200 Subject: Documentation: fix tty link The commit below causes the following warnings: Documentation/driver-api/index.rst:14: WARNING: toctree contains reference to nonexisting document 'driver-api/tty' Documentation/driver-api/tty/index.rst: WARNING: document isn't included in any toctree This is because I omitted the "/index" part from the link. That part is needed for directories and I was confused by the surrounding links which are links to files. Fix it in this patch. Fixes: b96cd8b05ead ("Documentation: move tty to driver-api") Cc: Jonathan Corbet Reported-by: Stephen Rothwell Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220419074302.29632-1-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-api/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index bbbbcf20b7ce..d76a60d95b58 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst @@ -101,7 +101,7 @@ available subsections can be seen below. surface_aggregator/index switchtec sync_file - tty + tty/index vfio-mediated-device vfio vfio-pci-device-specific-driver-acceptance -- cgit v1.2.3 From 85a503c9ea7d4978db5f98de941e6c04b44623f1 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Mon, 25 Apr 2022 15:41:57 +0900 Subject: dt-bindings: serial: renesas,hscif: Document r8a779g0 bindings R-Car V4H (R8A779G0) SoC has the R-Car Gen4 compatible HSCIF ports, so document the SoC specific bindings. Signed-off-by: Yoshihiro Shimoda Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220425064201.459633-4-yoshihiro.shimoda.uh@renesas.com Reviewed-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/renesas,hscif.yaml | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml index ee9804cd49bb..d688a07a0e29 100644 --- a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml +++ b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml @@ -55,6 +55,12 @@ properties: - const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2 - const: renesas,hscif # generic HSCIF compatible UART + - items: + - enum: + - renesas,hscif-r8a779g0 # R-Car V4H + - const: renesas,rcar-gen4-hscif # R-Car Gen4 + - const: renesas,hscif # generic HSCIF compatible UART + reg: maxItems: 1 @@ -113,6 +119,7 @@ if: enum: - renesas,rcar-gen2-hscif - renesas,rcar-gen3-hscif + - renesas,rcar-gen4-hscif then: required: - resets -- cgit v1.2.3 From 103dcf2ea2df2669d3e4496974e6bb0911ff515f Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Tue, 26 Apr 2022 15:24:41 +0300 Subject: dt_bindings: rs485: Add receiver enable polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add polarity property for receiver enable. Some UARTs have separate enable pins for tx (RTS or DE) and rx (RE). As most RS485 transceivers have !RE pin, the default is active low in contrast to rs485-rts-active-low that defaults to active high. Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220426122448.38997-4-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/rs485.yaml | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml index 0c9fa694f85c..f2c9c9fe6aa7 100644 --- a/Documentation/devicetree/bindings/serial/rs485.yaml +++ b/Documentation/devicetree/bindings/serial/rs485.yaml @@ -33,6 +33,11 @@ properties: description: drive RTS low when sending (default is high). $ref: /schemas/types.yaml#/definitions/flag + rs485-rx-active-high: + description: Polarity of receiver enable signal (when separate from RTS). + True indicates active high (default is low). + $ref: /schemas/types.yaml#/definitions/flag + linux,rs485-enabled-at-boot-time: description: enables the rs485 feature at boot time. It can be disabled later with proper ioctl. -- cgit v1.2.3 From 1e70d57e7285996bcf0a226eac8c5ba43a89f85d Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Tue, 26 Apr 2022 15:24:42 +0300 Subject: ACPI / property: Document RS485 _DSD properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document RS485 related properties returned from ACPI _DSD as device properties. Signed-off-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20220426122448.38997-5-ilpo.jarvinen@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- Documentation/firmware-guide/acpi/enumeration.rst | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'Documentation') diff --git a/Documentation/firmware-guide/acpi/enumeration.rst b/Documentation/firmware-guide/acpi/enumeration.rst index 47fb4d6d4557..f584a6a0c5e3 100644 --- a/Documentation/firmware-guide/acpi/enumeration.rst +++ b/Documentation/firmware-guide/acpi/enumeration.rst @@ -390,6 +390,31 @@ descriptors once the device is released. See Documentation/firmware-guide/acpi/gpio-properties.rst for more information about the _DSD binding related to GPIOs. +RS-485 support +============== + +ACPI _DSD (Device Specific Data) can be used to describe RS-485 capability +of UART. + +For example:: + + Device (DEV) + { + ... + + // ACPI 5.1 _DSD used for RS-485 capabilities + Name (_DSD, Package () + { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () + { + Package () {"rs485-rts-active-low", Zero}, + Package () {"rs485-rx-active-high", Zero}, + Package () {"rs485-rx-during-tx", Zero}, + } + }) + ... + MFD devices =========== -- cgit v1.2.3 From e4de48da57f337a0296f04885ca8b94ae61ca41a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 May 2022 15:34:57 +0200 Subject: dt-bindings: serial: renesas,hscif: R-Car V3U is R-Car Gen4 Despite the name, R-Car V3U is the first member of the R-Car Gen4 family. Hence move its compatible value to the R-Car Gen4 section. Signed-off-by: Geert Uytterhoeven Acked-by: Krzysztof Kozlowski Reviewed-by: Wolfram Sang Link: https://lore.kernel.org/r/dd734aaa4e5e0b32864b038b79eafe72907fb99f.1651497024.git.geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/renesas,hscif.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml index d688a07a0e29..87180d95cd4c 100644 --- a/Documentation/devicetree/bindings/serial/renesas,hscif.yaml +++ b/Documentation/devicetree/bindings/serial/renesas,hscif.yaml @@ -51,12 +51,12 @@ properties: - renesas,hscif-r8a77980 # R-Car V3H - renesas,hscif-r8a77990 # R-Car E3 - renesas,hscif-r8a77995 # R-Car D3 - - renesas,hscif-r8a779a0 # R-Car V3U - const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2 - const: renesas,hscif # generic HSCIF compatible UART - items: - enum: + - renesas,hscif-r8a779a0 # R-Car V3U - renesas,hscif-r8a779g0 # R-Car V4H - const: renesas,rcar-gen4-hscif # R-Car Gen4 - const: renesas,hscif # generic HSCIF compatible UART -- cgit v1.2.3 From f26c65dacfc2a9a0da07220972727de48534b646 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 2 May 2022 15:34:58 +0200 Subject: dt-bindings: serial: renesas,scif: R-Car V3U is R-Car Gen4 Despite the name, R-Car V3U is the first member of the R-Car Gen4 family. Hence move its compatible value to the R-Car Gen4 section. Signed-off-by: Geert Uytterhoeven Acked-by: Krzysztof Kozlowski Reviewed-by: Wolfram Sang Link: https://lore.kernel.org/r/c57ed00e85778380776330be6183c6861d843c22.1651497024.git.geert+renesas@glider.be Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/renesas,scif.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/renesas,scif.yaml b/Documentation/devicetree/bindings/serial/renesas,scif.yaml index 5d37f8f189fb..90fe45265fbc 100644 --- a/Documentation/devicetree/bindings/serial/renesas,scif.yaml +++ b/Documentation/devicetree/bindings/serial/renesas,scif.yaml @@ -60,12 +60,12 @@ properties: - renesas,scif-r8a77980 # R-Car V3H - renesas,scif-r8a77990 # R-Car E3 - renesas,scif-r8a77995 # R-Car D3 - - renesas,scif-r8a779a0 # R-Car V3U - const: renesas,rcar-gen3-scif # R-Car Gen3 and RZ/G2 - const: renesas,scif # generic SCIF compatible UART - items: - enum: + - renesas,scif-r8a779a0 # R-Car V3U - renesas,scif-r8a779f0 # R-Car S4-8 - const: renesas,rcar-gen4-scif # R-Car Gen4 - const: renesas,scif # generic SCIF compatible UART -- cgit v1.2.3 From 366f6c955d4d1a5125ffcd6875ead26a3c7a2a1c Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 18 Apr 2022 16:27:33 +0100 Subject: serial: 8250: Add proper clock handling for OxSemi PCIe devices Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock. We currently drive the device using its default oversampling rate of 16 and the clock prescaler disabled, consequently yielding the baud base of 3906250. This base is inadequate for some of the high-speed baud rates such as 460800bps, for which the closest rate possible can be obtained by dividing the baud base by 8, yielding the baud rate of 488281.25bps, which is off by 5.9638%. This is enough for data communication to break with the remote end talking actual 460800bps, where missed stop bits have been observed. We can do better however, by taking advantage of a reduced oversampling rate, which can be set to any integer value from 4 to 16 inclusive by programming the TCR register, and by using the clock prescaler, which can be set to any value from 1 to 63.875 in increments of 0.125 in the CPR/CPR2 register pair. The prescaler has to be explicitly enabled though by setting bit 7 in the MCR or otherwise it is bypassed (in the enhanced mode that we enable) as if the value of 1 was used. Make use of these features then as follows: - Set the baud base to 15625000, reflecting the minimum oversampling rate of 4 with the clock prescaler and divisor both set to 1. - Override the `set_mctrl' and set the MCR shadow there so as to have MCR[7] always set and have the 8250 core propagate these settings. - Override the `get_divisor' handler and determine a good combination of parameters by using a lookup table with predetermined value pairs of the oversampling rate and the clock prescaler and finding a pair that divides the input clock such that the quotient, when rounded to the nearest integer, deviates the least from the exact result. Calculate the clock divisor accordingly. Scale the resulting oversampling rate (only by powers of two) if possible so as to maximise it, reducing the divisor accordingly, and avoid a divisor overflow for very low baud rates by scaling the oversampling rate and/or the prescaler even if that causes some accuracy loss. Also handle the historic spd_cust feature so as to allow one to set all the three parameters manually to arbitrary values, by keeping the low 16 bits for the divisor and then putting TCR in bits 19:16 and CPR/CPR2 in bits 28:20, sanitising the bit pattern supplied such as to clamp CPR/CPR2 values between 0.000 and 0.875 inclusive to 33.875. This preserves compatibility with any existing setups, that is where requesting a custom divisor that only has any bits set among the low 16 the oversampling rate of 16 and the clock prescaler of 33.875 will be used as with the original 8250. Finally abuse the `frac' argument to store the determined bit patterns for the TCR, CPR and CPR2 registers. - Override the `set_divisor' handler so as to set the TCR, CPR and CPR2 registers from the `frac' value supplied. Set the divisor as usual. With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX limitation imposed by `serial8250_get_baud_rate' standard baud rates below 300bps become unavailable in the regular way, e.g. the rate of 200bps requires the baud base to be divided by 78125 and that is beyond the unsigned 16-bit range. The historic spd_cust feature can still be used to obtain such rates if so required. See Documentation/tty/device_drivers/oxsemi-tornado.rst for more details. Signed-off-by: Maciej W. Rozycki Link: https://lore.kernel.org/r/alpine.DEB.2.21.2204181519450.9383@angie.orcam.me.uk Signed-off-by: Greg Kroah-Hartman --- .../tty/device_drivers/oxsemi-tornado.rst | 129 ++++++++ drivers/tty/serial/8250/8250_pci.c | 339 ++++++++++++++++----- 2 files changed, 400 insertions(+), 68 deletions(-) create mode 100644 Documentation/tty/device_drivers/oxsemi-tornado.rst (limited to 'Documentation') diff --git a/Documentation/tty/device_drivers/oxsemi-tornado.rst b/Documentation/tty/device_drivers/oxsemi-tornado.rst new file mode 100644 index 000000000000..0180d8bb0881 --- /dev/null +++ b/Documentation/tty/device_drivers/oxsemi-tornado.rst @@ -0,0 +1,129 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================================================================== +Notes on Oxford Semiconductor PCIe (Tornado) 950 serial port devices +==================================================================== + +Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven +by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock. + +The baud rate produced by the baud generator is obtained from this input +frequency by dividing it by the clock prescaler, which can be set to any +value from 1 to 63.875 in increments of 0.125, and then the usual 16-bit +divisor is used as with the original 8250, to divide the frequency by a +value from 1 to 65535. Finally a programmable oversampling rate is used +that can take any value from 4 to 16 to divide the frequency further and +determine the actual baud rate used. Baud rates from 15625000bps down +to 0.933bps can be obtained this way. + +By default the oversampling rate is set to 16 and the clock prescaler is +set to 33.875, meaning that the frequency to be used as the reference +for the usual 16-bit divisor is 115313.653, which is close enough to the +frequency of 115200 used by the original 8250 for the same values to be +used for the divisor to obtain the requested baud rates by software that +is unaware of the extra clock controls available. + +The oversampling rate is programmed with the TCR register and the clock +prescaler is programmed with the CPR/CPR2 register pair[1][2][3][4]. +To switch away from the default value of 33.875 for the prescaler the +the enhanced mode has to be explicitly enabled though, by setting bit 4 +of the EFR. In that mode setting bit 7 in the MCR enables the prescaler +or otherwise it is bypassed as if the value of 1 was used. Additionally +writing any value to CPR clears CPR2 for compatibility with old software +written for older conventional PCI Oxford Semiconductor devices that do +not have the extra prescaler's 9th bit in CPR2, so the CPR/CPR2 register +pair has to be programmed in the right order. + +By using these parameters rates from 15625000bps down to 1bps can be +obtained, with either exact or highly-accurate actual bit rates for +standard and many non-standard rates. + +Here are the figures for the standard and some non-standard baud rates +(including those quoted in Oxford Semiconductor documentation), giving +the requested rate (r), the actual rate yielded (a) and its deviation +from the requested rate (d), and the values of the oversampling rate +(tcr), the clock prescaler (cpr) and the divisor (div) produced by the +new `get_divisor' handler: + +r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1 +r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1 +r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1 +r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1 +r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1 +r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1 +r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1 +r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1 +r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1 +r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1 +r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1 +r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1 +r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1 +r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1 +r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2 +r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2 +r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5 +r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5 +r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31 +r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35 +r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30 +r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105 +r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643 +r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647 +r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286 +r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294 +r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215 +r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625 +r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245 +r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153 +r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348 +r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461 +r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500 +r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500 +r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828 +r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828 +r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154 + +With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX +limitation imposed by `serial8250_get_baud_rate' standard baud rates +below 300bps become unavailable in the regular way, e.g. the rate of +200bps requires the baud base to be divided by 78125 and that is beyond +the unsigned 16-bit range. The historic spd_cust feature can still be +used by encoding the values for, the prescaler, the oversampling rate +and the clock divisor (DLM/DLL) as follows to obtain such rates if so +required: + + 31 29 28 20 19 16 15 0 ++-----+-----------------+-------+-------------------------------+ +|0 0 0| CPR2:CPR | TCR | DLM:DLL | ++-----+-----------------+-------+-------------------------------+ + +Use a value such encoded for the `custom_divisor' field along with the +ASYNC_SPD_CUST flag set in the `flags' field in `struct serial_struct' +passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8) +utility and its `divisor' and `spd_cust' parameters, and the select +the baud rate of 38400bps. Note that the value of 0 in TCR sets the +oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are +clamped by the driver to 1. + +For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL +respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value, +the oversampling rate and the clock divisor of 62.500, 16 and 1250 +respectively. These parameters will set the baud rate for the serial +port to 62500000 / 62.500 / 1250 / 16 = 50bps. + +References: + +[1] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor, + Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65 + +[2] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port", + Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode", + p. 20 + +[3] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford + Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20 + +[4] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford + Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20 + +Maciej W. Rozycki diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index e8be1b3a9597..a17619db7939 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -1044,6 +1045,208 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev) return number_uarts; } +/* Tornado-specific constants for the TCR and CPR registers; see below. */ +#define OXSEMI_TORNADO_TCR_MASK 0xf +#define OXSEMI_TORNADO_CPR_MASK 0x1ff +#define OXSEMI_TORNADO_CPR_MIN 0x008 +#define OXSEMI_TORNADO_CPR_DEF 0x10f + +/* + * Determine the oversampling rate, the clock prescaler, and the clock + * divisor for the requested baud rate. The clock rate is 62.5 MHz, + * which is four times the baud base, and the prescaler increments in + * steps of 1/8. Therefore to make calculations on integers we need + * to use a scaled clock rate, which is the baud base multiplied by 32 + * (or our assumed UART clock rate multiplied by 2). + * + * The allowed oversampling rates are from 4 up to 16 inclusive (values + * from 0 to 3 inclusive map to 16). Likewise the clock prescaler allows + * values between 1.000 and 63.875 inclusive (operation for values from + * 0.000 to 0.875 has not been specified). The clock divisor is the usual + * unsigned 16-bit integer. + * + * For the most accurate baud rate we use a table of predetermined + * oversampling rates and clock prescalers that records all possible + * products of the two parameters in the range from 4 up to 255 inclusive, + * and additionally 335 for the 1500000bps rate, with the prescaler scaled + * by 8. The table is sorted by the decreasing value of the oversampling + * rate and ties are resolved by sorting by the decreasing value of the + * product. This way preference is given to higher oversampling rates. + * + * We iterate over the table and choose the product of an oversampling + * rate and a clock prescaler that gives the lowest integer division + * result deviation, or if an exact integer divider is found we stop + * looking for it right away. We do some fixup if the resulting clock + * divisor required would be out of its unsigned 16-bit integer range. + * + * Finally we abuse the supposed fractional part returned to encode the + * 4-bit value of the oversampling rate and the 9-bit value of the clock + * prescaler which will end up in the TCR and CPR/CPR2 registers. + */ +static unsigned int pci_oxsemi_tornado_get_divisor(struct uart_port *port, + unsigned int baud, + unsigned int *frac) +{ + static u8 p[][2] = { + { 16, 14, }, { 16, 13, }, { 16, 12, }, { 16, 11, }, + { 16, 10, }, { 16, 9, }, { 16, 8, }, { 15, 17, }, + { 15, 16, }, { 15, 15, }, { 15, 14, }, { 15, 13, }, + { 15, 12, }, { 15, 11, }, { 15, 10, }, { 15, 9, }, + { 15, 8, }, { 14, 18, }, { 14, 17, }, { 14, 14, }, + { 14, 13, }, { 14, 12, }, { 14, 11, }, { 14, 10, }, + { 14, 9, }, { 14, 8, }, { 13, 19, }, { 13, 18, }, + { 13, 17, }, { 13, 13, }, { 13, 12, }, { 13, 11, }, + { 13, 10, }, { 13, 9, }, { 13, 8, }, { 12, 19, }, + { 12, 18, }, { 12, 17, }, { 12, 11, }, { 12, 9, }, + { 12, 8, }, { 11, 23, }, { 11, 22, }, { 11, 21, }, + { 11, 20, }, { 11, 19, }, { 11, 18, }, { 11, 17, }, + { 11, 11, }, { 11, 10, }, { 11, 9, }, { 11, 8, }, + { 10, 25, }, { 10, 23, }, { 10, 20, }, { 10, 19, }, + { 10, 17, }, { 10, 10, }, { 10, 9, }, { 10, 8, }, + { 9, 27, }, { 9, 23, }, { 9, 21, }, { 9, 19, }, + { 9, 18, }, { 9, 17, }, { 9, 9, }, { 9, 8, }, + { 8, 31, }, { 8, 29, }, { 8, 23, }, { 8, 19, }, + { 8, 17, }, { 8, 8, }, { 7, 35, }, { 7, 31, }, + { 7, 29, }, { 7, 25, }, { 7, 23, }, { 7, 21, }, + { 7, 19, }, { 7, 17, }, { 7, 15, }, { 7, 14, }, + { 7, 13, }, { 7, 12, }, { 7, 11, }, { 7, 10, }, + { 7, 9, }, { 7, 8, }, { 6, 41, }, { 6, 37, }, + { 6, 31, }, { 6, 29, }, { 6, 23, }, { 6, 19, }, + { 6, 17, }, { 6, 13, }, { 6, 11, }, { 6, 10, }, + { 6, 9, }, { 6, 8, }, { 5, 67, }, { 5, 47, }, + { 5, 43, }, { 5, 41, }, { 5, 37, }, { 5, 31, }, + { 5, 29, }, { 5, 25, }, { 5, 23, }, { 5, 19, }, + { 5, 17, }, { 5, 15, }, { 5, 13, }, { 5, 11, }, + { 5, 10, }, { 5, 9, }, { 5, 8, }, { 4, 61, }, + { 4, 59, }, { 4, 53, }, { 4, 47, }, { 4, 43, }, + { 4, 41, }, { 4, 37, }, { 4, 31, }, { 4, 29, }, + { 4, 23, }, { 4, 19, }, { 4, 17, }, { 4, 13, }, + { 4, 9, }, { 4, 8, }, + }; + /* Scale the quotient for comparison to get the fractional part. */ + const unsigned int quot_scale = 65536; + unsigned int sclk = port->uartclk * 2; + unsigned int sdiv = DIV_ROUND_CLOSEST(sclk, baud); + unsigned int best_squot; + unsigned int squot; + unsigned int quot; + u16 cpr; + u8 tcr; + int i; + + /* Old custom speed handling. */ + if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) { + unsigned int cust_div = port->custom_divisor; + + quot = cust_div & UART_DIV_MAX; + tcr = (cust_div >> 16) & OXSEMI_TORNADO_TCR_MASK; + cpr = (cust_div >> 20) & OXSEMI_TORNADO_CPR_MASK; + if (cpr < OXSEMI_TORNADO_CPR_MIN) + cpr = OXSEMI_TORNADO_CPR_DEF; + } else { + best_squot = quot_scale; + for (i = 0; i < ARRAY_SIZE(p); i++) { + unsigned int spre; + unsigned int srem; + u8 cp; + u8 tc; + + tc = p[i][0]; + cp = p[i][1]; + spre = tc * cp; + + srem = sdiv % spre; + if (srem > spre / 2) + srem = spre - srem; + squot = DIV_ROUND_CLOSEST(srem * quot_scale, spre); + + if (srem == 0) { + tcr = tc; + cpr = cp; + quot = sdiv / spre; + break; + } else if (squot < best_squot) { + best_squot = squot; + tcr = tc; + cpr = cp; + quot = DIV_ROUND_CLOSEST(sdiv, spre); + } + } + while (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1 && + quot % 2 == 0) { + quot >>= 1; + tcr <<= 1; + } + while (quot > UART_DIV_MAX) { + if (tcr <= (OXSEMI_TORNADO_TCR_MASK + 1) >> 1) { + quot >>= 1; + tcr <<= 1; + } else if (cpr <= OXSEMI_TORNADO_CPR_MASK >> 1) { + quot >>= 1; + cpr <<= 1; + } else { + quot = quot * cpr / OXSEMI_TORNADO_CPR_MASK; + cpr = OXSEMI_TORNADO_CPR_MASK; + } + } + } + + *frac = (cpr << 8) | (tcr & OXSEMI_TORNADO_TCR_MASK); + return quot; +} + +/* + * Set the oversampling rate in the transmitter clock cycle register (TCR), + * the clock prescaler in the clock prescaler register (CPR and CPR2), and + * the clock divisor in the divisor latch (DLL and DLM). Note that for + * backwards compatibility any write to CPR clears CPR2 and therefore CPR + * has to be written first, followed by CPR2, which occupies the location + * of CKS used with earlier UART designs. + */ +static void pci_oxsemi_tornado_set_divisor(struct uart_port *port, + unsigned int baud, + unsigned int quot, + unsigned int quot_frac) +{ + struct uart_8250_port *up = up_to_u8250p(port); + u8 cpr2 = quot_frac >> 16; + u8 cpr = quot_frac >> 8; + u8 tcr = quot_frac; + + serial_icr_write(up, UART_TCR, tcr); + serial_icr_write(up, UART_CPR, cpr); + serial_icr_write(up, UART_CKS, cpr2); + serial8250_do_set_divisor(port, baud, quot, 0); +} + +/* + * For Tornado devices we force MCR[7] set for the Divide-by-M N/8 baud rate + * generator prescaler (CPR and CPR2). Otherwise no prescaler would be used. + */ +static void pci_oxsemi_tornado_set_mctrl(struct uart_port *port, + unsigned int mctrl) +{ + struct uart_8250_port *up = up_to_u8250p(port); + + up->mcr |= UART_MCR_CLKSEL; + serial8250_do_set_mctrl(port, mctrl); +} + +static int pci_oxsemi_tornado_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *up, int idx) +{ + struct pci_dev *dev = priv->dev; + + if (pci_oxsemi_tornado_p(dev)) { + up->port.get_divisor = pci_oxsemi_tornado_get_divisor; + up->port.set_divisor = pci_oxsemi_tornado_set_divisor; + up->port.set_mctrl = pci_oxsemi_tornado_set_mctrl; + } + + return pci_default_setup(priv, board, up, idx); +} + static int pci_asix_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) @@ -2245,7 +2448,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .init = pci_oxsemi_tornado_init, - .setup = pci_default_setup, + .setup = pci_oxsemi_tornado_setup, }, { .vendor = PCI_VENDOR_ID_MAINPINE, @@ -2253,7 +2456,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, .init = pci_oxsemi_tornado_init, - .setup = pci_default_setup, + .setup = pci_oxsemi_tornado_setup, }, { .vendor = PCI_VENDOR_ID_DIGI, @@ -2261,7 +2464,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subvendor = PCI_SUBVENDOR_ID_IBM, .subdevice = PCI_ANY_ID, .init = pci_oxsemi_tornado_init, - .setup = pci_default_setup, + .setup = pci_oxsemi_tornado_setup, }, { .vendor = PCI_VENDOR_ID_INTEL, @@ -2578,7 +2781,7 @@ enum pci_board_num_t { pbn_b0_2_1843200, pbn_b0_4_1843200, - pbn_b0_1_3906250, + pbn_b0_1_15625000, pbn_b0_bt_1_115200, pbn_b0_bt_2_115200, @@ -2657,10 +2860,10 @@ enum pci_board_num_t { pbn_panacom4, pbn_plx_romulus, pbn_oxsemi, - pbn_oxsemi_1_3906250, - pbn_oxsemi_2_3906250, - pbn_oxsemi_4_3906250, - pbn_oxsemi_8_3906250, + pbn_oxsemi_1_15625000, + pbn_oxsemi_2_15625000, + pbn_oxsemi_4_15625000, + pbn_oxsemi_8_15625000, pbn_intel_i960, pbn_sgi_ioc3, pbn_computone_4, @@ -2803,10 +3006,10 @@ static struct pciserial_board pci_boards[] = { .uart_offset = 8, }, - [pbn_b0_1_3906250] = { + [pbn_b0_1_15625000] = { .flags = FL_BASE0, .num_ports = 1, - .base_baud = 3906250, + .base_baud = 15625000, .uart_offset = 8, }, @@ -3187,31 +3390,31 @@ static struct pciserial_board pci_boards[] = { .base_baud = 115200, .uart_offset = 8, }, - [pbn_oxsemi_1_3906250] = { + [pbn_oxsemi_1_15625000] = { .flags = FL_BASE0, .num_ports = 1, - .base_baud = 3906250, + .base_baud = 15625000, .uart_offset = 0x200, .first_offset = 0x1000, }, - [pbn_oxsemi_2_3906250] = { + [pbn_oxsemi_2_15625000] = { .flags = FL_BASE0, .num_ports = 2, - .base_baud = 3906250, + .base_baud = 15625000, .uart_offset = 0x200, .first_offset = 0x1000, }, - [pbn_oxsemi_4_3906250] = { + [pbn_oxsemi_4_15625000] = { .flags = FL_BASE0, .num_ports = 4, - .base_baud = 3906250, + .base_baud = 15625000, .uart_offset = 0x200, .first_offset = 0x1000, }, - [pbn_oxsemi_8_3906250] = { + [pbn_oxsemi_8_15625000] = { .flags = FL_BASE0, .num_ports = 8, - .base_baud = 3906250, + .base_baud = 15625000, .uart_offset = 0x200, .first_offset = 0x1000, }, @@ -4205,165 +4408,165 @@ static const struct pci_device_id serial_pci_tbl[] = { */ { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_1_3906250 }, + pbn_b0_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_3906250 }, + pbn_oxsemi_2_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_3906250 }, + pbn_oxsemi_2_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_4_3906250 }, + pbn_oxsemi_4_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_4_3906250 }, + pbn_oxsemi_4_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_8_3906250 }, + pbn_oxsemi_8_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_8_3906250 }, + pbn_oxsemi_8_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */ PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, /* * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado */ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0, - pbn_oxsemi_1_3906250 }, + pbn_oxsemi_1_15625000 }, { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0, - pbn_oxsemi_2_3906250 }, + pbn_oxsemi_2_15625000 }, { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0, - pbn_oxsemi_4_3906250 }, + pbn_oxsemi_4_15625000 }, { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, - pbn_oxsemi_8_3906250 }, + pbn_oxsemi_8_15625000 }, /* * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado */ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM, PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_3906250 }, + pbn_oxsemi_2_15625000 }, /* * EndRun Technologies. PCI express device range. * EndRun PTP/1588 has 2 Native UARTs utilizing OxSemi 952. */ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_oxsemi_2_3906250 }, + pbn_oxsemi_2_15625000 }, /* * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, -- cgit v1.2.3 From 7b0364eacb8f5177b6747a1c524b4bfd04011a2a Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2022 23:42:03 +0100 Subject: Documentation: Move Oxford Semiconductor PCIe (Tornado) 950 to misc-devices Documentation/tty has been moved to driver-api, which is not suitable for user documentation, so move the Oxford Semiconductor PCIe (Tornado) 950 description to misc-devices instead. Signed-off-by: Maciej W. Rozycki Link: https://lore.kernel.org/r/alpine.DEB.2.21.2205131823430.10656@angie.orcam.me.uk Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/oxsemi-tornado.rst | 129 +++++++++++++++++++++ .../tty/device_drivers/oxsemi-tornado.rst | 129 --------------------- 2 files changed, 129 insertions(+), 129 deletions(-) create mode 100644 Documentation/misc-devices/oxsemi-tornado.rst delete mode 100644 Documentation/tty/device_drivers/oxsemi-tornado.rst (limited to 'Documentation') diff --git a/Documentation/misc-devices/oxsemi-tornado.rst b/Documentation/misc-devices/oxsemi-tornado.rst new file mode 100644 index 000000000000..0180d8bb0881 --- /dev/null +++ b/Documentation/misc-devices/oxsemi-tornado.rst @@ -0,0 +1,129 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================================================================== +Notes on Oxford Semiconductor PCIe (Tornado) 950 serial port devices +==================================================================== + +Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven +by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock. + +The baud rate produced by the baud generator is obtained from this input +frequency by dividing it by the clock prescaler, which can be set to any +value from 1 to 63.875 in increments of 0.125, and then the usual 16-bit +divisor is used as with the original 8250, to divide the frequency by a +value from 1 to 65535. Finally a programmable oversampling rate is used +that can take any value from 4 to 16 to divide the frequency further and +determine the actual baud rate used. Baud rates from 15625000bps down +to 0.933bps can be obtained this way. + +By default the oversampling rate is set to 16 and the clock prescaler is +set to 33.875, meaning that the frequency to be used as the reference +for the usual 16-bit divisor is 115313.653, which is close enough to the +frequency of 115200 used by the original 8250 for the same values to be +used for the divisor to obtain the requested baud rates by software that +is unaware of the extra clock controls available. + +The oversampling rate is programmed with the TCR register and the clock +prescaler is programmed with the CPR/CPR2 register pair[1][2][3][4]. +To switch away from the default value of 33.875 for the prescaler the +the enhanced mode has to be explicitly enabled though, by setting bit 4 +of the EFR. In that mode setting bit 7 in the MCR enables the prescaler +or otherwise it is bypassed as if the value of 1 was used. Additionally +writing any value to CPR clears CPR2 for compatibility with old software +written for older conventional PCI Oxford Semiconductor devices that do +not have the extra prescaler's 9th bit in CPR2, so the CPR/CPR2 register +pair has to be programmed in the right order. + +By using these parameters rates from 15625000bps down to 1bps can be +obtained, with either exact or highly-accurate actual bit rates for +standard and many non-standard rates. + +Here are the figures for the standard and some non-standard baud rates +(including those quoted in Oxford Semiconductor documentation), giving +the requested rate (r), the actual rate yielded (a) and its deviation +from the requested rate (d), and the values of the oversampling rate +(tcr), the clock prescaler (cpr) and the divisor (div) produced by the +new `get_divisor' handler: + +r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1 +r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1 +r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1 +r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1 +r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1 +r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1 +r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1 +r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1 +r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1 +r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1 +r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1 +r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1 +r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1 +r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1 +r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2 +r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2 +r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5 +r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5 +r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31 +r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35 +r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30 +r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105 +r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643 +r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647 +r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286 +r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294 +r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215 +r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625 +r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245 +r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153 +r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348 +r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461 +r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500 +r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500 +r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828 +r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828 +r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154 + +With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX +limitation imposed by `serial8250_get_baud_rate' standard baud rates +below 300bps become unavailable in the regular way, e.g. the rate of +200bps requires the baud base to be divided by 78125 and that is beyond +the unsigned 16-bit range. The historic spd_cust feature can still be +used by encoding the values for, the prescaler, the oversampling rate +and the clock divisor (DLM/DLL) as follows to obtain such rates if so +required: + + 31 29 28 20 19 16 15 0 ++-----+-----------------+-------+-------------------------------+ +|0 0 0| CPR2:CPR | TCR | DLM:DLL | ++-----+-----------------+-------+-------------------------------+ + +Use a value such encoded for the `custom_divisor' field along with the +ASYNC_SPD_CUST flag set in the `flags' field in `struct serial_struct' +passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8) +utility and its `divisor' and `spd_cust' parameters, and the select +the baud rate of 38400bps. Note that the value of 0 in TCR sets the +oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are +clamped by the driver to 1. + +For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL +respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value, +the oversampling rate and the clock divisor of 62.500, 16 and 1250 +respectively. These parameters will set the baud rate for the serial +port to 62500000 / 62.500 / 1250 / 16 = 50bps. + +References: + +[1] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor, + Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65 + +[2] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port", + Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode", + p. 20 + +[3] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford + Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20 + +[4] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford + Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20 + +Maciej W. Rozycki diff --git a/Documentation/tty/device_drivers/oxsemi-tornado.rst b/Documentation/tty/device_drivers/oxsemi-tornado.rst deleted file mode 100644 index 0180d8bb0881..000000000000 --- a/Documentation/tty/device_drivers/oxsemi-tornado.rst +++ /dev/null @@ -1,129 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0 - -==================================================================== -Notes on Oxford Semiconductor PCIe (Tornado) 950 serial port devices -==================================================================== - -Oxford Semiconductor PCIe (Tornado) 950 serial port devices are driven -by a fixed 62.5MHz clock input derived from the 100MHz PCI Express clock. - -The baud rate produced by the baud generator is obtained from this input -frequency by dividing it by the clock prescaler, which can be set to any -value from 1 to 63.875 in increments of 0.125, and then the usual 16-bit -divisor is used as with the original 8250, to divide the frequency by a -value from 1 to 65535. Finally a programmable oversampling rate is used -that can take any value from 4 to 16 to divide the frequency further and -determine the actual baud rate used. Baud rates from 15625000bps down -to 0.933bps can be obtained this way. - -By default the oversampling rate is set to 16 and the clock prescaler is -set to 33.875, meaning that the frequency to be used as the reference -for the usual 16-bit divisor is 115313.653, which is close enough to the -frequency of 115200 used by the original 8250 for the same values to be -used for the divisor to obtain the requested baud rates by software that -is unaware of the extra clock controls available. - -The oversampling rate is programmed with the TCR register and the clock -prescaler is programmed with the CPR/CPR2 register pair[1][2][3][4]. -To switch away from the default value of 33.875 for the prescaler the -the enhanced mode has to be explicitly enabled though, by setting bit 4 -of the EFR. In that mode setting bit 7 in the MCR enables the prescaler -or otherwise it is bypassed as if the value of 1 was used. Additionally -writing any value to CPR clears CPR2 for compatibility with old software -written for older conventional PCI Oxford Semiconductor devices that do -not have the extra prescaler's 9th bit in CPR2, so the CPR/CPR2 register -pair has to be programmed in the right order. - -By using these parameters rates from 15625000bps down to 1bps can be -obtained, with either exact or highly-accurate actual bit rates for -standard and many non-standard rates. - -Here are the figures for the standard and some non-standard baud rates -(including those quoted in Oxford Semiconductor documentation), giving -the requested rate (r), the actual rate yielded (a) and its deviation -from the requested rate (d), and the values of the oversampling rate -(tcr), the clock prescaler (cpr) and the divisor (div) produced by the -new `get_divisor' handler: - -r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1 -r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1 -r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1 -r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1 -r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1 -r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1 -r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1 -r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1 -r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1 -r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1 -r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1 -r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1 -r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1 -r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1 -r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2 -r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2 -r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5 -r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5 -r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31 -r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35 -r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30 -r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105 -r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643 -r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647 -r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286 -r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294 -r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215 -r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625 -r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245 -r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153 -r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348 -r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461 -r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500 -r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500 -r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828 -r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828 -r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154 - -With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX -limitation imposed by `serial8250_get_baud_rate' standard baud rates -below 300bps become unavailable in the regular way, e.g. the rate of -200bps requires the baud base to be divided by 78125 and that is beyond -the unsigned 16-bit range. The historic spd_cust feature can still be -used by encoding the values for, the prescaler, the oversampling rate -and the clock divisor (DLM/DLL) as follows to obtain such rates if so -required: - - 31 29 28 20 19 16 15 0 -+-----+-----------------+-------+-------------------------------+ -|0 0 0| CPR2:CPR | TCR | DLM:DLL | -+-----+-----------------+-------+-------------------------------+ - -Use a value such encoded for the `custom_divisor' field along with the -ASYNC_SPD_CUST flag set in the `flags' field in `struct serial_struct' -passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8) -utility and its `divisor' and `spd_cust' parameters, and the select -the baud rate of 38400bps. Note that the value of 0 in TCR sets the -oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are -clamped by the driver to 1. - -For example the value of 0x1f4004e2 will set CPR2/CPR, TCR and DLM/DLL -respectively to 0x1f4, 0x0 and 0x04e2, choosing the prescaler value, -the oversampling rate and the clock divisor of 62.500, 16 and 1250 -respectively. These parameters will set the baud rate for the serial -port to 62500000 / 62.500 / 1250 / 16 = 50bps. - -References: - -[1] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor, - Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65 - -[2] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port", - Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode", - p. 20 - -[3] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford - Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20 - -[4] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford - Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20 - -Maciej W. Rozycki -- cgit v1.2.3 From 421bdf5385dc551f2b35d17db3cfc150550d5434 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2022 23:42:08 +0100 Subject: Documentation: Reformat Oxford Semiconductor PCIe (Tornado) 950 Reformat Oxford Semiconductor PCIe (Tornado) 950 description in terms of reStructuredText markup, fixing warnings with `make htmldocs'. While at it remove typos: s/the the/the/ and s/the/then/ in lines changed anyway. Signed-off-by: Maciej W. Rozycki Link: https://lore.kernel.org/r/alpine.DEB.2.21.2205131721110.10656@angie.orcam.me.uk Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/oxsemi-tornado.rst | 138 +++++++++++++------------- 1 file changed, 70 insertions(+), 68 deletions(-) (limited to 'Documentation') diff --git a/Documentation/misc-devices/oxsemi-tornado.rst b/Documentation/misc-devices/oxsemi-tornado.rst index 0180d8bb0881..b33351bef6cf 100644 --- a/Documentation/misc-devices/oxsemi-tornado.rst +++ b/Documentation/misc-devices/oxsemi-tornado.rst @@ -24,15 +24,15 @@ used for the divisor to obtain the requested baud rates by software that is unaware of the extra clock controls available. The oversampling rate is programmed with the TCR register and the clock -prescaler is programmed with the CPR/CPR2 register pair[1][2][3][4]. -To switch away from the default value of 33.875 for the prescaler the -the enhanced mode has to be explicitly enabled though, by setting bit 4 -of the EFR. In that mode setting bit 7 in the MCR enables the prescaler -or otherwise it is bypassed as if the value of 1 was used. Additionally -writing any value to CPR clears CPR2 for compatibility with old software -written for older conventional PCI Oxford Semiconductor devices that do -not have the extra prescaler's 9th bit in CPR2, so the CPR/CPR2 register -pair has to be programmed in the right order. +prescaler is programmed with the CPR/CPR2 register pair [OX200]_ [OX952]_ +[OX954]_ [OX958]_. To switch away from the default value of 33.875 for +the prescaler the enhanced mode has to be explicitly enabled though, by +setting bit 4 of the EFR. In that mode setting bit 7 in the MCR enables +the prescaler or otherwise it is bypassed as if the value of 1 was used. +Additionally writing any value to CPR clears CPR2 for compatibility with +old software written for older conventional PCI Oxford Semiconductor +devices that do not have the extra prescaler's 9th bit in CPR2, so the +CPR/CPR2 register pair has to be programmed in the right order. By using these parameters rates from 15625000bps down to 1bps can be obtained, with either exact or highly-accurate actual bit rates for @@ -43,48 +43,50 @@ Here are the figures for the standard and some non-standard baud rates the requested rate (r), the actual rate yielded (a) and its deviation from the requested rate (d), and the values of the oversampling rate (tcr), the clock prescaler (cpr) and the divisor (div) produced by the -new `get_divisor' handler: - -r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1 -r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1 -r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1 -r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1 -r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1 -r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1 -r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1 -r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1 -r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1 -r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1 -r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1 -r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1 -r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1 -r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1 -r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2 -r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2 -r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5 -r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5 -r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31 -r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35 -r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30 -r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105 -r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643 -r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647 -r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286 -r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294 -r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215 -r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625 -r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245 -r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153 -r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348 -r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461 -r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500 -r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500 -r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828 -r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828 -r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154 +new ``get_divisor`` handler: + +:: + + r: 15625000, a: 15625000.00, d: 0.0000%, tcr: 4, cpr: 1.000, div: 1 + r: 12500000, a: 12500000.00, d: 0.0000%, tcr: 5, cpr: 1.000, div: 1 + r: 10416666, a: 10416666.67, d: 0.0000%, tcr: 6, cpr: 1.000, div: 1 + r: 8928571, a: 8928571.43, d: 0.0000%, tcr: 7, cpr: 1.000, div: 1 + r: 7812500, a: 7812500.00, d: 0.0000%, tcr: 8, cpr: 1.000, div: 1 + r: 4000000, a: 4000000.00, d: 0.0000%, tcr: 5, cpr: 3.125, div: 1 + r: 3686400, a: 3676470.59, d: -0.2694%, tcr: 8, cpr: 2.125, div: 1 + r: 3500000, a: 3496503.50, d: -0.0999%, tcr: 13, cpr: 1.375, div: 1 + r: 3000000, a: 2976190.48, d: -0.7937%, tcr: 14, cpr: 1.500, div: 1 + r: 2500000, a: 2500000.00, d: 0.0000%, tcr: 10, cpr: 2.500, div: 1 + r: 2000000, a: 2000000.00, d: 0.0000%, tcr: 10, cpr: 3.125, div: 1 + r: 1843200, a: 1838235.29, d: -0.2694%, tcr: 16, cpr: 2.125, div: 1 + r: 1500000, a: 1492537.31, d: -0.4975%, tcr: 5, cpr: 8.375, div: 1 + r: 1152000, a: 1152073.73, d: 0.0064%, tcr: 14, cpr: 3.875, div: 1 + r: 921600, a: 919117.65, d: -0.2694%, tcr: 16, cpr: 2.125, div: 2 + r: 576000, a: 576036.87, d: 0.0064%, tcr: 14, cpr: 3.875, div: 2 + r: 460800, a: 460829.49, d: 0.0064%, tcr: 7, cpr: 3.875, div: 5 + r: 230400, a: 230414.75, d: 0.0064%, tcr: 14, cpr: 3.875, div: 5 + r: 115200, a: 115207.37, d: 0.0064%, tcr: 14, cpr: 1.250, div: 31 + r: 57600, a: 57603.69, d: 0.0064%, tcr: 8, cpr: 3.875, div: 35 + r: 38400, a: 38402.46, d: 0.0064%, tcr: 14, cpr: 3.875, div: 30 + r: 19200, a: 19201.23, d: 0.0064%, tcr: 8, cpr: 3.875, div: 105 + r: 9600, a: 9600.06, d: 0.0006%, tcr: 9, cpr: 1.125, div: 643 + r: 4800, a: 4799.98, d: -0.0004%, tcr: 7, cpr: 2.875, div: 647 + r: 2400, a: 2400.02, d: 0.0008%, tcr: 9, cpr: 2.250, div: 1286 + r: 1200, a: 1200.00, d: 0.0000%, tcr: 14, cpr: 2.875, div: 1294 + r: 300, a: 300.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 7215 + r: 200, a: 200.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 15625 + r: 150, a: 150.00, d: 0.0000%, tcr: 13, cpr: 2.250, div: 14245 + r: 134, a: 134.00, d: 0.0000%, tcr: 11, cpr: 2.625, div: 16153 + r: 110, a: 110.00, d: 0.0000%, tcr: 12, cpr: 1.000, div: 47348 + r: 75, a: 75.00, d: 0.0000%, tcr: 4, cpr: 5.875, div: 35461 + r: 50, a: 50.00, d: 0.0000%, tcr: 16, cpr: 1.250, div: 62500 + r: 25, a: 25.00, d: 0.0000%, tcr: 16, cpr: 2.500, div: 62500 + r: 4, a: 4.00, d: 0.0000%, tcr: 16, cpr: 20.000, div: 48828 + r: 2, a: 2.00, d: 0.0000%, tcr: 16, cpr: 40.000, div: 48828 + r: 1, a: 1.00, d: 0.0000%, tcr: 16, cpr: 63.875, div: 61154 With the baud base set to 15625000 and the unsigned 16-bit UART_DIV_MAX -limitation imposed by `serial8250_get_baud_rate' standard baud rates +limitation imposed by ``serial8250_get_baud_rate`` standard baud rates below 300bps become unavailable in the regular way, e.g. the rate of 200bps requires the baud base to be divided by 78125 and that is beyond the unsigned 16-bit range. The historic spd_cust feature can still be @@ -92,15 +94,17 @@ used by encoding the values for, the prescaler, the oversampling rate and the clock divisor (DLM/DLL) as follows to obtain such rates if so required: - 31 29 28 20 19 16 15 0 -+-----+-----------------+-------+-------------------------------+ -|0 0 0| CPR2:CPR | TCR | DLM:DLL | -+-----+-----------------+-------+-------------------------------+ +:: -Use a value such encoded for the `custom_divisor' field along with the -ASYNC_SPD_CUST flag set in the `flags' field in `struct serial_struct' + 31 29 28 20 19 16 15 0 + +-----+-----------------+-------+-------------------------------+ + |0 0 0| CPR2:CPR | TCR | DLM:DLL | + +-----+-----------------+-------+-------------------------------+ + +Use a value such encoded for the ``custom_divisor`` field along with the +ASYNC_SPD_CUST flag set in the ``flags`` field in ``struct serial_struct`` passed with the TIOCSSERIAL ioctl(2), such as with the setserial(8) -utility and its `divisor' and `spd_cust' parameters, and the select +utility and its ``divisor`` and ``spd_cust`` parameters, and then select the baud rate of 38400bps. Note that the value of 0 in TCR sets the oversampling rate to 16 and prescaler values below 1 in CPR2/CPR are clamped by the driver to 1. @@ -111,19 +115,17 @@ the oversampling rate and the clock divisor of 62.500, 16 and 1250 respectively. These parameters will set the baud rate for the serial port to 62500000 / 62.500 / 1250 / 16 = 50bps. -References: - -[1] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor, - Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65 +Maciej W. Rozycki -[2] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port", - Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode", - p. 20 +.. [OX200] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor, + Inc., DS-0045, 10 Nov 2008, Section "950 Mode", pp. 64-65 -[3] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford - Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20 +.. [OX952] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port", + Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "950 Mode", + p. 20 -[4] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford - Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20 +.. [OX954] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford + Semiconductor, Inc., DS-0047, Feb 08, Section "950 Mode", p. 20 -Maciej W. Rozycki +.. [OX958] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford + Semiconductor, Inc., DS-0048, Feb 08, Section "950 Mode", p. 20 -- cgit v1.2.3 From 91ca09ca7f310aaefb2d56d57421e02cc44a7eb4 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 13 May 2022 23:42:13 +0100 Subject: Documentation: Wire Oxford Semiconductor PCIe (Tornado) 950 Wire Oxford Semiconductor PCIe (Tornado) 950 description as a chapter into the misc-devices document. Signed-off-by: Maciej W. Rozycki Link: https://lore.kernel.org/r/alpine.DEB.2.21.2205131727070.10656@angie.orcam.me.uk Signed-off-by: Greg Kroah-Hartman --- Documentation/misc-devices/index.rst | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst index 30ac58f81901..756be15a49a4 100644 --- a/Documentation/misc-devices/index.rst +++ b/Documentation/misc-devices/index.rst @@ -25,6 +25,7 @@ fit into other categories. isl29003 lis3lv02d max6875 + oxsemi-tornado pci-endpoint-test spear-pcie-gadget uacce -- cgit v1.2.3 From 4ed26f87c71f97d6551caeb2e9e533f8980e764e Mon Sep 17 00:00:00 2001 From: Phil Edworthy Date: Thu, 12 May 2022 08:26:49 +0100 Subject: dt-bindings: serial: renesas,em-uart: Add RZ/V2M clock to access the registers The RZ/V2M SoC has an additional clock to access the registers. The HW manual says this clock should not be touched as it is used by the "ISP Firmware". Reviewed-by: Geert Uytterhoeven Reviewed-by: Rob Herring Signed-off-by: Phil Edworthy Link: https://lore.kernel.org/r/20220512072649.7879-1-phil.edworthy@renesas.com Signed-off-by: Greg Kroah-Hartman --- .../bindings/serial/renesas,em-uart.yaml | 28 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml index 332c385618e1..b25aca733b72 100644 --- a/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml +++ b/Documentation/devicetree/bindings/serial/renesas,em-uart.yaml @@ -9,9 +9,6 @@ title: Renesas EMMA Mobile UART Interface maintainers: - Magnus Damm -allOf: - - $ref: serial.yaml# - properties: compatible: oneOf: @@ -30,10 +27,31 @@ properties: maxItems: 1 clocks: - maxItems: 1 + minItems: 1 + items: + - description: UART functional clock + - description: Internal clock to access the registers clock-names: - const: sclk + minItems: 1 + items: + - const: sclk + - const: pclk + +allOf: + - $ref: serial.yaml# + + - if: + properties: + compatible: + contains: + const: renesas,r9a09g011-uart + then: + properties: + clocks: + minItems: 2 + clock-names: + minItems: 2 required: - compatible -- cgit v1.2.3