Char/Misc and other driver changes for 6.12-rc1

Here is the "big" set of char/misc and other driver subsystem changes
 for 6.12-rc1.  Sorry for the delay, conference travel for the past two
 weeks has this and my other pull requests showing up real late
 in the cycle.
 
 Lots of changes in here, primarily dominated by the usual IIO driver
 updates and additions, but there are also small driver subsystem updates
 all over the place.  Included in here are:
   - lots and lots of new IIO drivers and updates to existing ones
   - interconnect subsystem updates and new drivers
   - nvmem subsystem updates and new drivers
   - mhi driver updates
   - power supply subsystem updates
   - kobj_type const work for many different small subsystems
   - comedi driver fix
   - coresight subsystem and driver updates
   - fpga subsystem improvements
   - slimbus fixups
   - binder new feature addition for "frozen" notifications
   - lots and lots of other small driver updates and cleanups
 
 All of these have been in linux-next for a long time with no reported
 problems.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZvUxoA8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykEnwCgnv9Q9tNrabLB2VXu8dRgMCee0J4AoIc5qA7/
 mLXk2wxl5+dt/dfNgZIp
 =x5HV
 -----END PGP SIGNATURE-----

Merge tag 'char-misc-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char / misc driver updates from Greg KH:
 "Here is the "big" set of char/misc and other driver subsystem changes
  for 6.12-rc1.

  Lots of changes in here, primarily dominated by the usual IIO driver
  updates and additions, but there are also small driver subsystem
  updates all over the place. Included in here are:

   - lots and lots of new IIO drivers and updates to existing ones

   - interconnect subsystem updates and new drivers

   - nvmem subsystem updates and new drivers

   - mhi driver updates

   - power supply subsystem updates

   - kobj_type const work for many different small subsystems

   - comedi driver fix

   - coresight subsystem and driver updates

   - fpga subsystem improvements

   - slimbus fixups

   - binder new feature addition for "frozen" notifications

   - lots and lots of other small driver updates and cleanups

  All of these have been in linux-next for a long time with no reported
  problems"

* tag 'char-misc-6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (354 commits)
  greybus: gb-beagleplay: Add firmware upload API
  arm64: dts: ti: k3-am625-beagleplay: Add bootloader-backdoor-gpios to cc1352p7
  dt-bindings: net: ti,cc1352p7: Add bootloader-backdoor-gpios
  MAINTAINERS: Update path for U-Boot environment variables YAML
  nvmem: layouts: add U-Boot env layout
  comedi: ni_routing: tools: Check when the file could not be opened
  ocxl: Remove the unused declarations in headr file
  hpet: Fix the wrong format specifier
  uio: Constify struct kobj_type
  cxl: Constify struct kobj_type
  binder: modify the comment for binder_proc_unlock
  iio: adc: axp20x_adc: add support for AXP717 ADC
  dt-bindings: iio: adc: Add AXP717 compatible
  iio: adc: axp20x_adc: Add adc_en1 and adc_en2 to axp_data
  w1: ds2482: Drop explicit initialization of struct i2c_device_id::driver_data to 0
  tools: iio: rm .*.cmd when make clean
  iio: adc: standardize on formatting for id match tables
  iio: proximity: aw96103: Add support for aw96103/aw96105 proximity sensor
  bus: mhi: host: pci_generic: Enable EDL trigger for Foxconn modems
  bus: mhi: host: pci_generic: Update EDL firmware path for Foxconn modems
  ...
This commit is contained in:
Linus Torvalds 2024-09-26 10:13:08 -07:00
commit 5e5466433d
337 changed files with 21962 additions and 3117 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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>;
};
};
};
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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";
};
};

View File

@ -16,6 +16,7 @@ properties:
- kionix,kxcj91008
- kionix,kxtj21009
- kionix,kxtf9
- kionix,kx022-1020
- kionix,kx023-1025
reg:

View File

@ -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;
};
};
};

View File

@ -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>;

View File

@ -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

View File

@ -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;
};
};
...

View File

@ -28,6 +28,9 @@ properties:
- adi,ad9265
- adi,ad9434
- adi,ad9467
- adi,ad9643
- adi,ad9649
- adi,ad9652
reg:
maxItems: 1

View File

@ -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>;
};
};
...

View File

@ -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

View File

@ -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>;
};

View File

@ -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>;
};
};

View File

@ -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:

View File

@ -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>;
};
};
};

View File

@ -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:

View File

@ -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>;
};
};
};
...

View File

@ -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>;
};
};
};
...

View File

@ -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

View File

@ -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

View File

@ -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>;
};
};
...

View File

@ -14,7 +14,9 @@ description:
properties:
compatible:
const: liteon,ltrf216a
enum:
- liteon,ltr308
- liteon,ltrf216a
reg:
maxItems: 1

View File

@ -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>;
};
};
...

View File

@ -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>;
};

View File

@ -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

View File

@ -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:

View File

@ -36,6 +36,9 @@ properties:
interrupts:
maxItems: 1
mount-matrix:
description: an optional 3x3 mounting rotation matrix.
additionalProperties: false
required:

View File

@ -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>;
};
};

View File

@ -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>;
};
};

View File

@ -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>;
};
};
};

View File

@ -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";

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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>;
};
};

View File

@ -15,6 +15,7 @@ description: |
allOf:
- $ref: nvmem.yaml#
- $ref: nvmem-deprecated-cells.yaml
properties:
compatible:

View File

@ -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:

View File

@ -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

View File

@ -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>;
};
};
};
};
};

View File

@ -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:

View File

@ -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,.*":

View File

@ -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 |
+-------------+

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -18,8 +18,12 @@ Industrial I/O Kernel Drivers
.. toctree::
:maxdepth: 1
ad4000
ad4695
ad7380
ad7944
adis16475
adis16480
adxl380
bno055
ep93xx_adc

View File

@ -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
@ -13418,6 +13455,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
@ -15186,6 +15233,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
@ -19990,6 +20044,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
@ -20843,6 +20903,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
@ -23605,7 +23671,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

View File

@ -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>;
};
};

View File

@ -277,7 +277,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()
@ -1352,6 +1352,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);
}
@ -1546,7 +1547,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)
{
@ -3842,6 +3843,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
@ -4325,6 +4475,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);
@ -4714,6 +4902,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",
@ -5322,6 +5550,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)
{
@ -5333,6 +5603,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;
}
@ -5365,6 +5636,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;
@ -5740,6 +6013,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;
@ -6291,7 +6565,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[] = {
@ -6314,6 +6590,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[] = {
@ -6323,7 +6602,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,

View File

@ -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;
};
@ -276,6 +279,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
@ -308,6 +319,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.
@ -324,6 +337,7 @@ struct binder_ref {
struct binder_proc *proc;
struct binder_node *node;
struct binder_ref_death *death;
struct binder_ref_freeze *freeze;
};
/**
@ -377,6 +391,8 @@ struct binder_ref {
* (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
@ -424,6 +440,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;

View File

@ -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;
}

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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[] = {
{

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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);

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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, &region_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,
};

View File

@ -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";

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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 */

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -177,6 +177,33 @@ config ADXL372_I2C
To compile this driver as a module, choose M here: the
module will be called adxl372_i2c.
config ADXL380
tristate
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
config ADXL380_SPI
tristate "Analog Devices ADXL380 3-Axis Accelerometer SPI Driver"
depends on SPI
select ADXL380
select REGMAP_SPI
help
Say yes here to add support for the Analog Devices ADXL380 triaxial
acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called adxl380_spi.
config ADXL380_I2C
tristate "Analog Devices ADXL380 3-Axis Accelerometer I2C Driver"
depends on I2C
select ADXL380
select REGMAP_I2C
help
Say yes here to add support for the Analog Devices ADXL380 triaxial
acceleration sensor.
To compile this driver as a module, choose M here: the
module will be called adxl380_i2c.
config BMA180
tristate "Bosch BMA023/BMA1x0/BMA250 3-Axis Accelerometer Driver"
depends on I2C && INPUT_BMA150=n

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