Merge 5d99aa093b ("Merge tag 'staging-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging") into android-mainline

TTY/Staging/USB merges on the way to 5.12-rc1

Resolves merge issues with:
	drivers/usb/gadget/configfs.c
	drivers/usb/typec/tcpm/tcpm.c
	include/linux/usb/tcpm.h

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ic094f04295e248c167193506a4bd1fc8b1856a93
This commit is contained in:
Greg Kroah-Hartman 2021-02-24 09:32:55 +01:00
commit c979eb9d81
507 changed files with 26558 additions and 13481 deletions

View File

@ -198,6 +198,7 @@ Description:
Units after application of scale and offset are m/s^2.
What: /sys/bus/iio/devices/iio:deviceX/in_angl_raw
What: /sys/bus/iio/devices/iio:deviceX/in_anglY_raw
KernelVersion: 4.17
Contact: linux-iio@vger.kernel.org
Description:
@ -1812,3 +1813,13 @@ Contact: linux-iio@vger.kernel.org
Description:
Unscaled light intensity according to CIE 1931/DIN 5033 color space.
Units after application of scale are nano nanowatts per square meter.
What: /sys/bus/iio/devices/iio:deviceX/in_anglY_label
KernelVersion: 5.12
Contact: linux-iio@vger.kernel.org
Description:
Optional symbolic label for channel Y.
For Intel hid hinge sensor, the label values are:
hinge, keyboard, screen. It means the three channels
each correspond respectively to hinge angle, keyboard angle,
and screen angle.

View File

@ -0,0 +1,31 @@
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_dither_enable
KernelVersion: 5.12
Contact: linux-iio@vger.kernel.org
Description:
Dither enable. Write 1 to enable dither or 0 to disable it.
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_dither_invert
KernelVersion: 5.12
Contact: linux-iio@vger.kernel.org
Description:
Inverts the dither applied to the selected DAC channel. Dither is not
inverted by default. Write "1" to invert dither.
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_dither_scale_available
KernelVersion: 5.12
Contact: linux-iio@vger.kernel.org
Description:
Returns possible scalings available for the current channel.
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_dither_scale
KernelVersion: 5.12
Contact: linux-iio@vger.kernel.org
Description:
Scales the dither before it is applied to the selected channel.
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_dither_source
KernelVersion: 5.12
Contact: linux-iio@vger.kernel.org
Description:
Selects dither source applied to the selected channel. Write "0" to
select N0 source, write "1" to select N1 source.

View File

@ -49,6 +49,15 @@ Description: Holds a comma separated list of device unique_ids that
If a device is authorized automatically during boot its
boot attribute is set to 1.
What: /sys/bus/thunderbolt/devices/.../domainX/deauthorization
Date: May 2021
KernelVersion: 5.12
Contact: Mika Westerberg <mika.westerberg@linux.intel.com>
Description: This attribute tells whether the system supports
de-authorization of devices. Value of 1 means user can
de-authorize PCIe tunnel by writing 0 to authorized
attribute under each device.
What: /sys/bus/thunderbolt/devices/.../domainX/iommu_dma_protection
Date: Mar 2019
KernelVersion: 4.21
@ -76,6 +85,8 @@ Description: This attribute holds current Thunderbolt security level
usbonly Automatically tunnel USB controller of the
connected Thunderbolt dock (and Display Port). All
PCIe links downstream of the dock are removed.
nopcie USB4 system where PCIe tunneling is disabled from
the BIOS.
======= ==================================================
What: /sys/bus/thunderbolt/devices/.../authorized
@ -84,22 +95,25 @@ KernelVersion: 4.13
Contact: thunderbolt-software@lists.01.org
Description: This attribute is used to authorize Thunderbolt devices
after they have been connected. If the device is not
authorized, no devices such as PCIe and Display port are
available to the system.
authorized, no PCIe devices are available to the system.
Contents of this attribute will be 0 when the device is not
yet authorized.
Possible values are supported:
== ===========================================
== ===================================================
0 The device will be de-authorized (only supported if
deauthorization attribute under domain contains 1)
1 The device will be authorized and connected
== ===========================================
== ===================================================
When key attribute contains 32 byte hex string the possible
values are:
== ========================================================
0 The device will be de-authorized (only supported if
deauthorization attribute under domain contains 1)
1 The 32 byte hex string is added to the device NVM and
the device is authorized.
2 Send a challenge based on the 32 byte hex string. If the

View File

@ -0,0 +1,6 @@
What: /sys/class/leds/<led>/ttyname
Date: Dec 2020
KernelVersion: 5.10
Contact: linux-leds@vger.kernel.org
Description:
Specifies the tty device name of the triggering tty

View File

@ -105,7 +105,25 @@ Date: April 2017
Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Description:
Revision number of the supported USB Power Delivery
specification, or 0 when USB Power Delivery is not supported.
specification, or 0.0 when USB Power Delivery is not supported.
Example values:
- "2.0": USB Power Delivery Release 2.0
- "3.0": USB Power Delivery Release 3.0
- "3.1": USB Power Delivery Release 3.1
What: /sys/class/typec/<port>-{partner|cable}/usb_power_delivery_revision
Date: January 2021
Contact: Benson Leung <bleung@chromium.org>
Description:
Revision number of the supported USB Power Delivery
specification of the port partner or cable, or 0.0 when USB
Power Delivery is not supported.
Example values:
- "2.0": USB Power Delivery Release 2.0
- "3.0": USB Power Delivery Release 3.0
- "3.1": USB Power Delivery Release 3.1
What: /sys/class/typec/<port>/usb_typec_revision
Date: April 2017

View File

@ -47,6 +47,9 @@ be DMA masters and thus read contents of the host memory without CPU and OS
knowing about it. There are ways to prevent this by setting up an IOMMU but
it is not always available for various reasons.
Some USB4 systems have a BIOS setting to disable PCIe tunneling. This is
treated as another security level (nopcie).
The security levels are as follows:
none
@ -77,6 +80,10 @@ The security levels are as follows:
Display Port in a dock. All PCIe links downstream of the dock are
removed.
nopcie
PCIe tunneling is disabled/forbidden from the BIOS. Available in some
USB4 systems.
The current security level can be read from
``/sys/bus/thunderbolt/devices/domainX/security`` where ``domainX`` is
the Thunderbolt domain the host controller manages. There is typically
@ -153,6 +160,22 @@ If the user still wants to connect the device they can either approve
the device without a key or write a new key and write 1 to the
``authorized`` file to get the new key stored on the device NVM.
De-authorizing devices
----------------------
It is possible to de-authorize devices by writing ``0`` to their
``authorized`` attribute. This requires support from the connection
manager implementation and can be checked by reading domain
``deauthorization`` attribute. If it reads ``1`` then the feature is
supported.
When a device is de-authorized the PCIe tunnel from the parent device
PCIe downstream (or root) port to the device PCIe upstream port is torn
down. This is essentially the same thing as PCIe hot-remove and the PCIe
toplogy in question will not be accessible anymore until the device is
authorized again. If there is storage such as NVMe or similar involved,
there is a risk for data loss if the filesystem on that storage is not
properly shut down. You have been warned!
DMA protection utilizing IOMMU
------------------------------
Recent systems from 2018 and forward with Thunderbolt ports may natively

View File

@ -137,6 +137,18 @@ properties:
maxItems: 7
$ref: /schemas/types.yaml#/definitions/uint32-array
sink-vdos:
description: An array of u32 with each entry, a Vendor Defined Message Object (VDO),
providing additional information corresponding to the product, the detailed bit
definitions and the order of each VDO can be found in
"USB Power Delivery Specification Revision 3.0, Version 2.0 + ECNs 2020-12-10"
chapter 6.4.4.3.1 Discover Identity. User can specify the VDO array via
VDO_IDH/_CERT/_PRODUCT/_UFP/_DFP/_PCABLE/_ACABLE(1/2)/_VPD() defined in
dt-bindings/usb/pd.h.
minItems: 3
maxItems: 6
$ref: /schemas/types.yaml#/definitions/uint32-array
op-sink-microwatt:
description: Sink required operating power in microwatt, if source can't
offer the power, Capability Mismatch is set. Required for power sink and

View File

@ -20,6 +20,9 @@ properties:
reg:
maxItems: 1
vdd-supply: true
vddio-supply: true
mount-matrix:
description: an optional 3x3 mounting rotation matrix.

View File

@ -1,13 +1,22 @@
Xilinx XADC device driver
This binding document describes the bindings for both of them since the
bindings are very similar. The Xilinx XADC is a ADC that can be found in the
series 7 FPGAs from Xilinx. The XADC has a DRP interface for communication.
Currently two different frontends for the DRP interface exist. One that is only
available on the ZYNQ family as a hardmacro in the SoC portion of the ZYNQ. The
other one is available on all series 7 platforms and is a softmacro with a AXI
interface. This binding document describes the bindings for both of them since
the bindings are very similar.
This binding document describes the bindings for the Xilinx 7 Series XADC as well
as the UltraScale/UltraScale+ System Monitor.
The Xilinx XADC is an ADC that can be found in the Series 7 FPGAs from Xilinx.
The XADC has a DRP interface for communication. Currently two different
frontends for the DRP interface exist. One that is only available on the ZYNQ
family as a hardmacro in the SoC portion of the ZYNQ. The other one is available
on all series 7 platforms and is a softmacro with a AXI interface. This binding
document describes the bindings for both of them since the bindings are very
similar.
The Xilinx System Monitor is an ADC that is found in the UltraScale and
UltraScale+ FPGAs from Xilinx. The System Monitor provides a DRP interface for
communication. Xilinx provides a standard IP core that can be used to access the
System Monitor through an AXI interface in the FPGA fabric. This IP core is
called the Xilinx System Management Wizard. This document describes the bindings
for this IP.
Required properties:
- compatible: Should be one of
@ -15,11 +24,14 @@ Required properties:
configuration interface to interface to the XADC hardmacro.
* "xlnx,axi-xadc-1.00.a": When using the axi-xadc pcore to
interface to the XADC hardmacro.
* "xlnx,system-management-wiz-1.3": When using the
Xilinx System Management Wizard fabric IP core to access the
UltraScale and UltraScale+ System Monitor.
- reg: Address and length of the register set for the device
- interrupts: Interrupt for the XADC control interface.
- clocks: When using the ZYNQ this must be the ZYNQ PCAP clock,
when using the AXI-XADC pcore this must be the clock that provides the
clock to the AXI bus interface of the core.
when using the axi-xadc or the axi-system-management-wizard this must be
the clock that provides the clock to the AXI bus interface of the core.
Optional properties:
- xlnx,external-mux:
@ -110,3 +122,20 @@ Examples:
};
};
};
adc@80000000 {
compatible = "xlnx,system-management-wiz-1.3";
reg = <0x80000000 0x1000>;
interrupts = <0 81 4>;
interrupt-parent = <&gic>;
clocks = <&fpga1_clk>;
xlnx,channels {
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
xlnx,bipolar;
};
};
};

View File

@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2020 Analog Devices Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/dac/adi,ad5766.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD5766 DAC device driver
maintainers:
- Cristian Pop <cristian.pop@analog.com>
description: |
Bindings for the Analog Devices AD5766 current DAC device. Datasheet can be
found here:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad5766-5767.pdf
properties:
compatible:
enum:
- adi,ad5766
- adi,ad5767
output-range-microvolts:
description: Select converter output range.
reg:
maxItems: 1
spi-max-frequency:
maximum: 1000000
spi-cpol: true
reset-gpios:
description: GPIO spec for the RESET pin. As the line is active low, it
should be marked GPIO_ACTIVE_LOW.
maxItems: 1
required:
- compatible
- output-range-microvolts
- reg
- spi-max-frequency
- spi-cpol
additionalProperties: false
examples:
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
ad5766@0 {
compatible = "adi,ad5766";
output-range-microvolts = <(-5000) 5000>;
reg = <0>;
spi-cpol;
spi-max-frequency = <1000000>;
reset-gpios = <&gpio 22 0>;
};
};

View File

@ -39,20 +39,39 @@ properties:
allOf:
- if:
not:
properties:
compatible:
contains:
const: microchip,mcp4726
properties:
compatible:
contains:
const: microchip,mcp4725
then:
properties:
vref-supply: false
required:
- vdd-supply
- if:
properties:
compatible:
contains:
const: microchip,mcp4726
then:
anyOf:
- required:
- vdd-supply
- required:
- vref-supply
- if:
not:
required:
- vref-supply
then:
properties:
microchip,vref-buffered: false
required:
- compatible
- reg
- vdd-supply
additionalProperties: false

View File

@ -19,6 +19,9 @@ properties:
reg:
maxItems: 1
vdd-supply: true
vddio-supply: true
interrupts:
minItems: 1
description:

View File

@ -1,45 +0,0 @@
Invensense MPU-3050 Gyroscope device tree bindings
Required properties:
- compatible : should be "invensense,mpu3050"
- reg : the I2C address of the sensor
Optional properties:
- interrupts : interrupt mapping for the trigger interrupt from the
internal oscillator. The following IRQ modes are supported:
IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_HIGH and
IRQ_TYPE_LEVEL_LOW. The driver should detect and configure the hardware
for the desired interrupt type.
- vdd-supply : supply regulator for the main power voltage.
- vlogic-supply : supply regulator for the signal voltage.
- mount-matrix : see iio/mount-matrix.txt
Optional subnodes:
- The MPU-3050 will pass through and forward the I2C signals from the
incoming I2C bus, alternatively drive traffic to a slave device (usually
an accelerometer) on its own initiative. Therefore is supports a subnode
i2c gate node. For details see: i2c/i2c-gate.txt
Example:
mpu3050@68 {
compatible = "invensense,mpu3050";
reg = <0x68>;
interrupt-parent = <&foo>;
interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
vdd-supply = <&bar>;
vlogic-supply = <&baz>;
/* External I2C interface */
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
fnord@18 {
compatible = "fnord";
reg = <0x18>;
interrupt-parent = <&foo>;
interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
};
};
};

View File

@ -0,0 +1,70 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/gyroscope/invensense,mpu3050.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Invensense MPU-3050 Gyroscope
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
properties:
compatible:
const: invensense,mpu3050
reg:
maxItems: 1
vdd-supply: true
vlogic-supply: true
interrupts:
minItems: 1
description:
Interrupt mapping for the trigger interrupt from the internal oscillator.
mount-matrix: true
i2c-gate:
$ref: /schemas/i2c/i2c-controller.yaml
unevaluatedProperties: false
description: |
The MPU-3050 will pass through and forward the I2C signals from the
incoming I2C bus, alternatively drive traffic to a slave device (usually
an accelerometer) on its own initiative. Therefore is supports an
i2c-gate subnode.
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
gyroscope@68 {
compatible = "invensense,mpu3050";
reg = <0x68>;
interrupt-parent = <&foo>;
interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
vdd-supply = <&bar>;
vlogic-supply = <&baz>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
magnetometer@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};
};
...

View File

@ -1,67 +0,0 @@
InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device
http://www.invensense.com/mems/gyro/mpu6050.html
Required properties:
- compatible : should be one of
"invensense,mpu6000"
"invensense,mpu6050"
"invensense,mpu6500"
"invensense,mpu6515"
"invensense,mpu9150"
"invensense,mpu9250"
"invensense,mpu9255"
"invensense,icm20608"
"invensense,icm20609"
"invensense,icm20689"
"invensense,icm20602"
"invensense,icm20690"
"invensense,iam20680"
- reg : the I2C address of the sensor
- interrupts: interrupt mapping for IRQ. It should be configured with flags
IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_LOW or
IRQ_TYPE_EDGE_FALLING.
Refer to interrupt-controller/interrupts.txt for generic interrupt client node
bindings.
Optional properties:
- vdd-supply: regulator phandle for VDD supply
- vddio-supply: regulator phandle for VDDIO supply
- mount-matrix: an optional 3x3 mounting rotation matrix
- i2c-gate node. These devices also support an auxiliary i2c bus. This is
simple enough to be described using the i2c-gate binding. See
i2c/i2c-gate.txt for more details.
Example:
mpu6050@68 {
compatible = "invensense,mpu6050";
reg = <0x68>;
interrupt-parent = <&gpio1>;
interrupts = <18 IRQ_TYPE_EDGE_RISING>;
mount-matrix = "-0.984807753012208", /* x0 */
"0", /* y0 */
"-0.173648177666930", /* z0 */
"0", /* x1 */
"-1", /* y1 */
"0", /* z1 */
"-0.173648177666930", /* x2 */
"0", /* y2 */
"0.984807753012208"; /* z2 */
};
mpu9250@68 {
compatible = "invensense,mpu9250";
reg = <0x68>;
interrupt-parent = <&gpio3>;
interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
ax8975@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};

View File

@ -0,0 +1,104 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/imu/invensense,mpu6050.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device
maintainers:
- Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
description: |
These devices support both I2C and SPI bus interfaces.
properties:
compatible:
enum:
- invensense,iam20680
- invensense,icm20608
- invensense,icm20609
- invensense,icm20689
- invensense,icm20602
- invensense,icm20690
- invensense,mpu6000
- invensense,mpu6050
- invensense,mpu6500
- invensense,mpu6515
- invensense,mpu6880
- invensense,mpu9150
- invensense,mpu9250
- invensense,mpu9255
reg:
maxItems: 1
interrupts:
maxItems: 1
spi-max-frequency: true
vdd-supply: true
vddio-supply: true
mount-matrix: true
i2c-gate:
$ref: /schemas/i2c/i2c-controller.yaml
unevaluatedProperties: false
description: |
These devices also support an auxiliary i2c bus via an i2c-gate.
allOf:
- if:
not:
properties:
compatible:
contains:
enum:
- invensense,mpu9150
- invensense,mpu9250
- invensense,mpu9255
then:
properties:
i2c-gate: false
additionalProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
imu@68 {
compatible = "invensense,mpu9250";
reg = <0x68>;
interrupt-parent = <&gpio3>;
interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;
mount-matrix = "-0.984807753012208", /* x0 */
"0", /* y0 */
"-0.173648177666930", /* z0 */
"0", /* x1 */
"-1", /* y1 */
"0", /* z1 */
"-0.173648177666930", /* x2 */
"0", /* y2 */
"0.984807753012208"; /* z2 */
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
magnetometer@c {
compatible = "ak,ak8975";
reg = <0x0c>;
};
};
};
};
...

View File

@ -30,6 +30,9 @@ properties:
reg:
maxItems: 1
vdd-supply: true
vddio-supply: true
interrupts:
maxItems: 1

View File

@ -0,0 +1,112 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/magnetometer/yamaha,yas530.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Yamaha YAS530 family of magnetometer sensors
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
description:
The Yamaha YAS530 magnetometers is a line of 3-axis magnetometers
first introduced by Yamaha in 2009 with the YAS530. They are successors
of Yamaha's first magnetometer YAS529. Over the years this magnetometer
has been miniaturized and appeared in a number of different variants.
properties:
$nodename:
pattern: '^magnetometer@[0-9a-f]+$'
compatible:
items:
- enum:
- yamaha,yas530
- yamaha,yas532
- yamaha,yas533
- yamaha,yas535
- yamaha,yas536
- yamaha,yas537
- yamaha,yas539
reg:
maxItems: 1
reset-gpios:
maxItems: 1
description: The YAS530 sensor has a RSTN pin used to reset
the logic inside the sensor. This GPIO line should connect
to that pin and be marked as GPIO_ACTIVE_LOW.
interrupts:
maxItems: 1
description: Interrupt for INT pin for interrupt generation.
The polarity, whether the interrupt is active on the rising
or the falling edge, is software-configurable in the hardware.
vdd-supply:
description: An optional regulator providing core power supply
on the VDD pin, typically 1.8 V or 3.0 V.
iovdd-supply:
description: An optional regulator providing I/O power supply
for the I2C interface on the IOVDD pin, typically 1.8 V.
mount-matrix:
description: An optional 3x3 mounting rotation matrix.
allOf:
- if:
not:
properties:
compatible:
items:
const: yamaha,yas530
then:
properties:
reset-gpios: false
- if:
properties:
compatible:
items:
const: yamaha,yas539
then:
properties:
interrupts: false
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
i2c-0 {
#address-cells = <1>;
#size-cells = <0>;
magnetometer@2e {
compatible = "yamaha,yas530";
reg = <0x2e>;
vdd-supply = <&ldo1_reg>;
iovdd-supply = <&ldo2_reg>;
reset-gpios = <&gpio6 12 GPIO_ACTIVE_LOW>;
interrupts = <&gpio6 13 IRQ_TYPE_EDGE_RISING>;
};
};
i2c-1 {
#address-cells = <1>;
#size-cells = <0>;
magnetometer@2e {
compatible = "yamaha,yas539";
reg = <0x2e>;
vdd-supply = <&ldo1_reg>;
};
};

View File

@ -4,7 +4,7 @@ Generic Bluetooth controller over USB (btusb driver)
Required properties:
- compatible : should comply with the format "usbVID,PID" specified in
Documentation/devicetree/bindings/usb/usb-device.txt
Documentation/devicetree/bindings/usb/usb-device.yaml
At the time of writing, the only OF supported devices
(more may be added later) are:

View File

@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)
maintainers:
- Fabio Estevam <fabio.estevam@nxp.com>
- Fabio Estevam <festevam@gmail.com>
allOf:
- $ref: "serial.yaml"

View File

@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale MXS Application UART (AUART)
maintainers:
- Fabio Estevam <fabio.estevam@nxp.com>
- Fabio Estevam <festevam@gmail.com>
allOf:
- $ref: "serial.yaml"

View File

@ -51,6 +51,7 @@ properties:
- renesas,hscif-r8a77980 # R-Car V3H
- renesas,hscif-r8a77990 # R-Car E3
- renesas,hscif-r8a77995 # R-Car D3
- renesas,hscif-r8a779a0 # R-Car V3U
- const: renesas,rcar-gen3-hscif # R-Car Gen3 and RZ/G2
- const: renesas,hscif # generic HSCIF compatible UART

View File

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

View File

@ -50,11 +50,14 @@ properties:
minItems: 1
maxItems: 2
cts-gpios:
maxItems: 1
rts-gpios:
maxItems: 1
# cts-gpios and rts-gpios properties can be used instead of 'uart-has-rtscts'
# or 'st,hw-flow-ctrl' (deprecated) for making use of any gpio pins for flow
# control instead of dedicated pins.
#
# It should be noted that both cts-gpios/rts-gpios and 'uart-has-rtscts' or
# 'st,hw-flow-ctrl' (deprecated) properties cannot co-exist in a design.
cts-gpios: true
rts-gpios: true
wakeup-source: true

View File

@ -148,15 +148,13 @@ properties:
- maxim,max31730
# mCube 3-axis 8-bit digital accelerometer
- mcube,mc3230
# MEMSIC magnetometer
- memsic,mmc35240
# MEMSIC 2-axis 8-bit digital accelerometer
- memsic,mxc6225
# Measurement Specialities I2C temperature and humidity sensor
- meas,htu21
# Measurement Specialities I2C pressure and temperature sensor
- meas,ms5637
# Measurement Specialities I2C pressure and temperature sensor
- meas,ms5803
# Measurement Specialities I2C pressure and temperature sensor
- meas,ms5805
# Measurement Specialities I2C pressure and temperature sensor
- meas,ms5837
@ -166,6 +164,10 @@ properties:
- meas,ms8607-temppressure
# Measurement Specialties temperature sensor
- meas,tsys01
# MEMSIC magnetometer
- memsic,mmc35240
# MEMSIC 2-axis 8-bit digital accelerometer
- memsic,mxc6225
# Microchip differential I2C ADC, 1 Channel, 18 bit
- microchip,mcp3421
# Microchip differential I2C ADC, 2 Channel, 18 bit

View File

@ -79,7 +79,9 @@ properties:
patternProperties:
"^usb@[0-9a-f]+$":
type: object
oneOf:
- $ref: dwc2.yaml#
- $ref: snps,dwc3.yaml#
additionalProperties: false
@ -229,6 +231,6 @@ examples:
interrupts = <30>;
dr_mode = "host";
snps,dis_u2_susphy_quirk;
snps,quirk-frame-length-adjustment;
snps,quirk-frame-length-adjustment = <0x20>;
};
};

View File

@ -31,13 +31,13 @@ See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Sub-nodes:
The dwc3 core should be added as subnode to ST DWC3 glue as shown in the
example below. The DT binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt
Documentation/devicetree/bindings/usb/snps,dwc3.yaml
NB: The dr_mode property described in [1] is NOT optional for this driver, as the default value
is "otg", which isn't supported by this SoC. Valid dr_mode values for dwc3-st are either "host"
or "device".
[1] Documentation/devicetree/bindings/usb/generic.txt
[1] Documentation/devicetree/bindings/usb/usb-drd.yaml
Example:

View File

@ -19,7 +19,7 @@ Example device node:
#address-cells = <0x2>;
#size-cells = <0x1>;
compatible = "xlnx,zynqmp-dwc3";
clock-names = "bus_clk" "ref_clk";
clock-names = "bus_clk", "ref_clk";
clocks = <&clk125>, <&clk125>;
ranges;

View File

@ -1,128 +0,0 @@
synopsys DWC3 CORE
DWC3- USB3 CONTROLLER. Complies to the generic USB binding properties
as described in 'usb/generic.txt'
Required properties:
- compatible: must be "snps,dwc3"
- reg : Address and length of the register set for the device
- interrupts: Interrupts used by the dwc3 controller.
- clock-names: list of clock names. Ideally should be "ref",
"bus_early", "suspend" but may be less or more.
- clocks: list of phandle and clock specifier pairs corresponding to
entries in the clock-names property.
Exception for clocks:
clocks are optional if the parent node (i.e. glue-layer) is compatible to
one of the following:
"cavium,octeon-7130-usb-uctl"
"qcom,dwc3"
"samsung,exynos5250-dwusb3"
"samsung,exynos5433-dwusb3"
"samsung,exynos7-dwusb3"
"sprd,sc9860-dwc3"
"st,stih407-dwc3"
"ti,am437x-dwc3"
"ti,dwc3"
"ti,keystone-dwc3"
"rockchip,rk3399-dwc3"
"xlnx,zynqmp-dwc3"
Optional properties:
- usb-phy : array of phandle for the PHY device. The first element
in the array is expected to be a handle to the USB2/HS PHY and
the second element is expected to be a handle to the USB3/SS PHY
- phys: from the *Generic PHY* bindings
- phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy"
or "usb3-phy".
- resets: set of phandle and reset specifier pairs
- snps,usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM
- snps,usb3_lpm_capable: determines if platform is USB3 LPM capable
- snps,dis-start-transfer-quirk: when set, disable isoc START TRANSFER command
failure SW work-around for DWC_usb31 version 1.70a-ea06
and prior.
- snps,disable_scramble_quirk: true when SW should disable data scrambling.
Only really useful for FPGA builds.
- snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled
- snps,lpm-nyet-threshold: LPM NYET threshold
- snps,u2exit_lfps_quirk: set if we want to enable u2exit lfps quirk
- snps,u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk
- snps,req_p1p2p3_quirk: when set, the core will always request for
P1/P2/P3 transition sequence.
- snps,del_p1p2p3_quirk: when set core will delay P1/P2/P3 until a certain
amount of 8B10B errors occur.
- snps,del_phy_power_chg_quirk: when set core will delay PHY power change
from P0 to P1/P2/P3.
- snps,lfps_filter_quirk: when set core will filter LFPS reception.
- snps,rx_detect_poll_quirk: when set core will disable a 400us delay to start
Polling LFPS after RX.Detect.
- snps,tx_de_emphasis_quirk: when set core will set Tx de-emphasis value.
- snps,tx_de_emphasis: the value driven to the PHY is controlled by the
LTSSM during USB3 Compliance mode.
- snps,dis_u3_susphy_quirk: when set core will disable USB3 suspend phy.
- snps,dis_u2_susphy_quirk: when set core will disable USB2 suspend phy.
- snps,dis_enblslpm_quirk: when set clears the enblslpm in GUSB2PHYCFG,
disabling the suspend signal to the PHY.
- snps,dis-u1-entry-quirk: set if link entering into U1 needs to be disabled.
- snps,dis-u2-entry-quirk: set if link entering into U2 needs to be disabled.
- snps,dis_rxdet_inp3_quirk: when set core will disable receiver detection
in PHY P3 power state.
- snps,dis-u2-freeclk-exists-quirk: when set, clear the u2_freeclk_exists
in GUSB2PHYCFG, specify that USB2 PHY doesn't provide
a free-running PHY clock.
- snps,dis-del-phy-power-chg-quirk: when set core will change PHY power
from P0 to P1/P2/P3 without delay.
- snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
during HS transmit.
- snps,parkmode-disable-ss-quirk: when set, all SuperSpeed bus instances in
park mode are disabled.
- snps,dis_metastability_quirk: when set, disable metastability workaround.
CAUTION: use only if you are absolutely sure of it.
- snps,dis-split-quirk: when set, change the way URBs are handled by the
driver. Needed to avoid -EPROTO errors with usbhid
on some devices (Hikey 970).
- snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
utmi_l1_suspend_n, false when asserts utmi_sleep_n
- snps,hird-threshold: HIRD threshold
- snps,hsphy_interface: High-Speed PHY interface selection between "utmi" for
UTMI+ and "ulpi" for ULPI when the DWC_USB3_HSPHY_INTERFACE has value 3.
- snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ
register for post-silicon frame length adjustment when the
fladj_30mhz_sdbnd signal is invalid or incorrect.
- snps,rx-thr-num-pkt-prd: periodic ESS RX packet threshold count - host mode
only. Set this and rx-max-burst-prd to a valid,
non-zero value 1-16 (DWC_usb31 programming guide
section 1.2.4) to enable periodic ESS RX threshold.
- snps,rx-max-burst-prd: max periodic ESS RX burst size - host mode only. Set
this and rx-thr-num-pkt-prd to a valid, non-zero value
1-16 (DWC_usb31 programming guide section 1.2.4) to
enable periodic ESS RX threshold.
- snps,tx-thr-num-pkt-prd: periodic ESS TX packet threshold count - host mode
only. Set this and tx-max-burst-prd to a valid,
non-zero value 1-16 (DWC_usb31 programming guide
section 1.2.3) to enable periodic ESS TX threshold.
- snps,tx-max-burst-prd: max periodic ESS TX burst size - host mode only. Set
this and tx-thr-num-pkt-prd to a valid, non-zero value
1-16 (DWC_usb31 programming guide section 1.2.3) to
enable periodic ESS TX threshold.
- <DEPRECATED> tx-fifo-resize: determines if the FIFO *has* to be reallocated.
- snps,incr-burst-type-adjustment: Value for INCR burst type of GSBUSCFG0
register, undefined length INCR burst type enable and INCRx type.
When just one value, which means INCRX burst mode enabled. When
more than one value, which means undefined length INCR burst type
enabled. The values can be 1, 4, 8, 16, 32, 64, 128 and 256.
- in addition all properties from usb-xhci.txt from the current directory are
supported as well
This is usually a subnode to DWC3 glue to which it is connected.
dwc3@4a030000 {
compatible = "snps,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>
usb-phy = <&usb2_phy>, <&usb3,phy>;
snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
};

View File

@ -93,7 +93,7 @@ Sub-nodes:
The dwc3 core should be added as subnode to Exynos dwc3 glue.
- dwc3 :
The binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt
Documentation/devicetree/bindings/usb/snps,dwc3.yaml
Example:
usb@12000000 {

View File

@ -0,0 +1,105 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 NXP
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/fsl,imx8mp-dwc3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP iMX8MP Soc USB Controller
maintainers:
- Li Jun <jun.li@nxp.com>
properties:
compatible:
const: fsl,imx8mp-dwc3
reg:
maxItems: 1
description: Address and length of the register set for the wrapper of
dwc3 core on the SOC.
"#address-cells":
enum: [ 1, 2 ]
"#size-cells":
enum: [ 1, 2 ]
dma-ranges:
description:
See section 2.3.9 of the DeviceTree Specification.
ranges: true
interrupts:
maxItems: 1
description: The interrupt that is asserted when a wakeup event is
received.
clocks:
description:
A list of phandle and clock-specifier pairs for the clocks
listed in clock-names.
items:
- description: system hsio root clock.
- description: suspend clock, used for usb wakeup logic.
clock-names:
items:
- const: hsio
- const: suspend
# Required child node:
patternProperties:
"^dwc3@[0-9a-f]+$":
type: object
description:
A child node must exist to represent the core DWC3 IP block
The content of the node is defined in dwc3.txt.
required:
- compatible
- reg
- "#address-cells"
- "#size-cells"
- dma-ranges
- ranges
- clocks
- clock-names
- interrupts
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/imx8mp-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
usb3_0: usb@32f10100 {
compatible = "fsl,imx8mp-dwc3";
reg = <0x32f10100 0x8>;
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "hsio", "suspend";
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x40000000 0x40000000 0xc0000000>;
ranges;
dwc3@38100000 {
compatible = "snps,dwc3";
reg = <0x38100000 0x10000>;
clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
<&clk IMX8MP_CLK_USB_CORE_REF>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>;
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>;
assigned-clock-rates = <500000000>;
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb3_phy0>, <&usb3_phy0>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis-u2-freeclk-exists-quirk;
};
};

View File

@ -24,8 +24,53 @@ allOf:
properties:
compatible:
contains:
const: generic-ehci
oneOf:
- items:
- enum:
- allwinner,sun4i-a10-ehci
- allwinner,sun50i-a64-ehci
- allwinner,sun50i-h6-ehci
- allwinner,sun5i-a13-ehci
- allwinner,sun6i-a31-ehci
- allwinner,sun7i-a20-ehci
- allwinner,sun8i-a23-ehci
- allwinner,sun8i-h3-ehci
- allwinner,sun8i-r40-ehci
- allwinner,sun9i-a80-ehci
- aspeed,ast2400-ehci
- aspeed,ast2500-ehci
- aspeed,ast2600-ehci
- brcm,bcm3384-ehci
- brcm,bcm63268-ehci
- brcm,bcm6328-ehci
- brcm,bcm6358-ehci
- brcm,bcm6362-ehci
- brcm,bcm6368-ehci
- brcm,bcm7125-ehci
- brcm,bcm7346-ehci
- brcm,bcm7358-ehci
- brcm,bcm7360-ehci
- brcm,bcm7362-ehci
- brcm,bcm7420-ehci
- brcm,bcm7425-ehci
- brcm,bcm7435-ehci
- ibm,476gtr-ehci
- nxp,lpc1850-ehci
- qca,ar7100-ehci
- snps,hsdk-v1.0-ehci
- socionext,uniphier-ehci
- const: generic-ehci
- items:
- enum:
- cavium,octeon-6335-ehci
- ibm,usb-ehci-440epx
- ibm,usb-ehci-460ex
- nintendo,hollywood-usb-ehci
- st,spear600-ehci
- const: usb-ehci
- enum:
- generic-ehci
- usb-ehci
reg:
minItems: 1
@ -101,7 +146,7 @@ additionalProperties: false
examples:
- |
usb@e0000300 {
compatible = "ibm,usb-ehci-440epx", "generic-ehci";
compatible = "ibm,usb-ehci-440epx", "usb-ehci";
interrupt-parent = <&UIC0>;
interrupts = <0x1a 4>;
reg = <0xe0000300 90>, <0xe0000390 70>;

View File

@ -14,8 +14,38 @@ maintainers:
properties:
compatible:
contains:
const: generic-ohci
oneOf:
- items:
- enum:
- allwinner,sun4i-a10-ohci
- allwinner,sun50i-a64-ohci
- allwinner,sun50i-h6-ohci
- allwinner,sun5i-a13-ohci
- allwinner,sun6i-a31-ohci
- allwinner,sun7i-a20-ohci
- allwinner,sun8i-a23-ohci
- allwinner,sun8i-h3-ohci
- allwinner,sun8i-r40-ohci
- allwinner,sun9i-a80-ohci
- brcm,bcm3384-ohci
- brcm,bcm63268-ohci
- brcm,bcm6328-ohci
- brcm,bcm6358-ohci
- brcm,bcm6362-ohci
- brcm,bcm6368-ohci
- brcm,bcm7125-ohci
- brcm,bcm7346-ohci
- brcm,bcm7358-ohci
- brcm,bcm7360-ohci
- brcm,bcm7362-ohci
- brcm,bcm7420-ohci
- brcm,bcm7425-ohci
- brcm,bcm7435-ohci
- ibm,476gtr-ohci
- ingenic,jz4740-ohci
- snps,hsdk-v1.0-ohci
- const: generic-ohci
- const: generic-ohci
reg:
maxItems: 1

View File

@ -0,0 +1,65 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/generic-xhci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: USB xHCI Controller Device Tree Bindings
maintainers:
- Mathias Nyman <mathias.nyman@intel.com>
allOf:
- $ref: "usb-xhci.yaml#"
properties:
compatible:
oneOf:
- description: Generic xHCI device
const: generic-xhci
- description: Armada 37xx/375/38x/8k SoCs
items:
- enum:
- marvell,armada3700-xhci
- marvell,armada-375-xhci
- marvell,armada-380-xhci
- marvell,armada-8k-xhci
- const: generic-xhci
- description: Broadcom STB SoCs with xHCI
enum:
- brcm,xhci-brcm-v2
- brcm,bcm7445-xhci
- description: Generic xHCI device
const: xhci-platform
deprecated: true
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
minItems: 1
items:
- const: core
- const: reg
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
usb@f0931000 {
compatible = "generic-xhci";
reg = <0xf0931000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
};

View File

@ -1,57 +0,0 @@
Generic USB Properties
Optional properties:
- maximum-speed: tells USB controllers we want to work up to a certain
speed. Valid arguments are "super-speed-plus",
"super-speed", "high-speed", "full-speed" and
"low-speed". In case this isn't passed via DT, USB
controllers should default to their maximum HW
capability.
- dr_mode: tells Dual-Role USB controllers that we want to work on a
particular mode. Valid arguments are "host",
"peripheral" and "otg". In case this attribute isn't
passed via DT, USB DRD controllers should default to
OTG.
- phy_type: tells USB controllers that we want to configure the core to support
a UTMI+ PHY with an 8- or 16-bit interface if UTMI+ is
selected. Valid arguments are "utmi" and "utmi_wide".
In case this isn't passed via DT, USB controllers should
default to HW capability.
- otg-rev: tells usb driver the release number of the OTG and EH supplement
with which the device and its descriptors are compliant,
in binary-coded decimal (i.e. 2.0 is 0200H). This
property is used if any real OTG features(HNP/SRP/ADP)
is enabled, if ADP is required, otg-rev should be
0x0200 or above.
- companion: phandle of a companion
- hnp-disable: tells OTG controllers we want to disable OTG HNP, normally HNP
is the basic function of real OTG except you want it
to be a srp-capable only B device.
- srp-disable: tells OTG controllers we want to disable OTG SRP, SRP is
optional for OTG device.
- adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
optional for OTG device.
- usb-role-switch: boolean, indicates that the device is capable of assigning
the USB data role (USB host or USB device) for a given
USB connector, such as Type-C, Type-B(micro).
see connector/usb-connector.yaml.
- role-switch-default-mode: indicating if usb-role-switch is enabled, the
device default operation mode of controller while usb
role is USB_ROLE_NONE. Valid arguments are "host" and
"peripheral". Defaults to "peripheral" if not
specified.
This is an attribute to a USB controller such as:
dwc3@4a030000 {
compatible = "synopsys,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>
usb-phy = <&usb2_phy>, <&usb3,phy>;
maximum-speed = "super-speed";
dr_mode = "otg";
phy_type = "utmi_wide";
otg-rev = <0x0200>;
adp-disable;
};

View File

@ -34,11 +34,8 @@ properties:
# Required child node:
patternProperties:
"^dwc3@[0-9a-f]+$":
type: object
description:
A child node must exist to represent the core DWC3 IP block.
The content of the node is defined in dwc3.txt.
"^usb@[0-9a-f]+$":
$ref: snps,dwc3.yaml#
required:
- compatible
@ -68,7 +65,7 @@ examples:
#address-cells = <1>;
#size-cells = <1>;
dwc3@34000000 {
usb@34000000 {
compatible = "snps,dwc3";
reg = <0x34000000 0x10000>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;

View File

@ -1,121 +0,0 @@
MT8173 xHCI
The device node for Mediatek SOC USB3.0 host controller
There are two scenarios: the first one only supports xHCI driver;
the second one supports dual-role mode, and the host is based on xHCI
driver. Take account of backward compatibility, we divide bindings
into two parts.
1st: only supports xHCI driver
------------------------------------------------------------------------
Required properties:
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
addition, one of:
- "mediatek,mt8173-xhci"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control
- interrupts : interrupt used by the controller
- power-domains : a phandle to USB power domain node to control USB's
mtcmos
- vusb33-supply : regulator of USB avdd3.3v
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain
"sys_ck": controller clock used by normal mode,
the following ones are optional:
"ref_ck": reference clock used by low power mode etc,
"mcu_ck": mcu_bus clock for register access,
"dma_ck": dma_bus clock for data transfer by DMA,
"xhci_ck": controller clock
- phys : see usb-hcd.yaml in the current directory
Optional properties:
- wakeup-source : enable USB remote wakeup;
- mediatek,syscon-wakeup : phandle to syscon used to access the register
of the USB wakeup glue layer between xHCI and SPM; it depends on
"wakeup-source", and has two arguments:
- the first one : register base address of the glue layer in syscon;
- the second one : hardware version of the glue layer
- 1 : used by mt8173 etc
- 2 : used by mt2712 etc
- mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
- vbus-supply : reference to the VBUS regulator;
- usb3-lpm-capable : supports USB3.0 LPM
- pinctrl-names : a pinctrl state named "default" must be defined
- pinctrl-0 : pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- imod-interval-ns: default interrupt moderation interval is 5000ns
additionally the properties from usb-hcd.yaml (in the current directory) are
supported.
Example:
usb30: usb@11270000 {
compatible = "mediatek,mt8173-xhci";
reg = <0 0x11270000 0 0x1000>,
<0 0x11280700 0 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
<&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB1>;
clock-names = "sys_ck", "ref_ck";
phys = <&phy_port0 PHY_TYPE_USB3>,
<&phy_port1 PHY_TYPE_USB2>;
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p1_vbus>;
usb3-lpm-capable;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
wakeup-source;
imod-interval-ns = <10000>;
};
2nd: dual-role mode with xHCI driver
------------------------------------------------------------------------
In the case, xhci is added as subnode to mtu3. An example and the DT binding
details of mtu3 can be found in:
Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
Required properties:
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
addition, one of:
- "mediatek,mt8173-xhci"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for xHCI MAC
- interrupts : interrupt used by the host controller
- power-domains : a phandle to USB power domain node to control USB's
mtcmos
- vusb33-supply : regulator of USB avdd3.3v
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain "sys_ck", and the following ones are optional:
"ref_ck", "mcu_ck" and "dma_ck", "xhci_ck"
Optional properties:
- vbus-supply : reference to the VBUS regulator;
- usb3-lpm-capable : supports USB3.0 LPM
Example:
usb30: usb@11270000 {
compatible = "mediatek,mt8173-xhci";
reg = <0 0x11270000 0 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
usb3-lpm-capable;
};

View File

@ -0,0 +1,188 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/mediatek,mtk-xhci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek USB3 xHCI Device Tree Bindings
maintainers:
- Chunfeng Yun <chunfeng.yun@mediatek.com>
allOf:
- $ref: "usb-xhci.yaml"
description: |
There are two scenarios:
case 1: only supports xHCI driver;
case 2: supports dual-role mode, and the host is based on xHCI driver.
properties:
# common properties for both case 1 and case 2
compatible:
items:
- enum:
- mediatek,mt2701-xhci
- mediatek,mt2712-xhci
- mediatek,mt7622-xhci
- mediatek,mt7623-xhci
- mediatek,mt7629-xhci
- mediatek,mt8173-xhci
- mediatek,mt8183-xhci
- const: mediatek,mtk-xhci
reg:
minItems: 1
items:
- description: the registers of xHCI MAC
- description: the registers of IP Port Control
reg-names:
minItems: 1
items:
- const: mac
- const: ippc # optional, only needed for case 1.
interrupts:
maxItems: 1
power-domains:
description: A phandle to USB power domain node to control USB's MTCMOS
maxItems: 1
clocks:
minItems: 1
items:
- description: Controller clock used by normal mode
- description: Reference clock used by low power mode etc
- description: Mcu bus clock for register access
- description: DMA bus clock for data transfer
- description: controller clock
clock-names:
minItems: 1
items:
- const: sys_ck # required, the following ones are optional
- const: ref_ck
- const: mcu_ck
- const: dma_ck
- const: xhci_ck
assigned-clocks:
minItems: 1
maxItems: 5
assigned-clock-parents:
minItems: 1
maxItems: 5
phys:
description:
List of all PHYs used on this HCD, it's better to keep PHYs in order
as the hardware layout
minItems: 1
items:
- description: USB2/HS PHY # required, others are optional
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
vusb33-supply:
description: Regulator of USB AVDD3.3v
vbus-supply:
description: Regulator of USB VBUS5v
usb3-lpm-capable:
description: supports USB3.0 LPM
type: boolean
imod-interval-ns:
description:
Interrupt moderation interval value, it is 8 times as much as that
defined in the xHCI spec on MTK's controller.
default: 5000
# the following properties are only used for case 1
wakeup-source:
description: enable USB remote wakeup, see power/wakeup-source.txt
type: boolean
mediatek,syscon-wakeup:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
description:
A phandle to syscon used to access the register of the USB wakeup glue
layer between xHCI and SPM, the field should always be 3 cells long.
items:
items:
- description:
The first cell represents a phandle to syscon
- description:
The second cell represents the register base address of the glue
layer in syscon
- description:
The third cell represents the hardware version of the glue layer,
1 is used by mt8173 etc, 2 is used by mt2712 etc
enum: [1, 2]
mediatek,u3p-dis-msk:
$ref: /schemas/types.yaml#/definitions/uint32
description: The mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"@[0-9a-f]{1}$":
type: object
description: The hard wired USB devices.
dependencies:
wakeup-source: [ 'mediatek,syscon-wakeup' ]
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/power/mt8173-power.h>
usb@11270000 {
compatible = "mediatek,mt8173-xhci", "mediatek,mtk-xhci";
reg = <0x11270000 0x1000>, <0x11280700 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
phys = <&u3port0 PHY_TYPE_USB3>, <&u2port1 PHY_TYPE_USB2>;
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p1_vbus>;
imod-interval-ns = <10000>;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
wakeup-source;
usb3-lpm-capable;
};
...

View File

@ -1,108 +0,0 @@
The device node for Mediatek USB3.0 DRD controller
Required properties:
- compatible : should be "mediatek,<soc-model>-mtu3", "mediatek,mtu3",
soc-model is the name of SoC, such as mt8173, mt2712 etc,
when using "mediatek,mtu3" compatible string, you need SoC specific
ones in addition, one of:
- "mediatek,mt8173-mtu3"
- reg : specifies physical base address and size of the registers
- reg-names: should be "mac" for device IP and "ippc" for IP port control
- interrupts : interrupt used by the device IP
- power-domains : a phandle to USB power domain node to control USB's
mtcmos
- vusb33-supply : regulator of USB avdd3.3v
- clocks : a list of phandle + clock-specifier pairs, one for each
entry in clock-names
- clock-names : must contain "sys_ck" for clock of controller,
the following clocks are optional:
"ref_ck", "mcu_ck" and "dma_ck";
- phys : see usb-hcd.yaml in the current directory
- dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
Optional properties:
- #address-cells, #size-cells : should be '2' if the device has sub-nodes
with 'reg' property
- ranges : allows valid 1:1 translation between child's address space and
parent's address space
- extcon : external connector for vbus and idpin changes detection, needed
when supports dual-role mode.
it's considered valid for compatibility reasons, not allowed for
new bindings, and use "usb-role-switch" property instead.
- vbus-supply : reference to the VBUS regulator, needed when supports
dual-role mode.
it's considered valid for compatibility reasons, not allowed for
new bindings, and put into a usb-connector node.
see connector/usb-connector.yaml.
- pinctrl-names : a pinctrl state named "default" is optional, and need be
defined if auto drd switch is enabled, that means the property dr_mode
is set as "otg", and meanwhile the property "mediatek,enable-manual-drd"
is not set.
- pinctrl-0 : pin control group
See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- maximum-speed : valid arguments are "super-speed", "high-speed" and
"full-speed"; refer to usb/generic.txt
- usb-role-switch : use USB Role Switch to support dual-role switch, but
not extcon; see usb/generic.txt.
- enable-manual-drd : supports manual dual-role switch via debugfs; usually
used when receptacle is TYPE-A and also wants to support dual-role
mode.
- wakeup-source: enable USB remote wakeup of host mode.
- mediatek,syscon-wakeup : phandle to syscon used to access the register
of the USB wakeup glue layer between SSUSB and SPM; it depends on
"wakeup-source", and has two arguments:
- the first one : register base address of the glue layer in syscon;
- the second one : hardware version of the glue layer
- 1 : used by mt8173 etc
- 2 : used by mt2712 etc
- mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc;
additionally the properties from usb-hcd.yaml (in the current directory) are
supported.
Sub-nodes:
The xhci should be added as subnode to mtu3 as shown in the following example
if host mode is enabled. The DT binding details of xhci can be found in:
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
The port would be added as subnode if use "usb-role-switch" property.
see graph.txt
Example:
ssusb: usb@11271000 {
compatible = "mediatek,mt8173-mtu3";
reg = <0 0x11271000 0 0x3000>,
<0 0x11280700 0 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
phys = <&phy_port0 PHY_TYPE_USB3>,
<&phy_port1 PHY_TYPE_USB2>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
<&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB1>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p0_vbus>;
extcon = <&extcon_usb>;
dr_mode = "otg";
wakeup-source;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
usb_host: xhci@11270000 {
compatible = "mediatek,mt8173-xhci";
reg = <0 0x11270000 0 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
};
};

View File

@ -0,0 +1,287 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/mediatek,mtu3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek USB3 DRD Controller Device Tree Bindings
maintainers:
- Chunfeng Yun <chunfeng.yun@mediatek.com>
allOf:
- $ref: "usb-drd.yaml"
description: |
The DRD controller has a glue layer IPPC (IP Port Control), and its host is
based on xHCI.
properties:
compatible:
items:
- enum:
- mediatek,mt2712-mtu3
- mediatek,mt8173-mtu3
- mediatek,mt8183-mtu3
- const: mediatek,mtu3
reg:
items:
- description: the registers of device MAC
- description: the registers of IP Port Control
reg-names:
items:
- const: mac
- const: ippc
interrupts:
maxItems: 1
power-domains:
description: A phandle to USB power domain node to control USB's MTCMOS
maxItems: 1
clocks:
minItems: 1
items:
- description: Controller clock used by normal mode
- description: Reference clock used by low power mode etc
- description: Mcu bus clock for register access
- description: DMA bus clock for data transfer
clock-names:
minItems: 1
items:
- const: sys_ck # required, others are optional
- const: ref_ck
- const: mcu_ck
- const: dma_ck
phys:
description:
List of all the USB PHYs used, it's better to keep the sequence
as the hardware layout.
minItems: 1
items:
- description: USB2/HS PHY # required, others are optional
- description: USB3/SS(P) PHY
- description: USB2/HS PHY # the following for backward compatible
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
- description: USB3/SS(P) PHY
- description: USB2/HS PHY
vusb33-supply:
description: Regulator of USB AVDD3.3v
vbus-supply:
deprecated: true
description: |
Regulator of USB VBUS5v, needed when supports dual-role mode.
Particularly, if use an output GPIO to control a VBUS regulator, should
model it as a regulator. See bindings/regulator/fixed-regulator.yaml
It's considered valid for compatibility reasons, not allowed for
new bindings, and put into a usb-connector node.
dr_mode:
enum: [host, peripheral, otg]
default: otg
maximum-speed:
enum: [super-speed-plus, super-speed, high-speed, full-speed]
"#address-cells":
enum: [1, 2]
"#size-cells":
enum: [1, 2]
ranges: true
extcon:
deprecated: true
description: |
Phandle to the extcon device detecting the IDDIG/VBUS state, neede
when supports dual-role mode.
It's considered valid for compatibility reasons, not allowed for
new bindings, and use "usb-role-switch" property instead.
usb-role-switch:
$ref: /schemas/types.yaml#/definitions/flag
description: Support role switch.
type: boolean
connector:
$ref: /connector/usb-connector.yaml#
description:
Connector for dual role switch, especially for "gpio-usb-b-connector"
type: object
port:
description:
Any connector to the data bus of this controller should be modelled
using the OF graph bindings specified, if the "usb-role-switch"
property is used. See graph.txt
type: object
enable-manual-drd:
$ref: /schemas/types.yaml#/definitions/flag
description:
supports manual dual-role switch via debugfs; usually used when
receptacle is TYPE-A and also wants to support dual-role mode.
type: boolean
wakeup-source:
description: enable USB remote wakeup, see power/wakeup-source.txt
type: boolean
mediatek,syscon-wakeup:
$ref: /schemas/types.yaml#/definitions/phandle-array
maxItems: 1
description:
A phandle to syscon used to access the register of the USB wakeup glue
layer between xHCI and SPM, the field should always be 3 cells long.
items:
items:
- description:
The first cell represents a phandle to syscon
- description:
The second cell represents the register base address of the glue
layer in syscon
- description:
The third cell represents the hardware version of the glue layer,
1 is used by mt8173 etc, 2 is used by mt2712 etc
enum: [1, 2]
mediatek,u3p-dis-msk:
$ref: /schemas/types.yaml#/definitions/uint32
description: The mask to disable u3ports, bit0 for u3port0,
bit1 for u3port1, ... etc
# Required child node when support dual-role
patternProperties:
"^usb@[0-9a-f]+$":
type: object
$ref: /usb/mediatek,mtk-xhci.yaml#
description:
The xhci should be added as subnode to mtu3 as shown in the following
example if the host mode is enabled.
dependencies:
connector: [ 'usb-role-switch' ]
port: [ 'usb-role-switch' ]
wakeup-source: [ 'mediatek,syscon-wakeup' ]
required:
- compatible
- reg
- reg-names
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
# Dual role switch by extcon
- |
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/power/mt8173-power.h>
usb@11271000 {
compatible = "mediatek,mt8173-mtu3", "mediatek,mtu3";
reg = <0x11271000 0x3000>, <0x11280700 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
phys = <&phy_port0 PHY_TYPE_USB3>, <&phy_port1 PHY_TYPE_USB2>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
vusb33-supply = <&mt6397_vusb_reg>;
vbus-supply = <&usb_p0_vbus>;
extcon = <&extcon_usb>;
dr_mode = "otg";
wakeup-source;
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
xhci: usb@11270000 {
compatible = "mediatek,mt8173-xhci", "mediatek,mtk-xhci";
reg = <0x11270000 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>;
clock-names = "sys_ck", "ref_ck";
vusb33-supply = <&mt6397_vusb_reg>;
};
};
# Enable/disable device by an input gpio for VBUS pin
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power/mt2712-power.h>
usb@112c1000 {
compatible = "mediatek,mt2712-mtu3", "mediatek,mtu3";
reg = <0x112c1000 0x3000>, <0x112d0700 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_LOW>;
phys = <&u2port2 PHY_TYPE_USB2>;
power-domains = <&scpsys MT2712_POWER_DOMAIN_USB2>;
clocks = <&topckgen CLK_TOP_USB30_SEL>;
clock-names = "sys_ck";
dr_mode = "peripheral";
usb-role-switch;
connector {
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
vbus-gpios = <&pio 13 GPIO_ACTIVE_HIGH>;
};
};
# Dual role switch with type-c
- |
usb@11201000 {
compatible ="mediatek,mt8183-mtu3", "mediatek,mtu3";
reg = <0x11201000 0x2e00>, <0x11203e00 0x0100>;
reg-names = "mac", "ippc";
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>;
phys = <&u2port0 PHY_TYPE_USB2>;
clocks = <&clk26m>;
clock-names = "sys_ck";
mediatek,syscon-wakeup = <&pericfg 0x400 1>;
wakeup-source;
dr_mode = "otg";
usb-role-switch;
#address-cells = <1>;
#size-cells = <1>;
ranges;
host: usb@11200000 {
compatible = "mediatek,mt8183-xhci", "mediatek,mtk-xhci";
reg = <0x11200000 0x1000>;
reg-names = "mac";
interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_LOW>;
clocks = <&clk26m>;
clock-names = "sys_ck";
};
port {
usb_role_sw: endpoint {
remote-endpoint = <&hs_ep>;
};
};
};
...

View File

@ -1,57 +0,0 @@
MediaTek musb DRD/OTG controller
-------------------------------------------
Required properties:
- compatible : should be one of:
"mediatek,mt2701-musb"
...
followed by "mediatek,mtk-musb"
- reg : specifies physical base address and size of
the registers
- interrupts : interrupt used by musb controller
- interrupt-names : must be "mc"
- phys : PHY specifier for the OTG phy
- dr_mode : should be one of "host", "peripheral" or "otg",
refer to usb/generic.txt
- clocks : a list of phandle + clock-specifier pairs, one for
each entry in clock-names
- clock-names : must contain "main", "mcu", "univpll"
for clocks of controller
Optional properties:
- power-domains : a phandle to USB power domain node to control USB's
MTCMOS
Required child nodes:
usb connector node as defined in bindings/connector/usb-connector.yaml
Optional properties:
- id-gpios : input GPIO for USB ID pin.
- vbus-gpios : input GPIO for USB VBUS pin.
- vbus-supply : reference to the VBUS regulator, needed when supports
dual-role mode
- usb-role-switch : use USB Role Switch to support dual-role switch, see
usb/generic.txt.
Example:
usb2: usb@11200000 {
compatible = "mediatek,mt2701-musb",
"mediatek,mtk-musb";
reg = <0 0x11200000 0 0x1000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "mc";
phys = <&u2port2 PHY_TYPE_USB2>;
dr_mode = "otg";
clocks = <&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB0_MCU>,
<&pericfg CLK_PERI_USB_SLV>;
clock-names = "main","mcu","univpll";
power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
usb-role-switch;
connector{
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
vbus-supply = <&usb_vbus>;
};
};

View File

@ -0,0 +1,114 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2020 MediaTek
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/mediatek,musb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MUSB DRD/OTG Controller Device Tree Bindings
maintainers:
- Min Guo <min.guo@mediatek.com>
properties:
$nodename:
pattern: '^usb@[0-9a-f]+$'
compatible:
items:
- enum:
- mediatek,mt8516-musb
- mediatek,mt2701-musb
- const: mediatek,mtk-musb
reg:
maxItems: 1
interrupts:
maxItems: 1
interrupt-names:
items:
- const: mc
clocks:
items:
- description: The main/core clock
- description: The system bus clock
- description: The 48Mhz clock
clock-names:
items:
- const: main
- const: mcu
- const: univpll
phys:
maxItems: 1
usb-role-switch:
$ref: /schemas/types.yaml#/definitions/flag
description: Support role switch. See usb/generic.txt
type: boolean
dr_mode:
enum:
- host
- otg
- peripheral
power-domains:
description: A phandle to USB power domain node to control USB's MTCMOS
maxItems: 1
connector:
$ref: /connector/usb-connector.yaml#
description: Connector for dual role switch
type: object
dependencies:
usb-role-switch: [ 'connector' ]
connector: [ 'usb-role-switch' ]
required:
- compatible
- reg
- interrupts
- interrupt-names
- phys
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt2701-clk.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/power/mt2701-power.h>
usb@11200000 {
compatible = "mediatek,mt2701-musb", "mediatek,mtk-musb";
reg = <0x11200000 0x1000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "mc";
phys = <&u2port2 PHY_TYPE_USB2>;
dr_mode = "otg";
clocks = <&pericfg CLK_PERI_USB0>,
<&pericfg CLK_PERI_USB0_MCU>,
<&pericfg CLK_PERI_USB_SLV>;
clock-names = "main","mcu","univpll";
power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
usb-role-switch;
connector {
compatible = "gpio-usb-b-connector", "usb-b-connector";
type = "micro";
id-gpios = <&pio 44 GPIO_ACTIVE_HIGH>;
vbus-supply = <&usb_vbus>;
};
};
...

View File

@ -65,7 +65,7 @@ Sub-nodes:
The dwc3 core should be added as subnode to omap dwc3 glue.
- dwc3 :
The binding details of dwc3 can be found in:
Documentation/devicetree/bindings/usb/dwc3.txt
Documentation/devicetree/bindings/usb/snps,dwc3.yaml
omap_dwc3 {
compatible = "ti,dwc3";

View File

@ -18,6 +18,9 @@ properties:
- qcom,sc7180-dwc3
- qcom,sdm845-dwc3
- qcom,sdx55-dwc3
- qcom,sm8150-dwc3
- qcom,sm8250-dwc3
- qcom,sm8350-dwc3
- const: qcom,dwc3
reg:
@ -104,11 +107,8 @@ properties:
# Required child node:
patternProperties:
"^dwc3@[0-9a-f]+$":
type: object
description:
A child node must exist to represent the core DWC3 IP block
The content of the node is defined in dwc3.txt.
"^usb@[0-9a-f]+$":
$ref: snps,dwc3.yaml#
required:
- compatible
@ -163,7 +163,7 @@ examples:
resets = <&gcc GCC_USB30_PRIM_BCR>;
dwc3@a600000 {
usb@a600000 {
compatible = "snps,dwc3";
reg = <0 0x0a600000 0 0xcd00>;
interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;

View File

@ -11,7 +11,7 @@ maintainers:
- Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
allOf:
- $ref: "usb-hcd.yaml"
- $ref: "usb-xhci.yaml"
properties:
compatible:
@ -68,7 +68,7 @@ required:
- power-domains
- resets
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -1,56 +0,0 @@
Rockchip SuperSpeed DWC3 USB SoC controller
Required properties:
- compatible: should contain "rockchip,rk3399-dwc3" for rk3399 SoC
- clocks: A list of phandle + clock-specifier pairs for the
clocks listed in clock-names
- clock-names: Should contain the following:
"ref_clk" Controller reference clk, have to be 24 MHz
"suspend_clk" Controller suspend clk, have to be 24 MHz or 32 KHz
"bus_clk" Master/Core clock, have to be >= 62.5 MHz for SS
operation and >= 30MHz for HS operation
"grf_clk" Controller grf clk
Required child node:
A child node must exist to represent the core DWC3 IP block. The name of
the node is not important. The content of the node is defined in dwc3.txt.
Phy documentation is provided in the following places:
Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml - USB2.0 PHY
Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt - Type-C PHY
Example device nodes:
usbdrd3_0: usb@fe800000 {
compatible = "rockchip,rk3399-dwc3";
clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>,
<&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "grf_clk";
#address-cells = <2>;
#size-cells = <2>;
ranges;
usbdrd_dwc3_0: dwc3@fe800000 {
compatible = "snps,dwc3";
reg = <0x0 0xfe800000 0x0 0x100000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "otg";
};
};
usbdrd3_1: usb@fe900000 {
compatible = "rockchip,rk3399-dwc3";
clocks = <&cru SCLK_USB3OTG1_REF>, <&cru SCLK_USB3OTG1_SUSPEND>,
<&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "grf_clk";
#address-cells = <2>;
#size-cells = <2>;
ranges;
usbdrd_dwc3_1: dwc3@fe900000 {
compatible = "snps,dwc3";
reg = <0x0 0xfe900000 0x0 0x100000>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "otg";
};
};

View File

@ -0,0 +1,108 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/rockchip,dwc3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip SuperSpeed DWC3 USB SoC controller
maintainers:
- Heiko Stuebner <heiko@sntech.de>
description:
The common content of the node is defined in snps,dwc3.yaml.
Phy documentation is provided in the following places.
USB2.0 PHY
Documentation/devicetree/bindings/phy/phy-rockchip-inno-usb2.yaml
Type-C PHY
Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
allOf:
- $ref: snps,dwc3.yaml#
select:
properties:
compatible:
contains:
enum:
- rockchip,rk3328-dwc3
- rockchip,rk3399-dwc3
required:
- compatible
properties:
compatible:
items:
- enum:
- rockchip,rk3328-dwc3
- rockchip,rk3399-dwc3
- const: snps,dwc3
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
minItems: 3
items:
- description:
Controller reference clock, must to be 24 MHz
- description:
Controller suspend clock, must to be 24 MHz or 32 KHz
- description:
Master/Core clock, must to be >= 62.5 MHz for SS
operation and >= 30MHz for HS operation
- description:
Controller grf clock
clock-names:
minItems: 3
items:
- const: ref_clk
- const: suspend_clk
- const: bus_clk
- const: grf_clk
power-domains:
maxItems: 1
resets:
maxItems: 1
reset-names:
const: usb3-otg
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
examples:
- |
#include <dt-bindings/clock/rk3399-cru.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
bus {
#address-cells = <2>;
#size-cells = <2>;
usbdrd3_0: usb@fe800000 {
compatible = "rockchip,rk3399-dwc3", "snps,dwc3";
reg = <0x0 0xfe800000 0x0 0x100000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>,
<&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_GRF>;
clock-names = "ref_clk", "suspend_clk",
"bus_clk", "grf_clk";
dr_mode = "otg";
};
};

View File

@ -0,0 +1,332 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/snps,dwc3.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys DesignWare USB3 Controller
maintainers:
- Felipe Balbi <balbi@kernel.org>
description:
This is usually a subnode to DWC3 glue to which it is connected, but can also
be presented as a standalone DT node with an optional vendor-specific
compatible string.
allOf:
- $ref: usb-drd.yaml#
- if:
properties:
dr_mode:
const: peripheral
required:
- dr_mode
then:
$ref: usb.yaml#
else:
$ref: usb-xhci.yaml#
properties:
compatible:
contains:
oneOf:
- const: snps,dwc3
- const: synopsys,dwc3
deprecated: true
interrupts:
description:
It's either a single common DWC3 interrupt (dwc_usb3) or individual
interrupts for the host, gadget and DRD modes.
minItems: 1
maxItems: 3
interrupt-names:
minItems: 1
maxItems: 3
oneOf:
- const: dwc_usb3
- items:
enum: [host, peripheral, otg]
clocks:
description:
In general the core supports three types of clocks. bus_early is a
SoC Bus Clock (AHB/AXI/Native). ref generates ITP when the UTMI/ULPI
PHY is suspended. suspend clocks a small part of the USB3 core when
SS PHY in P3. But particular cases may differ from that having less
or more clock sources with another names.
clock-names:
contains:
anyOf:
- enum: [bus_early, ref, suspend]
- true
usb-phy:
minItems: 1
items:
- description: USB2/HS PHY
- description: USB3/SS PHY
phys:
minItems: 1
items:
- description: USB2/HS PHY
- description: USB3/SS PHY
phy-names:
minItems: 1
items:
- const: usb2-phy
- const: usb3-phy
resets:
minItems: 1
snps,usb2-lpm-disable:
description: Indicate if we don't want to enable USB2 HW LPM
type: boolean
snps,usb3_lpm_capable:
description: Determines if platform is USB3 LPM capable
type: boolean
snps,dis-start-transfer-quirk:
description:
When set, disable isoc START TRANSFER command failure SW work-around
for DWC_usb31 version 1.70a-ea06 and prior.
type: boolean
snps,disable_scramble_quirk:
description:
True when SW should disable data scrambling. Only really useful for FPGA
builds.
type: boolean
snps,has-lpm-erratum:
description: True when DWC3 was configured with LPM Erratum enabled
type: boolean
snps,lpm-nyet-threshold:
description: LPM NYET threshold
$ref: /schemas/types.yaml#/definitions/uint8
snps,u2exit_lfps_quirk:
description: Set if we want to enable u2exit lfps quirk
type: boolean
snps,u2ss_inp3_quirk:
description: Set if we enable P3 OK for U2/SS Inactive quirk
type: boolean
snps,req_p1p2p3_quirk:
description:
When set, the core will always request for P1/P2/P3 transition sequence.
type: boolean
snps,del_p1p2p3_quirk:
description:
When set core will delay P1/P2/P3 until a certain amount of 8B10B errors
occur.
type: boolean
snps,del_phy_power_chg_quirk:
description: When set core will delay PHY power change from P0 to P1/P2/P3.
type: boolean
snps,lfps_filter_quirk:
description: When set core will filter LFPS reception.
type: boolean
snps,rx_detect_poll_quirk:
description:
when set core will disable a 400us delay to start Polling LFPS after
RX.Detect.
type: boolean
snps,tx_de_emphasis_quirk:
description: When set core will set Tx de-emphasis value
type: boolean
snps,tx_de_emphasis:
description:
The value driven to the PHY is controlled by the LTSSM during USB3
Compliance mode.
$ref: /schemas/types.yaml#/definitions/uint8
enum:
- 0 # -6dB de-emphasis
- 1 # -3.5dB de-emphasis
- 2 # No de-emphasis
snps,dis_u3_susphy_quirk:
description: When set core will disable USB3 suspend phy
type: boolean
snps,dis_u2_susphy_quirk:
description: When set core will disable USB2 suspend phy
type: boolean
snps,dis_enblslpm_quirk:
description:
When set clears the enblslpm in GUSB2PHYCFG, disabling the suspend signal
to the PHY.
type: boolean
snps,dis-u1-entry-quirk:
description: Set if link entering into U1 needs to be disabled
type: boolean
snps,dis-u2-entry-quirk:
description: Set if link entering into U2 needs to be disabled
type: boolean
snps,dis_rxdet_inp3_quirk:
description:
When set core will disable receiver detection in PHY P3 power state.
type: boolean
snps,dis-u2-freeclk-exists-quirk:
description:
When set, clear the u2_freeclk_exists in GUSB2PHYCFG, specify that USB2
PHY doesn't provide a free-running PHY clock.
type: boolean
snps,dis-del-phy-power-chg-quirk:
description:
When set core will change PHY power from P0 to P1/P2/P3 without delay.
type: boolean
snps,dis-tx-ipgap-linecheck-quirk:
description: When set, disable u2mac linestate check during HS transmit
type: boolean
snps,parkmode-disable-ss-quirk:
description:
When set, all SuperSpeed bus instances in park mode are disabled.
type: boolean
snps,dis_metastability_quirk:
description:
When set, disable metastability workaround. CAUTION! Use only if you are
absolutely sure of it.
type: boolean
snps,dis-split-quirk:
description:
When set, change the way URBs are handled by the driver. Needed to
avoid -EPROTO errors with usbhid on some devices (Hikey 970).
type: boolean
snps,is-utmi-l1-suspend:
description:
True when DWC3 asserts output signal utmi_l1_suspend_n, false when
asserts utmi_sleep_n.
type: boolean
snps,hird-threshold:
description: HIRD threshold
$ref: /schemas/types.yaml#/definitions/uint8
snps,hsphy_interface:
description:
High-Speed PHY interface selection between UTMI+ and ULPI when the
DWC_USB3_HSPHY_INTERFACE has value 3.
$ref: /schemas/types.yaml#/definitions/uint8
enum: [utmi, ulpi]
snps,quirk-frame-length-adjustment:
description:
Value for GFLADJ_30MHZ field of GFLADJ register for post-silicon frame
length adjustment when the fladj_30mhz_sdbnd signal is invalid or
incorrect.
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x3f
snps,rx-thr-num-pkt-prd:
description:
Periodic ESS RX packet threshold count (host mode only). Set this and
snps,rx-max-burst-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.4) to enable periodic ESS RX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
snps,rx-max-burst-prd:
description:
Max periodic ESS RX burst size (host mode only). Set this and
snps,rx-thr-num-pkt-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.4) to enable periodic ESS RX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
snps,tx-thr-num-pkt-prd:
description:
Periodic ESS TX packet threshold count (host mode only). Set this and
snps,tx-max-burst-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.3) to enable periodic ESS TX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
snps,tx-max-burst-prd:
description:
Max periodic ESS TX burst size (host mode only). Set this and
snps,tx-thr-num-pkt-prd to a valid, non-zero value 1-16 (DWC_usb31
programming guide section 1.2.3) to enable periodic ESS TX threshold.
$ref: /schemas/types.yaml#/definitions/uint8
minimum: 1
maximum: 16
tx-fifo-resize:
description: Determines if the FIFO *has* to be reallocated
deprecated: true
type: boolean
snps,incr-burst-type-adjustment:
description:
Value for INCR burst type of GSBUSCFG0 register, undefined length INCR
burst type enable and INCRx type. A single value means INCRX burst mode
enabled. If more than one value specified, undefined length INCR burst
type will be enabled with burst lengths utilized up to the maximum
of the values passed in this property.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
uniqueItems: true
items:
enum: [1, 4, 8, 16, 32, 64, 128, 256]
unevaluatedProperties: false
required:
- compatible
- reg
- interrupts
examples:
- |
usb@4a030000 {
compatible = "snps,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>;
usb-phy = <&usb2_phy>, <&usb3_phy>;
snps,incr-burst-type-adjustment = <1>, <4>, <8>, <16>;
};
- |
usb@4a000000 {
compatible = "snps,dwc3";
reg = <0x4a000000 0xcfff>;
interrupts = <0 92 4>;
clocks = <&clk 1>, <&clk 2>, <&clk 3>;
clock-names = "bus_early", "ref", "suspend";
phys = <&usb2_phy>, <&usb3_phy>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
};
...

View File

@ -64,9 +64,7 @@ properties:
patternProperties:
"usb@[a-f0-9]+$":
type: object
description: This is the node representing the DWC3 controller instance
Documentation/devicetree/bindings/usb/dwc3.txt
$ref: snps,dwc3.yaml#
required:
- compatible

View File

@ -1,102 +0,0 @@
Generic USB Device Properties
Usually, we only use device tree for hard wired USB device.
The reference binding doc is from:
http://www.devicetree.org/open-firmware/bindings/usb/usb-1_0.ps
Four types of device-tree nodes are defined: "host-controller nodes"
representing USB host controllers, "device nodes" representing USB devices,
"interface nodes" representing USB interfaces and "combined nodes"
representing simple USB devices.
A combined node shall be used instead of a device node and an interface node
for devices of class 0 or 9 (hub) with a single configuration and a single
interface.
A "hub node" is a combined node or an interface node that represents a USB
hub.
Required properties for device nodes:
- compatible: "usbVID,PID", where VID is the vendor id and PID the product id.
The textual representation of VID and PID shall be in lower case hexadecimal
with leading zeroes suppressed. The other compatible strings from the above
standard binding could also be used, but a device adhering to this binding
may leave out all except for "usbVID,PID".
- reg: the number of the USB hub port or the USB host-controller port to which
this device is attached. The range is 1-255.
Required properties for device nodes with interface nodes:
- #address-cells: shall be 2
- #size-cells: shall be 0
Required properties for interface nodes:
- compatible: "usbifVID,PID.configCN.IN", where VID is the vendor id, PID is
the product id, CN is the configuration value and IN is the interface
number. The textual representation of VID, PID, CN and IN shall be in lower
case hexadecimal with leading zeroes suppressed. The other compatible
strings from the above standard binding could also be used, but a device
adhering to this binding may leave out all except for
"usbifVID,PID.configCN.IN".
- reg: the interface number and configuration value
The configuration component is not included in the textual representation of
an interface-node unit address for configuration 1.
Required properties for combined nodes:
- compatible: "usbVID,PID", where VID is the vendor id and PID the product id.
The textual representation of VID and PID shall be in lower case hexadecimal
with leading zeroes suppressed. The other compatible strings from the above
standard binding could also be used, but a device adhering to this binding
may leave out all except for "usbVID,PID".
- reg: the number of the USB hub port or the USB host-controller port to which
this device is attached. The range is 1-255.
Required properties for hub nodes with device nodes:
- #address-cells: shall be 1
- #size-cells: shall be 0
Required properties for host-controller nodes with device nodes:
- #address-cells: shall be 1
- #size-cells: shall be 0
Example:
&usb1 { /* host controller */
#address-cells = <1>;
#size-cells = <0>;
hub@1 { /* hub connected to port 1 */
compatible = "usb5e3,608";
reg = <1>;
};
device@2 { /* device connected to port 2 */
compatible = "usb123,4567";
reg = <2>;
};
device@3 { /* device connected to port 3 */
compatible = "usb123,abcd";
reg = <3>;
#address-cells = <2>;
#size-cells = <0>;
interface@0 { /* interface 0 of configuration 1 */
compatible = "usbif123,abcd.config1.0";
reg = <0 1>;
};
interface@0,2 { /* interface 0 of configuration 2 */
compatible = "usbif123,abcd.config2.0";
reg = <0 2>;
};
};
};

View File

@ -0,0 +1,124 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb-device.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: The device tree bindings for the Generic USB Device
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
description: |
Usually, we only use device tree for hard wired USB device.
The reference binding doc is from:
http://www.devicetree.org/open-firmware/bindings/usb/usb-1_0.ps
Four types of device-tree nodes are defined: "host-controller nodes"
representing USB host controllers, "device nodes" representing USB devices,
"interface nodes" representing USB interfaces and "combined nodes"
representing simple USB devices.
A combined node shall be used instead of a device node and an interface node
for devices of class 0 or 9 (hub) with a single configuration and a single
interface.
A "hub node" is a combined node or an interface node that represents a USB
hub.
properties:
compatible:
pattern: "^usb[0-9a-f]{1,4},[0-9a-f]{1,4}$"
description: Device nodes or combined nodes.
"usbVID,PID", where VID is the vendor id and PID the product id.
The textual representation of VID and PID shall be in lower case
hexadecimal with leading zeroes suppressed. The other compatible
strings from the above standard binding could also be used,
but a device adhering to this binding may leave out all except
for "usbVID,PID".
reg:
description: the number of the USB hub port or the USB host-controller
port to which this device is attached. The range is 1-255.
maxItems: 1
"#address-cells":
description: should be 1 for hub nodes with device nodes,
should be 2 for device nodes with interface nodes.
enum: [1, 2]
"#size-cells":
const: 0
patternProperties:
"^interface@[0-9a-f]{1,2}(,[0-9a-f]{1,2})$":
type: object
description: USB interface nodes.
The configuration component is not included in the textual
representation of an interface-node unit address for configuration 1.
properties:
compatible:
pattern: "^usbif[0-9a-f]{1,4},[0-9a-f]{1,4}.config[0-9a-f]{1,2}.[0-9a-f]{1,2}$"
description: Interface nodes.
"usbifVID,PID.configCN.IN", where VID is the vendor id, PID is
the product id, CN is the configuration value and IN is the interface
number. The textual representation of VID, PID, CN and IN shall be
in lower case hexadecimal with leading zeroes suppressed.
The other compatible strings from the above standard binding could
also be used, but a device adhering to this binding may leave out
all except for "usbifVID,PID.configCN.IN".
reg:
description: should be 2 cells long, the first cell represents
the interface number and the second cell represents the
configuration value.
maxItems: 1
required:
- compatible
- reg
additionalProperties: true
examples:
#hub connected to port 1
#device connected to port 2
#device connected to port 3
# interface 0 of configuration 1
# interface 0 of configuration 2
- |
usb@11270000 {
reg = <0x11270000 0x1000>;
interrupts = <0x0 0x4e 0x0>;
#address-cells = <1>;
#size-cells = <0>;
hub@1 {
compatible = "usb5e3,608";
reg = <1>;
};
device@2 {
compatible = "usb123,4567";
reg = <2>;
};
device@3 {
compatible = "usb123,abcd";
reg = <3>;
#address-cells = <2>;
#size-cells = <0>;
interface@0 {
compatible = "usbif123,abcd.config1.0";
reg = <0 1>;
};
interface@0,2 {
compatible = "usbif123,abcd.config2.0";
reg = <0 2>;
};
};
};

View File

@ -0,0 +1,78 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb-drd.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic USB OTG Controller Device Tree Bindings
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
properties:
otg-rev:
description:
Tells usb driver the release number of the OTG and EH supplement with
which the device and its descriptors are compliant, in binary-coded
decimal (i.e. 2.0 is 0200H). This property is used if any real OTG
features (HNP/SRP/ADP) is enabled. If ADP is required, otg-rev should be
0x0200 or above.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0x0100, 0x0120, 0x0130, 0x0200]
dr_mode:
description:
Tells Dual-Role USB controllers that we want to work on a particular
mode. In case this attribute isn't passed via DT, USB DRD controllers
should default to OTG.
$ref: /schemas/types.yaml#/definitions/string
enum: [host, peripheral, otg]
hnp-disable:
description:
Tells OTG controllers we want to disable OTG HNP. Normally HNP is the
basic function of real OTG except you want it to be a srp-capable only B
device.
type: boolean
srp-disable:
description:
Tells OTG controllers we want to disable OTG SRP. SRP is optional for OTG
device.
type: boolean
adp-disable:
description:
Tells OTG controllers we want to disable OTG ADP. ADP is optional for OTG
device.
type: boolean
usb-role-switch:
description:
Indicates that the device is capable of assigning the USB data role
(USB host or USB device) for a given USB connector, such as Type-C,
Type-B(micro). See connector/usb-connector.yaml.
role-switch-default-mode:
description:
Indicates if usb-role-switch is enabled, the device default operation
mode of controller while usb role is USB_ROLE_NONE.
$ref: /schemas/types.yaml#/definitions/string
enum: [host, peripheral]
default: peripheral
additionalProperties: true
examples:
- |
usb@4a030000 {
compatible = "snps,dwc3";
reg = <0x4a030000 0xcfff>;
interrupts = <0 92 4>;
usb-phy = <&usb2_phy>, <&usb3_phy>;
maximum-speed = "super-speed";
dr_mode = "otg";
phy_type = "utmi_wide";
otg-rev = <0x0200>;
adp-disable;
};

View File

@ -9,18 +9,31 @@ title: Generic USB Host Controller Device Tree Bindings
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
allOf:
- $ref: usb.yaml#
properties:
$nodename:
pattern: "^usb(@.*)?"
companion:
description: Phandle of a companion device
$ref: /schemas/types.yaml#/definitions/phandle
phys:
$ref: /schemas/types.yaml#/definitions/phandle-array
tpl-support:
description:
List of all the USB PHYs on this HCD
Indicates if the Targeted Peripheral List is supported for given
targeted hosts (non-PC hosts).
type: boolean
phy-names:
description:
Name specifier for the USB PHY
"#address-cells":
const: 1
"#size-cells":
const: 0
patternProperties:
"^.*@[0-9a-f]{1,2}$":
description: The hard wired USB devices
type: object
$ref: /usb/usb-device.yaml
additionalProperties: true
@ -29,4 +42,11 @@ examples:
usb {
phys = <&usb2_phy1>, <&usb3_phy1>;
phy-names = "usb";
#address-cells = <1>;
#size-cells = <0>;
hub@1 {
compatible = "usb5e3,610";
reg = <1>;
};
};

View File

@ -1,41 +0,0 @@
USB xHCI controllers
Required properties:
- compatible: should be one or more of
- "generic-xhci" for generic XHCI device
- "marvell,armada3700-xhci" for Armada 37xx SoCs
- "marvell,armada-375-xhci" for Armada 375 SoCs
- "marvell,armada-380-xhci" for Armada 38x SoCs
- "brcm,bcm7445-xhci" for Broadcom STB SoCs with XHCI
- "xhci-platform" (deprecated)
When compatible with the generic version, nodes must list the
SoC-specific version corresponding to the platform first
followed by the generic version.
- reg: should contain address and length of the standard XHCI
register set for the device.
- interrupts: one XHCI interrupt should be described here.
Optional properties:
- clocks: reference to the clocks
- clock-names: mandatory if there is a second clock, in this case
the name must be "core" for the first clock and "reg" for the
second one
- usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM
- usb3-lpm-capable: determines if platform is USB3 LPM capable
- quirk-broken-port-ped: set if the controller has broken port disable mechanism
- imod-interval-ns: default interrupt moderation interval is 5000ns
- phys : see usb-hcd.yaml in the current directory
additionally the properties from usb-hcd.yaml (in the current directory) are
supported.
Example:
usb@f0931000 {
compatible = "generic-xhci";
reg = <0xf0931000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
};

View File

@ -0,0 +1,42 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb-xhci.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic USB xHCI Controller Device Tree Bindings
maintainers:
- Mathias Nyman <mathias.nyman@intel.com>
allOf:
- $ref: "usb-hcd.yaml#"
properties:
usb2-lpm-disable:
description: Indicates if we don't want to enable USB2 HW LPM
type: boolean
usb3-lpm-capable:
description: Determines if platform is USB3 LPM capable
type: boolean
quirk-broken-port-ped:
description: Set if the controller has broken port disable mechanism
type: boolean
imod-interval-ns:
description: Interrupt moderation interval
default: 5000
additionalProperties: true
examples:
- |
usb@f0930000 {
compatible = "generic-xhci";
reg = <0xf0930000 0x8c8>;
interrupts = <0x0 0x4e 0x0>;
usb2-lpm-disable;
usb3-lpm-capable;
};

View File

@ -0,0 +1,63 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/usb/usb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Generic USB Controller Device Tree Bindings
maintainers:
- Greg Kroah-Hartman <gregkh@linuxfoundation.org>
select: false
properties:
$nodename:
pattern: "^usb(@.*)?"
phys:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
List of all the USB PHYs on this HCD
phy-names:
description:
Name specifier for the USB PHY
usb-phy:
$ref: /schemas/types.yaml#/definitions/phandle-array
description:
List of all the USB PHYs on this HCD to be accepted by the legacy USB
Physical Layer subsystem.
deprecated: true
phy_type:
description:
Tells USB controllers that we want to configure the core to support a
UTMI+ PHY with an 8- or 16-bit interface if UTMI+ is selected, UTMI+ low
pin interface if ULPI is specified, Serial core/PHY interconnect if
serial is specified and High-Speed Inter-Chip feature if HSIC is
selected. In case this isn't passed via DT, USB controllers should
default to HW capability.
$ref: /schemas/types.yaml#/definitions/string
enum: [utmi, utmi_wide, ulpi, serial, hsic]
maximum-speed:
description:
Tells USB controllers we want to work up to a certain speed. In case this
isn't passed via DT, USB controllers should default to their maximum HW
capability.
$ref: /schemas/types.yaml#/definitions/string
enum:
- low-speed
- full-speed
- high-speed
- super-speed
- super-speed-plus
- super-speed-plus-gen2x1
- super-speed-plus-gen1x2
- super-speed-plus-gen2x2
additionalProperties: true
...

View File

@ -1,7 +1,7 @@
* Freescale i.MX non-core registers
Required properties:
- #index-cells: Cells used to descibe usb controller index. Should be <1>
- #index-cells: Cells used to describe usb controller index. Should be <1>
- compatible: Should be one of below:
"fsl,imx6q-usbmisc" for imx6q
"fsl,vf610-usbmisc" for Vybrid vf610

View File

@ -1260,6 +1260,8 @@ patternProperties:
description: Shenzhen Xunlong Software CO.,Limited
"^xylon,.*":
description: Xylon
"^yamaha,.*":
description: Yamaha Corporation
"^yes-optoelectronics,.*":
description: Yes Optoelectronics Co.,Ltd.
"^ylm,.*":

View File

@ -68,7 +68,6 @@ There are debugfs parameters provided for serial communication.
* tty_status: Prints the bit-mask tty status information
- 0x01 - tty->warned is on.
- 0x02 - tty->low_latency is on.
- 0x04 - tty->packed is on.
- 0x08 - tty->flow_stopped is on.
- 0x10 - tty->hw_stopped is on.

View File

@ -15,6 +15,7 @@ Contents:
ethernet/index
fddi/index
hamradio/index
qlogic/index
wan/index
wifi/index

View File

@ -0,0 +1,18 @@
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
QLogic QLGE Device Drivers
===============================================
Contents:
.. toctree::
:maxdepth: 2
qlge
.. only:: subproject and html
Indices
=======
* :ref:`genindex`

View File

@ -0,0 +1,118 @@
.. SPDX-License-Identifier: GPL-2.0
=======================================
QLogic QLGE 10Gb Ethernet device driver
=======================================
This driver use drgn and devlink for debugging.
Dump kernel data structures in drgn
-----------------------------------
To dump kernel data structures, the following Python script can be used
in drgn:
.. code-block:: python
def align(x, a):
"""the alignment a should be a power of 2
"""
mask = a - 1
return (x+ mask) & ~mask
def struct_size(struct_type):
struct_str = "struct {}".format(struct_type)
return sizeof(Object(prog, struct_str, address=0x0))
def netdev_priv(netdevice):
NETDEV_ALIGN = 32
return netdevice.value_() + align(struct_size("net_device"), NETDEV_ALIGN)
name = 'xxx'
qlge_device = None
netdevices = prog['init_net'].dev_base_head.address_of_()
for netdevice in list_for_each_entry("struct net_device", netdevices, "dev_list"):
if netdevice.name.string_().decode('ascii') == name:
print(netdevice.name)
ql_adapter = Object(prog, "struct ql_adapter", address=netdev_priv(qlge_device))
The struct ql_adapter will be printed in drgn as follows,
>>> ql_adapter
(struct ql_adapter){
.ricb = (struct ricb){
.base_cq = (u8)0,
.flags = (u8)120,
.mask = (__le16)26637,
.hash_cq_id = (u8 [1024]){ 172, 142, 255, 255 },
.ipv6_hash_key = (__le32 [10]){},
.ipv4_hash_key = (__le32 [4]){},
},
.flags = (unsigned long)0,
.wol = (u32)0,
.nic_stats = (struct nic_stats){
.tx_pkts = (u64)0,
.tx_bytes = (u64)0,
.tx_mcast_pkts = (u64)0,
.tx_bcast_pkts = (u64)0,
.tx_ucast_pkts = (u64)0,
.tx_ctl_pkts = (u64)0,
.tx_pause_pkts = (u64)0,
...
},
.active_vlans = (unsigned long [64]){
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52780853100545, 18446744073709551615,
18446619461681283072, 0, 42949673024, 2147483647,
},
.rx_ring = (struct rx_ring [17]){
{
.cqicb = (struct cqicb){
.msix_vect = (u8)0,
.reserved1 = (u8)0,
.reserved2 = (u8)0,
.flags = (u8)0,
.len = (__le16)0,
.rid = (__le16)0,
...
},
.cq_base = (void *)0x0,
.cq_base_dma = (dma_addr_t)0,
}
...
}
}
coredump via devlink
--------------------
And the coredump obtained via devlink in json format looks like,
.. code:: shell
$ devlink health dump show DEVICE reporter coredump -p -j
{
"Core Registers": {
"segment": 1,
"values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
},
"Test Logic Regs": {
"segment": 2,
"values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
},
"RMII Registers": {
"segment": 3,
"values": [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ]
},
...
"Sem Registers": {
"segment": 50,
"values": [ 0,0,0,0 ]
}
}
When the module parameter qlge_force_coredump is set to be true, the MPI
RISC reset before coredumping. So coredumping will much longer since
devlink tool has to wait for 5 secs for the resetting to be
finished.

View File

@ -91,9 +91,9 @@ The ECM function provides these attributes in its function directory:
and after creating the functions/ecm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the ECM function
------------------------
@ -131,9 +131,9 @@ The ECM subset function provides these attributes in its function directory:
and after creating the functions/ecm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the ECM subset function
-------------------------------
@ -171,9 +171,9 @@ The EEM function provides these attributes in its function directory:
and after creating the functions/eem.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the EEM function
------------------------
@ -453,9 +453,9 @@ The NCM function provides these attributes in its function directory:
and after creating the functions/ncm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the NCM function
------------------------
@ -591,9 +591,9 @@ The RNDIS function provides these attributes in its function directory:
and after creating the functions/rndis.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Except for ifname they can be written to until the function is linked to a
configuration. The ifname is read-only and contains the name of the interface
which was assigned by the net core, e. g. usb0.
The ifname can be written to if the function is not bound. A write must be an
interface pattern such as "usb%d", which will cause the net core to choose the
next free usbX interface. By default, it is set to "usb%d".
Testing the RNDIS function
--------------------------

View File

@ -2,83 +2,93 @@
USB Raw Gadget
==============
USB Raw Gadget is a kernel module that provides a userspace interface for
the USB Gadget subsystem. Essentially it allows to emulate USB devices
from userspace. Enabled with CONFIG_USB_RAW_GADGET. Raw Gadget is
currently a strictly debugging feature and shouldn't be used in
production, use GadgetFS instead.
USB Raw Gadget is a gadget driver that gives userspace low-level control over
the gadget's communication process.
Like any other gadget driver, Raw Gadget implements USB devices via the
USB gadget API. Unlike most gadget drivers, Raw Gadget does not implement
any concrete USB functions itself but requires userspace to do that.
Raw Gadget is currently a strictly debugging feature and should not be used
in production. Use GadgetFS instead.
Enabled with CONFIG_USB_RAW_GADGET.
Comparison to GadgetFS
~~~~~~~~~~~~~~~~~~~~~~
Raw Gadget is similar to GadgetFS, but provides a more low-level and
direct access to the USB Gadget layer for the userspace. The key
differences are:
Raw Gadget is similar to GadgetFS but provides more direct access to the
USB gadget layer for userspace. The key differences are:
1. Every USB request is passed to the userspace to get a response, while
1. Raw Gadget passes every USB request to userspace to get a response, while
GadgetFS responds to some USB requests internally based on the provided
descriptors. However note, that the UDC driver might respond to some
requests on its own and never forward them to the Gadget layer.
descriptors. Note that the UDC driver might respond to some requests on
its own and never forward them to the gadget layer.
2. GadgetFS performs some sanity checks on the provided USB descriptors,
while Raw Gadget allows you to provide arbitrary data as responses to
USB requests.
2. Raw Gadget allows providing arbitrary data as responses to USB requests,
while GadgetFS performs sanity checks on the provided USB descriptors.
This makes Raw Gadget suitable for fuzzing by providing malformed data as
responses to USB requests.
3. Raw Gadget provides a way to select a UDC device/driver to bind to,
while GadgetFS currently binds to the first available UDC.
while GadgetFS currently binds to the first available UDC. This allows
having multiple Raw Gadget instances bound to different UDCs.
4. Raw Gadget explicitly exposes information about endpoints addresses and
capabilities allowing a user to write UDC-agnostic gadgets.
capabilities. This allows the user to write UDC-agnostic gadgets.
5. Raw Gadget has ioctl-based interface instead of a filesystem-based one.
5. Raw Gadget has an ioctl-based interface instead of a filesystem-based
one.
Userspace interface
~~~~~~~~~~~~~~~~~~~
To create a Raw Gadget instance open /dev/raw-gadget. Multiple raw-gadget
instances (bound to different UDCs) can be used at the same time. The
interaction with the opened file happens through the ioctl() calls, see
comments in include/uapi/linux/usb/raw_gadget.h for details.
The user can interact with Raw Gadget by opening ``/dev/raw-gadget`` and
issuing ioctl calls; see the comments in include/uapi/linux/usb/raw_gadget.h
for details. Multiple Raw Gadget instances (bound to different UDCs) can be
used at the same time.
The typical usage of Raw Gadget looks like:
A typical usage scenario of Raw Gadget:
1. Open Raw Gadget instance via /dev/raw-gadget.
2. Initialize the instance via USB_RAW_IOCTL_INIT.
3. Launch the instance with USB_RAW_IOCTL_RUN.
4. In a loop issue USB_RAW_IOCTL_EVENT_FETCH calls to receive events from
Raw Gadget and react to those depending on what kind of USB device
needs to be emulated.
1. Create a Raw Gadget instance by opening ``/dev/raw-gadget``.
2. Initialize the instance via ``USB_RAW_IOCTL_INIT``.
3. Launch the instance with ``USB_RAW_IOCTL_RUN``.
4. In a loop issue ``USB_RAW_IOCTL_EVENT_FETCH`` to receive events from
Raw Gadget and react to those depending on what kind of USB gadget must
be implemented.
Note, that some UDC drivers have fixed addresses assigned to endpoints, and
therefore arbitrary endpoint addresses can't be used in the descriptors.
Nevertheles, Raw Gadget provides a UDC-agnostic way to write USB gadgets.
Once a USB_RAW_EVENT_CONNECT event is received via USB_RAW_IOCTL_EVENT_FETCH,
the USB_RAW_IOCTL_EPS_INFO ioctl can be used to find out information about
endpoints that the UDC driver has. Based on that information, the user must
chose UDC endpoints that will be used for the gadget being emulated, and
properly assign addresses in endpoint descriptors.
Note that some UDC drivers have fixed addresses assigned to endpoints, and
therefore arbitrary endpoint addresses cannot be used in the descriptors.
Nevertheless, Raw Gadget provides a UDC-agnostic way to write USB gadgets.
Once ``USB_RAW_EVENT_CONNECT`` is received via ``USB_RAW_IOCTL_EVENT_FETCH``,
``USB_RAW_IOCTL_EPS_INFO`` can be used to find out information about the
endpoints that the UDC driver has. Based on that, userspace must choose UDC
endpoints for the gadget and assign addresses in the endpoint descriptors
correspondingly.
You can find usage examples (along with a test suite) here:
Raw Gadget usage examples and a test suite:
https://github.com/xairy/raw-gadget
Internal details
~~~~~~~~~~~~~~~~
Currently every endpoint read/write ioctl submits a USB request and waits until
its completion. This is the desired mode for coverage-guided fuzzing (as we'd
like all USB request processing happen during the lifetime of a syscall),
and must be kept in the implementation. (This might be slow for real world
applications, thus the O_NONBLOCK improvement suggestion below.)
Every Raw Gadget endpoint read/write ioctl submits a USB request and waits
until its completion. This is done deliberately to assist with coverage-guided
fuzzing by having a single syscall fully process a single USB request. This
feature must be kept in the implementation.
Potential future improvements
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Report more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH.
- Report more events (suspend, resume, etc.) through
``USB_RAW_IOCTL_EVENT_FETCH``.
- Support O_NONBLOCK I/O.
- Support ``O_NONBLOCK`` I/O. This would be another mode of operation, where
Raw Gadget would not wait until the completion of each USB request.
- Support USB 3 features (accept SS endpoint companion descriptor when
enabling endpoints; allow providing stream_id for bulk transfers).
enabling endpoints; allow providing ``stream_id`` for bulk transfers).
- Support ISO transfer features (expose frame_number for completed requests).
- Support ISO transfer features (expose ``frame_number`` for completed
requests).

View File

@ -2071,7 +2071,7 @@ M: Chunfeng Yun <chunfeng.yun@mediatek.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/phy/phy-mtk-*
F: Documentation/devicetree/bindings/phy/mediatek,*
F: drivers/phy/mediatek/
ARM/Microchip (AT91) SoC support
@ -3855,6 +3855,15 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
F: Documentation/devicetree/bindings/usb/cdns,usb3.yaml
F: drivers/usb/cdns3/
X: drivers/usb/cdns3/cdnsp*
CADENCE USBSSP DRD IP DRIVER
M: Pawel Laszczak <pawell@cadence.com>
L: linux-usb@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
F: drivers/usb/cdns3/
X: drivers/usb/cdns3/cdns3*
CADET FM/AM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
@ -11236,6 +11245,8 @@ L: linux-usb@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/usb/mediatek,*
F: drivers/usb/host/xhci-mtk*
F: drivers/usb/mtu3/
MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
@ -14592,6 +14603,12 @@ L: netdev@vger.kernel.org
S: Supported
F: drivers/staging/qlge/
QLOGIC QLGE 10Gb ETHERNET DRIVER
M: Coiby Xu <coiby.xu@gmail.com>
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/networking/device_drivers/qlogic/qlge.rst
QM1D1B0004 MEDIA DRIVER
M: Akihiro Tsukada <tskd08@gmail.com>
L: linux-media@vger.kernel.org

View File

@ -238,12 +238,13 @@ CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_TEGRA=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_TEGRA=y
CONFIG_USB_ACM=y
CONFIG_USB_WDM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
CONFIG_USB_CHIPIDEA_TEGRA=y
CONFIG_USB_GADGET=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16

View File

@ -127,6 +127,21 @@ &uart2 {
status = "okay";
};
&usb3_phy1 {
status = "okay";
};
&usb3_1 {
status = "okay";
};
&usb_dwc3_1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb1_vbus>;
dr_mode = "host";
status = "okay";
};
&usdhc2 {
assigned-clocks = <&clk IMX8MP_CLK_USDHC2>;
assigned-clock-rates = <400000000>;
@ -232,6 +247,12 @@ MX8MP_IOMUXC_UART2_TXD__UART2_DCE_TX 0x49
>;
};
pinctrl_usb1_vbus: usb1grp {
fsl,pins = <
MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR 0x19
>;
};
pinctrl_usdhc2: usdhc2grp {
fsl,pins = <
MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190

View File

@ -803,5 +803,87 @@ ddr-pmu@3d800000 {
reg = <0x3d800000 0x400000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
};
usb3_phy0: usb-phy@381f0040 {
compatible = "fsl,imx8mp-usb-phy";
reg = <0x381f0040 0x40>;
clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
clock-names = "phy";
assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
#phy-cells = <0>;
status = "disabled";
};
usb3_0: usb@32f10100 {
compatible = "fsl,imx8mp-dwc3";
reg = <0x32f10100 0x8>;
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "hsio", "suspend";
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x40000000 0x40000000 0xc0000000>;
ranges;
status = "disabled";
usb_dwc3_0: dwc3@38100000 {
compatible = "snps,dwc3";
reg = <0x38100000 0x10000>;
clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
<&clk IMX8MP_CLK_USB_CORE_REF>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>;
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>;
assigned-clock-rates = <500000000>;
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb3_phy0>, <&usb3_phy0>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis-u2-freeclk-exists-quirk;
};
};
usb3_phy1: usb-phy@382f0040 {
compatible = "fsl,imx8mp-usb-phy";
reg = <0x382f0040 0x40>;
clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
clock-names = "phy";
assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
#phy-cells = <0>;
};
usb3_1: usb@32f10108 {
compatible = "fsl,imx8mp-dwc3";
reg = <0x32f10108 0x8>;
clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "hsio", "suspend";
interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <1>;
dma-ranges = <0x40000000 0x40000000 0xc0000000>;
ranges;
status = "disabled";
usb_dwc3_1: dwc3@38200000 {
compatible = "snps,dwc3";
reg = <0x38200000 0x10000>;
clocks = <&clk IMX8MP_CLK_HSIO_AXI>,
<&clk IMX8MP_CLK_USB_CORE_REF>,
<&clk IMX8MP_CLK_USB_ROOT>;
clock-names = "bus_early", "ref", "suspend";
assigned-clocks = <&clk IMX8MP_CLK_HSIO_AXI>;
assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_500M>;
assigned-clock-rates = <500000000>;
interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usb3_phy1>, <&usb3_phy1>;
phy-names = "usb2-phy", "usb3-phy";
snps,dis-u2-freeclk-exists-quirk;
};
};
};
};

View File

@ -152,7 +152,7 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth)
if (ret)
return ret;
tty = tty_kopen(dev);
tty = tty_kopen_exclusive(dev);
if (IS_ERR(tty))
return PTR_ERR(tty);

View File

@ -281,10 +281,16 @@ bool osc_sb_apei_support_acked;
bool osc_pc_lpi_support_confirmed;
EXPORT_SYMBOL_GPL(osc_pc_lpi_support_confirmed);
/*
* ACPI 6.4 Operating System Capabilities for USB.
*/
bool osc_sb_native_usb4_support_confirmed;
EXPORT_SYMBOL_GPL(osc_sb_native_usb4_support_confirmed);
static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
static void acpi_bus_osc_support(void)
static void acpi_bus_osc_negotiate_platform_control(void)
{
u32 capbuf[2];
u32 capbuf[2], *capbuf_ret;
struct acpi_osc_context context = {
.uuid_str = sb_uuid_str,
.rev = 1,
@ -317,21 +323,109 @@ static void acpi_bus_osc_support(void)
if (IS_ENABLED(CONFIG_SCHED_MC_PRIO))
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT;
if (IS_ENABLED(CONFIG_USB4))
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_NATIVE_USB4_SUPPORT;
if (!ghes_disable)
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
return;
if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
u32 *capbuf_ret = context.ret.pointer;
if (context.ret.length > OSC_SUPPORT_DWORD) {
osc_sb_apei_support_acked =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
osc_pc_lpi_support_confirmed =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
}
if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
return;
capbuf_ret = context.ret.pointer;
if (context.ret.length <= OSC_SUPPORT_DWORD) {
kfree(context.ret.pointer);
return;
}
/* do we need to check other returned cap? Sounds no */
/*
* Now run _OSC again with query flag clear and with the caps
* supported by both the OS and the platform.
*/
capbuf[OSC_QUERY_DWORD] = 0;
capbuf[OSC_SUPPORT_DWORD] = capbuf_ret[OSC_SUPPORT_DWORD];
kfree(context.ret.pointer);
if (ACPI_FAILURE(acpi_run_osc(handle, &context)))
return;
capbuf_ret = context.ret.pointer;
if (context.ret.length > OSC_SUPPORT_DWORD) {
osc_sb_apei_support_acked =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_APEI_SUPPORT;
osc_pc_lpi_support_confirmed =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_PCLPI_SUPPORT;
osc_sb_native_usb4_support_confirmed =
capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_NATIVE_USB4_SUPPORT;
}
kfree(context.ret.pointer);
}
/*
* Native control of USB4 capabilities. If any of the tunneling bits is
* set it means OS is in control and we use software based connection
* manager.
*/
u32 osc_sb_native_usb4_control;
EXPORT_SYMBOL_GPL(osc_sb_native_usb4_control);
static void acpi_bus_decode_usb_osc(const char *msg, u32 bits)
{
printk(KERN_INFO PREFIX "%s USB3%c DisplayPort%c PCIe%c XDomain%c\n", msg,
(bits & OSC_USB_USB3_TUNNELING) ? '+' : '-',
(bits & OSC_USB_DP_TUNNELING) ? '+' : '-',
(bits & OSC_USB_PCIE_TUNNELING) ? '+' : '-',
(bits & OSC_USB_XDOMAIN) ? '+' : '-');
}
static u8 sb_usb_uuid_str[] = "23A0D13A-26AB-486C-9C5F-0FFA525A575A";
static void acpi_bus_osc_negotiate_usb_control(void)
{
u32 capbuf[3];
struct acpi_osc_context context = {
.uuid_str = sb_usb_uuid_str,
.rev = 1,
.cap.length = sizeof(capbuf),
.cap.pointer = capbuf,
};
acpi_handle handle;
acpi_status status;
u32 control;
if (!osc_sb_native_usb4_support_confirmed)
return;
if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
return;
control = OSC_USB_USB3_TUNNELING | OSC_USB_DP_TUNNELING |
OSC_USB_PCIE_TUNNELING | OSC_USB_XDOMAIN;
capbuf[OSC_QUERY_DWORD] = 0;
capbuf[OSC_SUPPORT_DWORD] = 0;
capbuf[OSC_CONTROL_DWORD] = control;
status = acpi_run_osc(handle, &context);
if (ACPI_FAILURE(status))
return;
if (context.ret.length != sizeof(capbuf)) {
printk(KERN_INFO PREFIX "USB4 _OSC: returned invalid length buffer\n");
goto out_free;
}
osc_sb_native_usb4_control =
control & ((u32 *)context.ret.pointer)[OSC_CONTROL_DWORD];
acpi_bus_decode_usb_osc("USB4 _OSC: OS supports", control);
acpi_bus_decode_usb_osc("USB4 _OSC: OS controls",
osc_sb_native_usb4_control);
out_free:
kfree(context.ret.pointer);
}
/* --------------------------------------------------------------------------
@ -1168,7 +1262,8 @@ static int __init acpi_bus_init(void)
* _OSC method may exist in module level code,
* so it must be run after ACPI_FULL_INITIALIZATION
*/
acpi_bus_osc_support();
acpi_bus_osc_negotiate_platform_control();
acpi_bus_osc_negotiate_usb_control();
/*
* _PDC control method may load dynamic SSDT tables,

View File

@ -24,6 +24,7 @@ struct swnode {
struct swnode *parent;
unsigned int allocated:1;
unsigned int managed:1;
};
static DEFINE_IDA(swnode_root_ids);
@ -48,6 +49,19 @@ EXPORT_SYMBOL_GPL(is_software_node);
struct swnode, fwnode) : NULL; \
})
static inline struct swnode *dev_to_swnode(struct device *dev)
{
struct fwnode_handle *fwnode = dev_fwnode(dev);
if (!fwnode)
return NULL;
if (!is_software_node(fwnode))
fwnode = fwnode->secondary;
return to_swnode(fwnode);
}
static struct swnode *
software_node_to_swnode(const struct software_node *node)
{
@ -843,22 +857,99 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode)
}
EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
/**
* device_add_software_node - Assign software node to a device
* @dev: The device the software node is meant for.
* @swnode: The software node.
*
* This function will register @swnode and make it the secondary firmware node
* pointer of @dev. If @dev has no primary node, then @swnode will become the primary
* node.
*/
int device_add_software_node(struct device *dev, const struct software_node *swnode)
{
int ret;
/* Only one software node per device. */
if (dev_to_swnode(dev))
return -EBUSY;
ret = software_node_register(swnode);
if (ret)
return ret;
set_secondary_fwnode(dev, software_node_fwnode(swnode));
return 0;
}
EXPORT_SYMBOL_GPL(device_add_software_node);
/**
* device_remove_software_node - Remove device's software node
* @dev: The device with the software node.
*
* This function will unregister the software node of @dev.
*/
void device_remove_software_node(struct device *dev)
{
struct swnode *swnode;
swnode = dev_to_swnode(dev);
if (!swnode)
return;
software_node_notify(dev, KOBJ_REMOVE);
set_secondary_fwnode(dev, NULL);
kobject_put(&swnode->kobj);
}
EXPORT_SYMBOL_GPL(device_remove_software_node);
/**
* device_create_managed_software_node - Create a software node for a device
* @dev: The device the software node is assigned to.
* @properties: Device properties for the software node.
* @parent: Parent of the software node.
*
* Creates a software node as a managed resource for @dev, which means the
* lifetime of the newly created software node is tied to the lifetime of @dev.
* Software nodes created with this function should not be reused or shared
* because of that. The function takes a deep copy of @properties for the
* software node.
*
* Since the new software node is assigned directly to @dev, and since it should
* not be shared, it is not returned to the caller. The function returns 0 on
* success, and errno in case of an error.
*/
int device_create_managed_software_node(struct device *dev,
const struct property_entry *properties,
const struct software_node *parent)
{
struct fwnode_handle *p = software_node_fwnode(parent);
struct fwnode_handle *fwnode;
if (parent && !p)
return -EINVAL;
fwnode = fwnode_create_software_node(properties, p);
if (IS_ERR(fwnode))
return PTR_ERR(fwnode);
to_swnode(fwnode)->managed = true;
set_secondary_fwnode(dev, fwnode);
return 0;
}
EXPORT_SYMBOL_GPL(device_create_managed_software_node);
int software_node_notify(struct device *dev, unsigned long action)
{
struct fwnode_handle *fwnode = dev_fwnode(dev);
struct swnode *swnode;
int ret;
if (!fwnode)
swnode = dev_to_swnode(dev);
if (!swnode)
return 0;
if (!is_software_node(fwnode))
fwnode = fwnode->secondary;
if (!is_software_node(fwnode))
return 0;
swnode = to_swnode(fwnode);
switch (action) {
case KOBJ_ADD:
ret = sysfs_create_link(&dev->kobj, &swnode->kobj,
@ -878,6 +969,11 @@ int software_node_notify(struct device *dev, unsigned long action)
sysfs_remove_link(&swnode->kobj, dev_name(dev));
sysfs_remove_link(&dev->kobj, "software_node");
kobject_put(&swnode->kobj);
if (swnode->managed) {
set_secondary_fwnode(dev, NULL);
kobject_put(&swnode->kobj);
}
break;
default:
break;

View File

@ -801,7 +801,8 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file *file,
* We don't provide read/write/poll interface for user space.
*/
static ssize_t hci_uart_tty_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
unsigned char *buf, size_t nr,
void **cookie, unsigned long offset)
{
return 0;
}
@ -818,29 +819,28 @@ static __poll_t hci_uart_tty_poll(struct tty_struct *tty,
return 0;
}
static struct tty_ldisc_ops hci_uart_ldisc = {
.owner = THIS_MODULE,
.magic = TTY_LDISC_MAGIC,
.name = "n_hci",
.open = hci_uart_tty_open,
.close = hci_uart_tty_close,
.read = hci_uart_tty_read,
.write = hci_uart_tty_write,
.ioctl = hci_uart_tty_ioctl,
.compat_ioctl = hci_uart_tty_ioctl,
.poll = hci_uart_tty_poll,
.receive_buf = hci_uart_tty_receive,
.write_wakeup = hci_uart_tty_wakeup,
};
static int __init hci_uart_init(void)
{
static struct tty_ldisc_ops hci_uart_ldisc;
int err;
BT_INFO("HCI UART driver ver %s", VERSION);
/* Register the tty discipline */
memset(&hci_uart_ldisc, 0, sizeof(hci_uart_ldisc));
hci_uart_ldisc.magic = TTY_LDISC_MAGIC;
hci_uart_ldisc.name = "n_hci";
hci_uart_ldisc.open = hci_uart_tty_open;
hci_uart_ldisc.close = hci_uart_tty_close;
hci_uart_ldisc.read = hci_uart_tty_read;
hci_uart_ldisc.write = hci_uart_tty_write;
hci_uart_ldisc.ioctl = hci_uart_tty_ioctl;
hci_uart_ldisc.compat_ioctl = hci_uart_tty_ioctl;
hci_uart_ldisc.poll = hci_uart_tty_poll;
hci_uart_ldisc.receive_buf = hci_uart_tty_receive;
hci_uart_ldisc.write_wakeup = hci_uart_tty_wakeup;
hci_uart_ldisc.owner = THIS_MODULE;
err = tty_register_ldisc(N_HCI, &hci_uart_ldisc);
if (err) {
BT_ERR("HCI line discipline registration failed. (%d)", err);

View File

@ -2494,8 +2494,6 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
__FILE__, __LINE__, tty->driver->name, port->count);
port->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
spin_lock_irqsave(&info->netlock, flags);
if (info->netcount) {
retval = -EBUSY;

View File

@ -4,6 +4,7 @@
* Copyright (c) 2015, Intel Corporation.
*/
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@ -21,6 +22,7 @@
#define HID_CUSTOM_TOTAL_ATTRS (HID_CUSTOM_MAX_CORE_ATTRS + 1)
#define HID_CUSTOM_FIFO_SIZE 4096
#define HID_CUSTOM_MAX_FEATURE_BYTES 64
#define HID_SENSOR_USAGE_LENGTH (4 + 1)
struct hid_sensor_custom_field {
int report_id;
@ -50,6 +52,7 @@ struct hid_sensor_custom {
struct kfifo data_fifo;
unsigned long misc_opened;
wait_queue_head_t wait;
struct platform_device *custom_pdev;
};
/* Header for each sample to user space via dev interface */
@ -746,11 +749,130 @@ static void hid_sensor_custom_dev_if_remove(struct hid_sensor_custom
}
/* luid defined in FW (e.g. ISH). Maybe used to identify sensor. */
static const char *const known_sensor_luid[] = { "020B000000000000" };
static int get_luid_table_index(unsigned char *usage_str)
{
int i;
for (i = 0; i < ARRAY_SIZE(known_sensor_luid); i++) {
if (!strncmp(usage_str, known_sensor_luid[i],
strlen(known_sensor_luid[i])))
return i;
}
return -ENODEV;
}
static int get_known_custom_sensor_index(struct hid_sensor_hub_device *hsdev)
{
struct hid_sensor_hub_attribute_info sensor_manufacturer = { 0 };
struct hid_sensor_hub_attribute_info sensor_luid_info = { 0 };
int report_size;
int ret;
static u16 w_buf[HID_CUSTOM_MAX_FEATURE_BYTES];
static char buf[HID_CUSTOM_MAX_FEATURE_BYTES];
int i;
memset(w_buf, 0, sizeof(w_buf));
memset(buf, 0, sizeof(buf));
/* get manufacturer info */
ret = sensor_hub_input_get_attribute_info(hsdev,
HID_FEATURE_REPORT, hsdev->usage,
HID_USAGE_SENSOR_PROP_MANUFACTURER, &sensor_manufacturer);
if (ret < 0)
return ret;
report_size =
sensor_hub_get_feature(hsdev, sensor_manufacturer.report_id,
sensor_manufacturer.index, sizeof(w_buf),
w_buf);
if (report_size <= 0) {
hid_err(hsdev->hdev,
"Failed to get sensor manufacturer info %d\n",
report_size);
return -ENODEV;
}
/* convert from wide char to char */
for (i = 0; i < ARRAY_SIZE(buf) - 1 && w_buf[i]; i++)
buf[i] = (char)w_buf[i];
/* ensure it's ISH sensor */
if (strncmp(buf, "INTEL", strlen("INTEL")))
return -ENODEV;
memset(w_buf, 0, sizeof(w_buf));
memset(buf, 0, sizeof(buf));
/* get real usage id */
ret = sensor_hub_input_get_attribute_info(hsdev,
HID_FEATURE_REPORT, hsdev->usage,
HID_USAGE_SENSOR_PROP_SERIAL_NUM, &sensor_luid_info);
if (ret < 0)
return ret;
report_size = sensor_hub_get_feature(hsdev, sensor_luid_info.report_id,
sensor_luid_info.index, sizeof(w_buf),
w_buf);
if (report_size <= 0) {
hid_err(hsdev->hdev, "Failed to get real usage info %d\n",
report_size);
return -ENODEV;
}
/* convert from wide char to char */
for (i = 0; i < ARRAY_SIZE(buf) - 1 && w_buf[i]; i++)
buf[i] = (char)w_buf[i];
if (strlen(buf) != strlen(known_sensor_luid[0]) + 5) {
hid_err(hsdev->hdev,
"%s luid length not match %zu != (%zu + 5)\n", __func__,
strlen(buf), strlen(known_sensor_luid[0]));
return -ENODEV;
}
/* get table index with luid (not matching 'LUID: ' in luid) */
return get_luid_table_index(&buf[5]);
}
static struct platform_device *
hid_sensor_register_platform_device(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
int index)
{
char real_usage[HID_SENSOR_USAGE_LENGTH] = { 0 };
struct platform_device *custom_pdev;
const char *dev_name;
char *c;
/* copy real usage id */
memcpy(real_usage, known_sensor_luid[index], 4);
/* usage id are all lowcase */
for (c = real_usage; *c != '\0'; c++)
*c = tolower(*c);
/* HID-SENSOR-INT-REAL_USAGE_ID */
dev_name = kasprintf(GFP_KERNEL, "HID-SENSOR-INT-%s", real_usage);
if (!dev_name)
return ERR_PTR(-ENOMEM);
custom_pdev = platform_device_register_data(pdev->dev.parent, dev_name,
PLATFORM_DEVID_NONE, hsdev,
sizeof(*hsdev));
kfree(dev_name);
return custom_pdev;
}
static int hid_sensor_custom_probe(struct platform_device *pdev)
{
struct hid_sensor_custom *sensor_inst;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
int ret;
int index;
sensor_inst = devm_kzalloc(&pdev->dev, sizeof(*sensor_inst),
GFP_KERNEL);
@ -764,6 +886,22 @@ static int hid_sensor_custom_probe(struct platform_device *pdev)
sensor_inst->pdev = pdev;
mutex_init(&sensor_inst->mutex);
platform_set_drvdata(pdev, sensor_inst);
index = get_known_custom_sensor_index(hsdev);
if (index >= 0 && index < ARRAY_SIZE(known_sensor_luid)) {
sensor_inst->custom_pdev =
hid_sensor_register_platform_device(pdev, hsdev, index);
ret = PTR_ERR_OR_ZERO(sensor_inst->custom_pdev);
if (ret) {
dev_err(&pdev->dev,
"register_platform_device failed\n");
return ret;
}
return 0;
}
ret = sensor_hub_register_callback(hsdev, hsdev->usage,
&sensor_inst->callbacks);
if (ret < 0) {
@ -802,6 +940,11 @@ static int hid_sensor_custom_remove(struct platform_device *pdev)
struct hid_sensor_custom *sensor_inst = platform_get_drvdata(pdev);
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
if (sensor_inst->custom_pdev) {
platform_device_unregister(sensor_inst->custom_pdev);
return 0;
}
hid_sensor_custom_dev_if_remove(sensor_inst);
hid_sensor_custom_remove_attributes(sensor_inst);
sysfs_remove_group(&sensor_inst->pdev->dev.kobj,

View File

@ -23,6 +23,7 @@ enum accel_3d_channel {
ACCEL_3D_CHANNEL_MAX,
};
#define CHANNEL_SCAN_INDEX_TIMESTAMP ACCEL_3D_CHANNEL_MAX
struct accel_3d_state {
struct hid_sensor_hub_callbacks callbacks;
struct hid_sensor_common common_attributes;
@ -75,7 +76,7 @@ static const struct iio_chan_spec accel_3d_channels[] = {
BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Z,
},
IIO_CHAN_SOFT_TIMESTAMP(3)
IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
};
/* Channel definitions */
@ -110,7 +111,8 @@ static const struct iio_chan_spec gravity_channels[] = {
BIT(IIO_CHAN_INFO_SAMP_FREQ) |
BIT(IIO_CHAN_INFO_HYSTERESIS),
.scan_index = CHANNEL_SCAN_INDEX_Z,
}
},
IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP),
};
/* Adjust channel real bits based on report descriptor */

View File

@ -14,6 +14,7 @@
#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
@ -133,6 +134,7 @@ enum kx_acpi_type {
};
struct kxcjk1013_data {
struct regulator_bulk_data regulators[2];
struct i2c_client *client;
struct iio_trigger *dready_trig;
struct iio_trigger *motion_trig;
@ -1300,6 +1302,13 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev,
return dev_name(dev);
}
static void kxcjk1013_disable_regulators(void *d)
{
struct kxcjk1013_data *data = d;
regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
}
static int kxcjk1013_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -1330,6 +1339,29 @@ static int kxcjk1013_probe(struct i2c_client *client,
return ret;
}
data->regulators[0].supply = "vdd";
data->regulators[1].supply = "vddio";
ret = devm_regulator_bulk_get(&client->dev, ARRAY_SIZE(data->regulators),
data->regulators);
if (ret)
return dev_err_probe(&client->dev, ret, "Failed to get regulators\n");
ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
data->regulators);
if (ret)
return ret;
ret = devm_add_action_or_reset(&client->dev, kxcjk1013_disable_regulators, data);
if (ret)
return ret;
/*
* A typical delay of 10ms is required for powering up
* according to the data sheets of supported chips.
* Hence double that to play safe.
*/
msleep(20);
if (id) {
data->chipset = (enum kx_chipset)(id->driver_data);
name = id->name;

View File

@ -1228,8 +1228,15 @@ config XILINX_XADC
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say yes here to have support for the Xilinx XADC. The driver does support
both the ZYNQ interface to the XADC as well as the AXI-XADC interface.
Say yes here to have support for the Xilinx 7 Series XADC or
UltraScale/UltraScale+ System Management Wizard.
For the 7 Series the driver does support both the ZYNQ interface
to the XADC as well as the AXI-XADC interface.
The driver also support the Xilinx System Management Wizard IP core
that can be used to access the System Monitor ADC on the Xilinx
UltraScale and UltraScale+ FPGAs.
The driver can also be build as a module. If so, the module will be called
xilinx-xadc.

View File

@ -1108,10 +1108,14 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
return gpadc->irq_sw;
}
gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END");
if (gpadc->irq_hw < 0) {
dev_err(dev, "failed to get platform hw_conv_end irq\n");
return gpadc->irq_hw;
if (is_ab8500(gpadc->ab8500)) {
gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END");
if (gpadc->irq_hw < 0) {
dev_err(dev, "failed to get platform hw_conv_end irq\n");
return gpadc->irq_hw;
}
} else {
gpadc->irq_hw = 0;
}
/* Initialize completion used to notify completion of conversion */
@ -1128,14 +1132,16 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
return ret;
}
ret = devm_request_threaded_irq(dev, gpadc->irq_hw, NULL,
ab8500_bm_gpadcconvend_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
"ab8500-gpadc-hw", gpadc);
if (ret < 0) {
dev_err(dev,
"Failed to request hw conversion irq: %d\n",
gpadc->irq_hw);
return ret;
if (gpadc->irq_hw) {
ret = devm_request_threaded_irq(dev, gpadc->irq_hw, NULL,
ab8500_bm_gpadcconvend_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
"ab8500-gpadc-hw", gpadc);
if (ret < 0) {
dev_err(dev,
"Failed to request hw conversion irq: %d\n",
gpadc->irq_hw);
return ret;
}
}
/* The VTVout LDO used to power the AB8500 GPADC */

View File

@ -67,6 +67,7 @@ enum ad7476_supported_device_ids {
ID_ADS7866,
ID_ADS7867,
ID_ADS7868,
ID_LTC2314_14,
};
static void ad7091_convst(struct ad7476_state *st)
@ -250,6 +251,10 @@ static const struct ad7476_chip_info ad7476_chip_info_tbl[] = {
.channel[0] = ADS786X_CHAN(8),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
[ID_LTC2314_14] = {
.channel[0] = AD7940_CHAN(14),
.channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1),
},
};
static const struct iio_info ad7476_info = {
@ -365,6 +370,7 @@ static const struct spi_device_id ad7476_id[] = {
{"ads7866", ID_ADS7866},
{"ads7867", ID_ADS7867},
{"ads7868", ID_ADS7868},
{"ltc2314-14", ID_LTC2314_14},
{}
};
MODULE_DEVICE_TABLE(spi, ad7476_id);

View File

@ -10,6 +10,7 @@
* Author: Linus Walleij <linus.walleij@linaro.org>
*/
#include <linux/iio/adc/qcom-vadc-common.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/module.h>
@ -21,8 +22,6 @@
#include <linux/interrupt.h>
#include <linux/regulator/consumer.h>
#include "qcom-vadc-common.h"
/*
* Definitions for the "user processor" registers lifted from the v3.4
* Qualcomm tree. Their kernel has two out-of-tree drivers for the ADC:

View File

@ -7,6 +7,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/iio/adc/qcom-vadc-common.h>
#include <linux/iio/iio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@ -14,12 +15,12 @@
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <dt-bindings/iio/qcom,spmi-vadc.h>
#include "qcom-vadc-common.h"
#define ADC5_USR_REVISION1 0x0
#define ADC5_USR_STATUS1 0x8
@ -154,18 +155,6 @@ struct adc5_chip {
const struct adc5_data *data;
};
static const struct vadc_prescale_ratio adc5_prescale_ratios[] = {
{.num = 1, .den = 1},
{.num = 1, .den = 3},
{.num = 1, .den = 4},
{.num = 1, .den = 6},
{.num = 1, .den = 20},
{.num = 1, .den = 8},
{.num = 10, .den = 81},
{.num = 1, .den = 10},
{.num = 1, .den = 16}
};
static int adc5_read(struct adc5_chip *adc, u16 offset, u8 *data, int len)
{
return regmap_bulk_read(adc->regmap, adc->base + offset, data, len);
@ -181,55 +170,6 @@ static int adc5_masked_write(struct adc5_chip *adc, u16 offset, u8 mask, u8 val)
return regmap_update_bits(adc->regmap, adc->base + offset, mask, val);
}
static int adc5_prescaling_from_dt(u32 num, u32 den)
{
unsigned int pre;
for (pre = 0; pre < ARRAY_SIZE(adc5_prescale_ratios); pre++)
if (adc5_prescale_ratios[pre].num == num &&
adc5_prescale_ratios[pre].den == den)
break;
if (pre == ARRAY_SIZE(adc5_prescale_ratios))
return -EINVAL;
return pre;
}
static int adc5_hw_settle_time_from_dt(u32 value,
const unsigned int *hw_settle)
{
unsigned int i;
for (i = 0; i < VADC_HW_SETTLE_SAMPLES_MAX; i++) {
if (value == hw_settle[i])
return i;
}
return -EINVAL;
}
static int adc5_avg_samples_from_dt(u32 value)
{
if (!is_power_of_2(value) || value > ADC5_AVG_SAMPLES_MAX)
return -EINVAL;
return __ffs(value);
}
static int adc5_decimation_from_dt(u32 value,
const unsigned int *decimation)
{
unsigned int i;
for (i = 0; i < ADC5_DECIMATION_SAMPLES_MAX; i++) {
if (value == decimation[i])
return i;
}
return -EINVAL;
}
static int adc5_read_voltage_data(struct adc5_chip *adc, u16 *data)
{
int ret;
@ -511,7 +451,7 @@ static int adc_read_raw_common(struct iio_dev *indio_dev,
return ret;
ret = qcom_adc5_hw_scale(prop->scale_fn_type,
&adc5_prescale_ratios[prop->prescale],
prop->prescale,
adc->data,
adc_code_volt, val);
if (ret)
@ -717,7 +657,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
ret = of_property_read_u32(node, "qcom,decimation", &value);
if (!ret) {
ret = adc5_decimation_from_dt(value, data->decimation);
ret = qcom_adc5_decimation_from_dt(value, data->decimation);
if (ret < 0) {
dev_err(dev, "%02x invalid decimation %d\n",
chan, value);
@ -730,7 +670,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
ret = of_property_read_u32_array(node, "qcom,pre-scaling", varr, 2);
if (!ret) {
ret = adc5_prescaling_from_dt(varr[0], varr[1]);
ret = qcom_adc5_prescaling_from_dt(varr[0], varr[1]);
if (ret < 0) {
dev_err(dev, "%02x invalid pre-scaling <%d %d>\n",
chan, varr[0], varr[1]);
@ -759,11 +699,9 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
if ((dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR &&
dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR) ||
adc->data->info == &adc7_info)
ret = adc5_hw_settle_time_from_dt(value,
data->hw_settle_2);
ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_2);
else
ret = adc5_hw_settle_time_from_dt(value,
data->hw_settle_1);
ret = qcom_adc5_hw_settle_time_from_dt(value, data->hw_settle_1);
if (ret < 0) {
dev_err(dev, "%02x invalid hw-settle-time %d us\n",
@ -777,7 +715,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
ret = of_property_read_u32(node, "qcom,avg-samples", &value);
if (!ret) {
ret = adc5_avg_samples_from_dt(value);
ret = qcom_adc5_avg_samples_from_dt(value);
if (ret < 0) {
dev_err(dev, "%02x invalid avg-samples %d\n",
chan, value);
@ -870,8 +808,6 @@ static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node)
struct adc5_channel_prop prop, *chan_props;
struct device_node *child;
unsigned int index = 0;
const struct of_device_id *id;
const struct adc5_data *data;
int ret;
adc->nchannels = of_get_available_child_count(node);
@ -890,24 +826,21 @@ static int adc5_get_dt_data(struct adc5_chip *adc, struct device_node *node)
chan_props = adc->chan_props;
iio_chan = adc->iio_chans;
id = of_match_node(adc5_match_table, node);
if (id)
data = id->data;
else
data = &adc5_data_pmic;
adc->data = data;
adc->data = of_device_get_match_data(adc->dev);
if (!adc->data)
adc->data = &adc5_data_pmic;
for_each_available_child_of_node(node, child) {
ret = adc5_get_dt_channel_data(adc, &prop, child, data);
ret = adc5_get_dt_channel_data(adc, &prop, child, adc->data);
if (ret) {
of_node_put(child);
return ret;
}
prop.scale_fn_type =
data->adc_chans[prop.channel].scale_fn_type;
adc->data->adc_chans[prop.channel].scale_fn_type;
*chan_props = prop;
adc_chan = &data->adc_chans[prop.channel];
adc_chan = &adc->data->adc_chans[prop.channel];
iio_chan->channel = prop.channel;
iio_chan->datasheet_name = prop.datasheet_name;

View File

@ -7,6 +7,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/iio/adc/qcom-vadc-common.h>
#include <linux/iio/iio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@ -20,8 +21,6 @@
#include <dt-bindings/iio/qcom,spmi-vadc.h>
#include "qcom-vadc-common.h"
/* VADC register and bit definitions */
#define VADC_REVISION2 0x1
#define VADC_REVISION2_SUPPORTED_VADC 1

View File

@ -2,50 +2,61 @@
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/fixp-arith.h>
#include <linux/iio/adc/qcom-vadc-common.h>
#include <linux/math64.h>
#include <linux/log2.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/units.h>
#include "qcom-vadc-common.h"
/**
* struct vadc_map_pt - Map the graph representation for ADC channel
* @x: Represent the ADC digitized code.
* @y: Represent the physical data which can be temperature, voltage,
* resistance.
*/
struct vadc_map_pt {
s32 x;
s32 y;
};
/* Voltage to temperature */
static const struct vadc_map_pt adcmap_100k_104ef_104fb[] = {
{1758, -40},
{1742, -35},
{1719, -30},
{1691, -25},
{1654, -20},
{1608, -15},
{1551, -10},
{1483, -5},
{1404, 0},
{1315, 5},
{1218, 10},
{1114, 15},
{1007, 20},
{900, 25},
{795, 30},
{696, 35},
{605, 40},
{522, 45},
{448, 50},
{383, 55},
{327, 60},
{278, 65},
{237, 70},
{202, 75},
{172, 80},
{146, 85},
{125, 90},
{107, 95},
{92, 100},
{79, 105},
{68, 110},
{59, 115},
{51, 120},
{44, 125}
{1758, -40000 },
{1742, -35000 },
{1719, -30000 },
{1691, -25000 },
{1654, -20000 },
{1608, -15000 },
{1551, -10000 },
{1483, -5000 },
{1404, 0 },
{1315, 5000 },
{1218, 10000 },
{1114, 15000 },
{1007, 20000 },
{900, 25000 },
{795, 30000 },
{696, 35000 },
{605, 40000 },
{522, 45000 },
{448, 50000 },
{383, 55000 },
{327, 60000 },
{278, 65000 },
{237, 70000 },
{202, 75000 },
{172, 80000 },
{146, 85000 },
{125, 90000 },
{107, 95000 },
{92, 100000 },
{79, 105000 },
{68, 110000 },
{59, 115000 },
{51, 120000 },
{44, 125000 }
};
/*
@ -90,18 +101,18 @@ static const struct vadc_map_pt adcmap_100k_104ef_104fb_1875_vref[] = {
};
static const struct vadc_map_pt adcmap7_die_temp[] = {
{ 433700, 1967},
{ 473100, 1964},
{ 512400, 1957},
{ 551500, 1949},
{ 590500, 1940},
{ 629300, 1930},
{ 667900, 1921},
{ 706400, 1910},
{ 744600, 1896},
{ 782500, 1878},
{ 820100, 1859},
{ 857300, 0},
{ 857300, 160000 },
{ 820100, 140000 },
{ 782500, 120000 },
{ 744600, 100000 },
{ 706400, 80000 },
{ 667900, 60000 },
{ 629300, 40000 },
{ 590500, 20000 },
{ 551500, 0 },
{ 512400, -20000 },
{ 473100, -40000 },
{ 433700, -60000 },
};
/*
@ -278,6 +289,18 @@ static const struct vadc_map_pt adcmap7_100k[] = {
{ 2420, 130048 }
};
static const struct vadc_prescale_ratio adc5_prescale_ratios[] = {
{.num = 1, .den = 1},
{.num = 1, .den = 3},
{.num = 1, .den = 4},
{.num = 1, .den = 6},
{.num = 1, .den = 20},
{.num = 1, .den = 8},
{.num = 10, .den = 81},
{.num = 1, .den = 10},
{.num = 1, .den = 16}
};
static int qcom_vadc_scale_hw_calib_volt(
const struct vadc_prescale_ratio *prescale,
const struct adc5_data *data,
@ -323,43 +346,23 @@ static struct qcom_adc5_scale_type scale_adc5_fn[] = {
static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts,
u32 tablesize, s32 input, int *output)
{
bool descending = 1;
u32 i = 0;
if (!pts)
return -EINVAL;
/* Check if table is descending or ascending */
if (tablesize > 1) {
if (pts[0].x < pts[1].x)
descending = 0;
}
while (i < tablesize) {
if ((descending) && (pts[i].x < input)) {
/* table entry is less than measured*/
/* value and table is descending, stop */
break;
} else if ((!descending) &&
(pts[i].x > input)) {
/* table entry is greater than measured*/
/*value and table is ascending, stop */
break;
}
while (i < tablesize && pts[i].x > input)
i++;
}
if (i == 0) {
*output = pts[0].y;
} else if (i == tablesize) {
*output = pts[tablesize - 1].y;
} else {
/* result is between search_index and search_index-1 */
/* interpolate linearly */
*output = (((s32)((pts[i].y - pts[i - 1].y) *
(input - pts[i - 1].x)) /
(pts[i].x - pts[i - 1].x)) +
pts[i - 1].y);
*output = fixp_linear_interpolate(pts[i - 1].x, pts[i - 1].y,
pts[i].x, pts[i].y,
input);
}
return 0;
@ -415,8 +418,6 @@ static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph,
if (ret)
return ret;
*result_mdec *= 1000;
return 0;
}
@ -563,33 +564,13 @@ static int qcom_vadc7_scale_hw_calib_die_temp(
u16 adc_code, int *result_mdec)
{
int voltage, vtemp0, temp, i;
int voltage;
voltage = qcom_vadc_scale_code_voltage_factor(adc_code,
prescale, data, 1);
if (adcmap7_die_temp[0].x > voltage) {
*result_mdec = DIE_TEMP_ADC7_SCALE_1;
return 0;
}
if (adcmap7_die_temp[ARRAY_SIZE(adcmap7_die_temp) - 1].x <= voltage) {
*result_mdec = DIE_TEMP_ADC7_MAX;
return 0;
}
for (i = 0; i < ARRAY_SIZE(adcmap7_die_temp); i++)
if (adcmap7_die_temp[i].x > voltage)
break;
vtemp0 = adcmap7_die_temp[i - 1].x;
voltage = voltage - vtemp0;
temp = div64_s64(voltage * DIE_TEMP_ADC7_SCALE_FACTOR,
adcmap7_die_temp[i - 1].y);
temp += DIE_TEMP_ADC7_SCALE_1 + (DIE_TEMP_ADC7_SCALE_2 * (i - 1));
*result_mdec = temp;
return 0;
return qcom_vadc_map_voltage_temp(adcmap7_die_temp, ARRAY_SIZE(adcmap7_die_temp),
voltage, result_mdec);
}
static int qcom_vadc_scale_hw_smb_temp(
@ -647,10 +628,12 @@ int qcom_vadc_scale(enum vadc_scale_fn_type scaletype,
EXPORT_SYMBOL(qcom_vadc_scale);
int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
const struct vadc_prescale_ratio *prescale,
unsigned int prescale_ratio,
const struct adc5_data *data,
u16 adc_code, int *result)
{
const struct vadc_prescale_ratio *prescale = &adc5_prescale_ratios[prescale_ratio];
if (!(scaletype >= SCALE_HW_CALIB_DEFAULT &&
scaletype < SCALE_HW_CALIB_INVALID)) {
pr_err("Invalid scale type %d\n", scaletype);
@ -662,6 +645,58 @@ int qcom_adc5_hw_scale(enum vadc_scale_fn_type scaletype,
}
EXPORT_SYMBOL(qcom_adc5_hw_scale);
int qcom_adc5_prescaling_from_dt(u32 num, u32 den)
{
unsigned int pre;
for (pre = 0; pre < ARRAY_SIZE(adc5_prescale_ratios); pre++)
if (adc5_prescale_ratios[pre].num == num &&
adc5_prescale_ratios[pre].den == den)
break;
if (pre == ARRAY_SIZE(adc5_prescale_ratios))
return -EINVAL;
return pre;
}
EXPORT_SYMBOL(qcom_adc5_prescaling_from_dt);
int qcom_adc5_hw_settle_time_from_dt(u32 value,
const unsigned int *hw_settle)
{
unsigned int i;
for (i = 0; i < VADC_HW_SETTLE_SAMPLES_MAX; i++) {
if (value == hw_settle[i])
return i;
}
return -EINVAL;
}
EXPORT_SYMBOL(qcom_adc5_hw_settle_time_from_dt);
int qcom_adc5_avg_samples_from_dt(u32 value)
{
if (!is_power_of_2(value) || value > ADC5_AVG_SAMPLES_MAX)
return -EINVAL;
return __ffs(value);
}
EXPORT_SYMBOL(qcom_adc5_avg_samples_from_dt);
int qcom_adc5_decimation_from_dt(u32 value, const unsigned int *decimation)
{
unsigned int i;
for (i = 0; i < ADC5_DECIMATION_SAMPLES_MAX; i++) {
if (value == decimation[i])
return i;
}
return -EINVAL;
}
EXPORT_SYMBOL(qcom_adc5_decimation_from_dt);
int qcom_vadc_decimation_from_dt(u32 value)
{
if (!is_power_of_2(value) || value < VADC_DECIMATION_MIN ||

View File

@ -307,7 +307,7 @@ static int sc27xx_adc_convert_volt(struct sc27xx_adc_data *data, int channel,
sc27xx_adc_volt_ratio(data, channel, scale, &numerator, &denominator);
return (volt * denominator + numerator / 2) / numerator;
return DIV_ROUND_CLOSEST(volt * denominator, numerator);
}
static int sc27xx_adc_read_processed(struct sc27xx_adc_data *data,

View File

@ -535,20 +535,16 @@ static int stm32_adc_core_hw_start(struct device *dev)
goto err_switches_dis;
}
if (priv->bclk) {
ret = clk_prepare_enable(priv->bclk);
if (ret < 0) {
dev_err(dev, "bus clk enable failed\n");
goto err_regulator_disable;
}
ret = clk_prepare_enable(priv->bclk);
if (ret < 0) {
dev_err(dev, "bus clk enable failed\n");
goto err_regulator_disable;
}
if (priv->aclk) {
ret = clk_prepare_enable(priv->aclk);
if (ret < 0) {
dev_err(dev, "adc clk enable failed\n");
goto err_bclk_disable;
}
ret = clk_prepare_enable(priv->aclk);
if (ret < 0) {
dev_err(dev, "adc clk enable failed\n");
goto err_bclk_disable;
}
writel_relaxed(priv->ccr_bak, priv->common.base + priv->cfg->regs->ccr);
@ -556,8 +552,7 @@ static int stm32_adc_core_hw_start(struct device *dev)
return 0;
err_bclk_disable:
if (priv->bclk)
clk_disable_unprepare(priv->bclk);
clk_disable_unprepare(priv->bclk);
err_regulator_disable:
regulator_disable(priv->vref);
err_switches_dis:
@ -575,10 +570,8 @@ static void stm32_adc_core_hw_stop(struct device *dev)
/* Backup CCR that may be lost (depends on power state to achieve) */
priv->ccr_bak = readl_relaxed(priv->common.base + priv->cfg->regs->ccr);
if (priv->aclk)
clk_disable_unprepare(priv->aclk);
if (priv->bclk)
clk_disable_unprepare(priv->bclk);
clk_disable_unprepare(priv->aclk);
clk_disable_unprepare(priv->bclk);
regulator_disable(priv->vref);
stm32_adc_core_switches_supply_dis(priv);
regulator_disable(priv->vdda);

View File

@ -546,8 +546,7 @@ static int stm32_adc_hw_stop(struct device *dev)
if (adc->cfg->unprepare)
adc->cfg->unprepare(indio_dev);
if (adc->clk)
clk_disable_unprepare(adc->clk);
clk_disable_unprepare(adc->clk);
return 0;
}
@ -558,11 +557,9 @@ static int stm32_adc_hw_start(struct device *dev)
struct stm32_adc *adc = iio_priv(indio_dev);
int ret;
if (adc->clk) {
ret = clk_prepare_enable(adc->clk);
if (ret)
return ret;
}
ret = clk_prepare_enable(adc->clk);
if (ret)
return ret;
stm32_adc_set_res(adc);
@ -575,8 +572,7 @@ static int stm32_adc_hw_start(struct device *dev)
return 0;
err_clk_dis:
if (adc->clk)
clk_disable_unprepare(adc->clk);
clk_disable_unprepare(adc->clk);
return ret;
}

View File

@ -117,8 +117,7 @@ static void stm32_dfsdm_clk_disable_unprepare(struct stm32_dfsdm *dfsdm)
{
struct dfsdm_priv *priv = to_stm32_dfsdm_priv(dfsdm);
if (priv->aclk)
clk_disable_unprepare(priv->aclk);
clk_disable_unprepare(priv->aclk);
clk_disable_unprepare(priv->clk);
}

View File

@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/overflow.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
@ -92,7 +93,12 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
#define XADC_AXI_REG_GIER 0x5c
#define XADC_AXI_REG_IPISR 0x60
#define XADC_AXI_REG_IPIER 0x68
#define XADC_AXI_ADC_REG_OFFSET 0x200
/* 7 Series */
#define XADC_7S_AXI_ADC_REG_OFFSET 0x200
/* UltraScale */
#define XADC_US_AXI_ADC_REG_OFFSET 0x400
#define XADC_AXI_RESET_MAGIC 0xa
#define XADC_AXI_GIER_ENABLE BIT(31)
@ -447,6 +453,12 @@ static const struct xadc_ops xadc_zynq_ops = {
.get_dclk_rate = xadc_zynq_get_dclk_rate,
.interrupt_handler = xadc_zynq_interrupt_handler,
.update_alarm = xadc_zynq_update_alarm,
.type = XADC_TYPE_S7,
};
static const unsigned int xadc_axi_reg_offsets[] = {
[XADC_TYPE_S7] = XADC_7S_AXI_ADC_REG_OFFSET,
[XADC_TYPE_US] = XADC_US_AXI_ADC_REG_OFFSET,
};
static int xadc_axi_read_adc_reg(struct xadc *xadc, unsigned int reg,
@ -454,7 +466,8 @@ static int xadc_axi_read_adc_reg(struct xadc *xadc, unsigned int reg,
{
uint32_t val32;
xadc_read_reg(xadc, XADC_AXI_ADC_REG_OFFSET + reg * 4, &val32);
xadc_read_reg(xadc, xadc_axi_reg_offsets[xadc->ops->type] + reg * 4,
&val32);
*val = val32 & 0xffff;
return 0;
@ -463,7 +476,8 @@ static int xadc_axi_read_adc_reg(struct xadc *xadc, unsigned int reg,
static int xadc_axi_write_adc_reg(struct xadc *xadc, unsigned int reg,
uint16_t val)
{
xadc_write_reg(xadc, XADC_AXI_ADC_REG_OFFSET + reg * 4, val);
xadc_write_reg(xadc, xadc_axi_reg_offsets[xadc->ops->type] + reg * 4,
val);
return 0;
}
@ -541,7 +555,7 @@ static unsigned long xadc_axi_get_dclk(struct xadc *xadc)
return clk_get_rate(xadc->clk);
}
static const struct xadc_ops xadc_axi_ops = {
static const struct xadc_ops xadc_7s_axi_ops = {
.read = xadc_axi_read_adc_reg,
.write = xadc_axi_write_adc_reg,
.setup = xadc_axi_setup,
@ -549,6 +563,18 @@ static const struct xadc_ops xadc_axi_ops = {
.update_alarm = xadc_axi_update_alarm,
.interrupt_handler = xadc_axi_interrupt_handler,
.flags = XADC_FLAGS_BUFFERED,
.type = XADC_TYPE_S7,
};
static const struct xadc_ops xadc_us_axi_ops = {
.read = xadc_axi_read_adc_reg,
.write = xadc_axi_write_adc_reg,
.setup = xadc_axi_setup,
.get_dclk_rate = xadc_axi_get_dclk,
.update_alarm = xadc_axi_update_alarm,
.interrupt_handler = xadc_axi_interrupt_handler,
.flags = XADC_FLAGS_BUFFERED,
.type = XADC_TYPE_US,
};
static int _xadc_update_adc_reg(struct xadc *xadc, unsigned int reg,
@ -585,15 +611,22 @@ static int xadc_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *mask)
{
struct xadc *xadc = iio_priv(indio_dev);
unsigned int n;
size_t new_size, n;
void *data;
n = bitmap_weight(mask, indio_dev->masklength);
kfree(xadc->data);
xadc->data = kcalloc(n, sizeof(*xadc->data), GFP_KERNEL);
if (!xadc->data)
if (check_mul_overflow(n, sizeof(*xadc->data), &new_size))
return -ENOMEM;
data = devm_krealloc(indio_dev->dev.parent, xadc->data,
new_size, GFP_KERNEL);
if (!data)
return -ENOMEM;
memset(data, 0, new_size);
xadc->data = data;
return 0;
}
@ -705,11 +738,12 @@ static const struct iio_trigger_ops xadc_trigger_ops = {
static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev,
const char *name)
{
struct device *dev = indio_dev->dev.parent;
struct iio_trigger *trig;
int ret;
trig = iio_trigger_alloc("%s%d-%s", indio_dev->name,
indio_dev->id, name);
trig = devm_iio_trigger_alloc(dev, "%s%d-%s", indio_dev->name,
indio_dev->id, name);
if (trig == NULL)
return ERR_PTR(-ENOMEM);
@ -717,21 +751,26 @@ static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev,
trig->ops = &xadc_trigger_ops;
iio_trigger_set_drvdata(trig, iio_priv(indio_dev));
ret = iio_trigger_register(trig);
ret = devm_iio_trigger_register(dev, trig);
if (ret)
goto error_free_trig;
return ERR_PTR(ret);
return trig;
error_free_trig:
iio_trigger_free(trig);
return ERR_PTR(ret);
}
static int xadc_power_adc_b(struct xadc *xadc, unsigned int seq_mode)
{
uint16_t val;
/*
* As per datasheet the power-down bits are don't care in the
* UltraScale, but as per reality setting the power-down bit for the
* non-existing ADC-B powers down the main ADC, so just return and don't
* do anything.
*/
if (xadc->ops->type == XADC_TYPE_US)
return 0;
/* Powerdown the ADC-B when it is not needed. */
switch (seq_mode) {
case XADC_CONF1_SEQ_SIMULTANEOUS:
@ -751,6 +790,10 @@ static int xadc_get_seq_mode(struct xadc *xadc, unsigned long scan_mode)
{
unsigned int aux_scan_mode = scan_mode >> 16;
/* UltraScale has only one ADC and supports only continuous mode */
if (xadc->ops->type == XADC_TYPE_US)
return XADC_CONF1_SEQ_CONTINUOUS;
if (xadc->external_mux_mode == XADC_EXTERNAL_MUX_DUAL)
return XADC_CONF1_SEQ_SIMULTANEOUS;
@ -863,6 +906,7 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int *val, int *val2, long info)
{
struct xadc *xadc = iio_priv(indio_dev);
unsigned int bits = chan->scan_type.realbits;
uint16_t val16;
int ret;
@ -874,17 +918,17 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
val16 >>= 4;
val16 >>= chan->scan_type.shift;
if (chan->scan_type.sign == 'u')
*val = val16;
else
*val = sign_extend32(val16, 11);
*val = sign_extend32(val16, bits - 1);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_VOLTAGE:
/* V = (val * 3.0) / 4096 */
/* V = (val * 3.0) / 2**bits */
switch (chan->address) {
case XADC_REG_VCCINT:
case XADC_REG_VCCAUX:
@ -900,19 +944,19 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
*val = 1000;
break;
}
*val2 = 12;
*val2 = chan->scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
case IIO_TEMP:
/* Temp in C = (val * 503.975) / 4096 - 273.15 */
/* Temp in C = (val * 503.975) / 2**bits - 273.15 */
*val = 503975;
*val2 = 12;
*val2 = bits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_OFFSET:
/* Only the temperature channel has an offset */
*val = -((273150 << 12) / 503975);
*val = -((273150 << bits) / 503975);
return IIO_VAL_INT;
case IIO_CHAN_INFO_SAMP_FREQ:
ret = xadc_read_samplerate(xadc);
@ -1001,7 +1045,7 @@ static const struct iio_event_spec xadc_voltage_events[] = {
},
};
#define XADC_CHAN_TEMP(_chan, _scan_index, _addr) { \
#define XADC_CHAN_TEMP(_chan, _scan_index, _addr, _bits) { \
.type = IIO_TEMP, \
.indexed = 1, \
.channel = (_chan), \
@ -1015,14 +1059,14 @@ static const struct iio_event_spec xadc_voltage_events[] = {
.scan_index = (_scan_index), \
.scan_type = { \
.sign = 'u', \
.realbits = 12, \
.realbits = (_bits), \
.storagebits = 16, \
.shift = 4, \
.shift = 16 - (_bits), \
.endianness = IIO_CPU, \
}, \
}
#define XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, _ext, _alarm) { \
#define XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, _bits, _ext, _alarm) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = (_chan), \
@ -1035,41 +1079,82 @@ static const struct iio_event_spec xadc_voltage_events[] = {
.scan_index = (_scan_index), \
.scan_type = { \
.sign = ((_addr) == XADC_REG_VREFN) ? 's' : 'u', \
.realbits = 12, \
.realbits = (_bits), \
.storagebits = 16, \
.shift = 4, \
.shift = 16 - (_bits), \
.endianness = IIO_CPU, \
}, \
.extend_name = _ext, \
}
static const struct iio_chan_spec xadc_channels[] = {
XADC_CHAN_TEMP(0, 8, XADC_REG_TEMP),
XADC_CHAN_VOLTAGE(0, 9, XADC_REG_VCCINT, "vccint", true),
XADC_CHAN_VOLTAGE(1, 10, XADC_REG_VCCAUX, "vccaux", true),
XADC_CHAN_VOLTAGE(2, 14, XADC_REG_VCCBRAM, "vccbram", true),
XADC_CHAN_VOLTAGE(3, 5, XADC_REG_VCCPINT, "vccpint", true),
XADC_CHAN_VOLTAGE(4, 6, XADC_REG_VCCPAUX, "vccpaux", true),
XADC_CHAN_VOLTAGE(5, 7, XADC_REG_VCCO_DDR, "vccoddr", true),
XADC_CHAN_VOLTAGE(6, 12, XADC_REG_VREFP, "vrefp", false),
XADC_CHAN_VOLTAGE(7, 13, XADC_REG_VREFN, "vrefn", false),
XADC_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, NULL, false),
XADC_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), NULL, false),
XADC_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), NULL, false),
XADC_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), NULL, false),
XADC_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), NULL, false),
XADC_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), NULL, false),
XADC_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), NULL, false),
XADC_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), NULL, false),
XADC_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), NULL, false),
XADC_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), NULL, false),
XADC_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), NULL, false),
XADC_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), NULL, false),
XADC_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), NULL, false),
XADC_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), NULL, false),
XADC_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), NULL, false),
XADC_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), NULL, false),
XADC_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), NULL, false),
/* 7 Series */
#define XADC_7S_CHAN_TEMP(_chan, _scan_index, _addr) \
XADC_CHAN_TEMP(_chan, _scan_index, _addr, 12)
#define XADC_7S_CHAN_VOLTAGE(_chan, _scan_index, _addr, _ext, _alarm) \
XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, 12, _ext, _alarm)
static const struct iio_chan_spec xadc_7s_channels[] = {
XADC_7S_CHAN_TEMP(0, 8, XADC_REG_TEMP),
XADC_7S_CHAN_VOLTAGE(0, 9, XADC_REG_VCCINT, "vccint", true),
XADC_7S_CHAN_VOLTAGE(1, 10, XADC_REG_VCCAUX, "vccaux", true),
XADC_7S_CHAN_VOLTAGE(2, 14, XADC_REG_VCCBRAM, "vccbram", true),
XADC_7S_CHAN_VOLTAGE(3, 5, XADC_REG_VCCPINT, "vccpint", true),
XADC_7S_CHAN_VOLTAGE(4, 6, XADC_REG_VCCPAUX, "vccpaux", true),
XADC_7S_CHAN_VOLTAGE(5, 7, XADC_REG_VCCO_DDR, "vccoddr", true),
XADC_7S_CHAN_VOLTAGE(6, 12, XADC_REG_VREFP, "vrefp", false),
XADC_7S_CHAN_VOLTAGE(7, 13, XADC_REG_VREFN, "vrefn", false),
XADC_7S_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, NULL, false),
XADC_7S_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), NULL, false),
XADC_7S_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), NULL, false),
XADC_7S_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), NULL, false),
XADC_7S_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), NULL, false),
XADC_7S_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), NULL, false),
XADC_7S_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), NULL, false),
XADC_7S_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), NULL, false),
XADC_7S_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), NULL, false),
XADC_7S_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), NULL, false),
XADC_7S_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), NULL, false),
XADC_7S_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), NULL, false),
XADC_7S_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), NULL, false),
XADC_7S_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), NULL, false),
XADC_7S_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), NULL, false),
XADC_7S_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), NULL, false),
XADC_7S_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), NULL, false),
};
/* UltraScale */
#define XADC_US_CHAN_TEMP(_chan, _scan_index, _addr) \
XADC_CHAN_TEMP(_chan, _scan_index, _addr, 10)
#define XADC_US_CHAN_VOLTAGE(_chan, _scan_index, _addr, _ext, _alarm) \
XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, 10, _ext, _alarm)
static const struct iio_chan_spec xadc_us_channels[] = {
XADC_US_CHAN_TEMP(0, 8, XADC_REG_TEMP),
XADC_US_CHAN_VOLTAGE(0, 9, XADC_REG_VCCINT, "vccint", true),
XADC_US_CHAN_VOLTAGE(1, 10, XADC_REG_VCCAUX, "vccaux", true),
XADC_US_CHAN_VOLTAGE(2, 14, XADC_REG_VCCBRAM, "vccbram", true),
XADC_US_CHAN_VOLTAGE(3, 5, XADC_REG_VCCPINT, "vccpsintlp", true),
XADC_US_CHAN_VOLTAGE(4, 6, XADC_REG_VCCPAUX, "vccpsintfp", true),
XADC_US_CHAN_VOLTAGE(5, 7, XADC_REG_VCCO_DDR, "vccpsaux", true),
XADC_US_CHAN_VOLTAGE(6, 12, XADC_REG_VREFP, "vrefp", false),
XADC_US_CHAN_VOLTAGE(7, 13, XADC_REG_VREFN, "vrefn", false),
XADC_US_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, NULL, false),
XADC_US_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), NULL, false),
XADC_US_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), NULL, false),
XADC_US_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), NULL, false),
XADC_US_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), NULL, false),
XADC_US_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), NULL, false),
XADC_US_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), NULL, false),
XADC_US_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), NULL, false),
XADC_US_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), NULL, false),
XADC_US_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), NULL, false),
XADC_US_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), NULL, false),
XADC_US_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), NULL, false),
XADC_US_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), NULL, false),
XADC_US_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), NULL, false),
XADC_US_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), NULL, false),
XADC_US_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), NULL, false),
XADC_US_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), NULL, false),
};
static const struct iio_info xadc_info = {
@ -1083,8 +1168,16 @@ static const struct iio_info xadc_info = {
};
static const struct of_device_id xadc_of_match_table[] = {
{ .compatible = "xlnx,zynq-xadc-1.00.a", (void *)&xadc_zynq_ops },
{ .compatible = "xlnx,axi-xadc-1.00.a", (void *)&xadc_axi_ops },
{
.compatible = "xlnx,zynq-xadc-1.00.a",
.data = &xadc_zynq_ops
}, {
.compatible = "xlnx,axi-xadc-1.00.a",
.data = &xadc_7s_axi_ops
}, {
.compatible = "xlnx,system-management-wiz-1.3",
.data = &xadc_us_axi_ops
},
{ },
};
MODULE_DEVICE_TABLE(of, xadc_of_match_table);
@ -1094,8 +1187,10 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
{
struct device *dev = indio_dev->dev.parent;
struct xadc *xadc = iio_priv(indio_dev);
const struct iio_chan_spec *channel_templates;
struct iio_chan_spec *channels, *chan;
struct device_node *chan_node, *child;
unsigned int max_channels;
unsigned int num_channels;
const char *external_mux;
u32 ext_mux_chan;
@ -1136,9 +1231,15 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
*conf |= XADC_CONF0_MUX | XADC_CONF0_CHAN(ext_mux_chan);
}
channels = devm_kmemdup(dev, xadc_channels,
sizeof(xadc_channels), GFP_KERNEL);
if (xadc->ops->type == XADC_TYPE_S7) {
channel_templates = xadc_7s_channels;
max_channels = ARRAY_SIZE(xadc_7s_channels);
} else {
channel_templates = xadc_us_channels;
max_channels = ARRAY_SIZE(xadc_us_channels);
}
channels = devm_kmemdup(dev, channel_templates,
sizeof(channels[0]) * max_channels, GFP_KERNEL);
if (!channels)
return -ENOMEM;
@ -1148,7 +1249,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
chan_node = of_get_child_by_name(np, "xlnx,channels");
if (chan_node) {
for_each_child_of_node(chan_node, child) {
if (num_channels >= ARRAY_SIZE(xadc_channels)) {
if (num_channels >= max_channels) {
of_node_put(child);
break;
}
@ -1184,8 +1285,28 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
return 0;
}
static const char * const xadc_type_names[] = {
[XADC_TYPE_S7] = "xadc",
[XADC_TYPE_US] = "xilinx-system-monitor",
};
static void xadc_clk_disable_unprepare(void *data)
{
struct clk *clk = data;
clk_disable_unprepare(clk);
}
static void xadc_cancel_delayed_work(void *data)
{
struct delayed_work *work = data;
cancel_delayed_work_sync(work);
}
static int xadc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *id;
struct iio_dev *indio_dev;
unsigned int bipolar_mask;
@ -1195,10 +1316,10 @@ static int xadc_probe(struct platform_device *pdev)
int irq;
int i;
if (!pdev->dev.of_node)
if (!dev->of_node)
return -ENODEV;
id = of_match_node(xadc_of_match_table, pdev->dev.of_node);
id = of_match_node(xadc_of_match_table, dev->of_node);
if (!id)
return -EINVAL;
@ -1206,7 +1327,7 @@ static int xadc_probe(struct platform_device *pdev)
if (irq <= 0)
return -ENXIO;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*xadc));
indio_dev = devm_iio_device_alloc(dev, sizeof(*xadc));
if (!indio_dev)
return -ENOMEM;
@ -1222,43 +1343,44 @@ static int xadc_probe(struct platform_device *pdev)
if (IS_ERR(xadc->base))
return PTR_ERR(xadc->base);
indio_dev->name = "xadc";
indio_dev->name = xadc_type_names[xadc->ops->type];
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &xadc_info;
ret = xadc_parse_dt(indio_dev, pdev->dev.of_node, &conf0);
ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0);
if (ret)
return ret;
if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
ret = iio_triggered_buffer_setup(indio_dev,
&iio_pollfunc_store_time, &xadc_trigger_handler,
&xadc_buffer_ops);
ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
&iio_pollfunc_store_time,
&xadc_trigger_handler,
&xadc_buffer_ops);
if (ret)
return ret;
xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst");
if (IS_ERR(xadc->convst_trigger)) {
ret = PTR_ERR(xadc->convst_trigger);
goto err_triggered_buffer_cleanup;
}
if (IS_ERR(xadc->convst_trigger))
return PTR_ERR(xadc->convst_trigger);
xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev,
"samplerate");
if (IS_ERR(xadc->samplerate_trigger)) {
ret = PTR_ERR(xadc->samplerate_trigger);
goto err_free_convst_trigger;
}
if (IS_ERR(xadc->samplerate_trigger))
return PTR_ERR(xadc->samplerate_trigger);
}
xadc->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(xadc->clk)) {
ret = PTR_ERR(xadc->clk);
goto err_free_samplerate_trigger;
}
xadc->clk = devm_clk_get(dev, NULL);
if (IS_ERR(xadc->clk))
return PTR_ERR(xadc->clk);
ret = clk_prepare_enable(xadc->clk);
if (ret)
goto err_free_samplerate_trigger;
return ret;
ret = devm_add_action_or_reset(dev,
xadc_clk_disable_unprepare, xadc->clk);
if (ret)
return ret;
/*
* Make sure not to exceed the maximum samplerate since otherwise the
@ -1267,22 +1389,28 @@ static int xadc_probe(struct platform_device *pdev)
if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
ret = xadc_read_samplerate(xadc);
if (ret < 0)
goto err_free_samplerate_trigger;
return ret;
if (ret > XADC_MAX_SAMPLERATE) {
ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE);
if (ret < 0)
goto err_free_samplerate_trigger;
return ret;
}
}
ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
dev_name(&pdev->dev), indio_dev);
ret = devm_request_irq(dev, xadc->irq, xadc->ops->interrupt_handler, 0,
dev_name(dev), indio_dev);
if (ret)
goto err_clk_disable_unprepare;
return ret;
ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work,
&xadc->zynq_unmask_work);
if (ret)
return ret;
ret = xadc->ops->setup(pdev, indio_dev, xadc->irq);
if (ret)
goto err_free_irq;
return ret;
for (i = 0; i < 16; i++)
xadc_read_adc_reg(xadc, XADC_REG_THRESHOLD(i),
@ -1290,7 +1418,7 @@ static int xadc_probe(struct platform_device *pdev)
ret = xadc_write_adc_reg(xadc, XADC_REG_CONF0, conf0);
if (ret)
goto err_free_irq;
return ret;
bipolar_mask = 0;
for (i = 0; i < indio_dev->num_channels; i++) {
@ -1300,17 +1428,18 @@ static int xadc_probe(struct platform_device *pdev)
ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(0), bipolar_mask);
if (ret)
goto err_free_irq;
return ret;
ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(1),
bipolar_mask >> 16);
if (ret)
goto err_free_irq;
return ret;
/* Disable all alarms */
ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK,
XADC_CONF1_ALARM_MASK);
if (ret)
goto err_free_irq;
return ret;
/* Set thresholds to min/max */
for (i = 0; i < 16; i++) {
@ -1325,60 +1454,17 @@ static int xadc_probe(struct platform_device *pdev)
ret = xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i),
xadc->threshold[i]);
if (ret)
goto err_free_irq;
return ret;
}
/* Go to non-buffered mode */
xadc_postdisable(indio_dev);
ret = iio_device_register(indio_dev);
if (ret)
goto err_free_irq;
platform_set_drvdata(pdev, indio_dev);
return 0;
err_free_irq:
free_irq(xadc->irq, indio_dev);
cancel_delayed_work_sync(&xadc->zynq_unmask_work);
err_clk_disable_unprepare:
clk_disable_unprepare(xadc->clk);
err_free_samplerate_trigger:
if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
iio_trigger_free(xadc->samplerate_trigger);
err_free_convst_trigger:
if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
iio_trigger_free(xadc->convst_trigger);
err_triggered_buffer_cleanup:
if (xadc->ops->flags & XADC_FLAGS_BUFFERED)
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
static int xadc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct xadc *xadc = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
iio_trigger_free(xadc->samplerate_trigger);
iio_trigger_free(xadc->convst_trigger);
iio_triggered_buffer_cleanup(indio_dev);
}
free_irq(xadc->irq, indio_dev);
cancel_delayed_work_sync(&xadc->zynq_unmask_work);
clk_disable_unprepare(xadc->clk);
kfree(xadc->data);
return 0;
return devm_iio_device_register(dev, indio_dev);
}
static struct platform_driver xadc_driver = {
.probe = xadc_probe,
.remove = xadc_remove,
.driver = {
.name = "xadc",
.of_match_table = xadc_of_match_table,

View File

@ -155,9 +155,6 @@ int xadc_write_event_config(struct iio_dev *indio_dev,
return ret;
}
/* Register value is msb aligned, the lower 4 bits are ignored */
#define XADC_THRESHOLD_VALUE_SHIFT 4
int xadc_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
@ -177,7 +174,8 @@ int xadc_read_event_value(struct iio_dev *indio_dev,
return -EINVAL;
}
*val >>= XADC_THRESHOLD_VALUE_SHIFT;
/* MSB aligned */
*val >>= 16 - chan->scan_type.realbits;
return IIO_VAL_INT;
}
@ -191,7 +189,8 @@ int xadc_write_event_value(struct iio_dev *indio_dev,
struct xadc *xadc = iio_priv(indio_dev);
int ret = 0;
val <<= XADC_THRESHOLD_VALUE_SHIFT;
/* MSB aligned */
val <<= 16 - chan->scan_type.realbits;
if (val < 0 || val > 0xffff)
return -EINVAL;

View File

@ -70,6 +70,11 @@ struct xadc {
int irq;
};
enum xadc_type {
XADC_TYPE_S7, /* Series 7 */
XADC_TYPE_US, /* UltraScale and UltraScale+ */
};
struct xadc_ops {
int (*read)(struct xadc *xadc, unsigned int reg, uint16_t *val);
int (*write)(struct xadc *xadc, unsigned int reg, uint16_t val);
@ -80,6 +85,7 @@ struct xadc_ops {
irqreturn_t (*interrupt_handler)(int irq, void *devid);
unsigned int flags;
enum xadc_type type;
};
static inline int _xadc_read_adc_reg(struct xadc *xadc, unsigned int reg,

View File

@ -479,7 +479,7 @@ static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp)
var4 = (var3 / (calib->res_heat_range + 4));
var5 = 131 * calib->res_heat_val + 65536;
heatr_res_x100 = ((var4 / var5) - 250) * 34;
heatr_res = (heatr_res_x100 + 50) / 100;
heatr_res = DIV_ROUND_CLOSEST(heatr_res_x100, 100);
return heatr_res;
}

View File

@ -282,7 +282,7 @@ static int pms7003_probe(struct serdev_device *serdev)
state->serdev = serdev;
indio_dev->info = &pms7003_info;
indio_dev->name = PMS7003_DRIVER_NAME;
indio_dev->channels = pms7003_channels,
indio_dev->channels = pms7003_channels;
indio_dev->num_channels = ARRAY_SIZE(pms7003_channels);
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->available_scan_masks = pms7003_scan_masks;

View File

@ -71,6 +71,8 @@ static struct {
{HID_USAGE_SENSOR_TEMPERATURE, HID_USAGE_SENSOR_UNITS_DEGREES, 1000, 0},
{HID_USAGE_SENSOR_HUMIDITY, 0, 1000, 0},
{HID_USAGE_SENSOR_HINGE, 0, 0, 17453293},
{HID_USAGE_SENSOR_HINGE, HID_USAGE_SENSOR_UNITS_DEGREES, 0, 17453293},
};
static void simple_div(int dividend, int divisor, int *whole,

View File

@ -488,24 +488,20 @@ int ms_sensors_ht_read_humidity(struct ms_ht_dev *dev_data,
EXPORT_SYMBOL(ms_sensors_ht_read_humidity);
/**
* ms_sensors_tp_crc_valid() - CRC check function for
* ms_sensors_tp_crc4() - Calculate PROM CRC for
* Temperature and pressure devices.
* This function is only used when reading PROM coefficients
*
* @prom: pointer to PROM coefficients array
* @len: length of PROM coefficients array
*
* Return: True if CRC is ok.
* Return: CRC.
*/
static bool ms_sensors_tp_crc_valid(u16 *prom, u8 len)
static u8 ms_sensors_tp_crc4(u16 *prom)
{
unsigned int cnt, n_bit;
u16 n_rem = 0x0000, crc_read = prom[0], crc = (*prom & 0xF000) >> 12;
u16 n_rem = 0x0000;
prom[len - 1] = 0;
prom[0] &= 0x0FFF; /* Clear the CRC computation part */
for (cnt = 0; cnt < len * 2; cnt++) {
for (cnt = 0; cnt < MS_SENSORS_TP_PROM_WORDS_NB * 2; cnt++) {
if (cnt % 2 == 1)
n_rem ^= prom[cnt >> 1] & 0x00FF;
else
@ -518,10 +514,55 @@ static bool ms_sensors_tp_crc_valid(u16 *prom, u8 len)
n_rem <<= 1;
}
}
n_rem >>= 12;
prom[0] = crc_read;
return n_rem == crc;
return n_rem >> 12;
}
/**
* ms_sensors_tp_crc_valid_112() - CRC check function for
* Temperature and pressure devices for 112bit PROM.
* This function is only used when reading PROM coefficients
*
* @prom: pointer to PROM coefficients array
*
* Return: True if CRC is ok.
*/
static bool ms_sensors_tp_crc_valid_112(u16 *prom)
{
u16 w0 = prom[0], crc_read = (w0 & 0xF000) >> 12;
u8 crc;
prom[0] &= 0x0FFF; /* Clear the CRC computation part */
prom[MS_SENSORS_TP_PROM_WORDS_NB - 1] = 0;
crc = ms_sensors_tp_crc4(prom);
prom[0] = w0;
return crc == crc_read;
}
/**
* ms_sensors_tp_crc_valid_128() - CRC check function for
* Temperature and pressure devices for 128bit PROM.
* This function is only used when reading PROM coefficients
*
* @prom: pointer to PROM coefficients array
*
* Return: True if CRC is ok.
*/
static bool ms_sensors_tp_crc_valid_128(u16 *prom)
{
u16 w7 = prom[7], crc_read = w7 & 0x000F;
u8 crc;
prom[7] &= 0xFF00; /* Clear the CRC and LSB part */
crc = ms_sensors_tp_crc4(prom);
prom[7] = w7;
return crc == crc_read;
}
/**
@ -536,8 +577,9 @@ static bool ms_sensors_tp_crc_valid(u16 *prom, u8 len)
int ms_sensors_tp_read_prom(struct ms_tp_dev *dev_data)
{
int i, ret;
bool valid;
for (i = 0; i < MS_SENSORS_TP_PROM_WORDS_NB; i++) {
for (i = 0; i < dev_data->hw->prom_len; i++) {
ret = ms_sensors_read_prom_word(
dev_data->client,
MS_SENSORS_TP_PROM_READ + (i << 1),
@ -547,8 +589,12 @@ int ms_sensors_tp_read_prom(struct ms_tp_dev *dev_data)
return ret;
}
if (!ms_sensors_tp_crc_valid(dev_data->prom,
MS_SENSORS_TP_PROM_WORDS_NB + 1)) {
if (dev_data->hw->prom_len == 8)
valid = ms_sensors_tp_crc_valid_128(dev_data->prom);
else
valid = ms_sensors_tp_crc_valid_112(dev_data->prom);
if (!valid) {
dev_err(&dev_data->client->dev,
"Calibration coefficients crc check error\n");
return -ENODEV;

View File

@ -11,7 +11,7 @@
#include <linux/i2c.h>
#include <linux/mutex.h>
#define MS_SENSORS_TP_PROM_WORDS_NB 7
#define MS_SENSORS_TP_PROM_WORDS_NB 8
/**
* struct ms_ht_dev - Humidity/Temperature sensor device structure
@ -25,6 +25,16 @@ struct ms_ht_dev {
u8 res_index;
};
/**
* struct ms_hw_data - Temperature/Pressure sensor hardware data
* @prom_len: number of words in the PROM
* @max_res_index: maximum sensor resolution index
*/
struct ms_tp_hw_data {
u8 prom_len;
u8 max_res_index;
};
/**
* struct ms_tp_dev - Temperature/Pressure sensor device structure
* @client: i2c client
@ -36,7 +46,8 @@ struct ms_ht_dev {
struct ms_tp_dev {
struct i2c_client *client;
struct mutex lock;
u16 prom[MS_SENSORS_TP_PROM_WORDS_NB + 1];
const struct ms_tp_hw_data *hw;
u16 prom[MS_SENSORS_TP_PROM_WORDS_NB];
u8 res_index;
};

View File

@ -189,6 +189,16 @@ config AD5764
To compile this driver as a module, choose M here: the
module will be called ad5764.
config AD5766
tristate "Analog Devices AD5766/AD5767 DAC driver"
depends on SPI_MASTER
help
Say yes here to build support for Analog Devices AD5766, AD5767
Digital to Analog Converter.
To compile this driver as a module, choose M here: the
module will be called ad5766.
config AD5770R
tristate "Analog Devices AD5770R IDAC driver"
depends on SPI_MASTER

View File

@ -19,6 +19,7 @@ obj-$(CONFIG_AD5755) += ad5755.o
obj-$(CONFIG_AD5755) += ad5758.o
obj-$(CONFIG_AD5761) += ad5761.o
obj-$(CONFIG_AD5764) += ad5764.o
obj-$(CONFIG_AD5766) += ad5766.o
obj-$(CONFIG_AD5770R) += ad5770r.o
obj-$(CONFIG_AD5791) += ad5791.o
obj-$(CONFIG_AD5686) += ad5686.o

643
drivers/iio/dac/ad5766.c Normal file
View File

@ -0,0 +1,643 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Analog Devices AD5766, AD5767
* Digital to Analog Converters driver
* Copyright 2019-2020 Analog Devices Inc.
*/
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <asm/unaligned.h>
#define AD5766_UPPER_WORD_SPI_MASK GENMASK(31, 16)
#define AD5766_LOWER_WORD_SPI_MASK GENMASK(15, 0)
#define AD5766_DITHER_SOURCE_MASK(ch) GENMASK(((2 * ch) + 1), (2 * ch))
#define AD5766_DITHER_SOURCE(ch, source) BIT((ch * 2) + source)
#define AD5766_DITHER_SCALE_MASK(x) AD5766_DITHER_SOURCE_MASK(x)
#define AD5766_DITHER_SCALE(ch, scale) (scale << (ch * 2))
#define AD5766_DITHER_ENABLE_MASK(ch) BIT(ch)
#define AD5766_DITHER_ENABLE(ch, state) ((!state) << ch)
#define AD5766_DITHER_INVERT_MASK(ch) BIT(ch)
#define AD5766_DITHER_INVERT(ch, state) (state << ch)
#define AD5766_CMD_NOP_MUX_OUT 0x00
#define AD5766_CMD_SDO_CNTRL 0x01
#define AD5766_CMD_WR_IN_REG(x) (0x10 | ((x) & GENMASK(3, 0)))
#define AD5766_CMD_WR_DAC_REG(x) (0x20 | ((x) & GENMASK(3, 0)))
#define AD5766_CMD_SW_LDAC 0x30
#define AD5766_CMD_SPAN_REG 0x40
#define AD5766_CMD_WR_PWR_DITHER 0x51
#define AD5766_CMD_WR_DAC_REG_ALL 0x60
#define AD5766_CMD_SW_FULL_RESET 0x70
#define AD5766_CMD_READBACK_REG(x) (0x80 | ((x) & GENMASK(3, 0)))
#define AD5766_CMD_DITHER_SIG_1 0x90
#define AD5766_CMD_DITHER_SIG_2 0xA0
#define AD5766_CMD_INV_DITHER 0xB0
#define AD5766_CMD_DITHER_SCALE_1 0xC0
#define AD5766_CMD_DITHER_SCALE_2 0xD0
#define AD5766_FULL_RESET_CODE 0x1234
enum ad5766_type {
ID_AD5766,
ID_AD5767,
};
enum ad5766_voltage_range {
AD5766_VOLTAGE_RANGE_M20V_0V,
AD5766_VOLTAGE_RANGE_M16V_to_0V,
AD5766_VOLTAGE_RANGE_M10V_to_0V,
AD5766_VOLTAGE_RANGE_M12V_to_14V,
AD5766_VOLTAGE_RANGE_M16V_to_10V,
AD5766_VOLTAGE_RANGE_M10V_to_6V,
AD5766_VOLTAGE_RANGE_M5V_to_5V,
AD5766_VOLTAGE_RANGE_M10V_to_10V,
};
/**
* struct ad5766_chip_info - chip specific information
* @num_channels: number of channels
* @channels: channel specification
*/
struct ad5766_chip_info {
unsigned int num_channels;
const struct iio_chan_spec *channels;
};
enum {
AD5766_DITHER_ENABLE,
AD5766_DITHER_INVERT,
AD5766_DITHER_SOURCE,
};
/*
* Dither signal can also be scaled.
* Available dither scale strings corresponding to "dither_scale" field in
* "struct ad5766_state".
*/
static const char * const ad5766_dither_scales[] = {
"1",
"0.75",
"0.5",
"0.25",
};
/**
* struct ad5766_state - driver instance specific data
* @spi: SPI device
* @lock: Lock used to restrict concurent access to SPI device
* @chip_info: Chip model specific constants
* @gpio_reset: Reset GPIO, used to reset the device
* @crt_range: Current selected output range
* @dither_enable: Power enable bit for each channel dither block (for
* example, D15 = DAC 15,D8 = DAC 8, and D0 = DAC 0)
* 0 - Normal operation, 1 - Power down
* @dither_invert: Inverts the dither signal applied to the selected DAC
* outputs
* @dither_source: Selects between 2 possible sources:
* 1: N0, 2: N1
* Two bits are used for each channel
* @dither_scale: Two bits are used for each of the 16 channels:
* 0: 1 SCALING, 1: 0.75 SCALING, 2: 0.5 SCALING,
* 3: 0.25 SCALING.
* @data: SPI transfer buffers
*/
struct ad5766_state {
struct spi_device *spi;
struct mutex lock;
const struct ad5766_chip_info *chip_info;
struct gpio_desc *gpio_reset;
enum ad5766_voltage_range crt_range;
u16 dither_enable;
u16 dither_invert;
u32 dither_source;
u32 dither_scale;
union {
u32 d32;
u16 w16[2];
u8 b8[4];
} data[3] ____cacheline_aligned;
};
struct ad5766_span_tbl {
int min;
int max;
};
static const struct ad5766_span_tbl ad5766_span_tbl[] = {
[AD5766_VOLTAGE_RANGE_M20V_0V] = {-20, 0},
[AD5766_VOLTAGE_RANGE_M16V_to_0V] = {-16, 0},
[AD5766_VOLTAGE_RANGE_M10V_to_0V] = {-10, 0},
[AD5766_VOLTAGE_RANGE_M12V_to_14V] = {-12, 14},
[AD5766_VOLTAGE_RANGE_M16V_to_10V] = {-16, 10},
[AD5766_VOLTAGE_RANGE_M10V_to_6V] = {-10, 6},
[AD5766_VOLTAGE_RANGE_M5V_to_5V] = {-5, 5},
[AD5766_VOLTAGE_RANGE_M10V_to_10V] = {-10, 10},
};
static int __ad5766_spi_read(struct ad5766_state *st, u8 dac, int *val)
{
int ret;
struct spi_transfer xfers[] = {
{
.tx_buf = &st->data[0].d32,
.bits_per_word = 8,
.len = 3,
.cs_change = 1,
}, {
.tx_buf = &st->data[1].d32,
.rx_buf = &st->data[2].d32,
.bits_per_word = 8,
.len = 3,
},
};
st->data[0].d32 = AD5766_CMD_READBACK_REG(dac);
st->data[1].d32 = AD5766_CMD_NOP_MUX_OUT;
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
if (ret)
return ret;
*val = st->data[2].w16[1];
return ret;
}
static int __ad5766_spi_write(struct ad5766_state *st, u8 command, u16 data)
{
st->data[0].b8[0] = command;
put_unaligned_be16(data, &st->data[0].b8[1]);
return spi_write(st->spi, &st->data[0].b8[0], 3);
}
static int ad5766_read(struct iio_dev *indio_dev, u8 dac, int *val)
{
struct ad5766_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->lock);
ret = __ad5766_spi_read(st, dac, val);
mutex_unlock(&st->lock);
return ret;
}
static int ad5766_write(struct iio_dev *indio_dev, u8 dac, u16 data)
{
struct ad5766_state *st = iio_priv(indio_dev);
int ret;
mutex_lock(&st->lock);
ret = __ad5766_spi_write(st, AD5766_CMD_WR_DAC_REG(dac), data);
mutex_unlock(&st->lock);
return ret;
}
static int ad5766_reset(struct ad5766_state *st)
{
int ret;
if (st->gpio_reset) {
gpiod_set_value_cansleep(st->gpio_reset, 1);
ndelay(100); /* t_reset >= 100ns */
gpiod_set_value_cansleep(st->gpio_reset, 0);
} else {
ret = __ad5766_spi_write(st, AD5766_CMD_SW_FULL_RESET,
AD5766_FULL_RESET_CODE);
if (ret < 0)
return ret;
}
/*
* Minimum time between a reset and the subsequent successful write is
* typically 25 ns
*/
ndelay(25);
return 0;
}
static int ad5766_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long m)
{
struct ad5766_state *st = iio_priv(indio_dev);
int ret;
switch (m) {
case IIO_CHAN_INFO_RAW:
ret = ad5766_read(indio_dev, chan->address, val);
if (ret)
return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
*val = ad5766_span_tbl[st->crt_range].min;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = ad5766_span_tbl[st->crt_range].max -
ad5766_span_tbl[st->crt_range].min;
*val2 = st->chip_info->channels[0].scan_type.realbits;
return IIO_VAL_FRACTIONAL_LOG2;
default:
return -EINVAL;
}
}
static int ad5766_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val,
int val2,
long info)
{
switch (info) {
case IIO_CHAN_INFO_RAW:
{
const int max_val = GENMASK(chan->scan_type.realbits - 1, 0);
if (val > max_val || val < 0)
return -EINVAL;
val <<= chan->scan_type.shift;
return ad5766_write(indio_dev, chan->address, val);
}
default:
return -EINVAL;
}
}
static const struct iio_info ad5766_info = {
.read_raw = ad5766_read_raw,
.write_raw = ad5766_write_raw,
};
static int ad5766_get_dither_source(struct iio_dev *dev,
const struct iio_chan_spec *chan)
{
struct ad5766_state *st = iio_priv(dev);
u32 source;
source = st->dither_source & AD5766_DITHER_SOURCE_MASK(chan->channel);
source = source >> (chan->channel * 2);
source -= 1;
return source;
}
static int ad5766_set_dither_source(struct iio_dev *dev,
const struct iio_chan_spec *chan,
unsigned int source)
{
struct ad5766_state *st = iio_priv(dev);
uint16_t val;
int ret;
st->dither_source &= ~AD5766_DITHER_SOURCE_MASK(chan->channel);
st->dither_source |= AD5766_DITHER_SOURCE(chan->channel, source);
val = FIELD_GET(AD5766_LOWER_WORD_SPI_MASK, st->dither_source);
ret = ad5766_write(dev, AD5766_CMD_DITHER_SIG_1, val);
if (ret)
return ret;
val = FIELD_GET(AD5766_UPPER_WORD_SPI_MASK, st->dither_source);
return ad5766_write(dev, AD5766_CMD_DITHER_SIG_2, val);
}
static int ad5766_get_dither_scale(struct iio_dev *dev,
const struct iio_chan_spec *chan)
{
struct ad5766_state *st = iio_priv(dev);
u32 scale;
scale = st->dither_scale & AD5766_DITHER_SCALE_MASK(chan->channel);
return (scale >> (chan->channel * 2));
}
static int ad5766_set_dither_scale(struct iio_dev *dev,
const struct iio_chan_spec *chan,
unsigned int scale)
{
int ret;
struct ad5766_state *st = iio_priv(dev);
uint16_t val;
st->dither_scale &= ~AD5766_DITHER_SCALE_MASK(chan->channel);
st->dither_scale |= AD5766_DITHER_SCALE(chan->channel, scale);
val = FIELD_GET(AD5766_LOWER_WORD_SPI_MASK, st->dither_scale);
ret = ad5766_write(dev, AD5766_CMD_DITHER_SCALE_1, val);
if (ret)
return ret;
val = FIELD_GET(AD5766_UPPER_WORD_SPI_MASK, st->dither_scale);
return ad5766_write(dev, AD5766_CMD_DITHER_SCALE_2, val);
}
static const struct iio_enum ad5766_dither_scale_enum = {
.items = ad5766_dither_scales,
.num_items = ARRAY_SIZE(ad5766_dither_scales),
.set = ad5766_set_dither_scale,
.get = ad5766_get_dither_scale,
};
static ssize_t ad5766_read_ext(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
char *buf)
{
struct ad5766_state *st = iio_priv(indio_dev);
switch (private) {
case AD5766_DITHER_ENABLE:
return sprintf(buf, "%u\n",
!(st->dither_enable & BIT(chan->channel)));
break;
case AD5766_DITHER_INVERT:
return sprintf(buf, "%u\n",
!!(st->dither_invert & BIT(chan->channel)));
break;
case AD5766_DITHER_SOURCE:
return sprintf(buf, "%d\n",
ad5766_get_dither_source(indio_dev, chan));
default:
return -EINVAL;
}
}
static ssize_t ad5766_write_ext(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
const char *buf, size_t len)
{
struct ad5766_state *st = iio_priv(indio_dev);
bool readin;
int ret;
ret = kstrtobool(buf, &readin);
if (ret)
return ret;
switch (private) {
case AD5766_DITHER_ENABLE:
st->dither_enable &= ~AD5766_DITHER_ENABLE_MASK(chan->channel);
st->dither_enable |= AD5766_DITHER_ENABLE(chan->channel,
readin);
ret = ad5766_write(indio_dev, AD5766_CMD_WR_PWR_DITHER,
st->dither_enable);
break;
case AD5766_DITHER_INVERT:
st->dither_invert &= ~AD5766_DITHER_INVERT_MASK(chan->channel);
st->dither_invert |= AD5766_DITHER_INVERT(chan->channel,
readin);
ret = ad5766_write(indio_dev, AD5766_CMD_INV_DITHER,
st->dither_invert);
break;
case AD5766_DITHER_SOURCE:
ret = ad5766_set_dither_source(indio_dev, chan, readin);
break;
default:
return -EINVAL;
}
return ret ? ret : len;
}
#define _AD5766_CHAN_EXT_INFO(_name, _what, _shared) { \
.name = _name, \
.read = ad5766_read_ext, \
.write = ad5766_write_ext, \
.private = _what, \
.shared = _shared, \
}
#define IIO_ENUM_AVAILABLE_SHARED(_name, _shared, _e) \
{ \
.name = (_name "_available"), \
.shared = _shared, \
.read = iio_enum_available_read, \
.private = (uintptr_t)(_e), \
}
static const struct iio_chan_spec_ext_info ad5766_ext_info[] = {
_AD5766_CHAN_EXT_INFO("dither_enable", AD5766_DITHER_ENABLE,
IIO_SEPARATE),
_AD5766_CHAN_EXT_INFO("dither_invert", AD5766_DITHER_INVERT,
IIO_SEPARATE),
_AD5766_CHAN_EXT_INFO("dither_source", AD5766_DITHER_SOURCE,
IIO_SEPARATE),
IIO_ENUM("dither_scale", IIO_SEPARATE, &ad5766_dither_scale_enum),
IIO_ENUM_AVAILABLE_SHARED("dither_scale",
IIO_SEPARATE,
&ad5766_dither_scale_enum),
{}
};
#define AD576x_CHANNEL(_chan, _bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.output = 1, \
.channel = (_chan), \
.address = (_chan), \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | \
BIT(IIO_CHAN_INFO_SCALE), \
.scan_type = { \
.sign = 'u', \
.realbits = (_bits), \
.storagebits = 16, \
.shift = 16 - (_bits), \
}, \
.ext_info = ad5766_ext_info, \
}
#define DECLARE_AD576x_CHANNELS(_name, _bits) \
const struct iio_chan_spec _name[] = { \
AD576x_CHANNEL(0, (_bits)), \
AD576x_CHANNEL(1, (_bits)), \
AD576x_CHANNEL(2, (_bits)), \
AD576x_CHANNEL(3, (_bits)), \
AD576x_CHANNEL(4, (_bits)), \
AD576x_CHANNEL(5, (_bits)), \
AD576x_CHANNEL(6, (_bits)), \
AD576x_CHANNEL(7, (_bits)), \
AD576x_CHANNEL(8, (_bits)), \
AD576x_CHANNEL(9, (_bits)), \
AD576x_CHANNEL(10, (_bits)), \
AD576x_CHANNEL(11, (_bits)), \
AD576x_CHANNEL(12, (_bits)), \
AD576x_CHANNEL(13, (_bits)), \
AD576x_CHANNEL(14, (_bits)), \
AD576x_CHANNEL(15, (_bits)), \
}
static DECLARE_AD576x_CHANNELS(ad5766_channels, 16);
static DECLARE_AD576x_CHANNELS(ad5767_channels, 12);
static const struct ad5766_chip_info ad5766_chip_infos[] = {
[ID_AD5766] = {
.num_channels = ARRAY_SIZE(ad5766_channels),
.channels = ad5766_channels,
},
[ID_AD5767] = {
.num_channels = ARRAY_SIZE(ad5767_channels),
.channels = ad5767_channels,
},
};
static int ad5766_get_output_range(struct ad5766_state *st)
{
int i, ret, min, max, tmp[2];
ret = device_property_read_u32_array(&st->spi->dev,
"output-range-voltage",
tmp, 2);
if (ret)
return ret;
min = tmp[0] / 1000;
max = tmp[1] / 1000;
for (i = 0; i < ARRAY_SIZE(ad5766_span_tbl); i++) {
if (ad5766_span_tbl[i].min != min ||
ad5766_span_tbl[i].max != max)
continue;
st->crt_range = i;
return 0;
}
return -EINVAL;
}
static int ad5766_default_setup(struct ad5766_state *st)
{
uint16_t val;
int ret, i;
/* Always issue a reset before writing to the span register. */
ret = ad5766_reset(st);
if (ret)
return ret;
ret = ad5766_get_output_range(st);
if (ret)
return ret;
/* Dither power down */
st->dither_enable = GENMASK(15, 0);
ret = __ad5766_spi_write(st, AD5766_CMD_WR_PWR_DITHER,
st->dither_enable);
if (ret)
return ret;
st->dither_source = 0;
for (i = 0; i < ARRAY_SIZE(ad5766_channels); i++)
st->dither_source |= AD5766_DITHER_SOURCE(i, 0);
val = FIELD_GET(AD5766_LOWER_WORD_SPI_MASK, st->dither_source);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SIG_1, val);
if (ret)
return ret;
val = FIELD_GET(AD5766_UPPER_WORD_SPI_MASK, st->dither_source);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SIG_2, val);
if (ret)
return ret;
st->dither_scale = 0;
val = FIELD_GET(AD5766_LOWER_WORD_SPI_MASK, st->dither_scale);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SCALE_1, val);
if (ret)
return ret;
val = FIELD_GET(AD5766_UPPER_WORD_SPI_MASK, st->dither_scale);
ret = __ad5766_spi_write(st, AD5766_CMD_DITHER_SCALE_2, val);
if (ret)
return ret;
st->dither_invert = 0;
ret = __ad5766_spi_write(st, AD5766_CMD_INV_DITHER, st->dither_invert);
if (ret)
return ret;
return __ad5766_spi_write(st, AD5766_CMD_SPAN_REG, st->crt_range);
}
static int ad5766_probe(struct spi_device *spi)
{
enum ad5766_type type;
struct iio_dev *indio_dev;
struct ad5766_state *st;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
mutex_init(&st->lock);
st->spi = spi;
type = spi_get_device_id(spi)->driver_data;
st->chip_info = &ad5766_chip_infos[type];
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
indio_dev->info = &ad5766_info;
indio_dev->dev.parent = &spi->dev;
indio_dev->dev.of_node = spi->dev.of_node;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->modes = INDIO_DIRECT_MODE;
st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(st->gpio_reset))
return PTR_ERR(st->gpio_reset);
ret = ad5766_default_setup(st);
if (ret)
return ret;
return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct of_device_id ad5766_dt_match[] = {
{ .compatible = "adi,ad5766" },
{ .compatible = "adi,ad5767" },
{}
};
MODULE_DEVICE_TABLE(of, ad5766_dt_match);
static const struct spi_device_id ad5766_spi_ids[] = {
{ "ad5766", ID_AD5766 },
{ "ad5767", ID_AD5767 },
{}
};
MODULE_DEVICE_TABLE(spi, ad5766_spi_ids);
static struct spi_driver ad5766_driver = {
.driver = {
.name = "ad5766",
.of_match_table = ad5766_dt_match,
},
.probe = ad5766_probe,
.id_table = ad5766_spi_ids,
};
module_spi_driver(ad5766_driver);
MODULE_AUTHOR("Denis-Gabriel Gheorghescu <denis.gheorghescu@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5766/AD5767 DACs");
MODULE_LICENSE("GPL v2");

View File

@ -582,8 +582,7 @@ static int adf4350_probe(struct spi_device *spi)
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
error_disable_clk:
if (clk)
clk_disable_unprepare(clk);
clk_disable_unprepare(clk);
return ret;
}
@ -599,8 +598,7 @@ static int adf4350_remove(struct spi_device *spi)
iio_device_unregister(indio_dev);
if (st->clk)
clk_disable_unprepare(st->clk);
clk_disable_unprepare(st->clk);
if (!IS_ERR(reg))
regulator_disable(reg);

View File

@ -19,6 +19,7 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include "bmg160.h"
#define BMG160_IRQ_NAME "bmg160_event"
@ -92,6 +93,7 @@
struct bmg160_data {
struct regmap *regmap;
struct regulator_bulk_data regulators[2];
struct iio_trigger *dready_trig;
struct iio_trigger *motion_trig;
struct iio_mount_matrix orientation;
@ -1061,6 +1063,13 @@ static const char *bmg160_match_acpi_device(struct device *dev)
return dev_name(dev);
}
static void bmg160_disable_regulators(void *d)
{
struct bmg160_data *data = d;
regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
}
int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name)
{
@ -1077,6 +1086,22 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
data->irq = irq;
data->regmap = regmap;
data->regulators[0].supply = "vdd";
data->regulators[1].supply = "vddio";
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators),
data->regulators);
if (ret)
return dev_err_probe(dev, ret, "Failed to get regulators\n");
ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
data->regulators);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, bmg160_disable_regulators, data);
if (ret)
return ret;
ret = iio_read_mount_matrix(dev, "mount-matrix",
&data->orientation);
if (ret)

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