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:
commit
5e5466433d
@ -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.
|
||||
|
||||
|
39
Documentation/ABI/testing/debugfs-iio-ad9467
Normal file
39
Documentation/ABI/testing/debugfs-iio-ad9467
Normal 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.
|
20
Documentation/ABI/testing/debugfs-iio-backend
Normal file
20
Documentation/ABI/testing/debugfs-iio-backend
Normal 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
|
@ -523,13 +523,27 @@ Description:
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltageY_i_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltageY_q_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_capacitance_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_resistance_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_temp_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_calibbias
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@ -541,6 +555,10 @@ Description:
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_temp_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibbias_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_calibbias_available
|
||||
KernelVersion: 5.8
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@ -549,25 +567,34 @@ Description:
|
||||
- a small discrete set of values like "0 2 4 6 8"
|
||||
- a range specified as "[min step max]"
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_altvoltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_capacitance_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_both_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_ir_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressure_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_currentY_calibscale
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_calibscale
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@ -575,6 +602,20 @@ Description:
|
||||
production inaccuracies). If shared across all channels,
|
||||
<type>_calibscale is used.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminanceY_calibscale_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensityY_calibscale_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximityY_calibscale_available
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale_available
|
||||
KernelVersion: 4.8
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Available values of calibscale. Maybe expressed as either of:
|
||||
|
||||
- a small discrete set of values like "1 8 16"
|
||||
- a range specified as "[min step max]"
|
||||
|
||||
If shared across all channels, <type>_calibscale_available is used.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_activity_calibgender
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_energy_calibgender
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_distance_calibgender
|
||||
@ -708,6 +749,7 @@ Description:
|
||||
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
||||
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
|
||||
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
|
||||
42kohm_to_gnd: connected to ground via a 42kOhm resistor,
|
||||
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
|
||||
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
|
||||
125kohm_to_gnd: connected to ground via an 125kOhm resistor,
|
||||
@ -2289,3 +2331,11 @@ KernelVersion: 6.7
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
List of available timeout value for tap gesture confirmation.
|
||||
|
||||
What: /sys/.../iio:deviceX/in_shunt_resistor
|
||||
What: /sys/.../iio:deviceX/in_current_shunt_resistor
|
||||
What: /sys/.../iio:deviceX/in_power_shunt_resistor
|
||||
KernelVersion: 6.10
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
The value of current sense resistor in Ohms.
|
||||
|
@ -1,17 +0,0 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_power_shunt_resistor
|
||||
Date: March 2017
|
||||
KernelVersion: 4.12
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description: The value of the shunt resistor used to compute power drain on
|
||||
common input voltage pin (RS+). In Ohms.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_current_shunt_resistor
|
||||
Date: March 2017
|
||||
KernelVersion: 4.12
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description: The value of the shunt resistor used to compute current flowing
|
||||
between RS+ and RS- voltage sense inputs. In Ohms.
|
||||
|
||||
These attributes describe a single physical component, exposed as two distinct
|
||||
attributes as it is used to calculate two different values: power load and
|
||||
current flowing between RS+ and RS- inputs.
|
@ -15,17 +15,3 @@ Description:
|
||||
Set the relative humidity. This value is sent to the sensor for
|
||||
humidity compensation.
|
||||
Default value: 50000 (50 % relative humidity)
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_resistance_calibbias
|
||||
Date: August 2021
|
||||
KernelVersion: 5.15
|
||||
Contact: Andreas Klinger <ak@it-klinger.de>
|
||||
Description:
|
||||
Set the bias value for the resistance which is used for
|
||||
calculation of in_concentration_input as follows:
|
||||
|
||||
x = (in_resistance_raw - in_resistance_calibbias) * 0.65
|
||||
|
||||
in_concentration_input = 500 / (1 + e^x)
|
||||
|
||||
Default value: 30000
|
||||
|
61
Documentation/ABI/testing/sysfs-bus-iio-dac
Normal file
61
Documentation/ABI/testing/sysfs-bus-iio-dac
Normal 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.
|
@ -53,34 +53,3 @@ KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Returns the available values for the dither phase.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_toggle_en
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Toggle enable. Write 1 to enable toggle or 0 to disable it. This is
|
||||
useful when one wants to change the DAC output codes. The way it should
|
||||
be done is:
|
||||
|
||||
- disable toggle operation;
|
||||
- change out_voltageY_raw0 and out_voltageY_raw1;
|
||||
- enable toggle operation.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw0
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw1
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
It has the same meaning as out_voltageY_raw. This attribute is
|
||||
specific to toggle enabled channels and refers to the DAC output
|
||||
code in INPUT_A (_raw0) and INPUT_B (_raw1). The same scale and offset
|
||||
as in out_voltageY_raw applies.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_symbol
|
||||
KernelVersion: 5.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Performs a SW toggle. This attribute is specific to toggle
|
||||
enabled channels and allows to toggle between out_voltageY_raw0
|
||||
and out_voltageY_raw1 through software. Writing 0 will select
|
||||
out_voltageY_raw0 while 1 selects out_voltageY_raw1.
|
||||
|
@ -3,7 +3,7 @@ KernelVersion:
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Reading this returns the valid values that can be written to the
|
||||
on_altvoltage0_mode attribute:
|
||||
filter_mode attribute:
|
||||
|
||||
- auto -> Adjust bandpass filter to track changes in input clock rate.
|
||||
- manual -> disable/unregister the clock rate notifier / input clock tracking.
|
||||
|
@ -13,12 +13,3 @@ Description:
|
||||
available for reading data. However, samples can be occasionally skipped
|
||||
or repeated, depending on the beat between the capture and conversion
|
||||
rates.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_shunt_resistor
|
||||
Date: December 2015
|
||||
KernelVersion: 4.4
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
The value of the shunt resistor may be known only at runtime fom an
|
||||
eeprom content read by a client application. This attribute allows to
|
||||
set its value in ohms.
|
||||
|
@ -37,6 +37,11 @@ properties:
|
||||
GPIO pin (output) used to control VBUS. If skipped, no such control
|
||||
takes place.
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
A port node to link the usb controller for the dual role switch.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- interrupts
|
||||
@ -58,5 +63,11 @@ examples:
|
||||
interrupt-parent = <&msmgpio>;
|
||||
interrupts = <78 IRQ_TYPE_LEVEL_HIGH>;
|
||||
vbus-gpios = <&msmgpio 148 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&usb1_drd_sw>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1,21 +0,0 @@
|
||||
USB GPIO Extcon device
|
||||
|
||||
This is a virtual device used to generate USB cable states from the USB ID pin
|
||||
connected to a GPIO pin.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "linux,extcon-usb-gpio"
|
||||
|
||||
Either one of id-gpio or vbus-gpio must be present. Both can be present as well.
|
||||
- id-gpio: gpio for USB ID pin. See gpio binding.
|
||||
- vbus-gpio: gpio for USB VBUS pin.
|
||||
|
||||
Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
|
||||
extcon_usb1 {
|
||||
compatible = "linux,extcon-usb-gpio";
|
||||
id-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
|
||||
}
|
||||
|
||||
&omap_dwc3_1 {
|
||||
extcon = <&extcon_usb1>;
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/extcon/linux,extcon-usb-gpio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: USB GPIO Extcon device
|
||||
|
||||
maintainers:
|
||||
- Frank Li <Frank.Li@nxp.com>
|
||||
|
||||
description:
|
||||
This is a virtual device used to generate USB cable states from the USB ID pin
|
||||
connected to a GPIO pin.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: linux,extcon-usb-gpio
|
||||
|
||||
id-gpios:
|
||||
description: gpio for USB ID pin. See gpio binding.
|
||||
vbus-gpios:
|
||||
description: gpio for USB VBUS pin.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
extcon_usb1 {
|
||||
compatible = "linux,extcon-usb-gpio";
|
||||
id-gpios = <&gpio6 1 GPIO_ACTIVE_HIGH>;
|
||||
};
|
92
Documentation/devicetree/bindings/iio/accel/adi,adxl380.yaml
Normal file
92
Documentation/devicetree/bindings/iio/accel/adi,adxl380.yaml
Normal 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";
|
||||
};
|
||||
};
|
@ -16,6 +16,7 @@ properties:
|
||||
- kionix,kxcj91008
|
||||
- kionix,kxtj21009
|
||||
- kionix,kxtf9
|
||||
- kionix,kx022-1020
|
||||
- kionix,kx023-1025
|
||||
|
||||
reg:
|
||||
|
254
Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml
Normal file
254
Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml
Normal 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;
|
||||
};
|
||||
};
|
||||
};
|
@ -39,11 +39,21 @@ properties:
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: phandle to the master clock (mclk)
|
||||
description:
|
||||
Optionally, either a crystal can be attached externally between MCLK1 and
|
||||
MCLK2 pins, or an external CMOS-compatible clock can drive the MCLK2
|
||||
pin. If absent, internal 4.92MHz clock is used, which can be made
|
||||
available on MCLK2 pin.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk
|
||||
enum:
|
||||
- xtal
|
||||
- mclk
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
description:
|
||||
If present when internal clock is used, configured as clock provider.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
@ -134,8 +144,6 @@ patternProperties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- dvdd-supply
|
||||
- avdd-supply
|
||||
@ -156,6 +164,18 @@ allOf:
|
||||
then:
|
||||
patternProperties:
|
||||
"^channel@[0-9a-f]+$": false
|
||||
- if:
|
||||
anyOf:
|
||||
- required:
|
||||
- clocks
|
||||
- required:
|
||||
- clock-names
|
||||
then:
|
||||
properties:
|
||||
"#clock-cells": false
|
||||
required:
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
@ -201,8 +221,7 @@ examples:
|
||||
spi-max-frequency = <1000000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
clocks = <&ad7192_mclk>;
|
||||
clock-names = "mclk";
|
||||
#clock-cells = <0>;
|
||||
interrupts = <25 0x2>;
|
||||
interrupt-parent = <&gpio>;
|
||||
aincom-supply = <&aincom>;
|
||||
|
@ -15,10 +15,17 @@ description: |
|
||||
* https://www.analog.com/en/products/ad7381.html
|
||||
* https://www.analog.com/en/products/ad7383.html
|
||||
* https://www.analog.com/en/products/ad7384.html
|
||||
* https://www.analog.com/en/products/ad7386.html
|
||||
* https://www.analog.com/en/products/ad7387.html
|
||||
* https://www.analog.com/en/products/ad7388.html
|
||||
* https://www.analog.com/en/products/ad7380-4.html
|
||||
* https://www.analog.com/en/products/ad7381-4.html
|
||||
* https://www.analog.com/en/products/ad7383-4.html
|
||||
* https://www.analog.com/en/products/ad7384-4.html
|
||||
* https://www.analog.com/en/products/ad7386-4.html
|
||||
* https://www.analog.com/en/products/ad7387-4.html
|
||||
* https://www.analog.com/en/products/ad7388-4.html
|
||||
|
||||
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
@ -29,10 +36,16 @@ properties:
|
||||
- adi,ad7381
|
||||
- adi,ad7383
|
||||
- adi,ad7384
|
||||
- adi,ad7386
|
||||
- adi,ad7387
|
||||
- adi,ad7388
|
||||
- adi,ad7380-4
|
||||
- adi,ad7381-4
|
||||
- adi,ad7383-4
|
||||
- adi,ad7384-4
|
||||
- adi,ad7386-4
|
||||
- adi,ad7387-4
|
||||
- adi,ad7388-4
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -35,65 +35,83 @@ properties:
|
||||
|
||||
avcc-supply: true
|
||||
|
||||
vdrive-supply:
|
||||
description:
|
||||
Determines the voltage level at which the interface logic pins will
|
||||
operate.
|
||||
|
||||
refin-supply:
|
||||
description:
|
||||
The voltage supply for optional external reference voltage.
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
The BUSY pin falling edge indicates that the conversion is over, and thus
|
||||
new data is available.
|
||||
maxItems: 1
|
||||
|
||||
adi,conversion-start-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the CONVST pin.
|
||||
This logic input is used to initiate conversions on the analog
|
||||
input channels. As the line is active high, it should be marked
|
||||
GPIO_ACTIVE_HIGH.
|
||||
maxItems: 1
|
||||
Must be the device tree identifier of the CONVST pin(s). This logic input
|
||||
is used to initiate conversions on the analog input channels. As the line
|
||||
is active high, it should be marked GPIO_ACTIVE_HIGH.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the RESET pin. If specified,
|
||||
it will be asserted during driver probe. As the line is active high,
|
||||
it should be marked GPIO_ACTIVE_HIGH.
|
||||
Must be the device tree identifier of the RESET pin. If specified, it will
|
||||
be asserted during driver probe. On the AD7606x, as the line is active
|
||||
high, it should be marked GPIO_ACTIVE_HIGH. On the AD7616, as the line is
|
||||
active low, it should be marked GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
standby-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the STBY pin. This pin is used
|
||||
to place the AD7606 into one of two power-down modes, Standby mode or
|
||||
Must be the device tree identifier of the STBY pin. This pin is used to
|
||||
place the AD7606 into one of two power-down modes, Standby mode or
|
||||
Shutdown mode. As the line is active low, it should be marked
|
||||
GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
adi,first-data-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the FRSTDATA pin.
|
||||
The FRSTDATA output indicates when the first channel, V1, is
|
||||
being read back on either the parallel, byte or serial interface.
|
||||
As the line is active high, it should be marked GPIO_ACTIVE_HIGH.
|
||||
Must be the device tree identifier of the FRSTDATA pin. The FRSTDATA
|
||||
output indicates when the first channel, V1, is being read back on either
|
||||
the parallel, byte or serial interface. As the line is active high, it
|
||||
should be marked GPIO_ACTIVE_HIGH.
|
||||
maxItems: 1
|
||||
|
||||
adi,range-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the RANGE pin. The polarity on
|
||||
this pin determines the input range of the analog input channels. If
|
||||
this pin is tied to a logic high, the analog input range is ±10V for
|
||||
all channels. If this pin is tied to a logic low, the analog input range
|
||||
Must be the device tree identifier of the RANGE pin. The state on this
|
||||
pin determines the input range of the analog input channels. If this pin
|
||||
is tied to a logic high, the analog input range is ±10V for all channels.
|
||||
On the AD760X, if this pin is tied to a logic low, the analog input range
|
||||
is ±5V for all channels. As the line is active high, it should be marked
|
||||
GPIO_ACTIVE_HIGH.
|
||||
maxItems: 1
|
||||
GPIO_ACTIVE_HIGH. On the AD7616, there are 2 pins, and if the 2 pins are
|
||||
tied to a logic high, software mode is enabled, otherwise one of the 3
|
||||
possible range values is selected.
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
adi,oversampling-ratio-gpios:
|
||||
description:
|
||||
Must be the device tree identifier of the over-sampling
|
||||
mode pins. As the line is active high, it should be marked
|
||||
GPIO_ACTIVE_HIGH.
|
||||
Must be the device tree identifier of the over-sampling mode pins. As the
|
||||
line is active high, it should be marked GPIO_ACTIVE_HIGH. On the AD7606X
|
||||
parts that support it, if all 3 pins are tied to a logic high, software
|
||||
mode is enabled.
|
||||
maxItems: 3
|
||||
|
||||
adi,sw-mode:
|
||||
description:
|
||||
Software mode of operation, so far available only for ad7616 and ad7606b.
|
||||
It is enabled when all three oversampling mode pins are connected to
|
||||
high level. The device is configured by the corresponding registers. If the
|
||||
adi,oversampling-ratio-gpios property is defined, then the driver will set the
|
||||
oversampling gpios to high. Otherwise, it is assumed that the pins are hardwired
|
||||
to VDD.
|
||||
Software mode of operation, so far available only for AD7616 and AD7606B.
|
||||
It is enabled when all three oversampling mode pins are connected to high
|
||||
level for the AD7606B, or both the range selection are connected to high
|
||||
level for the AD7616. The device is configured by the corresponding
|
||||
registers. If the adi,oversampling-ratio-gpios property is defined, then
|
||||
the driver will set the oversampling gpios to high. Otherwise, it is
|
||||
assumed that the pins are hardwired to VDD.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
@ -101,12 +119,57 @@ required:
|
||||
- reg
|
||||
- spi-cpha
|
||||
- avcc-supply
|
||||
- vdrive-supply
|
||||
- interrupts
|
||||
- adi,conversion-start-gpios
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: adi,ad7616
|
||||
then:
|
||||
properties:
|
||||
adi,first-data-gpios: false
|
||||
standby-gpios: false
|
||||
adi,range-gpios:
|
||||
maxItems: 2
|
||||
else:
|
||||
properties:
|
||||
adi,range-gpios:
|
||||
maxItems: 1
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad7605-4
|
||||
- adi,ad7616
|
||||
then:
|
||||
properties:
|
||||
adi,oversampling-ratio-gpios: false
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad7605-4
|
||||
- adi,ad7606-4
|
||||
- adi,ad7606-6
|
||||
- adi,ad7606-8
|
||||
then:
|
||||
properties:
|
||||
adi,sw-mode: false
|
||||
else:
|
||||
properties:
|
||||
adi,conversion-start-gpios:
|
||||
maxItems: 1
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
@ -125,6 +188,7 @@ examples:
|
||||
spi-cpha;
|
||||
|
||||
avcc-supply = <&adc_vref>;
|
||||
vdrive-supply = <&vdd_supply>;
|
||||
|
||||
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-parent = <&gpio>;
|
||||
@ -136,7 +200,6 @@ examples:
|
||||
<&gpio 23 GPIO_ACTIVE_HIGH>,
|
||||
<&gpio 26 GPIO_ACTIVE_HIGH>;
|
||||
standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
|
||||
adi,sw-mode;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
@ -28,6 +28,9 @@ properties:
|
||||
- adi,ad9265
|
||||
- adi,ad9434
|
||||
- adi,ad9467
|
||||
- adi,ad9643
|
||||
- adi,ad9649
|
||||
- adi,ad9652
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/microchip,pac1921.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip PAC1921 High-Side Power/Current Monitor with Anaog Output
|
||||
|
||||
maintainers:
|
||||
- Matteo Martelli <matteomartelli3@gmail.com>
|
||||
|
||||
description: |
|
||||
The PAC1921 is a power/current monitoring device with an analog output
|
||||
and I2C/SMBus interface.
|
||||
|
||||
Datasheet can be found here:
|
||||
https://ww1.microchip.com/downloads/en/DeviceDoc/PAC1921-Data-Sheet-DS20005293E.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,pac1921
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
shunt-resistor-micro-ohms:
|
||||
description:
|
||||
Value in micro Ohms of the shunt resistor connected between
|
||||
the SENSE+ and SENSE- inputs, across which the current is measured.
|
||||
Value is needed to compute the scaling of the measured current.
|
||||
|
||||
label:
|
||||
description: Unique name to identify which device this is.
|
||||
|
||||
read-integrate-gpios:
|
||||
description:
|
||||
READ/INT input pin to control the current state of the device, either in
|
||||
the INTEGRATE state when driven high, or in the READ state when driven low.
|
||||
When not connected the pin is floating and it can be overridden by the
|
||||
INT_EN register bit after asserting the READ/INT_OVR register bit.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- shunt-resistor-micro-ohms
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@4c {
|
||||
compatible = "microchip,pac1921";
|
||||
reg = <0x4c>;
|
||||
vdd-supply = <&vdd>;
|
||||
#io-channel-cells = <1>;
|
||||
label = "vbat";
|
||||
shunt-resistor-micro-ohms = <10000>;
|
||||
};
|
||||
};
|
||||
...
|
@ -16,6 +16,9 @@ properties:
|
||||
- const: rockchip,rk3066-tsadc
|
||||
- const: rockchip,rk3399-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
- const: rockchip,rk3576-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-saradc
|
||||
|
@ -18,18 +18,39 @@ properties:
|
||||
- sd-modulator
|
||||
- ads1201
|
||||
|
||||
'#io-backend-cells':
|
||||
const: 0
|
||||
|
||||
'#io-channel-cells':
|
||||
const: 0
|
||||
|
||||
vref-supply:
|
||||
description: Phandle to the vref input analog reference voltage.
|
||||
|
||||
dependencies:
|
||||
vref-supply: [ '#io-backend-cells' ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- '#io-channel-cells'
|
||||
|
||||
anyOf:
|
||||
- required: ['#io-backend-cells']
|
||||
- required: ['#io-channel-cells']
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
ads1202: adc {
|
||||
// Backend binding example. SD modulator configured as an IIO backend device
|
||||
ads1201_0: adc {
|
||||
compatible = "sd-modulator";
|
||||
vref-supply = <&vdd_adc>;
|
||||
#io-backend-cells = <0>;
|
||||
};
|
||||
|
||||
- |
|
||||
// Legacy binding example. SD modulator configured as an IIO channel provider
|
||||
ads1201_1: adc {
|
||||
compatible = "sd-modulator";
|
||||
#io-channel-cells = <0>;
|
||||
};
|
||||
|
@ -0,0 +1,83 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/sophgo,cv1800b-saradc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title:
|
||||
Sophgo CV1800B SoC 3 channels Successive Approximation Analog to
|
||||
Digital Converters
|
||||
|
||||
maintainers:
|
||||
- Thomas Bonnefille <thomas.bonnefille@bootlin.com>
|
||||
|
||||
description:
|
||||
Datasheet at https://github.com/sophgo/sophgo-doc/releases
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sophgo,cv1800b-saradc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-2]$":
|
||||
$ref: adc.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- minimum: 0
|
||||
maximum: 2
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/sophgo,cv1800.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
adc@30f0000 {
|
||||
compatible = "sophgo,cv1800b-saradc";
|
||||
reg = <0x030f0000 0x1000>;
|
||||
clocks = <&clk CLK_SARADC>;
|
||||
interrupts = <100 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
@ -54,7 +54,9 @@ properties:
|
||||
It's not present on stm32f4.
|
||||
It's required on stm32h7 and stm32mp1.
|
||||
|
||||
clock-names: true
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
st,max-clk-rate-hz:
|
||||
description:
|
||||
|
@ -102,9 +102,11 @@ patternProperties:
|
||||
items:
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
deprecated: true
|
||||
|
||||
st,adc-channel-names:
|
||||
description: List of single-ended channel names.
|
||||
deprecated: true
|
||||
|
||||
st,filter-order:
|
||||
description: |
|
||||
@ -118,6 +120,12 @@ patternProperties:
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
st,adc-channel-types:
|
||||
description: |
|
||||
Single-ended channel input type.
|
||||
@ -128,6 +136,7 @@ patternProperties:
|
||||
items:
|
||||
enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
deprecated: true
|
||||
|
||||
st,adc-channel-clk-src:
|
||||
description: |
|
||||
@ -139,6 +148,7 @@ patternProperties:
|
||||
items:
|
||||
enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
deprecated: true
|
||||
|
||||
st,adc-alt-channel:
|
||||
description:
|
||||
@ -147,6 +157,7 @@ patternProperties:
|
||||
If not set, channel n is connected to SPI input n.
|
||||
If set, channel n is connected to SPI input n + 1.
|
||||
type: boolean
|
||||
deprecated: true
|
||||
|
||||
st,filter0-sync:
|
||||
description:
|
||||
@ -165,11 +176,60 @@ patternProperties:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- st,adc-channels
|
||||
- st,adc-channel-names
|
||||
- st,filter-order
|
||||
- "#io-channel-cells"
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
type: object
|
||||
$ref: adc.yaml
|
||||
unevaluatedProperties: false
|
||||
description: Represents the external channels which are connected to the DFSDM.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maximum: 7
|
||||
|
||||
label:
|
||||
description:
|
||||
Unique name to identify which channel this is.
|
||||
|
||||
st,adc-channel-type:
|
||||
description: |
|
||||
Single-ended channel input type.
|
||||
- "SPI_R": SPI with data on rising edge (default)
|
||||
- "SPI_F": SPI with data on falling edge
|
||||
- "MANCH_R": manchester codec, rising edge = logic 0, falling edge = logic 1
|
||||
- "MANCH_F": manchester codec, rising edge = logic 1, falling edge = logic 0
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum: [ SPI_R, SPI_F, MANCH_R, MANCH_F ]
|
||||
|
||||
st,adc-channel-clk-src:
|
||||
description: |
|
||||
Conversion clock source.
|
||||
- "CLKIN": external SPI clock (CLKIN x)
|
||||
- "CLKOUT": internal SPI clock (CLKOUT) (default)
|
||||
- "CLKOUT_F": internal SPI clock divided by 2 (falling edge).
|
||||
- "CLKOUT_R": internal SPI clock divided by 2 (rising edge).
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum: [ CLKIN, CLKOUT, CLKOUT_F, CLKOUT_R ]
|
||||
|
||||
st,adc-alt-channel:
|
||||
description:
|
||||
Must be defined if two sigma delta modulators are
|
||||
connected on same SPI input.
|
||||
If not set, channel n is connected to SPI input n.
|
||||
If set, channel n is connected to SPI input n + 1.
|
||||
type: boolean
|
||||
|
||||
io-backends:
|
||||
description:
|
||||
Used to pipe external sigma delta modulator or internal ADC backend to DFSDM channel.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
@ -199,9 +259,19 @@ patternProperties:
|
||||
description:
|
||||
From common IIO binding. Used to pipe external sigma delta
|
||||
modulator or internal ADC output to DFSDM channel.
|
||||
deprecated: true
|
||||
|
||||
required:
|
||||
- io-channels
|
||||
if:
|
||||
required:
|
||||
- st,adc-channels
|
||||
then:
|
||||
required:
|
||||
- io-channels
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]$":
|
||||
required:
|
||||
- io-backends
|
||||
|
||||
- if:
|
||||
properties:
|
||||
@ -298,6 +368,7 @@ examples:
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
// Example 1: Audio use case with generic binding
|
||||
dfsdm0: filter@0 {
|
||||
compatible = "st,stm32-dfsdm-dmic";
|
||||
reg = <0>;
|
||||
@ -305,12 +376,18 @@ examples:
|
||||
dmas = <&dmamux1 101 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
#io-channel-cells = <1>;
|
||||
st,adc-channels = <1>;
|
||||
st,adc-channel-names = "dmic0";
|
||||
st,adc-channel-types = "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
st,filter-order = <5>;
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
label = "dmic0";
|
||||
st,adc-channel-type = "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
st,adc-alt-channel;
|
||||
};
|
||||
|
||||
asoc_pdm0: dfsdm-dai {
|
||||
compatible = "st,stm32h7-dfsdm-dai";
|
||||
#sound-dai-cells = <0>;
|
||||
@ -318,19 +395,34 @@ examples:
|
||||
};
|
||||
};
|
||||
|
||||
dfsdm_pdm1: filter@1 {
|
||||
// Example 2: Analog use case with generic binding
|
||||
dfsdm1: filter@1 {
|
||||
compatible = "st,stm32-dfsdm-adc";
|
||||
reg = <1>;
|
||||
interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmamux1 102 0x400 0x01>;
|
||||
dma-names = "rx";
|
||||
#io-channel-cells = <1>;
|
||||
st,adc-channels = <2 3>;
|
||||
st,adc-channel-names = "in2", "in3";
|
||||
st,adc-channel-types = "SPI_R", "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT_F", "CLKOUT_F";
|
||||
io-channels = <&sd_adc2 &sd_adc3>;
|
||||
st,filter-order = <1>;
|
||||
#io-channel-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
label = "in2";
|
||||
st,adc-channel-type = "SPI_F";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
st,adc-alt-channel;
|
||||
io-backends = <&sd_adc2>;
|
||||
};
|
||||
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
label = "in3";
|
||||
st,adc-channel-type = "SPI_R";
|
||||
st,adc-channel-clk-src = "CLKOUT";
|
||||
io-backends = <&sd_adc3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -37,6 +37,17 @@ description: |
|
||||
3 | batt_dischrg_i
|
||||
4 | ts_v
|
||||
|
||||
AXP717
|
||||
------
|
||||
0 | batt_v
|
||||
1 | ts_v
|
||||
2 | vbus_v
|
||||
3 | vsys_v
|
||||
4 | pmic_temp
|
||||
5 | batt_chrg_i
|
||||
6 | vmid_v
|
||||
7 | bkup_batt_v
|
||||
|
||||
AXP813
|
||||
------
|
||||
0 | pmic_temp
|
||||
@ -52,6 +63,7 @@ properties:
|
||||
oneOf:
|
||||
- const: x-powers,axp209-adc
|
||||
- const: x-powers,axp221-adc
|
||||
- const: x-powers,axp717-adc
|
||||
- const: x-powers,axp813-adc
|
||||
|
||||
- items:
|
||||
|
181
Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml
Normal file
181
Documentation/devicetree/bindings/iio/dac/adi,ltc2664.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
160
Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml
Normal file
160
Documentation/devicetree/bindings/iio/dac/adi,ltc2672.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
50
Documentation/devicetree/bindings/iio/dac/dac.yaml
Normal file
50
Documentation/devicetree/bindings/iio/dac/dac.yaml
Normal 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
|
@ -17,6 +17,7 @@ description: |
|
||||
applications.
|
||||
|
||||
https://www.analog.com/en/products/adf4377.html
|
||||
https://www.analog.com/en/products/adf4378.html
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@ -73,6 +74,15 @@ required:
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,adf4378
|
||||
then:
|
||||
properties:
|
||||
clk2-enable-gpios: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
@ -0,0 +1,55 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/humidity/sciosense,ens210.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ScioSense ENS210 temperature and humidity sensor
|
||||
|
||||
maintainers:
|
||||
- Joshua Felmeden <jfelmeden@thegoodpenguin.co.uk>
|
||||
|
||||
description: |
|
||||
Temperature and Humidity sensor.
|
||||
|
||||
Datasheet:
|
||||
https://www.sciosense.com/wp-content/uploads/2024/04/ENS21x-Datasheet.pdf
|
||||
https://www.sciosense.com/wp-content/uploads/2023/12/ENS210-Datasheet.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- sciosense,ens210a
|
||||
- sciosense,ens211
|
||||
- sciosense,ens212
|
||||
- sciosense,ens213a
|
||||
- sciosense,ens215
|
||||
- const: sciosense,ens210
|
||||
- const: sciosense,ens210
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
temperature-sensor@43 {
|
||||
compatible = "sciosense,ens210";
|
||||
reg = <0x43>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
@ -14,7 +14,9 @@ description:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: liteon,ltrf216a
|
||||
enum:
|
||||
- liteon,ltr308
|
||||
- liteon,ltrf216a
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
53
Documentation/devicetree/bindings/iio/light/rohm,bh1745.yaml
Normal file
53
Documentation/devicetree/bindings/iio/light/rohm,bh1745.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,23 +1,22 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bu27034.yaml#
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bu27034anuc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BU27034 ambient light sensor
|
||||
title: ROHM BU27034ANUC ambient light sensor
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
ROHM BU27034 is an ambient light sesnor with 3 channels and 3 photo diodes
|
||||
ROHM BU27034ANUC is an ambient light sensor with 2 channels and 2 photo diodes
|
||||
capable of detecting a very wide range of illuminance. Typical application
|
||||
is adjusting LCD and backlight power of TVs and mobile phones.
|
||||
https://fscdn.rohm.com/en/products/databook/datasheet/ic/sensor/light/bu27034nuc-e.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bu27034
|
||||
const: rohm,bu27034anuc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -37,7 +36,7 @@ examples:
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@38 {
|
||||
compatible = "rohm,bu27034";
|
||||
compatible = "rohm,bu27034anuc";
|
||||
reg = <0x38>;
|
||||
vdd-supply = <&vdd>;
|
||||
};
|
@ -18,10 +18,15 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- sensortek,stk3310
|
||||
- sensortek,stk3311
|
||||
- sensortek,stk3335
|
||||
oneOf:
|
||||
- enum:
|
||||
- sensortek,stk3310
|
||||
- sensortek,stk3311
|
||||
- sensortek,stk3335
|
||||
- items:
|
||||
- enum:
|
||||
- sensortek,stk3013
|
||||
- const: sensortek,stk3310
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -18,12 +18,15 @@ properties:
|
||||
- asahi-kasei,ak09911
|
||||
- asahi-kasei,ak09912
|
||||
- asahi-kasei,ak09916
|
||||
- items:
|
||||
# ak09918 is register compatible with ak09912.
|
||||
- const: asahi-kasei,ak09918
|
||||
- const: asahi-kasei,ak09912
|
||||
- enum:
|
||||
- ak8975
|
||||
- ak8963
|
||||
- ak09911
|
||||
- ak09912
|
||||
- ak09916
|
||||
deprecated: true
|
||||
|
||||
reg:
|
||||
|
@ -36,6 +36,9 @@ properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
mount-matrix:
|
||||
description: an optional 3x3 mounting rotation matrix.
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
|
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/pressure/sensirion,sdp500.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: sdp500/sdp510 pressure sensor with I2C bus interface
|
||||
|
||||
maintainers:
|
||||
- Petar Stoykov <petar.stoykov@prodrive-technologies.com>
|
||||
|
||||
description: |
|
||||
Pressure sensor from Sensirion with I2C bus interface.
|
||||
There is no software difference between sdp500 and sdp510.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: sensirion,sdp510
|
||||
- const: sensirion,sdp500
|
||||
- const: sensirion,sdp500
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pressure@40 {
|
||||
compatible = "sensirion,sdp500";
|
||||
reg = <0x40>;
|
||||
vdd-supply = <&foo>;
|
||||
};
|
||||
};
|
@ -0,0 +1,61 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/proximity/awinic,aw96103.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Awinic's AW96103 capacitive proximity sensor and similar
|
||||
|
||||
maintainers:
|
||||
- Wang Shuaijie <wangshuaijie@awinic.com>
|
||||
|
||||
description: |
|
||||
Awinic's AW96103/AW96105 proximity sensor.
|
||||
The specific absorption rate (SAR) is a metric that measures
|
||||
the degree of absorption of electromagnetic radiation emitted by
|
||||
wireless devices, such as mobile phones and tablets, by human tissue.
|
||||
In mobile phone applications, the proximity sensor is primarily
|
||||
used to detect the proximity of the human body to the phone. When the
|
||||
phone approaches the human body, it will actively reduce the transmit
|
||||
power of the antenna to keep the SAR within a safe range. Therefore,
|
||||
we also refer to the proximity sensor as a SAR sensor.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- awinic,aw96103
|
||||
- awinic,aw96105
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
Generated by the device to announce that a close/far
|
||||
proximity event has happened.
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- vcc-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
proximity@12 {
|
||||
compatible = "awinic,aw96103";
|
||||
reg = <0x12>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
|
||||
vcc-supply = <&pp1800_prox>;
|
||||
};
|
||||
};
|
@ -0,0 +1,93 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/proximity/tyhx,hx9023s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TYHX HX9023S capacitive proximity sensor
|
||||
|
||||
maintainers:
|
||||
- Yasin Lee <yasin.lee.x@gmail.com>
|
||||
|
||||
description: |
|
||||
TYHX HX9023S proximity sensor. Datasheet can be found here:
|
||||
http://www.tianyihexin.com/ueditor/php/upload/file/20240614/1718336303992081.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: tyhx,hx9023s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
description:
|
||||
Generated by device to announce preceding read request has finished
|
||||
and data is available or that a close/far proximity event has happened.
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-4]$":
|
||||
$ref: /schemas/iio/adc/adc.yaml
|
||||
type: object
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
minimum: 0
|
||||
maximum: 4
|
||||
description: The channel number.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
proximity@2a {
|
||||
compatible = "tyhx,hx9023s";
|
||||
reg = <0x2a>;
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
|
||||
vdd-supply = <&pp1800_prox>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
single-channel = <0>;
|
||||
};
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
single-channel = <1>;
|
||||
};
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
single-channel = <2>;
|
||||
};
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
diff-channels = <1 0>;
|
||||
};
|
||||
channel@4 {
|
||||
reg = <4>;
|
||||
diff-channels = <2 0>;
|
||||
};
|
||||
};
|
||||
};
|
@ -4,14 +4,14 @@
|
||||
$id: http://devicetree.org/schemas/interconnect/qcom,msm8939.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm MSM8939 Network-On-Chip interconnect
|
||||
title: Qualcomm MSM8937/MSM8939/MSM8976 Network-On-Chip interconnect
|
||||
|
||||
maintainers:
|
||||
- Konrad Dybcio <konradybcio@kernel.org>
|
||||
|
||||
description: |
|
||||
The Qualcomm MSM8939 interconnect providers support adjusting the
|
||||
bandwidth requirements between the various NoC fabrics.
|
||||
description:
|
||||
The Qualcomm MSM8937/MSM8939/MSM8976 interconnect providers support
|
||||
adjusting the bandwidth requirements between the various NoC fabrics.
|
||||
|
||||
allOf:
|
||||
- $ref: qcom,rpm-common.yaml#
|
||||
@ -19,9 +19,15 @@ allOf:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,msm8937-bimc
|
||||
- qcom,msm8937-pcnoc
|
||||
- qcom,msm8937-snoc
|
||||
- qcom,msm8939-bimc
|
||||
- qcom,msm8939-pcnoc
|
||||
- qcom,msm8939-snoc
|
||||
- qcom,msm8976-bimc
|
||||
- qcom,msm8976-pcnoc
|
||||
- qcom,msm8976-snoc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@ -39,7 +45,10 @@ patternProperties:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,msm8939-snoc-mm
|
||||
enum:
|
||||
- qcom,msm8937-snoc-mm
|
||||
- qcom,msm8939-snoc-mm
|
||||
- qcom,msm8976-snoc-mm
|
||||
|
||||
required:
|
||||
- compatible
|
||||
@ -60,12 +69,6 @@ examples:
|
||||
compatible = "qcom,msm8939-snoc";
|
||||
reg = <0x00580000 0x14000>;
|
||||
#interconnect-cells = <1>;
|
||||
};
|
||||
|
||||
bimc: interconnect@400000 {
|
||||
compatible = "qcom,msm8939-bimc";
|
||||
reg = <0x00400000 0x62000>;
|
||||
#interconnect-cells = <1>;
|
||||
|
||||
snoc_mm: interconnect-snoc {
|
||||
compatible = "qcom,msm8939-snoc-mm";
|
||||
|
@ -13,8 +13,7 @@ description: |
|
||||
The Qualcomm MSM8953 interconnect providers support adjusting the
|
||||
bandwidth requirements between the various NoC fabrics.
|
||||
|
||||
See also:
|
||||
- dt-bindings/interconnect/qcom,msm8953.h
|
||||
See also: include/dt-bindings/interconnect/qcom,msm8953.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -26,6 +26,7 @@ properties:
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,qcm2290-cpu-bwmon
|
||||
- qcom,sa8775p-cpu-bwmon
|
||||
- qcom,sc7180-cpu-bwmon
|
||||
- qcom,sc7280-cpu-bwmon
|
||||
- qcom,sc8280xp-cpu-bwmon
|
||||
@ -39,6 +40,7 @@ properties:
|
||||
- const: qcom,sdm845-bwmon # BWMON v4, unified register space
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sa8775p-llcc-bwmon
|
||||
- qcom,sc7180-llcc-bwmon
|
||||
- qcom,sc8280xp-llcc-bwmon
|
||||
- qcom,sm6350-cpu-bwmon
|
||||
|
@ -71,7 +71,7 @@ properties:
|
||||
- qcom,sdx65-system-noc
|
||||
- qcom,sm8150-aggre1-noc
|
||||
- qcom,sm8150-aggre2-noc
|
||||
- qcom,sm8150-camnoc-noc
|
||||
- qcom,sm8150-camnoc-virt
|
||||
- qcom,sm8150-compute-noc
|
||||
- qcom,sm8150-config-noc
|
||||
- qcom,sm8150-dc-noc
|
||||
@ -113,6 +113,9 @@ allOf:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,sc8180x-camnoc-virt
|
||||
- qcom,sc8180x-mc-virt
|
||||
- qcom,sc8180x-qup-virt
|
||||
- qcom,sdx65-mc-virt
|
||||
- qcom,sm8250-qup-virt
|
||||
then:
|
||||
|
@ -26,6 +26,7 @@ properties:
|
||||
- mdsp
|
||||
- sdsp
|
||||
- cdsp
|
||||
- cdsp1
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
@ -81,7 +82,7 @@ patternProperties:
|
||||
|
||||
iommus:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
maxItems: 10
|
||||
|
||||
qcom,nsessions:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
@ -29,6 +29,12 @@ properties:
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
bootloader-backdoor-gpios:
|
||||
maxItems: 1
|
||||
description: |
|
||||
gpios to enable bootloader backdoor in cc1352p7 bootloader to allow
|
||||
flashing new firmware.
|
||||
|
||||
vdds-supply: true
|
||||
|
||||
required:
|
||||
@ -46,6 +52,7 @@ examples:
|
||||
clocks = <&sclk_hf 0>, <&sclk_lf 25>;
|
||||
clock-names = "sclk_hf", "sclk_lf";
|
||||
reset-gpios = <&pio 35 GPIO_ACTIVE_LOW>;
|
||||
bootloader-backdoor-gpios = <&pio 36 GPIO_ACTIVE_LOW>;
|
||||
vdds-supply = <&vdds>;
|
||||
};
|
||||
};
|
||||
|
@ -15,6 +15,7 @@ description: |
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
- $ref: nvmem-deprecated-cells.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -14,7 +14,7 @@ maintainers:
|
||||
description: |
|
||||
This binding represents the on-chip eFuse OTP controller found on
|
||||
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL,
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93 SoCs.
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93/5 SoCs.
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
@ -36,6 +36,7 @@ properties:
|
||||
- fsl,imx8mq-ocotp
|
||||
- fsl,imx8mm-ocotp
|
||||
- fsl,imx93-ocotp
|
||||
- fsl,imx95-ocotp
|
||||
- const: syscon
|
||||
- items:
|
||||
- enum:
|
||||
|
@ -21,6 +21,7 @@ oneOf:
|
||||
- $ref: fixed-layout.yaml
|
||||
- $ref: kontron,sl28-vpd.yaml
|
||||
- $ref: onie,tlv-layout.yaml
|
||||
- $ref: u-boot,env.yaml
|
||||
|
||||
properties:
|
||||
compatible: true
|
||||
|
@ -1,10 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/nvmem/u-boot,env.yaml#
|
||||
$id: http://devicetree.org/schemas/nvmem/layouts/u-boot,env.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: U-Boot environment variables
|
||||
title: U-Boot environment variables layout
|
||||
|
||||
description: |
|
||||
U-Boot uses environment variables to store device parameters and
|
||||
@ -21,9 +21,6 @@ description: |
|
||||
This binding allows marking storage device (as containing env data) and
|
||||
specifying used format.
|
||||
|
||||
Right now only flash partition case is covered but it may be extended to e.g.
|
||||
UBI volumes in the future.
|
||||
|
||||
Variables can be defined as NVMEM device subnodes.
|
||||
|
||||
maintainers:
|
||||
@ -42,6 +39,7 @@ properties:
|
||||
const: brcm,env
|
||||
|
||||
reg:
|
||||
description: Partition offset and size for env on top of MTD
|
||||
maxItems: 1
|
||||
|
||||
bootcmd:
|
||||
@ -58,6 +56,17 @@ properties:
|
||||
description: The first argument is a MAC address offset.
|
||||
const: 1
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
$nodename:
|
||||
not:
|
||||
contains:
|
||||
pattern: "^partition@[0-9a-f]+$"
|
||||
then:
|
||||
properties:
|
||||
reg: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
@ -101,3 +110,23 @@ examples:
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
partition@0 {
|
||||
reg = <0x0 0x100000>;
|
||||
label = "ubi";
|
||||
compatible = "linux,ubi";
|
||||
|
||||
volumes {
|
||||
ubi-volume-u-boot-env {
|
||||
volname = "env";
|
||||
|
||||
nvmem-layout {
|
||||
compatible = "u-boot,env";
|
||||
|
||||
ethaddr {
|
||||
#nvmem-cell-cells = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -17,6 +17,7 @@ maintainers:
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
- $ref: nvmem-deprecated-cells.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@ -32,6 +33,8 @@ properties:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: layouts/fixed-cell.yaml
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
st,non-secure-otp:
|
||||
|
@ -1541,6 +1541,8 @@ patternProperties:
|
||||
description: Turing Machines, Inc.
|
||||
"^tyan,.*":
|
||||
description: Tyan Computer Corporation
|
||||
"^tyhx,.*":
|
||||
description: NanjingTianyihexin Electronics Ltd.
|
||||
"^u-blox,.*":
|
||||
description: u-blox
|
||||
"^u-boot,.*":
|
||||
|
131
Documentation/iio/ad4000.rst
Normal file
131
Documentation/iio/ad4000.rst
Normal 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 |
|
||||
+-------------+
|
167
Documentation/iio/ad4695.rst
Normal file
167
Documentation/iio/ad4695.rst
Normal 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.
|
130
Documentation/iio/ad7380.rst
Normal file
130
Documentation/iio/ad7380.rst
Normal 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.
|
233
Documentation/iio/adxl380.rst
Normal file
233
Documentation/iio/adxl380.rst
Normal 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.
|
@ -18,8 +18,12 @@ Industrial I/O Kernel Drivers
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ad4000
|
||||
ad4695
|
||||
ad7380
|
||||
ad7944
|
||||
adis16475
|
||||
adis16480
|
||||
adxl380
|
||||
bno055
|
||||
ep93xx_adc
|
||||
|
69
MAINTAINERS
69
MAINTAINERS
@ -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
|
||||
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -202,29 +202,24 @@ static void cache_of_set_props(struct cacheinfo *this_leaf,
|
||||
|
||||
static int cache_setup_of_node(unsigned int cpu)
|
||||
{
|
||||
struct device_node *np, *prev;
|
||||
struct cacheinfo *this_leaf;
|
||||
unsigned int index = 0;
|
||||
|
||||
np = of_cpu_device_node_get(cpu);
|
||||
struct device_node *np __free(device_node) = of_cpu_device_node_get(cpu);
|
||||
if (!np) {
|
||||
pr_err("Failed to find cpu%d device node\n", cpu);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!of_check_cache_nodes(np)) {
|
||||
of_node_put(np);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
prev = np;
|
||||
|
||||
while (index < cache_leaves(cpu)) {
|
||||
this_leaf = per_cpu_cacheinfo_idx(cpu, index);
|
||||
if (this_leaf->level != 1) {
|
||||
struct device_node *prev __free(device_node) = np;
|
||||
np = of_find_next_cache_node(np);
|
||||
of_node_put(prev);
|
||||
prev = np;
|
||||
if (!np)
|
||||
break;
|
||||
}
|
||||
@ -233,8 +228,6 @@ static int cache_setup_of_node(unsigned int cpu)
|
||||
index++;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
if (index != cache_leaves(cpu)) /* not all OF nodes populated */
|
||||
return -ENOENT;
|
||||
|
||||
@ -243,17 +236,14 @@ static int cache_setup_of_node(unsigned int cpu)
|
||||
|
||||
static bool of_check_cache_nodes(struct device_node *np)
|
||||
{
|
||||
struct device_node *next;
|
||||
|
||||
if (of_property_present(np, "cache-size") ||
|
||||
of_property_present(np, "i-cache-size") ||
|
||||
of_property_present(np, "d-cache-size") ||
|
||||
of_property_present(np, "cache-unified"))
|
||||
return true;
|
||||
|
||||
next = of_find_next_cache_node(np);
|
||||
struct device_node *next __free(device_node) = of_find_next_cache_node(np);
|
||||
if (next) {
|
||||
of_node_put(next);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -287,12 +277,10 @@ static int of_count_cache_leaves(struct device_node *np)
|
||||
int init_of_cache_level(unsigned int cpu)
|
||||
{
|
||||
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
||||
struct device_node *np = of_cpu_device_node_get(cpu);
|
||||
struct device_node *prev = NULL;
|
||||
struct device_node *np __free(device_node) = of_cpu_device_node_get(cpu);
|
||||
unsigned int levels = 0, leaves, level;
|
||||
|
||||
if (!of_check_cache_nodes(np)) {
|
||||
of_node_put(np);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@ -300,30 +288,27 @@ int init_of_cache_level(unsigned int cpu)
|
||||
if (leaves > 0)
|
||||
levels = 1;
|
||||
|
||||
prev = np;
|
||||
while ((np = of_find_next_cache_node(np))) {
|
||||
of_node_put(prev);
|
||||
prev = np;
|
||||
while (1) {
|
||||
struct device_node *prev __free(device_node) = np;
|
||||
np = of_find_next_cache_node(np);
|
||||
if (!np)
|
||||
break;
|
||||
|
||||
if (!of_device_is_compatible(np, "cache"))
|
||||
goto err_out;
|
||||
return -EINVAL;
|
||||
if (of_property_read_u32(np, "cache-level", &level))
|
||||
goto err_out;
|
||||
return -EINVAL;
|
||||
if (level <= levels)
|
||||
goto err_out;
|
||||
return -EINVAL;
|
||||
|
||||
leaves += of_count_cache_leaves(np);
|
||||
levels = level;
|
||||
}
|
||||
|
||||
of_node_put(np);
|
||||
this_cpu_ci->num_levels = levels;
|
||||
this_cpu_ci->num_leaves = leaves;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
of_node_put(np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -1464,7 +1464,7 @@ static int mhi_match(struct device *dev, const struct device_driver *drv)
|
||||
return 0;
|
||||
};
|
||||
|
||||
struct bus_type mhi_bus_type = {
|
||||
const struct bus_type mhi_bus_type = {
|
||||
.name = "mhi",
|
||||
.dev_name = "mhi",
|
||||
.match = mhi_match,
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
extern struct bus_type mhi_bus_type;
|
||||
extern const struct bus_type mhi_bus_type;
|
||||
|
||||
/* Host request register */
|
||||
#define MHI_SOC_RESET_REQ_OFFSET 0xb0
|
||||
|
@ -26,6 +26,7 @@
|
||||
/* PCI VID definitions */
|
||||
#define PCI_VENDOR_ID_THALES 0x1269
|
||||
#define PCI_VENDOR_ID_QUECTEL 0x1eac
|
||||
#define PCI_VENDOR_ID_NETPRISMA 0x203e
|
||||
|
||||
#define MHI_EDL_DB 91
|
||||
#define MHI_EDL_COOKIE 0xEDEDEDED
|
||||
@ -433,8 +434,8 @@ static const struct mhi_controller_config modem_foxconn_sdx72_config = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = {
|
||||
.name = "foxconn-sdx55",
|
||||
.fw = "qcom/sdx55m/sbl1.mbn",
|
||||
.edl = "qcom/sdx55m/edl.mbn",
|
||||
.edl = "qcom/sdx55m/foxconn/prog_firehose_sdx55.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@ -444,8 +445,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_sdx55_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w175_info = {
|
||||
.name = "foxconn-t99w175",
|
||||
.fw = "qcom/sdx55m/sbl1.mbn",
|
||||
.edl = "qcom/sdx55m/edl.mbn",
|
||||
.edl = "qcom/sdx55m/foxconn/prog_firehose_sdx55.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@ -455,8 +456,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w175_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_dw5930e_info = {
|
||||
.name = "foxconn-dw5930e",
|
||||
.fw = "qcom/sdx55m/sbl1.mbn",
|
||||
.edl = "qcom/sdx55m/edl.mbn",
|
||||
.edl = "qcom/sdx55m/foxconn/prog_firehose_sdx55.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@ -466,6 +467,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_dw5930e_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w368_info = {
|
||||
.name = "foxconn-t99w368",
|
||||
.edl = "qcom/sdx65m/foxconn/prog_firehose_lite.elf",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@ -475,6 +478,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w368_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w373_info = {
|
||||
.name = "foxconn-t99w373",
|
||||
.edl = "qcom/sdx65m/foxconn/prog_firehose_lite.elf",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@ -484,6 +489,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w373_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w510_info = {
|
||||
.name = "foxconn-t99w510",
|
||||
.edl = "qcom/sdx24m/foxconn/prog_firehose_sdx24.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@ -493,6 +500,8 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w510_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_dw5932e_info = {
|
||||
.name = "foxconn-dw5932e",
|
||||
.edl = "qcom/sdx65m/foxconn/prog_firehose_lite.elf",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx55_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
@ -502,7 +511,7 @@ static const struct mhi_pci_dev_info mhi_foxconn_dw5932e_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w515_info = {
|
||||
.name = "foxconn-t99w515",
|
||||
.edl = "fox/sdx72m/edl.mbn",
|
||||
.edl = "qcom/sdx72m/foxconn/edl.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx72_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
@ -513,7 +522,7 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w515_info = {
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_dw5934e_info = {
|
||||
.name = "foxconn-dw5934e",
|
||||
.edl = "fox/sdx72m/edl.mbn",
|
||||
.edl = "qcom/sdx72m/foxconn/edl.mbn",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx72_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
@ -680,6 +689,35 @@ static const struct mhi_pci_dev_info mhi_telit_fn990_info = {
|
||||
.mru_default = 32768,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_telit_fe990a_info = {
|
||||
.name = "telit-fe990a",
|
||||
.config = &modem_telit_fn990_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.sideband_wake = false,
|
||||
.mru_default = 32768,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = {
|
||||
.name = "netprisma-lcur57",
|
||||
.edl = "qcom/prog_firehose_sdx24.mbn",
|
||||
.config = &modem_quectel_em1xx_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.mru_default = 32768,
|
||||
.sideband_wake = true,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_netprisma_fcun69_info = {
|
||||
.name = "netprisma-fcun69",
|
||||
.edl = "qcom/prog_firehose_sdx6x.elf",
|
||||
.config = &modem_quectel_em1xx_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.mru_default = 32768,
|
||||
.sideband_wake = true,
|
||||
};
|
||||
|
||||
/* Keep the list sorted based on the PID. New VID should be added as the last entry */
|
||||
static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),
|
||||
@ -697,9 +735,9 @@ static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
/* Telit FN990 */
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2010),
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fn990_info },
|
||||
/* Telit FE990 */
|
||||
/* Telit FE990A */
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2015),
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fn990_info },
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fe990a_info },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0308),
|
||||
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx65_info },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0309),
|
||||
@ -778,6 +816,12 @@ static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
/* T99W175 (sdx55), HP variant */
|
||||
{ PCI_DEVICE(0x03f0, 0x0a6c),
|
||||
.driver_data = (kernel_ulong_t) &mhi_foxconn_t99w175_info },
|
||||
/* NETPRISMA LCUR57 (SDX24) */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NETPRISMA, 0x1000),
|
||||
.driver_data = (kernel_ulong_t) &mhi_netprisma_lcur57_info },
|
||||
/* NETPRISMA FCUN69 (SDX6X) */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NETPRISMA, 0x1001),
|
||||
.driver_data = (kernel_ulong_t) &mhi_netprisma_fcun69_info },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
|
||||
|
@ -27,10 +27,6 @@
|
||||
#include "bitfield.h"
|
||||
#include "mcdi.h"
|
||||
|
||||
struct cdx_mcdi_copy_buffer {
|
||||
struct cdx_dword buffer[DIV_ROUND_UP(MCDI_CTL_SDU_LEN_MAX, 4)];
|
||||
};
|
||||
|
||||
static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd);
|
||||
static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx);
|
||||
static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx,
|
||||
|
@ -808,7 +808,7 @@ int hpet_alloc(struct hpet_data *hdp)
|
||||
struct hpets *hpetp;
|
||||
struct hpet __iomem *hpet;
|
||||
static struct hpets *last;
|
||||
unsigned long period;
|
||||
u32 period;
|
||||
unsigned long long temp;
|
||||
u32 remainder;
|
||||
|
||||
@ -865,11 +865,11 @@ int hpet_alloc(struct hpet_data *hdp)
|
||||
do_div(temp, period);
|
||||
hpetp->hp_tick_freq = temp; /* ticks per second */
|
||||
|
||||
printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
|
||||
printk(KERN_INFO "hpet%u: at MMIO 0x%lx, IRQ%s",
|
||||
hpetp->hp_which, hdp->hd_phys_address,
|
||||
hpetp->hp_ntimer > 1 ? "s" : "");
|
||||
for (i = 0; i < hpetp->hp_ntimer; i++)
|
||||
printk(KERN_CONT "%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
|
||||
printk(KERN_CONT "%s %u", i > 0 ? "," : "", hdp->hd_irq[i]);
|
||||
printk(KERN_CONT "\n");
|
||||
|
||||
temp = hpetp->hp_tick_freq;
|
||||
|
@ -79,6 +79,15 @@
|
||||
|
||||
#include "ni_stc.h"
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext = {
|
||||
4, {
|
||||
BIP_RANGE(10),
|
||||
UNI_RANGE(10),
|
||||
RANGE_ext(-1, 1),
|
||||
RANGE_ext(0, 1)
|
||||
}
|
||||
};
|
||||
|
||||
/* AT specific setup */
|
||||
static const struct ni_board_struct ni_boards[] = {
|
||||
{
|
||||
|
@ -166,15 +166,6 @@ static const struct comedi_lrange range_ni_M_ai_628x = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext = {
|
||||
4, {
|
||||
BIP_RANGE(10),
|
||||
UNI_RANGE(10),
|
||||
RANGE_ext(-1, 1),
|
||||
RANGE_ext(0, 1)
|
||||
}
|
||||
};
|
||||
|
||||
static const struct comedi_lrange *const ni_range_lkup[] = {
|
||||
[ai_gain_16] = &range_ni_E_ai,
|
||||
[ai_gain_8] = &range_ni_E_ai_limited,
|
||||
|
@ -102,6 +102,15 @@
|
||||
|
||||
#define PCIDMA
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext = {
|
||||
4, {
|
||||
BIP_RANGE(10),
|
||||
UNI_RANGE(10),
|
||||
RANGE_ext(-1, 1),
|
||||
RANGE_ext(0, 1)
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* These are not all the possible ao ranges for 628x boards.
|
||||
* They can do OFFSET +- REFERENCE where OFFSET can be
|
||||
|
@ -140,6 +140,11 @@ int main(void)
|
||||
{
|
||||
FILE *fp = fopen("ni_values.py", "w");
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Could not open file!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* write route register values */
|
||||
fprintf(fp, "ni_route_values = {\n");
|
||||
for (int i = 0; ni_all_route_values[i]; ++i)
|
||||
|
@ -1137,6 +1137,4 @@ struct ni_private {
|
||||
u8 rgout0_usage;
|
||||
};
|
||||
|
||||
static const struct comedi_lrange range_ni_E_ao_ext;
|
||||
|
||||
#endif /* _COMEDI_NI_STC_H */
|
||||
|
@ -75,6 +75,17 @@ config EXTCON_INTEL_MRFLD
|
||||
Say Y here to enable extcon support for charger detection / control
|
||||
on the Intel Merrifield Basin Cove PMIC.
|
||||
|
||||
config EXTCON_LC824206XA
|
||||
tristate "LC824206XA extcon Support"
|
||||
depends on I2C
|
||||
depends on POWER_SUPPLY
|
||||
help
|
||||
Say Y here to enable support for the ON Semiconductor LC824206XA
|
||||
microUSB switch and accessory detector chip. The LC824206XA is a USB
|
||||
port accessory detector and switch. The LC824206XA is fully controlled
|
||||
using I2C and enables USB data, stereo and mono audio, video,
|
||||
microphone and UART data to use a common connector port.
|
||||
|
||||
config EXTCON_MAX14577
|
||||
tristate "Maxim MAX14577/77836 EXTCON Support"
|
||||
depends on MFD_MAX14577
|
||||
|
@ -12,6 +12,7 @@ obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o
|
||||
obj-$(CONFIG_EXTCON_INTEL_INT3496) += extcon-intel-int3496.o
|
||||
obj-$(CONFIG_EXTCON_INTEL_CHT_WC) += extcon-intel-cht-wc.o
|
||||
obj-$(CONFIG_EXTCON_INTEL_MRFLD) += extcon-intel-mrfld.o
|
||||
obj-$(CONFIG_EXTCON_LC824206XA) += extcon-lc824206xa.o
|
||||
obj-$(CONFIG_EXTCON_MAX14577) += extcon-max14577.o
|
||||
obj-$(CONFIG_EXTCON_MAX3355) += extcon-max3355.o
|
||||
obj-$(CONFIG_EXTCON_MAX77693) += extcon-max77693.o
|
||||
|
495
drivers/extcon/extcon-lc824206xa.c
Normal file
495
drivers/extcon/extcon-lc824206xa.c
Normal 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");
|
@ -301,16 +301,17 @@ static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id)
|
||||
|
||||
static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv)
|
||||
{
|
||||
int timeout, ret = 0;
|
||||
int ret = 0;
|
||||
long time_left;
|
||||
|
||||
socfpga_fpga_disable_irqs(priv);
|
||||
init_completion(&priv->status_complete);
|
||||
socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE);
|
||||
|
||||
timeout = wait_for_completion_interruptible_timeout(
|
||||
time_left = wait_for_completion_interruptible_timeout(
|
||||
&priv->status_complete,
|
||||
msecs_to_jiffies(10));
|
||||
if (timeout == 0)
|
||||
if (time_left == 0)
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
socfpga_fpga_disable_irqs(priv);
|
||||
|
@ -23,6 +23,13 @@ struct bridge_ctx {
|
||||
struct bridge_stats stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper to avoid a cast warning when passing the action function directly
|
||||
* to kunit_add_action().
|
||||
*/
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper, fpga_bridge_unregister,
|
||||
struct fpga_bridge *);
|
||||
|
||||
static int op_enable_set(struct fpga_bridge *bridge, bool enable)
|
||||
{
|
||||
struct bridge_stats *stats = bridge->priv;
|
||||
@ -50,6 +57,7 @@ static const struct fpga_bridge_ops fake_bridge_ops = {
|
||||
static struct bridge_ctx *register_test_bridge(struct kunit *test, const char *dev_name)
|
||||
{
|
||||
struct bridge_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
|
||||
@ -61,13 +69,10 @@ static struct bridge_ctx *register_test_bridge(struct kunit *test, const char *d
|
||||
&ctx->stats);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->bridge));
|
||||
|
||||
return ctx;
|
||||
}
|
||||
ret = kunit_add_action_or_reset(test, fpga_bridge_unregister_wrapper, ctx->bridge);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
static void unregister_test_bridge(struct kunit *test, struct bridge_ctx *ctx)
|
||||
{
|
||||
fpga_bridge_unregister(ctx->bridge);
|
||||
kunit_device_unregister(test, ctx->dev);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void fpga_bridge_test_get(struct kunit *test)
|
||||
@ -141,8 +146,6 @@ static void fpga_bridge_test_get_put_list(struct kunit *test)
|
||||
fpga_bridges_put(&bridge_list);
|
||||
|
||||
KUNIT_EXPECT_TRUE(test, list_empty(&bridge_list));
|
||||
|
||||
unregister_test_bridge(test, ctx_1);
|
||||
}
|
||||
|
||||
static int fpga_bridge_test_init(struct kunit *test)
|
||||
@ -152,11 +155,6 @@ static int fpga_bridge_test_init(struct kunit *test)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fpga_bridge_test_exit(struct kunit *test)
|
||||
{
|
||||
unregister_test_bridge(test, test->priv);
|
||||
}
|
||||
|
||||
static struct kunit_case fpga_bridge_test_cases[] = {
|
||||
KUNIT_CASE(fpga_bridge_test_get),
|
||||
KUNIT_CASE(fpga_bridge_test_toggle),
|
||||
@ -167,7 +165,6 @@ static struct kunit_case fpga_bridge_test_cases[] = {
|
||||
static struct kunit_suite fpga_bridge_suite = {
|
||||
.name = "fpga_bridge",
|
||||
.init = fpga_bridge_test_init,
|
||||
.exit = fpga_bridge_test_exit,
|
||||
.test_cases = fpga_bridge_test_cases,
|
||||
};
|
||||
|
||||
|
@ -44,6 +44,16 @@ struct mgr_ctx {
|
||||
struct mgr_stats stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrappers to avoid cast warnings when passing action functions directly
|
||||
* to kunit_add_action().
|
||||
*/
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(sg_free_table_wrapper, sg_free_table,
|
||||
struct sg_table *);
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper, fpga_image_info_free,
|
||||
struct fpga_image_info *);
|
||||
|
||||
/**
|
||||
* init_test_buffer() - Allocate and initialize a test image in a buffer.
|
||||
* @test: KUnit test context object.
|
||||
@ -257,6 +267,9 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test)
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE);
|
||||
|
||||
ret = kunit_add_action_or_reset(test, sg_free_table_wrapper, sgt);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ctx->img_info->sgt = sgt;
|
||||
|
||||
ret = fpga_mgr_load(ctx->mgr, ctx->img_info);
|
||||
@ -273,13 +286,12 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test)
|
||||
KUNIT_EXPECT_EQ(test, ctx->stats.op_write_init_seq, ctx->stats.op_parse_header_seq + 1);
|
||||
KUNIT_EXPECT_EQ(test, ctx->stats.op_write_sg_seq, ctx->stats.op_parse_header_seq + 2);
|
||||
KUNIT_EXPECT_EQ(test, ctx->stats.op_write_complete_seq, ctx->stats.op_parse_header_seq + 3);
|
||||
|
||||
sg_free_table(ctx->img_info->sgt);
|
||||
}
|
||||
|
||||
static int fpga_mgr_test_init(struct kunit *test)
|
||||
{
|
||||
struct mgr_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
|
||||
@ -294,19 +306,14 @@ static int fpga_mgr_test_init(struct kunit *test)
|
||||
ctx->img_info = fpga_image_info_alloc(ctx->dev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->img_info);
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_image_info_free_wrapper, ctx->img_info);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
test->priv = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fpga_mgr_test_exit(struct kunit *test)
|
||||
{
|
||||
struct mgr_ctx *ctx = test->priv;
|
||||
|
||||
fpga_image_info_free(ctx->img_info);
|
||||
kunit_device_unregister(test, ctx->dev);
|
||||
}
|
||||
|
||||
static struct kunit_case fpga_mgr_test_cases[] = {
|
||||
KUNIT_CASE(fpga_mgr_test_get),
|
||||
KUNIT_CASE(fpga_mgr_test_lock),
|
||||
@ -318,7 +325,6 @@ static struct kunit_case fpga_mgr_test_cases[] = {
|
||||
static struct kunit_suite fpga_mgr_suite = {
|
||||
.name = "fpga_mgr",
|
||||
.init = fpga_mgr_test_init,
|
||||
.exit = fpga_mgr_test_exit,
|
||||
.test_cases = fpga_mgr_test_cases,
|
||||
};
|
||||
|
||||
|
@ -35,6 +35,19 @@ struct test_ctx {
|
||||
struct mgr_stats mgr_stats;
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrappers to avoid cast warnings when passing action functions directly
|
||||
* to kunit_add_action().
|
||||
*/
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_image_info_free_wrapper, fpga_image_info_free,
|
||||
struct fpga_image_info *);
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_bridge_unregister_wrapper, fpga_bridge_unregister,
|
||||
struct fpga_bridge *);
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(fpga_region_unregister_wrapper, fpga_region_unregister,
|
||||
struct fpga_region *);
|
||||
|
||||
static int op_write(struct fpga_manager *mgr, const char *buf, size_t count)
|
||||
{
|
||||
struct mgr_stats *stats = mgr->priv;
|
||||
@ -111,6 +124,9 @@ static void fpga_region_test_program_fpga(struct kunit *test)
|
||||
img_info = fpga_image_info_alloc(ctx->mgr_dev);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, img_info);
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_image_info_free_wrapper, img_info);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
img_info->buf = img_buf;
|
||||
img_info->count = sizeof(img_buf);
|
||||
|
||||
@ -130,8 +146,6 @@ static void fpga_region_test_program_fpga(struct kunit *test)
|
||||
KUNIT_EXPECT_EQ(test, 2, ctx->bridge_stats.cycles_count);
|
||||
|
||||
fpga_bridges_put(&ctx->region->bridge_list);
|
||||
|
||||
fpga_image_info_free(img_info);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -144,6 +158,7 @@ static int fpga_region_test_init(struct kunit *test)
|
||||
{
|
||||
struct test_ctx *ctx;
|
||||
struct fpga_region_info region_info = { 0 };
|
||||
int ret;
|
||||
|
||||
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
|
||||
@ -164,6 +179,9 @@ static int fpga_region_test_init(struct kunit *test)
|
||||
|
||||
ctx->bridge_stats.enable = true;
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_bridge_unregister_wrapper, ctx->bridge);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
ctx->region_dev = kunit_device_register(test, "fpga-region-test-dev");
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->region_dev);
|
||||
|
||||
@ -174,24 +192,14 @@ static int fpga_region_test_init(struct kunit *test)
|
||||
ctx->region = fpga_region_register_full(ctx->region_dev, ®ion_info);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR_OR_NULL(ctx->region));
|
||||
|
||||
ret = kunit_add_action_or_reset(test, fpga_region_unregister_wrapper, ctx->region);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
|
||||
test->priv = ctx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fpga_region_test_exit(struct kunit *test)
|
||||
{
|
||||
struct test_ctx *ctx = test->priv;
|
||||
|
||||
fpga_region_unregister(ctx->region);
|
||||
kunit_device_unregister(test, ctx->region_dev);
|
||||
|
||||
fpga_bridge_unregister(ctx->bridge);
|
||||
kunit_device_unregister(test, ctx->bridge_dev);
|
||||
|
||||
kunit_device_unregister(test, ctx->mgr_dev);
|
||||
}
|
||||
|
||||
static struct kunit_case fpga_region_test_cases[] = {
|
||||
KUNIT_CASE(fpga_region_test_class_find),
|
||||
KUNIT_CASE(fpga_region_test_program_fpga),
|
||||
@ -199,9 +207,8 @@ static struct kunit_case fpga_region_test_cases[] = {
|
||||
};
|
||||
|
||||
static struct kunit_suite fpga_region_suite = {
|
||||
.name = "fpga_mgr",
|
||||
.name = "fpga_region",
|
||||
.init = fpga_region_test_init,
|
||||
.exit = fpga_region_test_exit,
|
||||
.test_cases = fpga_region_test_cases,
|
||||
};
|
||||
|
||||
|
@ -387,7 +387,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
|
||||
const char *why;
|
||||
int err;
|
||||
u32 intr_status;
|
||||
unsigned long timeout;
|
||||
unsigned long time_left;
|
||||
unsigned long flags;
|
||||
struct scatterlist *sg;
|
||||
int i;
|
||||
@ -427,8 +427,8 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
|
||||
zynq_step_dma(priv);
|
||||
spin_unlock_irqrestore(&priv->dma_lock, flags);
|
||||
|
||||
timeout = wait_for_completion_timeout(&priv->dma_done,
|
||||
msecs_to_jiffies(DMA_TIMEOUT_MS));
|
||||
time_left = wait_for_completion_timeout(&priv->dma_done,
|
||||
msecs_to_jiffies(DMA_TIMEOUT_MS));
|
||||
|
||||
spin_lock_irqsave(&priv->dma_lock, flags);
|
||||
zynq_fpga_set_irq(priv, 0);
|
||||
@ -452,7 +452,7 @@ static int zynq_fpga_ops_write(struct fpga_manager *mgr, struct sg_table *sgt)
|
||||
|
||||
if (priv->cur_sg ||
|
||||
!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
|
||||
if (timeout == 0)
|
||||
if (time_left == 0)
|
||||
why = "DMA timed out";
|
||||
else
|
||||
why = "DMA did not complete";
|
||||
|
@ -21,6 +21,8 @@ config GREYBUS_BEAGLEPLAY
|
||||
tristate "Greybus BeaglePlay driver"
|
||||
depends on SERIAL_DEV_BUS
|
||||
select CRC_CCITT
|
||||
select FW_LOADER
|
||||
select FW_UPLOAD
|
||||
help
|
||||
Select this option if you have a BeaglePlay where CC1352
|
||||
co-processor acts as Greybus SVC.
|
||||
|
@ -6,21 +6,19 @@
|
||||
* Copyright (c) 2023 BeagleBoard.org Foundation
|
||||
*/
|
||||
|
||||
#include <linux/gfp.h>
|
||||
#include <asm-generic/unaligned.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/greybus.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/serdev.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/tty_driver.h>
|
||||
#include <linux/greybus/hd.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/crc-ccitt.h>
|
||||
#include <linux/circ_buf.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define CC1352_FIRMWARE_SIZE (704 * 1024)
|
||||
#define CC1352_BOOTLOADER_TIMEOUT 2000
|
||||
#define CC1352_BOOTLOADER_ACK 0xcc
|
||||
#define CC1352_BOOTLOADER_NACK 0x33
|
||||
|
||||
#define RX_HDLC_PAYLOAD 256
|
||||
#define CRC_LEN 2
|
||||
@ -57,6 +55,17 @@
|
||||
* @rx_buffer_len: length of receive buffer filled.
|
||||
* @rx_buffer: hdlc frame receive buffer
|
||||
* @rx_in_esc: hdlc rx flag to indicate ESC frame
|
||||
*
|
||||
* @fwl: underlying firmware upload device
|
||||
* @bootloader_backdoor_gpio: cc1352p7 boot gpio
|
||||
* @rst_gpio: cc1352p7 reset gpio
|
||||
* @flashing_mode: flag to indicate that flashing is currently in progress
|
||||
* @fwl_ack_com: completion to signal an Ack/Nack
|
||||
* @fwl_ack: Ack/Nack byte received
|
||||
* @fwl_cmd_response_com: completion to signal a bootloader command response
|
||||
* @fwl_cmd_response: bootloader command response data
|
||||
* @fwl_crc32: crc32 of firmware to flash
|
||||
* @fwl_reset_addr: flag to indicate if we need to send COMMAND_DOWNLOAD again
|
||||
*/
|
||||
struct gb_beagleplay {
|
||||
struct serdev_device *sd;
|
||||
@ -72,6 +81,17 @@ struct gb_beagleplay {
|
||||
u16 rx_buffer_len;
|
||||
bool rx_in_esc;
|
||||
u8 rx_buffer[MAX_RX_HDLC];
|
||||
|
||||
struct fw_upload *fwl;
|
||||
struct gpio_desc *bootloader_backdoor_gpio;
|
||||
struct gpio_desc *rst_gpio;
|
||||
bool flashing_mode;
|
||||
struct completion fwl_ack_com;
|
||||
u8 fwl_ack;
|
||||
struct completion fwl_cmd_response_com;
|
||||
u32 fwl_cmd_response;
|
||||
u32 fwl_crc32;
|
||||
bool fwl_reset_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -100,6 +120,87 @@ struct hdlc_greybus_frame {
|
||||
u8 payload[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum cc1352_bootloader_cmd: CC1352 Bootloader Commands
|
||||
*
|
||||
* @COMMAND_DOWNLOAD: Prepares flash programming
|
||||
* @COMMAND_GET_STATUS: Returns the status of the last command that was issued
|
||||
* @COMMAND_SEND_DATA: Transfers data and programs flash
|
||||
* @COMMAND_RESET: Performs a system reset
|
||||
* @COMMAND_CRC32: Calculates CRC32 over a specified memory area
|
||||
* @COMMAND_BANK_ERASE: Performs an erase of all of the customer-accessible
|
||||
* flash sectors not protected by FCFG1 and CCFG
|
||||
* writeprotect bits.
|
||||
*
|
||||
* CC1352 Bootloader serial bus commands
|
||||
*/
|
||||
enum cc1352_bootloader_cmd {
|
||||
COMMAND_DOWNLOAD = 0x21,
|
||||
COMMAND_GET_STATUS = 0x23,
|
||||
COMMAND_SEND_DATA = 0x24,
|
||||
COMMAND_RESET = 0x25,
|
||||
COMMAND_CRC32 = 0x27,
|
||||
COMMAND_BANK_ERASE = 0x2c,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum cc1352_bootloader_status: CC1352 Bootloader COMMAND_GET_STATUS response
|
||||
*
|
||||
* @COMMAND_RET_SUCCESS: Status for successful command
|
||||
* @COMMAND_RET_UNKNOWN_CMD: Status for unknown command
|
||||
* @COMMAND_RET_INVALID_CMD: Status for invalid command (in other words,
|
||||
* incorrect packet size)
|
||||
* @COMMAND_RET_INVALID_ADR: Status for invalid input address
|
||||
* @COMMAND_RET_FLASH_FAIL: Status for failing flash erase or program operation
|
||||
*/
|
||||
enum cc1352_bootloader_status {
|
||||
COMMAND_RET_SUCCESS = 0x40,
|
||||
COMMAND_RET_UNKNOWN_CMD = 0x41,
|
||||
COMMAND_RET_INVALID_CMD = 0x42,
|
||||
COMMAND_RET_INVALID_ADR = 0x43,
|
||||
COMMAND_RET_FLASH_FAIL = 0x44,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cc1352_bootloader_packet: CC1352 Bootloader Request Packet
|
||||
*
|
||||
* @len: length of packet + optional request data
|
||||
* @checksum: 8-bit checksum excluding len
|
||||
* @cmd: bootloader command
|
||||
*/
|
||||
struct cc1352_bootloader_packet {
|
||||
u8 len;
|
||||
u8 checksum;
|
||||
u8 cmd;
|
||||
} __packed;
|
||||
|
||||
#define CC1352_BOOTLOADER_PKT_MAX_SIZE \
|
||||
(U8_MAX - sizeof(struct cc1352_bootloader_packet))
|
||||
|
||||
/**
|
||||
* struct cc1352_bootloader_download_cmd_data: CC1352 Bootloader COMMAND_DOWNLOAD request data
|
||||
*
|
||||
* @addr: address to start programming data into
|
||||
* @size: size of data that will be sent
|
||||
*/
|
||||
struct cc1352_bootloader_download_cmd_data {
|
||||
__be32 addr;
|
||||
__be32 size;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct cc1352_bootloader_crc32_cmd_data: CC1352 Bootloader COMMAND_CRC32 request data
|
||||
*
|
||||
* @addr: address where crc32 calculation starts
|
||||
* @size: number of bytes comprised by crc32 calculation
|
||||
* @read_repeat: number of read repeats for each data location
|
||||
*/
|
||||
struct cc1352_bootloader_crc32_cmd_data {
|
||||
__be32 addr;
|
||||
__be32 size;
|
||||
__be32 read_repeat;
|
||||
} __packed;
|
||||
|
||||
static void hdlc_rx_greybus_frame(struct gb_beagleplay *bg, u8 *buf, u16 len)
|
||||
{
|
||||
struct hdlc_greybus_frame *gb_frame = (struct hdlc_greybus_frame *)buf;
|
||||
@ -331,11 +432,135 @@ static void hdlc_deinit(struct gb_beagleplay *bg)
|
||||
flush_work(&bg->tx_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* csum8: Calculate 8-bit checksum on data
|
||||
*
|
||||
* @data: bytes to calculate 8-bit checksum of
|
||||
* @size: number of bytes
|
||||
* @base: starting value for checksum
|
||||
*/
|
||||
static u8 csum8(const u8 *data, size_t size, u8 base)
|
||||
{
|
||||
size_t i;
|
||||
u8 sum = base;
|
||||
|
||||
for (i = 0; i < size; ++i)
|
||||
sum += data[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void cc1352_bootloader_send_ack(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const u8 ack[] = { 0x00, CC1352_BOOTLOADER_ACK };
|
||||
|
||||
serdev_device_write_buf(bg->sd, ack, sizeof(ack));
|
||||
}
|
||||
|
||||
static void cc1352_bootloader_send_nack(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const u8 nack[] = { 0x00, CC1352_BOOTLOADER_NACK };
|
||||
|
||||
serdev_device_write_buf(bg->sd, nack, sizeof(nack));
|
||||
}
|
||||
|
||||
/**
|
||||
* cc1352_bootloader_pkt_rx: Process a CC1352 Bootloader Packet
|
||||
*
|
||||
* @bg: beagleplay greybus driver
|
||||
* @data: packet buffer
|
||||
* @count: packet buffer size
|
||||
*
|
||||
* @return: number of bytes processed
|
||||
*
|
||||
* Here are the steps to successfully receive a packet from cc1352 bootloader
|
||||
* according to the docs:
|
||||
* 1. Wait for nonzero data to be returned from the device. This is important
|
||||
* as the device may send zero bytes between a sent and a received data
|
||||
* packet. The first nonzero byte received is the size of the packet that is
|
||||
* being received.
|
||||
* 2. Read the next byte, which is the checksum for the packet.
|
||||
* 3. Read the data bytes from the device. During the data phase, packet size
|
||||
* minus 2 bytes is sent.
|
||||
* 4. Calculate the checksum of the data bytes and verify it matches the
|
||||
* checksum received in the packet.
|
||||
* 5. Send an acknowledge byte or a not-acknowledge byte to the device to
|
||||
* indicate the successful or unsuccessful reception of the packet.
|
||||
*/
|
||||
static int cc1352_bootloader_pkt_rx(struct gb_beagleplay *bg, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
bool is_valid = false;
|
||||
|
||||
switch (data[0]) {
|
||||
/* Skip 0x00 bytes. */
|
||||
case 0x00:
|
||||
return 1;
|
||||
case CC1352_BOOTLOADER_ACK:
|
||||
case CC1352_BOOTLOADER_NACK:
|
||||
WRITE_ONCE(bg->fwl_ack, data[0]);
|
||||
complete(&bg->fwl_ack_com);
|
||||
return 1;
|
||||
case 3:
|
||||
if (count < 3)
|
||||
return 0;
|
||||
is_valid = data[1] == data[2];
|
||||
WRITE_ONCE(bg->fwl_cmd_response, (u32)data[2]);
|
||||
break;
|
||||
case 6:
|
||||
if (count < 6)
|
||||
return 0;
|
||||
is_valid = csum8(&data[2], sizeof(__be32), 0) == data[1];
|
||||
WRITE_ONCE(bg->fwl_cmd_response, get_unaligned_be32(&data[2]));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_valid) {
|
||||
cc1352_bootloader_send_ack(bg);
|
||||
complete(&bg->fwl_cmd_response_com);
|
||||
} else {
|
||||
dev_warn(&bg->sd->dev,
|
||||
"Dropping bootloader packet with invalid checksum");
|
||||
cc1352_bootloader_send_nack(bg);
|
||||
}
|
||||
|
||||
return data[0];
|
||||
}
|
||||
|
||||
static size_t cc1352_bootloader_rx(struct gb_beagleplay *bg, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
int ret;
|
||||
size_t off = 0;
|
||||
|
||||
memcpy(bg->rx_buffer + bg->rx_buffer_len, data, count);
|
||||
bg->rx_buffer_len += count;
|
||||
|
||||
do {
|
||||
ret = cc1352_bootloader_pkt_rx(bg, bg->rx_buffer + off,
|
||||
bg->rx_buffer_len - off);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Invalid Packet");
|
||||
off += ret;
|
||||
} while (ret > 0 && off < count);
|
||||
|
||||
bg->rx_buffer_len -= off;
|
||||
memmove(bg->rx_buffer, bg->rx_buffer + off, bg->rx_buffer_len);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static size_t gb_tty_receive(struct serdev_device *sd, const u8 *data,
|
||||
size_t count)
|
||||
{
|
||||
struct gb_beagleplay *bg = serdev_device_get_drvdata(sd);
|
||||
|
||||
if (READ_ONCE(bg->flashing_mode))
|
||||
return cc1352_bootloader_rx(bg, data, count);
|
||||
|
||||
return hdlc_rx(bg, data, count);
|
||||
}
|
||||
|
||||
@ -343,7 +568,8 @@ static void gb_tty_wakeup(struct serdev_device *serdev)
|
||||
{
|
||||
struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev);
|
||||
|
||||
schedule_work(&bg->tx_work);
|
||||
if (!READ_ONCE(bg->flashing_mode))
|
||||
schedule_work(&bg->tx_work);
|
||||
}
|
||||
|
||||
static struct serdev_device_ops gb_beagleplay_ops = {
|
||||
@ -412,6 +638,195 @@ static void gb_beagleplay_stop_svc(struct gb_beagleplay *bg)
|
||||
hdlc_tx_frames(bg, ADDRESS_CONTROL, 0x03, &payload, 1);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_wait_for_ack(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_ack_com, msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Failed to acquire ack semaphore");
|
||||
|
||||
switch (READ_ONCE(bg->fwl_ack)) {
|
||||
case CC1352_BOOTLOADER_ACK:
|
||||
return 0;
|
||||
case CC1352_BOOTLOADER_NACK:
|
||||
return -EAGAIN;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_sync(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const u8 sync_bytes[] = { 0x55, 0x55 };
|
||||
|
||||
serdev_device_write_buf(bg->sd, sync_bytes, sizeof(sync_bytes));
|
||||
return cc1352_bootloader_wait_for_ack(bg);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_get_status(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
static const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt),
|
||||
.checksum = COMMAND_GET_STATUS,
|
||||
.cmd = COMMAND_GET_STATUS
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_cmd_response_com,
|
||||
msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Failed to acquire last status semaphore");
|
||||
|
||||
switch (READ_ONCE(bg->fwl_cmd_response)) {
|
||||
case COMMAND_RET_SUCCESS:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_erase(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
static const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt),
|
||||
.checksum = COMMAND_BANK_ERASE,
|
||||
.cmd = COMMAND_BANK_ERASE
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return cc1352_bootloader_get_status(bg);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_reset(struct gb_beagleplay *bg)
|
||||
{
|
||||
static const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt),
|
||||
.checksum = COMMAND_RESET,
|
||||
.cmd = COMMAND_RESET
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
|
||||
return cc1352_bootloader_wait_for_ack(bg);
|
||||
}
|
||||
|
||||
/**
|
||||
* cc1352_bootloader_empty_pkt: Calculate the number of empty bytes in the current packet
|
||||
*
|
||||
* @data: packet bytes array to check
|
||||
* @size: number of bytes in array
|
||||
*/
|
||||
static size_t cc1352_bootloader_empty_pkt(const u8 *data, size_t size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size && data[i] == 0xff; ++i)
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_crc32(struct gb_beagleplay *bg, u32 *crc32)
|
||||
{
|
||||
int ret;
|
||||
static const struct cc1352_bootloader_crc32_cmd_data cmd_data = {
|
||||
.addr = 0, .size = cpu_to_be32(704 * 1024), .read_repeat = 0
|
||||
};
|
||||
const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt) + sizeof(cmd_data),
|
||||
.checksum = csum8((const void *)&cmd_data, sizeof(cmd_data),
|
||||
COMMAND_CRC32),
|
||||
.cmd = COMMAND_CRC32
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&cmd_data,
|
||||
sizeof(cmd_data));
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_cmd_response_com,
|
||||
msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
"Failed to acquire last status semaphore");
|
||||
|
||||
*crc32 = READ_ONCE(bg->fwl_cmd_response);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_download(struct gb_beagleplay *bg, u32 size,
|
||||
u32 addr)
|
||||
{
|
||||
int ret;
|
||||
const struct cc1352_bootloader_download_cmd_data cmd_data = {
|
||||
.addr = cpu_to_be32(addr),
|
||||
.size = cpu_to_be32(size),
|
||||
};
|
||||
const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt) + sizeof(cmd_data),
|
||||
.checksum = csum8((const void *)&cmd_data, sizeof(cmd_data),
|
||||
COMMAND_DOWNLOAD),
|
||||
.cmd = COMMAND_DOWNLOAD
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&cmd_data,
|
||||
sizeof(cmd_data));
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return cc1352_bootloader_get_status(bg);
|
||||
}
|
||||
|
||||
static int cc1352_bootloader_send_data(struct gb_beagleplay *bg, const u8 *data,
|
||||
size_t size)
|
||||
{
|
||||
int ret, rem = min(size, CC1352_BOOTLOADER_PKT_MAX_SIZE);
|
||||
const struct cc1352_bootloader_packet pkt = {
|
||||
.len = sizeof(pkt) + rem,
|
||||
.checksum = csum8(data, rem, COMMAND_SEND_DATA),
|
||||
.cmd = COMMAND_SEND_DATA
|
||||
};
|
||||
|
||||
serdev_device_write_buf(bg->sd, (const u8 *)&pkt, sizeof(pkt));
|
||||
serdev_device_write_buf(bg->sd, data, rem);
|
||||
|
||||
ret = cc1352_bootloader_wait_for_ack(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cc1352_bootloader_get_status(bg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return rem;
|
||||
}
|
||||
|
||||
static void gb_greybus_deinit(struct gb_beagleplay *bg)
|
||||
{
|
||||
gb_hd_del(bg->gb_hd);
|
||||
@ -442,6 +857,157 @@ free_gb_hd:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum fw_upload_err cc1352_prepare(struct fw_upload *fw_upload,
|
||||
const u8 *data, u32 size)
|
||||
{
|
||||
int ret;
|
||||
u32 curr_crc32;
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
dev_info(&bg->sd->dev, "CC1352 Start Flashing...");
|
||||
|
||||
if (size != CC1352_FIRMWARE_SIZE)
|
||||
return FW_UPLOAD_ERR_INVALID_SIZE;
|
||||
|
||||
/* Might involve network calls */
|
||||
gb_greybus_deinit(bg);
|
||||
msleep(5 * MSEC_PER_SEC);
|
||||
|
||||
gb_beagleplay_stop_svc(bg);
|
||||
msleep(200);
|
||||
flush_work(&bg->tx_work);
|
||||
|
||||
serdev_device_wait_until_sent(bg->sd, CC1352_BOOTLOADER_TIMEOUT);
|
||||
|
||||
WRITE_ONCE(bg->flashing_mode, true);
|
||||
|
||||
gpiod_direction_output(bg->bootloader_backdoor_gpio, 0);
|
||||
gpiod_direction_output(bg->rst_gpio, 0);
|
||||
msleep(200);
|
||||
|
||||
gpiod_set_value(bg->rst_gpio, 1);
|
||||
msleep(200);
|
||||
|
||||
gpiod_set_value(bg->bootloader_backdoor_gpio, 1);
|
||||
msleep(200);
|
||||
|
||||
gpiod_direction_input(bg->bootloader_backdoor_gpio);
|
||||
gpiod_direction_input(bg->rst_gpio);
|
||||
|
||||
ret = cc1352_bootloader_sync(bg);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to sync");
|
||||
|
||||
ret = cc1352_bootloader_crc32(bg, &curr_crc32);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to fetch crc32");
|
||||
|
||||
bg->fwl_crc32 = crc32(0xffffffff, data, size) ^ 0xffffffff;
|
||||
|
||||
/* Check if attempting to reflash same firmware */
|
||||
if (bg->fwl_crc32 == curr_crc32) {
|
||||
dev_warn(&bg->sd->dev, "Skipping reflashing same image");
|
||||
cc1352_bootloader_reset(bg);
|
||||
WRITE_ONCE(bg->flashing_mode, false);
|
||||
msleep(200);
|
||||
gb_greybus_init(bg);
|
||||
gb_beagleplay_start_svc(bg);
|
||||
return FW_UPLOAD_ERR_FW_INVALID;
|
||||
}
|
||||
|
||||
ret = cc1352_bootloader_erase(bg);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to erase");
|
||||
|
||||
bg->fwl_reset_addr = true;
|
||||
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
static void cc1352_cleanup(struct fw_upload *fw_upload)
|
||||
{
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
WRITE_ONCE(bg->flashing_mode, false);
|
||||
}
|
||||
|
||||
static enum fw_upload_err cc1352_write(struct fw_upload *fw_upload,
|
||||
const u8 *data, u32 offset, u32 size,
|
||||
u32 *written)
|
||||
{
|
||||
int ret;
|
||||
size_t empty_bytes;
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
/* Skip 0xff packets. Significant performance improvement */
|
||||
empty_bytes = cc1352_bootloader_empty_pkt(data + offset, size);
|
||||
if (empty_bytes >= CC1352_BOOTLOADER_PKT_MAX_SIZE) {
|
||||
bg->fwl_reset_addr = true;
|
||||
*written = empty_bytes;
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
if (bg->fwl_reset_addr) {
|
||||
ret = cc1352_bootloader_download(bg, size, offset);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev,
|
||||
FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to send download cmd");
|
||||
|
||||
bg->fwl_reset_addr = false;
|
||||
}
|
||||
|
||||
ret = cc1352_bootloader_send_data(bg, data + offset, size);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to flash firmware");
|
||||
*written = ret;
|
||||
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
static enum fw_upload_err cc1352_poll_complete(struct fw_upload *fw_upload)
|
||||
{
|
||||
u32 curr_crc32;
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
if (cc1352_bootloader_crc32(bg, &curr_crc32) < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to fetch crc32");
|
||||
|
||||
if (bg->fwl_crc32 != curr_crc32)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_FW_INVALID,
|
||||
"Invalid CRC32");
|
||||
|
||||
if (cc1352_bootloader_reset(bg) < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_HW_ERROR,
|
||||
"Failed to reset");
|
||||
|
||||
dev_info(&bg->sd->dev, "CC1352 Flashing Successful");
|
||||
WRITE_ONCE(bg->flashing_mode, false);
|
||||
msleep(200);
|
||||
|
||||
if (gb_greybus_init(bg) < 0)
|
||||
return dev_err_probe(&bg->sd->dev, FW_UPLOAD_ERR_RW_ERROR,
|
||||
"Failed to initialize greybus");
|
||||
|
||||
gb_beagleplay_start_svc(bg);
|
||||
|
||||
return FW_UPLOAD_ERR_NONE;
|
||||
}
|
||||
|
||||
static void cc1352_cancel(struct fw_upload *fw_upload)
|
||||
{
|
||||
struct gb_beagleplay *bg = fw_upload->dd_handle;
|
||||
|
||||
dev_info(&bg->sd->dev, "CC1352 Bootloader Cancel");
|
||||
|
||||
cc1352_bootloader_reset(bg);
|
||||
}
|
||||
|
||||
static void gb_serdev_deinit(struct gb_beagleplay *bg)
|
||||
{
|
||||
serdev_device_close(bg->sd);
|
||||
@ -463,6 +1029,65 @@ static int gb_serdev_init(struct gb_beagleplay *bg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fw_upload_ops cc1352_bootloader_ops = {
|
||||
.prepare = cc1352_prepare,
|
||||
.write = cc1352_write,
|
||||
.poll_complete = cc1352_poll_complete,
|
||||
.cancel = cc1352_cancel,
|
||||
.cleanup = cc1352_cleanup
|
||||
};
|
||||
|
||||
static int gb_fw_init(struct gb_beagleplay *bg)
|
||||
{
|
||||
int ret;
|
||||
struct fw_upload *fwl;
|
||||
struct gpio_desc *desc;
|
||||
|
||||
bg->fwl = NULL;
|
||||
bg->bootloader_backdoor_gpio = NULL;
|
||||
bg->rst_gpio = NULL;
|
||||
bg->flashing_mode = false;
|
||||
bg->fwl_cmd_response = 0;
|
||||
bg->fwl_ack = 0;
|
||||
init_completion(&bg->fwl_ack_com);
|
||||
init_completion(&bg->fwl_cmd_response_com);
|
||||
|
||||
desc = devm_gpiod_get(&bg->sd->dev, "bootloader-backdoor", GPIOD_IN);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
bg->bootloader_backdoor_gpio = desc;
|
||||
|
||||
desc = devm_gpiod_get(&bg->sd->dev, "reset", GPIOD_IN);
|
||||
if (IS_ERR(desc)) {
|
||||
ret = PTR_ERR(desc);
|
||||
goto free_boot;
|
||||
}
|
||||
bg->rst_gpio = desc;
|
||||
|
||||
fwl = firmware_upload_register(THIS_MODULE, &bg->sd->dev, "cc1352p7",
|
||||
&cc1352_bootloader_ops, bg);
|
||||
if (IS_ERR(fwl)) {
|
||||
ret = PTR_ERR(fwl);
|
||||
goto free_reset;
|
||||
}
|
||||
bg->fwl = fwl;
|
||||
|
||||
return 0;
|
||||
|
||||
free_reset:
|
||||
devm_gpiod_put(&bg->sd->dev, bg->rst_gpio);
|
||||
bg->rst_gpio = NULL;
|
||||
free_boot:
|
||||
devm_gpiod_put(&bg->sd->dev, bg->bootloader_backdoor_gpio);
|
||||
bg->bootloader_backdoor_gpio = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gb_fw_deinit(struct gb_beagleplay *bg)
|
||||
{
|
||||
firmware_upload_unregister(bg->fwl);
|
||||
}
|
||||
|
||||
static int gb_beagleplay_probe(struct serdev_device *serdev)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -481,14 +1106,20 @@ static int gb_beagleplay_probe(struct serdev_device *serdev)
|
||||
if (ret)
|
||||
goto free_serdev;
|
||||
|
||||
ret = gb_greybus_init(bg);
|
||||
ret = gb_fw_init(bg);
|
||||
if (ret)
|
||||
goto free_hdlc;
|
||||
|
||||
ret = gb_greybus_init(bg);
|
||||
if (ret)
|
||||
goto free_fw;
|
||||
|
||||
gb_beagleplay_start_svc(bg);
|
||||
|
||||
return 0;
|
||||
|
||||
free_fw:
|
||||
gb_fw_deinit(bg);
|
||||
free_hdlc:
|
||||
hdlc_deinit(bg);
|
||||
free_serdev:
|
||||
@ -500,6 +1131,7 @@ static void gb_beagleplay_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct gb_beagleplay *bg = serdev_device_get_drvdata(serdev);
|
||||
|
||||
gb_fw_deinit(bg);
|
||||
gb_greybus_deinit(bg);
|
||||
gb_beagleplay_stop_svc(bg);
|
||||
hdlc_deinit(bg);
|
||||
|
@ -487,23 +487,25 @@ struct coresight_device *coresight_get_sink(struct list_head *path)
|
||||
return csdev;
|
||||
}
|
||||
|
||||
u32 coresight_get_sink_id(struct coresight_device *csdev)
|
||||
{
|
||||
if (!csdev->ea)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* See function etm_perf_add_symlink_sink() to know where
|
||||
* this comes from.
|
||||
*/
|
||||
return (u32) (unsigned long) csdev->ea->var;
|
||||
}
|
||||
|
||||
static int coresight_sink_by_id(struct device *dev, const void *data)
|
||||
{
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
unsigned long hash;
|
||||
|
||||
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
|
||||
if (!csdev->ea)
|
||||
return 0;
|
||||
/*
|
||||
* See function etm_perf_add_symlink_sink() to know where
|
||||
* this comes from.
|
||||
*/
|
||||
hash = (unsigned long)csdev->ea->var;
|
||||
|
||||
if ((u32)hash == *(u32 *)data)
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
if (coresight_get_sink_id(csdev) == *(u32 *)data)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -902,6 +904,7 @@ static void coresight_device_release(struct device *dev)
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
fwnode_handle_put(csdev->dev.fwnode);
|
||||
free_percpu(csdev->perf_sink_id_map.cpu_map);
|
||||
kfree(csdev);
|
||||
}
|
||||
|
||||
@ -1159,6 +1162,16 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
||||
csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev));
|
||||
dev_set_name(&csdev->dev, "%s", desc->name);
|
||||
|
||||
if (csdev->type == CORESIGHT_DEV_TYPE_SINK ||
|
||||
csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
spin_lock_init(&csdev->perf_sink_id_map.lock);
|
||||
csdev->perf_sink_id_map.cpu_map = alloc_percpu(atomic_t);
|
||||
if (!csdev->perf_sink_id_map.cpu_map) {
|
||||
kfree(csdev);
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Make sure the device registration and the connection fixup
|
||||
* are synchronised, so that we don't see uninitialised devices
|
||||
|
@ -416,20 +416,16 @@ static int cti_plat_create_impdef_connections(struct device *dev,
|
||||
struct cti_drvdata *drvdata)
|
||||
{
|
||||
int rc = 0;
|
||||
struct fwnode_handle *fwnode = dev_fwnode(dev);
|
||||
struct fwnode_handle *child = NULL;
|
||||
|
||||
if (IS_ERR_OR_NULL(fwnode))
|
||||
if (IS_ERR_OR_NULL(dev_fwnode(dev)))
|
||||
return -EINVAL;
|
||||
|
||||
fwnode_for_each_child_node(fwnode, child) {
|
||||
device_for_each_child_node_scoped(dev, child) {
|
||||
if (cti_plat_node_name_eq(child, CTI_DT_CONNS))
|
||||
rc = cti_plat_create_connection(dev, drvdata,
|
||||
child);
|
||||
rc = cti_plat_create_connection(dev, drvdata, child);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
fwnode_handle_put(child);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -21,8 +21,12 @@ DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
|
||||
DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
|
||||
|
||||
static int dummy_source_enable(struct coresight_device *csdev,
|
||||
struct perf_event *event, enum cs_mode mode)
|
||||
struct perf_event *event, enum cs_mode mode,
|
||||
__maybe_unused struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
if (!coresight_take_mode(csdev, mode))
|
||||
return -EBUSY;
|
||||
|
||||
dev_dbg(csdev->dev.parent, "Dummy source enabled\n");
|
||||
|
||||
return 0;
|
||||
@ -31,6 +35,7 @@ static int dummy_source_enable(struct coresight_device *csdev,
|
||||
static void dummy_source_disable(struct coresight_device *csdev,
|
||||
struct perf_event *event)
|
||||
{
|
||||
coresight_set_mode(csdev, CS_MODE_DISABLED);
|
||||
dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
|
||||
}
|
||||
|
||||
|
@ -229,14 +229,23 @@ static void free_event_data(struct work_struct *work)
|
||||
struct list_head **ppath;
|
||||
|
||||
ppath = etm_event_cpu_path_ptr(event_data, cpu);
|
||||
if (!(IS_ERR_OR_NULL(*ppath)))
|
||||
coresight_release_path(*ppath);
|
||||
*ppath = NULL;
|
||||
coresight_trace_id_put_cpu_id(cpu);
|
||||
}
|
||||
if (!(IS_ERR_OR_NULL(*ppath))) {
|
||||
struct coresight_device *sink = coresight_get_sink(*ppath);
|
||||
|
||||
/* mark perf event as done for trace id allocator */
|
||||
coresight_trace_id_perf_stop();
|
||||
/*
|
||||
* Mark perf event as done for trace id allocator, but don't call
|
||||
* coresight_trace_id_put_cpu_id_map() on individual IDs. Perf sessions
|
||||
* never free trace IDs to ensure that the ID associated with a CPU
|
||||
* cannot change during their and other's concurrent sessions. Instead,
|
||||
* a refcount is used so that the last event to call
|
||||
* coresight_trace_id_perf_stop() frees all IDs.
|
||||
*/
|
||||
coresight_trace_id_perf_stop(&sink->perf_sink_id_map);
|
||||
|
||||
coresight_release_path(*ppath);
|
||||
}
|
||||
*ppath = NULL;
|
||||
}
|
||||
|
||||
free_percpu(event_data->path);
|
||||
kfree(event_data);
|
||||
@ -325,9 +334,6 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
|
||||
sink = user_sink = coresight_get_sink_by_id(id);
|
||||
}
|
||||
|
||||
/* tell the trace ID allocator that a perf event is starting up */
|
||||
coresight_trace_id_perf_start();
|
||||
|
||||
/* check if user wants a coresight configuration selected */
|
||||
cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32);
|
||||
if (cfg_hash) {
|
||||
@ -401,13 +407,14 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
|
||||
}
|
||||
|
||||
/* ensure we can allocate a trace ID for this CPU */
|
||||
trace_id = coresight_trace_id_get_cpu_id(cpu);
|
||||
trace_id = coresight_trace_id_get_cpu_id_map(cpu, &sink->perf_sink_id_map);
|
||||
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
|
||||
cpumask_clear_cpu(cpu, mask);
|
||||
coresight_release_path(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
coresight_trace_id_perf_start(&sink->perf_sink_id_map);
|
||||
*etm_event_cpu_path_ptr(event_data, cpu) = path;
|
||||
}
|
||||
|
||||
@ -453,6 +460,7 @@ static void etm_event_start(struct perf_event *event, int flags)
|
||||
struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
|
||||
struct list_head *path;
|
||||
u64 hw_id;
|
||||
u8 trace_id;
|
||||
|
||||
if (!csdev)
|
||||
goto fail;
|
||||
@ -495,7 +503,8 @@ static void etm_event_start(struct perf_event *event, int flags)
|
||||
goto fail_end_stop;
|
||||
|
||||
/* Finally enable the tracer */
|
||||
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
|
||||
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF,
|
||||
&sink->perf_sink_id_map))
|
||||
goto fail_disable_path;
|
||||
|
||||
/*
|
||||
@ -504,10 +513,16 @@ static void etm_event_start(struct perf_event *event, int flags)
|
||||
*/
|
||||
if (!cpumask_test_cpu(cpu, &event_data->aux_hwid_done)) {
|
||||
cpumask_set_cpu(cpu, &event_data->aux_hwid_done);
|
||||
hw_id = FIELD_PREP(CS_AUX_HW_ID_VERSION_MASK,
|
||||
CS_AUX_HW_ID_CURR_VERSION);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK,
|
||||
coresight_trace_id_read_cpu_id(cpu));
|
||||
|
||||
trace_id = coresight_trace_id_read_cpu_id_map(cpu, &sink->perf_sink_id_map);
|
||||
|
||||
hw_id = FIELD_PREP(CS_AUX_HW_ID_MAJOR_VERSION_MASK,
|
||||
CS_AUX_HW_ID_MAJOR_VERSION);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_MINOR_VERSION_MASK,
|
||||
CS_AUX_HW_ID_MINOR_VERSION);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_TRACE_ID_MASK, trace_id);
|
||||
hw_id |= FIELD_PREP(CS_AUX_HW_ID_SINK_ID_MASK, coresight_get_sink_id(sink));
|
||||
|
||||
perf_report_aux_output_id(event, hw_id);
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,6 @@ struct etm_event_data {
|
||||
struct list_head * __percpu *path;
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT)
|
||||
int etm_perf_symlink(struct coresight_device *csdev, bool link);
|
||||
int etm_perf_add_symlink_sink(struct coresight_device *csdev);
|
||||
void etm_perf_del_symlink_sink(struct coresight_device *csdev);
|
||||
@ -77,23 +76,6 @@ static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
|
||||
int etm_perf_add_symlink_cscfg(struct device *dev,
|
||||
struct cscfg_config_desc *config_desc);
|
||||
void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc);
|
||||
#else
|
||||
static inline int etm_perf_symlink(struct coresight_device *csdev, bool link)
|
||||
{ return -EINVAL; }
|
||||
int etm_perf_add_symlink_sink(struct coresight_device *csdev)
|
||||
{ return -EINVAL; }
|
||||
void etm_perf_del_symlink_sink(struct coresight_device *csdev) {}
|
||||
static inline void *etm_perf_sink_config(struct perf_output_handle *handle)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
int etm_perf_add_symlink_cscfg(struct device *dev,
|
||||
struct cscfg_config_desc *config_desc)
|
||||
{ return -EINVAL; }
|
||||
void etm_perf_del_symlink_cscfg(struct cscfg_config_desc *config_desc) {}
|
||||
|
||||
#endif /* CONFIG_CORESIGHT */
|
||||
|
||||
int __init etm_perf_init(void);
|
||||
void etm_perf_exit(void);
|
||||
|
||||
|
@ -481,7 +481,8 @@ void etm_release_trace_id(struct etm_drvdata *drvdata)
|
||||
}
|
||||
|
||||
static int etm_enable_perf(struct coresight_device *csdev,
|
||||
struct perf_event *event)
|
||||
struct perf_event *event,
|
||||
struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int trace_id;
|
||||
@ -500,7 +501,7 @@ static int etm_enable_perf(struct coresight_device *csdev,
|
||||
* with perf locks - we know the ID cannot change until perf shuts down
|
||||
* the session
|
||||
*/
|
||||
trace_id = coresight_trace_id_read_cpu_id(drvdata->cpu);
|
||||
trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
|
||||
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
|
||||
dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
|
||||
dev_name(&drvdata->csdev->dev), drvdata->cpu);
|
||||
@ -553,7 +554,7 @@ unlock_enable_sysfs:
|
||||
}
|
||||
|
||||
static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
int ret;
|
||||
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
@ -568,7 +569,7 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
ret = etm_enable_sysfs(csdev);
|
||||
break;
|
||||
case CS_MODE_PERF:
|
||||
ret = etm_enable_perf(csdev, event);
|
||||
ret = etm_enable_perf(csdev, event, id_map);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -752,7 +752,8 @@ out:
|
||||
}
|
||||
|
||||
static int etm4_enable_perf(struct coresight_device *csdev,
|
||||
struct perf_event *event)
|
||||
struct perf_event *event,
|
||||
struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
int ret = 0, trace_id;
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
@ -775,7 +776,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
|
||||
* with perf locks - we know the ID cannot change until perf shuts down
|
||||
* the session
|
||||
*/
|
||||
trace_id = coresight_trace_id_read_cpu_id(drvdata->cpu);
|
||||
trace_id = coresight_trace_id_read_cpu_id_map(drvdata->cpu, id_map);
|
||||
if (!IS_VALID_CS_TRACE_ID(trace_id)) {
|
||||
dev_err(&drvdata->csdev->dev, "Failed to set trace ID for %s on CPU%d\n",
|
||||
dev_name(&drvdata->csdev->dev), drvdata->cpu);
|
||||
@ -837,7 +838,7 @@ unlock_sysfs_enable:
|
||||
}
|
||||
|
||||
static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -851,7 +852,7 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
ret = etm4_enable_sysfs(csdev);
|
||||
break;
|
||||
case CS_MODE_PERF:
|
||||
ret = etm4_enable_perf(csdev, event);
|
||||
ret = etm4_enable_perf(csdev, event, id_map);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
|
@ -148,6 +148,7 @@ int coresight_make_links(struct coresight_device *orig,
|
||||
struct coresight_device *target);
|
||||
void coresight_remove_links(struct coresight_device *orig,
|
||||
struct coresight_connection *conn);
|
||||
u32 coresight_get_sink_id(struct coresight_device *csdev);
|
||||
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
|
||||
extern int etm_readl_cp14(u32 off, unsigned int *val);
|
||||
|
@ -194,7 +194,8 @@ static void stm_enable_hw(struct stm_drvdata *drvdata)
|
||||
}
|
||||
|
||||
static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode,
|
||||
__maybe_unused struct coresight_trace_id_map *trace_id)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
#include "coresight-trace-id.h"
|
||||
|
||||
/*
|
||||
* Use IDR to map the hash of the source's device name
|
||||
@ -63,7 +64,7 @@ static int coresight_enable_source_sysfs(struct coresight_device *csdev,
|
||||
*/
|
||||
lockdep_assert_held(&coresight_mutex);
|
||||
if (coresight_get_mode(csdev) != CS_MODE_SYSFS) {
|
||||
ret = source_ops(csdev)->enable(csdev, data, mode);
|
||||
ret = source_ops(csdev)->enable(csdev, data, mode, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ struct etr_buf_hw {
|
||||
* etr_perf_buffer - Perf buffer used for ETR
|
||||
* @drvdata - The ETR drvdaga this buffer has been allocated for.
|
||||
* @etr_buf - Actual buffer used by the ETR
|
||||
* @pid - The PID this etr_perf_buffer belongs to.
|
||||
* @pid - The PID of the session owner that etr_perf_buffer
|
||||
* belongs to.
|
||||
* @snaphost - Perf session mode
|
||||
* @nr_pages - Number of pages in the ring buffer.
|
||||
* @pages - Array of Pages in the ring buffer.
|
||||
@ -261,6 +262,7 @@ void tmc_free_sg_table(struct tmc_sg_table *sg_table)
|
||||
{
|
||||
tmc_free_table_pages(sg_table);
|
||||
tmc_free_data_pages(sg_table);
|
||||
kfree(sg_table);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tmc_free_sg_table);
|
||||
|
||||
@ -342,7 +344,6 @@ struct tmc_sg_table *tmc_alloc_sg_table(struct device *dev,
|
||||
rc = tmc_alloc_table_pages(sg_table);
|
||||
if (rc) {
|
||||
tmc_free_sg_table(sg_table);
|
||||
kfree(sg_table);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
@ -1662,7 +1663,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
|
||||
goto unlock_out;
|
||||
}
|
||||
|
||||
/* Get a handle on the pid of the process to monitor */
|
||||
/* Get a handle on the pid of the session owner */
|
||||
pid = etr_perf->pid;
|
||||
|
||||
/* Do not proceed if this device is associated with another session */
|
||||
|
@ -171,8 +171,9 @@ struct etr_buf {
|
||||
* @csdev: component vitals needed by the framework.
|
||||
* @miscdev: specifics to handle "/dev/xyz.tmc" entry.
|
||||
* @spinlock: only one at a time pls.
|
||||
* @pid: Process ID of the process being monitored by the session
|
||||
* that is using this component.
|
||||
* @pid: Process ID of the process that owns the session that is using
|
||||
* this component. For example this would be the pid of the Perf
|
||||
* process.
|
||||
* @buf: Snapshot of the trace data for ETF/ETB.
|
||||
* @etr_buf: details of buffer used in TMC-ETR
|
||||
* @len: size of the available trace for ETF/ETB.
|
||||
|
@ -439,7 +439,8 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata)
|
||||
}
|
||||
|
||||
static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
enum cs_mode mode)
|
||||
enum cs_mode mode,
|
||||
__maybe_unused struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
@ -449,6 +450,11 @@ static int tpdm_enable(struct coresight_device *csdev, struct perf_event *event,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!coresight_take_mode(csdev, mode)) {
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
__tpdm_enable(drvdata);
|
||||
drvdata->enable = true;
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
@ -506,6 +512,7 @@ static void tpdm_disable(struct coresight_device *csdev,
|
||||
}
|
||||
|
||||
__tpdm_disable(drvdata);
|
||||
coresight_set_mode(csdev, CS_MODE_DISABLED);
|
||||
drvdata->enable = false;
|
||||
spin_unlock(&drvdata->spinlock);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2022, Linaro Limited, All rights reserved.
|
||||
* Author: Mike Leach <mike.leach@linaro.org>
|
||||
*/
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/coresight-pmu.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/kernel.h>
|
||||
@ -11,18 +12,12 @@
|
||||
|
||||
#include "coresight-trace-id.h"
|
||||
|
||||
/* Default trace ID map. Used on systems that don't require per sink mappings */
|
||||
static struct coresight_trace_id_map id_map_default;
|
||||
|
||||
/* maintain a record of the mapping of IDs and pending releases per cpu */
|
||||
static DEFINE_PER_CPU(atomic_t, cpu_id) = ATOMIC_INIT(0);
|
||||
static cpumask_t cpu_id_release_pending;
|
||||
|
||||
/* perf session active counter */
|
||||
static atomic_t perf_cs_etm_session_active = ATOMIC_INIT(0);
|
||||
|
||||
/* lock to protect id_map and cpu data */
|
||||
static DEFINE_SPINLOCK(id_map_lock);
|
||||
/* Default trace ID map. Used in sysfs mode and for system sources */
|
||||
static DEFINE_PER_CPU(atomic_t, id_map_default_cpu_ids) = ATOMIC_INIT(0);
|
||||
static struct coresight_trace_id_map id_map_default = {
|
||||
.cpu_map = &id_map_default_cpu_ids,
|
||||
.lock = __SPIN_LOCK_UNLOCKED(id_map_default.lock)
|
||||
};
|
||||
|
||||
/* #define TRACE_ID_DEBUG 1 */
|
||||
#if defined(TRACE_ID_DEBUG) || defined(CONFIG_COMPILE_TEST)
|
||||
@ -32,7 +27,6 @@ static void coresight_trace_id_dump_table(struct coresight_trace_id_map *id_map,
|
||||
{
|
||||
pr_debug("%s id_map::\n", func_name);
|
||||
pr_debug("Used = %*pb\n", CORESIGHT_TRACE_IDS_MAX, id_map->used_ids);
|
||||
pr_debug("Pend = %*pb\n", CORESIGHT_TRACE_IDS_MAX, id_map->pend_rel_ids);
|
||||
}
|
||||
#define DUMP_ID_MAP(map) coresight_trace_id_dump_table(map, __func__)
|
||||
#define DUMP_ID_CPU(cpu, id) pr_debug("%s called; cpu=%d, id=%d\n", __func__, cpu, id)
|
||||
@ -46,9 +40,9 @@ static void coresight_trace_id_dump_table(struct coresight_trace_id_map *id_map,
|
||||
#endif
|
||||
|
||||
/* unlocked read of current trace ID value for given CPU */
|
||||
static int _coresight_trace_id_read_cpu_id(int cpu)
|
||||
static int _coresight_trace_id_read_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
return atomic_read(&per_cpu(cpu_id, cpu));
|
||||
return atomic_read(per_cpu_ptr(id_map->cpu_map, cpu));
|
||||
}
|
||||
|
||||
/* look for next available odd ID, return 0 if none found */
|
||||
@ -119,49 +113,33 @@ static void coresight_trace_id_free(int id, struct coresight_trace_id_map *id_ma
|
||||
clear_bit(id, id_map->used_ids);
|
||||
}
|
||||
|
||||
static void coresight_trace_id_set_pend_rel(int id, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
if (WARN(!IS_VALID_CS_TRACE_ID(id), "Invalid Trace ID %d\n", id))
|
||||
return;
|
||||
set_bit(id, id_map->pend_rel_ids);
|
||||
}
|
||||
|
||||
/*
|
||||
* release all pending IDs for all current maps & clear CPU associations
|
||||
*
|
||||
* This currently operates on the default id map, but may be extended to
|
||||
* operate on all registered id maps if per sink id maps are used.
|
||||
* Release all IDs and clear CPU associations.
|
||||
*/
|
||||
static void coresight_trace_id_release_all_pending(void)
|
||||
static void coresight_trace_id_release_all(struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
struct coresight_trace_id_map *id_map = &id_map_default;
|
||||
unsigned long flags;
|
||||
int cpu, bit;
|
||||
int cpu;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
for_each_set_bit(bit, id_map->pend_rel_ids, CORESIGHT_TRACE_ID_RES_TOP) {
|
||||
clear_bit(bit, id_map->used_ids);
|
||||
clear_bit(bit, id_map->pend_rel_ids);
|
||||
}
|
||||
for_each_cpu(cpu, &cpu_id_release_pending) {
|
||||
atomic_set(&per_cpu(cpu_id, cpu), 0);
|
||||
cpumask_clear_cpu(cpu, &cpu_id_release_pending);
|
||||
}
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
bitmap_zero(id_map->used_ids, CORESIGHT_TRACE_IDS_MAX);
|
||||
for_each_possible_cpu(cpu)
|
||||
atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
DUMP_ID_MAP(id_map);
|
||||
}
|
||||
|
||||
static int coresight_trace_id_map_get_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
static int _coresight_trace_id_get_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
|
||||
/* check for existing allocation for this CPU */
|
||||
id = _coresight_trace_id_read_cpu_id(cpu);
|
||||
id = _coresight_trace_id_read_cpu_id(cpu, id_map);
|
||||
if (id)
|
||||
goto get_cpu_id_clr_pend;
|
||||
goto get_cpu_id_out_unlock;
|
||||
|
||||
/*
|
||||
* Find a new ID.
|
||||
@ -180,44 +158,32 @@ static int coresight_trace_id_map_get_cpu_id(int cpu, struct coresight_trace_id_
|
||||
goto get_cpu_id_out_unlock;
|
||||
|
||||
/* allocate the new id to the cpu */
|
||||
atomic_set(&per_cpu(cpu_id, cpu), id);
|
||||
|
||||
get_cpu_id_clr_pend:
|
||||
/* we are (re)using this ID - so ensure it is not marked for release */
|
||||
cpumask_clear_cpu(cpu, &cpu_id_release_pending);
|
||||
clear_bit(id, id_map->pend_rel_ids);
|
||||
atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), id);
|
||||
|
||||
get_cpu_id_out_unlock:
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
|
||||
DUMP_ID_CPU(cpu, id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
return id;
|
||||
}
|
||||
|
||||
static void coresight_trace_id_map_put_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
static void _coresight_trace_id_put_cpu_id(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
/* check for existing allocation for this CPU */
|
||||
id = _coresight_trace_id_read_cpu_id(cpu);
|
||||
id = _coresight_trace_id_read_cpu_id(cpu, id_map);
|
||||
if (!id)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
|
||||
if (atomic_read(&perf_cs_etm_session_active)) {
|
||||
/* set release at pending if perf still active */
|
||||
coresight_trace_id_set_pend_rel(id, id_map);
|
||||
cpumask_set_cpu(cpu, &cpu_id_release_pending);
|
||||
} else {
|
||||
/* otherwise clear id */
|
||||
coresight_trace_id_free(id, id_map);
|
||||
atomic_set(&per_cpu(cpu_id, cpu), 0);
|
||||
}
|
||||
coresight_trace_id_free(id, id_map);
|
||||
atomic_set(per_cpu_ptr(id_map->cpu_map, cpu), 0);
|
||||
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
DUMP_ID_CPU(cpu, id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
}
|
||||
@ -227,10 +193,10 @@ static int coresight_trace_id_map_get_system_id(struct coresight_trace_id_map *i
|
||||
unsigned long flags;
|
||||
int id;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
/* prefer odd IDs for system components to avoid legacy CPU IDS */
|
||||
id = coresight_trace_id_alloc_new_id(id_map, 0, true);
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
|
||||
DUMP_ID(id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
@ -241,9 +207,9 @@ static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&id_map_lock, flags);
|
||||
spin_lock_irqsave(&id_map->lock, flags);
|
||||
coresight_trace_id_free(id, id_map);
|
||||
spin_unlock_irqrestore(&id_map_lock, flags);
|
||||
spin_unlock_irqrestore(&id_map->lock, flags);
|
||||
|
||||
DUMP_ID(id);
|
||||
DUMP_ID_MAP(id_map);
|
||||
@ -253,22 +219,40 @@ static void coresight_trace_id_map_put_system_id(struct coresight_trace_id_map *
|
||||
|
||||
int coresight_trace_id_get_cpu_id(int cpu)
|
||||
{
|
||||
return coresight_trace_id_map_get_cpu_id(cpu, &id_map_default);
|
||||
return _coresight_trace_id_get_cpu_id(cpu, &id_map_default);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_get_cpu_id);
|
||||
|
||||
int coresight_trace_id_get_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
return _coresight_trace_id_get_cpu_id(cpu, id_map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_get_cpu_id_map);
|
||||
|
||||
void coresight_trace_id_put_cpu_id(int cpu)
|
||||
{
|
||||
coresight_trace_id_map_put_cpu_id(cpu, &id_map_default);
|
||||
_coresight_trace_id_put_cpu_id(cpu, &id_map_default);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_put_cpu_id);
|
||||
|
||||
void coresight_trace_id_put_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
_coresight_trace_id_put_cpu_id(cpu, id_map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_put_cpu_id_map);
|
||||
|
||||
int coresight_trace_id_read_cpu_id(int cpu)
|
||||
{
|
||||
return _coresight_trace_id_read_cpu_id(cpu);
|
||||
return _coresight_trace_id_read_cpu_id(cpu, &id_map_default);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_read_cpu_id);
|
||||
|
||||
int coresight_trace_id_read_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
return _coresight_trace_id_read_cpu_id(cpu, id_map);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_read_cpu_id_map);
|
||||
|
||||
int coresight_trace_id_get_system_id(void)
|
||||
{
|
||||
return coresight_trace_id_map_get_system_id(&id_map_default);
|
||||
@ -281,17 +265,17 @@ void coresight_trace_id_put_system_id(int id)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_put_system_id);
|
||||
|
||||
void coresight_trace_id_perf_start(void)
|
||||
void coresight_trace_id_perf_start(struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
atomic_inc(&perf_cs_etm_session_active);
|
||||
PERF_SESSION(atomic_read(&perf_cs_etm_session_active));
|
||||
atomic_inc(&id_map->perf_cs_etm_session_active);
|
||||
PERF_SESSION(atomic_read(&id_map->perf_cs_etm_session_active));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_perf_start);
|
||||
|
||||
void coresight_trace_id_perf_stop(void)
|
||||
void coresight_trace_id_perf_stop(struct coresight_trace_id_map *id_map)
|
||||
{
|
||||
if (!atomic_dec_return(&perf_cs_etm_session_active))
|
||||
coresight_trace_id_release_all_pending();
|
||||
PERF_SESSION(atomic_read(&perf_cs_etm_session_active));
|
||||
if (!atomic_dec_return(&id_map->perf_cs_etm_session_active))
|
||||
coresight_trace_id_release_all(id_map);
|
||||
PERF_SESSION(atomic_read(&id_map->perf_cs_etm_session_active));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_trace_id_perf_stop);
|
||||
|
@ -17,9 +17,10 @@
|
||||
* released when done.
|
||||
*
|
||||
* In order to ensure that a consistent cpu / ID matching is maintained
|
||||
* throughout a perf cs_etm event session - a session in progress flag will
|
||||
* be maintained, and released IDs not cleared until the perf session is
|
||||
* complete. This allows the same CPU to be re-allocated its prior ID.
|
||||
* throughout a perf cs_etm event session - a session in progress flag will be
|
||||
* maintained for each sink, and IDs are cleared when all the perf sessions
|
||||
* complete. This allows the same CPU to be re-allocated its prior ID when
|
||||
* events are scheduled in and out.
|
||||
*
|
||||
*
|
||||
* Trace ID maps will be created and initialised to prevent architecturally
|
||||
@ -32,10 +33,6 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
/* architecturally we have 128 IDs some of which are reserved */
|
||||
#define CORESIGHT_TRACE_IDS_MAX 128
|
||||
|
||||
/* ID 0 is reserved */
|
||||
#define CORESIGHT_TRACE_ID_RES_0 0
|
||||
|
||||
@ -46,23 +43,6 @@
|
||||
#define IS_VALID_CS_TRACE_ID(id) \
|
||||
((id > CORESIGHT_TRACE_ID_RES_0) && (id < CORESIGHT_TRACE_ID_RES_TOP))
|
||||
|
||||
/**
|
||||
* Trace ID map.
|
||||
*
|
||||
* @used_ids: Bitmap to register available (bit = 0) and in use (bit = 1) IDs.
|
||||
* Initialised so that the reserved IDs are permanently marked as
|
||||
* in use.
|
||||
* @pend_rel_ids: CPU IDs that have been released by the trace source but not
|
||||
* yet marked as available, to allow re-allocation to the same
|
||||
* CPU during a perf session.
|
||||
*/
|
||||
struct coresight_trace_id_map {
|
||||
DECLARE_BITMAP(used_ids, CORESIGHT_TRACE_IDS_MAX);
|
||||
DECLARE_BITMAP(pend_rel_ids, CORESIGHT_TRACE_IDS_MAX);
|
||||
};
|
||||
|
||||
/* Allocate and release IDs for a single default trace ID map */
|
||||
|
||||
/**
|
||||
* Read and optionally allocate a CoreSight trace ID and associate with a CPU.
|
||||
*
|
||||
@ -78,19 +58,27 @@ struct coresight_trace_id_map {
|
||||
*/
|
||||
int coresight_trace_id_get_cpu_id(int cpu);
|
||||
|
||||
/**
|
||||
* Version of coresight_trace_id_get_cpu_id() that allows the ID map to operate
|
||||
* on to be provided.
|
||||
*/
|
||||
int coresight_trace_id_get_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Release an allocated trace ID associated with the CPU.
|
||||
*
|
||||
* This will release the CoreSight trace ID associated with the CPU,
|
||||
* unless a perf session is in operation.
|
||||
*
|
||||
* If a perf session is in operation then the ID will be marked as pending
|
||||
* release.
|
||||
* This will release the CoreSight trace ID associated with the CPU.
|
||||
*
|
||||
* @cpu: The CPU index to release the associated trace ID.
|
||||
*/
|
||||
void coresight_trace_id_put_cpu_id(int cpu);
|
||||
|
||||
/**
|
||||
* Version of coresight_trace_id_put_cpu_id() that allows the ID map to operate
|
||||
* on to be provided.
|
||||
*/
|
||||
void coresight_trace_id_put_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Read the current allocated CoreSight Trace ID value for the CPU.
|
||||
*
|
||||
@ -111,6 +99,12 @@ void coresight_trace_id_put_cpu_id(int cpu);
|
||||
*/
|
||||
int coresight_trace_id_read_cpu_id(int cpu);
|
||||
|
||||
/**
|
||||
* Version of coresight_trace_id_read_cpu_id() that allows the ID map to operate
|
||||
* on to be provided.
|
||||
*/
|
||||
int coresight_trace_id_read_cpu_id_map(int cpu, struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Allocate a CoreSight trace ID for a system component.
|
||||
*
|
||||
@ -136,21 +130,21 @@ void coresight_trace_id_put_system_id(int id);
|
||||
/**
|
||||
* Notify the Trace ID allocator that a perf session is starting.
|
||||
*
|
||||
* Increase the perf session reference count - called by perf when setting up
|
||||
* a trace event.
|
||||
* Increase the perf session reference count - called by perf when setting up a
|
||||
* trace event.
|
||||
*
|
||||
* This reference count is used by the ID allocator to ensure that trace IDs
|
||||
* associated with a CPU cannot change or be released during a perf session.
|
||||
* Perf sessions never free trace IDs to ensure that the ID associated with a
|
||||
* CPU cannot change during their and other's concurrent sessions. Instead,
|
||||
* this refcount is used so that the last event to finish always frees all IDs.
|
||||
*/
|
||||
void coresight_trace_id_perf_start(void);
|
||||
void coresight_trace_id_perf_start(struct coresight_trace_id_map *id_map);
|
||||
|
||||
/**
|
||||
* Notify the ID allocator that a perf session is stopping.
|
||||
*
|
||||
* Decrease the perf session reference count.
|
||||
* if this causes the count to go to zero, then all Trace IDs marked as pending
|
||||
* release, will be released.
|
||||
* Decrease the perf session reference count. If this causes the count to go to
|
||||
* zero, then all Trace IDs will be released.
|
||||
*/
|
||||
void coresight_trace_id_perf_stop(void);
|
||||
void coresight_trace_id_perf_stop(struct coresight_trace_id_map *id_map);
|
||||
|
||||
#endif /* _CORESIGHT_TRACE_ID_H */
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user