mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
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:
commit
c979eb9d81
|
|
@ -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.
|
||||
|
|
|
|||
31
Documentation/ABI/testing/sysfs-bus-iio-dac-ad5766
Normal file
31
Documentation/ABI/testing/sysfs-bus-iio-dac-ad5766
Normal 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.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
6
Documentation/ABI/testing/sysfs-class-led-trigger-tty
Normal file
6
Documentation/ABI/testing/sysfs-class-led-trigger-tty
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
vddio-supply: true
|
||||
|
||||
mount-matrix:
|
||||
description: an optional 3x3 mounting rotation matrix.
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
63
Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml
Normal file
63
Documentation/devicetree/bindings/iio/dac/adi,ad5766.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
vddio-supply: true
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -30,6 +30,9 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
vddio-supply: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
105
Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
Normal file
105
Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
Normal 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;
|
||||
};
|
||||
};
|
||||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
65
Documentation/devicetree/bindings/usb/generic-xhci.yaml
Normal file
65
Documentation/devicetree/bindings/usb/generic-xhci.yaml
Normal 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>;
|
||||
};
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
188
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
Normal file
188
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.yaml
Normal 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;
|
||||
};
|
||||
...
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
287
Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
Normal file
287
Documentation/devicetree/bindings/usb/mediatek,mtu3.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
114
Documentation/devicetree/bindings/usb/mediatek,musb.yaml
Normal file
114
Documentation/devicetree/bindings/usb/mediatek,musb.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
- |
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
108
Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
Normal file
108
Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
Normal 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";
|
||||
};
|
||||
};
|
||||
332
Documentation/devicetree/bindings/usb/snps,dwc3.yaml
Normal file
332
Documentation/devicetree/bindings/usb/snps,dwc3.yaml
Normal 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;
|
||||
};
|
||||
...
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
124
Documentation/devicetree/bindings/usb/usb-device.yaml
Normal file
124
Documentation/devicetree/bindings/usb/usb-device.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
78
Documentation/devicetree/bindings/usb/usb-drd.yaml
Normal file
78
Documentation/devicetree/bindings/usb/usb-drd.yaml
Normal 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;
|
||||
};
|
||||
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
};
|
||||
42
Documentation/devicetree/bindings/usb/usb-xhci.yaml
Normal file
42
Documentation/devicetree/bindings/usb/usb-xhci.yaml
Normal 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;
|
||||
};
|
||||
63
Documentation/devicetree/bindings/usb/usb.yaml
Normal file
63
Documentation/devicetree/bindings/usb/usb.yaml
Normal 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
|
||||
|
||||
...
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,.*":
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ Contents:
|
|||
ethernet/index
|
||||
fddi/index
|
||||
hamradio/index
|
||||
qlogic/index
|
||||
wan/index
|
||||
wifi/index
|
||||
|
||||
|
|
|
|||
18
Documentation/networking/device_drivers/qlogic/index.rst
Normal file
18
Documentation/networking/device_drivers/qlogic/index.rst
Normal 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`
|
||||
118
Documentation/networking/device_drivers/qlogic/qlge.rst
Normal file
118
Documentation/networking/device_drivers/qlogic/qlge.rst
Normal 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.
|
||||
|
|
@ -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
|
||||
--------------------------
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
19
MAINTAINERS
19
MAINTAINERS
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
643
drivers/iio/dac/ad5766.c
Normal 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");
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue
Block a user