Merge 62a0e2fa40 ("Merge tag 'net-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net") into android-mainline
Steps on the way to 6.12-rc1 Bug: 367265496 Change-Id: I1ece105acb05b97d8cd9299ed0ee6a81a74fd353 Signed-off-by: Matthias Maennich <maennich@google.com>
This commit is contained in:
@@ -11,7 +11,7 @@ Description:
|
||||
Read returns '0' or '1' for read-write or read-only modes
|
||||
respectively.
|
||||
Write parses one of 'YyTt1NnFf0', or [oO][NnFf] for "on"
|
||||
and "off", i.e. what kstrbool() supports.
|
||||
and "off", i.e. what kstrtobool() supports.
|
||||
Note: This file is only present if CONFIG_NVMEM_SYSFS
|
||||
is enabled.
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
What: /sys/kernel/debug/iio/iio:deviceX/calibration_table_dump
|
||||
KernelVersion: 6.11
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This dumps the calibration table that was filled during the
|
||||
digital interface tuning process.
|
||||
|
||||
What: /sys/kernel/debug/iio/iio:deviceX/in_voltage_test_mode_available
|
||||
KernelVersion: 6.11
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
List all the available test tones:
|
||||
- off
|
||||
- midscale_short
|
||||
- pos_fullscale
|
||||
- neg_fullscale
|
||||
- checkerboard
|
||||
- prbs23
|
||||
- prbs9
|
||||
- one_zero_toggle
|
||||
- user
|
||||
- bit_toggle
|
||||
- sync
|
||||
- one_bit_high
|
||||
- mixed_bit_frequency
|
||||
- ramp
|
||||
|
||||
Note that depending on the actual device being used, some of the
|
||||
above might not be available (and they won't be listed when
|
||||
reading the file).
|
||||
|
||||
What: /sys/kernel/debug/iio/iio:deviceX/in_voltageY_test_mode
|
||||
KernelVersion: 6.11
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Writing to this file will initiate one of available test tone on
|
||||
channel Y. Reading it, shows which test is running. In cases
|
||||
where an IIO backend is available and supports the test tone,
|
||||
additional information about the data correctness is given.
|
||||
@@ -0,0 +1,20 @@
|
||||
What: /sys/kernel/debug/iio/iio:deviceX/backendY/name
|
||||
KernelVersion: 6.11
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Name of Backend Y connected to device X.
|
||||
|
||||
What: /sys/kernel/debug/iio/iio:deviceX/backendY/direct_reg_access
|
||||
KernelVersion: 6.11
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Directly access the registers of backend Y. Typical usage is:
|
||||
|
||||
Reading address 0x50
|
||||
echo 0x50 > direct_reg_access
|
||||
cat direct_reg_access
|
||||
|
||||
Writing address 0x50
|
||||
echo 0x50 0x3 > direct_reg_access
|
||||
//readback address 0x50
|
||||
cat direct_reg_access
|
||||
@@ -523,13 +523,27 @@ Description:
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltageY_i_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltageY_q_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_capacitance_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_resistance_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_temp_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_calibbias
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@@ -541,6 +555,10 @@ Description:
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_temp_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_calibbias_available
|
||||
KernelVersion: 5.8
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@@ -549,25 +567,34 @@ Description:
|
||||
- a small discrete set of values like "0 2 4 6 8"
|
||||
- a range specified as "[min step max]"
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_capacitance_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_both_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ir_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_calibscale
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@@ -575,6 +602,20 @@ Description:
|
||||
production inaccuracies). If shared across all channels,
|
||||
<type>_calibscale is used.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminanceY_calibscale_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_calibscale_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximityY_calibscale_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale_available
|
||||
KernelVersion: 4.8
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Available values of calibscale. Maybe expressed as either of:
|
||||
|
||||
- a small discrete set of values like "1 8 16"
|
||||
- a range specified as "[min step max]"
|
||||
|
||||
If shared across all channels, <type>_calibscale_available is used.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender
|
||||
@@ -708,6 +749,7 @@ Description:
|
||||
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
||||
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
|
||||
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
|
||||
42kohm_to_gnd: connected to ground via a 42kOhm resistor,
|
||||
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
|
||||
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
|
||||
125kohm_to_gnd: connected to ground via an 125kOhm resistor,
|
||||
@@ -2289,3 +2331,11 @@ KernelVersion: 6.7
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
List of available timeout value for tap gesture confirmation.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_shunt_resistor
|
||||
What: /sys/.../iio:deviceX/in_current_shunt_resistor
|
||||
What: /sys/.../iio:deviceX/in_power_shunt_resistor
|
||||
KernelVersion: 6.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
The value of current sense resistor in Ohms.
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_power_shunt_resistor
|
||||
Date: March 2017
|
||||
KernelVersion: 4.12
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description: The value of the shunt resistor used to compute power drain on
|
||||
common input voltage pin (RS+). In Ohms.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_current_shunt_resistor
|
||||
Date: March 2017
|
||||
KernelVersion: 4.12
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description: The value of the shunt resistor used to compute current flowing
|
||||
between RS+ and RS- voltage sense inputs. In Ohms.
|
||||
|
||||
These attributes describe a single physical component, exposed as two distinct
|
||||
attributes as it is used to calculate two different values: power load and
|
||||
current flowing between RS+ and RS- inputs.
|
||||
@@ -15,17 +15,3 @@ Description:
|
||||
Set the relative humidity. This value is sent to the sensor for
|
||||
humidity compensation.
|
||||
Default value: 50000 (50 % relative humidity)
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_resistance_calibbias
|
||||
Date: August 2021
|
||||
KernelVersion: 5.15
|
||||
Contact: Andreas Klinger <ak@it-klinger.de>
|
||||
Description:
|
||||
Set the bias value for the resistance which is used for
|
||||
calculation of in_concentration_input as follows:
|
||||
|
||||
x = (in_resistance_raw - in_resistance_calibbias) * 0.65
|
||||
|
||||
in_concentration_input = 500 / (1 + e^x)
|
||||
|
||||
Default value: 30000
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_toggle_en
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Toggle enable. Write 1 to enable toggle or 0 to disable it. This
|
||||
is useful when one wants to change the DAC output codes. For
|
||||
autonomous toggling, the way it should be done is:
|
||||
|
||||
- disable toggle operation;
|
||||
- change out_currentY_rawN, where N is the integer value of the symbol;
|
||||
- enable toggle operation.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_rawN
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute has the same meaning as out_currentY_raw. It is
|
||||
specific to toggle enabled channels and refers to the DAC output
|
||||
code in INPUT_N (_rawN), where N is the integer value of the symbol.
|
||||
The same scale and offset as in out_currentY_raw applies.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_symbol
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Performs a SW switch to a predefined output symbol. This attribute
|
||||
is specific to toggle enabled channels and allows switching between
|
||||
multiple predefined symbols. Each symbol corresponds to a different
|
||||
output, denoted as out_currentY_rawN, where N is the integer value
|
||||
of the symbol. Writing an integer value N will select out_currentY_rawN.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_toggle_en
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Toggle enable. Write 1 to enable toggle or 0 to disable it. This
|
||||
is useful when one wants to change the DAC output codes. For
|
||||
autonomous toggling, the way it should be done is:
|
||||
|
||||
- disable toggle operation;
|
||||
- change out_voltageY_rawN, where N is the integer value of the symbol;
|
||||
- enable toggle operation.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_rawN
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute has the same meaning as out_currentY_raw. It is
|
||||
specific to toggle enabled channels and refers to the DAC output
|
||||
code in INPUT_N (_rawN), where N is the integer value of the symbol.
|
||||
The same scale and offset as in out_currentY_raw applies.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_symbol
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Performs a SW switch to a predefined output symbol. This attribute
|
||||
is specific to toggle enabled channels and allows switching between
|
||||
multiple predefined symbols. Each symbol corresponds to a different
|
||||
output, denoted as out_voltageY_rawN, where N is the integer value
|
||||
of the symbol. Writing an integer value N will select out_voltageY_rawN.
|
||||
@@ -53,34 +53,3 @@ KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Returns the available values for the dither phase.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_toggle_en
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Toggle enable. Write 1 to enable toggle or 0 to disable it. This is
|
||||
useful when one wants to change the DAC output codes. The way it should
|
||||
be done is:
|
||||
|
||||
- disable toggle operation;
|
||||
- change out_voltageY_raw0 and out_voltageY_raw1;
|
||||
- enable toggle operation.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw0
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw1
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
It has the same meaning as out_voltageY_raw. This attribute is
|
||||
specific to toggle enabled channels and refers to the DAC output
|
||||
code in INPUT_A (_raw0) and INPUT_B (_raw1). The same scale and offset
|
||||
as in out_voltageY_raw applies.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_symbol
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Performs a SW toggle. This attribute is specific to toggle
|
||||
enabled channels and allows to toggle between out_voltageY_raw0
|
||||
and out_voltageY_raw1 through software. Writing 0 will select
|
||||
out_voltageY_raw0 while 1 selects out_voltageY_raw1.
|
||||
|
||||
@@ -3,7 +3,7 @@ KernelVersion:
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Reading this returns the valid values that can be written to the
|
||||
on_altvoltage0_mode attribute:
|
||||
filter_mode attribute:
|
||||
|
||||
- auto -> Adjust bandpass filter to track changes in input clock rate.
|
||||
- manual -> disable/unregister the clock rate notifier / input clock tracking.
|
||||
|
||||
@@ -13,12 +13,3 @@ Description:
|
||||
available for reading data. However, samples can be occasionally skipped
|
||||
or repeated, depending on the beat between the capture and conversion
|
||||
rates.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_shunt_resistor
|
||||
Date: December 2015
|
||||
KernelVersion: 4.4
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
The value of the shunt resistor may be known only at runtime fom an
|
||||
eeprom content read by a client application. This attribute allows to
|
||||
set its value in ohms.
|
||||
|
||||
@@ -37,6 +37,11 @@ properties:
|
||||
GPIO pin (output) used to control VBUS. If skipped, no such control
|
||||
takes place.
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
A port node to link the usb controller for the dual role switch.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
@@ -58,5 +63,11 @@ examples:
|
||||
interrupt-parent = <&msmgpio>;
|
||||
interrupts = <78 IRQ_TYPE_LEVEL_HIGH>;
|
||||
vbus-gpios = <&msmgpio 148 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&usb1_drd_sw>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
USB GPIO Extcon device
|
||||
|
||||
This is a virtual device used to generate USB cable states from the USB ID pin
|
||||
connected to a GPIO pin.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "linux,extcon-usb-gpio"
|
||||
|
||||
Either one of id-gpio or vbus-gpio must be present. Both can be present as well.
|
||||
- id-gpio: gpio for USB ID pin. See gpio binding.
|
||||
- vbus-gpio: gpio for USB VBUS pin.
|
||||
|
||||
Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
|
||||
extcon_usb1 {
|
||||
compatible = "linux,extcon-usb-gpio";
|
||||
id-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
|
||||
}
|
||||
|
||||
&omap_dwc3_1 {
|
||||
extcon = <&extcon_usb1>;
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/extcon/linux,extcon-usb-gpio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: USB GPIO Extcon device
|
||||
|
||||
maintainers:
|
||||
- Frank Li <Frank.Li@nxp.com>
|
||||
|
||||
description:
|
||||
This is a virtual device used to generate USB cable states from the USB ID pin
|
||||
connected to a GPIO pin.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: linux,extcon-usb-gpio
|
||||
|
||||
id-gpios:
|
||||
description: gpio for USB ID pin. See gpio binding.
|
||||
vbus-gpios:
|
||||
description: gpio for USB VBUS pin.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
extcon_usb1 {
|
||||
compatible = "linux,extcon-usb-gpio";
|
||||
id-gpios = <&gpio6 1 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/accel/adi,adxl380.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices ADXL380/382 3-Axis Digital Accelerometer
|
||||
|
||||
maintainers:
|
||||
- Ramona Gradinariu <ramona.gradinariu@analog.com>
|
||||
- Antoniu Miclaus <antoniu.miclaus@analog.com>
|
||||
|
||||
description: |
|
||||
The ADXL380/ADXL382 is a low noise density, low power, 3-axis
|
||||
accelerometer with selectable measurement ranges. The ADXL380
|
||||
supports the ±4 g, ±8 g, and ±16 g ranges, and the ADXL382 supports
|
||||
±15 g, ±30 g, and ±60 g ranges.
|
||||
|
||||
https://www.analog.com/en/products/adxl380.html
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,adxl380
|
||||
- adi,adxl382
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- enum: [INT0, INT1]
|
||||
- const: INT1
|
||||
|
||||
vddio-supply: true
|
||||
|
||||
vsupply-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- vddio-supply
|
||||
- vsupply-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
accelerometer@54 {
|
||||
compatible = "adi,adxl380";
|
||||
reg = <0x54>;
|
||||
vddio-supply = <&vddio>;
|
||||
vsupply-supply = <&vsupply>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <25 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "INT0";
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
accelerometer@0 {
|
||||
compatible = "adi,adxl380";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <8000000>;
|
||||
vddio-supply = <&vddio>;
|
||||
vsupply-supply = <&vsupply>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <25 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "INT0";
|
||||
};
|
||||
};
|
||||
@@ -16,6 +16,7 @@ properties:
|
||||
- kionix,kxcj91008
|
||||
- kionix,kxtj21009
|
||||
- kionix,kxtf9
|
||||
- kionix,kx022-1020
|
||||
- kionix,kx023-1025
|
||||
|
||||
reg:
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,ad4695.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices Easy Drive Multiplexed SAR Analog to Digital Converters
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <Michael.Hennerich@analog.com>
|
||||
- Nuno Sá <nuno.sa@analog.com>
|
||||
|
||||
description: |
|
||||
A family of similar multi-channel analog to digital converters with SPI bus.
|
||||
|
||||
* https://www.analog.com/en/products/ad4695.html
|
||||
* https://www.analog.com/en/products/ad4696.html
|
||||
* https://www.analog.com/en/products/ad4697.html
|
||||
* https://www.analog.com/en/products/ad4698.html
|
||||
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad4695
|
||||
- adi,ad4696
|
||||
- adi,ad4697
|
||||
- adi,ad4698
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 80000000
|
||||
|
||||
spi-cpol: true
|
||||
spi-cpha: true
|
||||
|
||||
spi-rx-bus-width:
|
||||
minimum: 1
|
||||
maximum: 4
|
||||
|
||||
avdd-supply:
|
||||
description: Analog power supply.
|
||||
|
||||
vio-supply:
|
||||
description: I/O pin power supply.
|
||||
|
||||
ldo-in-supply:
|
||||
description: Internal LDO Input. Mutually exclusive with vdd-supply.
|
||||
|
||||
vdd-supply:
|
||||
description: Core power supply. Mutually exclusive with ldo-in-supply.
|
||||
|
||||
ref-supply:
|
||||
description:
|
||||
External reference voltage. Mutually exclusive with refin-supply.
|
||||
|
||||
refin-supply:
|
||||
description:
|
||||
Internal reference buffer input. Mutually exclusive with ref-supply.
|
||||
|
||||
com-supply:
|
||||
description: Common voltage supply for pseudo-differential analog inputs.
|
||||
|
||||
adi,no-ref-current-limit:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
When this flag is present, the REF Overvoltage Reduced Current protection
|
||||
is disabled.
|
||||
|
||||
adi,no-ref-high-z:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Enable this flag if the ref-supply requires Reference Input High-Z Mode
|
||||
to be disabled for proper operation.
|
||||
|
||||
cnv-gpios:
|
||||
description: The Convert Input (CNV). If omitted, CNV is tied to SPI CS.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: The Reset Input (RESET). Should be configured GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Signal coming from the BSY_ALT_GP0 pin (ALERT or BUSY).
|
||||
- description: Signal coming from the GP2 pin (ALERT).
|
||||
- description: Signal coming from the GP3 pin (BUSY).
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: gp0
|
||||
- const: gp2
|
||||
- const: gp3
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
description: |
|
||||
The first cell is the GPn number: 0 to 3.
|
||||
The second cell takes standard GPIO flags.
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^in(?:[13579]|1[135])-supply$":
|
||||
description:
|
||||
Optional voltage supply for odd numbered channels when they are used as
|
||||
the negative input for a pseudo-differential channel.
|
||||
|
||||
"^channel@[0-9a-f]$":
|
||||
type: object
|
||||
$ref: adc.yaml
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
Describes each individual channel. In addition the properties defined
|
||||
below, bipolar from adc.yaml is also supported.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maximum: 15
|
||||
|
||||
common-mode-channel:
|
||||
description:
|
||||
Describes the common mode channel for single channels. 0xFF is REFGND
|
||||
and OxFE is COM. Macros are available for these values in
|
||||
dt-bindings/iio/adi,ad4695.h. Values 1 to 15 correspond to INx inputs.
|
||||
Only odd numbered INx inputs can be used as common mode channels.
|
||||
enum: [1, 3, 5, 7, 9, 11, 13, 15, 0xFE, 0xFF]
|
||||
default: 0xFF
|
||||
|
||||
adi,no-high-z:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Enable this flag if the input pin requires the Analog Input High-Z
|
||||
Mode to be disabled for proper operation.
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
# bipolar mode can't be used with REFGND
|
||||
- if:
|
||||
properties:
|
||||
common-mode-channel:
|
||||
const: 0xFF
|
||||
then:
|
||||
properties:
|
||||
bipolar: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- avdd-supply
|
||||
- vio-supply
|
||||
|
||||
allOf:
|
||||
- oneOf:
|
||||
- required:
|
||||
- ldo-in-supply
|
||||
- required:
|
||||
- vdd-supply
|
||||
|
||||
- oneOf:
|
||||
- required:
|
||||
- ref-supply
|
||||
- required:
|
||||
- refin-supply
|
||||
|
||||
# the internal reference buffer always requires high-z mode
|
||||
- if:
|
||||
required:
|
||||
- refin-supply
|
||||
then:
|
||||
properties:
|
||||
adi,no-ref-high-z: false
|
||||
|
||||
# limit channels for 8-channel chips
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad4697
|
||||
- adi,ad4698
|
||||
then:
|
||||
patternProperties:
|
||||
"^in(?:9|1[135])-supply$": false
|
||||
"^channel@[0-7]$":
|
||||
properties:
|
||||
reg:
|
||||
maximum: 7
|
||||
common-mode-channel:
|
||||
enum: [1, 3, 5, 7, 0xFE, 0xFF]
|
||||
"^channel@[8-9a-f]$": false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/iio/adi,ad4695.h>
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,ad4695";
|
||||
reg = <0>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
spi-max-frequency = <80000000>;
|
||||
avdd-supply = <&power_supply>;
|
||||
ldo-in-supply = <&power_supply>;
|
||||
vio-supply = <&io_supply>;
|
||||
refin-supply = <&supply_5V>;
|
||||
com-supply = <&supply_2V5>;
|
||||
in3-supply = <&supply_2V5>;
|
||||
reset-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* Pseudo-differential channel between IN0 and REFGND. */
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
/* Pseudo-differential channel between IN1 and COM. */
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
common-mode-channel = <AD4695_COMMON_MODE_COM>;
|
||||
bipolar;
|
||||
};
|
||||
|
||||
/* Pseudo-differential channel between IN2 and IN3. */
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
common-mode-channel = <3>;
|
||||
bipolar;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -39,11 +39,21 @@ properties:
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: phandle to the master clock (mclk)
|
||||
description:
|
||||
Optionally, either a crystal can be attached externally between MCLK1 and
|
||||
MCLK2 pins, or an external CMOS-compatible clock can drive the MCLK2
|
||||
pin. If absent, internal 4.92MHz clock is used, which can be made
|
||||
available on MCLK2 pin.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
enum:
|
||||
- xtal
|
||||
- mclk
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
description:
|
||||
If present when internal clock is used, configured as clock provider.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
@@ -134,8 +144,6 @@ patternProperties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- dvdd-supply
|
||||
- avdd-supply
|
||||
@@ -156,6 +164,18 @@ allOf:
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel@[0-9a-f]+$": false
|
||||
- if:
|
||||
anyOf:
|
||||
- required:
|
||||
- clocks
|
||||
- required:
|
||||
- clock-names
|
||||
then:
|
||||
properties:
|
||||
"#clock-cells": false
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
@@ -201,8 +221,7 @@ examples:
|
||||
spi-max-frequency = <1000000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
clocks = <&ad7192_mclk>;
|
||||
clock-names = "mclk";
|
||||
#clock-cells = <0>;
|
||||
interrupts = <25 0x2>;
|
||||
interrupt-parent = <&gpio>;
|
||||
aincom-supply = <&aincom>;
|
||||
|
||||
@@ -15,10 +15,17 @@ description: |
|
||||
* https://www.analog.com/en/products/ad7381.html
|
||||
* https://www.analog.com/en/products/ad7383.html
|
||||
* https://www.analog.com/en/products/ad7384.html
|
||||
* https://www.analog.com/en/products/ad7386.html
|
||||
* https://www.analog.com/en/products/ad7387.html
|
||||
* https://www.analog.com/en/products/ad7388.html
|
||||
* https://www.analog.com/en/products/ad7380-4.html
|
||||
* https://www.analog.com/en/products/ad7381-4.html
|
||||
* https://www.analog.com/en/products/ad7383-4.html
|
||||
* https://www.analog.com/en/products/ad7384-4.html
|
||||
* https://www.analog.com/en/products/ad7386-4.html
|
||||
* https://www.analog.com/en/products/ad7387-4.html
|
||||
* https://www.analog.com/en/products/ad7388-4.html
|
||||
|
||||
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
@@ -29,10 +36,16 @@ properties:
|
||||
- adi,ad7381
|
||||
- adi,ad7383
|
||||
- adi,ad7384
|
||||
- adi,ad7386
|
||||
- adi,ad7387
|
||||
- adi,ad7388
|
||||
- adi,ad7380-4
|
||||
- adi,ad7381-4
|
||||
- adi,ad7383-4
|
||||
- adi,ad7384-4
|
||||
- adi,ad7386-4
|
||||
- adi,ad7387-4
|
||||
- adi,ad7388-4
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -35,65 +35,83 @@ properties:
|
||||
|
||||
avcc-supply: true
|
||||
|
||||
vdrive-supply:
|
||||
description:
|
||||
Determines the voltage level at which the interface logic pins will
|
||||
operate.
|
||||
|
||||
refin-supply:
|
||||
description:
|
||||
The voltage supply for optional external reference voltage.
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
The BUSY pin falling edge indicates that the conversion is over, and thus
|
||||
new data is available.
|
||||
maxItems: 1
|
||||
|
||||
adi,conversion-start-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the CONVST pin.
|
||||
This logic input is used to initiate conversions on the analog
|
||||
input channels. As the line is active high, it should be marked
|
||||
GPIO_ACTIVE_HIGH.
|
||||
maxItems: 1
|
||||
Must be the device tree identifier of the CONVST pin(s). This logic input
|
||||
is used to initiate conversions on the analog input channels. As the line
|
||||
is active high, it should be marked GPIO_ACTIVE_HIGH.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the RESET pin. If specified,
|
||||
it will be asserted during driver probe. As the line is active high,
|
||||
it should be marked GPIO_ACTIVE_HIGH.
|
||||
Must be the device tree identifier of the RESET pin. If specified, it will
|
||||
be asserted during driver probe. On the AD7606x, as the line is active
|
||||
high, it should be marked GPIO_ACTIVE_HIGH. On the AD7616, as the line is
|
||||
active low, it should be marked GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
standby-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the STBY pin. This pin is used
|
||||
to place the AD7606 into one of two power-down modes, Standby mode or
|
||||
Must be the device tree identifier of the STBY pin. This pin is used to
|
||||
place the AD7606 into one of two power-down modes, Standby mode or
|
||||
Shutdown mode. As the line is active low, it should be marked
|
||||
GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
adi,first-data-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the FRSTDATA pin.
|
||||
The FRSTDATA output indicates when the first channel, V1, is
|
||||
being read back on either the parallel, byte or serial interface.
|
||||
As the line is active high, it should be marked GPIO_ACTIVE_HIGH.
|
||||
Must be the device tree identifier of the FRSTDATA pin. The FRSTDATA
|
||||
output indicates when the first channel, V1, is being read back on either
|
||||
the parallel, byte or serial interface. As the line is active high, it
|
||||
should be marked GPIO_ACTIVE_HIGH.
|
||||
maxItems: 1
|
||||
|
||||
adi,range-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the RANGE pin. The polarity on
|
||||
this pin determines the input range of the analog input channels. If
|
||||
this pin is tied to a logic high, the analog input range is ±10V for
|
||||
all channels. If this pin is tied to a logic low, the analog input range
|
||||
Must be the device tree identifier of the RANGE pin. The state on this
|
||||
pin determines the input range of the analog input channels. If this pin
|
||||
is tied to a logic high, the analog input range is ±10V for all channels.
|
||||
On the AD760X, if this pin is tied to a logic low, the analog input range
|
||||
is ±5V for all channels. As the line is active high, it should be marked
|
||||
GPIO_ACTIVE_HIGH.
|
||||
maxItems: 1
|
||||
GPIO_ACTIVE_HIGH. On the AD7616, there are 2 pins, and if the 2 pins are
|
||||
tied to a logic high, software mode is enabled, otherwise one of the 3
|
||||
possible range values is selected.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
adi,oversampling-ratio-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the over-sampling
|
||||
mode pins. As the line is active high, it should be marked
|
||||
GPIO_ACTIVE_HIGH.
|
||||
Must be the device tree identifier of the over-sampling mode pins. As the
|
||||
line is active high, it should be marked GPIO_ACTIVE_HIGH. On the AD7606X
|
||||
parts that support it, if all 3 pins are tied to a logic high, software
|
||||
mode is enabled.
|
||||
maxItems: 3
|
||||
|
||||
adi,sw-mode:
|
||||
description:
|
||||
Software mode of operation, so far available only for ad7616 and ad7606b.
|
||||
It is enabled when all three oversampling mode pins are connected to
|
||||
high level. The device is configured by the corresponding registers. If the
|
||||
adi,oversampling-ratio-gpios property is defined, then the driver will set the
|
||||
oversampling gpios to high. Otherwise, it is assumed that the pins are hardwired
|
||||
to VDD.
|
||||
Software mode of operation, so far available only for AD7616 and AD7606B.
|
||||
It is enabled when all three oversampling mode pins are connected to high
|
||||
level for the AD7606B, or both the range selection are connected to high
|
||||
level for the AD7616. The device is configured by the corresponding
|
||||
registers. If the adi,oversampling-ratio-gpios property is defined, then
|
||||
the driver will set the oversampling gpios to high. Otherwise, it is
|
||||
assumed that the pins are hardwired to VDD.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
@@ -101,12 +119,57 @@ required:
|
||||
- reg
|
||||
- spi-cpha
|
||||
- avcc-supply
|
||||
- vdrive-supply
|
||||
- interrupts
|
||||
- adi,conversion-start-gpios
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: adi,ad7616
|
||||
then:
|
||||
properties:
|
||||
adi,first-data-gpios: false
|
||||
standby-gpios: false
|
||||
adi,range-gpios:
|
||||
maxItems: 2
|
||||
else:
|
||||
properties:
|
||||
adi,range-gpios:
|
||||
maxItems: 1
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad7605-4
|
||||
- adi,ad7616
|
||||
then:
|
||||
properties:
|
||||
adi,oversampling-ratio-gpios: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad7605-4
|
||||
- adi,ad7606-4
|
||||
- adi,ad7606-6
|
||||
- adi,ad7606-8
|
||||
then:
|
||||
properties:
|
||||
adi,sw-mode: false
|
||||
else:
|
||||
properties:
|
||||
adi,conversion-start-gpios:
|
||||
maxItems: 1
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
@@ -125,6 +188,7 @@ examples:
|
||||
spi-cpha;
|
||||
|
||||
avcc-supply = <&adc_vref>;
|
||||
vdrive-supply = <&vdd_supply>;
|
||||
|
||||
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-parent = <&gpio>;
|
||||
@@ -136,7 +200,6 @@ examples:
|
||||
<&gpio 23 GPIO_ACTIVE_HIGH>,
|
||||
<&gpio 26 GPIO_ACTIVE_HIGH>;
|
||||
standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
|
||||
adi,sw-mode;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
||||
@@ -28,6 +28,9 @@ properties:
|
||||
- adi,ad9265
|
||||
- adi,ad9434
|
||||
- adi,ad9467
|
||||
- adi,ad9643
|
||||
- adi,ad9649
|
||||
- adi,ad9652
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/microchip,pac1921.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip PAC1921 High-Side Power/Current Monitor with Anaog Output
|
||||
|
||||
maintainers:
|
||||
- Matteo Martelli <matteomartelli3@gmail.com>
|
||||
|
||||
description: |
|
||||
The PAC1921 is a power/current monitoring device with an analog output
|
||||
and I2C/SMBus interface.
|
||||
|
||||
Datasheet can be found here:
|
||||
https://ww1.microchip.com/downloads/en/DeviceDoc/PAC1921-Data-Sheet-DS20005293E.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,pac1921
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
shunt-resistor-micro-ohms:
|
||||
description:
|
||||
Value in micro Ohms of the shunt resistor connected between
|
||||
the SENSE+ and SENSE- inputs, across which the current is measured.
|
||||
Value is needed to compute the scaling of the measured current.
|
||||
|
||||
label:
|
||||
description: Unique name to identify which device this is.
|
||||
|
||||
read-integrate-gpios:
|
||||
description:
|
||||
READ/INT input pin to control the current state of the device, either in
|
||||
the INTEGRATE state when driven high, or in the READ state when driven low.
|
||||
When not connected the pin is floating and it can be overridden by the
|
||||
INT_EN register bit after asserting the READ/INT_OVR register bit.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- shunt-resistor-micro-ohms
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@4c {
|
||||
compatible = "microchip,pac1921";
|
||||
reg = <0x4c>;
|
||||
vdd-supply = <&vdd>;
|
||||
#io-channel-cells = <1>;
|
||||
label = "vbat";
|
||||
shunt-resistor-micro-ohms = <10000>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -16,6 +16,9 @@ properties:
|
||||
- const: rockchip,rk3066-tsadc
|
||||
- const: rockchip,rk3399-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
- const: rockchip,rk3576-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-saradc
|
||||
|
||||
@@ -18,18 +18,39 @@ properties:
|
||||
- sd-modulator
|
||||
- ads1201
|
||||
|
||||
'#io-backend-cells':
|
||||
const: 0
|
||||
|
||||
'#io-channel-cells':
|
||||
const: 0
|
||||
|
||||
vref-supply:
|
||||
description: Phandle to the vref input analog reference voltage.
|
||||
|
||||
dependencies:
|
||||
vref-supply: [ '#io-backend-cells' ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#io-channel-cells'
|
||||
|
||||
anyOf:
|
||||
- required: ['#io-backend-cells']
|
||||
- required: ['#io-channel-cells']
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
ads1202: adc {
|
||||
// Backend binding example. SD modulator configured as an IIO backend device
|
||||
ads1201_0: adc {
|
||||
compatible = "sd-modulator";
|
||||
vref-supply = <&vdd_adc>;
|
||||
#io-backend-cells = <0>;
|
||||
};
|
||||
|
||||
- |
|
||||
// Legacy binding example. SD modulator configured as an IIO channel provider
|
||||
ads1201_1: adc {
|
||||
compatible = "sd-modulator";
|
||||
#io-channel-cells = <0>;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/sophgo,cv1800b-saradc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title:
|
||||
Sophgo CV1800B SoC 3 channels Successive Approximation Analog to
|
||||
Digital Converters
|
||||
|
||||
maintainers:
|
||||
- Thomas Bonnefille <thomas.bonnefille@bootlin.com>
|
||||
|
||||
description:
|
||||
Datasheet at https://github.com/sophgo/sophgo-doc/releases
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sophgo,cv1800b-saradc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-2]$":
|
||||
$ref: adc.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- minimum: 0
|
||||
maximum: 2
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/sophgo,cv1800.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
adc@30f0000 {
|
||||
compatible = "sophgo,cv1800b-saradc";
|
||||
reg = <0x030f0000 0x1000>;
|
||||
clocks = <&clk CLK_SARADC>;
|
||||
interrupts = <100 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
@@ -54,7 +54,9 @@ properties:
|
||||
It's not present on stm32f4.
|
||||
It's required on stm32h7 and stm32mp1.
|
||||
|
||||
clock-names: true
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
st,max-clk-rate-hz:
|
||||
description:
|
||||
|
||||
@@ -102,9 +102,11 @@ patternProperties:
|
||||
items:
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
deprecated: true
|
||||
|
||||
st,adc-channel-names:
|
||||
description: List of single-ended channel names.
|
||||
deprecated: true
|
||||
|
||||
st,filter-order:
|
||||
description: |
|
||||
@@ -118,6 +120,12 @@ patternProperties:
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
st,adc-channel-types:
|
||||
description: |
|
||||
Single-ended channel input type.
|
||||
@@ -128,6 +136,7 @@ patternProperties:
|
||||
items:
|
||||
enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
deprecated: true
|
||||
|
||||
st,adc-channel-clk-src:
|
||||
description: |
|
||||
@@ -139,6 +148,7 @@ patternProperties:
|
||||
items:
|
||||
enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
deprecated: true
|
||||
|
||||
st,adc-alt-channel:
|
||||
description:
|
||||
@@ -147,6 +157,7 @@ patternProperties:
|
||||
If not set, channel n is connected to SPI input n.
|
||||
If set, channel n is connected to SPI input n + 1.
|
||||
type: boolean
|
||||
deprecated: true
|
||||
|
||||
st,filter0-sync:
|
||||
description:
|
||||
@@ -165,11 +176,60 @@ patternProperties:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- st,adc-channels
|
||||
- st,adc-channel-names
|
||||
- st,filter-order
|
||||
- "#io-channel-cells"
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
type: object
|
||||
$ref: adc.yaml
|
||||
unevaluatedProperties: false
|
||||
description: Represents the external channels which are connected to the DFSDM.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maximum: 7
|
||||
|
||||
label:
|
||||
description:
|
||||
Unique name to identify which channel this is.
|
||||
|
||||
st,adc-channel-type:
|
||||
description: |
|
||||
Single-ended channel input type.
|
||||
- "SPI_R": SPI with data on rising edge (default)
|
||||
- "SPI_F": SPI with data on falling edge
|
||||
- "MANCH_R": manchester codec, rising edge = logic 0, falling edge = logic 1
|
||||
- "MANCH_F": manchester codec, rising edge = logic 1, falling edge = logic 0
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
|
||||
|
||||
st,adc-channel-clk-src:
|
||||
description: |
|
||||
Conversion clock source.
|
||||
- "CLKIN": external SPI clock (CLKIN x)
|
||||
- "CLKOUT": internal SPI clock (CLKOUT) (default)
|
||||
- "CLKOUT_F": internal SPI clock divided by 2 (falling edge).
|
||||
- "CLKOUT_R": internal SPI clock divided by 2 (rising edge).
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
|
||||
|
||||
st,adc-alt-channel:
|
||||
description:
|
||||
Must be defined if two sigma delta modulators are
|
||||
connected on same SPI input.
|
||||
If not set, channel n is connected to SPI input n.
|
||||
If set, channel n is connected to SPI input n + 1.
|
||||
type: boolean
|
||||
|
||||
io-backends:
|
||||
description:
|
||||
Used to pipe external sigma delta modulator or internal ADC backend to DFSDM channel.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
@@ -199,9 +259,19 @@ patternProperties:
|
||||
description:
|
||||
From common IIO binding. Used to pipe external sigma delta
|
||||
modulator or internal ADC output to DFSDM channel.
|
||||
deprecated: true
|
||||
|
||||
required:
|
||||
- io-channels
|
||||
if:
|
||||
required:
|
||||
- st,adc-channels
|
||||
then:
|
||||
required:
|
||||
- io-channels
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
required:
|
||||
- io-backends
|
||||
|
||||
- if:
|
||||
properties:
|
||||
@@ -298,6 +368,7 @@ examples:
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
// Example 1: Audio use case with generic binding
|
||||
dfsdm0: filter@0 {
|
||||
compatible = "st,stm32-dfsdm-dmic";
|
||||
reg = <0>;
|
||||
@@ -305,12 +376,18 @@ examples:
|
||||
dmas = <&dmamux1 101 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
#io-channel-cells = <1>;
|
||||
st,adc-channels = <1>;
|
||||
st,adc-channel-names = "dmic0";
|
||||
st,adc-channel-types = "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
st,filter-order = <5>;
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
label = "dmic0";
|
||||
st,adc-channel-type = "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
st,adc-alt-channel;
|
||||
};
|
||||
|
||||
asoc_pdm0: dfsdm-dai {
|
||||
compatible = "st,stm32h7-dfsdm-dai";
|
||||
#sound-dai-cells = <0>;
|
||||
@@ -318,19 +395,34 @@ examples:
|
||||
};
|
||||
};
|
||||
|
||||
dfsdm_pdm1: filter@1 {
|
||||
// Example 2: Analog use case with generic binding
|
||||
dfsdm1: filter@1 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
reg = <1>;
|
||||
interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 102 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
#io-channel-cells = <1>;
|
||||
st,adc-channels = <2 3>;
|
||||
st,adc-channel-names = "in2", "in3";
|
||||
st,adc-channel-types = "SPI_R", "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT_F", "CLKOUT_F";
|
||||
io-channels = <&sd_adc2 &sd_adc3>;
|
||||
st,filter-order = <1>;
|
||||
#io-channel-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
label = "in2";
|
||||
st,adc-channel-type = "SPI_F";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
st,adc-alt-channel;
|
||||
io-backends = <&sd_adc2>;
|
||||
};
|
||||
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
label = "in3";
|
||||
st,adc-channel-type = "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
io-backends = <&sd_adc3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -37,6 +37,17 @@ description: |
|
||||
3 | batt_dischrg_i
|
||||
4 | ts_v
|
||||
|
||||
AXP717
|
||||
------
|
||||
0 | batt_v
|
||||
1 | ts_v
|
||||
2 | vbus_v
|
||||
3 | vsys_v
|
||||
4 | pmic_temp
|
||||
5 | batt_chrg_i
|
||||
6 | vmid_v
|
||||
7 | bkup_batt_v
|
||||
|
||||
AXP813
|
||||
------
|
||||
0 | pmic_temp
|
||||
@@ -52,6 +63,7 @@ properties:
|
||||
oneOf:
|
||||
- const: x-powers,axp209-adc
|
||||
- const: x-powers,axp221-adc
|
||||
- const: x-powers,axp717-adc
|
||||
- const: x-powers,axp813-adc
|
||||
|
||||
- items:
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/dac/adi,ltc2664.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices LTC2664 DAC
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Kim Seer Paller <kimseer.paller@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices LTC2664 4 channel, 12-/16-Bit, +-10V DAC
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/2664fa.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ltc2664
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 50000000
|
||||
|
||||
vcc-supply:
|
||||
description: Analog Supply Voltage Input.
|
||||
|
||||
v-pos-supply:
|
||||
description: Positive Supply Voltage Input.
|
||||
|
||||
v-neg-supply:
|
||||
description: Negative Supply Voltage Input.
|
||||
|
||||
iovcc-supply:
|
||||
description: Digital Input/Output Supply Voltage.
|
||||
|
||||
ref-supply:
|
||||
description:
|
||||
Reference Input/Output. The voltage at the REF pin sets the full-scale
|
||||
range of all channels. If not provided the internal reference is used and
|
||||
also provided on the VREF pin.
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Active-low Asynchronous Clear Input. A logic low at this level-triggered
|
||||
input clears the part to the reset code and range determined by the
|
||||
hardwired option chosen using the MSPAN pins. The control registers are
|
||||
cleared to zero.
|
||||
maxItems: 1
|
||||
|
||||
adi,manual-span-operation-config:
|
||||
description:
|
||||
This property must mimic the MSPAN pin configurations. By tying the MSPAN
|
||||
pins (MSP2, MSP1 and MSP0) to GND and/or VCC, any output range can be
|
||||
hardware-configured with different mid-scale or zero-scale reset options.
|
||||
The hardware configuration is latched during power on reset for proper
|
||||
operation.
|
||||
0 - MPS2=GND, MPS1=GND, MSP0=GND (+-10V, reset to 0V)
|
||||
1 - MPS2=GND, MPS1=GND, MSP0=VCC (+-5V, reset to 0V)
|
||||
2 - MPS2=GND, MPS1=VCC, MSP0=GND (+-2.5V, reset to 0V)
|
||||
3 - MPS2=GND, MPS1=VCC, MSP0=VCC (0V to 10, reset to 0V)
|
||||
4 - MPS2=VCC, MPS1=GND, MSP0=GND (0V to 10V, reset to 5V)
|
||||
5 - MPS2=VCC, MPS1=GND, MSP0=VCC (0V to 5V, reset to 0V)
|
||||
6 - MPS2=VCC, MPS1=VCC, MSP0=GND (0V to 5V, reset to 2.5V)
|
||||
7 - MPS2=VCC, MPS1=VCC, MSP0=VCC (0V to 5V, reset to 0V, enables SoftSpan)
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1, 2, 3, 4, 5, 6, 7]
|
||||
default: 7
|
||||
|
||||
io-channels:
|
||||
description:
|
||||
ADC channel to monitor voltages and temperature at the MUXOUT pin.
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-3]$":
|
||||
$ref: dac.yaml
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: The channel number representing the DAC output channel.
|
||||
maximum: 3
|
||||
|
||||
adi,toggle-mode:
|
||||
description:
|
||||
Set the channel as a toggle enabled channel. Toggle operation enables
|
||||
fast switching of a DAC output between two different DAC codes without
|
||||
any SPI transaction.
|
||||
type: boolean
|
||||
|
||||
output-range-microvolt:
|
||||
description:
|
||||
This property is only allowed when SoftSpan is enabled. If not present,
|
||||
[0, 5000000] is the default output range.
|
||||
oneOf:
|
||||
- items:
|
||||
- const: 0
|
||||
- enum: [5000000, 10000000]
|
||||
- items:
|
||||
- const: -5000000
|
||||
- const: 5000000
|
||||
- items:
|
||||
- const: -10000000
|
||||
- const: 10000000
|
||||
- items:
|
||||
- const: -2500000
|
||||
- const: 2500000
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
adi,manual-span-operation-config:
|
||||
const: 7
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel@[0-3]$":
|
||||
properties:
|
||||
output-range-microvolt: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- spi-max-frequency
|
||||
- vcc-supply
|
||||
- iovcc-supply
|
||||
- v-pos-supply
|
||||
- v-neg-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dac@0 {
|
||||
compatible = "adi,ltc2664";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
vcc-supply = <&vcc>;
|
||||
iovcc-supply = <&vcc>;
|
||||
ref-supply = <&vref>;
|
||||
v-pos-supply = <&vpos>;
|
||||
v-neg-supply = <&vneg>;
|
||||
|
||||
io-channels = <&adc 0>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
adi,toggle-mode;
|
||||
output-range-microvolt = <(-10000000) 10000000>;
|
||||
};
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
output-range-microvolt= <0 10000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,160 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/dac/adi,ltc2672.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices LTC2672 DAC
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Kim Seer Paller <kimseer.paller@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices LTC2672 5 channel, 12-/16-Bit, 300mA DAC
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ltc2672.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ltc2672
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 50000000
|
||||
|
||||
vcc-supply:
|
||||
description: Analog Supply Voltage Input.
|
||||
|
||||
v-neg-supply:
|
||||
description: Negative Supply Voltage Input.
|
||||
|
||||
vdd0-supply:
|
||||
description: Positive Supply Voltage Input for DAC OUT0.
|
||||
|
||||
vdd1-supply:
|
||||
description: Positive Supply Voltage Input for DAC OUT1.
|
||||
|
||||
vdd2-supply:
|
||||
description: Positive Supply Voltage Input for DAC OUT2.
|
||||
|
||||
vdd3-supply:
|
||||
description: Positive Supply Voltage Input for DAC OUT3.
|
||||
|
||||
vdd4-supply:
|
||||
description: Positive Supply Voltage Input for DAC OUT4.
|
||||
|
||||
iovcc-supply:
|
||||
description: Digital Input/Output Supply Voltage.
|
||||
|
||||
ref-supply:
|
||||
description:
|
||||
Reference Input/Output. The voltage at the REF pin sets the full-scale
|
||||
range of all channels. If not provided the internal reference is used and
|
||||
also provided on the VREF pin.
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Active Low Asynchronous Clear Input. A logic low at this level triggered
|
||||
input clears the device to the default reset code and output range, which
|
||||
is zero-scale with the outputs off. The control registers are cleared to
|
||||
zero.
|
||||
maxItems: 1
|
||||
|
||||
adi,rfsadj-ohms:
|
||||
description:
|
||||
If FSADJ is tied to VCC, an internal RFSADJ (20 kΩ) is selected, which
|
||||
results in nominal output ranges. When an external resistor of 19 kΩ to
|
||||
41 kΩ can be used instead by connecting the resistor between FSADJ and GND
|
||||
it controls the scaling of the ranges, and the internal resistor is
|
||||
automatically disconnected.
|
||||
minimum: 19000
|
||||
maximum: 41000
|
||||
default: 20000
|
||||
|
||||
io-channels:
|
||||
description:
|
||||
ADC channel to monitor voltages and currents at the MUX pin.
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-4]$":
|
||||
$ref: dac.yaml
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: The channel number representing the DAC output channel.
|
||||
maximum: 4
|
||||
|
||||
adi,toggle-mode:
|
||||
description:
|
||||
Set the channel as a toggle enabled channel. Toggle operation enables
|
||||
fast switching of a DAC output between two different DAC codes without
|
||||
any SPI transaction.
|
||||
type: boolean
|
||||
|
||||
output-range-microamp:
|
||||
items:
|
||||
- const: 0
|
||||
- enum: [3125000, 6250000, 12500000, 25000000, 50000000, 100000000,
|
||||
200000000, 300000000]
|
||||
|
||||
required:
|
||||
- reg
|
||||
- output-range-microamp
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- spi-max-frequency
|
||||
- vcc-supply
|
||||
- iovcc-supply
|
||||
- v-neg-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dac@0 {
|
||||
compatible = "adi,ltc2672";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
|
||||
vcc-supply = <&vcc>;
|
||||
iovcc-supply = <&vcc>;
|
||||
ref-supply = <&vref>;
|
||||
v-neg-supply = <&vneg>;
|
||||
|
||||
io-channels = <&adc 0>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
adi,toggle-mode;
|
||||
output-range-microamp = <0 3125000>;
|
||||
};
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
output-range-microamp = <0 6250000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/dac/dac.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: IIO Common Properties for DAC Channels
|
||||
|
||||
maintainers:
|
||||
- Jonathan Cameron <jic23@kernel.org>
|
||||
|
||||
description:
|
||||
A few properties are defined in a common way for DAC channels.
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^channel(@[0-9a-f]+)?$"
|
||||
description:
|
||||
A channel index should match reg.
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
label:
|
||||
description: Unique name to identify which channel this is.
|
||||
|
||||
output-range-microamp:
|
||||
maxItems: 2
|
||||
minItems: 2
|
||||
description:
|
||||
Specify the channel output full scale range in microamperes.
|
||||
|
||||
output-range-microvolt:
|
||||
maxItems: 2
|
||||
minItems: 2
|
||||
description:
|
||||
Specify the channel output full scale range in microvolts.
|
||||
|
||||
anyOf:
|
||||
- oneOf:
|
||||
- required:
|
||||
- reg
|
||||
- output-range-microamp
|
||||
- required:
|
||||
- reg
|
||||
- output-range-microvolt
|
||||
- required:
|
||||
- reg
|
||||
|
||||
additionalProperties: true
|
||||
@@ -17,6 +17,7 @@ description: |
|
||||
applications.
|
||||
|
||||
https://www.analog.com/en/products/adf4377.html
|
||||
https://www.analog.com/en/products/adf4378.html
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@@ -73,6 +74,15 @@ required:
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,adf4378
|
||||
then:
|
||||
properties:
|
||||
clk2-enable-gpios: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/humidity/sciosense,ens210.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ScioSense ENS210 temperature and humidity sensor
|
||||
|
||||
maintainers:
|
||||
- Joshua Felmeden <jfelmeden@thegoodpenguin.co.uk>
|
||||
|
||||
description: |
|
||||
Temperature and Humidity sensor.
|
||||
|
||||
Datasheet:
|
||||
https://www.sciosense.com/wp-content/uploads/2024/04/ENS21x-Datasheet.pdf
|
||||
https://www.sciosense.com/wp-content/uploads/2023/12/ENS210-Datasheet.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- sciosense,ens210a
|
||||
- sciosense,ens211
|
||||
- sciosense,ens212
|
||||
- sciosense,ens213a
|
||||
- sciosense,ens215
|
||||
- const: sciosense,ens210
|
||||
- const: sciosense,ens210
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
temperature-sensor@43 {
|
||||
compatible = "sciosense,ens210";
|
||||
reg = <0x43>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
||||
@@ -14,7 +14,9 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: liteon,ltrf216a
|
||||
enum:
|
||||
- liteon,ltr308
|
||||
- liteon,ltrf216a
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bh1745.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BH1745 colour sensor
|
||||
|
||||
maintainers:
|
||||
- Mudit Sharma <muditsharma.info@gmail.com>
|
||||
|
||||
description:
|
||||
BH1745 is an I2C colour sensor with red, green, blue and clear
|
||||
channels. It has a programmable active low interrupt pin.
|
||||
Interrupt occurs when the signal from the selected interrupt
|
||||
source channel crosses set interrupt threshold high/low level.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bh1745
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
colour-sensor@38 {
|
||||
compatible = "rohm,bh1745";
|
||||
reg = <0x38>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
|
||||
vdd-supply = <&vdd>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
+5
-6
@@ -1,23 +1,22 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bu27034.yaml#
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bu27034anuc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BU27034 ambient light sensor
|
||||
title: ROHM BU27034ANUC ambient light sensor
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
ROHM BU27034 is an ambient light sesnor with 3 channels and 3 photo diodes
|
||||
ROHM BU27034ANUC is an ambient light sensor with 2 channels and 2 photo diodes
|
||||
capable of detecting a very wide range of illuminance. Typical application
|
||||
is adjusting LCD and backlight power of TVs and mobile phones.
|
||||
https://fscdn.rohm.com/en/products/databook/datasheet/ic/sensor/light/bu27034nuc-e.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bu27034
|
||||
const: rohm,bu27034anuc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -37,7 +36,7 @@ examples:
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@38 {
|
||||
compatible = "rohm,bu27034";
|
||||
compatible = "rohm,bu27034anuc";
|
||||
reg = <0x38>;
|
||||
vdd-supply = <&vdd>;
|
||||
};
|
||||
@@ -18,10 +18,15 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- sensortek,stk3310
|
||||
- sensortek,stk3311
|
||||
- sensortek,stk3335
|
||||
oneOf:
|
||||
- enum:
|
||||
- sensortek,stk3310
|
||||
- sensortek,stk3311
|
||||
- sensortek,stk3335
|
||||
- items:
|
||||
- enum:
|
||||
- sensortek,stk3013
|
||||
- const: sensortek,stk3310
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -18,12 +18,15 @@ properties:
|
||||
- asahi-kasei,ak09911
|
||||
- asahi-kasei,ak09912
|
||||
- asahi-kasei,ak09916
|
||||
- items:
|
||||
# ak09918 is register compatible with ak09912.
|
||||
- const: asahi-kasei,ak09918
|
||||
- const: asahi-kasei,ak09912
|
||||
- enum:
|
||||
- ak8975
|
||||
- ak8963
|
||||
- ak09911
|
||||
- ak09912
|
||||
- ak09916
|
||||
deprecated: true
|
||||
|
||||
reg:
|
||||
|
||||
@@ -36,6 +36,9 @@ properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
mount-matrix:
|
||||
description: an optional 3x3 mounting rotation matrix.
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/pressure/sensirion,sdp500.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: sdp500/sdp510 pressure sensor with I2C bus interface
|
||||
|
||||
maintainers:
|
||||
- Petar Stoykov <petar.stoykov@prodrive-technologies.com>
|
||||
|
||||
description: |
|
||||
Pressure sensor from Sensirion with I2C bus interface.
|
||||
There is no software difference between sdp500 and sdp510.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: sensirion,sdp510
|
||||
- const: sensirion,sdp500
|
||||
- const: sensirion,sdp500
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pressure@40 {
|
||||
compatible = "sensirion,sdp500";
|
||||
reg = <0x40>;
|
||||
vdd-supply = <&foo>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/proximity/awinic,aw96103.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Awinic's AW96103 capacitive proximity sensor and similar
|
||||
|
||||
maintainers:
|
||||
- Wang Shuaijie <wangshuaijie@awinic.com>
|
||||
|
||||
description: |
|
||||
Awinic's AW96103/AW96105 proximity sensor.
|
||||
The specific absorption rate (SAR) is a metric that measures
|
||||
the degree of absorption of electromagnetic radiation emitted by
|
||||
wireless devices, such as mobile phones and tablets, by human tissue.
|
||||
In mobile phone applications, the proximity sensor is primarily
|
||||
used to detect the proximity of the human body to the phone. When the
|
||||
phone approaches the human body, it will actively reduce the transmit
|
||||
power of the antenna to keep the SAR within a safe range. Therefore,
|
||||
we also refer to the proximity sensor as a SAR sensor.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- awinic,aw96103
|
||||
- awinic,aw96105
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
Generated by the device to announce that a close/far
|
||||
proximity event has happened.
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- vcc-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
proximity@12 {
|
||||
compatible = "awinic,aw96103";
|
||||
reg = <0x12>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
|
||||
vcc-supply = <&pp1800_prox>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/proximity/tyhx,hx9023s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TYHX HX9023S capacitive proximity sensor
|
||||
|
||||
maintainers:
|
||||
- Yasin Lee <yasin.lee.x@gmail.com>
|
||||
|
||||
description: |
|
||||
TYHX HX9023S proximity sensor. Datasheet can be found here:
|
||||
http://www.tianyihexin.com/ueditor/php/upload/file/20240614/1718336303992081.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: tyhx,hx9023s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
Generated by device to announce preceding read request has finished
|
||||
and data is available or that a close/far proximity event has happened.
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-4]$":
|
||||
$ref: /schemas/iio/adc/adc.yaml
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
description: The channel number.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
proximity@2a {
|
||||
compatible = "tyhx,hx9023s";
|
||||
reg = <0x2a>;
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
|
||||
vdd-supply = <&pp1800_prox>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
single-channel = <0>;
|
||||
};
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
single-channel = <1>;
|
||||
};
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
single-channel = <2>;
|
||||
};
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
diff-channels = <1 0>;
|
||||
};
|
||||
channel@4 {
|
||||
reg = <4>;
|
||||
diff-channels = <2 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -4,14 +4,14 @@
|
||||
$id: http://devicetree.org/schemas/interconnect/qcom,msm8939.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm MSM8939 Network-On-Chip interconnect
|
||||
title: Qualcomm MSM8937/MSM8939/MSM8976 Network-On-Chip interconnect
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konradybcio@kernel.org>
|
||||
|
||||
description: |
|
||||
The Qualcomm MSM8939 interconnect providers support adjusting the
|
||||
bandwidth requirements between the various NoC fabrics.
|
||||
description:
|
||||
The Qualcomm MSM8937/MSM8939/MSM8976 interconnect providers support
|
||||
adjusting the bandwidth requirements between the various NoC fabrics.
|
||||
|
||||
allOf:
|
||||
- $ref: qcom,rpm-common.yaml#
|
||||
@@ -19,9 +19,15 @@ allOf:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,msm8937-bimc
|
||||
- qcom,msm8937-pcnoc
|
||||
- qcom,msm8937-snoc
|
||||
- qcom,msm8939-bimc
|
||||
- qcom,msm8939-pcnoc
|
||||
- qcom,msm8939-snoc
|
||||
- qcom,msm8976-bimc
|
||||
- qcom,msm8976-pcnoc
|
||||
- qcom,msm8976-snoc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -39,7 +45,10 @@ patternProperties:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,msm8939-snoc-mm
|
||||
enum:
|
||||
- qcom,msm8937-snoc-mm
|
||||
- qcom,msm8939-snoc-mm
|
||||
- qcom,msm8976-snoc-mm
|
||||
|
||||
required:
|
||||
- compatible
|
||||
@@ -60,12 +69,6 @@ examples:
|
||||
compatible = "qcom,msm8939-snoc";
|
||||
reg = <0x00580000 0x14000>;
|
||||
#interconnect-cells = <1>;
|
||||
};
|
||||
|
||||
bimc: interconnect@400000 {
|
||||
compatible = "qcom,msm8939-bimc";
|
||||
reg = <0x00400000 0x62000>;
|
||||
#interconnect-cells = <1>;
|
||||
|
||||
snoc_mm: interconnect-snoc {
|
||||
compatible = "qcom,msm8939-snoc-mm";
|
||||
|
||||
@@ -13,8 +13,7 @@ description: |
|
||||
The Qualcomm MSM8953 interconnect providers support adjusting the
|
||||
bandwidth requirements between the various NoC fabrics.
|
||||
|
||||
See also:
|
||||
- dt-bindings/interconnect/qcom,msm8953.h
|
||||
See also: include/dt-bindings/interconnect/qcom,msm8953.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -26,6 +26,7 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,qcm2290-cpu-bwmon
|
||||
- qcom,sa8775p-cpu-bwmon
|
||||
- qcom,sc7180-cpu-bwmon
|
||||
- qcom,sc7280-cpu-bwmon
|
||||
- qcom,sc8280xp-cpu-bwmon
|
||||
@@ -39,6 +40,7 @@ properties:
|
||||
- const: qcom,sdm845-bwmon # BWMON v4, unified register space
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sa8775p-llcc-bwmon
|
||||
- qcom,sc7180-llcc-bwmon
|
||||
- qcom,sc8280xp-llcc-bwmon
|
||||
- qcom,sm6350-cpu-bwmon
|
||||
|
||||
@@ -71,7 +71,7 @@ properties:
|
||||
- qcom,sdx65-system-noc
|
||||
- qcom,sm8150-aggre1-noc
|
||||
- qcom,sm8150-aggre2-noc
|
||||
- qcom,sm8150-camnoc-noc
|
||||
- qcom,sm8150-camnoc-virt
|
||||
- qcom,sm8150-compute-noc
|
||||
- qcom,sm8150-config-noc
|
||||
- qcom,sm8150-dc-noc
|
||||
@@ -113,6 +113,9 @@ allOf:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sc8180x-camnoc-virt
|
||||
- qcom,sc8180x-mc-virt
|
||||
- qcom,sc8180x-qup-virt
|
||||
- qcom,sdx65-mc-virt
|
||||
- qcom,sm8250-qup-virt
|
||||
then:
|
||||
|
||||
@@ -26,6 +26,7 @@ properties:
|
||||
- mdsp
|
||||
- sdsp
|
||||
- cdsp
|
||||
- cdsp1
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
@@ -81,7 +82,7 @@ patternProperties:
|
||||
|
||||
iommus:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
maxItems: 10
|
||||
|
||||
qcom,nsessions:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
@@ -29,6 +29,12 @@ properties:
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
bootloader-backdoor-gpios:
|
||||
maxItems: 1
|
||||
description: |
|
||||
gpios to enable bootloader backdoor in cc1352p7 bootloader to allow
|
||||
flashing new firmware.
|
||||
|
||||
vdds-supply: true
|
||||
|
||||
required:
|
||||
@@ -46,6 +52,7 @@ examples:
|
||||
clocks = <&sclk_hf 0>, <&sclk_lf 25>;
|
||||
clock-names = "sclk_hf", "sclk_lf";
|
||||
reset-gpios = <&pio 35 GPIO_ACTIVE_LOW>;
|
||||
bootloader-backdoor-gpios = <&pio 36 GPIO_ACTIVE_LOW>;
|
||||
vdds-supply = <&vdds>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ description: |
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
- $ref: nvmem-deprecated-cells.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -14,7 +14,7 @@ maintainers:
|
||||
description: |
|
||||
This binding represents the on-chip eFuse OTP controller found on
|
||||
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL,
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93 SoCs.
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93/5 SoCs.
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
@@ -36,6 +36,7 @@ properties:
|
||||
- fsl,imx8mq-ocotp
|
||||
- fsl,imx8mm-ocotp
|
||||
- fsl,imx93-ocotp
|
||||
- fsl,imx95-ocotp
|
||||
- const: syscon
|
||||
- items:
|
||||
- enum:
|
||||
|
||||
@@ -21,6 +21,7 @@ oneOf:
|
||||
- $ref: fixed-layout.yaml
|
||||
- $ref: kontron,sl28-vpd.yaml
|
||||
- $ref: onie,tlv-layout.yaml
|
||||
- $ref: u-boot,env.yaml
|
||||
|
||||
properties:
|
||||
compatible: true
|
||||
|
||||
+34
-5
@@ -1,10 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/nvmem/u-boot,env.yaml#
|
||||
$id: http://devicetree.org/schemas/nvmem/layouts/u-boot,env.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: U-Boot environment variables
|
||||
title: U-Boot environment variables layout
|
||||
|
||||
description: |
|
||||
U-Boot uses environment variables to store device parameters and
|
||||
@@ -21,9 +21,6 @@ description: |
|
||||
This binding allows marking storage device (as containing env data) and
|
||||
specifying used format.
|
||||
|
||||
Right now only flash partition case is covered but it may be extended to e.g.
|
||||
UBI volumes in the future.
|
||||
|
||||
Variables can be defined as NVMEM device subnodes.
|
||||
|
||||
maintainers:
|
||||
@@ -42,6 +39,7 @@ properties:
|
||||
const: brcm,env
|
||||
|
||||
reg:
|
||||
description: Partition offset and size for env on top of MTD
|
||||
maxItems: 1
|
||||
|
||||
bootcmd:
|
||||
@@ -58,6 +56,17 @@ properties:
|
||||
description: The first argument is a MAC address offset.
|
||||
const: 1
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
$nodename:
|
||||
not:
|
||||
contains:
|
||||
pattern: "^partition@[0-9a-f]+$"
|
||||
then:
|
||||
properties:
|
||||
reg: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
@@ -101,3 +110,23 @@ examples:
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
partition@0 {
|
||||
reg = <0x0 0x100000>;
|
||||
label = "ubi";
|
||||
compatible = "linux,ubi";
|
||||
|
||||
volumes {
|
||||
ubi-volume-u-boot-env {
|
||||
volname = "env";
|
||||
|
||||
nvmem-layout {
|
||||
compatible = "u-boot,env";
|
||||
|
||||
ethaddr {
|
||||
#nvmem-cell-cells = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -17,6 +17,7 @@ maintainers:
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
- $ref: nvmem-deprecated-cells.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@@ -32,6 +33,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: layouts/fixed-cell.yaml
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
st,non-secure-otp:
|
||||
|
||||
@@ -1541,6 +1541,8 @@ patternProperties:
|
||||
description: Turing Machines, Inc.
|
||||
"^tyan,.*":
|
||||
description: Tyan Computer Corporation
|
||||
"^tyhx,.*":
|
||||
description: NanjingTianyihexin Electronics Ltd.
|
||||
"^u-blox,.*":
|
||||
description: u-blox
|
||||
"^u-boot,.*":
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
=============
|
||||
AD4000 driver
|
||||
=============
|
||||
|
||||
Device driver for Analog Devices Inc. AD4000 series of ADCs.
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
||||
* `AD4000 <https://www.analog.com/AD4000>`_
|
||||
* `AD4001 <https://www.analog.com/AD4001>`_
|
||||
* `AD4002 <https://www.analog.com/AD4002>`_
|
||||
* `AD4003 <https://www.analog.com/AD4003>`_
|
||||
* `AD4004 <https://www.analog.com/AD4004>`_
|
||||
* `AD4005 <https://www.analog.com/AD4005>`_
|
||||
* `AD4006 <https://www.analog.com/AD4006>`_
|
||||
* `AD4007 <https://www.analog.com/AD4007>`_
|
||||
* `AD4008 <https://www.analog.com/AD4008>`_
|
||||
* `AD4010 <https://www.analog.com/AD4010>`_
|
||||
* `AD4011 <https://www.analog.com/AD4011>`_
|
||||
* `AD4020 <https://www.analog.com/AD4020>`_
|
||||
* `AD4021 <https://www.analog.com/AD4021>`_
|
||||
* `AD4022 <https://www.analog.com/AD4022>`_
|
||||
* `ADAQ4001 <https://www.analog.com/ADAQ4001>`_
|
||||
* `ADAQ4003 <https://www.analog.com/ADAQ4003>`_
|
||||
|
||||
Wiring connections
|
||||
------------------
|
||||
|
||||
Devices of the AD4000 series can be connected to the SPI host controller in a
|
||||
few different modes.
|
||||
|
||||
CS mode, 3-wire turbo mode
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Datasheet "3-wire" mode is what most resembles standard SPI connection which,
|
||||
for these devices, comprises of connecting the controller CS line to device CNV
|
||||
pin and other SPI lines as usual. This configuration is (misleadingly) called
|
||||
"CS Mode, 3-Wire Turbo Mode" connection in datasheets.
|
||||
NOTE: The datasheet definition of 3-wire mode for the AD4000 series is NOT the
|
||||
same of standard spi-3wire mode.
|
||||
This is the only connection mode that allows configuration register access but
|
||||
it requires the SPI controller to support the ``SPI_MOSI_IDLE_HIGH`` feature.
|
||||
|
||||
Omit the ``adi,sdi-pin`` property in device tree to select this mode.
|
||||
|
||||
::
|
||||
|
||||
+-------------+
|
||||
+ ----------------------------------| SDO |
|
||||
| | |
|
||||
| +-------------------| CS |
|
||||
| v | |
|
||||
| +--------------------+ | HOST |
|
||||
| | CNV | | |
|
||||
+--->| SDI AD4000 SDO |-------->| SDI |
|
||||
| SCK | | |
|
||||
+--------------------+ | |
|
||||
^ | |
|
||||
+--------------------| SCLK |
|
||||
+-------------+
|
||||
|
||||
CS mode, 3-wire, without busy indicator
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Another wiring configuration supported as "3-wire" mode has the SDI pin
|
||||
hard-wired to digital input/output interface supply (VIO). In this setup, the
|
||||
controller is not required to support ``SPI_MOSI_IDLE_HIGH`` but register access
|
||||
is not possible. This connection mode saves one wire and works with any SPI
|
||||
controller.
|
||||
|
||||
Set the ``adi,sdi-pin`` device tree property to ``"high"`` to select this mode.
|
||||
|
||||
::
|
||||
|
||||
+-------------+
|
||||
+--------------------| CS |
|
||||
v | |
|
||||
VIO +--------------------+ | HOST |
|
||||
| | CNV | | |
|
||||
+--->| SDI AD4000 SDO |-------->| SDI |
|
||||
| SCK | | |
|
||||
+--------------------+ | |
|
||||
^ | |
|
||||
+--------------------| SCLK |
|
||||
+-------------+
|
||||
|
||||
Alternatively, a GPIO may be connected to the device CNV pin. This is similar to
|
||||
the previous wiring configuration but saves the use of a CS line.
|
||||
|
||||
::
|
||||
|
||||
+-------------+
|
||||
+--------------------| GPIO |
|
||||
v | |
|
||||
VIO +--------------------+ | HOST |
|
||||
| | CNV | | |
|
||||
+--->| SDI AD4000 SDO |-------->| SDI |
|
||||
| SCK | | |
|
||||
+--------------------+ | |
|
||||
^ | |
|
||||
+--------------------| SCLK |
|
||||
+-------------+
|
||||
|
||||
CS mode, 4-wire without busy indicator
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In datasheet "4-wire" mode, the controller CS line is connected to the ADC SDI
|
||||
pin and a GPIO is connected to the ADC CNV pin. This connection mode may better
|
||||
suit scenarios where multiple ADCs can share one CNV trigger.
|
||||
|
||||
Set ``adi,sdi-pin`` to ``"cs"`` to select this mode.
|
||||
|
||||
|
||||
::
|
||||
|
||||
+-------------+
|
||||
+ ----------------------------------| CS |
|
||||
| | |
|
||||
| +-------------------| GPIO |
|
||||
| v | |
|
||||
| +--------------------+ | HOST |
|
||||
| | CNV | | |
|
||||
+--->| SDI AD4000 SDO |-------->| SDI |
|
||||
| SCK | | |
|
||||
+--------------------+ | |
|
||||
^ | |
|
||||
+--------------------| SCLK |
|
||||
+-------------+
|
||||
@@ -0,0 +1,167 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
=============
|
||||
AD4695 driver
|
||||
=============
|
||||
|
||||
ADC driver for Analog Devices Inc. AD4695 and similar devices. The module name
|
||||
is ``ad4695``.
|
||||
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
||||
The following chips are supported by this driver:
|
||||
|
||||
* `AD4695 <https://www.analog.com/AD4695>`_
|
||||
* `AD4696 <https://www.analog.com/AD4696>`_
|
||||
* `AD4697 <https://www.analog.com/AD4697>`_
|
||||
* `AD4698 <https://www.analog.com/AD4698>`_
|
||||
|
||||
|
||||
Supported features
|
||||
==================
|
||||
|
||||
SPI wiring modes
|
||||
----------------
|
||||
|
||||
The driver currently supports the following SPI wiring configuration:
|
||||
|
||||
4-wire mode
|
||||
^^^^^^^^^^^
|
||||
|
||||
In this mode, CNV and CS are tied together and there is a single SDO line.
|
||||
|
||||
.. code-block::
|
||||
|
||||
+-------------+ +-------------+
|
||||
| CS |<-+------| CS |
|
||||
| CNV |<-+ | |
|
||||
| ADC | | HOST |
|
||||
| | | |
|
||||
| SDI |<--------| SDO |
|
||||
| SDO |-------->| SDI |
|
||||
| SCLK |<--------| SCLK |
|
||||
+-------------+ +-------------+
|
||||
|
||||
To use this mode, in the device tree, omit the ``cnv-gpios`` and
|
||||
``spi-rx-bus-width`` properties.
|
||||
|
||||
Channel configuration
|
||||
---------------------
|
||||
|
||||
Since the chip supports multiple ways to configure each channel, this must be
|
||||
described in the device tree based on what is actually wired up to the inputs.
|
||||
|
||||
There are three typical configurations:
|
||||
|
||||
An ``INx`` pin is used as the positive input with the ``REFGND``, ``COM`` or
|
||||
the next ``INx`` pin as the negative input.
|
||||
|
||||
Pairing with REFGND
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Each ``INx`` pin can be used as a pseudo-differential input in conjunction with
|
||||
the ``REFGND`` pin. The device tree will look like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
channel@0 {
|
||||
reg = <0>; /* IN0 */
|
||||
};
|
||||
|
||||
If no other channel properties are needed (e.g. ``adi,no-high-z``), the channel
|
||||
node can be omitted entirely.
|
||||
|
||||
This will appear on the IIO bus as the ``voltage0`` channel. The processed value
|
||||
(*raw × scale*) will be the voltage present on the ``IN0`` pin relative to
|
||||
``REFGND``. (Offset is always 0 when pairing with ``REFGND``.)
|
||||
|
||||
Pairing with COM
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Each ``INx`` pin can be used as a pseudo-differential input in conjunction with
|
||||
the ``COM`` pin. The device tree will look like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
com-supply = <&vref_div_2>;
|
||||
|
||||
channel@1 {
|
||||
reg = <1>; /* IN1 */
|
||||
common-mode-channel = <AD4695_COMMON_MODE_COM>;
|
||||
bipolar;
|
||||
};
|
||||
|
||||
This will appear on the IIO bus as the ``voltage1`` channel. The processed value
|
||||
(*(raw + offset) × scale*) will be the voltage measured on the ``IN1`` pin
|
||||
relative to ``REFGND``. (The offset is determined by the ``com-supply`` voltage.)
|
||||
|
||||
The macro comes from:
|
||||
|
||||
.. code-block::
|
||||
|
||||
#include <dt-bindings/iio/adi,ad4695.h>
|
||||
|
||||
Pairing two INx pins
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
An even-numbered ``INx`` pin and the following odd-numbered ``INx`` pin can be
|
||||
used as a pseudo-differential input. The device tree for using ``IN2`` as the
|
||||
positive input and ``IN3`` as the negative input will look like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
in3-supply = <&vref_div_2>;
|
||||
|
||||
channel@2 {
|
||||
reg = <2>; /* IN2 */
|
||||
common-mode-channel = <3>; /* IN3 */
|
||||
bipolar;
|
||||
};
|
||||
|
||||
This will appear on the IIO bus as the ``voltage2`` channel. The processed value
|
||||
(*(raw + offset) × scale*) will be the voltage measured on the ``IN1`` pin
|
||||
relative to ``REFGND``. (Offset is determined by the ``in3-supply`` voltage.)
|
||||
|
||||
VCC supply
|
||||
----------
|
||||
|
||||
The chip supports being powered by an external LDO via the ``VCC`` input or an
|
||||
internal LDO via the ``LDO_IN`` input. The driver looks at the device tree to
|
||||
determine which is being used. If ``ldo-supply`` is present, then the internal
|
||||
LDO is used. If ``vcc-supply`` is present, then the external LDO is used and
|
||||
the internal LDO is disabled.
|
||||
|
||||
Reference voltage
|
||||
-----------------
|
||||
|
||||
The chip supports an external reference voltage via the ``REF`` input or an
|
||||
internal buffered reference voltage via the ``REFIN`` input. The driver looks
|
||||
at the device tree to determine which is being used. If ``ref-supply`` is
|
||||
present, then the external reference voltage is used and the internal buffer is
|
||||
disabled. If ``refin-supply`` is present, then the internal buffered reference
|
||||
voltage is used.
|
||||
|
||||
Gain/offset calibration
|
||||
-----------------------
|
||||
|
||||
System calibration is supported using the channel gain and offset registers via
|
||||
the ``calibscale`` and ``calibbias`` attributes respectively.
|
||||
|
||||
Unimplemented features
|
||||
----------------------
|
||||
|
||||
- Additional wiring modes
|
||||
- Threshold events
|
||||
- Oversampling
|
||||
- GPIO support
|
||||
- CRC support
|
||||
|
||||
Device buffers
|
||||
==============
|
||||
|
||||
This driver supports hardware triggered buffers. This uses the "advanced
|
||||
sequencer" feature of the chip to trigger a burst of conversions.
|
||||
|
||||
Also see :doc:`iio_devbuf` for more general information.
|
||||
@@ -0,0 +1,130 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
=============
|
||||
AD7380 driver
|
||||
=============
|
||||
|
||||
ADC driver for Analog Devices Inc. AD7380 and similar devices. The module name
|
||||
is ``ad7380``.
|
||||
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
||||
The following chips are supported by this driver:
|
||||
|
||||
* `AD7380 <https://www.analog.com/en/products/ad7380.html>`_
|
||||
* `AD7381 <https://www.analog.com/en/products/ad7381.html>`_
|
||||
* `AD7383 <https://www.analog.com/en/products/ad7383.html>`_
|
||||
* `AD7384 <https://www.analog.com/en/products/ad7384.html>`_
|
||||
* `AD7386 <https://www.analog.com/en/products/ad7386.html>`_
|
||||
* `AD7387 <https://www.analog.com/en/products/ad7387.html>`_
|
||||
* `AD7388 <https://www.analog.com/en/products/ad7388.html>`_
|
||||
* `AD7380-4 <https://www.analog.com/en/products/ad7380-4.html>`_
|
||||
* `AD7381-4 <https://www.analog.com/en/products/ad7381-4.html>`_
|
||||
* `AD7383-4 <https://www.analog.com/en/products/ad7383-4.html>`_
|
||||
* `AD7384-4 <https://www.analog.com/en/products/ad7384-4.html>`_
|
||||
* `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_
|
||||
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
|
||||
* `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_
|
||||
|
||||
|
||||
Supported features
|
||||
==================
|
||||
|
||||
SPI wiring modes
|
||||
----------------
|
||||
|
||||
ad738x ADCs can output data on several SDO lines (1/2/4). The driver currently
|
||||
supports only 1 SDO line.
|
||||
|
||||
Reference voltage
|
||||
-----------------
|
||||
|
||||
2 possible reference voltage sources are supported:
|
||||
|
||||
- Internal reference (2.5V)
|
||||
- External reference (2.5V to 3.3V)
|
||||
|
||||
The source is determined by the device tree. If ``refio-supply`` is present,
|
||||
then the external reference is used, else the internal reference is used.
|
||||
|
||||
Oversampling and resolution boost
|
||||
---------------------------------
|
||||
|
||||
This family supports 2 types of oversampling: normal average and rolling
|
||||
average. Only normal average is supported by the driver, as rolling average can
|
||||
be achieved by processing a captured data buffer. The following ratios are
|
||||
available: 1 (oversampling disabled)/2/4/8/16/32.
|
||||
|
||||
When the on-chip oversampling function is enabled the performance of the ADC can
|
||||
exceed the default resolution. To accommodate the performance boost achievable,
|
||||
it is possible to enable an additional two bits of resolution. Because the
|
||||
resolution boost feature can only be enabled when oversampling is enabled and
|
||||
oversampling is not as useful without the resolution boost, the driver
|
||||
automatically enables the resolution boost if and only if oversampling is
|
||||
enabled.
|
||||
|
||||
Since the resolution boost feature causes 16-bit chips to now have 18-bit data
|
||||
which means the storagebits has to change from 16 to 32 bits, we use the new
|
||||
ext_scan_type feature to allow changing the scan_type at runtime. Unfortunately
|
||||
libiio does not support it. So when enabling or disabling oversampling, user
|
||||
must restart iiod using the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:~# systemctl restart iiod
|
||||
|
||||
Channel selection and sequencer (single-end chips only)
|
||||
-------------------------------------------------------
|
||||
|
||||
Single-ended chips of this family (ad7386/7/8(-4)) have a 2:1 multiplexer in
|
||||
front of each ADC. They also include additional configuration registers that
|
||||
allow for either manual selection or automatic switching (sequencer mode), of
|
||||
the multiplexer inputs.
|
||||
|
||||
From an IIO point of view, all inputs are exported, i.e ad7386/7/8
|
||||
export 4 channels and ad7386-4/7-4/8-4 export 8 channels.
|
||||
|
||||
Inputs ``AinX0`` of multiplexers correspond to the first half of IIO channels (i.e
|
||||
0-1 or 0-3) and inputs ``AinX1`` correspond to second half (i.e 2-3 or 4-7).
|
||||
Example for AD7386/7/8 (2 channels parts):
|
||||
|
||||
.. code-block::
|
||||
|
||||
IIO | AD7386/7/8
|
||||
| +----------------------------
|
||||
| | _____ ______
|
||||
| | | | | |
|
||||
voltage0 | AinA0 --|--->| | | |
|
||||
| | | mux |----->| ADCA |---
|
||||
voltage2 | AinA1 --|--->| | | |
|
||||
| | |_____| |_____ |
|
||||
| | _____ ______
|
||||
| | | | | |
|
||||
voltage1 | AinB0 --|--->| | | |
|
||||
| | | mux |----->| ADCB |---
|
||||
voltage3 | AinB1 --|--->| | | |
|
||||
| | |_____| |______|
|
||||
| |
|
||||
| +----------------------------
|
||||
|
||||
|
||||
When enabling sequencer mode, the effective sampling rate is divided by two.
|
||||
|
||||
Unimplemented features
|
||||
----------------------
|
||||
|
||||
- 2/4 SDO lines
|
||||
- Rolling average oversampling
|
||||
- Power down mode
|
||||
- CRC indication
|
||||
- Alert
|
||||
|
||||
|
||||
Device buffers
|
||||
==============
|
||||
|
||||
This driver supports IIO triggered buffers.
|
||||
|
||||
See :doc:`iio_devbuf` for more information.
|
||||
@@ -0,0 +1,233 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
===============
|
||||
ADXL380 driver
|
||||
===============
|
||||
|
||||
This driver supports Analog Device's ADXL380/382 on SPI/I2C bus.
|
||||
|
||||
1. Supported devices
|
||||
====================
|
||||
|
||||
* `ADXL380 <https://www.analog.com/ADXL380>`_
|
||||
* `ADXL382 <https://www.analog.com/ADXL382>`_
|
||||
|
||||
The ADXL380/ADXL382 is a low noise density, low power, 3-axis accelerometer with
|
||||
selectable measurement ranges. The ADXL380 supports the ±4 g, ±8 g, and ±16 g
|
||||
ranges, and the ADXL382 supports ±15 g, ±30 g, and ±60 g ranges.
|
||||
|
||||
2. Device attributes
|
||||
====================
|
||||
|
||||
Accelerometer measurements are always provided.
|
||||
|
||||
Temperature data are also provided. This data can be used to monitor the
|
||||
internal system temperature or to improve the temperature stability of the
|
||||
device via calibration.
|
||||
|
||||
Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``,
|
||||
where X is the IIO index of the device. Under these folders reside a set of
|
||||
device files, depending on the characteristics and features of the hardware
|
||||
device in questions. These files are consistently generalized and documented in
|
||||
the IIO ABI documentation.
|
||||
|
||||
The following tables show the adxl380 related device files, found in the
|
||||
specific device folder path ``/sys/bus/iio/devices/iio:deviceX``.
|
||||
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| 3-Axis Accelerometer related device files | Description |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_scale | Scale for the accelerometer channels. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_filter_high_pass_3db_frequency | Low pass filter bandwidth. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_filter_high_pass_3db_frequency_available | Available low pass filter bandwidth configurations. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_filter_low_pass_3db_frequency | High pass filter bandwidth. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_filter_low_pass_3db_frequency_available | Available high pass filter bandwidth configurations. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_x_calibbias | Calibration offset for the X-axis accelerometer channel. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_x_raw | Raw X-axis accelerometer channel value. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_calibbias | y-axis acceleration offset correction |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_y_raw | Raw Y-axis accelerometer channel value. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_z_calibbias | Calibration offset for the Z-axis accelerometer channel. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
| in_accel_z_raw | Raw Z-axis accelerometer channel value. |
|
||||
+---------------------------------------------------+----------------------------------------------------------+
|
||||
|
||||
+----------------------------------+--------------------------------------------+
|
||||
| Temperature sensor related files | Description |
|
||||
+----------------------------------+--------------------------------------------+
|
||||
| in_temp_raw | Raw temperature channel value. |
|
||||
+----------------------------------+--------------------------------------------+
|
||||
| in_temp_offset | Offset for the temperature sensor channel. |
|
||||
+----------------------------------+--------------------------------------------+
|
||||
| in_temp_scale | Scale for the temperature sensor channel. |
|
||||
+----------------------------------+--------------------------------------------+
|
||||
|
||||
+------------------------------+----------------------------------------------+
|
||||
| Miscellaneous device files | Description |
|
||||
+------------------------------+----------------------------------------------+
|
||||
| name | Name of the IIO device. |
|
||||
+------------------------------+----------------------------------------------+
|
||||
| sampling_frequency | Currently selected sample rate. |
|
||||
+------------------------------+----------------------------------------------+
|
||||
| sampling_frequency_available | Available sampling frequency configurations. |
|
||||
+------------------------------+----------------------------------------------+
|
||||
|
||||
Channels processed values
|
||||
-------------------------
|
||||
|
||||
A channel value can be read from its _raw attribute. The value returned is the
|
||||
raw value as reported by the devices. To get the processed value of the channel,
|
||||
apply the following formula:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
processed value = (_raw + _offset) * _scale
|
||||
|
||||
Where _offset and _scale are device attributes. If no _offset attribute is
|
||||
present, simply assume its value is 0.
|
||||
|
||||
The adis16475 driver offers data for 2 types of channels, the table below shows
|
||||
the measurement units for the processed value, which are defined by the IIO
|
||||
framework:
|
||||
|
||||
+-------------------------------------+---------------------------+
|
||||
| Channel type | Measurement unit |
|
||||
+-------------------------------------+---------------------------+
|
||||
| Acceleration on X, Y, and Z axis | Meters per Second squared |
|
||||
+-------------------------------------+---------------------------+
|
||||
| Temperature | Millidegrees Celsius |
|
||||
+-------------------------------------+---------------------------+
|
||||
|
||||
Usage examples
|
||||
--------------
|
||||
|
||||
Show device name:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> cat name
|
||||
adxl382
|
||||
|
||||
Show accelerometer channels value:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_raw
|
||||
-1771
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_y_raw
|
||||
282
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_z_raw
|
||||
-1523
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_scale
|
||||
0.004903325
|
||||
|
||||
- X-axis acceleration = in_accel_x_raw * in_accel_scale = −8.683788575 m/s^2
|
||||
- Y-axis acceleration = in_accel_y_raw * in_accel_scale = 1.38273765 m/s^2
|
||||
- Z-axis acceleration = in_accel_z_raw * in_accel_scale = -7.467763975 m/s^2
|
||||
|
||||
Set calibration offset for accelerometer channels:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias
|
||||
0
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 50 > in_accel_x_calibbias
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias
|
||||
50
|
||||
|
||||
Set sampling frequency:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> cat sampling_frequency
|
||||
16000
|
||||
root:/sys/bus/iio/devices/iio:device0> cat sampling_frequency_available
|
||||
16000 32000 64000
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 32000 > sampling_frequency
|
||||
root:/sys/bus/iio/devices/iio:device0> cat sampling_frequency
|
||||
32000
|
||||
|
||||
Set low pass filter bandwidth for accelerometer channels:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_filter_low_pass_3db_frequency
|
||||
32000
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_filter_low_pass_3db_frequency_available
|
||||
32000 8000 4000 2000
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 2000 > in_accel_filter_low_pass_3db_frequency
|
||||
root:/sys/bus/iio/devices/iio:device0> cat in_accel_filter_low_pass_3db_frequency
|
||||
2000
|
||||
|
||||
3. Device buffers
|
||||
=================
|
||||
|
||||
This driver supports IIO buffers.
|
||||
|
||||
All devices support retrieving the raw acceleration and temperature measurements
|
||||
using buffers.
|
||||
|
||||
Usage examples
|
||||
--------------
|
||||
|
||||
Select channels for buffer read:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_accel_x_en
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_accel_y_en
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_accel_z_en
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_temp_en
|
||||
|
||||
Set the number of samples to be stored in the buffer:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 10 > buffer/length
|
||||
|
||||
Enable buffer readings:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> echo 1 > buffer/enable
|
||||
|
||||
Obtain buffered data:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
root:/sys/bus/iio/devices/iio:device0> hexdump -C /dev/iio\:device0
|
||||
...
|
||||
002bc300 f7 e7 00 a8 fb c5 24 80 f7 e7 01 04 fb d6 24 80 |......$.......$.|
|
||||
002bc310 f7 f9 00 ab fb dc 24 80 f7 c3 00 b8 fb e2 24 80 |......$.......$.|
|
||||
002bc320 f7 fb 00 bb fb d1 24 80 f7 b1 00 5f fb d1 24 80 |......$...._..$.|
|
||||
002bc330 f7 c4 00 c6 fb a6 24 80 f7 a6 00 68 fb f1 24 80 |......$....h..$.|
|
||||
002bc340 f7 b8 00 a3 fb e7 24 80 f7 9a 00 b1 fb af 24 80 |......$.......$.|
|
||||
002bc350 f7 b1 00 67 fb ee 24 80 f7 96 00 be fb 92 24 80 |...g..$.......$.|
|
||||
002bc360 f7 ab 00 7a fc 1b 24 80 f7 b6 00 ae fb 76 24 80 |...z..$......v$.|
|
||||
002bc370 f7 ce 00 a3 fc 02 24 80 f7 c0 00 be fb 8b 24 80 |......$.......$.|
|
||||
002bc380 f7 c3 00 93 fb d0 24 80 f7 ce 00 d8 fb c8 24 80 |......$.......$.|
|
||||
002bc390 f7 bd 00 c0 fb 82 24 80 f8 00 00 e8 fb db 24 80 |......$.......$.|
|
||||
002bc3a0 f7 d8 00 d3 fb b4 24 80 f8 0b 00 e5 fb c3 24 80 |......$.......$.|
|
||||
002bc3b0 f7 eb 00 c8 fb 92 24 80 f7 e7 00 ea fb cb 24 80 |......$.......$.|
|
||||
002bc3c0 f7 fd 00 cb fb 94 24 80 f7 e3 00 f2 fb b8 24 80 |......$.......$.|
|
||||
...
|
||||
|
||||
See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered
|
||||
data is structured.
|
||||
|
||||
4. IIO Interfacing Tools
|
||||
========================
|
||||
|
||||
See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO
|
||||
interfacing tools.
|
||||
@@ -18,8 +18,12 @@ Industrial I/O Kernel Drivers
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ad4000
|
||||
ad4695
|
||||
ad7380
|
||||
ad7944
|
||||
adis16475
|
||||
adis16480
|
||||
adxl380
|
||||
bno055
|
||||
ep93xx_adc
|
||||
|
||||
@@ -17,7 +17,7 @@ The idea is that you identify packets with destination address matching a local
|
||||
socket on your box, set the packet mark to a certain value::
|
||||
|
||||
# iptables -t mangle -N DIVERT
|
||||
# iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
|
||||
# iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j DIVERT
|
||||
# iptables -t mangle -A DIVERT -j MARK --set-mark 1
|
||||
# iptables -t mangle -A DIVERT -j ACCEPT
|
||||
|
||||
|
||||
+69
-2
@@ -449,6 +449,7 @@ S: Supported
|
||||
W: https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
|
||||
F: Documentation/iio/ad7380.rst
|
||||
F: drivers/iio/adc/ad7380.c
|
||||
|
||||
AD7877 TOUCHSCREEN DRIVER
|
||||
@@ -631,6 +632,17 @@ F: drivers/iio/accel/adxl372.c
|
||||
F: drivers/iio/accel/adxl372_i2c.c
|
||||
F: drivers/iio/accel/adxl372_spi.c
|
||||
|
||||
ADXL380 THREE-AXIS DIGITAL ACCELEROMETER DRIVER
|
||||
M: Ramona Gradinariu <ramona.gradinariu@analog.com>
|
||||
M: Antoniu Miclaus <antoniu.miclaus@analog.com>
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/accel/adi,adxl380.yaml
|
||||
F: drivers/iio/accel/adxl380.c
|
||||
F: drivers/iio/accel/adxl380.h
|
||||
F: drivers/iio/accel/adxl380_i2c.c
|
||||
F: drivers/iio/accel/adxl380_spi.c
|
||||
|
||||
AF8133J THREE-AXIS MAGNETOMETER DRIVER
|
||||
M: Ondřej Jirman <megi@xff.cz>
|
||||
S: Maintained
|
||||
@@ -1242,6 +1254,8 @@ L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4000.yaml
|
||||
F: Documentation/iio/ad4000.rst
|
||||
F: drivers/iio/adc/ad4000.c
|
||||
|
||||
ANALOG DEVICES INC AD4130 DRIVER
|
||||
M: Cosmin Tanislav <cosmin.tanislav@analog.com>
|
||||
@@ -1252,6 +1266,18 @@ F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
|
||||
F: drivers/iio/adc/ad4130.c
|
||||
|
||||
ANALOG DEVICES INC AD4695 DRIVER
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
M: Nuno Sá <nuno.sa@analog.com>
|
||||
R: David Lechner <dlechner@baylibre.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml
|
||||
F: Documentation/iio/ad4695.rst
|
||||
F: drivers/iio/adc/ad4695.c
|
||||
F: include/dt-bindings/iio/adi,ad4695.h
|
||||
|
||||
ANALOG DEVICES INC AD7091R DRIVER
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
@@ -1318,6 +1344,16 @@ W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml
|
||||
F: drivers/iio/adc/ad7780.c
|
||||
|
||||
ANALOG DEVICES INC AD9467 DRIVER
|
||||
M: Michael Hennerich <Michael.Hennerich@analog.com>
|
||||
M: Nuno Sa <nuno.sa@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/ABI/testing/debugfs-iio-ad9467
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
|
||||
F: drivers/iio/adc/ad9467.c
|
||||
|
||||
ANALOG DEVICES INC AD9739a DRIVER
|
||||
M: Nuno Sa <nuno.sa@analog.com>
|
||||
M: Dragos Bogdan <dragos.bogdan@analog.com>
|
||||
@@ -10977,6 +11013,7 @@ M: Nuno Sa <nuno.sa@analog.com>
|
||||
R: Olivier Moysan <olivier.moysan@foss.st.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/debugfs-iio-backend
|
||||
F: drivers/iio/industrialio-backend.c
|
||||
F: include/linux/iio/backend.h
|
||||
|
||||
@@ -13425,6 +13462,16 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/dac/lltc,ltc1660.yaml
|
||||
F: drivers/iio/dac/ltc1660.c
|
||||
|
||||
LTC2664 IIO DAC DRIVER
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
M: Kim Seer Paller <kimseer.paller@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml
|
||||
F: drivers/iio/dac/ltc2664.c
|
||||
|
||||
LTC2688 IIO DAC DRIVER
|
||||
M: Nuno Sá <nuno.sa@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
@@ -15193,6 +15240,13 @@ F: Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
|
||||
F: drivers/nvmem/microchip-otpc.c
|
||||
F: include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
|
||||
|
||||
MICROCHIP PAC1921 POWER/CURRENT MONITOR DRIVER
|
||||
M: Matteo Martelli <matteomartelli3@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/iio/adc/microchip,pac1921.yaml
|
||||
F: drivers/iio/adc/pac1921.c
|
||||
|
||||
MICROCHIP PAC1934 POWER/ENERGY MONITOR DRIVER
|
||||
M: Marius Cristea <marius.cristea@microchip.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
@@ -17269,8 +17323,8 @@ M: Parthiban Veerasooran <parthiban.veerasooran@microchip.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/networking/oa-tc6-framework.rst
|
||||
F: drivers/include/linux/oa_tc6.h
|
||||
F: drivers/net/ethernet/oa_tc6.c
|
||||
F: include/linux/oa_tc6.h
|
||||
|
||||
OPEN FIRMWARE AND FLATTENED DEVICE TREE
|
||||
M: Rob Herring <robh@kernel.org>
|
||||
@@ -19997,6 +20051,12 @@ S: Supported
|
||||
F: drivers/power/supply/bd99954-charger.c
|
||||
F: drivers/power/supply/bd99954-charger.h
|
||||
|
||||
ROHM BH1745 COLOUR SENSOR
|
||||
M: Mudit Sharma <muditsharma.info@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/iio/light/bh1745.c
|
||||
|
||||
ROHM BH1750 AMBIENT LIGHT SENSOR DRIVER
|
||||
M: Tomasz Duszynski <tduszyns@gmail.com>
|
||||
S: Maintained
|
||||
@@ -20850,6 +20910,12 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/chemical/sensirion,scd4x.yaml
|
||||
F: drivers/iio/chemical/scd4x.c
|
||||
|
||||
SENSIRION SDP500 DIFFERENTIAL PRESSURE SENSOR DRIVER
|
||||
M: Petar Stoykov <petar.stoykov@prodrive-technologies.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/pressure/sensirion,sdp500.yaml
|
||||
F: drivers/iio/pressure/sdp500.c
|
||||
|
||||
SENSIRION SGP40 GAS SENSOR DRIVER
|
||||
M: Andreas Klinger <ak@it-klinger.de>
|
||||
S: Maintained
|
||||
@@ -23612,7 +23678,8 @@ F: drivers/media/pci/tw686x/
|
||||
U-BOOT ENVIRONMENT VARIABLES
|
||||
M: Rafał Miłecki <rafal@milecki.pl>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
|
||||
F: Documentation/devicetree/bindings/nvmem/layouts/u-boot,env.yaml
|
||||
F: drivers/nvmem/layouts/u-boot-env.c
|
||||
F: drivers/nvmem/u-boot-env.c
|
||||
|
||||
UACCE ACCELERATOR FRAMEWORK
|
||||
|
||||
@@ -888,7 +888,8 @@
|
||||
|
||||
mcu {
|
||||
compatible = "ti,cc1352p7";
|
||||
reset-gpios = <&main_gpio0 72 GPIO_ACTIVE_LOW>;
|
||||
bootloader-backdoor-gpios = <&main_gpio0 13 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&main_gpio0 14 GPIO_ACTIVE_HIGH>;
|
||||
vdds-supply = <&vdd_3v3>;
|
||||
};
|
||||
};
|
||||
|
||||
+284
-4
@@ -278,7 +278,7 @@ _binder_proc_lock(struct binder_proc *proc, int line)
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_proc_unlock() - Release spinlock for given binder_proc
|
||||
* binder_proc_unlock() - Release outer lock for given binder_proc
|
||||
* @proc: struct binder_proc to acquire
|
||||
*
|
||||
* Release lock acquired via binder_proc_lock()
|
||||
@@ -1525,6 +1525,7 @@ static void binder_free_ref(struct binder_ref *ref)
|
||||
if (ref->node)
|
||||
binder_free_node(ref->node);
|
||||
kfree(ref->death);
|
||||
kfree(ref->freeze);
|
||||
kfree(ref);
|
||||
}
|
||||
|
||||
@@ -1719,7 +1720,7 @@ static void binder_thread_dec_tmpref(struct binder_thread *thread)
|
||||
* by threads that are being released. When done with the binder_proc,
|
||||
* this function is called to decrement the counter and free the
|
||||
* proc if appropriate (proc has been released, all threads have
|
||||
* been released and not currenly in-use to process a transaction).
|
||||
* been released and not currently in-use to process a transaction).
|
||||
*/
|
||||
static void binder_proc_dec_tmpref(struct binder_proc *proc)
|
||||
{
|
||||
@@ -4035,6 +4036,155 @@ err_invalid_target_handle:
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
binder_request_freeze_notification(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
struct binder_handle_cookie *handle_cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_ref *ref;
|
||||
bool is_frozen;
|
||||
|
||||
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
|
||||
if (!freeze)
|
||||
return -ENOMEM;
|
||||
binder_proc_lock(proc);
|
||||
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||
if (!ref) {
|
||||
binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||
proc->pid, thread->pid, handle_cookie->handle);
|
||||
binder_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
binder_node_lock(ref->node);
|
||||
|
||||
if (ref->freeze || !ref->node->proc) {
|
||||
binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
|
||||
proc->pid, thread->pid,
|
||||
ref->freeze ? "already set" : "dead node");
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
return -EINVAL;
|
||||
}
|
||||
binder_inner_proc_lock(ref->node->proc);
|
||||
is_frozen = ref->node->proc->is_frozen;
|
||||
binder_inner_proc_unlock(ref->node->proc);
|
||||
|
||||
binder_stats_created(BINDER_STAT_FREEZE);
|
||||
INIT_LIST_HEAD(&freeze->work.entry);
|
||||
freeze->cookie = handle_cookie->cookie;
|
||||
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||
freeze->is_frozen = is_frozen;
|
||||
|
||||
ref->freeze = freeze;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
binder_inner_proc_unlock(proc);
|
||||
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_clear_freeze_notification(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
struct binder_handle_cookie *handle_cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_ref *ref;
|
||||
|
||||
binder_proc_lock(proc);
|
||||
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||
if (!ref) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||
proc->pid, thread->pid, handle_cookie->handle);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
binder_node_lock(ref->node);
|
||||
|
||||
if (!ref->freeze) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active\n",
|
||||
proc->pid, thread->pid);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
freeze = ref->freeze;
|
||||
binder_inner_proc_lock(proc);
|
||||
if (freeze->cookie != handle_cookie->cookie) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch %016llx != %016llx\n",
|
||||
proc->pid, thread->pid, (u64)freeze->cookie,
|
||||
(u64)handle_cookie->cookie);
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
ref->freeze = NULL;
|
||||
/*
|
||||
* Take the existing freeze object and overwrite its work type. There are three cases here:
|
||||
* 1. No pending notification. In this case just add the work to the queue.
|
||||
* 2. A notification was sent and is pending an ack from userspace. Once an ack arrives, we
|
||||
* should resend with the new work type.
|
||||
* 3. A notification is pending to be sent. Since the work is already in the queue, nothing
|
||||
* needs to be done here.
|
||||
*/
|
||||
freeze->work.type = BINDER_WORK_CLEAR_FREEZE_NOTIFICATION;
|
||||
if (list_empty(&freeze->work.entry)) {
|
||||
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
} else if (freeze->sent) {
|
||||
freeze->resend = true;
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_freeze_notification_done(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
binder_uintptr_t cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze = NULL;
|
||||
struct binder_work *w;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
list_for_each_entry(w, &proc->delivered_freeze, entry) {
|
||||
struct binder_ref_freeze *tmp_freeze =
|
||||
container_of(w, struct binder_ref_freeze, work);
|
||||
|
||||
if (tmp_freeze->cookie == cookie) {
|
||||
freeze = tmp_freeze;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!freeze) {
|
||||
binder_user_error("%d:%d BC_FREEZE_NOTIFICATION_DONE %016llx not found\n",
|
||||
proc->pid, thread->pid, (u64)cookie);
|
||||
binder_inner_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
binder_dequeue_work_ilocked(&freeze->work);
|
||||
freeze->sent = false;
|
||||
if (freeze->resend) {
|
||||
freeze->resend = false;
|
||||
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_free_buf() - free the specified buffer
|
||||
* @proc: binder proc that owns buffer
|
||||
@@ -4518,6 +4668,44 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||
binder_inner_proc_unlock(proc);
|
||||
} break;
|
||||
|
||||
case BC_REQUEST_FREEZE_NOTIFICATION: {
|
||||
struct binder_handle_cookie handle_cookie;
|
||||
int error;
|
||||
|
||||
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(handle_cookie);
|
||||
error = binder_request_freeze_notification(proc, thread,
|
||||
&handle_cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
case BC_CLEAR_FREEZE_NOTIFICATION: {
|
||||
struct binder_handle_cookie handle_cookie;
|
||||
int error;
|
||||
|
||||
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(handle_cookie);
|
||||
error = binder_clear_freeze_notification(proc, thread, &handle_cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
case BC_FREEZE_NOTIFICATION_DONE: {
|
||||
binder_uintptr_t cookie;
|
||||
int error;
|
||||
|
||||
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
|
||||
ptr += sizeof(cookie);
|
||||
error = binder_freeze_notification_done(proc, thread, cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
default:
|
||||
pr_err("%d:%d unknown command %u\n",
|
||||
proc->pid, thread->pid, cmd);
|
||||
@@ -4907,6 +5095,46 @@ retry:
|
||||
if (cmd == BR_DEAD_BINDER)
|
||||
goto done; /* DEAD_BINDER notifications can cause transactions */
|
||||
} break;
|
||||
|
||||
case BINDER_WORK_FROZEN_BINDER: {
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_frozen_state_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
freeze = container_of(w, struct binder_ref_freeze, work);
|
||||
info.is_frozen = freeze->is_frozen;
|
||||
info.cookie = freeze->cookie;
|
||||
freeze->sent = true;
|
||||
binder_enqueue_work_ilocked(w, &proc->delivered_freeze);
|
||||
binder_inner_proc_unlock(proc);
|
||||
|
||||
if (put_user(BR_FROZEN_BINDER, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(uint32_t);
|
||||
if (copy_to_user(ptr, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(info);
|
||||
binder_stat_br(proc, thread, BR_FROZEN_BINDER);
|
||||
goto done; /* BR_FROZEN_BINDER notifications can cause transactions */
|
||||
} break;
|
||||
|
||||
case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
|
||||
struct binder_ref_freeze *freeze =
|
||||
container_of(w, struct binder_ref_freeze, work);
|
||||
binder_uintptr_t cookie = freeze->cookie;
|
||||
|
||||
binder_inner_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
binder_stats_deleted(BINDER_STAT_FREEZE);
|
||||
if (put_user(BR_CLEAR_FREEZE_NOTIFICATION_DONE, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(uint32_t);
|
||||
if (put_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(binder_uintptr_t);
|
||||
binder_stat_br(proc, thread, BR_CLEAR_FREEZE_NOTIFICATION_DONE);
|
||||
} break;
|
||||
|
||||
default:
|
||||
binder_inner_proc_unlock(proc);
|
||||
pr_err("%d:%d: bad work type %d\n",
|
||||
@@ -5514,6 +5742,48 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
|
||||
{
|
||||
struct rb_node *n;
|
||||
struct binder_ref *ref;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
|
||||
struct binder_node *node;
|
||||
|
||||
node = rb_entry(n, struct binder_node, rb_node);
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_lock(node);
|
||||
hlist_for_each_entry(ref, &node->refs, node_entry) {
|
||||
/*
|
||||
* Need the node lock to synchronize
|
||||
* with new notification requests and the
|
||||
* inner lock to synchronize with queued
|
||||
* freeze notifications.
|
||||
*/
|
||||
binder_inner_proc_lock(ref->proc);
|
||||
if (!ref->freeze) {
|
||||
binder_inner_proc_unlock(ref->proc);
|
||||
continue;
|
||||
}
|
||||
ref->freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||
if (list_empty(&ref->freeze->work.entry)) {
|
||||
ref->freeze->is_frozen = is_frozen;
|
||||
binder_enqueue_work_ilocked(&ref->freeze->work, &ref->proc->todo);
|
||||
binder_wakeup_proc_ilocked(ref->proc);
|
||||
} else {
|
||||
if (ref->freeze->sent && ref->freeze->is_frozen != is_frozen)
|
||||
ref->freeze->resend = true;
|
||||
ref->freeze->is_frozen = is_frozen;
|
||||
}
|
||||
binder_inner_proc_unlock(ref->proc);
|
||||
}
|
||||
binder_node_unlock(node);
|
||||
binder_inner_proc_lock(proc);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
}
|
||||
|
||||
static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
struct binder_proc *target_proc)
|
||||
{
|
||||
@@ -5525,6 +5795,7 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
target_proc->async_recv = false;
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
binder_add_freeze_work(target_proc, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5557,6 +5828,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
} else {
|
||||
binder_add_freeze_work(target_proc, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -5939,6 +6212,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
||||
binder_stats_created(BINDER_STAT_PROC);
|
||||
proc->pid = current->group_leader->pid;
|
||||
INIT_LIST_HEAD(&proc->delivered_death);
|
||||
INIT_LIST_HEAD(&proc->delivered_freeze);
|
||||
INIT_LIST_HEAD(&proc->waiting_threads);
|
||||
filp->private_data = proc;
|
||||
|
||||
@@ -6492,7 +6766,9 @@ static const char * const binder_return_strings[] = {
|
||||
"BR_FAILED_REPLY",
|
||||
"BR_FROZEN_REPLY",
|
||||
"BR_ONEWAY_SPAM_SUSPECT",
|
||||
"BR_TRANSACTION_PENDING_FROZEN"
|
||||
"BR_TRANSACTION_PENDING_FROZEN",
|
||||
"BR_FROZEN_BINDER",
|
||||
"BR_CLEAR_FREEZE_NOTIFICATION_DONE",
|
||||
};
|
||||
|
||||
static const char * const binder_command_strings[] = {
|
||||
@@ -6515,6 +6791,9 @@ static const char * const binder_command_strings[] = {
|
||||
"BC_DEAD_BINDER_DONE",
|
||||
"BC_TRANSACTION_SG",
|
||||
"BC_REPLY_SG",
|
||||
"BC_REQUEST_FREEZE_NOTIFICATION",
|
||||
"BC_CLEAR_FREEZE_NOTIFICATION",
|
||||
"BC_FREEZE_NOTIFICATION_DONE",
|
||||
};
|
||||
|
||||
static const char * const binder_objstat_strings[] = {
|
||||
@@ -6524,7 +6803,8 @@ static const char * const binder_objstat_strings[] = {
|
||||
"ref",
|
||||
"death",
|
||||
"transaction",
|
||||
"transaction_complete"
|
||||
"transaction_complete",
|
||||
"freeze",
|
||||
};
|
||||
|
||||
static void print_binder_stats(struct seq_file *m, const char *prefix,
|
||||
|
||||
@@ -130,12 +130,13 @@ enum binder_stat_types {
|
||||
BINDER_STAT_DEATH,
|
||||
BINDER_STAT_TRANSACTION,
|
||||
BINDER_STAT_TRANSACTION_COMPLETE,
|
||||
BINDER_STAT_FREEZE,
|
||||
BINDER_STAT_COUNT
|
||||
};
|
||||
|
||||
struct binder_stats {
|
||||
atomic_t br[_IOC_NR(BR_TRANSACTION_PENDING_FROZEN) + 1];
|
||||
atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
|
||||
atomic_t br[_IOC_NR(BR_CLEAR_FREEZE_NOTIFICATION_DONE) + 1];
|
||||
atomic_t bc[_IOC_NR(BC_FREEZE_NOTIFICATION_DONE) + 1];
|
||||
atomic_t obj_created[BINDER_STAT_COUNT];
|
||||
atomic_t obj_deleted[BINDER_STAT_COUNT];
|
||||
};
|
||||
@@ -160,6 +161,8 @@ struct binder_work {
|
||||
BINDER_WORK_DEAD_BINDER,
|
||||
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
|
||||
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
|
||||
BINDER_WORK_FROZEN_BINDER,
|
||||
BINDER_WORK_CLEAR_FREEZE_NOTIFICATION,
|
||||
} type;
|
||||
};
|
||||
|
||||
@@ -281,6 +284,14 @@ struct binder_ref_death {
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
|
||||
struct binder_ref_freeze {
|
||||
struct binder_work work;
|
||||
binder_uintptr_t cookie;
|
||||
bool is_frozen:1;
|
||||
bool sent:1;
|
||||
bool resend:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct binder_ref_data - binder_ref counts and id
|
||||
* @debug_id: unique ID for the ref
|
||||
@@ -313,6 +324,8 @@ struct binder_ref_data {
|
||||
* @node indicates the node must be freed
|
||||
* @death: pointer to death notification (ref_death) if requested
|
||||
* (protected by @node->lock)
|
||||
* @freeze: pointer to freeze notification (ref_freeze) if requested
|
||||
* (protected by @node->lock)
|
||||
*
|
||||
* Structure to track references from procA to target node (on procB). This
|
||||
* structure is unsafe to access without holding @proc->outer_lock.
|
||||
@@ -329,6 +342,7 @@ struct binder_ref {
|
||||
struct binder_proc *proc;
|
||||
struct binder_node *node;
|
||||
struct binder_ref_death *death;
|
||||
struct binder_ref_freeze *freeze;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -404,6 +418,8 @@ enum binder_prio_state {
|
||||
* (atomics, no lock needed)
|
||||
* @delivered_death: list of delivered death notification
|
||||
* (protected by @inner_lock)
|
||||
* @delivered_freeze: list of delivered freeze notification
|
||||
* (protected by @inner_lock)
|
||||
* @max_threads: cap on number of binder threads
|
||||
* (protected by @inner_lock)
|
||||
* @requested_threads: number of binder threads requested but not
|
||||
@@ -451,6 +467,7 @@ struct binder_proc {
|
||||
struct list_head todo;
|
||||
struct binder_stats stats;
|
||||
struct list_head delivered_death;
|
||||
struct list_head delivered_freeze;
|
||||
u32 max_threads;
|
||||
int requested_threads;
|
||||
int requested_threads_started;
|
||||
|
||||
@@ -58,6 +58,7 @@ enum binderfs_stats_mode {
|
||||
struct binder_features {
|
||||
bool oneway_spam_detection;
|
||||
bool extended_error;
|
||||
bool freeze_notification;
|
||||
};
|
||||
|
||||
static const struct constant_table binderfs_param_stats[] = {
|
||||
@@ -74,6 +75,7 @@ static const struct fs_parameter_spec binderfs_fs_parameters[] = {
|
||||
static struct binder_features binder_features = {
|
||||
.oneway_spam_detection = true,
|
||||
.extended_error = true,
|
||||
.freeze_notification = true,
|
||||
};
|
||||
|
||||
static inline struct binderfs_info *BINDERFS_SB(const struct super_block *sb)
|
||||
@@ -608,6 +610,12 @@ static int init_binder_features(struct super_block *sb)
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
dentry = binderfs_create_file(dir, "freeze_notification",
|
||||
&binder_features_fops,
|
||||
&binder_features.freeze_notification);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+13
-28
@@ -202,29 +202,24 @@ static void cache_of_set_props(struct cacheinfo *this_leaf,
|
||||
|
||||
static int cache_setup_of_node(unsigned int cpu)
|
||||
{
|
||||
struct device_node *np, *prev;
|
||||
struct cacheinfo *this_leaf;
|
||||
unsigned int index = 0;
|
||||
|
||||
np = of_cpu_device_node_get(cpu);
|
||||
struct device_node *np __free(device_node) = of_cpu_device_node_get(cpu);
|
||||
if (!np) {
|
||||
pr_err("Failed to find cpu%d device node\n", cpu);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!of_check_cache_nodes(np)) {
|
||||
of_node_put(np);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
prev = np;
|
||||
|
||||
while (index < cache_leaves(cpu)) {
|
||||
this_leaf = per_cpu_cacheinfo_idx(cpu, index);
|
||||
if (this_leaf->level != 1) {
|
||||
struct device_node *prev __free(device_node) = np;
|
||||
np = of_find_next_cache_node(np);
|
||||
of_node_put(prev);
|
||||
prev = np;
|
||||
if (!np)
|
||||
break;
|
||||
}
|
||||
@@ -233,8 +228,6 @@ static int cache_setup_of_node(unsigned int cpu)
|
||||
index++;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
if (index != cache_leaves(cpu)) /* not all OF nodes populated */
|
||||
return -ENOENT;
|
||||
|
||||
@@ -243,17 +236,14 @@ static int cache_setup_of_node(unsigned int cpu)
|
||||
|
||||
static bool of_check_cache_nodes(struct device_node *np)
|
||||
{
|
||||
struct device_node *next;
|
||||
|
||||
if (of_property_present(np, "cache-size") ||
|
||||
of_property_present(np, "i-cache-size") ||
|
||||
of_property_present(np, "d-cache-size") ||
|
||||
of_property_present(np, "cache-unified"))
|
||||
return true;
|
||||
|
||||
next = of_find_next_cache_node(np);
|
||||
struct device_node *next __free(device_node) = of_find_next_cache_node(np);
|
||||
if (next) {
|
||||
of_node_put(next);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -287,12 +277,10 @@ static int of_count_cache_leaves(struct device_node *np)
|
||||
int init_of_cache_level(unsigned int cpu)
|
||||
{
|
||||
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
||||
struct device_node *np = of_cpu_device_node_get(cpu);
|
||||
struct device_node *prev = NULL;
|
||||
struct device_node *np __free(device_node) = of_cpu_device_node_get(cpu);
|
||||
unsigned int levels = 0, leaves, level;
|
||||
|
||||
if (!of_check_cache_nodes(np)) {
|
||||
of_node_put(np);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -300,30 +288,27 @@ int init_of_cache_level(unsigned int cpu)
|
||||
if (leaves > 0)
|
||||
levels = 1;
|
||||
|
||||
prev = np;
|
||||
while ((np = of_find_next_cache_node(np))) {
|
||||
of_node_put(prev);
|
||||
prev = np;
|
||||
while (1) {
|
||||
struct device_node *prev __free(device_node) = np;
|
||||
np = of_find_next_cache_node(np);
|
||||
if (!np)
|
||||
break;
|
||||
|
||||
if (!of_device_is_compatible(np, "cache"))
|
||||
goto err_out;
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "cache-level", &level))
|
||||
goto err_out;
|
||||
return -EINVAL;
|
||||
if (level <= levels)
|
||||
goto err_out;
|
||||
return -EINVAL;
|
||||
|
||||
leaves += of_count_cache_leaves(np);
|
||||
levels = level;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
this_cpu_ci->num_levels = levels;
|
||||
this_cpu_ci->num_leaves = leaves;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
of_node_put(np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@@ -1464,7 +1464,7 @@ static int mhi_match(struct device *dev, const struct device_driver *drv)
|
||||
return 0;
|
||||
};
|
||||
|
||||
struct bus_type mhi_bus_type = {
|
||||
const struct bus_type mhi_bus_type = {
|
||||
.name = "mhi",
|
||||
.dev_name = "mhi",
|
||||
.match = mhi_match,
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
extern struct bus_type mhi_bus_type;
|
||||
extern const struct bus_type mhi_bus_type;
|
||||
|
||||
/* Host request register */
|
||||
#define MHI_SOC_RESET_REQ_OFFSET 0xb0
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
/* PCI VID definitions */
|
||||
#define PCI_VENDOR_ID_THALES 0x1269
|
||||
#define PCI_VENDOR_ID_QUECTEL 0x1eac
|
||||
#define PCI_VENDOR_ID_NETPRISMA 0x203e
|
||||
|
||||
#define MHI_EDL_DB 91
|
||||
#define MHI_EDL_COOKIE 0xEDEDEDED
|
||||
@@ -433,8 +434,8 @@ static const struct mhi_controller_config modem_foxconn_sdx72_config = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = {
|
||||
.name = "foxconn-sdx55",
|
||||
.fw = "qcom/sdx55m/sbl1.mbn",
|
||||
.edl = "qcom/sdx55m/edl.mbn",
|
||||
.edl = "qcom/sdx55m/foxconn/prog_firehose_sdx55.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@@ -444,8 +445,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w175_info = {
|
||||
.name = "foxconn-t99w175",
|
||||
.fw = "qcom/sdx55m/sbl1.mbn",
|
||||
.edl = "qcom/sdx55m/edl.mbn",
|
||||
.edl = "qcom/sdx55m/foxconn/prog_firehose_sdx55.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@@ -455,8 +456,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w175_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_dw5930e_info = {
|
||||
.name = "foxconn-dw5930e",
|
||||
.fw = "qcom/sdx55m/sbl1.mbn",
|
||||
.edl = "qcom/sdx55m/edl.mbn",
|
||||
.edl = "qcom/sdx55m/foxconn/prog_firehose_sdx55.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@@ -466,6 +467,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_dw5930e_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w368_info = {
|
||||
.name = "foxconn-t99w368",
|
||||
.edl = "qcom/sdx65m/foxconn/prog_firehose_lite.elf",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@@ -475,6 +478,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w368_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w373_info = {
|
||||
.name = "foxconn-t99w373",
|
||||
.edl = "qcom/sdx65m/foxconn/prog_firehose_lite.elf",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@@ -484,6 +489,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w373_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w510_info = {
|
||||
.name = "foxconn-t99w510",
|
||||
.edl = "qcom/sdx24m/foxconn/prog_firehose_sdx24.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@@ -493,6 +500,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w510_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_dw5932e_info = {
|
||||
.name = "foxconn-dw5932e",
|
||||
.edl = "qcom/sdx65m/foxconn/prog_firehose_lite.elf",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@@ -502,7 +511,7 @@ static const struct mhi_pci_dev_info mhi_foxconn_dw5932e_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w515_info = {
|
||||
.name = "foxconn-t99w515",
|
||||
.edl = "fox/sdx72m/edl.mbn",
|
||||
.edl = "qcom/sdx72m/foxconn/edl.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx72_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
@@ -513,7 +522,7 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w515_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_dw5934e_info = {
|
||||
.name = "foxconn-dw5934e",
|
||||
.edl = "fox/sdx72m/edl.mbn",
|
||||
.edl = "qcom/sdx72m/foxconn/edl.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx72_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
@@ -680,6 +689,35 @@ static const struct mhi_pci_dev_info mhi_telit_fn990_info = {
|
||||
.mru_default = 32768,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_telit_fe990a_info = {
|
||||
.name = "telit-fe990a",
|
||||
.config = &modem_telit_fn990_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.sideband_wake = false,
|
||||
.mru_default = 32768,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = {
|
||||
.name = "netprisma-lcur57",
|
||||
.edl = "qcom/prog_firehose_sdx24.mbn",
|
||||
.config = &modem_quectel_em1xx_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.mru_default = 32768,
|
||||
.sideband_wake = true,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_netprisma_fcun69_info = {
|
||||
.name = "netprisma-fcun69",
|
||||
.edl = "qcom/prog_firehose_sdx6x.elf",
|
||||
.config = &modem_quectel_em1xx_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.mru_default = 32768,
|
||||
.sideband_wake = true,
|
||||
};
|
||||
|
||||
/* Keep the list sorted based on the PID. New VID should be added as the last entry */
|
||||
static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),
|
||||
@@ -697,9 +735,9 @@ static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
/* Telit FN990 */
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2010),
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fn990_info },
|
||||
/* Telit FE990 */
|
||||
/* Telit FE990A */
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2015),
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fn990_info },
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fe990a_info },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0308),
|
||||
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx65_info },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0309),
|
||||
@@ -778,6 +816,12 @@ static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
/* T99W175 (sdx55), HP variant */
|
||||
{ PCI_DEVICE(0x03f0, 0x0a6c),
|
||||
.driver_data = (kernel_ulong_t) &mhi_foxconn_t99w175_info },
|
||||
/* NETPRISMA LCUR57 (SDX24) */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NETPRISMA, 0x1000),
|
||||
.driver_data = (kernel_ulong_t) &mhi_netprisma_lcur57_info },
|
||||
/* NETPRISMA FCUN69 (SDX6X) */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NETPRISMA, 0x1001),
|
||||
.driver_data = (kernel_ulong_t) &mhi_netprisma_fcun69_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
#include "bitfield.h"
|
||||
#include "mcdi.h"
|
||||
|
||||
struct cdx_mcdi_copy_buffer {
|
||||
struct cdx_dword buffer[DIV_ROUND_UP(MCDI_CTL_SDU_LEN_MAX, 4)];
|
||||
};
|
||||
|
||||
static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd);
|
||||
static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx);
|
||||
static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx,
|
||||
|
||||
+3
-3
@@ -808,7 +808,7 @@ int hpet_alloc(struct hpet_data *hdp)
|
||||
struct hpets *hpetp;
|
||||
struct hpet __iomem *hpet;
|
||||
static struct hpets *last;
|
||||
unsigned long period;
|
||||
u32 period;
|
||||
unsigned long long temp;
|
||||
u32 remainder;
|
||||
|
||||
@@ -865,11 +865,11 @@ int hpet_alloc(struct hpet_data *hdp)
|
||||
do_div(temp, period);
|
||||
hpetp->hp_tick_freq = temp; /* ticks per second */
|
||||
|
||||
printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
|
||||
printk(KERN_INFO "hpet%u: at MMIO 0x%lx, IRQ%s",
|
||||
hpetp->hp_which, hdp->hd_phys_address,
|
||||
hpetp->hp_ntimer > 1 ? "s" : "");
|
||||
for (i = 0; i < hpetp->hp_ntimer; i++)
|
||||
printk(KERN_CONT "%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
|
||||
printk(KERN_CONT "%s %u", i > 0 ? "," : "", hdp->hd_irq[i]);
|
||||
printk(KERN_CONT "\n");
|
||||
|
||||
temp = hpetp->hp_tick_freq;
|
||||
|
||||
@@ -79,6 +79,15 @@
|
||||
|
||||
#include "ni_stc.h"
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext = {
|
||||
4, {
|
||||
BIP_RANGE(10),
|
||||
UNI_RANGE(10),
|
||||
RANGE_ext(-1, 1),
|
||||
RANGE_ext(0, 1)
|
||||
}
|
||||
};
|
||||
|
||||
/* AT specific setup */
|
||||
static const struct ni_board_struct ni_boards[] = {
|
||||
{
|
||||
|
||||
@@ -166,15 +166,6 @@ static const struct comedi_lrange range_ni_M_ai_628x = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext = {
|
||||
4, {
|
||||
BIP_RANGE(10),
|
||||
UNI_RANGE(10),
|
||||
RANGE_ext(-1, 1),
|
||||
RANGE_ext(0, 1)
|
||||
}
|
||||
};
|
||||
|
||||
static const struct comedi_lrange *const ni_range_lkup[] = {
|
||||
[ai_gain_16] = &range_ni_E_ai,
|
||||
[ai_gain_8] = &range_ni_E_ai_limited,
|
||||
|
||||
@@ -102,6 +102,15 @@
|
||||
|
||||
#define PCIDMA
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext = {
|
||||
4, {
|
||||
BIP_RANGE(10),
|
||||
UNI_RANGE(10),
|
||||
RANGE_ext(-1, 1),
|
||||
RANGE_ext(0, 1)
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* These are not all the possible ao ranges for 628x boards.
|
||||
* They can do OFFSET +- REFERENCE where OFFSET can be
|
||||
|
||||
@@ -140,6 +140,11 @@ int main(void)
|
||||
{
|
||||
FILE *fp = fopen("ni_values.py", "w");
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Could not open file!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* write route register values */
|
||||
fprintf(fp, "ni_route_values = {\n");
|
||||
for (int i = 0; ni_all_route_values[i]; ++i)
|
||||
|
||||
@@ -1137,6 +1137,4 @@ struct ni_private {
|
||||
u8 rgout0_usage;
|
||||
};
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext;
|
||||
|
||||
#endif /* _COMEDI_NI_STC_H */
|
||||
|
||||
@@ -75,6 +75,17 @@ config EXTCON_INTEL_MRFLD
|
||||
Say Y here to enable extcon support for charger detection / control
|
||||
on the Intel Merrifield Basin Cove PMIC.
|
||||
|
||||
config EXTCON_LC824206XA
|
||||
tristate "LC824206XA extcon Support"
|
||||
depends on I2C
|
||||
depends on POWER_SUPPLY
|
||||
help
|
||||
Say Y here to enable support for the ON Semiconductor LC824206XA
|
||||
microUSB switch and accessory detector chip. The LC824206XA is a USB
|
||||
port accessory detector and switch. The LC824206XA is fully controlled
|
||||
using I2C and enables USB data, stereo and mono audio, video,
|
||||
microphone and UART data to use a common connector port.
|
||||
|
||||
config EXTCON_MAX14577
|
||||
tristate "Maxim MAX14577/77836 EXTCON Support"
|
||||
depends on MFD_MAX14577
|
||||
|
||||
@@ -12,6 +12,7 @@ obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
|
||||
obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
|
||||
obj-$(CONFIG_EXTCON_INTEL_CHT_WC) += extcon-intel-cht-wc.o
|
||||
obj-$(CONFIG_EXTCON_INTEL_MRFLD) += extcon-intel-mrfld.o
|
||||
obj-$(CONFIG_EXTCON_LC824206XA) += extcon-lc824206xa.o
|
||||
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
|
||||
obj-$(CONFIG_EXTCON_MAX3355) += extcon-max3355.o
|
||||
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
|
||||
|
||||
@@ -0,0 +1,495 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* ON Semiconductor LC824206XA Micro USB Switch driver
|
||||
*
|
||||
* Copyright (c) 2024 Hans de Goede <hansg@kernel.org>
|
||||
*
|
||||
* ON Semiconductor has an "Advance Information" datasheet available
|
||||
* (ENA2222-D.PDF), but no full datasheet. So there is no documentation
|
||||
* available for the registers.
|
||||
*
|
||||
* This driver is based on the register info from the extcon-fsa9285.c driver,
|
||||
* from the Lollipop Android sources for the Lenovo Yoga Tablet 2 (Pro)
|
||||
* 830 / 1050 / 1380 models. Note despite the name this is actually a driver
|
||||
* for the LC824206XA not the FSA9285. The Android sources can be downloaded
|
||||
* from Lenovo's support page for these tablets, filename:
|
||||
* yoga_tab_2_osc_android_to_lollipop_201505.rar.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/extcon-provider.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/*
|
||||
* Register defines as mentioned above there is no datasheet with register
|
||||
* info, so this may not be 100% accurate.
|
||||
*/
|
||||
#define REG00 0x00
|
||||
#define REG00_INIT_VALUE 0x01
|
||||
|
||||
#define REG_STATUS 0x01
|
||||
#define STATUS_OVP BIT(0)
|
||||
#define STATUS_DATA_SHORT BIT(1)
|
||||
#define STATUS_VBUS_PRESENT BIT(2)
|
||||
#define STATUS_USB_ID GENMASK(7, 3)
|
||||
#define STATUS_USB_ID_GND 0x80
|
||||
#define STATUS_USB_ID_ACA 0xf0
|
||||
#define STATUS_USB_ID_FLOAT 0xf8
|
||||
|
||||
/*
|
||||
* This controls the DP/DM muxes + other switches,
|
||||
* meaning of individual bits is unknown.
|
||||
*/
|
||||
#define REG_SWITCH_CONTROL 0x02
|
||||
#define SWITCH_STEREO_MIC 0xc8
|
||||
#define SWITCH_USB_HOST 0xec
|
||||
#define SWITCH_DISCONNECTED 0xf8
|
||||
#define SWITCH_USB_DEVICE 0xfc
|
||||
|
||||
/* 5 bits? ADC 0x10 GND, 0x1a-0x1f ACA, 0x1f float */
|
||||
#define REG_ID_PIN_ADC_VALUE 0x03
|
||||
|
||||
/* Masks for all 3 interrupt registers */
|
||||
#define INTR_ID_PIN_CHANGE BIT(0)
|
||||
#define INTR_VBUS_CHANGE BIT(1)
|
||||
/* Both of these get set after a continuous mode ADC conversion */
|
||||
#define INTR_ID_PIN_ADC_INT1 BIT(2)
|
||||
#define INTR_ID_PIN_ADC_INT2 BIT(3)
|
||||
/* Charger type available in reg 0x09 */
|
||||
#define INTR_CHARGER_DET_DONE BIT(4)
|
||||
#define INTR_OVP BIT(5)
|
||||
|
||||
/* There are 7 interrupt sources, bit 6 use is unknown (OCP?) */
|
||||
#define INTR_ALL GENMASK(6, 0)
|
||||
|
||||
/* Unmask interrupts this driver cares about */
|
||||
#define INTR_MASK \
|
||||
(INTR_ALL & ~(INTR_ID_PIN_CHANGE | INTR_VBUS_CHANGE | INTR_CHARGER_DET_DONE))
|
||||
|
||||
/* Active (event happened and not cleared yet) interrupts */
|
||||
#define REG_INTR_STATUS 0x04
|
||||
|
||||
/*
|
||||
* Writing a 1 to a bit here clears it in INTR_STATUS. These bits do NOT
|
||||
* auto-reset to 0, so these must be set to 0 manually after clearing.
|
||||
*/
|
||||
#define REG_INTR_CLEAR 0x05
|
||||
|
||||
/* Interrupts which bit is set to 1 here will not raise the HW IRQ */
|
||||
#define REG_INTR_MASK 0x06
|
||||
|
||||
/* ID pin ADC control, meaning of individual bits is unknown */
|
||||
#define REG_ID_PIN_ADC_CTRL 0x07
|
||||
#define ID_PIN_ADC_AUTO 0x40
|
||||
#define ID_PIN_ADC_CONTINUOUS 0x44
|
||||
|
||||
#define REG_CHARGER_DET 0x08
|
||||
#define CHARGER_DET_ON BIT(0)
|
||||
#define CHARGER_DET_CDP_ON BIT(1)
|
||||
#define CHARGER_DET_CDP_VAL BIT(2)
|
||||
|
||||
#define REG_CHARGER_TYPE 0x09
|
||||
#define CHARGER_TYPE_UNKNOWN 0x00
|
||||
#define CHARGER_TYPE_DCP 0x01
|
||||
#define CHARGER_TYPE_SDP_OR_CDP 0x04
|
||||
#define CHARGER_TYPE_QC 0x06
|
||||
|
||||
#define REG10 0x10
|
||||
#define REG10_INIT_VALUE 0x00
|
||||
|
||||
struct lc824206xa_data {
|
||||
struct work_struct work;
|
||||
struct i2c_client *client;
|
||||
struct extcon_dev *edev;
|
||||
struct power_supply *psy;
|
||||
struct regulator *vbus_boost;
|
||||
unsigned int usb_type;
|
||||
unsigned int cable;
|
||||
unsigned int previous_cable;
|
||||
u8 switch_control;
|
||||
u8 previous_switch_control;
|
||||
bool vbus_ok;
|
||||
bool vbus_boost_enabled;
|
||||
bool fastcharge_over_miclr;
|
||||
};
|
||||
|
||||
static const unsigned int lc824206xa_cables[] = {
|
||||
EXTCON_USB_HOST,
|
||||
EXTCON_CHG_USB_SDP,
|
||||
EXTCON_CHG_USB_CDP,
|
||||
EXTCON_CHG_USB_DCP,
|
||||
EXTCON_CHG_USB_ACA,
|
||||
EXTCON_CHG_USB_FAST,
|
||||
EXTCON_NONE,
|
||||
};
|
||||
|
||||
/* read/write reg helpers to add error logging to smbus byte functions */
|
||||
static int lc824206xa_read_reg(struct lc824206xa_data *data, u8 reg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_read_byte_data(data->client, reg);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev, "Error %d reading reg 0x%02x\n", ret, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lc824206xa_write_reg(struct lc824206xa_data *data, u8 reg, u8 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = i2c_smbus_write_byte_data(data->client, reg, val);
|
||||
if (ret < 0)
|
||||
dev_err(&data->client->dev, "Error %d writing reg 0x%02x\n", ret, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lc824206xa_get_id(struct lc824206xa_data *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lc824206xa_write_reg(data, REG_ID_PIN_ADC_CTRL, ID_PIN_ADC_CONTINUOUS);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = lc824206xa_read_reg(data, REG_ID_PIN_ADC_VALUE);
|
||||
|
||||
lc824206xa_write_reg(data, REG_ID_PIN_ADC_CTRL, ID_PIN_ADC_AUTO);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void lc824206xa_set_vbus_boost(struct lc824206xa_data *data, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (data->vbus_boost_enabled == enable)
|
||||
return;
|
||||
|
||||
if (enable)
|
||||
ret = regulator_enable(data->vbus_boost);
|
||||
else
|
||||
ret = regulator_disable(data->vbus_boost);
|
||||
|
||||
if (ret == 0)
|
||||
data->vbus_boost_enabled = enable;
|
||||
else
|
||||
dev_err(&data->client->dev, "Error updating Vbus boost regulator: %d\n", ret);
|
||||
}
|
||||
|
||||
static void lc824206xa_charger_detect(struct lc824206xa_data *data)
|
||||
{
|
||||
int charger_type, ret;
|
||||
|
||||
charger_type = lc824206xa_read_reg(data, REG_CHARGER_TYPE);
|
||||
if (charger_type < 0)
|
||||
return;
|
||||
|
||||
dev_dbg(&data->client->dev, "charger type 0x%02x\n", charger_type);
|
||||
|
||||
switch (charger_type) {
|
||||
case CHARGER_TYPE_UNKNOWN:
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
|
||||
/* Treat as SDP */
|
||||
data->cable = EXTCON_CHG_USB_SDP;
|
||||
data->switch_control = SWITCH_USB_DEVICE;
|
||||
break;
|
||||
case CHARGER_TYPE_SDP_OR_CDP:
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_SDP;
|
||||
data->cable = EXTCON_CHG_USB_SDP;
|
||||
data->switch_control = SWITCH_USB_DEVICE;
|
||||
|
||||
ret = lc824206xa_write_reg(data, REG_CHARGER_DET,
|
||||
CHARGER_DET_CDP_ON | CHARGER_DET_ON);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
msleep(100);
|
||||
ret = lc824206xa_read_reg(data, REG_CHARGER_DET);
|
||||
if (ret >= 0 && (ret & CHARGER_DET_CDP_VAL)) {
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_CDP;
|
||||
data->cable = EXTCON_CHG_USB_CDP;
|
||||
}
|
||||
|
||||
lc824206xa_write_reg(data, REG_CHARGER_DET, CHARGER_DET_ON);
|
||||
break;
|
||||
case CHARGER_TYPE_DCP:
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_DCP;
|
||||
data->cable = EXTCON_CHG_USB_DCP;
|
||||
if (data->fastcharge_over_miclr)
|
||||
data->switch_control = SWITCH_STEREO_MIC;
|
||||
else
|
||||
data->switch_control = SWITCH_DISCONNECTED;
|
||||
break;
|
||||
case CHARGER_TYPE_QC:
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_DCP;
|
||||
data->cable = EXTCON_CHG_USB_DCP;
|
||||
data->switch_control = SWITCH_DISCONNECTED;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&data->client->dev, "Unknown charger type: 0x%02x\n", charger_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void lc824206xa_work(struct work_struct *work)
|
||||
{
|
||||
struct lc824206xa_data *data = container_of(work, struct lc824206xa_data, work);
|
||||
bool vbus_boost_enable = false;
|
||||
int status, id;
|
||||
|
||||
status = lc824206xa_read_reg(data, REG_STATUS);
|
||||
if (status < 0)
|
||||
return;
|
||||
|
||||
dev_dbg(&data->client->dev, "status 0x%02x\n", status);
|
||||
|
||||
data->vbus_ok = (status & (STATUS_VBUS_PRESENT | STATUS_OVP)) == STATUS_VBUS_PRESENT;
|
||||
|
||||
/* Read id pin ADC if necessary */
|
||||
switch (status & STATUS_USB_ID) {
|
||||
case STATUS_USB_ID_GND:
|
||||
case STATUS_USB_ID_FLOAT:
|
||||
break;
|
||||
default:
|
||||
/* Happens when the connector is inserted slowly, log at dbg level */
|
||||
dev_dbg(&data->client->dev, "Unknown status 0x%02x\n", status);
|
||||
fallthrough;
|
||||
case STATUS_USB_ID_ACA:
|
||||
id = lc824206xa_get_id(data);
|
||||
dev_dbg(&data->client->dev, "RID 0x%02x\n", id);
|
||||
switch (id) {
|
||||
case 0x10:
|
||||
status = STATUS_USB_ID_GND;
|
||||
break;
|
||||
case 0x18 ... 0x1e:
|
||||
status = STATUS_USB_ID_ACA;
|
||||
break;
|
||||
case 0x1f:
|
||||
status = STATUS_USB_ID_FLOAT;
|
||||
break;
|
||||
default:
|
||||
dev_warn(&data->client->dev, "Unknown RID 0x%02x\n", id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for out of spec OTG charging hubs, treat as ACA */
|
||||
if ((status & STATUS_USB_ID) == STATUS_USB_ID_GND &&
|
||||
data->vbus_ok && !data->vbus_boost_enabled) {
|
||||
dev_info(&data->client->dev, "Out of spec USB host adapter with Vbus present, not enabling 5V output\n");
|
||||
status = STATUS_USB_ID_ACA;
|
||||
}
|
||||
|
||||
switch (status & STATUS_USB_ID) {
|
||||
case STATUS_USB_ID_ACA:
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_ACA;
|
||||
data->cable = EXTCON_CHG_USB_ACA;
|
||||
data->switch_control = SWITCH_USB_HOST;
|
||||
break;
|
||||
case STATUS_USB_ID_GND:
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
|
||||
data->cable = EXTCON_USB_HOST;
|
||||
data->switch_control = SWITCH_USB_HOST;
|
||||
vbus_boost_enable = true;
|
||||
break;
|
||||
case STATUS_USB_ID_FLOAT:
|
||||
/* When fast charging with Vbus > 5V, OVP will be set */
|
||||
if (data->fastcharge_over_miclr &&
|
||||
data->switch_control == SWITCH_STEREO_MIC &&
|
||||
(status & STATUS_OVP)) {
|
||||
data->cable = EXTCON_CHG_USB_FAST;
|
||||
break;
|
||||
}
|
||||
|
||||
if (data->vbus_ok) {
|
||||
lc824206xa_charger_detect(data);
|
||||
} else {
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
|
||||
data->cable = EXTCON_NONE;
|
||||
data->switch_control = SWITCH_DISCONNECTED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
lc824206xa_set_vbus_boost(data, vbus_boost_enable);
|
||||
|
||||
if (data->switch_control != data->previous_switch_control) {
|
||||
lc824206xa_write_reg(data, REG_SWITCH_CONTROL, data->switch_control);
|
||||
data->previous_switch_control = data->switch_control;
|
||||
}
|
||||
|
||||
if (data->cable != data->previous_cable) {
|
||||
extcon_set_state_sync(data->edev, data->previous_cable, false);
|
||||
extcon_set_state_sync(data->edev, data->cable, true);
|
||||
data->previous_cable = data->cable;
|
||||
}
|
||||
|
||||
power_supply_changed(data->psy);
|
||||
}
|
||||
|
||||
static irqreturn_t lc824206xa_irq(int irq, void *_data)
|
||||
{
|
||||
struct lc824206xa_data *data = _data;
|
||||
int intr_status;
|
||||
|
||||
intr_status = lc824206xa_read_reg(data, REG_INTR_STATUS);
|
||||
if (intr_status < 0)
|
||||
intr_status = INTR_ALL; /* Should never happen, clear all */
|
||||
|
||||
dev_dbg(&data->client->dev, "interrupt 0x%02x\n", intr_status);
|
||||
|
||||
lc824206xa_write_reg(data, REG_INTR_CLEAR, intr_status);
|
||||
lc824206xa_write_reg(data, REG_INTR_CLEAR, 0);
|
||||
|
||||
schedule_work(&data->work);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Newer charger (power_supply) drivers expect the max input current to be
|
||||
* provided by a parent power_supply device for the charger chip.
|
||||
*/
|
||||
static int lc824206xa_psy_get_prop(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct lc824206xa_data *data = power_supply_get_drvdata(psy);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
val->intval = data->vbus_ok && !data->vbus_boost_enabled;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_USB_TYPE:
|
||||
val->intval = data->usb_type;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
switch (data->usb_type) {
|
||||
case POWER_SUPPLY_USB_TYPE_DCP:
|
||||
case POWER_SUPPLY_USB_TYPE_ACA:
|
||||
val->intval = 2000000;
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_CDP:
|
||||
val->intval = 1500000;
|
||||
break;
|
||||
default:
|
||||
val->intval = 500000;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const enum power_supply_property lc824206xa_psy_props[] = {
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_USB_TYPE,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
};
|
||||
|
||||
static const struct power_supply_desc lc824206xa_psy_desc = {
|
||||
.name = "lc824206xa-charger-detect",
|
||||
.type = POWER_SUPPLY_TYPE_USB,
|
||||
.usb_types = BIT(POWER_SUPPLY_USB_TYPE_SDP) |
|
||||
BIT(POWER_SUPPLY_USB_TYPE_CDP) |
|
||||
BIT(POWER_SUPPLY_USB_TYPE_DCP) |
|
||||
BIT(POWER_SUPPLY_USB_TYPE_ACA) |
|
||||
BIT(POWER_SUPPLY_USB_TYPE_UNKNOWN),
|
||||
.properties = lc824206xa_psy_props,
|
||||
.num_properties = ARRAY_SIZE(lc824206xa_psy_props),
|
||||
.get_property = lc824206xa_psy_get_prop,
|
||||
};
|
||||
|
||||
static int lc824206xa_probe(struct i2c_client *client)
|
||||
{
|
||||
struct power_supply_config psy_cfg = { };
|
||||
struct device *dev = &client->dev;
|
||||
struct lc824206xa_data *data;
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
INIT_WORK(&data->work, lc824206xa_work);
|
||||
data->cable = EXTCON_NONE;
|
||||
data->previous_cable = EXTCON_NONE;
|
||||
data->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
|
||||
/* Some designs use a custom fast-charge protocol over the mic L/R inputs */
|
||||
data->fastcharge_over_miclr =
|
||||
device_property_read_bool(dev, "onnn,enable-miclr-for-dcp");
|
||||
|
||||
data->vbus_boost = devm_regulator_get(dev, "vbus");
|
||||
if (IS_ERR(data->vbus_boost))
|
||||
return dev_err_probe(dev, PTR_ERR(data->vbus_boost),
|
||||
"getting regulator\n");
|
||||
|
||||
/* Init */
|
||||
ret = lc824206xa_write_reg(data, REG00, REG00_INIT_VALUE);
|
||||
ret |= lc824206xa_write_reg(data, REG10, REG10_INIT_VALUE);
|
||||
msleep(100);
|
||||
ret |= lc824206xa_write_reg(data, REG_INTR_CLEAR, INTR_ALL);
|
||||
ret |= lc824206xa_write_reg(data, REG_INTR_CLEAR, 0);
|
||||
ret |= lc824206xa_write_reg(data, REG_INTR_MASK, INTR_MASK);
|
||||
ret |= lc824206xa_write_reg(data, REG_ID_PIN_ADC_CTRL, ID_PIN_ADC_AUTO);
|
||||
ret |= lc824206xa_write_reg(data, REG_CHARGER_DET, CHARGER_DET_ON);
|
||||
if (ret)
|
||||
return -EIO;
|
||||
|
||||
/* Initialize extcon device */
|
||||
data->edev = devm_extcon_dev_allocate(dev, lc824206xa_cables);
|
||||
if (IS_ERR(data->edev))
|
||||
return PTR_ERR(data->edev);
|
||||
|
||||
ret = devm_extcon_dev_register(dev, data->edev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "registering extcon device\n");
|
||||
|
||||
psy_cfg.drv_data = data;
|
||||
data->psy = devm_power_supply_register(dev, &lc824206xa_psy_desc, &psy_cfg);
|
||||
if (IS_ERR(data->psy))
|
||||
return dev_err_probe(dev, PTR_ERR(data->psy), "registering power supply\n");
|
||||
|
||||
ret = devm_request_threaded_irq(dev, client->irq, NULL, lc824206xa_irq,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
KBUILD_MODNAME, data);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "requesting IRQ\n");
|
||||
|
||||
/* Sync initial state */
|
||||
schedule_work(&data->work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id lc824206xa_i2c_ids[] = {
|
||||
{ "lc824206xa" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lc824206xa_i2c_ids);
|
||||
|
||||
static struct i2c_driver lc824206xa_driver = {
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
},
|
||||
.probe = lc824206xa_probe,
|
||||
.id_table = lc824206xa_i2c_ids,
|
||||
};
|
||||
|
||||
module_i2c_driver(lc824206xa_driver);
|
||||
|
||||
MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>");
|
||||
MODULE_DESCRIPTION("LC824206XA Micro USB Switch driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -301,16 +301,17 @@ static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id)
|
||||
|
||||
static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv)
|
||||
{
|
||||
int timeout, ret = 0;
|
||||
int ret = 0;
|
||||
long time_left;
|
||||
|
||||
socfpga_fpga_disable_irqs(priv);
|
||||
init_completion(&priv->status_complete);
|
||||
socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE);
|
||||
|
||||
timeout = wait_for_completion_interruptible_timeout(
|
||||
time_left = wait_for_completion_interruptible_timeout(
|
||||
&priv->status_complete,
|
||||
msecs_to_jiffies(10));
|
||||
if (timeout == 0)
|
||||
if (time_left == 0)
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
socfpga_fpga_disable_irqs(priv);
|
||||
|
||||
@@ -23,6 +23,13 @@ struct bridge_ctx {
|
||||
struct bridge_stats stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper to avoid a cast warning when passing the action function directly
|
||||
* to kunit_add_action().
|
||||
*/
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper, fpga_bridge_unregister,
|
||||
struct fpga_bridge *);
|
||||
|
||||
static int op_enable_set(struct fpga_bridge *bridge, bool enable)
|
||||
{
|
||||
struct bridge_stats *stats = bridge->priv;
|
||||
@@ -50,6 +57,7 @@ static const struct fpga_bridge_ops fake_bridge_ops = {
|
||||
static struct bridge_ctx *register_test_bridge(struct kunit *test, const char *dev_name)
|
||||
{
|
||||
struct bridge_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
|
||||
@@ -61,13 +69,10 @@ static struct bridge_ctx *register_test_bridge(struct kunit *test, const char *d
|
||||
&ctx->stats);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->bridge));
|
||||
|
||||
return ctx;
|
||||
}
|
||||
ret = kunit_add_action_or_reset(test, fpga_bridge_unregister_wrapper, ctx->bridge);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
static void unregister_test_bridge(struct kunit *test, struct bridge_ctx *ctx)
|
||||
{
|
||||
fpga_bridge_unregister(ctx->bridge);
|
||||
kunit_device_unregister(test, ctx->dev);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void fpga_bridge_test_get(struct kunit *test)
|
||||
@@ -141,8 +146,6 @@ static void fpga_bridge_test_get_put_list(struct kunit *test)
|
||||
fpga_bridges_put(&bridge_list);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, list_empty(&bridge_list));
|
||||
|
||||
unregister_test_bridge(test, ctx_1);
|
||||
}
|
||||
|
||||
static int fpga_bridge_test_init(struct kunit *test)
|
||||
@@ -152,11 +155,6 @@ static int fpga_bridge_test_init(struct kunit *test)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fpga_bridge_test_exit(struct kunit *test)
|
||||
{
|
||||
unregister_test_bridge(test, test->priv);
|
||||
}
|
||||
|
||||
static struct kunit_case fpga_bridge_test_cases[] = {
|
||||
KUNIT_CASE(fpga_bridge_test_get),
|
||||
KUNIT_CASE(fpga_bridge_test_toggle),
|
||||
@@ -167,7 +165,6 @@ static struct kunit_case fpga_bridge_test_cases[] = {
|
||||
static struct kunit_suite fpga_bridge_suite = {
|
||||
.name = "fpga_bridge",
|
||||
.init = fpga_bridge_test_init,
|
||||
.exit = fpga_bridge_test_exit,
|
||||
.test_cases = fpga_bridge_test_cases,
|
||||
};
|
||||
|
||||
|
||||
@@ -44,6 +44,16 @@ struct mgr_ctx {
|
||||
struct mgr_stats stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrappers to avoid cast warnings when passing action functions directly
|
||||
* to kunit_add_action().
|
||||
*/
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(sg_free_table_wrapper, sg_free_table,
|
||||
struct sg_table *);
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper, fpga_image_info_free,
|
||||
struct fpga_image_info *);
|
||||
|
||||
/**
|
||||
* init_test_buffer() - Allocate and initialize a test image in a buffer.
|
||||
* @test: KUnit test context object.
|
||||
@@ -257,6 +267,9 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE);
|
||||
|
||||
ret = kunit_add_action_or_reset(test, sg_free_table_wrapper, sgt);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ctx->img_info->sgt = sgt;
|
||||
|
||||
ret = fpga_mgr_load(ctx->mgr, ctx->img_info);
|
||||
@@ -273,13 +286,12 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test)
|
||||
KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_seq, ctx->stats.op_parse_header_seq + 1);
|
||||
KUNIT_EXPECT_EQ(test, ctx->stats.op_write_sg_seq, ctx->stats.op_parse_header_seq + 2);
|
||||
KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_seq, ctx->stats.op_parse_header_seq + 3);
|
||||
|
||||
sg_free_table(ctx->img_info->sgt);
|
||||
}
|
||||
|
||||
static int fpga_mgr_test_init(struct kunit *test)
|
||||
{
|
||||
struct mgr_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
|
||||
@@ -294,19 +306,14 @@ static int fpga_mgr_test_init(struct kunit *test)
|
||||
ctx->img_info = fpga_image_info_alloc(ctx->dev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->img_info);
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_image_info_free_wrapper, ctx->img_info);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
test->priv = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fpga_mgr_test_exit(struct kunit *test)
|
||||
{
|
||||
struct mgr_ctx *ctx = test->priv;
|
||||
|
||||
fpga_image_info_free(ctx->img_info);
|
||||
kunit_device_unregister(test, ctx->dev);
|
||||
}
|
||||
|
||||
static struct kunit_case fpga_mgr_test_cases[] = {
|
||||
KUNIT_CASE(fpga_mgr_test_get),
|
||||
KUNIT_CASE(fpga_mgr_test_lock),
|
||||
@@ -318,7 +325,6 @@ static struct kunit_case fpga_mgr_test_cases[] = {
|
||||
static struct kunit_suite fpga_mgr_suite = {
|
||||
.name = "fpga_mgr",
|
||||
.init = fpga_mgr_test_init,
|
||||
.exit = fpga_mgr_test_exit,
|
||||
.test_cases = fpga_mgr_test_cases,
|
||||
};
|
||||
|
||||
|
||||
@@ -35,6 +35,19 @@ struct test_ctx {
|
||||
struct mgr_stats mgr_stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrappers to avoid cast warnings when passing action functions directly
|
||||
* to kunit_add_action().
|
||||
*/
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper, fpga_image_info_free,
|
||||
struct fpga_image_info *);
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper, fpga_bridge_unregister,
|
||||
struct fpga_bridge *);
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_region_unregister_wrapper, fpga_region_unregister,
|
||||
struct fpga_region *);
|
||||
|
||||
static int op_write(struct fpga_manager *mgr, const char *buf, size_t count)
|
||||
{
|
||||
struct mgr_stats *stats = mgr->priv;
|
||||
@@ -111,6 +124,9 @@ static void fpga_region_test_program_fpga(struct kunit *test)
|
||||
img_info = fpga_image_info_alloc(ctx->mgr_dev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, img_info);
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_image_info_free_wrapper, img_info);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
img_info->buf = img_buf;
|
||||
img_info->count = sizeof(img_buf);
|
||||
|
||||
@@ -130,8 +146,6 @@ static void fpga_region_test_program_fpga(struct kunit *test)
|
||||
KUNIT_EXPECT_EQ(test, 2, ctx->bridge_stats.cycles_count);
|
||||
|
||||
fpga_bridges_put(&ctx->region->bridge_list);
|
||||
|
||||
fpga_image_info_free(img_info);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -144,6 +158,7 @@ static int fpga_region_test_init(struct kunit *test)
|
||||
{
|
||||
struct test_ctx *ctx;
|
||||
struct fpga_region_info region_info = { 0 };
|
||||
int ret;
|
||||
|
||||
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
|
||||
@@ -164,6 +179,9 @@ static int fpga_region_test_init(struct kunit *test)
|
||||
|
||||
ctx->bridge_stats.enable = true;
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_bridge_unregister_wrapper, ctx->bridge);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ctx->region_dev = kunit_device_register(test, "fpga-region-test-dev");
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->region_dev);
|
||||
|
||||
@@ -174,24 +192,14 @@ static int fpga_region_test_init(struct kunit *test)
|
||||
ctx->region = fpga_region_register_full(ctx->region_dev, ®ion_info);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->region));
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_region_unregister_wrapper, ctx->region);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
test->priv = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fpga_region_test_exit(struct kunit *test)
|
||||
{
|
||||
struct test_ctx *ctx = test->priv;
|
||||
|
||||
fpga_region_unregister(ctx->region);
|
||||
kunit_device_unregister(test, ctx->region_dev);
|
||||
|
||||
fpga_bridge_unregister(ctx->bridge);
|
||||
kunit_device_unregister(test, ctx->bridge_dev);
|
||||
|
||||
kunit_device_unregister(test, ctx->mgr_dev);
|
||||
}
|
||||
|
||||
static struct kunit_case fpga_region_test_cases[] = {
|
||||
KUNIT_CASE(fpga_region_test_class_find),
|
||||
KUNIT_CASE(fpga_region_test_program_fpga),
|
||||
@@ -199,9 +207,8 @@ static struct kunit_case fpga_region_test_cases[] = {
|
||||
};
|
||||
|
||||
static struct kunit_suite fpga_region_suite = {
|
||||
.name = "fpga_mgr",
|
||||
.name = "fpga_region",
|
||||
.init = fpga_region_test_init,
|
||||
.exit = fpga_region_test_exit,
|
||||
.test_cases = fpga_region_test_cases,
|
||||
};
|
||||
|
||||
|
||||
@@ -387,7 +387,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
|
||||
const char *why;
|
||||
int err;
|
||||
u32 intr_status;
|
||||
unsigned long timeout;
|
||||
unsigned long time_left;
|
||||
unsigned long flags;
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
@@ -427,8 +427,8 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
|
||||
zynq_step_dma(priv);
|
||||
spin_unlock_irqrestore(&priv->dma_lock, flags);
|
||||
|
||||
timeout = wait_for_completion_timeout(&priv->dma_done,
|
||||
msecs_to_jiffies(DMA_TIMEOUT_MS));
|
||||
time_left = wait_for_completion_timeout(&priv->dma_done,
|
||||
msecs_to_jiffies(DMA_TIMEOUT_MS));
|
||||
|
||||
spin_lock_irqsave(&priv->dma_lock, flags);
|
||||
zynq_fpga_set_irq(priv, 0);
|
||||
@@ -452,7 +452,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
|
||||
|
||||
if (priv->cur_sg ||
|
||||
!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
|
||||
if (timeout == 0)
|
||||
if (time_left == 0)
|
||||
why = "DMA timed out";
|
||||
else
|
||||
why = "DMA did not complete";
|
||||
|
||||
@@ -21,6 +21,8 @@ config GREYBUS_BEAGLEPLAY
|
||||
tristate "Greybus BeaglePlay driver"
|
||||
depends on SERIAL_DEV_BUS
|
||||
select CRC_CCITT
|
||||
select FW_LOADER
|
||||
select FW_UPLOAD
|
||||
help
|
||||
Select this option if you have a BeaglePlay where CC1352
|
||||
co-processor acts as Greybus SVC.
|
||||
|
||||
+645
-13
@@ -6,21 +6,19 @@
|
||||
* Copyright (c) 2023 BeagleBoard.org Foundation
|
||||
*/
|
||||
|
||||
#include <linux/gfp.h>
|
||||
#include <asm-generic/unaligned.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/greybus.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/serdev.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/greybus/hd.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/crc-ccitt.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define CC1352_FIRMWARE_SIZE (704 * 1024)
|
||||
#define CC1352_BOOTLOADER_TIMEOUT 2000
|
||||
#define CC1352_BOOTLOADER_ACK 0xcc
|
||||
#define CC1352_BOOTLOADER_NACK 0x33
|
||||
|
||||
#define RX_HDLC_PAYLOAD 256
|
||||
#define CRC_LEN 2
|
||||
@@ -57,6 +55,17 @@
|
||||
* @rx_buffer_len: length of receive buffer filled.
|
||||
* @rx_buffer: hdlc frame receive buffer
|
||||
* @rx_in_esc: hdlc rx flag to indicate ESC frame
|
||||
*
|
||||
* @fwl: underlying firmware upload device
|
||||
* @bootloader_backdoor_gpio: cc1352p7 boot gpio
|
||||
* @rst_gpio: cc1352p7 reset gpio
|
||||
* @flashing_mode: flag to indicate that flashing is currently in progress
|
||||
* @fwl_ack_com: completion to signal an Ack/Nack
|
||||
* @fwl_ack: Ack/Nack byte received
|
||||
* @fwl_cmd_response_com: completion to signal a bootloader command response
|
||||
* @fwl_cmd_response: bootloader command response data
|
||||
* @fwl_crc32: crc32 of firmware to flash
|
||||
* @fwl_reset_addr: flag to indicate if we need to send COMMAND_DOWNLOAD again
|
||||
*/
|
||||
struct gb_beagleplay {
|
||||
struct serdev_device *sd;
|
||||
@@ -72,6 +81,17 @@ struct gb_beagleplay {
|
||||
u16 rx_buffer_len;
|
||||
bool rx_in_esc;
|
||||
u8 rx_buffer[MAX_RX_HDLC];
|
||||
|
||||
struct fw_upload *fwl;
|
||||
struct gpio_desc *bootloader_backdoor_gpio;
|
||||
struct gpio_desc *rst_gpio;
|
||||
bool flashing_mode;
|
||||
struct completion fwl_ack_com;
|
||||
u8 fwl_ack;
|
||||
struct completion fwl_cmd_response_com;
|
||||
u32 fwl_cmd_response;
|
||||
u32 fwl_crc32;
|
||||
bool fwl_reset_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -100,6 +120,87 @@ struct hdlc_greybus_frame {
|
||||
u8 payload[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum cc1352_bootloader_cmd: CC1352 Bootloader Commands
|
||||
*
|
||||
* @COMMAND_DOWNLOAD: Prepares flash programming
|
||||
* @COMMAND_GET_STATUS: Returns the status of the last command that was issued
|
||||
* @COMMAND_SEND_DATA: Transfers data and programs flash
|
||||
* @COMMAND_RESET: Performs a system reset
|
||||
* @COMMAND_CRC32: Calculates CRC32 over a specified memory area
|
||||
* @COMMAND_BANK_ERASE: Performs an erase of all of the customer-accessible
|
||||
* flash sectors not protected by FCFG1 and CCFG
|
||||
* writeprotect bits.
|
||||
*
|
||||
* CC1352 Bootloader serial bus commands
|
||||
*/
|
||||
enum cc1352_bootloader_cmd {
|
||||
COMMAND_DOWNLOAD = 0x21,
|
||||
COMMAND_GET_STATUS = 0x23,
|
||||
COMMAND_SEND_DATA = 0x24,
|
||||
COMMAND_RESET = 0x25,
|
||||
COMMAND_CRC32 = 0x27,
|
||||
COMMAND_BANK_ERASE = 0x2c,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cc1352_bootloader_status: CC1352 Bootloader COMMAND_GET_STATUS response
|
||||
*
|
||||
* @COMMAND_RET_SUCCESS: Status for successful command
|
||||
* @COMMAND_RET_UNKNOWN_CMD: Status for unknown command
|
||||
* @COMMAND_RET_INVALID_CMD: Status for invalid command (in other words,
|
||||
* incorrect packet size)
|
||||
* @COMMAND_RET_INVALID_ADR: Status for invalid input address
|
||||
* @COMMAND_RET_FLASH_FAIL: Status for failing flash erase or program operation
|
||||
*/
|
||||
enum cc1352_bootloader_status {
|
||||
COMMAND_RET_SUCCESS = 0x40,
|
||||
COMMAND_RET_UNKNOWN_CMD = 0x41,
|
||||
COMMAND_RET_INVALID_CMD = 0x42,
|
||||
COMMAND_RET_INVALID_ADR = 0x43,
|
||||
COMMAND_RET_FLASH_FAIL = 0x44,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cc1352_bootloader_packet: CC1352 Bootloader Request Packet
|
||||
*
|
||||
* @len: length of packet + optional request data
|
||||
* @checksum: 8-bit checksum excluding len
|
||||
* @cmd: bootloader command
|
||||
*/
|
||||
struct cc1352_bootloader_packet {
|
||||
u8 len;
|
||||
u8 checksum;
|
||||
u8 cmd;
|
||||
} __packed;
|
||||
|
||||
#define CC1352_BOOTLOADER_PKT_MAX_SIZE \
|
||||
(U8_MAX - sizeof(struct cc1352_bootloader_packet))
|
||||
|
||||
/**
|
||||
* struct cc1352_bootloader_download_cmd_data: CC1352 Bootloader COMMAND_DOWNLOAD request data
|
||||
*
|
||||
* @addr: address to start programming data into
|
||||
* @size: size of data that will be sent
|
||||
*/
|
||||
struct cc1352_bootloader_download_cmd_data {
|
||||
__be32 addr;
|
||||
__be32 size;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct cc1352_bootloader_crc32_cmd_data: CC1352 Bootloader COMMAND_CRC32 request data
|
||||
*
|
||||
* @addr: address where crc32 calculation starts
|
||||
* @size: number of bytes comprised by crc32 calculation
|
||||
* @read_repeat: number of read repeats for each data location
|
||||
*/
|
||||
struct cc1352_bootloader_crc32_cmd_data {
|
||||
__be32 addr;
|
||||
__be32 size;
|
||||
__be32 read_repeat;
|
||||
} __packed;
|
||||
|
||||
static void hdlc_rx_greybus_frame(struct gb_beagleplay *bg, u8 *buf, u16 len)
|
||||
{
|
||||
struct hdlc_greybus_frame *gb_frame = (struct hdlc_greybus_frame *)buf;
|
||||
@@ -331,11 +432,135 @@ static void hdlc_deinit(struct gb_beagleplay *bg)
|
||||
flush_work(&bg->tx_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* csum8: Calculate 8-bit checksum on data
|
||||
*
|
||||
* @data: bytes to calculate 8-bit checksum of
|
||||
* @size: number of bytes
|
||||
* @base: starting value for checksum
|
||||
*/
|
||||
static u8 csum8(const u8 *data, size_t size, u8 base)
|
||||
{
|
||||
size_t i;
|
||||
u8 sum = base;
|
||||
|
||||
for (i = 0; i < size; ++i)
|
||||
sum += data[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void cc1352_bootloader_send_ack(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const u8 ack[] = { 0x00, CC1352_BOOTLOADER_ACK };
|
||||
|
||||
serdev_device_write_buf(bg->sd, ack, sizeof(ack));
|
||||
}
|
||||
|
||||
static void cc1352_bootloader_send_nack(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const u8 nack[] = { 0x00, CC1352_BOOTLOADER_NACK };
|
||||
|
||||
serdev_device_write_buf(bg->sd, nack, sizeof(nack));
|
||||
}
|
||||
|
||||
/**
|
||||
* cc1352_bootloader_pkt_rx: Process a CC1352 Bootloader Packet
|
||||
*
|
||||
* @bg: beagleplay greybus driver
|
||||
* @data: packet buffer
|
||||
* @count: packet buffer size
|
||||
*
|
||||
* @return: number of bytes processed
|
||||
*
|
||||
* Here are the steps to successfully receive a packet from cc1352 bootloader
|
||||
* according to the docs:
|
||||
* 1. Wait for nonzero data to be returned from the device. This is important
|
||||
* as the device may send zero bytes between a sent and a received data
|
||||
* packet. The first nonzero byte received is the size of the packet that is
|
||||
* being received.
|
||||
* 2. Read the next byte, which is the checksum for the packet.
|
||||
* 3. Read the data bytes from the device. During the data phase, packet size
|
||||
* minus 2 bytes is sent.
|
||||
* 4. Calculate the checksum of the data bytes and verify it matches the
|
||||
* checksum received in the packet.
|
||||
* 5. Send an acknowledge byte or a not-acknowledge byte to the device to
|
||||
* indicate the successful or unsuccessful reception of the packet.
|
||||
*/
|
||||
static int cc1352_bootloader_pkt_rx(struct gb_beagleplay *bg, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
bool is_valid = false;
|
||||
|
||||
switch (data[0]) {
|
||||
/* Skip 0x00 bytes. */
|
||||
case 0x00:
|
||||
return 1;
|
||||
case CC1352_BOOTLOADER_ACK:
|
||||
case CC1352_BOOTLOADER_NACK:
|
||||
WRITE_ONCE(bg->fwl_ack, data[0]);
|
||||
complete(&bg->fwl_ack_com);
|
||||
return 1;
|
||||
case 3:
|
||||
if (count < 3)
|
||||
return 0;
|
||||
is_valid = data[1] == data[2];
|
||||
WRITE_ONCE(bg->fwl_cmd_response, (u32)data[2]);
|
||||
break;
|
||||
case 6:
|
||||
if (count < 6)
|
||||
return 0;
|
||||
is_valid = csum8(&data[2], sizeof(__be32), 0) == data[1];
|
||||
WRITE_ONCE(bg->fwl_cmd_response, get_unaligned_be32(&data[2]));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_valid) {
|
||||
cc1352_bootloader_send_ack(bg);
|
||||
complete(&bg->fwl_cmd_response_com);
|
||||
} else {
|
||||
dev_warn(&bg->sd->dev,
|
||||
"Dropping bootloader packet with invalid checksum");
|
||||
cc1352_bootloader_send_nack(bg);
|
||||
}
|
||||
|
||||
return data[0];
|
||||
}
|
||||
|
||||
static size_t cc1352_bootloader_rx(struct gb_beagleplay *bg, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
int ret;
|
||||
size_t off = 0;
|
||||
|
||||
memcpy(bg->rx_buffer + bg->rx_buffer_len, data, count);
|
||||
bg->rx_buffer_len += count;
|
||||
|
||||
do {
|
||||
ret = cc1352_bootloader_pkt_rx(bg, bg->rx_buffer + off,
|
||||
bg->rx_buffer_len - off);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Invalid Packet");
|
||||
off += ret;
|
||||
} while (ret > 0 && off < count);
|
||||
|
||||
bg->rx_buffer_len -= off;
|
||||
memmove(bg->rx_buffer, bg->rx_buffer + off, bg->rx_buffer_len);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static size_t gb_tty_receive(struct serdev_device *sd, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
struct gb_beagleplay *bg = serdev_device_get_drvdata(sd);
|
||||
|
||||
if (READ_ONCE(bg->flashing_mode))
|
||||
return cc1352_bootloader_rx(bg, data, count);
|
||||
|
||||
return hdlc_rx(bg, data, count);
|
||||
}
|
||||
|
||||
@@ -343,7 +568,8 @@ static void gb_tty_wakeup(struct serdev_device *serdev)
|
||||
{
|
||||
struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev);
|
||||
|
||||
schedule_work(&bg->tx_work);
|
||||
if (!READ_ONCE(bg->flashing_mode))
|
||||
schedule_work(&bg->tx_work);
|
||||
}
|
||||
|
||||
static struct serdev_device_ops gb_beagleplay_ops = {
|
||||
@@ -412,6 +638,195 @@ static void gb_beagleplay_stop_svc(struct gb_beagleplay *bg)
|
||||
hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_wait_for_ack(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_ack_com, msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Failed to acquire ack semaphore");
|
||||
|
||||
switch (READ_ONCE(bg->fwl_ack)) {
|
||||
case CC1352_BOOTLOADER_ACK:
|
||||
return 0;
|
||||
case CC1352_BOOTLOADER_NACK:
|
||||
return -EAGAIN;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_sync(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const u8 sync_bytes[] = { 0x55, 0x55 };
|
||||
|
||||
serdev_device_write_buf(bg->sd, sync_bytes, sizeof(sync_bytes));
|
||||
return cc1352_bootloader_wait_for_ack(bg);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_get_status(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
static const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt),
|
||||
.checksum = COMMAND_GET_STATUS,
|
||||
.cmd = COMMAND_GET_STATUS
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_cmd_response_com,
|
||||
msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Failed to acquire last status semaphore");
|
||||
|
||||
switch (READ_ONCE(bg->fwl_cmd_response)) {
|
||||
case COMMAND_RET_SUCCESS:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_erase(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
static const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt),
|
||||
.checksum = COMMAND_BANK_ERASE,
|
||||
.cmd = COMMAND_BANK_ERASE
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return cc1352_bootloader_get_status(bg);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_reset(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt),
|
||||
.checksum = COMMAND_RESET,
|
||||
.cmd = COMMAND_RESET
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
|
||||
return cc1352_bootloader_wait_for_ack(bg);
|
||||
}
|
||||
|
||||
/**
|
||||
* cc1352_bootloader_empty_pkt: Calculate the number of empty bytes in the current packet
|
||||
*
|
||||
* @data: packet bytes array to check
|
||||
* @size: number of bytes in array
|
||||
*/
|
||||
static size_t cc1352_bootloader_empty_pkt(const u8 *data, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size && data[i] == 0xff; ++i)
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_crc32(struct gb_beagleplay *bg, u32 *crc32)
|
||||
{
|
||||
int ret;
|
||||
static const struct cc1352_bootloader_crc32_cmd_data cmd_data = {
|
||||
.addr = 0, .size = cpu_to_be32(704 * 1024), .read_repeat = 0
|
||||
};
|
||||
const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt) + sizeof(cmd_data),
|
||||
.checksum = csum8((const void *)&cmd_data, sizeof(cmd_data),
|
||||
COMMAND_CRC32),
|
||||
.cmd = COMMAND_CRC32
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&cmd_data,
|
||||
sizeof(cmd_data));
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_cmd_response_com,
|
||||
msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Failed to acquire last status semaphore");
|
||||
|
||||
*crc32 = READ_ONCE(bg->fwl_cmd_response);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_download(struct gb_beagleplay *bg, u32 size,
|
||||
u32 addr)
|
||||
{
|
||||
int ret;
|
||||
const struct cc1352_bootloader_download_cmd_data cmd_data = {
|
||||
.addr = cpu_to_be32(addr),
|
||||
.size = cpu_to_be32(size),
|
||||
};
|
||||
const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt) + sizeof(cmd_data),
|
||||
.checksum = csum8((const void *)&cmd_data, sizeof(cmd_data),
|
||||
COMMAND_DOWNLOAD),
|
||||
.cmd = COMMAND_DOWNLOAD
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&cmd_data,
|
||||
sizeof(cmd_data));
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return cc1352_bootloader_get_status(bg);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_send_data(struct gb_beagleplay *bg, const u8 *data,
|
||||
size_t size)
|
||||
{
|
||||
int ret, rem = min(size, CC1352_BOOTLOADER_PKT_MAX_SIZE);
|
||||
const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt) + rem,
|
||||
.checksum = csum8(data, rem, COMMAND_SEND_DATA),
|
||||
.cmd = COMMAND_SEND_DATA
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
serdev_device_write_buf(bg->sd, data, rem);
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cc1352_bootloader_get_status(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
static void gb_greybus_deinit(struct gb_beagleplay *bg)
|
||||
{
|
||||
gb_hd_del(bg->gb_hd);
|
||||
@@ -442,6 +857,157 @@ free_gb_hd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum fw_upload_err cc1352_prepare(struct fw_upload *fw_upload,
|
||||
const u8 *data, u32 size)
|
||||
{
|
||||
int ret;
|
||||
u32 curr_crc32;
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
dev_info(&bg->sd->dev, "CC1352 Start Flashing...");
|
||||
|
||||
if (size != CC1352_FIRMWARE_SIZE)
|
||||
return FW_UPLOAD_ERR_INVALID_SIZE;
|
||||
|
||||
/* Might involve network calls */
|
||||
gb_greybus_deinit(bg);
|
||||
msleep(5 * MSEC_PER_SEC);
|
||||
|
||||
gb_beagleplay_stop_svc(bg);
|
||||
msleep(200);
|
||||
flush_work(&bg->tx_work);
|
||||
|
||||
serdev_device_wait_until_sent(bg->sd, CC1352_BOOTLOADER_TIMEOUT);
|
||||
|
||||
WRITE_ONCE(bg->flashing_mode, true);
|
||||
|
||||
gpiod_direction_output(bg->bootloader_backdoor_gpio, 0);
|
||||
gpiod_direction_output(bg->rst_gpio, 0);
|
||||
msleep(200);
|
||||
|
||||
gpiod_set_value(bg->rst_gpio, 1);
|
||||
msleep(200);
|
||||
|
||||
gpiod_set_value(bg->bootloader_backdoor_gpio, 1);
|
||||
msleep(200);
|
||||
|
||||
gpiod_direction_input(bg->bootloader_backdoor_gpio);
|
||||
gpiod_direction_input(bg->rst_gpio);
|
||||
|
||||
ret = cc1352_bootloader_sync(bg);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to sync");
|
||||
|
||||
ret = cc1352_bootloader_crc32(bg, &curr_crc32);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to fetch crc32");
|
||||
|
||||
bg->fwl_crc32 = crc32(0xffffffff, data, size) ^ 0xffffffff;
|
||||
|
||||
/* Check if attempting to reflash same firmware */
|
||||
if (bg->fwl_crc32 == curr_crc32) {
|
||||
dev_warn(&bg->sd->dev, "Skipping reflashing same image");
|
||||
cc1352_bootloader_reset(bg);
|
||||
WRITE_ONCE(bg->flashing_mode, false);
|
||||
msleep(200);
|
||||
gb_greybus_init(bg);
|
||||
gb_beagleplay_start_svc(bg);
|
||||
return FW_UPLOAD_ERR_FW_INVALID;
|
||||
}
|
||||
|
||||
ret = cc1352_bootloader_erase(bg);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to erase");
|
||||
|
||||
bg->fwl_reset_addr = true;
|
||||
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
static void cc1352_cleanup(struct fw_upload *fw_upload)
|
||||
{
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
WRITE_ONCE(bg->flashing_mode, false);
|
||||
}
|
||||
|
||||
static enum fw_upload_err cc1352_write(struct fw_upload *fw_upload,
|
||||
const u8 *data, u32 offset, u32 size,
|
||||
u32 *written)
|
||||
{
|
||||
int ret;
|
||||
size_t empty_bytes;
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
/* Skip 0xff packets. Significant performance improvement */
|
||||
empty_bytes = cc1352_bootloader_empty_pkt(data + offset, size);
|
||||
if (empty_bytes >= CC1352_BOOTLOADER_PKT_MAX_SIZE) {
|
||||
bg->fwl_reset_addr = true;
|
||||
*written = empty_bytes;
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
if (bg->fwl_reset_addr) {
|
||||
ret = cc1352_bootloader_download(bg, size, offset);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev,
|
||||
FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to send download cmd");
|
||||
|
||||
bg->fwl_reset_addr = false;
|
||||
}
|
||||
|
||||
ret = cc1352_bootloader_send_data(bg, data + offset, size);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to flash firmware");
|
||||
*written = ret;
|
||||
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
static enum fw_upload_err cc1352_poll_complete(struct fw_upload *fw_upload)
|
||||
{
|
||||
u32 curr_crc32;
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
if (cc1352_bootloader_crc32(bg, &curr_crc32) < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to fetch crc32");
|
||||
|
||||
if (bg->fwl_crc32 != curr_crc32)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_FW_INVALID,
|
||||
"Invalid CRC32");
|
||||
|
||||
if (cc1352_bootloader_reset(bg) < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to reset");
|
||||
|
||||
dev_info(&bg->sd->dev, "CC1352 Flashing Successful");
|
||||
WRITE_ONCE(bg->flashing_mode, false);
|
||||
msleep(200);
|
||||
|
||||
if (gb_greybus_init(bg) < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_RW_ERROR,
|
||||
"Failed to initialize greybus");
|
||||
|
||||
gb_beagleplay_start_svc(bg);
|
||||
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
static void cc1352_cancel(struct fw_upload *fw_upload)
|
||||
{
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
dev_info(&bg->sd->dev, "CC1352 Bootloader Cancel");
|
||||
|
||||
cc1352_bootloader_reset(bg);
|
||||
}
|
||||
|
||||
static void gb_serdev_deinit(struct gb_beagleplay *bg)
|
||||
{
|
||||
serdev_device_close(bg->sd);
|
||||
@@ -463,6 +1029,65 @@ static int gb_serdev_init(struct gb_beagleplay *bg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fw_upload_ops cc1352_bootloader_ops = {
|
||||
.prepare = cc1352_prepare,
|
||||
.write = cc1352_write,
|
||||
.poll_complete = cc1352_poll_complete,
|
||||
.cancel = cc1352_cancel,
|
||||
.cleanup = cc1352_cleanup
|
||||
};
|
||||
|
||||
static int gb_fw_init(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
struct fw_upload *fwl;
|
||||
struct gpio_desc *desc;
|
||||
|
||||
bg->fwl = NULL;
|
||||
bg->bootloader_backdoor_gpio = NULL;
|
||||
bg->rst_gpio = NULL;
|
||||
bg->flashing_mode = false;
|
||||
bg->fwl_cmd_response = 0;
|
||||
bg->fwl_ack = 0;
|
||||
init_completion(&bg->fwl_ack_com);
|
||||
init_completion(&bg->fwl_cmd_response_com);
|
||||
|
||||
desc = devm_gpiod_get(&bg->sd->dev, "bootloader-backdoor", GPIOD_IN);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
bg->bootloader_backdoor_gpio = desc;
|
||||
|
||||
desc = devm_gpiod_get(&bg->sd->dev, "reset", GPIOD_IN);
|
||||
if (IS_ERR(desc)) {
|
||||
ret = PTR_ERR(desc);
|
||||
goto free_boot;
|
||||
}
|
||||
bg->rst_gpio = desc;
|
||||
|
||||
fwl = firmware_upload_register(THIS_MODULE, &bg->sd->dev, "cc1352p7",
|
||||
&cc1352_bootloader_ops, bg);
|
||||
if (IS_ERR(fwl)) {
|
||||
ret = PTR_ERR(fwl);
|
||||
goto free_reset;
|
||||
}
|
||||
bg->fwl = fwl;
|
||||
|
||||
return 0;
|
||||
|
||||
free_reset:
|
||||
devm_gpiod_put(&bg->sd->dev, bg->rst_gpio);
|
||||
bg->rst_gpio = NULL;
|
||||
free_boot:
|
||||
devm_gpiod_put(&bg->sd->dev, bg->bootloader_backdoor_gpio);
|
||||
bg->bootloader_backdoor_gpio = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gb_fw_deinit(struct gb_beagleplay *bg)
|
||||
{
|
||||
firmware_upload_unregister(bg->fwl);
|
||||
}
|
||||
|
||||
static int gb_beagleplay_probe(struct serdev_device *serdev)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -481,14 +1106,20 @@ static int gb_beagleplay_probe(struct serdev_device *serdev)
|
||||
if (ret)
|
||||
goto free_serdev;
|
||||
|
||||
ret = gb_greybus_init(bg);
|
||||
ret = gb_fw_init(bg);
|
||||
if (ret)
|
||||
goto free_hdlc;
|
||||
|
||||
ret = gb_greybus_init(bg);
|
||||
if (ret)
|
||||
goto free_fw;
|
||||
|
||||
gb_beagleplay_start_svc(bg);
|
||||
|
||||
return 0;
|
||||
|
||||
free_fw:
|
||||
gb_fw_deinit(bg);
|
||||
free_hdlc:
|
||||
hdlc_deinit(bg);
|
||||
free_serdev:
|
||||
@@ -500,6 +1131,7 @@ static void gb_beagleplay_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev);
|
||||
|
||||
gb_fw_deinit(bg);
|
||||
gb_greybus_deinit(bg);
|
||||
gb_beagleplay_stop_svc(bg);
|
||||
hdlc_deinit(bg);
|
||||
|
||||
@@ -487,23 +487,25 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
|
||||
return csdev;
|
||||
}
|
||||
|
||||
u32 coresight_get_sink_id(struct coresight_device *csdev)
|
||||
{
|
||||
if (!csdev->ea)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* See function etm_perf_add_symlink_sink() to know where
|
||||
* this comes from.
|
||||
*/
|
||||
return (u32) (unsigned long) csdev->ea->var;
|
||||
}
|
||||
|
||||
static int coresight_sink_by_id(struct device *dev, const void *data)
|
||||
{
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
unsigned long hash;
|
||||
|
||||
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
|
||||
if (!csdev->ea)
|
||||
return 0;
|
||||
/*
|
||||
* See function etm_perf_add_symlink_sink() to know where
|
||||
* this comes from.
|
||||
*/
|
||||
hash = (unsigned long)csdev->ea->var;
|
||||
|
||||
if ((u32)hash == *(u32 *)data)
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
if (coresight_get_sink_id(csdev) == *(u32 *)data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -902,6 +904,7 @@ static void coresight_device_release(struct device *dev)
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
fwnode_handle_put(csdev->dev.fwnode);
|
||||
free_percpu(csdev->perf_sink_id_map.cpu_map);
|
||||
kfree(csdev);
|
||||
}
|
||||
|
||||
@@ -1159,6 +1162,16 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
||||
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
|
||||
dev_set_name(&csdev->dev, "%s", desc->name);
|
||||
|
||||
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
spin_lock_init(&csdev->perf_sink_id_map.lock);
|
||||
csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t);
|
||||
if (!csdev->perf_sink_id_map.cpu_map) {
|
||||
kfree(csdev);
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Make sure the device registration and the connection fixup
|
||||
* are synchronised, so that we don't see uninitialised devices
|
||||
|
||||
@@ -416,20 +416,16 @@ static int cti_plat_create_impdef_connections(struct device *dev,
|
||||
struct cti_drvdata *drvdata)
|
||||
{
|
||||
int rc = 0;
|
||||
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
||||
struct fwnode_handle *child = NULL;
|
||||
|
||||
if (IS_ERR_OR_NULL(fwnode))
|
||||
if (IS_ERR_OR_NULL(dev_fwnode(dev)))
|
||||
return -EINVAL;
|
||||
|
||||
fwnode_for_each_child_node(fwnode, child) {
|
||||
device_for_each_child_node_scoped(dev, child) {
|
||||
if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
|
||||
rc = cti_plat_create_connection(dev, drvdata,
|
||||
child);
|
||||
rc = cti_plat_create_connection(dev, drvdata, child);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
fwnode_handle_put(child);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,12 @@ DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
|
||||
DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
|
||||
|
||||
static int dummy_source_enable(struct coresight_device *csdev,
|
||||
struct perf_event *event, enum cs_mode mode)
|
||||
struct perf_event *event, enum cs_mode mode,
|
||||
__maybe_unused struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
if (!coresight_take_mode(csdev, mode))
|
||||
return -EBUSY;
|
||||
|
||||
dev_dbg(csdev->dev.parent, "Dummy source enabled\n");
|
||||
|
||||
return 0;
|
||||
@@ -31,6 +35,7 @@ static int dummy_source_enable(struct coresight_device *csdev,
|
||||
static void dummy_source_disable(struct coresight_device *csdev,
|
||||
struct perf_event *event)
|
||||
{
|
||||
coresight_set_mode(csdev, CS_MODE_DISABLED);
|
||||
dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -229,14 +229,23 @@ static void free_event_data(struct work_struct *work)
|
||||
struct list_head **ppath;
|
||||
|
||||
ppath = etm_event_cpu_path_ptr(event_data, cpu);
|
||||
if (!(IS_ERR_OR_NULL(*ppath)))
|
||||
coresight_release_path(*ppath);
|
||||
*ppath = NULL;
|
||||
coresight_trace_id_put_cpu_id(cpu);
|
||||
}
|
||||
if (!(IS_ERR_OR_NULL(*ppath))) {
|
||||
struct coresight_device *sink = coresight_get_sink(*ppath);
|
||||
|
||||
/* mark perf event as done for trace id allocator */
|
||||
coresight_trace_id_perf_stop();
|
||||
/*
|
||||
* Mark perf event as done for trace id allocator, but don't call
|
||||
* coresight_trace_id_put_cpu_id_map() on individual IDs. Perf sessions
|
||||
* never free trace IDs to ensure that the ID associated with a CPU
|
||||
* cannot change during their and other's concurrent sessions. Instead,
|
||||
* a refcount is used so that the last event to call
|
||||
* coresight_trace_id_perf_stop() frees all IDs.
|
||||
*/
|
||||
coresight_trace_id_perf_stop(&sink->perf_sink_id_map);
|
||||
|
||||
coresight_release_path(*ppath);
|
||||
}
|
||||
*ppath = NULL;
|
||||
}
|
||||
|
||||
free_percpu(event_data->path);
|
||||
kfree(event_data);
|
||||
@@ -325,9 +334,6 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
|
||||
sink = user_sink = coresight_get_sink_by_id(id);
|
||||
}
|
||||
|
||||
/* tell the trace ID allocator that a perf event is starting up */
|
||||
coresight_trace_id_perf_start();
|
||||
|
||||
/* check if user wants a coresight configuration selected */
|
||||
cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32);
|
||||
if (cfg_hash) {
|
||||
@@ -401,13 +407,14 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
|
||||
}
|
||||
|
||||
/* ensure we can allocate a trace ID for this CPU */
|
||||
trace_id = coresight_trace_id_get_cpu_id(cpu);
|
||||
trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
|
||||
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
|
||||
cpumask_clear_cpu(cpu, mask);
|
||||
coresight_release_path(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
coresight_trace_id_perf_start(&sink->perf_sink_id_map);
|
||||
*etm_event_cpu_path_ptr(event_data, cpu) = path;
|
||||
}
|
||||
|
||||
@@ -453,6 +460,7 @@ static void etm_event_start(struct perf_event *event, int flags)
|
||||
struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
|
||||
struct list_head *path;
|
||||
u64 hw_id;
|
||||
u8 trace_id;
|
||||
|
||||
if (!csdev)
|
||||
goto fail;
|
||||
@@ -495,7 +503,8 @@ static void etm_event_start(struct perf_event *event, int flags)
|
||||
goto fail_end_stop;
|
||||
|
||||
/* Finally enable the tracer */
|
||||
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
|
||||
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF,
|
||||
&sink->perf_sink_id_map))
|
||||
goto fail_disable_path;
|
||||
|
||||
/*
|
||||
@@ -504,10 +513,16 @@ static void etm_event_start(struct perf_event *event, int flags)
|
||||
*/
|
||||
if (!cpumask_test_cpu(cpu, &event_data->aux_hwid_done)) {
|
||||
cpumask_set_cpu(cpu, &event_data->aux_hwid_done);
|
||||
hw_id = FIELD_PREP(CS_AUX_HW_ID_VERSION_MASK,
|
||||
CS_AUX_HW_ID_CURR_VERSION);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK,
|
||||
coresight_trace_id_read_cpu_id(cpu));
|
||||
|
||||
trace_id = coresight_trace_id_read_cpu_id_map(cpu, &sink->perf_sink_id_map);
|
||||
|
||||
hw_id = FIELD_PREP(CS_AUX_HW_ID_MAJOR_VERSION_MASK,
|
||||
CS_AUX_HW_ID_MAJOR_VERSION);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_MINOR_VERSION_MASK,
|
||||
CS_AUX_HW_ID_MINOR_VERSION);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK, trace_id);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_SINK_ID_MASK, coresight_get_sink_id(sink));
|
||||
|
||||
perf_report_aux_output_id(event, hw_id);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ struct etm_event_data {
|
||||
struct list_head * __percpu *path;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT)
|
||||
int etm_perf_symlink(struct coresight_device *csdev, bool link);
|
||||
int etm_perf_add_symlink_sink(struct coresight_device *csdev);
|
||||
void etm_perf_del_symlink_sink(struct coresight_device *csdev);
|
||||
@@ -77,23 +76,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
|
||||
int etm_perf_add_symlink_cscfg(struct device *dev,
|
||||
struct cscfg_config_desc *config_desc);
|
||||
void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc);
|
||||
#else
|
||||
static inline int etm_perf_symlink(struct coresight_device *csdev, bool link)
|
||||
{ return -EINVAL; }
|
||||
int etm_perf_add_symlink_sink(struct coresight_device *csdev)
|
||||
{ return -EINVAL; }
|
||||
void etm_perf_del_symlink_sink(struct coresight_device *csdev) {}
|
||||
static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
int etm_perf_add_symlink_cscfg(struct device *dev,
|
||||
struct cscfg_config_desc *config_desc)
|
||||
{ return -EINVAL; }
|
||||
void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc) {}
|
||||
|
||||
#endif /* CONFIG_CORESIGHT */
|
||||
|
||||
int __init etm_perf_init(void);
|
||||
void etm_perf_exit(void);
|
||||
|
||||
|
||||
@@ -481,7 +481,8 @@ void etm_release_trace_id(struct etm_drvdata *drvdata)
|
||||
}
|
||||
|
||||
static int etm_enable_perf(struct coresight_device *csdev,
|
||||
struct perf_event *event)
|
||||
struct perf_event *event,
|
||||
struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int trace_id;
|
||||
@@ -500,7 +501,7 @@ static int etm_enable_perf(struct coresight_device *csdev,
|
||||
* with perf locks - we know the ID cannot change until perf shuts down
|
||||
* the session
|
||||
*/
|
||||
trace_id = coresight_trace_id_read_cpu_id(drvdata->cpu);
|
||||
trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
|
||||
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
|
||||
dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
|
||||
dev_name(&drvdata->csdev->dev), drvdata->cpu);
|
||||
@@ -553,7 +554,7 @@ unlock_enable_sysfs:
|
||||
}
|
||||
|
||||
static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
int ret;
|
||||
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
@@ -568,7 +569,7 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
ret = etm_enable_sysfs(csdev);
|
||||
break;
|
||||
case CS_MODE_PERF:
|
||||
ret = etm_enable_perf(csdev, event);
|
||||
ret = etm_enable_perf(csdev, event, id_map);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
@@ -752,7 +752,8 @@ out:
|
||||
}
|
||||
|
||||
static int etm4_enable_perf(struct coresight_device *csdev,
|
||||
struct perf_event *event)
|
||||
struct perf_event *event,
|
||||
struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
int ret = 0, trace_id;
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
@@ -775,7 +776,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
|
||||
* with perf locks - we know the ID cannot change until perf shuts down
|
||||
* the session
|
||||
*/
|
||||
trace_id = coresight_trace_id_read_cpu_id(drvdata->cpu);
|
||||
trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
|
||||
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
|
||||
dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
|
||||
dev_name(&drvdata->csdev->dev), drvdata->cpu);
|
||||
@@ -837,7 +838,7 @@ unlock_sysfs_enable:
|
||||
}
|
||||
|
||||
static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -851,7 +852,7 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
ret = etm4_enable_sysfs(csdev);
|
||||
break;
|
||||
case CS_MODE_PERF:
|
||||
ret = etm4_enable_perf(csdev, event);
|
||||
ret = etm4_enable_perf(csdev, event, id_map);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
||||
@@ -148,6 +148,7 @@ int coresight_make_links(struct coresight_device *orig,
|
||||
struct coresight_device *target);
|
||||
void coresight_remove_links(struct coresight_device *orig,
|
||||
struct coresight_connection *conn);
|
||||
u32 coresight_get_sink_id(struct coresight_device *csdev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
|
||||
extern int etm_readl_cp14(u32 off, unsigned int *val);
|
||||
|
||||
@@ -194,7 +194,8 @@ static void stm_enable_hw(struct stm_drvdata *drvdata)
|
||||
}
|
||||
|
||||
static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode,
|
||||
__maybe_unused struct coresight_trace_id_map *trace_id)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
#include "coresight-trace-id.h"
|
||||
|
||||
/*
|
||||
* Use IDR to map the hash of the source's device name
|
||||
@@ -63,7 +64,7 @@ static int coresight_enable_source_sysfs(struct coresight_device *csdev,
|
||||
*/
|
||||
lockdep_assert_held(&coresight_mutex);
|
||||
if (coresight_get_mode(csdev) != CS_MODE_SYSFS) {
|
||||
ret = source_ops(csdev)->enable(csdev, data, mode);
|
||||
ret = source_ops(csdev)->enable(csdev, data, mode, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ struct etr_buf_hw {
|
||||
* etr_perf_buffer - Perf buffer used for ETR
|
||||
* @drvdata - The ETR drvdaga this buffer has been allocated for.
|
||||
* @etr_buf - Actual buffer used by the ETR
|
||||
* @pid - The PID this etr_perf_buffer belongs to.
|
||||
* @pid - The PID of the session owner that etr_perf_buffer
|
||||
* belongs to.
|
||||
* @snaphost - Perf session mode
|
||||
* @nr_pages - Number of pages in the ring buffer.
|
||||
* @pages - Array of Pages in the ring buffer.
|
||||
@@ -261,6 +262,7 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
|
||||
{
|
||||
tmc_free_table_pages(sg_table);
|
||||
tmc_free_data_pages(sg_table);
|
||||
kfree(sg_table);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tmc_free_sg_table);
|
||||
|
||||
@@ -342,7 +344,6 @@ struct tmc_sg_table *tmc_alloc_sg_table(struct device *dev,
|
||||
rc = tmc_alloc_table_pages(sg_table);
|
||||
if (rc) {
|
||||
tmc_free_sg_table(sg_table);
|
||||
kfree(sg_table);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
@@ -1662,7 +1663,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
|
||||
goto unlock_out;
|
||||
}
|
||||
|
||||
/* Get a handle on the pid of the process to monitor */
|
||||
/* Get a handle on the pid of the session owner */
|
||||
pid = etr_perf->pid;
|
||||
|
||||
/* Do not proceed if this device is associated with another session */
|
||||
|
||||
@@ -171,8 +171,9 @@ struct etr_buf {
|
||||
* @csdev: component vitals needed by the framework.
|
||||
* @miscdev: specifics to handle "/dev/xyz.tmc" entry.
|
||||
* @spinlock: only one at a time pls.
|
||||
* @pid: Process ID of the process being monitored by the session
|
||||
* that is using this component.
|
||||
* @pid: Process ID of the process that owns the session that is using
|
||||
* this component. For example this would be the pid of the Perf
|
||||
* process.
|
||||
* @buf: Snapshot of the trace data for ETF/ETB.
|
||||
* @etr_buf: details of buffer used in TMC-ETR
|
||||
* @len: size of the available trace for ETF/ETB.
|
||||
|
||||
@@ -439,7 +439,8 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
|
||||
}
|
||||
|
||||
static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode,
|
||||
__maybe_unused struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
@@ -449,6 +450,11 @@ static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!coresight_take_mode(csdev, mode)) {
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
__tpdm_enable(drvdata);
|
||||
drvdata->enable = true;
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
@@ -506,6 +512,7 @@ static void tpdm_disable(struct coresight_device *csdev,
|
||||
}
|
||||
|
||||
__tpdm_disable(drvdata);
|
||||
coresight_set_mode(csdev, CS_MODE_DISABLED);
|
||||
drvdata->enable = false;
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2022, Linaro Limited, All rights reserved.
|
||||
* Author: Mike Leach <mike.leach@linaro.org>
|
||||
*/
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/coresight-pmu.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -11,18 +12,12 @@
|
||||
|
||||
#include "coresight-trace-id.h"
|
||||
|
||||
/* Default trace ID map. Used on systems that don't require per sink mappings */
|
||||
static struct coresight_trace_id_map id_map_default;
|
||||
|
||||
/* maintain a record of the mapping of IDs and pending releases per cpu */
|
||||
static DEFINE_PER_CPU(atomic_t, cpu_id) = ATOMIC_INIT(0);
|
||||
static cpumask_t cpu_id_release_pending;
|
||||
|
||||
/* perf session active counter */
|
||||
static atomic_t perf_cs_etm_session_active = ATOMIC_INIT(0);
|
||||
|
||||
/* lock to protect id_map and cpu data */
|
||||
static DEFINE_SPINLOCK(id_map_lock);
|
||||
/* Default trace ID map. Used in sysfs mode and for system sources */
|
||||
static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0);
|
||||
static struct coresight_trace_id_map id_map_default = {
|
||||
.cpu_map = &id_map_default_cpu_ids,
|
||||
.lock = __SPIN_LOCK_UNLOCKED(id_map_default.lock)
|
||||
};
|
||||
|
||||
/* #define TRACE_ID_DEBUG 1 */
|
||||
#if defined(TRACE_ID_DEBUG) || defined(CONFIG_COMPILE_TEST)
|
||||
@@ -32,7 +27,6 @@ static void coresight_trace_id_dump_table(struct coresight_trace_id_map *id_map,
|
||||
{
|
||||
pr_debug("%s id_map::\n", func_name);
|
||||
pr_debug("Used = %*pb\n", CORESIGHT_TRACE_IDS_MAX, id_map->used_ids);
|
||||
pr_debug("Pend = %*pb\n", CORESIGHT_TRACE_IDS_MAX, id_map->pend_rel_ids);
|
||||
}
|
||||
#define DUMP_ID_MAP(map) coresight_trace_id_dump_table(map, __func__)
|
||||
#define DUMP_ID_CPU(cpu, id) pr_debug("%s called; cpu=%d, id=%d\n", __func__, cpu, id)
|
||||
@@ -46,9 +40,9 @@ static void coresight_trace_id_dump_table(struct coresight_trace_id_map *id_map,
|
||||
#endif
|
||||
|
||||
/* unlocked read of current trace ID value for given CPU */
|
||||
static int _coresight_trace_id_read_cpu_id(int cpu)
|
||||
static int _coresight_trace_id_read_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
return atomic_read(&per_cpu(cpu_id, cpu));
|
||||
return atomic_read(per_cpu_ptr(id_map->cpu_map, cpu));
|
||||
}
|
||||
|
||||
/* look for next available odd ID, return 0 if none found */
|
||||
@@ -119,49 +113,33 @@ static void coresight_trace_id_free(int id, struct coresight_trace_id_map *id_ma
|
||||
clear_bit(id, id_map->used_ids);
|
||||
}
|
||||
|
||||
static void coresight_trace_id_set_pend_rel(int id, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
if (WARN(!IS_VALID_CS_TRACE_ID(id), "Invalid Trace ID %d\n", id))
|
||||
return;
|
||||
set_bit(id, id_map->pend_rel_ids);
|
||||
}
|
||||
|
||||
/*
|
||||
* release all pending IDs for all current maps & clear CPU associations
|
||||
*
|
||||
* This currently operates on the default id map, but may be extended to
|
||||
* operate on all registered id maps if per sink id maps are used.
|
||||
* Release all IDs and clear CPU associations.
|
||||
*/
|
||||
static void coresight_trace_id_release_all_pending(void)
|
||||
static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
struct coresight_trace_id_map *id_map = &id_map_default;
|
||||
unsigned long flags;
|
||||
int cpu, bit;
|
||||
int cpu;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
for_each_set_bit(bit, id_map->pend_rel_ids, CORESIGHT_TRACE_ID_RES_TOP) {
|
||||
clear_bit(bit, id_map->used_ids);
|
||||
clear_bit(bit, id_map->pend_rel_ids);
|
||||
}
|
||||
for_each_cpu(cpu, &cpu_id_release_pending) {
|
||||
atomic_set(&per_cpu(cpu_id, cpu), 0);
|
||||
cpumask_clear_cpu(cpu, &cpu_id_release_pending);
|
||||
}
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX);
|
||||
for_each_possible_cpu(cpu)
|
||||
atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
DUMP_ID_MAP(id_map);
|
||||
}
|
||||
|
||||
static int coresight_trace_id_map_get_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
|
||||
/* check for existing allocation for this CPU */
|
||||
id = _coresight_trace_id_read_cpu_id(cpu);
|
||||
id = _coresight_trace_id_read_cpu_id(cpu, id_map);
|
||||
if (id)
|
||||
goto get_cpu_id_clr_pend;
|
||||
goto get_cpu_id_out_unlock;
|
||||
|
||||
/*
|
||||
* Find a new ID.
|
||||
@@ -180,44 +158,32 @@ static int coresight_trace_id_map_get_cpu_id(int cpu, struct coresight_trace_id_
|
||||
goto get_cpu_id_out_unlock;
|
||||
|
||||
/* allocate the new id to the cpu */
|
||||
atomic_set(&per_cpu(cpu_id, cpu), id);
|
||||
|
||||
get_cpu_id_clr_pend:
|
||||
/* we are (re)using this ID - so ensure it is not marked for release */
|
||||
cpumask_clear_cpu(cpu, &cpu_id_release_pending);
|
||||
clear_bit(id, id_map->pend_rel_ids);
|
||||
atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id);
|
||||
|
||||
get_cpu_id_out_unlock:
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
|
||||
DUMP_ID_CPU(cpu, id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
return id;
|
||||
}
|
||||
|
||||
static void coresight_trace_id_map_put_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
/* check for existing allocation for this CPU */
|
||||
id = _coresight_trace_id_read_cpu_id(cpu);
|
||||
id = _coresight_trace_id_read_cpu_id(cpu, id_map);
|
||||
if (!id)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
|
||||
if (atomic_read(&perf_cs_etm_session_active)) {
|
||||
/* set release at pending if perf still active */
|
||||
coresight_trace_id_set_pend_rel(id, id_map);
|
||||
cpumask_set_cpu(cpu, &cpu_id_release_pending);
|
||||
} else {
|
||||
/* otherwise clear id */
|
||||
coresight_trace_id_free(id, id_map);
|
||||
atomic_set(&per_cpu(cpu_id, cpu), 0);
|
||||
}
|
||||
coresight_trace_id_free(id, id_map);
|
||||
atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
|
||||
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
DUMP_ID_CPU(cpu, id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
}
|
||||
@@ -227,10 +193,10 @@ static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *i
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
/* prefer odd IDs for system components to avoid legacy CPU IDS */
|
||||
id = coresight_trace_id_alloc_new_id(id_map, 0, true);
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
|
||||
DUMP_ID(id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
@@ -241,9 +207,9 @@ static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
coresight_trace_id_free(id, id_map);
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
|
||||
DUMP_ID(id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
@@ -253,22 +219,40 @@ static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *
|
||||
|
||||
int coresight_trace_id_get_cpu_id(int cpu)
|
||||
{
|
||||
return coresight_trace_id_map_get_cpu_id(cpu, &id_map_default);
|
||||
return _coresight_trace_id_get_cpu_id(cpu, &id_map_default);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_get_cpu_id);
|
||||
|
||||
int coresight_trace_id_get_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
return _coresight_trace_id_get_cpu_id(cpu, id_map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_get_cpu_id_map);
|
||||
|
||||
void coresight_trace_id_put_cpu_id(int cpu)
|
||||
{
|
||||
coresight_trace_id_map_put_cpu_id(cpu, &id_map_default);
|
||||
_coresight_trace_id_put_cpu_id(cpu, &id_map_default);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_put_cpu_id);
|
||||
|
||||
void coresight_trace_id_put_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
_coresight_trace_id_put_cpu_id(cpu, id_map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_put_cpu_id_map);
|
||||
|
||||
int coresight_trace_id_read_cpu_id(int cpu)
|
||||
{
|
||||
return _coresight_trace_id_read_cpu_id(cpu);
|
||||
return _coresight_trace_id_read_cpu_id(cpu, &id_map_default);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_read_cpu_id);
|
||||
|
||||
int coresight_trace_id_read_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
return _coresight_trace_id_read_cpu_id(cpu, id_map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_read_cpu_id_map);
|
||||
|
||||
int coresight_trace_id_get_system_id(void)
|
||||
{
|
||||
return coresight_trace_id_map_get_system_id(&id_map_default);
|
||||
@@ -281,17 +265,17 @@ void coresight_trace_id_put_system_id(int id)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_put_system_id);
|
||||
|
||||
void coresight_trace_id_perf_start(void)
|
||||
void coresight_trace_id_perf_start(struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
atomic_inc(&perf_cs_etm_session_active);
|
||||
PERF_SESSION(atomic_read(&perf_cs_etm_session_active));
|
||||
atomic_inc(&id_map->perf_cs_etm_session_active);
|
||||
PERF_SESSION(atomic_read(&id_map->perf_cs_etm_session_active));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_perf_start);
|
||||
|
||||
void coresight_trace_id_perf_stop(void)
|
||||
void coresight_trace_id_perf_stop(struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
if (!atomic_dec_return(&perf_cs_etm_session_active))
|
||||
coresight_trace_id_release_all_pending();
|
||||
PERF_SESSION(atomic_read(&perf_cs_etm_session_active));
|
||||
if (!atomic_dec_return(&id_map->perf_cs_etm_session_active))
|
||||
coresight_trace_id_release_all(id_map);
|
||||
PERF_SESSION(atomic_read(&id_map->perf_cs_etm_session_active));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_perf_stop);
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
* released when done.
|
||||
*
|
||||
* In order to ensure that a consistent cpu / ID matching is maintained
|
||||
* throughout a perf cs_etm event session - a session in progress flag will
|
||||
* be maintained, and released IDs not cleared until the perf session is
|
||||
* complete. This allows the same CPU to be re-allocated its prior ID.
|
||||
* throughout a perf cs_etm event session - a session in progress flag will be
|
||||
* maintained for each sink, and IDs are cleared when all the perf sessions
|
||||
* complete. This allows the same CPU to be re-allocated its prior ID when
|
||||
* events are scheduled in and out.
|
||||
*
|
||||
*
|
||||
* Trace ID maps will be created and initialised to prevent architecturally
|
||||
@@ -32,10 +33,6 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
/* architecturally we have 128 IDs some of which are reserved */
|
||||
#define CORESIGHT_TRACE_IDS_MAX 128
|
||||
|
||||
/* ID 0 is reserved */
|
||||
#define CORESIGHT_TRACE_ID_RES_0 0
|
||||
|
||||
@@ -46,23 +43,6 @@
|
||||
#define IS_VALID_CS_TRACE_ID(id) \
|
||||
((id > CORESIGHT_TRACE_ID_RES_0) && (id < CORESIGHT_TRACE_ID_RES_TOP))
|
||||
|
||||
/**
|
||||
* Trace ID map.
|
||||
*
|
||||
* @used_ids: Bitmap to register available (bit = 0) and in use (bit = 1) IDs.
|
||||
* Initialised so that the reserved IDs are permanently marked as
|
||||
* in use.
|
||||
* @pend_rel_ids: CPU IDs that have been released by the trace source but not
|
||||
* yet marked as available, to allow re-allocation to the same
|
||||
* CPU during a perf session.
|
||||
*/
|
||||
struct coresight_trace_id_map {
|
||||
DECLARE_BITMAP(used_ids, CORESIGHT_TRACE_IDS_MAX);
|
||||
DECLARE_BITMAP(pend_rel_ids, CORESIGHT_TRACE_IDS_MAX);
|
||||
};
|
||||
|
||||
/* Allocate and release IDs for a single default trace ID map */
|
||||
|
||||
/**
|
||||
* Read and optionally allocate a CoreSight trace ID and associate with a CPU.
|
||||
*
|
||||
@@ -78,19 +58,27 @@ struct coresight_trace_id_map {
|
||||
*/
|
||||
int coresight_trace_id_get_cpu_id(int cpu);
|
||||
|
||||
/**
|
||||
* Version of coresight_trace_id_get_cpu_id() that allows the ID map to operate
|
||||
* on to be provided.
|
||||
*/
|
||||
int coresight_trace_id_get_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Release an allocated trace ID associated with the CPU.
|
||||
*
|
||||
* This will release the CoreSight trace ID associated with the CPU,
|
||||
* unless a perf session is in operation.
|
||||
*
|
||||
* If a perf session is in operation then the ID will be marked as pending
|
||||
* release.
|
||||
* This will release the CoreSight trace ID associated with the CPU.
|
||||
*
|
||||
* @cpu: The CPU index to release the associated trace ID.
|
||||
*/
|
||||
void coresight_trace_id_put_cpu_id(int cpu);
|
||||
|
||||
/**
|
||||
* Version of coresight_trace_id_put_cpu_id() that allows the ID map to operate
|
||||
* on to be provided.
|
||||
*/
|
||||
void coresight_trace_id_put_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Read the current allocated CoreSight Trace ID value for the CPU.
|
||||
*
|
||||
@@ -111,6 +99,12 @@ void coresight_trace_id_put_cpu_id(int cpu);
|
||||
*/
|
||||
int coresight_trace_id_read_cpu_id(int cpu);
|
||||
|
||||
/**
|
||||
* Version of coresight_trace_id_read_cpu_id() that allows the ID map to operate
|
||||
* on to be provided.
|
||||
*/
|
||||
int coresight_trace_id_read_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Allocate a CoreSight trace ID for a system component.
|
||||
*
|
||||
@@ -136,21 +130,21 @@ void coresight_trace_id_put_system_id(int id);
|
||||
/**
|
||||
* Notify the Trace ID allocator that a perf session is starting.
|
||||
*
|
||||
* Increase the perf session reference count - called by perf when setting up
|
||||
* a trace event.
|
||||
* Increase the perf session reference count - called by perf when setting up a
|
||||
* trace event.
|
||||
*
|
||||
* This reference count is used by the ID allocator to ensure that trace IDs
|
||||
* associated with a CPU cannot change or be released during a perf session.
|
||||
* Perf sessions never free trace IDs to ensure that the ID associated with a
|
||||
* CPU cannot change during their and other's concurrent sessions. Instead,
|
||||
* this refcount is used so that the last event to finish always frees all IDs.
|
||||
*/
|
||||
void coresight_trace_id_perf_start(void);
|
||||
void coresight_trace_id_perf_start(struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Notify the ID allocator that a perf session is stopping.
|
||||
*
|
||||
* Decrease the perf session reference count.
|
||||
* if this causes the count to go to zero, then all Trace IDs marked as pending
|
||||
* release, will be released.
|
||||
* Decrease the perf session reference count. If this causes the count to go to
|
||||
* zero, then all Trace IDs will be released.
|
||||
*/
|
||||
void coresight_trace_id_perf_stop(void);
|
||||
void coresight_trace_id_perf_stop(struct coresight_trace_id_map *id_map);
|
||||
|
||||
#endif /* _CORESIGHT_TRACE_ID_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user