Merge 356a031945 ("Merge tag 'tty-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty") into android-mainline

Steps on the way to 6.12-rc1

Bug: 367265496
Change-Id: I0558de38f29cc97e194b80b6c6a79f67e9c0ebaa
Signed-off-by: Matthias Maennich <maennich@google.com>
This commit is contained in:
Matthias Maennich
2024-10-03 15:49:54 +00:00
committed by Treehugger Robot
309 changed files with 6879 additions and 2518 deletions
@@ -6,3 +6,10 @@ Description:
This item contains just one readonly attribute: port_num.
It contains the port number of the /dev/ttyGS<n> device
associated with acm function's instance "name".
What: /config/usb-gadget/gadget/functions/acm.name/protocol
Date: Aug 2024
KernelVersion: 6.13
Description:
Reported bInterfaceProtocol for the ACM device. For legacy
reasons, this defaults to 1 (USB_CDC_ACM_PROTO_AT_V25TER).
@@ -30,4 +30,12 @@ Description:
req_number the number of pre-allocated requests
for both capture and playback
function_name name of the interface
p_it_name playback input terminal name
p_it_ch_name playback channels name
p_ot_name playback output terminal name
p_fu_vol_name playback mute/volume functional unit name
c_it_name capture input terminal name
c_it_ch_name capture channels name
c_ot_name capture output terminal name
c_fu_vol_name capture mute/volume functional unit name
===================== =======================================
@@ -35,6 +35,17 @@ Description:
req_number the number of pre-allocated requests
for both capture and playback
function_name name of the interface
if_ctrl_name topology control name
clksrc_in_name input clock name
clksrc_out_name output clock name
p_it_name playback input terminal name
p_it_ch_name playback input first channel name
p_ot_name playback output terminal name
p_fu_vol_name playback mute/volume function unit name
c_it_name capture input terminal name
c_it_ch_name capture input first channel name
c_ot_name capture output terminal name
c_fu_vol_name capture mute/volume functional unit name
c_terminal_type code of the capture terminal type
p_terminal_type code of the playback terminal type
===================== =======================================
@@ -1,71 +0,0 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/input/goodix,gt7986u.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: GOODIX GT7986U SPI HID Touchscreen
maintainers:
- Charles Wang <charles.goodix@gmail.com>
description: Supports the Goodix GT7986U touchscreen.
This touch controller reports data packaged according to the HID protocol,
but is incompatible with Microsoft's HID-over-SPI protocol.
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
enum:
- goodix,gt7986u
reg:
maxItems: 1
interrupts:
maxItems: 1
reset-gpios:
maxItems: 1
goodix,hid-report-addr:
$ref: /schemas/types.yaml#/definitions/uint32
description:
The register address for retrieving HID report data.
This address is related to the device firmware and may
change after a firmware update.
spi-max-frequency: true
additionalProperties: false
required:
- compatible
- reg
- interrupts
- reset-gpios
- goodix,hid-report-addr
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
touchscreen@0 {
compatible = "goodix,gt7986u";
reg = <0>;
interrupt-parent = <&gpio>;
interrupts = <25 IRQ_TYPE_LEVEL_LOW>;
reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
spi-max-frequency = <10000000>;
goodix,hid-report-addr = <0x22c8c>;
};
};
...
@@ -87,6 +87,12 @@ properties:
maximum: 119
default: 100
nxp,sim:
description:
The system integration module (SIM) provides system control and chip
configuration registers.
$ref: /schemas/types.yaml#/definitions/phandle
required:
- compatible
- reg
@@ -110,6 +116,17 @@ allOf:
required:
- fsl,anatop
- if:
properties:
compatible:
const: fsl,imx7ulp-usbphy
then:
required:
- nxp,sim
else:
properties:
nxp,sim: false
additionalProperties: false
examples:
@@ -22,6 +22,9 @@ properties:
interrupts:
maxItems: 1
"#clock-cells":
const: 0
trickle-resistor-ohms:
enum:
- 3000
@@ -0,0 +1,49 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/sprd,sc2731-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Spreadtrum SC2731 Real Time Clock
maintainers:
- Orson Zhai <orsonzhai@gmail.com>
- Baolin Wang <baolin.wang7@gmail.com>
- Chunyan Zhang <zhang.lyra@gmail.com>
properties:
compatible:
const: sprd,sc2731-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
allOf:
- $ref: rtc.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
pmic {
#address-cells = <1>;
#size-cells = <0>;
rtc@280 {
compatible = "sprd,sc2731-rtc";
reg = <0x280>;
interrupt-parent = <&sc2731_pmic>;
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
};
};
...
@@ -1,26 +0,0 @@
Spreadtrum SC27xx Real Time Clock
Required properties:
- compatible: should be "sprd,sc2731-rtc".
- reg: address offset of rtc register.
- interrupts: rtc alarm interrupt.
Example:
sc2731_pmic: pmic@0 {
compatible = "sprd,sc2731";
reg = <0>;
spi-max-frequency = <26000000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
rtc@280 {
compatible = "sprd,sc2731-rtc";
reg = <0x280>;
interrupt-parent = <&sc2731_pmic>;
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
};
};
@@ -53,6 +53,28 @@ properties:
override default rtc_ck parent clock phandle of the new parent clock of rtc_ck
maxItems: 1
patternProperties:
"^rtc-[a-z]+-[0-9]+$":
type: object
$ref: /schemas/pinctrl/pinmux-node.yaml
description: |
Configuration of STM32 RTC pins description. STM32 RTC is able to output
some signals on specific pins:
- LSCO (Low Speed Clock Output) that allow to output LSE clock on a pin.
- Alarm out that allow to send a pulse on a pin when alarm A of the RTC
expires.
additionalProperties: false
properties:
function:
enum:
- lsco
- alarm-a
pins:
enum:
- out1
- out2
- out2_rmp
allOf:
- if:
properties:
@@ -68,6 +90,9 @@ allOf:
clock-names: false
patternProperties:
"^rtc-[a-z]+-[0-9]+$": false
required:
- st,syscfg
@@ -83,6 +108,9 @@ allOf:
minItems: 2
maxItems: 2
patternProperties:
"^rtc-[a-z]+-[0-9]+$": false
required:
- clock-names
- st,syscfg
@@ -38,12 +38,13 @@ properties:
- dallas,ds1672
# Extremely Accurate I²C RTC with Integrated Crystal and SRAM
- dallas,ds3232
# SD2405AL Real-Time Clock
- dfrobot,sd2405al
# EM Microelectronic EM3027 RTC
- emmicro,em3027
# I2C-BUS INTERFACE REAL TIME CLOCK MODULE
- epson,rx8010
# I2C-BUS INTERFACE REAL TIME CLOCK MODULE
- epson,rx8025
- epson,rx8035
# I2C-BUS INTERFACE REAL TIME CLOCK MODULE with Battery Backed RAM
- epson,rx8111
@@ -52,10 +53,6 @@ properties:
- epson,rx8581
# Android Goldfish Real-time Clock
- google,goldfish-rtc
# Intersil ISL1208 Low Power RTC with Battery Backed SRAM
- isil,isl1208
# Intersil ISL1218 Low Power RTC with Battery Backed SRAM
- isil,isl1218
# Mvebu Real-time Clock
- marvell,orion-rtc
# Maxim DS1742/DS1743 Real-time Clock
@@ -68,8 +65,6 @@ properties:
- microcrystal,rv8523
# NXP LPC32xx SoC Real-time Clock
- nxp,lpc3220-rtc
# Real-time Clock Module
- pericom,pt7c4338
# I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
- ricoh,r2025sd
# I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
@@ -76,6 +76,7 @@ properties:
clock-frequency: true
current-speed: true
overrun-throttle-ms: true
wakeup-source: true
required:
- compatible
@@ -23,13 +23,20 @@ properties:
- const: atmel,at91sam9260-dbgu
- const: atmel,at91sam9260-usart
- items:
- const: microchip,sam9x60-usart
- enum:
- microchip,sam9x60-usart
- microchip,sam9x7-usart
- const: atmel,at91sam9260-usart
- items:
- const: microchip,sam9x60-dbgu
- const: microchip,sam9x60-usart
- const: atmel,at91sam9260-dbgu
- const: atmel,at91sam9260-usart
- items:
- const: microchip,sam9x7-dbgu
- const: atmel,at91sam9260-dbgu
- const: microchip,sam9x7-usart
- const: atmel,at91sam9260-usart
reg:
maxItems: 1
@@ -36,6 +36,7 @@ properties:
- mediatek,mt7622-uart
- mediatek,mt7623-uart
- mediatek,mt7629-uart
- mediatek,mt7981-uart
- mediatek,mt7986-uart
- mediatek,mt7988-uart
- mediatek,mt8127-uart
@@ -46,6 +46,7 @@ properties:
- items:
- enum:
- renesas,scif-r8a774a1 # RZ/G2M
- renesas,scif-r8a774a3 # RZ/G2M v3.0
- renesas,scif-r8a774b1 # RZ/G2N
- renesas,scif-r8a774c0 # RZ/G2E
- renesas,scif-r8a774e1 # RZ/G2H
@@ -56,14 +56,8 @@ properties:
maxItems: 5
clock-names:
description: N = 0 is allowed for SoCs without internal baud clock mux.
minItems: 2
items:
- const: uart
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
- pattern: '^clk_uart_baud[0-3]$'
maxItems: 5
dmas:
items:
@@ -103,18 +97,45 @@ allOf:
compatible:
contains:
enum:
- samsung,s5pv210-uart
- samsung,s3c6400-uart
then:
properties:
clocks:
minItems: 2
minItems: 3
maxItems: 3
clock-names:
items:
- const: uart
- const: clk_uart_baud2
- const: clk_uart_baud3
else:
properties:
clock-names:
minItems: 2
items:
- const: uart
- pattern: '^clk_uart_baud[0-1]$'
- pattern: '^clk_uart_baud[0-1]$'
- const: clk_uart_baud0
- const: clk_uart_baud1
- const: clk_uart_baud2
- const: clk_uart_baud3
- if:
properties:
compatible:
contains:
enum:
- samsung,s5pv210-uart
then:
properties:
clocks:
minItems: 3
maxItems: 3
clock-names:
minItems: 3
maxItems: 3
- if:
properties:
@@ -129,10 +150,9 @@ allOf:
properties:
clocks:
maxItems: 2
clock-names:
items:
- const: uart
- const: clk_uart_baud0
maxItems: 2
- if:
properties:
@@ -146,6 +166,12 @@ allOf:
properties:
reg-io-width: false
clocks:
maxItems: 2
clock-names:
maxItems: 2
unevaluatedProperties: false
examples:
@@ -163,3 +189,19 @@ examples:
<&clocks SCLK_UART>;
samsung,uart-fifosize = <16>;
};
- |
#include <dt-bindings/clock/google,gs101.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
serial_0: serial@10a00000 {
compatible = "google,gs101-uart";
reg = <0x10a00000 0xc0>;
clocks = <&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP1_PCLK_0>,
<&cmu_peric0 CLK_GOUT_PERIC0_PERIC0_TOP1_IPCLK_0>;
clock-names = "uart", "clk_uart_baud0";
interrupts = <GIC_SPI 634 IRQ_TYPE_LEVEL_HIGH 0>;
pinctrl-0 = <&uart0_bus>;
pinctrl-names = "default";
samsung,uart-fifosize = <256>;
};
@@ -0,0 +1,52 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/fsl,ls1028a.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale layerscape SuperSpeed DWC3 USB SoC controller
maintainers:
- Frank Li <Frank.Li@nxp.com>
select:
properties:
compatible:
contains:
enum:
- fsl,ls1028a-dwc3
required:
- compatible
properties:
compatible:
items:
- enum:
- fsl,ls1028a-dwc3
- const: snps,dwc3
reg:
maxItems: 1
interrupts:
maxItems: 1
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
allOf:
- $ref: snps,dwc3.yaml#
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
usb@fe800000 {
compatible = "fsl,ls1028a-dwc3", "snps,dwc3";
reg = <0xfe800000 0x100000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
};
@@ -1,110 +0,0 @@
MSM SoC HSUSB controllers
EHCI
Required properties:
- compatible: Should contain "qcom,ehci-host"
- regs: offset and length of the register set in the memory map
- usb-phy: phandle for the PHY device
Example EHCI controller device node:
ehci: ehci@f9a55000 {
compatible = "qcom,ehci-host";
reg = <0xf9a55000 0x400>;
usb-phy = <&usb_otg>;
};
USB PHY with optional OTG:
Required properties:
- compatible: Should contain:
"qcom,usb-otg-ci" for chipsets with ChipIdea 45nm PHY
"qcom,usb-otg-snps" for chipsets with Synopsys 28nm PHY
- regs: Offset and length of the register set in the memory map
- interrupts: interrupt-specifier for the OTG interrupt.
- clocks: A list of phandle + clock-specifier pairs for the
clocks listed in clock-names
- clock-names: Should contain the following:
"phy" USB PHY reference clock
"core" Protocol engine clock
"iface" Interface bus clock
"alt_core" Protocol engine clock for targets with asynchronous
reset methodology. (optional)
- vdccx-supply: phandle to the regulator for the vdd supply for
digital circuit operation.
- v1p8-supply: phandle to the regulator for the 1.8V supply
- v3p3-supply: phandle to the regulator for the 3.3V supply
- resets: A list of phandle + reset-specifier pairs for the
resets listed in reset-names
- reset-names: Should contain the following:
"phy" USB PHY controller reset
"link" USB LINK controller reset
- qcom,otg-control: OTG control (VBUS and ID notifications) can be one of
1 - PHY control
2 - PMIC control
Optional properties:
- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
- switch-gpio: A phandle + gpio-specifier pair. Some boards are using Dual
SPDT USB Switch, witch is controlled by GPIO to de/multiplex
D+/D- USB lines between connectors.
- qcom,phy-init-sequence: PHY configuration sequence values. This is related to Device
Mode Eye Diagram test. Start address at which these values will be
written is ULPI_EXT_VENDOR_SPECIFIC. Value of -1 is reserved as
"do not overwrite default value at this address".
For example: qcom,phy-init-sequence = < -1 0x63 >;
Will update only value at address ULPI_EXT_VENDOR_SPECIFIC + 1.
- qcom,phy-num: Select number of pyco-phy to use, can be one of
0 - PHY one, default
1 - Second PHY
Some platforms may have configuration to allow USB
controller work with any of the two HSPHYs present.
- qcom,vdd-levels: This property must be a list of three integer values
(no, min, max) where each value represents either a voltage
in microvolts or a value corresponding to voltage corner.
- qcom,manual-pullup: If present, vbus is not routed to USB controller/phy
and controller driver therefore enables pull-up explicitly
before starting controller using usbcmd run/stop bit.
- extcon: phandles to external connector devices. First phandle
should point to external connector, which provide "USB"
cable events, the second should point to external connector
device, which provide "USB-HOST" cable events. If one of
the external connector devices is not required empty <0>
phandle should be specified.
Example HSUSB OTG controller device node:
usb@f9a55000 {
compatible = "qcom,usb-otg-snps";
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0>;
dr_mode = "peripheral";
clocks = <&gcc GCC_XO_CLK>, <&gcc GCC_USB_HS_SYSTEM_CLK>,
<&gcc GCC_USB_HS_AHB_CLK>;
clock-names = "phy", "core", "iface";
vddcx-supply = <&pm8841_s2_corner>;
v1p8-supply = <&pm8941_l6>;
v3p3-supply = <&pm8941_l24>;
resets = <&gcc GCC_USB2A_PHY_BCR>, <&gcc GCC_USB_HS_BCR>;
reset-names = "phy", "link";
qcom,otg-control = <1>;
qcom,phy-init-sequence = < -1 0x63 >;
qcom,vdd-levels = <1 5 7>;
};
@@ -52,6 +52,7 @@ properties:
- qcom,sm8550-dwc3
- qcom,sm8650-dwc3
- qcom,x1e80100-dwc3
- qcom,x1e80100-dwc3-mp
- const: qcom,dwc3
reg:
@@ -289,6 +290,7 @@ allOf:
- qcom,sc8280xp-dwc3
- qcom,sc8280xp-dwc3-mp
- qcom,x1e80100-dwc3
- qcom,x1e80100-dwc3-mp
then:
properties:
clocks:
@@ -428,6 +430,21 @@ allOf:
contains:
enum:
- qcom,ipq5332-dwc3
then:
properties:
interrupts:
maxItems: 3
interrupt-names:
items:
- const: pwr_event
- const: dp_hs_phy_irq
- const: dm_hs_phy_irq
- if:
properties:
compatible:
contains:
enum:
- qcom,x1e80100-dwc3
then:
properties:
@@ -486,6 +503,7 @@ allOf:
contains:
enum:
- qcom,sc8180x-dwc3-mp
- qcom,x1e80100-dwc3-mp
then:
properties:
interrupts:
@@ -13,10 +13,9 @@ properties:
compatible:
oneOf:
- const: ti,j721e-usb
- const: ti,am64-usb
- items:
- const: ti,j721e-usb
- const: ti,am64-usb
- const: ti,j721e-usb
reg:
maxItems: 1
@@ -368,6 +368,8 @@ patternProperties:
description: Devantech, Ltd.
"^dfi,.*":
description: DFI Inc.
"^dfrobot,.*":
description: DFRobot Corporation
"^dh,.*":
description: DH electronics GmbH
"^difrnce,.*":
+57 -1
View File
@@ -48,11 +48,66 @@ For server running on QEMU host with virtio transport::
mount -t 9p -o trans=virtio <mount_tag> /mnt/9
where mount_tag is the tag associated by the server to each of the exported
where mount_tag is the tag generated by the server to each of the exported
mount points. Each 9P export is seen by the client as a virtio device with an
associated "mount_tag" property. Available mount tags can be
seen by reading /sys/bus/virtio/drivers/9pnet_virtio/virtio<n>/mount_tag files.
USBG Usage
==========
To mount a 9p FS on a USB Host accessible via the gadget at runtime::
mount -t 9p -o trans=usbg,aname=/path/to/fs <device> /mnt/9
To mount a 9p FS on a USB Host accessible via the gadget as root filesystem::
root=<device> rootfstype=9p rootflags=trans=usbg,cache=loose,uname=root,access=0,dfltuid=0,dfltgid=0,aname=/path/to/rootfs
where <device> is the tag associated by the usb gadget transport.
It is defined by the configfs instance name.
USBG Example
============
The USB host exports a filesystem, while the gadget on the USB device
side makes it mountable.
Diod (9pfs server) and the forwarder are on the development host, where
the root filesystem is actually stored. The gadget is initialized during
boot (or later) on the embedded board. Then the forwarder will find it
on the USB bus and start forwarding requests.
In this case the 9p requests come from the device and are handled by the
host. The reason is that USB device ports are normally not available on
PCs, so a connection in the other direction would not work.
When using the usbg transport, for now there is no native usb host
service capable to handle the requests from the gadget driver. For
this we have to use the extra python tool p9_fwd.py from tools/usb.
Just start the 9pfs capable network server like diod/nfs-ganesha e.g.::
$ diod -f -n -d 0 -S -l 0.0.0.0:9999 -e $PWD
Optionaly scan your bus if there are more then one usbg gadgets to find their path::
$ python $kernel_dir/tools/usb/p9_fwd.py list
Bus | Addr | Manufacturer | Product | ID | Path
--- | ---- | ---------------- | ---------------- | --------- | ----
2 | 67 | unknown | unknown | 1d6b:0109 | 2-1.1.2
2 | 68 | unknown | unknown | 1d6b:0109 | 2-1.1.3
Then start the python transport::
$ python $kernel_dir/tools/usb/p9_fwd.py --path 2-1.1.2 connect -p 9999
After that the gadget driver can be used as described above.
One use-case is to use it as an alternative to NFS root booting during
the development of embedded Linux devices.
Options
=======
@@ -68,6 +123,7 @@ Options
virtio connect to the next virtio channel available
(from QEMU with trans_virtio module)
rdma connect to a specified RDMA channel
usbg connect to a specified usb gadget channel
======== ============================================
uname=name user name to attempt mount as on the remote server. The
+39
View File
@@ -0,0 +1,39 @@
======================
FunctionFS Descriptors
======================
Some of the descriptors that can be written to the FFS gadget are
described below. Device and configuration descriptors are handled
by the composite gadget and are not written by the user to the
FFS gadget.
Descriptors are written to the "ep0" file in the FFS gadget
following the descriptor header.
.. kernel-doc:: include/uapi/linux/usb/functionfs.h
:doc: descriptors
Interface Descriptors
---------------------
Standard USB interface descriptors may be written. The class/subclass of the
most recent interface descriptor determines what type of class-specific
descriptors are accepted.
Class-Specific Descriptors
--------------------------
Class-specific descriptors are accepted only for the class/subclass of the
most recent interface descriptor. The following are some of the
class-specific descriptors that are supported.
DFU Functional Descriptor
~~~~~~~~~~~~~~~~~~~~~~~~~
When the interface class is USB_CLASS_APP_SPEC and the interface subclass
is USB_SUBCLASS_DFU, a DFU functional descriptor can be provided.
The DFU functional descriptor is a described in the USB specification for
Device Firmware Upgrade (DFU), version 1.1 as of this writing.
.. kernel-doc:: include/uapi/linux/usb/functionfs.h
:doc: usb_dfu_functional_descriptor
+2
View File
@@ -25,6 +25,8 @@ interface numbers starting from zero). The FunctionFS changes
them as needed also handling situation when numbers differ in
different configurations.
For more information about FunctionFS descriptors see :doc:`functionfs-desc`
When descriptors and strings are written "ep#" files appear
(one for each declared endpoint) which handle communication on
a single endpoint. Again, FunctionFS takes care of the real
+19
View File
@@ -765,6 +765,17 @@ The uac2 function provides these attributes in its function directory:
req_number the number of pre-allocated request for both capture
and playback
function_name name of the interface
if_ctrl_name topology control name
clksrc_in_name input clock name
clksrc_out_name output clock name
p_it_name playback input terminal name
p_it_ch_name playback input first channel name
p_ot_name playback output terminal name
p_fu_vol_name playback function unit name
c_it_name capture input terminal name
c_it_ch_name capture input first channel name
c_ot_name capture output terminal name
c_fu_vol_name capture functional unit name
c_terminal_type code of the capture terminal type
p_terminal_type code of the playback terminal type
================ ====================================================
@@ -957,6 +968,14 @@ The uac1 function provides these attributes in its function directory:
req_number the number of pre-allocated requests for both capture
and playback
function_name name of the interface
p_it_name playback input terminal name
p_it_ch_name playback channels name
p_ot_name playback output terminal name
p_fu_vol_name playback mute/volume functional unit name
c_it_name capture input terminal name
c_it_ch_name capture channels name
c_ot_name capture output terminal name
c_fu_vol_name capture mute/volume functional unit name
================ ====================================================
The attributes have sane default values.
+1
View File
@@ -11,6 +11,7 @@ USB support
dwc3
ehci
functionfs
functionfs-desc
gadget_configfs
gadget_hid
gadget_multi
+7
View File
@@ -6557,6 +6557,12 @@ F: include/net/devlink.h
F: include/uapi/linux/devlink.h
F: net/devlink/
DFROBOT SD2405AL RTC DRIVER
M: Tóth János <gomba007@gmail.com>
L: linux-rtc@vger.kernel.org
S: Maintained
F: drivers/rtc/rtc-sd2405al.c
DH ELECTRONICS IMX6 DHCOM/DHCOR BOARD SUPPORT
M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
L: kernel@dh-electronics.com
@@ -24465,6 +24471,7 @@ F: include/linux/vdpa.h
F: include/linux/virtio*.h
F: include/linux/vringh.h
F: include/uapi/linux/virtio_*.h
F: net/vmw_vsock/virtio*
F: tools/virtio/
F: tools/testing/selftests/drivers/net/virtio_net/
+33
View File
@@ -94,6 +94,39 @@
#pwm-cells = <2>;
};
serial@11002000 {
compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart";
reg = <0 0x11002000 0 0x100>;
interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uart", "wakeup";
clocks = <&infracfg CLK_INFRA_UART0_SEL>,
<&infracfg CLK_INFRA_UART0_CK>;
clock-names = "baud", "bus";
status = "disabled";
};
serial@11003000 {
compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart";
reg = <0 0x11003000 0 0x100>;
interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uart", "wakeup";
clocks = <&infracfg CLK_INFRA_UART1_SEL>,
<&infracfg CLK_INFRA_UART1_CK>;
clock-names = "baud", "bus";
status = "disabled";
};
serial@11004000 {
compatible = "mediatek,mt7981-uart", "mediatek,mt6577-uart";
reg = <0 0x11004000 0 0x100>;
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "uart", "wakeup";
clocks = <&infracfg CLK_INFRA_UART2_SEL>,
<&infracfg CLK_INFRA_UART2_CK>;
clock-names = "baud", "bus";
status = "disabled";
};
i2c@11007000 {
compatible = "mediatek,mt7981-i2c";
reg = <0 0x11007000 0 0x1000>,
+2 -2
View File
@@ -555,7 +555,7 @@ retry:
/* if claiming is already in progress, wait for it to finish */
if (whole->bd_claiming) {
wait_queue_head_t *wq = bit_waitqueue(&whole->bd_claiming, 0);
wait_queue_head_t *wq = __var_waitqueue(&whole->bd_claiming);
DEFINE_WAIT(wait);
prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
@@ -578,7 +578,7 @@ static void bd_clear_claiming(struct block_device *whole, void *holder)
/* tell others that we're done */
BUG_ON(whole->bd_claiming != holder);
whole->bd_claiming = NULL;
wake_up_bit(&whole->bd_claiming, 0);
wake_up_var(&whole->bd_claiming);
}
/**
-1
View File
@@ -367,7 +367,6 @@ free_bvec:
kfree(bvec);
return ret;
}
EXPORT_SYMBOL_GPL(bio_integrity_map_user);
/**
* bio_integrity_prep - Prepare bio for integrity I/O
+25 -11
View File
@@ -53,7 +53,6 @@ new_segment:
return segments;
}
EXPORT_SYMBOL(blk_rq_count_integrity_sg);
/**
* blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
@@ -63,19 +62,20 @@ EXPORT_SYMBOL(blk_rq_count_integrity_sg);
*
* Description: Map the integrity vectors in request into a
* scatterlist. The scatterlist must be big enough to hold all
* elements. I.e. sized using blk_rq_count_integrity_sg().
* elements. I.e. sized using blk_rq_count_integrity_sg() or
* rq->nr_integrity_segments.
*/
int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio,
struct scatterlist *sglist)
int blk_rq_map_integrity_sg(struct request *rq, struct scatterlist *sglist)
{
struct bio_vec iv, ivprv = { NULL };
struct request_queue *q = rq->q;
struct scatterlist *sg = NULL;
struct bio *bio = rq->bio;
unsigned int segments = 0;
struct bvec_iter iter;
int prev = 0;
bio_for_each_integrity_vec(iv, bio, iter) {
if (prev) {
if (!biovec_phys_mergeable(q, &ivprv, &iv))
goto new_segment;
@@ -103,10 +103,30 @@ new_segment:
if (sg)
sg_mark_end(sg);
/*
* Something must have been wrong if the figured number of segment
* is bigger than number of req's physical integrity segments
*/
BUG_ON(segments > rq->nr_integrity_segments);
BUG_ON(segments > queue_max_integrity_segments(q));
return segments;
}
EXPORT_SYMBOL(blk_rq_map_integrity_sg);
int blk_rq_integrity_map_user(struct request *rq, void __user *ubuf,
ssize_t bytes, u32 seed)
{
int ret = bio_integrity_map_user(rq->bio, ubuf, bytes, seed);
if (ret)
return ret;
rq->nr_integrity_segments = blk_rq_count_integrity_sg(rq->q, rq->bio);
rq->cmd_flags |= REQ_INTEGRITY;
return 0;
}
EXPORT_SYMBOL_GPL(blk_rq_integrity_map_user);
bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
struct request *next)
{
@@ -134,7 +154,6 @@ bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
struct bio *bio)
{
int nr_integrity_segs;
struct bio *next = bio->bi_next;
if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL)
return true;
@@ -145,16 +164,11 @@ bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags)
return false;
bio->bi_next = NULL;
nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
bio->bi_next = next;
if (req->nr_integrity_segments + nr_integrity_segs >
q->limits.max_integrity_segments)
return false;
req->nr_integrity_segments += nr_integrity_segs;
return true;
}
+4
View File
@@ -639,6 +639,9 @@ static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
* counters.
*/
req->nr_phys_segments += nr_phys_segs;
if (bio_integrity(bio))
req->nr_integrity_segments += blk_rq_count_integrity_sg(req->q,
bio);
return 1;
no_merge:
@@ -731,6 +734,7 @@ static int ll_merge_requests_fn(struct request_queue *q, struct request *req,
/* Merge is OK... */
req->nr_phys_segments = total_phys_segments;
req->nr_integrity_segments += next->nr_integrity_segments;
return 1;
}
+3 -2
View File
@@ -376,9 +376,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
rq->io_start_time_ns = 0;
rq->stats_sectors = 0;
rq->nr_phys_segments = 0;
#if defined(CONFIG_BLK_DEV_INTEGRITY)
rq->nr_integrity_segments = 0;
#endif
rq->end_io = NULL;
rq->end_io_data = NULL;
@@ -2546,6 +2544,9 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio,
rq->__sector = bio->bi_iter.bi_sector;
rq->write_hint = bio->bi_write_hint;
blk_rq_bio_prep(rq, bio, nr_segs);
if (bio_integrity(bio))
rq->nr_integrity_segments = blk_rq_count_integrity_sg(rq->q,
bio);
/* This can't fail, since GFP_NOIO includes __GFP_DIRECT_RECLAIM. */
err = blk_crypto_rq_bio_prep(rq, bio, GFP_NOIO);
-42
View File
@@ -437,48 +437,6 @@ int queue_limits_set(struct request_queue *q, struct queue_limits *lim)
}
EXPORT_SYMBOL_GPL(queue_limits_set);
/**
* blk_limits_io_min - set minimum request size for a device
* @limits: the queue limits
* @min: smallest I/O size in bytes
*
* Description:
* Some devices have an internal block size bigger than the reported
* hardware sector size. This function can be used to signal the
* smallest I/O the device can perform without incurring a performance
* penalty.
*/
void blk_limits_io_min(struct queue_limits *limits, unsigned int min)
{
limits->io_min = min;
if (limits->io_min < limits->logical_block_size)
limits->io_min = limits->logical_block_size;
if (limits->io_min < limits->physical_block_size)
limits->io_min = limits->physical_block_size;
}
EXPORT_SYMBOL(blk_limits_io_min);
/**
* blk_limits_io_opt - set optimal request size for a device
* @limits: the queue limits
* @opt: smallest I/O size in bytes
*
* Description:
* Storage devices may report an optimal I/O size, which is the
* device's preferred unit for sustained I/O. This is rarely reported
* for disk drives. For RAID arrays it is usually the stripe width or
* the internal track size. A properly aligned multiple of
* optimal_io_size is the preferred request size for workloads where
* sustained throughput is desired.
*/
void blk_limits_io_opt(struct queue_limits *limits, unsigned int opt)
{
limits->io_opt = opt;
}
EXPORT_SYMBOL(blk_limits_io_opt);
static int queue_limit_alignment_offset(const struct queue_limits *lim,
sector_t sector)
{
+3 -1
View File
@@ -715,7 +715,9 @@ int elv_iosched_load_module(struct gendisk *disk, const char *buf,
strscpy(elevator_name, buf, sizeof(elevator_name));
return request_module("%s-iosched", strstrip(elevator_name));
request_module("%s-iosched", strstrip(elevator_name));
return 0;
}
ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
+5 -3
View File
@@ -3399,10 +3399,12 @@ void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
{
unsigned long flags;
if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
return;
spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) {
spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
return;
}
if (val == 0) {
drbd_uuid_move_history(device);
device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP];
+1 -1
View File
@@ -452,7 +452,7 @@ static void fw_cfg_sysfs_release_entry(struct kobject *kobj)
}
/* kobj_type: ties together all properties required to register an entry */
static struct kobj_type fw_cfg_sysfs_entry_ktype = {
static const struct kobj_type fw_cfg_sysfs_entry_ktype = {
.default_groups = fw_cfg_sysfs_entry_groups,
.sysfs_ops = &fw_cfg_sysfs_attr_ops,
.release = fw_cfg_sysfs_release_entry,
-9
View File
@@ -786,14 +786,6 @@ static const struct acpi_device_id goodix_spi_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, goodix_spi_acpi_match);
#endif
#ifdef CONFIG_OF
static const struct of_device_id goodix_spi_of_match[] = {
{ .compatible = "goodix,gt7986u", },
{ }
};
MODULE_DEVICE_TABLE(of, goodix_spi_of_match);
#endif
static const struct spi_device_id goodix_spi_ids[] = {
{ "gt7986u" },
{ },
@@ -804,7 +796,6 @@ static struct spi_driver goodix_spi_driver = {
.driver = {
.name = "goodix-spi-hid",
.acpi_match_table = ACPI_PTR(goodix_spi_acpi_match),
.of_match_table = of_match_ptr(goodix_spi_of_match),
.pm = pm_sleep_ptr(&goodix_spi_pm_ops),
},
.probe = goodix_spi_probe,
+16 -5
View File
@@ -1887,10 +1887,12 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
throttle_op = mlx5_cmd_is_throttle_opcode(opcode);
if (throttle_op) {
/* atomic context may not sleep */
if (callback)
return -EINVAL;
down(&dev->cmd.vars.throttle_sem);
if (callback) {
if (down_trylock(&dev->cmd.vars.throttle_sem))
return -EBUSY;
} else {
down(&dev->cmd.vars.throttle_sem);
}
}
pages_queue = is_manage_pages(in);
@@ -2096,10 +2098,19 @@ static void mlx5_cmd_exec_cb_handler(int status, void *_work)
{
struct mlx5_async_work *work = _work;
struct mlx5_async_ctx *ctx;
struct mlx5_core_dev *dev;
u16 opcode;
ctx = work->ctx;
status = cmd_status_err(ctx->dev, status, work->opcode, work->op_mod, work->out);
dev = ctx->dev;
opcode = work->opcode;
status = cmd_status_err(dev, status, work->opcode, work->op_mod, work->out);
work->user_callback(status, work);
/* Can't access "work" from this point on. It could have been freed in
* the callback.
*/
if (mlx5_cmd_is_throttle_opcode(opcode))
up(&dev->cmd.vars.throttle_sem);
if (atomic_dec_and_test(&ctx->num_inflight))
complete(&ctx->inflight_done);
}
+20 -40
View File
@@ -37,8 +37,6 @@
#include <linux/semaphore.h>
#include <linux/refcount.h>
#define SIXPACK_VERSION "Revision: 0.3.0"
/* sixpack priority commands */
#define SIXP_SEOF 0x40 /* start and end of a 6pack frame */
#define SIXP_TX_URUN 0x48 /* transmit overrun */
@@ -88,22 +86,18 @@ struct sixpack {
struct net_device *dev; /* easy for intr handling */
/* These are pointers to the malloc()ed frame buffers. */
unsigned char *rbuff; /* receiver buffer */
int rcount; /* received chars counter */
unsigned char *xbuff; /* transmitter buffer */
unsigned char *xhead; /* next byte to XMIT */
int xleft; /* bytes left in XMIT queue */
unsigned char raw_buf[4];
unsigned char cooked_buf[400];
u8 raw_buf[4];
u8 cooked_buf[400];
unsigned int rx_count;
unsigned int rx_count_cooked;
spinlock_t rxlock;
int mtu; /* Our mtu (to spot changes!) */
int buffsize; /* Max buffers sizes */
unsigned long flags; /* Flag values/ mode etc */
unsigned char mode; /* 6pack mode */
@@ -113,8 +107,8 @@ struct sixpack {
unsigned char slottime;
unsigned char duplex;
unsigned char led_state;
unsigned char status;
unsigned char status1;
u8 status;
u8 status1;
unsigned char status2;
unsigned char tx_enable;
unsigned char tnc_state;
@@ -128,7 +122,7 @@ struct sixpack {
#define AX25_6PACK_HEADER_LEN 0
static void sixpack_decode(struct sixpack *, const unsigned char[], int);
static void sixpack_decode(struct sixpack *, const u8 *, size_t);
static int encode_sixpack(unsigned char *, unsigned char *, int, unsigned char);
/*
@@ -167,7 +161,7 @@ static void sp_encaps(struct sixpack *sp, unsigned char *icp, int len)
unsigned char *msg, *p = icp;
int actual, count;
if (len > sp->mtu) { /* sp->mtu = AX25_MTU = max. PACLEN = 256 */
if (len > AX25_MTU + 73) {
msg = "oversized transmit packet!";
goto out_drop;
}
@@ -333,7 +327,7 @@ static void sp_bump(struct sixpack *sp, char cmd)
{
struct sk_buff *skb;
int count;
unsigned char *ptr;
u8 *ptr;
count = sp->rcount + 1;
@@ -431,7 +425,7 @@ static void sixpack_receive_buf(struct tty_struct *tty, const u8 *cp,
const u8 *fp, size_t count)
{
struct sixpack *sp;
int count1;
size_t count1;
if (!count)
return;
@@ -544,7 +538,7 @@ static inline int tnc_init(struct sixpack *sp)
*/
static int sixpack_open(struct tty_struct *tty)
{
char *rbuff = NULL, *xbuff = NULL;
char *xbuff = NULL;
struct net_device *dev;
struct sixpack *sp;
unsigned long len;
@@ -574,10 +568,8 @@ static int sixpack_open(struct tty_struct *tty)
len = dev->mtu * 2;
rbuff = kmalloc(len + 4, GFP_KERNEL);
xbuff = kmalloc(len + 4, GFP_KERNEL);
if (rbuff == NULL || xbuff == NULL) {
if (xbuff == NULL) {
err = -ENOBUFS;
goto out_free;
}
@@ -586,11 +578,8 @@ static int sixpack_open(struct tty_struct *tty)
sp->tty = tty;
sp->rbuff = rbuff;
sp->xbuff = xbuff;
sp->mtu = AX25_MTU + 73;
sp->buffsize = len;
sp->rcount = 0;
sp->rx_count = 0;
sp->rx_count_cooked = 0;
@@ -631,7 +620,6 @@ static int sixpack_open(struct tty_struct *tty)
out_free:
kfree(xbuff);
kfree(rbuff);
free_netdev(dev);
@@ -676,7 +664,6 @@ static void sixpack_close(struct tty_struct *tty)
del_timer_sync(&sp->resync_t);
/* Free all 6pack frame buffers after unreg. */
kfree(sp->rbuff);
kfree(sp->xbuff);
free_netdev(sp->dev);
@@ -756,21 +743,14 @@ static struct tty_ldisc_ops sp_ldisc = {
/* Initialize 6pack control device -- register 6pack line discipline */
static const char msg_banner[] __initconst = KERN_INFO \
"AX.25: 6pack driver, " SIXPACK_VERSION "\n";
static const char msg_regfail[] __initconst = KERN_ERR \
"6pack: can't register line discipline (err = %d)\n";
static int __init sixpack_init_driver(void)
{
int status;
printk(msg_banner);
/* Register the provided line protocol discipline */
status = tty_register_ldisc(&sp_ldisc);
if (status)
printk(msg_regfail, status);
pr_err("6pack: can't register line discipline (err = %d)\n", status);
return status;
}
@@ -820,9 +800,9 @@ static int encode_sixpack(unsigned char *tx_buf, unsigned char *tx_buf_raw,
/* decode 4 sixpack-encoded bytes into 3 data bytes */
static void decode_data(struct sixpack *sp, unsigned char inbyte)
static void decode_data(struct sixpack *sp, u8 inbyte)
{
unsigned char *buf;
u8 *buf;
if (sp->rx_count != 3) {
sp->raw_buf[sp->rx_count++] = inbyte;
@@ -848,9 +828,9 @@ static void decode_data(struct sixpack *sp, unsigned char inbyte)
/* identify and execute a 6pack priority command byte */
static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
static void decode_prio_command(struct sixpack *sp, u8 cmd)
{
int actual;
ssize_t actual;
if ((cmd & SIXP_PRIO_DATA_MASK) != 0) { /* idle ? */
@@ -898,9 +878,9 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd)
/* identify and execute a standard 6pack command byte */
static void decode_std_command(struct sixpack *sp, unsigned char cmd)
static void decode_std_command(struct sixpack *sp, u8 cmd)
{
unsigned char checksum = 0, rest = 0;
u8 checksum = 0, rest = 0;
short i;
switch (cmd & SIXP_CMD_MASK) { /* normal command */
@@ -948,10 +928,10 @@ static void decode_std_command(struct sixpack *sp, unsigned char cmd)
/* decode a 6pack packet */
static void
sixpack_decode(struct sixpack *sp, const unsigned char *pre_rbuff, int count)
sixpack_decode(struct sixpack *sp, const u8 *pre_rbuff, size_t count)
{
unsigned char inbyte;
int count1;
size_t count1;
u8 inbyte;
for (count1 = 0; count1 < count; count1++) {
inbyte = pre_rbuff[count1];
+12 -11
View File
@@ -64,18 +64,18 @@ struct mctp_serial {
u16 txfcs, rxfcs, rxfcs_rcvd;
unsigned int txlen, rxlen;
unsigned int txpos, rxpos;
unsigned char txbuf[BUFSIZE],
u8 txbuf[BUFSIZE],
rxbuf[BUFSIZE];
};
static bool needs_escape(unsigned char c)
static bool needs_escape(u8 c)
{
return c == BYTE_ESC || c == BYTE_FRAME;
}
static int next_chunk_len(struct mctp_serial *dev)
static unsigned int next_chunk_len(struct mctp_serial *dev)
{
int i;
unsigned int i;
/* either we have no bytes to send ... */
if (dev->txpos == dev->txlen)
@@ -99,7 +99,7 @@ static int next_chunk_len(struct mctp_serial *dev)
return i;
}
static int write_chunk(struct mctp_serial *dev, unsigned char *buf, int len)
static ssize_t write_chunk(struct mctp_serial *dev, u8 *buf, size_t len)
{
return dev->tty->ops->write(dev->tty, buf, len);
}
@@ -108,9 +108,10 @@ static void mctp_serial_tx_work(struct work_struct *work)
{
struct mctp_serial *dev = container_of(work, struct mctp_serial,
tx_work);
unsigned char c, buf[3];
unsigned long flags;
int len, txlen;
ssize_t txlen;
unsigned int len;
u8 c, buf[3];
spin_lock_irqsave(&dev->lock, flags);
@@ -293,7 +294,7 @@ static void mctp_serial_rx(struct mctp_serial *dev)
dev->netdev->stats.rx_bytes += dev->rxlen;
}
static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c)
static void mctp_serial_push_header(struct mctp_serial *dev, u8 c)
{
switch (dev->rxpos) {
case 0:
@@ -323,7 +324,7 @@ static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c)
}
}
static void mctp_serial_push_trailer(struct mctp_serial *dev, unsigned char c)
static void mctp_serial_push_trailer(struct mctp_serial *dev, u8 c)
{
switch (dev->rxpos) {
case 0:
@@ -347,7 +348,7 @@ static void mctp_serial_push_trailer(struct mctp_serial *dev, unsigned char c)
}
}
static void mctp_serial_push(struct mctp_serial *dev, unsigned char c)
static void mctp_serial_push(struct mctp_serial *dev, u8 c)
{
switch (dev->rxstate) {
case STATE_IDLE:
@@ -394,7 +395,7 @@ static void mctp_serial_tty_receive_buf(struct tty_struct *tty, const u8 *c,
const u8 *f, size_t len)
{
struct mctp_serial *dev = tty->disc_data;
int i;
size_t i;
if (!netif_running(dev->netdev))
return;
+9
View File
@@ -44,6 +44,15 @@ static int virtio_pmem_flush(struct nd_region *nd_region)
unsigned long flags;
int err, err1;
/*
* Don't bother to submit the request to the device if the device is
* not activated.
*/
if (vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
dev_info(&vdev->dev, "virtio pmem device needs a reset\n");
return -EIO;
}
might_sleep();
req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
if (!req_data)
-5
View File
@@ -2468,11 +2468,6 @@ int nvme_enable_ctrl(struct nvme_ctrl *ctrl)
if (ret)
return ret;
/* Flush write to device (required if transport is PCI) */
ret = ctrl->ops->reg_read32(ctrl, NVME_REG_CC, &ctrl->ctrl_config);
if (ret)
return ret;
/* CAP value may change after initial CC write */
ret = ctrl->ops->reg_read64(ctrl, NVME_REG_CAP, &ctrl->cap);
if (ret)
+2 -4
View File
@@ -3,7 +3,6 @@
* Copyright (c) 2011-2014, Intel Corporation.
* Copyright (c) 2017-2021 Christoph Hellwig.
*/
#include <linux/bio-integrity.h>
#include <linux/blk-integrity.h>
#include <linux/ptrace.h> /* for force_successful_syscall_return */
#include <linux/nvme_ioctl.h>
@@ -153,11 +152,10 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
bio_set_dev(bio, bdev);
if (has_metadata) {
ret = bio_integrity_map_user(bio, meta_buffer, meta_len,
meta_seed);
ret = blk_rq_integrity_map_user(req, meta_buffer, meta_len,
meta_seed);
if (ret)
goto out_unmap;
req->cmd_flags |= REQ_INTEGRITY;
}
return ret;
+11 -3
View File
@@ -421,6 +421,9 @@ static bool nvme_available_path(struct nvme_ns_head *head)
{
struct nvme_ns *ns;
if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
return NULL;
list_for_each_entry_rcu(ns, &head->list, siblings) {
if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags))
continue;
@@ -648,7 +651,7 @@ static void nvme_mpath_set_live(struct nvme_ns *ns)
rc = device_add_disk(&head->subsys->dev, head->disk,
nvme_ns_attr_groups);
if (rc) {
clear_bit(NVME_NSHEAD_DISK_LIVE, &ns->flags);
clear_bit(NVME_NSHEAD_DISK_LIVE, &head->flags);
return;
}
nvme_add_ns_head_cdev(head);
@@ -969,11 +972,16 @@ void nvme_mpath_shutdown_disk(struct nvme_ns_head *head)
{
if (!head->disk)
return;
kblockd_schedule_work(&head->requeue_work);
if (test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
if (test_and_clear_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
nvme_cdev_del(&head->cdev, &head->cdev_device);
del_gendisk(head->disk);
}
/*
* requeue I/O after NVME_NSHEAD_DISK_LIVE has been cleared
* to allow multipath to fail all I/O.
*/
synchronize_srcu(&head->srcu);
kblockd_schedule_work(&head->requeue_work);
}
void nvme_mpath_remove_disk(struct nvme_ns_head *head)
+3 -3
View File
@@ -1496,7 +1496,7 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq,
req->metadata_sgl->sg_table.sgl =
(struct scatterlist *)(req->metadata_sgl + 1);
ret = sg_alloc_table_chained(&req->metadata_sgl->sg_table,
blk_rq_count_integrity_sg(rq->q, rq->bio),
rq->nr_integrity_segments,
req->metadata_sgl->sg_table.sgl,
NVME_INLINE_METADATA_SG_CNT);
if (unlikely(ret)) {
@@ -1504,8 +1504,8 @@ static int nvme_rdma_dma_map_req(struct ib_device *ibdev, struct request *rq,
goto out_unmap_sg;
}
req->metadata_sgl->nents = blk_rq_map_integrity_sg(rq->q,
rq->bio, req->metadata_sgl->sg_table.sgl);
req->metadata_sgl->nents = blk_rq_map_integrity_sg(rq,
req->metadata_sgl->sg_table.sgl);
*pi_count = ib_dma_map_sg(ibdev,
req->metadata_sgl->sg_table.sgl,
req->metadata_sgl->nents,
+1
View File
@@ -767,6 +767,7 @@ static struct attribute *nvme_tls_attrs[] = {
&dev_attr_tls_key.attr,
&dev_attr_tls_configured_key.attr,
&dev_attr_tls_keyring.attr,
NULL,
};
static umode_t nvme_tls_attrs_are_visible(struct kobject *kobj,
+16
View File
@@ -743,6 +743,16 @@ config RTC_DRV_S5M
This driver can also be built as a module. If so, the module
will be called rtc-s5m.
config RTC_DRV_SD2405AL
tristate "DFRobot SD2405AL"
select REGMAP_I2C
help
If you say yes here you will get support for the
DFRobot SD2405AL I2C RTC Module.
This driver can also be built as a module. If so, the module
will be called rtc-sd2405al.
config RTC_DRV_SD3078
tristate "ZXW Shenzhen whwave SD3078"
select REGMAP_I2C
@@ -1934,6 +1944,12 @@ config RTC_DRV_STM32
tristate "STM32 RTC"
select REGMAP_MMIO
depends on ARCH_STM32 || COMPILE_TEST
depends on OF
depends on PINCTRL
select PINMUX
select PINCONF
select GENERIC_PINCONF
depends on COMMON_CLK
help
If you say yes here you get support for the STM32 On-Chip
Real Time Clock.
+1
View File
@@ -163,6 +163,7 @@ obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o
obj-$(CONFIG_RTC_DRV_SD2405AL) += rtc-sd2405al.o
obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
+1
View File
@@ -368,6 +368,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
return ret;
rtc->gpbr = syscon_node_to_regmap(args.np);
of_node_put(args.np);
rtc->gpbr_offset = args.args[0];
if (IS_ERR(rtc->gpbr)) {
dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n");
+3 -1
View File
@@ -132,7 +132,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR);
if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100))
if (pdata->type == M48T59RTC_TYPE_M48T59 && (year >= 100))
val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
val |= (bin2bcd(tm->tm_wday) & 0x07);
M48T59_WRITE(val, M48T59_WDAY);
@@ -458,6 +458,8 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, m48t59);
m48t59->rtc->ops = &m48t59_rtc_ops;
m48t59->rtc->range_min = RTC_TIMESTAMP_BEGIN_1900;
m48t59->rtc->range_max = RTC_TIMESTAMP_END_2099;
nvmem_cfg.size = pdata->offset;
ret = devm_rtc_nvmem_register(m48t59->rtc, &nvmem_cfg);
+11 -2
View File
@@ -429,14 +429,23 @@ static int rc5t619_rtc_probe(struct platform_device *pdev)
return devm_rtc_register_device(rtc->rtc);
}
static const struct platform_device_id rc5t619_rtc_id[] = {
{
.name = "rc5t619-rtc",
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, rc5t619_rtc_id);
static struct platform_driver rc5t619_rtc_driver = {
.driver = {
.name = "rc5t619-rtc",
},
.probe = rc5t619_rtc_probe,
.id_table = rc5t619_rtc_id,
};
module_platform_driver(rc5t619_rtc_driver);
MODULE_ALIAS("platform:rc5t619-rtc");
MODULE_DESCRIPTION("RICOH RC5T619 RTC driver");
MODULE_LICENSE("GPL");
-1
View File
@@ -56,7 +56,6 @@ static const struct i2c_device_id s35390a_id[] = {
MODULE_DEVICE_TABLE(i2c, s35390a_id);
static const __maybe_unused struct of_device_id s35390a_of_match[] = {
{ .compatible = "s35390a" },
{ .compatible = "sii,s35390a" },
{ }
};
+227
View File
@@ -0,0 +1,227 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* RTC driver for the SD2405AL Real-Time Clock
*
* Datasheet:
* https://image.dfrobot.com/image/data/TOY0021/SD2405AL%20datasheet%20(Angelo%20v0.1).pdf
*
* Copyright (C) 2024 Tóth János <gomba007@gmail.com>
*/
#include <linux/bcd.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
/* Real time clock registers */
#define SD2405AL_REG_T_SEC 0x00
#define SD2405AL_REG_T_MIN 0x01
#define SD2405AL_REG_T_HOUR 0x02
# define SD2405AL_BIT_12H_PM BIT(5)
# define SD2405AL_BIT_24H BIT(7)
#define SD2405AL_REG_T_WEEK 0x03
#define SD2405AL_REG_T_DAY 0x04
#define SD2405AL_REG_T_MON 0x05
#define SD2405AL_REG_T_YEAR 0x06
#define SD2405AL_NUM_T_REGS (SD2405AL_REG_T_YEAR - SD2405AL_REG_T_SEC + 1)
/* Control registers */
#define SD2405AL_REG_CTR1 0x0F
# define SD2405AL_BIT_WRTC2 BIT(2)
# define SD2405AL_BIT_WRTC3 BIT(7)
#define SD2405AL_REG_CTR2 0x10
# define SD2405AL_BIT_WRTC1 BIT(7)
#define SD2405AL_REG_CTR3 0x11
#define SD2405AL_REG_TTF 0x12
#define SD2405AL_REG_CNTDWN 0x13
/* General RAM */
#define SD2405AL_REG_M_START 0x14
#define SD2405AL_REG_M_END 0x1F
struct sd2405al {
struct device *dev;
struct rtc_device *rtc;
struct regmap *regmap;
};
static int sd2405al_enable_reg_write(struct sd2405al *sd2405al)
{
int ret;
/* order of writes is important */
ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR2,
SD2405AL_BIT_WRTC1, SD2405AL_BIT_WRTC1);
if (ret < 0)
return ret;
ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR1,
SD2405AL_BIT_WRTC2 | SD2405AL_BIT_WRTC3,
SD2405AL_BIT_WRTC2 | SD2405AL_BIT_WRTC3);
if (ret < 0)
return ret;
return 0;
}
static int sd2405al_disable_reg_write(struct sd2405al *sd2405al)
{
int ret;
/* order of writes is important */
ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR1,
SD2405AL_BIT_WRTC2 | SD2405AL_BIT_WRTC3, 0x00);
if (ret < 0)
return ret;
ret = regmap_update_bits(sd2405al->regmap, SD2405AL_REG_CTR2,
SD2405AL_BIT_WRTC1, 0x00);
if (ret < 0)
return ret;
return 0;
}
static int sd2405al_read_time(struct device *dev, struct rtc_time *time)
{
u8 data[SD2405AL_NUM_T_REGS] = { 0 };
struct sd2405al *sd2405al = dev_get_drvdata(dev);
int ret;
ret = regmap_bulk_read(sd2405al->regmap, SD2405AL_REG_T_SEC, data,
SD2405AL_NUM_T_REGS);
if (ret < 0)
return ret;
time->tm_sec = bcd2bin(data[SD2405AL_REG_T_SEC] & 0x7F);
time->tm_min = bcd2bin(data[SD2405AL_REG_T_MIN] & 0x7F);
if (data[SD2405AL_REG_T_HOUR] & SD2405AL_BIT_24H)
time->tm_hour = bcd2bin(data[SD2405AL_REG_T_HOUR] & 0x3F);
else
if (data[SD2405AL_REG_T_HOUR] & SD2405AL_BIT_12H_PM)
time->tm_hour = bcd2bin(data[SD2405AL_REG_T_HOUR]
& 0x1F) + 12;
else /* 12 hour mode, AM */
time->tm_hour = bcd2bin(data[SD2405AL_REG_T_HOUR]
& 0x1F);
time->tm_wday = bcd2bin(data[SD2405AL_REG_T_WEEK] & 0x07);
time->tm_mday = bcd2bin(data[SD2405AL_REG_T_DAY] & 0x3F);
time->tm_mon = bcd2bin(data[SD2405AL_REG_T_MON] & 0x1F) - 1;
time->tm_year = bcd2bin(data[SD2405AL_REG_T_YEAR]) + 100;
dev_dbg(sd2405al->dev, "read time: %ptR (%d)\n", time, time->tm_wday);
return 0;
}
static int sd2405al_set_time(struct device *dev, struct rtc_time *time)
{
u8 data[SD2405AL_NUM_T_REGS];
struct sd2405al *sd2405al = dev_get_drvdata(dev);
int ret;
data[SD2405AL_REG_T_SEC] = bin2bcd(time->tm_sec);
data[SD2405AL_REG_T_MIN] = bin2bcd(time->tm_min);
data[SD2405AL_REG_T_HOUR] = bin2bcd(time->tm_hour) | SD2405AL_BIT_24H;
data[SD2405AL_REG_T_DAY] = bin2bcd(time->tm_mday);
data[SD2405AL_REG_T_WEEK] = bin2bcd(time->tm_wday);
data[SD2405AL_REG_T_MON] = bin2bcd(time->tm_mon) + 1;
data[SD2405AL_REG_T_YEAR] = bin2bcd(time->tm_year - 100);
ret = sd2405al_enable_reg_write(sd2405al);
if (ret < 0)
return ret;
ret = regmap_bulk_write(sd2405al->regmap, SD2405AL_REG_T_SEC, data,
SD2405AL_NUM_T_REGS);
if (ret < 0)
return ret;
ret = regmap_write(sd2405al->regmap, SD2405AL_REG_TTF, 0x00);
if (ret < 0)
return ret;
ret = sd2405al_disable_reg_write(sd2405al);
if (ret < 0)
return ret;
dev_dbg(sd2405al->dev, "set time: %ptR (%d)\n", time, time->tm_wday);
return 0;
}
static const struct rtc_class_ops sd2405al_rtc_ops = {
.read_time = sd2405al_read_time,
.set_time = sd2405al_set_time,
};
static const struct regmap_config sd2405al_regmap_conf = {
.reg_bits = 8,
.val_bits = 8,
.max_register = SD2405AL_REG_M_END,
};
static int sd2405al_probe(struct i2c_client *client)
{
struct sd2405al *sd2405al;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
sd2405al = devm_kzalloc(&client->dev, sizeof(*sd2405al), GFP_KERNEL);
if (!sd2405al)
return -ENOMEM;
sd2405al->dev = &client->dev;
sd2405al->regmap = devm_regmap_init_i2c(client, &sd2405al_regmap_conf);
if (IS_ERR(sd2405al->regmap))
return PTR_ERR(sd2405al->regmap);
sd2405al->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(sd2405al->rtc))
return PTR_ERR(sd2405al->rtc);
sd2405al->rtc->ops = &sd2405al_rtc_ops;
sd2405al->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
sd2405al->rtc->range_max = RTC_TIMESTAMP_END_2099;
dev_set_drvdata(&client->dev, sd2405al);
ret = devm_rtc_register_device(sd2405al->rtc);
if (ret < 0)
return ret;
return 0;
}
static const struct i2c_device_id sd2405al_id[] = {
{ "sd2405al" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, sd2405al_id);
static const __maybe_unused struct of_device_id sd2405al_of_match[] = {
{ .compatible = "dfrobot,sd2405al" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sd2405al_of_match);
static struct i2c_driver sd2405al_driver = {
.driver = {
.name = "sd2405al",
.of_match_table = of_match_ptr(sd2405al_of_match),
},
.probe = sd2405al_probe,
.id_table = sd2405al_id,
};
module_i2c_driver(sd2405al_driver);
MODULE_AUTHOR("Tóth János <gomba007@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SD2405AL RTC driver");
+281
View File
@@ -7,12 +7,16 @@
#include <linux/bcd.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/errno.h>
#include <linux/iopoll.h>
#include <linux/ioport.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/regmap.h>
@@ -42,6 +46,12 @@
#define STM32_RTC_CR_FMT BIT(6)
#define STM32_RTC_CR_ALRAE BIT(8)
#define STM32_RTC_CR_ALRAIE BIT(12)
#define STM32_RTC_CR_OSEL GENMASK(22, 21)
#define STM32_RTC_CR_OSEL_ALARM_A FIELD_PREP(STM32_RTC_CR_OSEL, 0x01)
#define STM32_RTC_CR_COE BIT(23)
#define STM32_RTC_CR_TAMPOE BIT(26)
#define STM32_RTC_CR_TAMPALRM_TYPE BIT(30)
#define STM32_RTC_CR_OUT2EN BIT(31)
/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
#define STM32_RTC_ISR_ALRAWF BIT(0)
@@ -78,6 +88,12 @@
/* STM32_RTC_SR/_SCR bit fields */
#define STM32_RTC_SR_ALRA BIT(0)
/* STM32_RTC_CFGR bit fields */
#define STM32_RTC_CFGR_OUT2_RMP BIT(0)
#define STM32_RTC_CFGR_LSCOEN GENMASK(2, 1)
#define STM32_RTC_CFGR_LSCOEN_OUT1 1
#define STM32_RTC_CFGR_LSCOEN_OUT2_RMP 2
/* STM32_RTC_VERR bit fields */
#define STM32_RTC_VERR_MINREV_SHIFT 0
#define STM32_RTC_VERR_MINREV GENMASK(3, 0)
@@ -107,6 +123,14 @@
/* STM32 RTC driver time helpers */
#define SEC_PER_DAY (24 * 60 * 60)
/* STM32 RTC pinctrl helpers */
#define STM32_RTC_PINMUX(_name, _action, ...) { \
.name = (_name), \
.action = (_action), \
.groups = ((const char *[]){ __VA_ARGS__ }), \
.num_groups = ARRAY_SIZE(((const char *[]){ __VA_ARGS__ })), \
}
struct stm32_rtc;
struct stm32_rtc_registers {
@@ -119,6 +143,7 @@ struct stm32_rtc_registers {
u16 wpr;
u16 sr;
u16 scr;
u16 cfgr;
u16 verr;
};
@@ -134,6 +159,8 @@ struct stm32_rtc_data {
bool need_dbp;
bool need_accuracy;
bool rif_protected;
bool has_lsco;
bool has_alarm_out;
};
struct stm32_rtc {
@@ -146,6 +173,7 @@ struct stm32_rtc {
struct clk *rtc_ck;
const struct stm32_rtc_data *data;
int irq_alarm;
struct clk *clk_lsco;
};
struct stm32_rtc_rif_resource {
@@ -171,6 +199,209 @@ static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr);
}
enum stm32_rtc_pin_name {
NONE,
OUT1,
OUT2,
OUT2_RMP
};
static const struct pinctrl_pin_desc stm32_rtc_pinctrl_pins[] = {
PINCTRL_PIN(OUT1, "out1"),
PINCTRL_PIN(OUT2, "out2"),
PINCTRL_PIN(OUT2_RMP, "out2_rmp"),
};
static int stm32_rtc_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(stm32_rtc_pinctrl_pins);
}
static const char *stm32_rtc_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
unsigned int selector)
{
return stm32_rtc_pinctrl_pins[selector].name;
}
static int stm32_rtc_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
unsigned int selector,
const unsigned int **pins,
unsigned int *num_pins)
{
*pins = &stm32_rtc_pinctrl_pins[selector].number;
*num_pins = 1;
return 0;
}
static const struct pinctrl_ops stm32_rtc_pinctrl_ops = {
.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
.dt_free_map = pinconf_generic_dt_free_map,
.get_groups_count = stm32_rtc_pinctrl_get_groups_count,
.get_group_name = stm32_rtc_pinctrl_get_group_name,
.get_group_pins = stm32_rtc_pinctrl_get_group_pins,
};
struct stm32_rtc_pinmux_func {
const char *name;
const char * const *groups;
const unsigned int num_groups;
int (*action)(struct pinctrl_dev *pctl_dev, unsigned int pin);
};
static int stm32_rtc_pinmux_action_alarm(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
struct stm32_rtc_registers regs = rtc->data->regs;
unsigned int cr = readl_relaxed(rtc->base + regs.cr);
unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
if (!rtc->data->has_alarm_out)
return -EPERM;
cr &= ~STM32_RTC_CR_OSEL;
cr |= STM32_RTC_CR_OSEL_ALARM_A;
cr &= ~STM32_RTC_CR_TAMPOE;
cr &= ~STM32_RTC_CR_COE;
cr &= ~STM32_RTC_CR_TAMPALRM_TYPE;
switch (pin) {
case OUT1:
cr &= ~STM32_RTC_CR_OUT2EN;
cfgr &= ~STM32_RTC_CFGR_OUT2_RMP;
break;
case OUT2:
cr |= STM32_RTC_CR_OUT2EN;
cfgr &= ~STM32_RTC_CFGR_OUT2_RMP;
break;
case OUT2_RMP:
cr |= STM32_RTC_CR_OUT2EN;
cfgr |= STM32_RTC_CFGR_OUT2_RMP;
break;
default:
return -EINVAL;
}
stm32_rtc_wpr_unlock(rtc);
writel_relaxed(cr, rtc->base + regs.cr);
writel_relaxed(cfgr, rtc->base + regs.cfgr);
stm32_rtc_wpr_lock(rtc);
return 0;
}
static int stm32_rtc_pinmux_lsco_available(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
struct stm32_rtc_registers regs = rtc->data->regs;
unsigned int cr = readl_relaxed(rtc->base + regs.cr);
unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
unsigned int calib = STM32_RTC_CR_COE;
unsigned int tampalrm = STM32_RTC_CR_TAMPOE | STM32_RTC_CR_OSEL;
switch (pin) {
case OUT1:
if ((!(cr & STM32_RTC_CR_OUT2EN) &&
((cr & calib) || cr & tampalrm)) ||
((cr & calib) && (cr & tampalrm)))
return -EBUSY;
break;
case OUT2_RMP:
if ((cr & STM32_RTC_CR_OUT2EN) &&
(cfgr & STM32_RTC_CFGR_OUT2_RMP) &&
((cr & calib) || (cr & tampalrm)))
return -EBUSY;
break;
default:
return -EINVAL;
}
if (clk_get_rate(rtc->rtc_ck) != 32768)
return -ERANGE;
return 0;
}
static int stm32_rtc_pinmux_action_lsco(struct pinctrl_dev *pctldev, unsigned int pin)
{
struct stm32_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
struct stm32_rtc_registers regs = rtc->data->regs;
struct device *dev = rtc->rtc_dev->dev.parent;
u8 lscoen;
int ret;
if (!rtc->data->has_lsco)
return -EPERM;
ret = stm32_rtc_pinmux_lsco_available(pctldev, pin);
if (ret)
return ret;
lscoen = (pin == OUT1) ? STM32_RTC_CFGR_LSCOEN_OUT1 : STM32_RTC_CFGR_LSCOEN_OUT2_RMP;
rtc->clk_lsco = clk_register_gate(dev, "rtc_lsco", __clk_get_name(rtc->rtc_ck),
CLK_IGNORE_UNUSED | CLK_IS_CRITICAL,
rtc->base + regs.cfgr, lscoen, 0, NULL);
if (IS_ERR(rtc->clk_lsco))
return PTR_ERR(rtc->clk_lsco);
of_clk_add_provider(dev->of_node, of_clk_src_simple_get, rtc->clk_lsco);
return 0;
}
static const struct stm32_rtc_pinmux_func stm32_rtc_pinmux_functions[] = {
STM32_RTC_PINMUX("lsco", &stm32_rtc_pinmux_action_lsco, "out1", "out2_rmp"),
STM32_RTC_PINMUX("alarm-a", &stm32_rtc_pinmux_action_alarm, "out1", "out2", "out2_rmp"),
};
static int stm32_rtc_pinmux_get_functions_count(struct pinctrl_dev *pctldev)
{
return ARRAY_SIZE(stm32_rtc_pinmux_functions);
}
static const char *stm32_rtc_pinmux_get_fname(struct pinctrl_dev *pctldev, unsigned int selector)
{
return stm32_rtc_pinmux_functions[selector].name;
}
static int stm32_rtc_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned int selector,
const char * const **groups, unsigned int * const num_groups)
{
*groups = stm32_rtc_pinmux_functions[selector].groups;
*num_groups = stm32_rtc_pinmux_functions[selector].num_groups;
return 0;
}
static int stm32_rtc_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
unsigned int group)
{
struct stm32_rtc_pinmux_func selected_func = stm32_rtc_pinmux_functions[selector];
struct pinctrl_pin_desc pin = stm32_rtc_pinctrl_pins[group];
/* Call action */
if (selected_func.action)
return selected_func.action(pctldev, pin.number);
return -EINVAL;
}
static const struct pinmux_ops stm32_rtc_pinmux_ops = {
.get_functions_count = stm32_rtc_pinmux_get_functions_count,
.get_function_name = stm32_rtc_pinmux_get_fname,
.get_function_groups = stm32_rtc_pinmux_get_groups,
.set_mux = stm32_rtc_pinmux_set_mux,
.strict = true,
};
static struct pinctrl_desc stm32_rtc_pdesc = {
.name = DRIVER_NAME,
.pins = stm32_rtc_pinctrl_pins,
.npins = ARRAY_SIZE(stm32_rtc_pinctrl_pins),
.owner = THIS_MODULE,
.pctlops = &stm32_rtc_pinctrl_ops,
.pmxops = &stm32_rtc_pinmux_ops,
};
static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
{
const struct stm32_rtc_registers *regs = &rtc->data->regs;
@@ -576,6 +807,8 @@ static const struct stm32_rtc_data stm32_rtc_data = {
.need_dbp = true,
.need_accuracy = false,
.rif_protected = false,
.has_lsco = false,
.has_alarm_out = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -586,6 +819,7 @@ static const struct stm32_rtc_data stm32_rtc_data = {
.wpr = 0x24,
.sr = 0x0C, /* set to ISR offset to ease alarm management */
.scr = UNDEF_REG,
.cfgr = UNDEF_REG,
.verr = UNDEF_REG,
},
.events = {
@@ -599,6 +833,8 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
.need_dbp = true,
.need_accuracy = false,
.rif_protected = false,
.has_lsco = false,
.has_alarm_out = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -609,6 +845,7 @@ static const struct stm32_rtc_data stm32h7_rtc_data = {
.wpr = 0x24,
.sr = 0x0C, /* set to ISR offset to ease alarm management */
.scr = UNDEF_REG,
.cfgr = UNDEF_REG,
.verr = UNDEF_REG,
},
.events = {
@@ -631,6 +868,8 @@ static const struct stm32_rtc_data stm32mp1_data = {
.need_dbp = false,
.need_accuracy = true,
.rif_protected = false,
.has_lsco = true,
.has_alarm_out = true,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -641,6 +880,7 @@ static const struct stm32_rtc_data stm32mp1_data = {
.wpr = 0x24,
.sr = 0x50,
.scr = 0x5C,
.cfgr = 0x60,
.verr = 0x3F4,
},
.events = {
@@ -654,6 +894,8 @@ static const struct stm32_rtc_data stm32mp25_data = {
.need_dbp = false,
.need_accuracy = true,
.rif_protected = true,
.has_lsco = true,
.has_alarm_out = true,
.regs = {
.tr = 0x00,
.dr = 0x04,
@@ -664,6 +906,7 @@ static const struct stm32_rtc_data stm32mp25_data = {
.wpr = 0x24,
.sr = 0x50,
.scr = 0x5C,
.cfgr = 0x60,
.verr = 0x3F4,
},
.events = {
@@ -681,6 +924,30 @@ static const struct of_device_id stm32_rtc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
static void stm32_rtc_clean_outs(struct stm32_rtc *rtc)
{
struct stm32_rtc_registers regs = rtc->data->regs;
unsigned int cr = readl_relaxed(rtc->base + regs.cr);
cr &= ~STM32_RTC_CR_OSEL;
cr &= ~STM32_RTC_CR_TAMPOE;
cr &= ~STM32_RTC_CR_COE;
cr &= ~STM32_RTC_CR_TAMPALRM_TYPE;
cr &= ~STM32_RTC_CR_OUT2EN;
stm32_rtc_wpr_unlock(rtc);
writel_relaxed(cr, rtc->base + regs.cr);
stm32_rtc_wpr_lock(rtc);
if (regs.cfgr != UNDEF_REG) {
unsigned int cfgr = readl_relaxed(rtc->base + regs.cfgr);
cfgr &= ~STM32_RTC_CFGR_LSCOEN;
cfgr &= ~STM32_RTC_CFGR_OUT2_RMP;
writel_relaxed(cfgr, rtc->base + regs.cfgr);
}
}
static int stm32_rtc_check_rif(struct stm32_rtc *stm32_rtc,
struct stm32_rtc_rif_resource res)
{
@@ -791,6 +1058,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
{
struct stm32_rtc *rtc;
const struct stm32_rtc_registers *regs;
struct pinctrl_dev *pctl;
int ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -912,6 +1180,16 @@ static int stm32_rtc_probe(struct platform_device *pdev)
goto err;
}
stm32_rtc_clean_outs(rtc);
ret = devm_pinctrl_register_and_init(&pdev->dev, &stm32_rtc_pdesc, rtc, &pctl);
if (ret)
return dev_err_probe(&pdev->dev, ret, "pinctrl register failed");
ret = pinctrl_enable(pctl);
if (ret)
return dev_err_probe(&pdev->dev, ret, "pinctrl enable failed");
/*
* If INITS flag is reset (calendar year field set to 0x00), calendar
* must be initialized
@@ -950,6 +1228,9 @@ static void stm32_rtc_remove(struct platform_device *pdev)
const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int cr;
if (!IS_ERR_OR_NULL(rtc->clk_lsco))
clk_unregister_gate(rtc->clk_lsco);
/* Disable interrupts */
stm32_rtc_wpr_unlock(rtc);
cr = readl_relaxed(rtc->base + regs->cr);
+1
View File
@@ -402,6 +402,7 @@ CLK_OF_DECLARE_DRIVER(sun8i_r40_rtc_clk, "allwinner,sun8i-r40-rtc",
static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = {
.rc_osc_rate = 32000,
.has_out_clk = 1,
.has_auto_swt = 1,
};
static void __init sun8i_v3_rtc_clk_init(struct device_node *node)
+2 -2
View File
@@ -591,8 +591,8 @@ static int twl_rtc_probe(struct platform_device *pdev)
memset(&nvmem_cfg, 0, sizeof(nvmem_cfg));
nvmem_cfg.name = "twl-secured-";
nvmem_cfg.type = NVMEM_TYPE_BATTERY_BACKED;
nvmem_cfg.reg_read = twl_nvram_read,
nvmem_cfg.reg_write = twl_nvram_write,
nvmem_cfg.reg_read = twl_nvram_read;
nvmem_cfg.reg_write = twl_nvram_write;
nvmem_cfg.word_size = 1;
nvmem_cfg.stride = 1;
if (twl_class_is_4030()) {
+3 -9
View File
@@ -1163,7 +1163,6 @@ blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
if (blk_integrity_rq(rq)) {
struct scsi_data_buffer *prot_sdb = cmd->prot_sdb;
int ivecs;
if (WARN_ON_ONCE(!prot_sdb)) {
/*
@@ -1175,20 +1174,15 @@ blk_status_t scsi_alloc_sgtables(struct scsi_cmnd *cmd)
goto out_free_sgtables;
}
ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio);
if (sg_alloc_table_chained(&prot_sdb->table, ivecs,
if (sg_alloc_table_chained(&prot_sdb->table,
rq->nr_integrity_segments,
prot_sdb->table.sgl,
SCSI_INLINE_PROT_SG_CNT)) {
ret = BLK_STS_RESOURCE;
goto out_free_sgtables;
}
count = blk_rq_map_integrity_sg(rq->q, rq->bio,
prot_sdb->table.sgl);
BUG_ON(count > ivecs);
BUG_ON(count > queue_max_integrity_segments(rq->q));
count = blk_rq_map_integrity_sg(rq, prot_sdb->table.sgl);
cmd->prot_sdb = prot_sdb;
cmd->prot_sdb->table.nents = count;
}
+9 -6
View File
@@ -375,9 +375,9 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
* If the QSPI controller is set in regular SPI mode, set it in
* Serial Memory Mode (SMM).
*/
if (aq->mr != QSPI_MR_SMM) {
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
aq->mr = QSPI_MR_SMM;
if (!(aq->mr & QSPI_MR_SMM)) {
aq->mr |= QSPI_MR_SMM;
atmel_qspi_write(aq->scr, aq, QSPI_MR);
}
/* Clear pending interrupts */
@@ -501,7 +501,8 @@ static int atmel_qspi_setup(struct spi_device *spi)
if (ret < 0)
return ret;
aq->scr = QSPI_SCR_SCBR(scbr);
aq->scr &= ~QSPI_SCR_SCBR_MASK;
aq->scr |= QSPI_SCR_SCBR(scbr);
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
pm_runtime_mark_last_busy(ctrl->dev.parent);
@@ -534,6 +535,7 @@ static int atmel_qspi_set_cs_timing(struct spi_device *spi)
if (ret < 0)
return ret;
aq->scr &= ~QSPI_SCR_DLYBS_MASK;
aq->scr |= QSPI_SCR_DLYBS(cs_setup);
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
@@ -549,8 +551,8 @@ static void atmel_qspi_init(struct atmel_qspi *aq)
atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR);
/* Set the QSPI controller by default in Serial Memory Mode */
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
aq->mr = QSPI_MR_SMM;
aq->mr |= QSPI_MR_SMM;
atmel_qspi_write(aq->mr, aq, QSPI_MR);
/* Enable the QSPI controller */
atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR);
@@ -721,6 +723,7 @@ static void atmel_qspi_remove(struct platform_device *pdev)
clk_unprepare(aq->pclk);
pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
}
+16 -27
View File
@@ -211,9 +211,6 @@ struct airoha_snand_dev {
u8 *txrx_buf;
dma_addr_t dma_addr;
u64 cur_page_num;
bool data_need_update;
};
struct airoha_snand_ctrl {
@@ -405,7 +402,7 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd,
for (i = 0; i < len; i += data_len) {
int err;
data_len = min(len, SPI_MAX_TRANSFER_SIZE);
data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
if (err)
return err;
@@ -427,7 +424,7 @@ static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data,
for (i = 0; i < len; i += data_len) {
int err;
data_len = min(len, SPI_MAX_TRANSFER_SIZE);
data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
if (err)
return err;
@@ -644,11 +641,6 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
u32 val, rd_mode;
int err;
if (!as_dev->data_need_update)
return len;
as_dev->data_need_update = false;
switch (op->cmd.opcode) {
case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
rd_mode = 1;
@@ -739,8 +731,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
if (err)
return err;
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
SPI_NFI_READ_FROM_CACHE_DONE);
/*
* SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
* of dirmap_read operation even if it is already set.
*/
err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
SPI_NFI_READ_FROM_CACHE_DONE,
SPI_NFI_READ_FROM_CACHE_DONE);
if (err)
return err;
@@ -870,8 +867,13 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
if (err)
return err;
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
SPI_NFI_LOAD_TO_CACHE_DONE);
/*
* SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
* of dirmap_write operation even if it is already set.
*/
err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
SPI_NFI_LOAD_TO_CACHE_DONE,
SPI_NFI_LOAD_TO_CACHE_DONE);
if (err)
return err;
@@ -885,23 +887,11 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
static int airoha_snand_exec_op(struct spi_mem *mem,
const struct spi_mem_op *op)
{
struct airoha_snand_dev *as_dev = spi_get_ctldata(mem->spi);
u8 data[8], cmd, opcode = op->cmd.opcode;
struct airoha_snand_ctrl *as_ctrl;
int i, err;
as_ctrl = spi_controller_get_devdata(mem->spi->controller);
if (opcode == SPI_NAND_OP_PROGRAM_EXECUTE &&
op->addr.val == as_dev->cur_page_num) {
as_dev->data_need_update = true;
} else if (opcode == SPI_NAND_OP_PAGE_READ) {
if (!as_dev->data_need_update &&
op->addr.val == as_dev->cur_page_num)
return 0;
as_dev->data_need_update = true;
as_dev->cur_page_num = op->addr.val;
}
/* switch to manual mode */
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
@@ -986,7 +976,6 @@ static int airoha_snand_setup(struct spi_device *spi)
if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
return -ENOMEM;
as_dev->data_need_update = true;
spi_set_ctldata(spi, as_dev);
return 0;
+1
View File
@@ -986,6 +986,7 @@ static void fsl_lpspi_remove(struct platform_device *pdev)
fsl_lpspi_dma_exit(controller);
pm_runtime_dont_use_autosuspend(fsl_lpspi->dev);
pm_runtime_disable(fsl_lpspi->dev);
}
+10 -30
View File
@@ -32,40 +32,20 @@ static acpi_status tb_acpi_add_link(acpi_handle handle, u32 level, void *data,
goto out_put;
/*
* Try to find physical device walking upwards to the hierarcy.
* We need to do this because the xHCI driver might not yet be
* bound so the USB3 SuperSpeed ports are not yet created.
* Ignore USB3 ports here as USB core will set up device links between
* tunneled USB3 devices and NHI host during USB device creation.
* USB3 ports might not even have a physical device yet if xHCI driver
* isn't bound yet.
*/
do {
dev = acpi_get_first_physical_node(adev);
if (dev)
break;
adev = acpi_dev_parent(adev);
} while (adev);
/*
* Check that the device is PCIe. This is because USB3
* SuperSpeed ports have this property and they are not power
* managed with the xHCI and the SuperSpeed hub so we create the
* link from xHCI instead.
*/
while (dev && !dev_is_pci(dev))
dev = dev->parent;
if (!dev)
dev = acpi_get_first_physical_node(adev);
if (!dev || !dev_is_pci(dev))
goto out_put;
/*
* Check that this actually matches the type of device we
* expect. It should either be xHCI or PCIe root/downstream
* port.
*/
/* Check that this matches a PCIe root/downstream port. */
pdev = to_pci_dev(dev);
if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI ||
(pci_is_pcie(pdev) &&
(pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM))) {
if (pci_is_pcie(pdev) &&
(pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT ||
pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM)) {
const struct device_link *link;
/*
+366 -16
View File
@@ -9,6 +9,7 @@
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/uaccess.h>
@@ -34,6 +35,14 @@
#define COUNTER_SET_LEN 3
/*
* USB4 spec doesn't specify dwell range, the range of 100 ms to 500 ms
* probed to give good results.
*/
#define MIN_DWELL_TIME 100 /* ms */
#define MAX_DWELL_TIME 500 /* ms */
#define DWELL_SAMPLE_INTERVAL 10
/* Sideband registers and their sizes as defined in the USB4 spec */
struct sb_reg {
unsigned int reg;
@@ -394,8 +403,15 @@ out:
* @ber_level: Current BER level contour value
* @voltage_steps: Number of mandatory voltage steps
* @max_voltage_offset: Maximum mandatory voltage offset (in mV)
* @voltage_steps_optional_range: Number of voltage steps for optional range
* @max_voltage_offset_optional_range: Maximum voltage offset for the optional
* range (in mV).
* @time_steps: Number of time margin steps
* @max_time_offset: Maximum time margin offset (in mUI)
* @voltage_time_offset: Offset for voltage / time for software margining
* @dwell_time: Dwell time for software margining (in ms)
* @error_counter: Error counter operation for software margining
* @optional_voltage_offset_range: Enable optional extended voltage range
* @software: %true if software margining is used instead of hardware
* @time: %true if time margining is used instead of voltage
* @right_high: %false if left/low margin test is performed, %true if
@@ -414,13 +430,37 @@ struct tb_margining {
unsigned int ber_level;
unsigned int voltage_steps;
unsigned int max_voltage_offset;
unsigned int voltage_steps_optional_range;
unsigned int max_voltage_offset_optional_range;
unsigned int time_steps;
unsigned int max_time_offset;
unsigned int voltage_time_offset;
unsigned int dwell_time;
enum usb4_margin_sw_error_counter error_counter;
bool optional_voltage_offset_range;
bool software;
bool time;
bool right_high;
};
static int margining_modify_error_counter(struct tb_margining *margining,
u32 lanes, enum usb4_margin_sw_error_counter error_counter)
{
struct usb4_port_margining_params params = { 0 };
struct tb_port *port = margining->port;
u32 result;
if (error_counter != USB4_MARGIN_SW_ERROR_COUNTER_CLEAR &&
error_counter != USB4_MARGIN_SW_ERROR_COUNTER_STOP)
return -EOPNOTSUPP;
params.error_counter = error_counter;
params.lanes = lanes;
return usb4_port_sw_margin(port, margining->target, margining->index,
&params, &result);
}
static bool supports_software(const struct tb_margining *margining)
{
return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW;
@@ -454,6 +494,12 @@ independent_time_margins(const struct tb_margining *margining)
return FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1]);
}
static bool
supports_optional_voltage_offset_range(const struct tb_margining *margining)
{
return margining->caps[0] & USB4_MARGIN_CAP_0_OPT_VOLTAGE_SUPPORT;
}
static ssize_t
margining_ber_level_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
@@ -553,6 +599,14 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
margining->voltage_steps);
seq_printf(s, "# maximum voltage offset: %u mV\n",
margining->max_voltage_offset);
seq_printf(s, "# optional voltage offset range support: %s\n",
str_yes_no(supports_optional_voltage_offset_range(margining)));
if (supports_optional_voltage_offset_range(margining)) {
seq_printf(s, "# voltage margin steps, optional range: %u\n",
margining->voltage_steps_optional_range);
seq_printf(s, "# maximum voltage offset, optional range: %u mV\n",
margining->max_voltage_offset_optional_range);
}
switch (independent_voltage_margins(margining)) {
case USB4_MARGIN_CAP_0_VOLTAGE_MIN:
@@ -667,6 +721,198 @@ static int margining_lanes_show(struct seq_file *s, void *not_used)
}
DEBUGFS_ATTR_RW(margining_lanes);
static ssize_t
margining_voltage_time_offset_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
unsigned int max_margin;
unsigned int val;
int ret;
ret = kstrtouint_from_user(user_buf, count, 10, &val);
if (ret)
return ret;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
if (!margining->software)
return -EOPNOTSUPP;
if (margining->time)
max_margin = margining->time_steps;
else
if (margining->optional_voltage_offset_range)
max_margin = margining->voltage_steps_optional_range;
else
max_margin = margining->voltage_steps;
margining->voltage_time_offset = clamp(val, 0, max_margin);
}
return count;
}
static int margining_voltage_time_offset_show(struct seq_file *s,
void *not_used)
{
const struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
if (!margining->software)
return -EOPNOTSUPP;
seq_printf(s, "%d\n", margining->voltage_time_offset);
}
return 0;
}
DEBUGFS_ATTR_RW(margining_voltage_time_offset);
static ssize_t
margining_error_counter_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
enum usb4_margin_sw_error_counter error_counter;
struct seq_file *s = file->private_data;
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
char *buf;
buf = validate_and_copy_from_user(user_buf, &count);
if (IS_ERR(buf))
return PTR_ERR(buf);
buf[count - 1] = '\0';
if (!strcmp(buf, "nop"))
error_counter = USB4_MARGIN_SW_ERROR_COUNTER_NOP;
else if (!strcmp(buf, "clear"))
error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR;
else if (!strcmp(buf, "start"))
error_counter = USB4_MARGIN_SW_ERROR_COUNTER_START;
else if (!strcmp(buf, "stop"))
error_counter = USB4_MARGIN_SW_ERROR_COUNTER_STOP;
else
return -EINVAL;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
if (!margining->software)
return -EOPNOTSUPP;
margining->error_counter = error_counter;
}
return count;
}
static int margining_error_counter_show(struct seq_file *s, void *not_used)
{
const struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
if (!margining->software)
return -EOPNOTSUPP;
switch (margining->error_counter) {
case USB4_MARGIN_SW_ERROR_COUNTER_NOP:
seq_puts(s, "[nop] clear start stop\n");
break;
case USB4_MARGIN_SW_ERROR_COUNTER_CLEAR:
seq_puts(s, "nop [clear] start stop\n");
break;
case USB4_MARGIN_SW_ERROR_COUNTER_START:
seq_puts(s, "nop clear [start] stop\n");
break;
case USB4_MARGIN_SW_ERROR_COUNTER_STOP:
seq_puts(s, "nop clear start [stop]\n");
break;
}
}
return 0;
}
DEBUGFS_ATTR_RW(margining_error_counter);
static ssize_t
margining_dwell_time_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
unsigned int val;
int ret;
ret = kstrtouint_from_user(user_buf, count, 10, &val);
if (ret)
return ret;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
if (!margining->software)
return -EOPNOTSUPP;
margining->dwell_time = clamp(val, MIN_DWELL_TIME, MAX_DWELL_TIME);
}
return count;
}
static int margining_dwell_time_show(struct seq_file *s, void *not_used)
{
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
if (!margining->software)
return -EOPNOTSUPP;
seq_printf(s, "%d\n", margining->dwell_time);
}
return 0;
}
DEBUGFS_ATTR_RW(margining_dwell_time);
static ssize_t
margining_optional_voltage_offset_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
bool val;
int ret;
ret = kstrtobool_from_user(user_buf, count, &val);
if (ret)
return ret;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
margining->optional_voltage_offset_range = val;
}
return count;
}
static int margining_optional_voltage_offset_show(struct seq_file *s,
void *not_used)
{
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
seq_printf(s, "%u\n", margining->optional_voltage_offset_range);
}
return 0;
}
DEBUGFS_ATTR_RW(margining_optional_voltage_offset);
static ssize_t margining_mode_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@@ -739,6 +985,51 @@ static int margining_mode_show(struct seq_file *s, void *not_used)
}
DEBUGFS_ATTR_RW(margining_mode);
static int margining_run_sw(struct tb_margining *margining,
struct usb4_port_margining_params *params)
{
u32 nsamples = margining->dwell_time / DWELL_SAMPLE_INTERVAL;
int ret, i;
ret = usb4_port_sw_margin(margining->port, margining->target, margining->index,
params, margining->results);
if (ret)
goto out_stop;
for (i = 0; i <= nsamples; i++) {
u32 errors = 0;
ret = usb4_port_sw_margin_errors(margining->port, margining->target,
margining->index, &margining->results[1]);
if (ret)
break;
if (margining->lanes == USB4_MARGIN_SW_LANE_0)
errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK,
margining->results[1]);
else if (margining->lanes == USB4_MARGIN_SW_LANE_1)
errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK,
margining->results[1]);
else if (margining->lanes == USB4_MARGIN_SW_ALL_LANES)
errors = margining->results[1];
/* Any errors stop the test */
if (errors)
break;
fsleep(DWELL_SAMPLE_INTERVAL * USEC_PER_MSEC);
}
out_stop:
/*
* Stop the counters but don't clear them to allow the
* different error counter configurations.
*/
margining_modify_error_counter(margining, margining->lanes,
USB4_MARGIN_SW_ERROR_COUNTER_STOP);
return ret;
}
static int margining_run_write(void *data, u64 val)
{
struct tb_margining *margining = data;
@@ -779,36 +1070,43 @@ static int margining_run_write(void *data, u64 val)
clx = ret;
}
/* Clear the results */
memset(margining->results, 0, sizeof(margining->results));
if (margining->software) {
struct usb4_port_margining_params params = {
.error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR,
.lanes = margining->lanes,
.time = margining->time,
.voltage_time_offset = margining->voltage_time_offset,
.right_high = margining->right_high,
.optional_voltage_offset_range = margining->optional_voltage_offset_range,
};
tb_port_dbg(port,
"running software %s lane margining for %s lanes %u\n",
margining->time ? "time" : "voltage", dev_name(dev),
margining->lanes);
ret = usb4_port_sw_margin(port, margining->target, margining->index,
margining->lanes, margining->time,
margining->right_high,
USB4_MARGIN_SW_COUNTER_CLEAR);
if (ret)
goto out_clx;
ret = usb4_port_sw_margin_errors(port, margining->target,
margining->index,
&margining->results[0]);
ret = margining_run_sw(margining, &params);
} else {
struct usb4_port_margining_params params = {
.ber_level = margining->ber_level,
.lanes = margining->lanes,
.time = margining->time,
.right_high = margining->right_high,
.optional_voltage_offset_range = margining->optional_voltage_offset_range,
};
tb_port_dbg(port,
"running hardware %s lane margining for %s lanes %u\n",
margining->time ? "time" : "voltage", dev_name(dev),
margining->lanes);
/* Clear the results */
margining->results[0] = 0;
margining->results[1] = 0;
ret = usb4_port_hw_margin(port, margining->target, margining->index,
margining->lanes, margining->ber_level,
margining->time, margining->right_high,
ret = usb4_port_hw_margin(port, margining->target, margining->index, &params,
margining->results);
}
out_clx:
if (down_sw)
tb_switch_clx_enable(down_sw, clx);
out_unlock:
@@ -837,6 +1135,13 @@ static ssize_t margining_results_write(struct file *file,
margining->results[0] = 0;
margining->results[1] = 0;
if (margining->software) {
/* Clear the error counters */
margining_modify_error_counter(margining,
USB4_MARGIN_SW_ALL_LANES,
USB4_MARGIN_SW_ERROR_COUNTER_CLEAR);
}
mutex_unlock(&tb->lock);
return count;
}
@@ -852,6 +1157,8 @@ static void voltage_margin_show(struct seq_file *s,
if (val & USB4_MARGIN_HW_RES_1_EXCEEDS)
seq_puts(s, " exceeds maximum");
seq_puts(s, "\n");
if (margining->optional_voltage_offset_range)
seq_puts(s, " optional voltage offset range enabled\n");
}
static void time_margin_show(struct seq_file *s,
@@ -924,6 +1231,24 @@ static int margining_results_show(struct seq_file *s, void *not_used)
voltage_margin_show(s, margining, val);
}
}
} else {
u32 lane_errors, result;
seq_printf(s, "0x%08x\n", margining->results[1]);
result = FIELD_GET(USB4_MARGIN_SW_LANES_MASK, margining->results[0]);
if (result == USB4_MARGIN_SW_LANE_0 ||
result == USB4_MARGIN_SW_ALL_LANES) {
lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK,
margining->results[1]);
seq_printf(s, "# lane 0 errors: %u\n", lane_errors);
}
if (result == USB4_MARGIN_SW_LANE_1 ||
result == USB4_MARGIN_SW_ALL_LANES) {
lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK,
margining->results[1]);
seq_printf(s, "# lane 1 errors: %u\n", lane_errors);
}
}
mutex_unlock(&tb->lock);
@@ -1091,6 +1416,15 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]);
margining->max_voltage_offset = 74 + val * 2;
if (supports_optional_voltage_offset_range(margining)) {
val = FIELD_GET(USB4_MARGIN_CAP_0_VOLT_STEPS_OPT_MASK,
margining->caps[0]);
margining->voltage_steps_optional_range = val;
val = FIELD_GET(USB4_MARGIN_CAP_1_MAX_VOLT_OFS_OPT_MASK,
margining->caps[1]);
margining->max_voltage_offset_optional_range = 74 + val * 2;
}
if (supports_time(margining)) {
val = FIELD_GET(USB4_MARGIN_CAP_1_TIME_STEPS_MASK, margining->caps[1]);
margining->time_steps = val;
@@ -1127,6 +1461,22 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
independent_time_margins(margining) == USB4_MARGIN_CAP_1_TIME_LR))
debugfs_create_file("margin", 0600, dir, margining,
&margining_margin_fops);
margining->error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR;
margining->dwell_time = MIN_DWELL_TIME;
if (supports_optional_voltage_offset_range(margining))
debugfs_create_file("optional_voltage_offset", DEBUGFS_MODE, dir, margining,
&margining_optional_voltage_offset_fops);
if (supports_software(margining)) {
debugfs_create_file("voltage_time_offset", DEBUGFS_MODE, dir, margining,
&margining_voltage_time_offset_fops);
debugfs_create_file("error_counter", DEBUGFS_MODE, dir, margining,
&margining_error_counter_fops);
debugfs_create_file("dwell_time", DEBUGFS_MODE, dir, margining,
&margining_dwell_time_fops);
}
return margining;
}
+13 -5
View File
@@ -57,6 +57,9 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_CAP_0_TIME BIT(5)
#define USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK GENMASK(12, 6)
#define USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK GENMASK(18, 13)
#define USB4_MARGIN_CAP_0_OPT_VOLTAGE_SUPPORT BIT(19)
#define USB4_MARGIN_CAP_0_VOLT_STEPS_OPT_MASK GENMASK(26, 20)
#define USB4_MARGIN_CAP_1_MAX_VOLT_OFS_OPT_MASK GENMASK(7, 0)
#define USB4_MARGIN_CAP_1_TIME_DESTR BIT(8)
#define USB4_MARGIN_CAP_1_TIME_INDP_MASK GENMASK(10, 9)
#define USB4_MARGIN_CAP_1_TIME_MIN 0x0
@@ -72,6 +75,7 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_HW_RH BIT(4)
#define USB4_MARGIN_HW_BER_MASK GENMASK(9, 5)
#define USB4_MARGIN_HW_BER_SHIFT 5
#define USB4_MARGIN_HW_OPT_VOLTAGE BIT(10)
/* Applicable to all margin values */
#define USB4_MARGIN_HW_RES_1_MARGIN_MASK GENMASK(6, 0)
@@ -82,13 +86,17 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT 24
/* USB4_SB_OPCODE_RUN_SW_LANE_MARGINING */
#define USB4_MARGIN_SW_LANES_MASK GENMASK(2, 0)
#define USB4_MARGIN_SW_LANE_0 0x0
#define USB4_MARGIN_SW_LANE_1 0x1
#define USB4_MARGIN_SW_ALL_LANES 0x7
#define USB4_MARGIN_SW_TIME BIT(3)
#define USB4_MARGIN_SW_RH BIT(4)
#define USB4_MARGIN_SW_OPT_VOLTAGE BIT(5)
#define USB4_MARGIN_SW_VT_MASK GENMASK(12, 6)
#define USB4_MARGIN_SW_COUNTER_MASK GENMASK(14, 13)
#define USB4_MARGIN_SW_COUNTER_SHIFT 13
#define USB4_MARGIN_SW_COUNTER_NOP 0x0
#define USB4_MARGIN_SW_COUNTER_CLEAR 0x1
#define USB4_MARGIN_SW_COUNTER_START 0x2
#define USB4_MARGIN_SW_COUNTER_STOP 0x3
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK GENMASK(3, 0)
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK GENMASK(7, 4)
#endif
+38 -4
View File
@@ -1353,14 +1353,48 @@ int usb4_port_sb_read(struct tb_port *port, enum usb4_sb_target target, u8 index
int usb4_port_sb_write(struct tb_port *port, enum usb4_sb_target target,
u8 index, u8 reg, const void *buf, u8 size);
/**
* enum usb4_margin_sw_error_counter - Software margining error counter operation
* @USB4_MARGIN_SW_ERROR_COUNTER_NOP: No change in counter setup
* @USB4_MARGIN_SW_ERROR_COUNTER_CLEAR: Set the error counter to 0, enable counter
* @USB4_MARGIN_SW_ERROR_COUNTER_START: Start counter, count from last value
* @USB4_MARGIN_SW_ERROR_COUNTER_STOP: Stop counter, do not clear value
*/
enum usb4_margin_sw_error_counter {
USB4_MARGIN_SW_ERROR_COUNTER_NOP,
USB4_MARGIN_SW_ERROR_COUNTER_CLEAR,
USB4_MARGIN_SW_ERROR_COUNTER_START,
USB4_MARGIN_SW_ERROR_COUNTER_STOP,
};
/**
* struct usb4_port_margining_params - USB4 margining parameters
* @error_counter: Error counter operation for software margining
* @ber_level: Current BER level contour value
* @lanes: %0, %1 or %7 (all)
* @voltage_time_offset: Offset for voltage / time for software margining
* @optional_voltage_offset_range: Enable optional extended voltage range
* @right_high: %false if left/low margin test is performed, %true if right/high
* @time: %true if time margining is used instead of voltage
*/
struct usb4_port_margining_params {
enum usb4_margin_sw_error_counter error_counter;
u32 ber_level;
u32 lanes;
u32 voltage_time_offset;
bool optional_voltage_offset_range;
bool right_high;
bool time;
};
int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
u8 index, u32 *caps);
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, unsigned int ber_level,
bool timing, bool right_high, u32 *results);
u8 index, const struct usb4_port_margining_params *params,
u32 *results);
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, bool timing,
bool right_high, u32 counter);
u8 index, const struct usb4_port_margining_params *params,
u32 *results);
int usb4_port_sw_margin_errors(struct tb_port *port, enum usb4_sb_target target,
u8 index, u32 *errors);
+35 -27
View File
@@ -1653,31 +1653,31 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
* @port: USB4 port
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @lanes: Which lanes to run (must match the port capabilities). Can be
* %0, %1 or %7.
* @ber_level: BER level contour value
* @timing: Perform timing margining instead of voltage
* @right_high: Use Right/high margin instead of left/low
* @params: Parameters for USB4 hardware margining
* @results: Array with at least two elements to hold the results
*
* Runs hardware lane margining on USB4 port and returns the result in
* @results.
*/
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, unsigned int ber_level,
bool timing, bool right_high, u32 *results)
u8 index, const struct usb4_port_margining_params *params,
u32 *results)
{
u32 val;
int ret;
val = lanes;
if (timing)
if (WARN_ON_ONCE(!params))
return -EINVAL;
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_HW_TIME;
if (right_high)
if (params->right_high)
val |= USB4_MARGIN_HW_RH;
if (ber_level)
val |= (ber_level << USB4_MARGIN_HW_BER_SHIFT) &
USB4_MARGIN_HW_BER_MASK;
if (params->ber_level)
val |= FIELD_PREP(USB4_MARGIN_HW_BER_MASK, params->ber_level);
if (params->optional_voltage_offset_range)
val |= USB4_MARGIN_HW_OPT_VOLTAGE;
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
sizeof(val));
@@ -1698,38 +1698,46 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
* @port: USB4 port
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @lanes: Which lanes to run (must match the port capabilities). Can be
* %0, %1 or %7.
* @timing: Perform timing margining instead of voltage
* @right_high: Use Right/high margin instead of left/low
* @counter: What to do with the error counter
* @params: Parameters for USB4 software margining
* @results: Data word for the operation completion data
*
* Runs software lane margining on USB4 port. Read back the error
* counters by calling usb4_port_sw_margin_errors(). Returns %0 in
* success and negative errno otherwise.
*/
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, unsigned int lanes, bool timing,
bool right_high, u32 counter)
u8 index, const struct usb4_port_margining_params *params,
u32 *results)
{
u32 val;
int ret;
val = lanes;
if (timing)
if (WARN_ON_ONCE(!params))
return -EINVAL;
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_SW_TIME;
if (right_high)
if (params->optional_voltage_offset_range)
val |= USB4_MARGIN_SW_OPT_VOLTAGE;
if (params->right_high)
val |= USB4_MARGIN_SW_RH;
val |= (counter << USB4_MARGIN_SW_COUNTER_SHIFT) &
USB4_MARGIN_SW_COUNTER_MASK;
val |= FIELD_PREP(USB4_MARGIN_SW_COUNTER_MASK, params->error_counter);
val |= FIELD_PREP(USB4_MARGIN_SW_VT_MASK, params->voltage_time_offset);
ret = usb4_port_sb_write(port, target, index, USB4_SB_METADATA, &val,
sizeof(val));
if (ret)
return ret;
return usb4_port_sb_op(port, target, index,
USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500);
ret = usb4_port_sb_op(port, target, index,
USB4_SB_OPCODE_RUN_SW_LANE_MARGINING, 2500);
if (ret)
return ret;
return usb4_port_sb_read(port, target, index, USB4_SB_DATA, results,
sizeof(*results));
}
/**
+1 -1
View File
@@ -303,7 +303,7 @@ int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr)
pr_devel("HVSI@%x: %s DTR...\n", pv->termno,
dtr ? "Setting" : "Clearing");
ctrl.hdr.type = VS_CONTROL_PACKET_HEADER,
ctrl.hdr.type = VS_CONTROL_PACKET_HEADER;
ctrl.hdr.len = sizeof(struct hvsi_control);
ctrl.verb = cpu_to_be16(VSV_SET_MODEM_CTL);
ctrl.mask = cpu_to_be32(HVSI_TSDTR);
+1 -6
View File
@@ -208,9 +208,6 @@ static const struct {
};
#define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info)
/* driver_data correspond to the lines in the structure above
see also ISA probe function before you change something */
static const struct pci_device_id mxser_pcibrds[] = {
{ PCI_DEVICE_DATA(MOXA, C168, 8) },
{ PCI_DEVICE_DATA(MOXA, C104, 4) },
@@ -986,7 +983,7 @@ static int mxser_get_serial_info(struct tty_struct *tty,
ss->baud_base = MXSER_BAUD_BASE;
ss->close_delay = close_delay;
ss->closing_wait = closing_wait;
ss->custom_divisor = MXSER_CUSTOM_DIVISOR,
ss->custom_divisor = MXSER_CUSTOM_DIVISOR;
mutex_unlock(&port->mutex);
return 0;
}
@@ -1773,8 +1770,6 @@ static void mxser_initbrd(struct mxser_board *brd, bool high_baud)
mxser_process_txrx_fifo(info);
info->port.close_delay = 5 * HZ / 10;
info->port.closing_wait = 30 * HZ;
spin_lock_init(&info->slock);
/* before set INT ISR, disable all int */
+1 -1
View File
@@ -529,7 +529,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
bool found = false;
for_each_available_child_of_node(ctrl->dev.of_node, node) {
if (!of_get_property(node, "compatible", NULL))
if (!of_property_present(node, "compatible"))
continue;
dev_dbg(&ctrl->dev, "adding child %pOF\n", node);
@@ -561,6 +561,7 @@ static const struct of_device_id aspeed_vuart_table[] = {
{ .compatible = "aspeed,ast2500-vuart" },
{ },
};
MODULE_DEVICE_TABLE(of, aspeed_vuart_table);
static struct platform_driver aspeed_vuart_driver = {
.driver = {
+47
View File
@@ -13,6 +13,7 @@
*/
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -213,11 +214,57 @@ static const struct acpi_device_id bcm2835aux_serial_acpi_match[] = {
};
MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);
static bool bcm2835aux_can_disable_clock(struct device *dev)
{
struct bcm2835aux_data *data = dev_get_drvdata(dev);
struct uart_8250_port *up = serial8250_get_port(data->line);
if (device_may_wakeup(dev))
return false;
if (uart_console(&up->port) && !console_suspend_enabled)
return false;
return true;
}
static int bcm2835aux_suspend(struct device *dev)
{
struct bcm2835aux_data *data = dev_get_drvdata(dev);
serial8250_suspend_port(data->line);
if (!bcm2835aux_can_disable_clock(dev))
return 0;
clk_disable_unprepare(data->clk);
return 0;
}
static int bcm2835aux_resume(struct device *dev)
{
struct bcm2835aux_data *data = dev_get_drvdata(dev);
int ret;
if (bcm2835aux_can_disable_clock(dev)) {
ret = clk_prepare_enable(data->clk);
if (ret)
return ret;
}
serial8250_resume_port(data->line);
return 0;
}
static DEFINE_SIMPLE_DEV_PM_OPS(bcm2835aux_dev_pm_ops, bcm2835aux_suspend, bcm2835aux_resume);
static struct platform_driver bcm2835aux_serial_driver = {
.driver = {
.name = "bcm2835-aux-uart",
.of_match_table = bcm2835aux_serial_match,
.acpi_match_table = bcm2835aux_serial_acpi_match,
.pm = pm_ptr(&bcm2835aux_dev_pm_ops),
},
.probe = bcm2835aux_serial_probe,
.remove_new = bcm2835aux_serial_remove,
+10 -9
View File
@@ -89,7 +89,9 @@ int serial8250_tx_dma(struct uart_8250_port *p)
struct tty_port *tport = &p->port.state->port;
struct dma_async_tx_descriptor *desc;
struct uart_port *up = &p->port;
struct scatterlist sg;
struct scatterlist *sg;
struct scatterlist sgl[2];
int i;
int ret;
if (dma->tx_running) {
@@ -110,18 +112,17 @@ int serial8250_tx_dma(struct uart_8250_port *p)
serial8250_do_prepare_tx_dma(p);
sg_init_table(&sg, 1);
/* kfifo can do more than one sg, we don't (quite yet) */
ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, &sg, 1,
sg_init_table(sgl, ARRAY_SIZE(sgl));
ret = kfifo_dma_out_prepare_mapped(&tport->xmit_fifo, sgl, ARRAY_SIZE(sgl),
UART_XMIT_SIZE, dma->tx_addr);
/* we already checked empty fifo above, so there should be something */
if (WARN_ON_ONCE(ret != 1))
return 0;
dma->tx_size = 0;
dma->tx_size = sg_dma_len(&sg);
for_each_sg(sgl, sg, ret, i)
dma->tx_size += sg_dma_len(sg);
desc = dmaengine_prep_slave_sg(dma->txchan, &sg, 1,
desc = dmaengine_prep_slave_sg(dma->txchan, sgl, ret,
DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
+1 -1
View File
@@ -89,7 +89,7 @@ static void dw8250_set_divisor(struct uart_port *p, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
{
dw8250_writel_ext(p, DW_UART_DLF, quot_frac);
serial8250_do_set_divisor(p, baud, quot, quot_frac);
serial8250_do_set_divisor(p, baud, quot);
}
void dw8250_do_set_termios(struct uart_port *p, struct ktermios *termios,
+11
View File
@@ -171,6 +171,17 @@ OF_EARLYCON_DECLARE(ns16550a, "ns16550a", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "nvidia,tegra20-uart", early_serial8250_setup);
OF_EARLYCON_DECLARE(uart, "snps,dw-apb-uart", early_serial8250_setup);
static int __init early_serial8250_rs2_setup(struct earlycon_device *device,
const char *options)
{
device->port.regshift = 2;
return early_serial8250_setup(device, options);
}
OF_EARLYCON_DECLARE(uart, "intel,xscale-uart", early_serial8250_rs2_setup);
OF_EARLYCON_DECLARE(uart, "mrvl,mmp-uart", early_serial8250_rs2_setup);
OF_EARLYCON_DECLARE(uart, "mrvl,pxa-uart", early_serial8250_rs2_setup);
#ifdef CONFIG_SERIAL_8250_OMAP
static int __init early_omap8250_setup(struct earlycon_device *device,
+1 -1
View File
@@ -500,7 +500,7 @@ static unsigned int xr17v35x_get_divisor(struct uart_port *p, unsigned int baud,
static void xr17v35x_set_divisor(struct uart_port *p, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
{
serial8250_do_set_divisor(p, baud, quot, quot_frac);
serial8250_do_set_divisor(p, baud, quot);
/* Preserve bits not related to baudrate; DLD[7:4]. */
quot_frac |= serial_port_in(p, 0x2) & 0xf0;
+6 -4
View File
@@ -137,7 +137,6 @@ struct omap8250_priv {
atomic_t active;
bool is_suspending;
int wakeirq;
int wakeups_enabled;
u32 latency;
u32 calc_latency;
struct pm_qos_request pm_qos_request;
@@ -1523,7 +1522,10 @@ static int omap8250_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
device_init_wakeup(&pdev->dev, true);
device_set_wakeup_capable(&pdev->dev, true);
if (of_property_read_bool(np, "wakeup-source"))
device_set_wakeup_enable(&pdev->dev, true);
pm_runtime_enable(&pdev->dev);
pm_runtime_use_autosuspend(&pdev->dev);
@@ -1581,7 +1583,7 @@ static int omap8250_probe(struct platform_device *pdev)
ret = devm_request_irq(&pdev->dev, up.port.irq, omap8250_irq, 0,
dev_name(&pdev->dev), priv);
if (ret < 0)
return ret;
goto err;
priv->wakeirq = irq_of_parse_and_map(np, 1);
@@ -1622,7 +1624,7 @@ static void omap8250_remove(struct platform_device *pdev)
flush_work(&priv->qos_work);
pm_runtime_disable(&pdev->dev);
cpu_latency_qos_remove_request(&priv->pm_qos_request);
device_init_wakeup(&pdev->dev, false);
device_set_wakeup_capable(&pdev->dev, false);
}
static int omap8250_prepare(struct device *dev)
+1 -1
View File
@@ -1277,7 +1277,7 @@ static void pci_oxsemi_tornado_set_divisor(struct uart_port *port,
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);
serial8250_do_set_divisor(port, baud, quot);
}
/*
+104 -18
View File
@@ -2,11 +2,15 @@
/*
* Universal/legacy platform driver for 8250/16550-type serial ports
*
* Supports: ISA-compatible 8250/16550 ports
* Supports:
* ISA-compatible 8250/16550 ports
* ACPI 8250/16550 ports
* PNP 8250/16550 ports
* "serial8250" platform devices
*/
#include <linux/acpi.h>
#include <linux/array_size.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/once.h>
@@ -22,9 +26,9 @@
/*
* Configuration:
* share_irqs Whether we pass IRQF_SHARED to request_irq().
* share_irqs: Whether we pass IRQF_SHARED to request_irq().
* This option is unsafe when used on edge-triggered interrupts.
* skip_txen_test Force skip of txen test at init time.
* skip_txen_test: Force skip of txen test at init time.
*/
unsigned int share_irqs = SERIAL8250_SHARE_IRQS;
unsigned int skip_txen_test;
@@ -61,9 +65,9 @@ static void __init __serial8250_isa_init_ports(void)
nr_uarts = UART_NR;
/*
* Set up initial isa ports based on nr_uart module param, or else
* Set up initial ISA ports based on nr_uart module param, or else
* default to CONFIG_SERIAL_8250_RUNTIME_UARTS. Note that we do not
* need to increase nr_uarts when setting up the initial isa ports.
* need to increase nr_uarts when setting up the initial ISA ports.
*/
for (i = 0; i < nr_uarts; i++)
serial8250_setup_port(i);
@@ -101,13 +105,63 @@ void __init serial8250_isa_init_ports(void)
}
/*
* Register a set of serial devices attached to a platform device. The
* list is terminated with a zero flags entry, which means we expect
* all entries to have at least UPF_BOOT_AUTOCONF set.
* Generic 16550A platform devices
*/
static int serial8250_probe(struct platform_device *dev)
static int serial8250_probe_acpi(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct uart_8250_port uart = { };
struct resource *regs;
unsigned char iotype;
int ret, line;
regs = platform_get_mem_or_io(pdev, 0);
if (!regs)
return dev_err_probe(dev, -EINVAL, "no registers defined\n");
switch (resource_type(regs)) {
case IORESOURCE_IO:
uart.port.iobase = regs->start;
iotype = UPIO_PORT;
break;
case IORESOURCE_MEM:
uart.port.mapbase = regs->start;
uart.port.mapsize = resource_size(regs);
uart.port.flags = UPF_IOREMAP;
iotype = UPIO_MEM;
break;
default:
return -EINVAL;
}
/* default clock frequency */
uart.port.uartclk = 1843200;
uart.port.type = PORT_16550A;
uart.port.dev = &pdev->dev;
uart.port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
ret = uart_read_and_validate_port_properties(&uart.port);
/* no interrupt -> fall back to polling */
if (ret == -ENXIO)
ret = 0;
if (ret)
return ret;
/*
* The previous call may not set iotype correctly when reg-io-width
* property is absent and it doesn't support IO port resource.
*/
uart.port.iotype = iotype;
line = serial8250_register_8250_port(&uart);
if (line < 0)
return line;
return 0;
}
static int serial8250_probe_platform(struct platform_device *dev, struct plat_serial8250_port *p)
{
struct plat_serial8250_port *p = dev_get_platdata(&dev->dev);
struct uart_8250_port uart;
int ret, i, irqflag = 0;
@@ -155,6 +209,31 @@ static int serial8250_probe(struct platform_device *dev)
return 0;
}
/*
* Register a set of serial devices attached to a platform device.
* The list is terminated with a zero flags entry, which means we expect
* all entries to have at least UPF_BOOT_AUTOCONF set.
*/
static int serial8250_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct plat_serial8250_port *p;
p = dev_get_platdata(dev);
if (p)
return serial8250_probe_platform(pdev, p);
/*
* Probe platform UART devices defined using standard hardware
* discovery mechanism like ACPI or DT. Support only ACPI based
* serial device for now.
*/
if (has_acpi_companion(dev))
return serial8250_probe_acpi(pdev);
return 0;
}
/*
* Remove serial ports registered against a platform device.
*/
@@ -198,6 +277,12 @@ static int serial8250_resume(struct platform_device *dev)
return 0;
}
static const struct acpi_device_id acpi_platform_serial_table[] = {
{ "RSCV0003" }, /* RISC-V Generic 16550A UART */
{ }
};
MODULE_DEVICE_TABLE(acpi, acpi_platform_serial_table);
static struct platform_driver serial8250_isa_driver = {
.probe = serial8250_probe,
.remove_new = serial8250_remove,
@@ -205,12 +290,13 @@ static struct platform_driver serial8250_isa_driver = {
.resume = serial8250_resume,
.driver = {
.name = "serial8250",
.acpi_match_table = acpi_platform_serial_table,
},
};
/*
* This "device" covers _all_ ISA 8250-compatible serial devices listed
* in the table in include/asm/serial.h
* in the table in include/asm/serial.h.
*/
struct platform_device *serial8250_isa_devs;
@@ -239,8 +325,7 @@ static int __init serial8250_init(void)
if (ret)
goto unreg_uart_drv;
serial8250_isa_devs = platform_device_alloc("serial8250",
PLAT8250_DEV_LEGACY);
serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
if (!serial8250_isa_devs) {
ret = -ENOMEM;
goto unreg_pnp;
@@ -279,7 +364,7 @@ static void __exit serial8250_exit(void)
/*
* This tells serial8250_unregister_port() not to re-register
* the ports (thereby making serial8250_isa_driver permanently
* in use.)
* in use).
*/
serial8250_isa_devs = NULL;
@@ -312,12 +397,13 @@ MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
#ifndef MODULE
/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name
* working as well for the module options so we don't break people. We
/*
* This module was renamed to 8250_core in 3.7. Keep the old "8250" name
* working as well for the module options so we don't break people. We
* need to keep the names identical and the convenient macros will happily
* refuse to let us do that by failing the build with redefinition errors
* of global variables. So we stick them inside a dummy function to avoid
* those conflicts. The options still get parsed, and the redefined
* of global variables. So we stick them inside a dummy function to avoid
* those conflicts. The options still get parsed, and the redefined
* MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
*
* This is hacky. I'm sorry.
+2 -2
View File
@@ -2609,7 +2609,7 @@ static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
}
void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
unsigned int quot, unsigned int quot_frac)
unsigned int quot)
{
struct uart_8250_port *up = up_to_u8250p(port);
@@ -2641,7 +2641,7 @@ static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
if (port->set_divisor)
port->set_divisor(port, baud, quot, quot_frac);
else
serial8250_do_set_divisor(port, baud, quot, quot_frac);
serial8250_do_set_divisor(port, baud, quot);
}
static unsigned int serial8250_get_baud_rate(struct uart_port *port,
-16
View File
@@ -165,22 +165,6 @@ static struct platform_driver serial_pxa_driver = {
module_platform_driver(serial_pxa_driver);
#ifdef CONFIG_SERIAL_8250_CONSOLE
static int __init early_serial_pxa_setup(struct earlycon_device *device,
const char *options)
{
struct uart_port *port = &device->port;
if (!(device->port.membase || device->port.iobase))
return -ENODEV;
port->regshift = 2;
return early_serial8250_setup(device, NULL);
}
OF_EARLYCON_DECLARE(early_pxa, "mrvl,pxa-uart", early_serial_pxa_setup);
OF_EARLYCON_DECLARE(mmp, "mrvl,mmp-uart", early_serial_pxa_setup);
#endif
MODULE_AUTHOR("Sergei Ianovich");
MODULE_DESCRIPTION("driver for PXA on-board UARTS");
MODULE_LICENSE("GPL");
+76 -57
View File
@@ -124,13 +124,14 @@ struct qcom_geni_serial_port {
dma_addr_t tx_dma_addr;
dma_addr_t rx_dma_addr;
bool setup;
unsigned int baud;
unsigned long poll_timeout_us;
unsigned long clk_rate;
void *rx_buf;
u32 loopback;
bool brk;
unsigned int tx_remaining;
unsigned int tx_queued;
int wakeup_irq;
bool rx_tx_swap;
bool cts_rts_swap;
@@ -144,6 +145,9 @@ static const struct uart_ops qcom_geni_uart_pops;
static struct uart_driver qcom_geni_console_driver;
static struct uart_driver qcom_geni_uart_driver;
static void __qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport);
static inline struct qcom_geni_serial_port *to_dev_port(struct uart_port *uport)
{
return container_of(uport, struct qcom_geni_serial_port, uport);
@@ -265,27 +269,18 @@ static bool qcom_geni_serial_secondary_active(struct uart_port *uport)
return readl(uport->membase + SE_GENI_STATUS) & S_GENI_CMD_ACTIVE;
}
static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
int offset, int field, bool set)
static bool qcom_geni_serial_poll_bitfield(struct uart_port *uport,
unsigned int offset, u32 field, u32 val)
{
u32 reg;
struct qcom_geni_serial_port *port;
unsigned int baud;
unsigned int fifo_bits;
unsigned long timeout_us = 20000;
struct qcom_geni_private_data *private_data = uport->private_data;
if (private_data->drv) {
port = to_dev_port(uport);
baud = port->baud;
if (!baud)
baud = 115200;
fifo_bits = port->tx_fifo_depth * port->tx_fifo_width;
/*
* Total polling iterations based on FIFO worth of bytes to be
* sent at current baud. Add a little fluff to the wait.
*/
timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500;
if (port->poll_timeout_us)
timeout_us = port->poll_timeout_us;
}
/*
@@ -295,7 +290,7 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10;
while (timeout_us) {
reg = readl(uport->membase + offset);
if ((bool)(reg & field) == set)
if ((reg & field) == val)
return true;
udelay(10);
timeout_us -= 10;
@@ -303,6 +298,12 @@ static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
return false;
}
static bool qcom_geni_serial_poll_bit(struct uart_port *uport,
unsigned int offset, u32 field, bool set)
{
return qcom_geni_serial_poll_bitfield(uport, offset, field, set ? field : 0);
}
static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size)
{
u32 m_cmd;
@@ -315,18 +316,16 @@ static void qcom_geni_serial_setup_tx(struct uart_port *uport, u32 xmit_size)
static void qcom_geni_serial_poll_tx_done(struct uart_port *uport)
{
int done;
u32 irq_clear = M_CMD_DONE_EN;
done = qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_DONE_EN, true);
if (!done) {
writel(M_GENI_CMD_ABORT, uport->membase +
SE_GENI_M_CMD_CTRL_REG);
irq_clear |= M_CMD_ABORT_EN;
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_ABORT_EN, true);
writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
writel(irq_clear, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
static void qcom_geni_serial_abort_rx(struct uart_port *uport)
@@ -386,17 +385,27 @@ static int qcom_geni_serial_get_char(struct uart_port *uport)
static void qcom_geni_serial_poll_put_char(struct uart_port *uport,
unsigned char c)
{
writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
if (qcom_geni_serial_main_active(uport)) {
qcom_geni_serial_poll_tx_done(uport);
__qcom_geni_serial_cancel_tx_cmd(uport);
}
writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_setup_tx(uport, 1);
WARN_ON(!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_TX_FIFO_WATERMARK_EN, true));
writel(c, uport->membase + SE_GENI_TX_FIFOn);
writel(M_TX_FIFO_WATERMARK_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_poll_tx_done(uport);
}
#endif
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
static void qcom_geni_serial_drain_fifo(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
qcom_geni_serial_poll_bitfield(uport, SE_GENI_M_GP_LENGTH, GP_LENGTH,
port->tx_queued);
}
static void qcom_geni_serial_wr_char(struct uart_port *uport, unsigned char ch)
{
struct qcom_geni_private_data *private_data = uport->private_data;
@@ -431,6 +440,7 @@ __qcom_geni_serial_console_write(struct uart_port *uport, const char *s,
}
writel(DEF_TX_WM, uport->membase + SE_GENI_TX_WATERMARK_REG);
writel(M_CMD_DONE_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
qcom_geni_serial_setup_tx(uport, bytes_to_send);
for (i = 0; i < count; ) {
size_t chars_to_write = 0;
@@ -469,10 +479,9 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
{
struct uart_port *uport;
struct qcom_geni_serial_port *port;
u32 m_irq_en, s_irq_en;
bool locked = true;
unsigned long flags;
u32 geni_status;
u32 irq_en;
WARN_ON(co->index < 0 || co->index >= GENI_UART_CONS_PORTS);
@@ -486,40 +495,28 @@ static void qcom_geni_serial_console_write(struct console *co, const char *s,
else
uart_port_lock_irqsave(uport, &flags);
geni_status = readl(uport->membase + SE_GENI_STATUS);
m_irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
s_irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN);
writel(0, uport->membase + SE_GENI_M_IRQ_EN);
writel(0, uport->membase + SE_GENI_S_IRQ_EN);
if (!locked) {
/*
* We can only get here if an oops is in progress then we were
* unable to get the lock. This means we can't safely access
* our state variables like tx_remaining. About the best we
* can do is wait for the FIFO to be empty before we start our
* transfer, so we'll do that.
*/
qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_TX_FIFO_NOT_EMPTY_EN, false);
} else if ((geni_status & M_GENI_CMD_ACTIVE) && !port->tx_remaining) {
/*
* It seems we can't interrupt existing transfers if all data
* has been sent, in which case we need to look for done first.
*/
qcom_geni_serial_poll_tx_done(uport);
if (qcom_geni_serial_main_active(uport)) {
/* Wait for completion or drain FIFO */
if (!locked || port->tx_remaining == 0)
qcom_geni_serial_poll_tx_done(uport);
else
qcom_geni_serial_drain_fifo(uport);
if (!kfifo_is_empty(&uport->state->port.xmit_fifo)) {
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
writel(irq_en | M_TX_FIFO_WATERMARK_EN,
uport->membase + SE_GENI_M_IRQ_EN);
}
qcom_geni_serial_cancel_tx_cmd(uport);
}
__qcom_geni_serial_console_write(uport, s, count);
writel(m_irq_en, uport->membase + SE_GENI_M_IRQ_EN);
writel(s_irq_en, uport->membase + SE_GENI_S_IRQ_EN);
if (locked) {
if (port->tx_remaining)
qcom_geni_serial_setup_tx(uport, port->tx_remaining);
if (locked)
uart_port_unlock_irqrestore(uport, flags);
}
}
static void handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)
@@ -682,13 +679,10 @@ static void qcom_geni_serial_stop_tx_fifo(struct uart_port *uport)
writel(irq_en, uport->membase + SE_GENI_M_IRQ_EN);
}
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
static void __qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
if (!qcom_geni_serial_main_active(uport))
return;
geni_se_cancel_m_cmd(&port->se);
if (!qcom_geni_serial_poll_bit(uport, SE_GENI_M_IRQ_STATUS,
M_CMD_CANCEL_EN, true)) {
@@ -698,8 +692,19 @@ static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
writel(M_CMD_ABORT_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
writel(M_CMD_CANCEL_EN, uport->membase + SE_GENI_M_IRQ_CLEAR);
}
static void qcom_geni_serial_cancel_tx_cmd(struct uart_port *uport)
{
struct qcom_geni_serial_port *port = to_dev_port(uport);
if (!qcom_geni_serial_main_active(uport))
return;
__qcom_geni_serial_cancel_tx_cmd(uport);
port->tx_remaining = 0;
port->tx_queued = 0;
}
static void qcom_geni_serial_handle_rx_fifo(struct uart_port *uport, bool drop)
@@ -923,9 +928,10 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
if (!chunk)
goto out_write_wakeup;
if (!port->tx_remaining) {
if (!active) {
qcom_geni_serial_setup_tx(uport, pending);
port->tx_remaining = pending;
port->tx_queued = 0;
irq_en = readl(uport->membase + SE_GENI_M_IRQ_EN);
if (!(irq_en & M_TX_FIFO_WATERMARK_EN))
@@ -934,6 +940,7 @@ static void qcom_geni_serial_handle_tx_fifo(struct uart_port *uport,
}
qcom_geni_serial_send_chunk_fifo(uport, chunk);
port->tx_queued += chunk;
/*
* The tx fifo watermark is level triggered and latched. Though we had
@@ -1244,11 +1251,11 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
unsigned long clk_rate;
u32 ver, sampling_rate;
unsigned int avg_bw_core;
unsigned long timeout;
qcom_geni_serial_stop_rx(uport);
/* baud rate */
baud = uart_get_baud_rate(uport, termios, old, 300, 4000000);
port->baud = baud;
sampling_rate = UART_OVERSAMPLING;
/* Sampling rate is halved for IP versions >= 2.5 */
@@ -1326,9 +1333,21 @@ static void qcom_geni_serial_set_termios(struct uart_port *uport,
else
tx_trans_cfg |= UART_CTS_MASK;
if (baud)
if (baud) {
uart_update_timeout(uport, termios->c_cflag, baud);
/*
* Make sure that qcom_geni_serial_poll_bitfield() waits for
* the FIFO, two-word intermediate transfer register and shift
* register to clear.
*
* Note that uart_fifo_timeout() also adds a 20 ms margin.
*/
timeout = jiffies_to_usecs(uart_fifo_timeout(uport));
timeout += 3 * timeout / port->tx_fifo_depth;
WRITE_ONCE(port->poll_timeout_us, timeout);
}
if (!uart_console(uport))
writel(port->loopback,
uport->membase + SE_UART_LOOPBACK_CFG);
+1 -1
View File
@@ -577,8 +577,8 @@ static void rp2_reset_asic(struct rp2_card *card, unsigned int asic_id)
u32 clk_cfg;
writew(1, base + RP2_GLOBAL_CMD);
readw(base + RP2_GLOBAL_CMD);
msleep(100);
readw(base + RP2_GLOBAL_CMD);
writel(0, base + RP2_CLK_PRESCALER);
/* TDM clock configuration */
+28 -23
View File
@@ -550,6 +550,7 @@ static void s3c24xx_serial_stop_rx(struct uart_port *port)
case TYPE_APPLE_S5L:
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
s3c24xx_clear_bit(port, APPLE_S5L_UCON_RXTO_LEGACY_ENA, S3C2410_UCON);
break;
default:
disable_irq_nosync(ourport->rx_irq);
@@ -707,9 +708,8 @@ static void enable_rx_pio(struct s3c24xx_uart_port *ourport)
static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport);
static irqreturn_t s3c24xx_serial_rx_chars_dma(void *dev_id)
static irqreturn_t s3c24xx_serial_rx_chars_dma(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
struct s3c24xx_uart_dma *dma = ourport->dma;
struct tty_struct *tty = tty_port_tty_get(&ourport->port.state->port);
@@ -843,9 +843,8 @@ static void s3c24xx_serial_rx_drain_fifo(struct s3c24xx_uart_port *ourport)
tty_flip_buffer_push(&port->state->port);
}
static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
static irqreturn_t s3c24xx_serial_rx_chars_pio(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_port *ourport = dev_id;
struct uart_port *port = &ourport->port;
uart_port_lock(port);
@@ -855,13 +854,11 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id)
return IRQ_HANDLED;
}
static irqreturn_t s3c24xx_serial_rx_irq(int irq, void *dev_id)
static irqreturn_t s3c24xx_serial_rx_irq(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_port *ourport = dev_id;
if (ourport->dma && ourport->dma->rx_chan)
return s3c24xx_serial_rx_chars_dma(dev_id);
return s3c24xx_serial_rx_chars_pio(dev_id);
return s3c24xx_serial_rx_chars_dma(ourport);
return s3c24xx_serial_rx_chars_pio(ourport);
}
static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
@@ -928,9 +925,8 @@ static void s3c24xx_serial_tx_chars(struct s3c24xx_uart_port *ourport)
s3c24xx_serial_stop_tx(port);
}
static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id)
static irqreturn_t s3c24xx_serial_tx_irq(struct s3c24xx_uart_port *ourport)
{
struct s3c24xx_uart_port *ourport = id;
struct uart_port *port = &ourport->port;
uart_port_lock(port);
@@ -944,17 +940,17 @@ static irqreturn_t s3c24xx_serial_tx_irq(int irq, void *id)
/* interrupt handler for s3c64xx and later SoC's.*/
static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
{
const struct s3c24xx_uart_port *ourport = id;
struct s3c24xx_uart_port *ourport = id;
const struct uart_port *port = &ourport->port;
u32 pend = rd_regl(port, S3C64XX_UINTP);
irqreturn_t ret = IRQ_HANDLED;
if (pend & S3C64XX_UINTM_RXD_MSK) {
ret = s3c24xx_serial_rx_irq(irq, id);
ret = s3c24xx_serial_rx_irq(ourport);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_RXD_MSK);
}
if (pend & S3C64XX_UINTM_TXD_MSK) {
ret = s3c24xx_serial_tx_irq(irq, id);
ret = s3c24xx_serial_tx_irq(ourport);
wr_regl(port, S3C64XX_UINTP, S3C64XX_UINTM_TXD_MSK);
}
return ret;
@@ -963,19 +959,21 @@ static irqreturn_t s3c64xx_serial_handle_irq(int irq, void *id)
/* interrupt handler for Apple SoC's.*/
static irqreturn_t apple_serial_handle_irq(int irq, void *id)
{
const struct s3c24xx_uart_port *ourport = id;
struct s3c24xx_uart_port *ourport = id;
const struct uart_port *port = &ourport->port;
u32 pend = rd_regl(port, S3C2410_UTRSTAT);
irqreturn_t ret = IRQ_NONE;
if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO)) {
if (pend & (APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO |
APPLE_S5L_UTRSTAT_RXTO_LEGACY)) {
wr_regl(port, S3C2410_UTRSTAT,
APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO);
ret = s3c24xx_serial_rx_irq(irq, id);
APPLE_S5L_UTRSTAT_RXTHRESH | APPLE_S5L_UTRSTAT_RXTO |
APPLE_S5L_UTRSTAT_RXTO_LEGACY);
ret = s3c24xx_serial_rx_irq(ourport);
}
if (pend & APPLE_S5L_UTRSTAT_TXTHRESH) {
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_TXTHRESH);
ret = s3c24xx_serial_tx_irq(irq, id);
ret = s3c24xx_serial_tx_irq(ourport);
}
return ret;
@@ -1195,7 +1193,8 @@ static void apple_s5l_serial_shutdown(struct uart_port *port)
ucon = rd_regl(port, S3C2410_UCON);
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK);
APPLE_S5L_UCON_RXTO_ENA_MSK |
APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK);
wr_regl(port, S3C2410_UCON, ucon);
wr_regl(port, S3C2410_UTRSTAT, APPLE_S5L_UTRSTAT_ALL_FLAGS);
@@ -1292,6 +1291,7 @@ static int apple_s5l_serial_startup(struct uart_port *port)
/* Enable Rx Interrupt */
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTHRESH_ENA, S3C2410_UCON);
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_ENA, S3C2410_UCON);
s3c24xx_set_bit(port, APPLE_S5L_UCON_RXTO_LEGACY_ENA, S3C2410_UCON);
return ret;
}
@@ -2148,13 +2148,15 @@ static int s3c24xx_serial_resume_noirq(struct device *dev)
ucon &= ~(APPLE_S5L_UCON_TXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK);
APPLE_S5L_UCON_RXTO_ENA_MSK |
APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK);
if (ourport->tx_enabled)
ucon |= APPLE_S5L_UCON_TXTHRESH_ENA_MSK;
if (ourport->rx_enabled)
ucon |= APPLE_S5L_UCON_RXTHRESH_ENA_MSK |
APPLE_S5L_UCON_RXTO_ENA_MSK;
APPLE_S5L_UCON_RXTO_ENA_MSK |
APPLE_S5L_UCON_RXTO_LEGACY_ENA_MSK;
wr_regl(port, S3C2410_UCON, ucon);
@@ -2541,7 +2543,7 @@ static const struct s3c24xx_serial_drv_data s5l_serial_drv_data = {
.name = "Apple S5L UART",
.type = TYPE_APPLE_S5L,
.port_type = PORT_8250,
.iotype = UPIO_MEM,
.iotype = UPIO_MEM32,
.fifosize = 16,
.rx_fifomask = S3C2410_UFSTAT_RXMASK,
.rx_fifoshift = S3C2410_UFSTAT_RXSHIFT,
@@ -2827,6 +2829,9 @@ OF_EARLYCON_DECLARE(gs101, "google,gs101-uart", gs101_early_console_setup);
static int __init apple_s5l_early_console_setup(struct earlycon_device *device,
const char *opt)
{
/* Apple A7-A11 requires MMIO32 register accesses. */
device->port.iotype = UPIO_MEM32;
/* Close enough to S3C2410 for earlycon... */
device->port.private_data = &s3c2410_early_console_data;
+94 -89
View File
@@ -10,6 +10,7 @@
#undef DEFAULT_SYMBOL_NAMESPACE
#define DEFAULT_SYMBOL_NAMESPACE SERIAL_NXP_SC16IS7XX
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -78,52 +79,52 @@
#define SC16IS7XX_XOFF2_REG (0x07) /* Xoff2 word */
/* IER register bits */
#define SC16IS7XX_IER_RDI_BIT (1 << 0) /* Enable RX data interrupt */
#define SC16IS7XX_IER_THRI_BIT (1 << 1) /* Enable TX holding register
#define SC16IS7XX_IER_RDI_BIT BIT(0) /* Enable RX data interrupt */
#define SC16IS7XX_IER_THRI_BIT BIT(1) /* Enable TX holding register
* interrupt */
#define SC16IS7XX_IER_RLSI_BIT (1 << 2) /* Enable RX line status
#define SC16IS7XX_IER_RLSI_BIT BIT(2) /* Enable RX line status
* interrupt */
#define SC16IS7XX_IER_MSI_BIT (1 << 3) /* Enable Modem status
#define SC16IS7XX_IER_MSI_BIT BIT(3) /* Enable Modem status
* interrupt */
/* IER register bits - write only if (EFR[4] == 1) */
#define SC16IS7XX_IER_SLEEP_BIT (1 << 4) /* Enable Sleep mode */
#define SC16IS7XX_IER_XOFFI_BIT (1 << 5) /* Enable Xoff interrupt */
#define SC16IS7XX_IER_RTSI_BIT (1 << 6) /* Enable nRTS interrupt */
#define SC16IS7XX_IER_CTSI_BIT (1 << 7) /* Enable nCTS interrupt */
#define SC16IS7XX_IER_SLEEP_BIT BIT(4) /* Enable Sleep mode */
#define SC16IS7XX_IER_XOFFI_BIT BIT(5) /* Enable Xoff interrupt */
#define SC16IS7XX_IER_RTSI_BIT BIT(6) /* Enable nRTS interrupt */
#define SC16IS7XX_IER_CTSI_BIT BIT(7) /* Enable nCTS interrupt */
/* FCR register bits */
#define SC16IS7XX_FCR_FIFO_BIT (1 << 0) /* Enable FIFO */
#define SC16IS7XX_FCR_RXRESET_BIT (1 << 1) /* Reset RX FIFO */
#define SC16IS7XX_FCR_TXRESET_BIT (1 << 2) /* Reset TX FIFO */
#define SC16IS7XX_FCR_RXLVLL_BIT (1 << 6) /* RX Trigger level LSB */
#define SC16IS7XX_FCR_RXLVLH_BIT (1 << 7) /* RX Trigger level MSB */
#define SC16IS7XX_FCR_FIFO_BIT BIT(0) /* Enable FIFO */
#define SC16IS7XX_FCR_RXRESET_BIT BIT(1) /* Reset RX FIFO */
#define SC16IS7XX_FCR_TXRESET_BIT BIT(2) /* Reset TX FIFO */
#define SC16IS7XX_FCR_RXLVLL_BIT BIT(6) /* RX Trigger level LSB */
#define SC16IS7XX_FCR_RXLVLH_BIT BIT(7) /* RX Trigger level MSB */
/* FCR register bits - write only if (EFR[4] == 1) */
#define SC16IS7XX_FCR_TXLVLL_BIT (1 << 4) /* TX Trigger level LSB */
#define SC16IS7XX_FCR_TXLVLH_BIT (1 << 5) /* TX Trigger level MSB */
#define SC16IS7XX_FCR_TXLVLL_BIT BIT(4) /* TX Trigger level LSB */
#define SC16IS7XX_FCR_TXLVLH_BIT BIT(5) /* TX Trigger level MSB */
/* IIR register bits */
#define SC16IS7XX_IIR_NO_INT_BIT (1 << 0) /* No interrupts pending */
#define SC16IS7XX_IIR_ID_MASK 0x3e /* Mask for the interrupt ID */
#define SC16IS7XX_IIR_THRI_SRC 0x02 /* TX holding register empty */
#define SC16IS7XX_IIR_RDI_SRC 0x04 /* RX data interrupt */
#define SC16IS7XX_IIR_RLSE_SRC 0x06 /* RX line status error */
#define SC16IS7XX_IIR_RTOI_SRC 0x0c /* RX time-out interrupt */
#define SC16IS7XX_IIR_MSI_SRC 0x00 /* Modem status interrupt
* - only on 75x/76x
*/
#define SC16IS7XX_IIR_INPIN_SRC 0x30 /* Input pin change of state
* - only on 75x/76x
*/
#define SC16IS7XX_IIR_XOFFI_SRC 0x10 /* Received Xoff */
#define SC16IS7XX_IIR_CTSRTS_SRC 0x20 /* nCTS,nRTS change of state
* from active (LOW)
* to inactive (HIGH)
*/
#define SC16IS7XX_IIR_NO_INT_BIT 0x01 /* No interrupts pending */
#define SC16IS7XX_IIR_ID_MASK GENMASK(5, 1) /* Mask for the interrupt ID */
#define SC16IS7XX_IIR_THRI_SRC 0x02 /* TX holding register empty */
#define SC16IS7XX_IIR_RDI_SRC 0x04 /* RX data interrupt */
#define SC16IS7XX_IIR_RLSE_SRC 0x06 /* RX line status error */
#define SC16IS7XX_IIR_RTOI_SRC 0x0c /* RX time-out interrupt */
#define SC16IS7XX_IIR_MSI_SRC 0x00 /* Modem status interrupt
* - only on 75x/76x
*/
#define SC16IS7XX_IIR_INPIN_SRC 0x30 /* Input pin change of state
* - only on 75x/76x
*/
#define SC16IS7XX_IIR_XOFFI_SRC 0x10 /* Received Xoff */
#define SC16IS7XX_IIR_CTSRTS_SRC 0x20 /* nCTS,nRTS change of state
* from active (LOW)
* to inactive (HIGH)
*/
/* LCR register bits */
#define SC16IS7XX_LCR_LENGTH0_BIT (1 << 0) /* Word length bit 0 */
#define SC16IS7XX_LCR_LENGTH1_BIT (1 << 1) /* Word length bit 1
#define SC16IS7XX_LCR_LENGTH0_BIT BIT(0) /* Word length bit 0 */
#define SC16IS7XX_LCR_LENGTH1_BIT BIT(1) /* Word length bit 1
*
* Word length bits table:
* 00 -> 5 bit words
@@ -131,7 +132,7 @@
* 10 -> 7 bit words
* 11 -> 8 bit words
*/
#define SC16IS7XX_LCR_STOPLEN_BIT (1 << 2) /* STOP length bit
#define SC16IS7XX_LCR_STOPLEN_BIT BIT(2) /* STOP length bit
*
* STOP length bit table:
* 0 -> 1 stop bit
@@ -139,11 +140,11 @@
* word length is 5,
* 2 stop bits otherwise
*/
#define SC16IS7XX_LCR_PARITY_BIT (1 << 3) /* Parity bit enable */
#define SC16IS7XX_LCR_EVENPARITY_BIT (1 << 4) /* Even parity bit enable */
#define SC16IS7XX_LCR_FORCEPARITY_BIT (1 << 5) /* 9-bit multidrop parity */
#define SC16IS7XX_LCR_TXBREAK_BIT (1 << 6) /* TX break enable */
#define SC16IS7XX_LCR_DLAB_BIT (1 << 7) /* Divisor Latch enable */
#define SC16IS7XX_LCR_PARITY_BIT BIT(3) /* Parity bit enable */
#define SC16IS7XX_LCR_EVENPARITY_BIT BIT(4) /* Even parity bit enable */
#define SC16IS7XX_LCR_FORCEPARITY_BIT BIT(5) /* 9-bit multidrop parity */
#define SC16IS7XX_LCR_TXBREAK_BIT BIT(6) /* TX break enable */
#define SC16IS7XX_LCR_DLAB_BIT BIT(7) /* Divisor Latch enable */
#define SC16IS7XX_LCR_WORD_LEN_5 (0x00)
#define SC16IS7XX_LCR_WORD_LEN_6 (0x01)
#define SC16IS7XX_LCR_WORD_LEN_7 (0x02)
@@ -154,61 +155,65 @@
* reg set */
/* MCR register bits */
#define SC16IS7XX_MCR_DTR_BIT (1 << 0) /* DTR complement
#define SC16IS7XX_MCR_DTR_BIT BIT(0) /* DTR complement
* - only on 75x/76x
*/
#define SC16IS7XX_MCR_RTS_BIT (1 << 1) /* RTS complement */
#define SC16IS7XX_MCR_TCRTLR_BIT (1 << 2) /* TCR/TLR register enable */
#define SC16IS7XX_MCR_LOOP_BIT (1 << 4) /* Enable loopback test mode */
#define SC16IS7XX_MCR_XONANY_BIT (1 << 5) /* Enable Xon Any
#define SC16IS7XX_MCR_RTS_BIT BIT(1) /* RTS complement */
#define SC16IS7XX_MCR_TCRTLR_BIT BIT(2) /* TCR/TLR register enable */
#define SC16IS7XX_MCR_LOOP_BIT BIT(4) /* Enable loopback test mode */
#define SC16IS7XX_MCR_XONANY_BIT BIT(5) /* Enable Xon Any
* - write enabled
* if (EFR[4] == 1)
*/
#define SC16IS7XX_MCR_IRDA_BIT (1 << 6) /* Enable IrDA mode
#define SC16IS7XX_MCR_IRDA_BIT BIT(6) /* Enable IrDA mode
* - write enabled
* if (EFR[4] == 1)
*/
#define SC16IS7XX_MCR_CLKSEL_BIT (1 << 7) /* Divide clock by 4
#define SC16IS7XX_MCR_CLKSEL_BIT BIT(7) /* Divide clock by 4
* - write enabled
* if (EFR[4] == 1)
*/
/* LSR register bits */
#define SC16IS7XX_LSR_DR_BIT (1 << 0) /* Receiver data ready */
#define SC16IS7XX_LSR_OE_BIT (1 << 1) /* Overrun Error */
#define SC16IS7XX_LSR_PE_BIT (1 << 2) /* Parity Error */
#define SC16IS7XX_LSR_FE_BIT (1 << 3) /* Frame Error */
#define SC16IS7XX_LSR_BI_BIT (1 << 4) /* Break Interrupt */
#define SC16IS7XX_LSR_BRK_ERROR_MASK 0x1E /* BI, FE, PE, OE bits */
#define SC16IS7XX_LSR_THRE_BIT (1 << 5) /* TX holding register empty */
#define SC16IS7XX_LSR_TEMT_BIT (1 << 6) /* Transmitter empty */
#define SC16IS7XX_LSR_FIFOE_BIT (1 << 7) /* Fifo Error */
#define SC16IS7XX_LSR_DR_BIT BIT(0) /* Receiver data ready */
#define SC16IS7XX_LSR_OE_BIT BIT(1) /* Overrun Error */
#define SC16IS7XX_LSR_PE_BIT BIT(2) /* Parity Error */
#define SC16IS7XX_LSR_FE_BIT BIT(3) /* Frame Error */
#define SC16IS7XX_LSR_BI_BIT BIT(4) /* Break Interrupt */
#define SC16IS7XX_LSR_BRK_ERROR_MASK \
(SC16IS7XX_LSR_OE_BIT | \
SC16IS7XX_LSR_PE_BIT | \
SC16IS7XX_LSR_FE_BIT | \
SC16IS7XX_LSR_BI_BIT)
#define SC16IS7XX_LSR_THRE_BIT BIT(5) /* TX holding register empty */
#define SC16IS7XX_LSR_TEMT_BIT BIT(6) /* Transmitter empty */
#define SC16IS7XX_LSR_FIFOE_BIT BIT(7) /* Fifo Error */
/* MSR register bits */
#define SC16IS7XX_MSR_DCTS_BIT (1 << 0) /* Delta CTS Clear To Send */
#define SC16IS7XX_MSR_DDSR_BIT (1 << 1) /* Delta DSR Data Set Ready
#define SC16IS7XX_MSR_DCTS_BIT BIT(0) /* Delta CTS Clear To Send */
#define SC16IS7XX_MSR_DDSR_BIT BIT(1) /* Delta DSR Data Set Ready
* or (IO4)
* - only on 75x/76x
*/
#define SC16IS7XX_MSR_DRI_BIT (1 << 2) /* Delta RI Ring Indicator
#define SC16IS7XX_MSR_DRI_BIT BIT(2) /* Delta RI Ring Indicator
* or (IO7)
* - only on 75x/76x
*/
#define SC16IS7XX_MSR_DCD_BIT (1 << 3) /* Delta CD Carrier Detect
#define SC16IS7XX_MSR_DCD_BIT BIT(3) /* Delta CD Carrier Detect
* or (IO6)
* - only on 75x/76x
*/
#define SC16IS7XX_MSR_CTS_BIT (1 << 4) /* CTS */
#define SC16IS7XX_MSR_DSR_BIT (1 << 5) /* DSR (IO4)
#define SC16IS7XX_MSR_CTS_BIT BIT(4) /* CTS */
#define SC16IS7XX_MSR_DSR_BIT BIT(5) /* DSR (IO4)
* - only on 75x/76x
*/
#define SC16IS7XX_MSR_RI_BIT (1 << 6) /* RI (IO7)
#define SC16IS7XX_MSR_RI_BIT BIT(6) /* RI (IO7)
* - only on 75x/76x
*/
#define SC16IS7XX_MSR_CD_BIT (1 << 7) /* CD (IO6)
#define SC16IS7XX_MSR_CD_BIT BIT(7) /* CD (IO6)
* - only on 75x/76x
*/
#define SC16IS7XX_MSR_DELTA_MASK 0x0F /* Any of the delta bits! */
/*
* TCR register bits
@@ -241,19 +246,19 @@
#define SC16IS7XX_TLR_RX_TRIGGER(words) ((((words) / 4) & 0x0f) << 4)
/* IOControl register bits (Only 75x/76x) */
#define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */
#define SC16IS7XX_IOCONTROL_MODEM_A_BIT (1 << 1) /* Enable GPIO[7:4] as modem A pins */
#define SC16IS7XX_IOCONTROL_MODEM_B_BIT (1 << 2) /* Enable GPIO[3:0] as modem B pins */
#define SC16IS7XX_IOCONTROL_SRESET_BIT (1 << 3) /* Software Reset */
#define SC16IS7XX_IOCONTROL_LATCH_BIT BIT(0) /* Enable input latching */
#define SC16IS7XX_IOCONTROL_MODEM_A_BIT BIT(1) /* Enable GPIO[7:4] as modem A pins */
#define SC16IS7XX_IOCONTROL_MODEM_B_BIT BIT(2) /* Enable GPIO[3:0] as modem B pins */
#define SC16IS7XX_IOCONTROL_SRESET_BIT BIT(3) /* Software Reset */
/* EFCR register bits */
#define SC16IS7XX_EFCR_9BIT_MODE_BIT (1 << 0) /* Enable 9-bit or Multidrop
#define SC16IS7XX_EFCR_9BIT_MODE_BIT BIT(0) /* Enable 9-bit or Multidrop
* mode (RS485) */
#define SC16IS7XX_EFCR_RXDISABLE_BIT (1 << 1) /* Disable receiver */
#define SC16IS7XX_EFCR_TXDISABLE_BIT (1 << 2) /* Disable transmitter */
#define SC16IS7XX_EFCR_AUTO_RS485_BIT (1 << 4) /* Auto RS485 RTS direction */
#define SC16IS7XX_EFCR_RTS_INVERT_BIT (1 << 5) /* RTS output inversion */
#define SC16IS7XX_EFCR_IRDA_MODE_BIT (1 << 7) /* IrDA mode
#define SC16IS7XX_EFCR_RXDISABLE_BIT BIT(1) /* Disable receiver */
#define SC16IS7XX_EFCR_TXDISABLE_BIT BIT(2) /* Disable transmitter */
#define SC16IS7XX_EFCR_AUTO_RS485_BIT BIT(4) /* Auto RS485 RTS direction */
#define SC16IS7XX_EFCR_RTS_INVERT_BIT BIT(5) /* RTS output inversion */
#define SC16IS7XX_EFCR_IRDA_MODE_BIT BIT(7) /* IrDA mode
* 0 = rate upto 115.2 kbit/s
* - Only 75x/76x
* 1 = rate upto 1.152 Mbit/s
@@ -261,16 +266,16 @@
*/
/* EFR register bits */
#define SC16IS7XX_EFR_AUTORTS_BIT (1 << 6) /* Auto RTS flow ctrl enable */
#define SC16IS7XX_EFR_AUTOCTS_BIT (1 << 7) /* Auto CTS flow ctrl enable */
#define SC16IS7XX_EFR_XOFF2_DETECT_BIT (1 << 5) /* Enable Xoff2 detection */
#define SC16IS7XX_EFR_ENABLE_BIT (1 << 4) /* Enable enhanced functions
#define SC16IS7XX_EFR_AUTORTS_BIT BIT(6) /* Auto RTS flow ctrl enable */
#define SC16IS7XX_EFR_AUTOCTS_BIT BIT(7) /* Auto CTS flow ctrl enable */
#define SC16IS7XX_EFR_XOFF2_DETECT_BIT BIT(5) /* Enable Xoff2 detection */
#define SC16IS7XX_EFR_ENABLE_BIT BIT(4) /* Enable enhanced functions
* and writing to IER[7:4],
* FCR[5:4], MCR[7:5]
*/
#define SC16IS7XX_EFR_SWFLOW3_BIT (1 << 3) /* SWFLOW bit 3 */
#define SC16IS7XX_EFR_SWFLOW2_BIT (1 << 2) /* SWFLOW bit 2
*
#define SC16IS7XX_EFR_SWFLOW3_BIT BIT(3)
#define SC16IS7XX_EFR_SWFLOW2_BIT BIT(2)
/*
* SWFLOW bits 3 & 2 table:
* 00 -> no transmitter flow
* control
@@ -282,10 +287,10 @@
* XON1, XON2, XOFF1 and
* XOFF2
*/
#define SC16IS7XX_EFR_SWFLOW1_BIT (1 << 1) /* SWFLOW bit 2 */
#define SC16IS7XX_EFR_SWFLOW0_BIT (1 << 0) /* SWFLOW bit 3
*
* SWFLOW bits 3 & 2 table:
#define SC16IS7XX_EFR_SWFLOW1_BIT BIT(1)
#define SC16IS7XX_EFR_SWFLOW0_BIT BIT(0)
/*
* SWFLOW bits 1 & 0 table:
* 00 -> no received flow
* control
* 01 -> receiver compares
@@ -309,9 +314,9 @@
#define SC16IS7XX_FIFO_SIZE (64)
#define SC16IS7XX_GPIOS_PER_BANK 4
#define SC16IS7XX_RECONF_MD (1 << 0)
#define SC16IS7XX_RECONF_IER (1 << 1)
#define SC16IS7XX_RECONF_RS485 (1 << 2)
#define SC16IS7XX_RECONF_MD BIT(0)
#define SC16IS7XX_RECONF_IER BIT(1)
#define SC16IS7XX_RECONF_RS485 BIT(2)
struct sc16is7xx_one_config {
unsigned int flags;
+62 -80
View File
@@ -407,14 +407,16 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
/*
* Turn off DTR and RTS early.
*/
if (uport && uart_console(uport) && tty) {
uport->cons->cflag = tty->termios.c_cflag;
uport->cons->ispeed = tty->termios.c_ispeed;
uport->cons->ospeed = tty->termios.c_ospeed;
}
if (uport) {
if (uart_console(uport) && tty) {
uport->cons->cflag = tty->termios.c_cflag;
uport->cons->ispeed = tty->termios.c_ispeed;
uport->cons->ospeed = tty->termios.c_ospeed;
}
if (!tty || C_HUPCL(tty))
uart_port_dtr_rts(uport, false);
if (!tty || C_HUPCL(tty))
uart_port_dtr_rts(uport, false);
}
uart_port_shutdown(port);
}
@@ -1102,21 +1104,19 @@ static int uart_tiocmget(struct tty_struct *tty)
struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port;
struct uart_port *uport;
int result = -EIO;
int result;
guard(mutex)(&port->mutex);
mutex_lock(&port->mutex);
uport = uart_port_check(state);
if (!uport)
goto out;
if (!uport || tty_io_error(tty))
return -EIO;
uart_port_lock_irq(uport);
result = uport->mctrl;
result |= uport->ops->get_mctrl(uport);
uart_port_unlock_irq(uport);
if (!tty_io_error(tty)) {
uart_port_lock_irq(uport);
result = uport->mctrl;
result |= uport->ops->get_mctrl(uport);
uart_port_unlock_irq(uport);
}
out:
mutex_unlock(&port->mutex);
return result;
}
@@ -1126,20 +1126,16 @@ uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port;
struct uart_port *uport;
int ret = -EIO;
mutex_lock(&port->mutex);
guard(mutex)(&port->mutex);
uport = uart_port_check(state);
if (!uport)
goto out;
if (!uport || tty_io_error(tty))
return -EIO;
if (!tty_io_error(tty)) {
uart_update_mctrl(uport, set, clear);
ret = 0;
}
out:
mutex_unlock(&port->mutex);
return ret;
uart_update_mctrl(uport, set, clear);
return 0;
}
static int uart_break_ctl(struct tty_struct *tty, int break_state)
@@ -1147,19 +1143,17 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state)
struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port;
struct uart_port *uport;
int ret = -EIO;
mutex_lock(&port->mutex);
guard(mutex)(&port->mutex);
uport = uart_port_check(state);
if (!uport)
goto out;
return -EIO;
if (uport->type != PORT_UNKNOWN && uport->ops->break_ctl)
uport->ops->break_ctl(uport, break_state);
ret = 0;
out:
mutex_unlock(&port->mutex);
return ret;
return 0;
}
static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
@@ -1176,17 +1170,14 @@ static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
* changing, and hence any extra opens of the port while
* we're auto-configuring.
*/
if (mutex_lock_interruptible(&port->mutex))
return -ERESTARTSYS;
scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &port->mutex) {
uport = uart_port_check(state);
if (!uport)
return -EIO;
uport = uart_port_check(state);
if (!uport) {
ret = -EIO;
goto out;
}
if (tty_port_users(port) != 1)
return -EBUSY;
ret = -EBUSY;
if (tty_port_users(port) == 1) {
uart_shutdown(tty, state);
/*
@@ -1207,14 +1198,15 @@ static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
uport->ops->config_port(uport, flags);
ret = uart_startup(tty, state, true);
if (ret == 0)
tty_port_set_initialized(port, true);
if (ret < 0)
return ret;
if (ret > 0)
ret = 0;
return 0;
tty_port_set_initialized(port, true);
}
out:
mutex_unlock(&port->mutex);
return ret;
return 0;
}
static void uart_enable_ms(struct uart_port *uport)
@@ -1709,10 +1701,11 @@ static void uart_set_termios(struct tty_struct *tty,
unsigned int iflag_mask = IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK;
bool sw_changed = false;
mutex_lock(&state->port.mutex);
guard(mutex)(&state->port.mutex);
uport = uart_port_check(state);
if (!uport)
goto out;
return;
/*
* Drivers doing software flow control also need to know
@@ -1735,9 +1728,8 @@ static void uart_set_termios(struct tty_struct *tty,
tty->termios.c_ospeed == old_termios->c_ospeed &&
tty->termios.c_ispeed == old_termios->c_ispeed &&
((tty->termios.c_iflag ^ old_termios->c_iflag) & iflag_mask) == 0 &&
!sw_changed) {
goto out;
}
!sw_changed)
return;
uart_change_line_settings(tty, state, old_termios);
/* reload cflag from termios; port driver may have overridden flags */
@@ -1754,8 +1746,6 @@ static void uart_set_termios(struct tty_struct *tty,
mask |= TIOCM_RTS;
uart_set_mctrl(uport, mask);
}
out:
mutex_unlock(&state->port.mutex);
}
/*
@@ -2049,10 +2039,11 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
unsigned int status;
int mmio;
mutex_lock(&port->mutex);
guard(mutex)(&port->mutex);
uport = uart_port_check(state);
if (!uport)
goto out;
return;
mmio = uport->iotype >= UPIO_MEM;
seq_printf(m, "%d: uart:%s %s%08llX irq:%d",
@@ -2064,7 +2055,7 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
if (uport->type == PORT_UNKNOWN) {
seq_putc(m, '\n');
goto out;
return;
}
if (capable(CAP_SYS_ADMIN)) {
@@ -2115,8 +2106,6 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
seq_putc(m, '\n');
#undef STATBIT
#undef INFOBIT
out:
mutex_unlock(&port->mutex);
}
static int uart_proc_show(struct seq_file *m, void *v)
@@ -2393,13 +2382,12 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
struct device *tty_dev;
struct uart_match match = {uport, drv};
mutex_lock(&port->mutex);
guard(mutex)(&port->mutex);
tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port);
if (tty_dev && device_may_wakeup(tty_dev)) {
enable_irq_wake(uport->irq);
put_device(tty_dev);
mutex_unlock(&port->mutex);
return 0;
}
put_device(tty_dev);
@@ -2417,7 +2405,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
uart_port_unlock_irq(uport);
}
device_set_awake_path(uport->dev);
goto unlock;
return 0;
}
uport->suspended = 1;
@@ -2460,8 +2448,6 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
console_stop(uport->cons);
uart_change_pm(state, UART_PM_STATE_OFF);
unlock:
mutex_unlock(&port->mutex);
return 0;
}
@@ -2475,14 +2461,13 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
struct uart_match match = {uport, drv};
struct ktermios termios;
mutex_lock(&port->mutex);
guard(mutex)(&port->mutex);
tty_dev = device_find_child(&uport->port_dev->dev, &match, serial_match_port);
if (!uport->suspended && device_may_wakeup(tty_dev)) {
if (irqd_is_wakeup_set(irq_get_irq_data((uport->irq))))
disable_irq_wake(uport->irq);
put_device(tty_dev);
mutex_unlock(&port->mutex);
return 0;
}
put_device(tty_dev);
@@ -2555,8 +2540,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
tty_port_set_suspended(port, false);
}
mutex_unlock(&port->mutex);
return 0;
}
EXPORT_SYMBOL(uart_resume_port);
@@ -2696,14 +2679,13 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
int ret = 0;
tport = &state->port;
mutex_lock(&tport->mutex);
guard(mutex)(&tport->mutex);
port = uart_port_check(state);
if (!port || port->type == PORT_UNKNOWN ||
!(port->ops->poll_get_char && port->ops->poll_put_char)) {
ret = -1;
goto out;
}
!(port->ops->poll_get_char && port->ops->poll_put_char))
return -1;
pm_state = state->pm_state;
uart_change_pm(state, UART_PM_STATE_ON);
@@ -2723,10 +2705,10 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
ret = uart_set_options(port, NULL, baud, parity, bits, flow);
console_list_unlock();
}
out:
if (ret)
uart_change_pm(state, pm_state);
mutex_unlock(&tport->mutex);
return ret;
}
+3 -7
View File
@@ -808,7 +808,6 @@ static void asc_serial_remove(struct platform_device *pdev)
uart_remove_one_port(&asc_uart_driver, port);
}
#ifdef CONFIG_PM_SLEEP
static int asc_serial_suspend(struct device *dev)
{
struct uart_port *port = dev_get_drvdata(dev);
@@ -823,8 +822,6 @@ static int asc_serial_resume(struct device *dev)
return uart_resume_port(&asc_uart_driver, port);
}
#endif /* CONFIG_PM_SLEEP */
/*----------------------------------------------------------------------*/
#ifdef CONFIG_SERIAL_ST_ASC_CONSOLE
@@ -932,16 +929,15 @@ static struct uart_driver asc_uart_driver = {
.cons = ASC_SERIAL_CONSOLE,
};
static const struct dev_pm_ops asc_serial_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(asc_serial_suspend, asc_serial_resume)
};
static DEFINE_SIMPLE_DEV_PM_OPS(asc_serial_pm_ops, asc_serial_suspend,
asc_serial_resume);
static struct platform_driver asc_serial_driver = {
.probe = asc_serial_probe,
.remove_new = asc_serial_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &asc_serial_pm_ops,
.pm = pm_sleep_ptr(&asc_serial_pm_ops),
.of_match_table = of_match_ptr(asc_match),
},
};
+1 -1
View File
@@ -219,7 +219,7 @@ struct cdns_platform_data {
u32 quirks;
};
struct serial_rs485 cdns_rs485_supported = {
static struct serial_rs485 cdns_rs485_supported = {
.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND |
SER_RS485_RTS_AFTER_SEND,
.delay_rts_before_send = 1,
+4 -7
View File
@@ -350,22 +350,19 @@ int tty_dev_name_to_number(const char *name, dev_t *number)
return ret;
prefix_length = str - name;
mutex_lock(&tty_mutex);
guard(mutex)(&tty_mutex);
list_for_each_entry(p, &tty_drivers, tty_drivers)
if (prefix_length == strlen(p->name) && strncmp(name,
p->name, prefix_length) == 0) {
if (index < p->num) {
*number = MKDEV(p->major, p->minor_start + index);
goto out;
return 0;
}
}
/* if here then driver wasn't found */
ret = -ENODEV;
out:
mutex_unlock(&tty_mutex);
return ret;
return -ENODEV;
}
EXPORT_SYMBOL_GPL(tty_dev_name_to_number);
+2 -3
View File
@@ -37,8 +37,7 @@ struct cdns3_wrap {
#define PCI_DRIVER_NAME "cdns3-pci-usbss"
#define PLAT_DRIVER_NAME "cdns-usb3"
#define CDNS_VENDOR_ID 0x17cd
#define CDNS_DEVICE_ID 0x0100
#define PCI_DEVICE_ID_CDNS_USB3 0x0100
static struct pci_dev *cdns3_get_second_fun(struct pci_dev *pdev)
{
@@ -190,7 +189,7 @@ static void cdns3_pci_remove(struct pci_dev *pdev)
}
static const struct pci_device_id cdns3_pci_ids[] = {
{ PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), },
{ PCI_VDEVICE(CDNS, PCI_DEVICE_ID_CDNS_USB3) },
{ 0, }
};
+15 -14
View File
@@ -28,10 +28,11 @@
#define PCI_DRIVER_NAME "cdns-pci-usbssp"
#define PLAT_DRIVER_NAME "cdns-usbssp"
#define CDNS_VENDOR_ID 0x17cd
#define CDNS_DEVICE_ID 0x0200
#define CDNS_DRD_ID 0x0100
#define CDNS_DRD_IF (PCI_CLASS_SERIAL_USB << 8 | 0x80)
#define PCI_DEVICE_ID_CDNS_USB3 0x0100
#define PCI_DEVICE_ID_CDNS_UDC 0x0200
#define PCI_CLASS_SERIAL_USB_CDNS_USB3 (PCI_CLASS_SERIAL_USB << 8 | 0x80)
#define PCI_CLASS_SERIAL_USB_CDNS_UDC PCI_CLASS_SERIAL_USB_DEVICE
static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
{
@@ -40,10 +41,10 @@ static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
* Platform has two function. The fist keeps resources for
* Host/Device while the secon keeps resources for DRD/OTG.
*/
if (pdev->device == CDNS_DEVICE_ID)
return pci_get_device(pdev->vendor, CDNS_DRD_ID, NULL);
else if (pdev->device == CDNS_DRD_ID)
return pci_get_device(pdev->vendor, CDNS_DEVICE_ID, NULL);
if (pdev->device == PCI_DEVICE_ID_CDNS_UDC)
return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_USB3, NULL);
if (pdev->device == PCI_DEVICE_ID_CDNS_USB3)
return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_UDC, NULL);
return NULL;
}
@@ -220,12 +221,12 @@ static const struct dev_pm_ops cdnsp_pci_pm_ops = {
};
static const struct pci_device_id cdnsp_pci_ids[] = {
{ PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_SERIAL_USB_DEVICE, PCI_ANY_ID },
{ PCI_VENDOR_ID_CDNS, CDNS_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
CDNS_DRD_IF, PCI_ANY_ID },
{ PCI_VENDOR_ID_CDNS, CDNS_DRD_ID, PCI_ANY_ID, PCI_ANY_ID,
CDNS_DRD_IF, PCI_ANY_ID },
{ PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_UDC),
.class = PCI_CLASS_SERIAL_USB_CDNS_UDC },
{ PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_UDC),
.class = PCI_CLASS_SERIAL_USB_CDNS_USB3 },
{ PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USB3),
.class = PCI_CLASS_SERIAL_USB_CDNS_USB3 },
{ 0, }
};
+4 -2
View File
@@ -718,7 +718,8 @@ int cdnsp_remove_request(struct cdnsp_device *pdev,
seg = cdnsp_trb_in_td(pdev, cur_td->start_seg, cur_td->first_trb,
cur_td->last_trb, hw_deq);
if (seg && (pep->ep_state & EP_ENABLED))
if (seg && (pep->ep_state & EP_ENABLED) &&
!(pep->ep_state & EP_DIS_IN_RROGRESS))
cdnsp_find_new_dequeue_state(pdev, pep, preq->request.stream_id,
cur_td, &deq_state);
else
@@ -736,7 +737,8 @@ int cdnsp_remove_request(struct cdnsp_device *pdev,
* During disconnecting all endpoint will be disabled so we don't
* have to worry about updating dequeue pointer.
*/
if (pdev->cdnsp_state & CDNSP_STATE_DISCONNECT_PENDING) {
if (pdev->cdnsp_state & CDNSP_STATE_DISCONNECT_PENDING ||
pep->ep_state & EP_DIS_IN_RROGRESS) {
status = -ESHUTDOWN;
ret = cdnsp_cmd_set_deq(pdev, pep, &deq_state);
}
+3 -1
View File
@@ -62,7 +62,9 @@ static const struct xhci_plat_priv xhci_plat_cdns3_xhci = {
.resume_quirk = xhci_cdns3_resume_quirk,
};
static const struct xhci_plat_priv xhci_plat_cdnsp_xhci;
static const struct xhci_plat_priv xhci_plat_cdnsp_xhci = {
.quirks = XHCI_CDNS_SCTX_QUIRK,
};
static int __cdns_host_init(struct cdns *cdns)
{
+1 -1
View File
@@ -128,7 +128,7 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev)
* In case the fsl,usbmisc property is not present this device doesn't
* need usbmisc. Return NULL (which is no error here)
*/
if (!of_get_property(np, "fsl,usbmisc", NULL))
if (!of_property_present(np, "fsl,usbmisc"))
return NULL;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+2 -2
View File
@@ -18,7 +18,7 @@ struct npcm_udc_data {
struct ci_hdrc_platform_data pdata;
};
static int npcm_udc_notify_event(struct ci_hdrc *ci, unsigned event)
static int npcm_udc_notify_event(struct ci_hdrc *ci, unsigned int event)
{
struct device *dev = ci->dev->parent;
@@ -28,7 +28,7 @@ static int npcm_udc_notify_event(struct ci_hdrc *ci, unsigned event)
hw_write(ci, OP_USBMODE, 0xffffffff, 0x0);
break;
default:
dev_dbg(dev, "unknown ci_hdrc event (%d)\n",event);
dev_dbg(dev, "unknown ci_hdrc event (%d)\n", event);
break;
}
+7 -1
View File
@@ -86,7 +86,7 @@ static int hw_device_state(struct ci_hdrc *ci, u32 dma)
hw_write(ci, OP_ENDPTLISTADDR, ~0, dma);
/* interrupt, error, port change, reset, sleep/suspend */
hw_write(ci, OP_USBINTR, ~0,
USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
USBi_UI|USBi_UEI|USBi_PCI|USBi_URI);
} else {
hw_write(ci, OP_USBINTR, ~0, 0);
}
@@ -877,6 +877,7 @@ __releases(ci->lock)
__acquires(ci->lock)
{
int retval;
u32 intr;
spin_unlock(&ci->lock);
if (ci->gadget.speed != USB_SPEED_UNKNOWN)
@@ -890,6 +891,11 @@ __acquires(ci->lock)
if (retval)
goto done;
/* clear SLI */
hw_write(ci, OP_USBSTS, USBi_SLI, USBi_SLI);
intr = hw_read(ci, OP_USBINTR, ~0);
hw_write(ci, OP_USBINTR, ~0, intr | USBi_SLI);
ci->status = usb_ep_alloc_request(&ci->ep0in->ep, GFP_ATOMIC);
if (ci->status == NULL)
retval = -ENOMEM;
+2
View File
@@ -962,10 +962,12 @@ static int get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
struct acm *acm = tty->driver_data;
ss->line = acm->minor;
mutex_lock(&acm->port.mutex);
ss->close_delay = jiffies_to_msecs(acm->port.close_delay) / 10;
ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE :
jiffies_to_msecs(acm->port.closing_wait) / 10;
mutex_unlock(&acm->port.mutex);
return 0;
}
+1 -1
View File
@@ -754,7 +754,7 @@ static struct urb *usbtmc_create_urb(void)
if (!urb)
return NULL;
dmabuf = kmalloc(bufsize, GFP_KERNEL);
dmabuf = kzalloc(bufsize, GFP_KERNEL);
if (!dmabuf) {
usb_free_urb(urb);
return NULL;
+10 -12
View File
@@ -107,19 +107,18 @@ EXPORT_SYMBOL_GPL(usb_speed_string);
*/
enum usb_device_speed usb_get_maximum_speed(struct device *dev)
{
const char *maximum_speed;
const char *p = "maximum-speed";
int ret;
ret = device_property_read_string(dev, "maximum-speed", &maximum_speed);
if (ret < 0)
return USB_SPEED_UNKNOWN;
ret = match_string(ssp_rate, ARRAY_SIZE(ssp_rate), maximum_speed);
ret = device_property_match_property_string(dev, p, ssp_rate, ARRAY_SIZE(ssp_rate));
if (ret > 0)
return USB_SPEED_SUPER_PLUS;
ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed);
return (ret < 0) ? USB_SPEED_UNKNOWN : ret;
ret = device_property_match_property_string(dev, p, speed_names, ARRAY_SIZE(speed_names));
if (ret > 0)
return ret;
return USB_SPEED_UNKNOWN;
}
EXPORT_SYMBOL_GPL(usb_get_maximum_speed);
@@ -276,14 +275,13 @@ EXPORT_SYMBOL_GPL(usb_decode_interval);
*/
enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)
{
struct device_node *controller = NULL;
struct device_node *controller;
struct of_phandle_args args;
const char *dr_mode;
int index;
int err;
do {
controller = of_find_node_with_property(controller, "phys");
for_each_node_with_property(controller, "phys") {
if (!of_device_is_available(controller))
continue;
index = 0;
@@ -306,7 +304,7 @@ enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)
goto finish;
index++;
} while (args.np);
} while (controller);
}
finish:
err = of_property_read_string(controller, "dr_mode", &dr_mode);
+53
View File
@@ -142,6 +142,53 @@ int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)
}
EXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
/**
* usb_acpi_add_usb4_devlink - add device link to USB4 Host Interface for tunneled USB3 devices
*
* @udev: Tunneled USB3 device connected to a roothub.
*
* Adds a device link between a tunneled USB3 device and the USB4 Host Interface
* device to ensure correct runtime PM suspend and resume order. This function
* should only be called for tunneled USB3 devices.
* The USB4 Host Interface this tunneled device depends on is found from the roothub
* port ACPI device specific data _DSD entry.
*
* Return: negative error code on failure, 0 otherwise
*/
static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
{
const struct device_link *link;
struct usb_port *port_dev;
struct usb_hub *hub;
if (!udev->parent || udev->parent->parent)
return 0;
hub = usb_hub_to_struct_hub(udev->parent);
port_dev = hub->ports[udev->portnum - 1];
struct fwnode_handle *nhi_fwnode __free(fwnode_handle) =
fwnode_find_reference(dev_fwnode(&port_dev->dev), "usb4-host-interface", 0);
if (IS_ERR(nhi_fwnode))
return 0;
link = device_link_add(&port_dev->child->dev, nhi_fwnode->dev,
DL_FLAG_AUTOREMOVE_CONSUMER |
DL_FLAG_RPM_ACTIVE |
DL_FLAG_PM_RUNTIME);
if (!link) {
dev_err(&port_dev->dev, "Failed to created device link from %s to %s\n",
dev_name(&port_dev->child->dev), dev_name(nhi_fwnode->dev));
return -EINVAL;
}
dev_dbg(&port_dev->dev, "Created device link from %s to %s\n",
dev_name(&port_dev->child->dev), dev_name(nhi_fwnode->dev));
return 0;
}
/*
* Private to usb-acpi, all the core needs to know is that
* port_dev->location is non-zero when it has been set by the firmware.
@@ -262,6 +309,12 @@ usb_acpi_find_companion_for_device(struct usb_device *udev)
if (!hub)
return NULL;
/* Tunneled USB3 devices depend on USB4 Host Interface, set device link to it */
if (udev->speed >= USB_SPEED_SUPER &&
udev->tunnel_mode != USB_LINK_NATIVE)
usb_acpi_add_usb4_devlink(udev);
/*
* This is an embedded USB device connected to a port and such
* devices share port's ACPI companion.
+1
View File
@@ -702,6 +702,7 @@ static int params_show(struct seq_file *seq, void *v)
print_param(seq, p, uframe_sched);
print_param(seq, p, external_id_pin_ctl);
print_param(seq, p, power_down);
print_param(seq, p, no_clock_gating);
print_param(seq, p, lpm);
print_param(seq, p, lpm_clock_gating);
print_param(seq, p, besl);
+9
View File
@@ -127,6 +127,15 @@ static int dwc2_drd_role_sw_set(struct usb_role_switch *sw, enum usb_role role)
role = USB_ROLE_DEVICE;
}
if ((IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) ||
IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)) &&
dwc2_is_device_mode(hsotg) &&
hsotg->lx_state == DWC2_L2 &&
hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
hsotg->bus_suspended &&
!hsotg->params.no_clock_gating)
dwc2_gadget_exit_clock_gating(hsotg, 0);
if (role == USB_ROLE_HOST) {
already = dwc2_ovr_avalid(hsotg, true);
} else if (role == USB_ROLE_DEVICE) {

Some files were not shown because too many files have changed in this diff Show More