Merge cf0c97f148 ("Merge tag 'pinctrl-v5.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl") into android-mainline
Baby steps to 5.8-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: Ia5ec011460c5041520483b43e129abbf4a298a99
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
What: /sys/devices/platform/firmware\:zynqmp-firmware/ggs*
|
||||
Date: March 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: "Jolly Shah" <jollys@xilinx.com>
|
||||
Description:
|
||||
Read/Write PMU global general storage register value,
|
||||
GLOBAL_GEN_STORAGE{0:3}.
|
||||
Global general storage register that can be used
|
||||
by system to pass information between masters.
|
||||
|
||||
The register is reset during system or power-on
|
||||
resets. Three registers are used by the FSBL and
|
||||
other Xilinx software products: GLOBAL_GEN_STORAGE{4:6}.
|
||||
|
||||
Usage:
|
||||
# cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
|
||||
# echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
|
||||
|
||||
Example:
|
||||
# cat /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
|
||||
# echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/ggs0
|
||||
|
||||
Users: Xilinx
|
||||
|
||||
What: /sys/devices/platform/firmware\:zynqmp-firmware/pggs*
|
||||
Date: March 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: "Jolly Shah" <jollys@xilinx.com>
|
||||
Description:
|
||||
Read/Write PMU persistent global general storage register
|
||||
value, PERS_GLOB_GEN_STORAGE{0:3}.
|
||||
Persistent global general storage register that
|
||||
can be used by system to pass information between
|
||||
masters.
|
||||
|
||||
This register is only reset by the power-on reset
|
||||
and maintains its value through a system reset.
|
||||
Four registers are used by the FSBL and other Xilinx
|
||||
software products: PERS_GLOB_GEN_STORAGE{4:7}.
|
||||
Register is reset only by a POR reset.
|
||||
|
||||
Usage:
|
||||
# cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
|
||||
# echo <value> > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
|
||||
|
||||
Example:
|
||||
# cat /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
|
||||
# echo 0x1234ABCD > /sys/devices/platform/firmware\:zynqmp-firmware/pggs0
|
||||
|
||||
Users: Xilinx
|
||||
|
||||
What: /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
|
||||
Date: March 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: "Jolly Shah" <jollys@xilinx.com>
|
||||
Description:
|
||||
This sysfs interface allows to set the shutdown scope for the
|
||||
next shutdown request. When the next shutdown is performed, the
|
||||
platform specific portion of PSCI-system_off can use the chosen
|
||||
shutdown scope.
|
||||
|
||||
Following are available shutdown scopes(subtypes):
|
||||
|
||||
subsystem: Only the APU along with all of its peripherals
|
||||
not used by other processing units will be
|
||||
shut down. This may result in the FPD power
|
||||
domain being shut down provided that no other
|
||||
processing unit uses FPD peripherals or DRAM.
|
||||
ps_only: The complete PS will be shut down, including the
|
||||
RPU, PMU, etc. Only the PL domain (FPGA)
|
||||
remains untouched.
|
||||
system: The complete system/device is shut down.
|
||||
|
||||
Usage:
|
||||
# cat /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
|
||||
# echo <scope> > /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
|
||||
|
||||
Example:
|
||||
# cat /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
|
||||
# echo "subsystem" > /sys/devices/platform/firmware\:zynqmp-firmware/shutdown_scope
|
||||
|
||||
Users: Xilinx
|
||||
|
||||
What: /sys/devices/platform/firmware\:zynqmp-firmware/health_status
|
||||
Date: March 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: "Jolly Shah" <jollys@xilinx.com>
|
||||
Description:
|
||||
This sysfs interface allows to set the health status. If PMUFW
|
||||
is compiled with CHECK_HEALTHY_BOOT, it will check the healthy
|
||||
bit on FPD WDT expiration. If healthy bit is set by a user
|
||||
application running in Linux, PMUFW will do APU only restart. If
|
||||
healthy bit is not set during FPD WDT expiration, PMUFW will do
|
||||
system restart.
|
||||
|
||||
Usage:
|
||||
Set healthy bit
|
||||
# echo 1 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status
|
||||
|
||||
Unset healthy bit
|
||||
# echo 0 > /sys/devices/platform/firmware\:zynqmp-firmware/health_status
|
||||
|
||||
Users: Xilinx
|
||||
@@ -8,6 +8,16 @@ Description: Sets the device address to be used for read or write through
|
||||
only when the IOMMU is disabled.
|
||||
The acceptable value is a string that starts with "0x"
|
||||
|
||||
What: /sys/kernel/debug/habanalabs/hl<n>/clk_gate
|
||||
Date: May 2020
|
||||
KernelVersion: 5.8
|
||||
Contact: oded.gabbay@gmail.com
|
||||
Description: Allow the root user to disable/enable in runtime the clock
|
||||
gating mechanism in Gaudi. Due to how Gaudi is built, the
|
||||
clock gating needs to be disabled in order to access the
|
||||
registers of the TPC and MME engines. This is sometimes needed
|
||||
during debug by the user and hence the user needs this option
|
||||
|
||||
What: /sys/kernel/debug/habanalabs/hl<n>/command_buffers
|
||||
Date: Jan 2019
|
||||
KernelVersion: 5.1
|
||||
@@ -150,3 +160,10 @@ KernelVersion: 5.1
|
||||
Contact: oded.gabbay@gmail.com
|
||||
Description: Displays a list with information about all the active virtual
|
||||
address mappings per ASID
|
||||
|
||||
What: /sys/kernel/debug/habanalabs/hl<n>/stop_on_err
|
||||
Date: Mar 2020
|
||||
KernelVersion: 5.6
|
||||
Contact: oded.gabbay@gmail.com
|
||||
Description: Sets the stop-on_error option for the device engines. Value of
|
||||
"0" is for disable, otherwise enable.
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
What: /sys/bus/event_source/devices/dfl_fmeX/format
|
||||
Date: April 2020
|
||||
KernelVersion: 5.8
|
||||
Contact: Wu Hao <hao.wu@intel.com>
|
||||
Description: Read-only. Attribute group to describe the magic bits
|
||||
that go into perf_event_attr.config for a particular pmu.
|
||||
(See ABI/testing/sysfs-bus-event_source-devices-format).
|
||||
|
||||
Each attribute under this group defines a bit range of the
|
||||
perf_event_attr.config. All supported attributes are listed
|
||||
below.
|
||||
|
||||
event = "config:0-11" - event ID
|
||||
evtype = "config:12-15" - event type
|
||||
portid = "config:16-23" - event source
|
||||
|
||||
For example,
|
||||
|
||||
fab_mmio_read = "event=0x06,evtype=0x02,portid=0xff"
|
||||
|
||||
It shows this fab_mmio_read is a fabric type (0x02) event with
|
||||
0x06 local event id for overall monitoring (portid=0xff).
|
||||
|
||||
What: /sys/bus/event_source/devices/dfl_fmeX/cpumask
|
||||
Date: April 2020
|
||||
KernelVersion: 5.8
|
||||
Contact: Wu Hao <hao.wu@intel.com>
|
||||
Description: Read-only. This file always returns cpu which the PMU is bound
|
||||
for access to all fme pmu performance monitoring events.
|
||||
|
||||
What: /sys/bus/event_source/devices/dfl_fmeX/events
|
||||
Date: April 2020
|
||||
KernelVersion: 5.8
|
||||
Contact: Wu Hao <hao.wu@intel.com>
|
||||
Description: Read-only. Attribute group to describe performance monitoring
|
||||
events specific to fme. Each attribute in this group describes
|
||||
a single performance monitoring event supported by this fme pmu.
|
||||
The name of the file is the name of the event.
|
||||
(See ABI/testing/sysfs-bus-event_source-devices-events).
|
||||
|
||||
All supported performance monitoring events are listed below.
|
||||
|
||||
Basic events (evtype=0x00)
|
||||
|
||||
clock = "event=0x00,evtype=0x00,portid=0xff"
|
||||
|
||||
Cache events (evtype=0x01)
|
||||
|
||||
cache_read_hit = "event=0x00,evtype=0x01,portid=0xff"
|
||||
cache_read_miss = "event=0x01,evtype=0x01,portid=0xff"
|
||||
cache_write_hit = "event=0x02,evtype=0x01,portid=0xff"
|
||||
cache_write_miss = "event=0x03,evtype=0x01,portid=0xff"
|
||||
cache_hold_request = "event=0x05,evtype=0x01,portid=0xff"
|
||||
cache_data_write_port_contention =
|
||||
"event=0x06,evtype=0x01,portid=0xff"
|
||||
cache_tag_write_port_contention =
|
||||
"event=0x07,evtype=0x01,portid=0xff"
|
||||
cache_tx_req_stall = "event=0x08,evtype=0x01,portid=0xff"
|
||||
cache_rx_req_stall = "event=0x09,evtype=0x01,portid=0xff"
|
||||
cache_eviction = "event=0x0a,evtype=0x01,portid=0xff"
|
||||
|
||||
Fabric events (evtype=0x02)
|
||||
|
||||
fab_pcie0_read = "event=0x00,evtype=0x02,portid=0xff"
|
||||
fab_pcie0_write = "event=0x01,evtype=0x02,portid=0xff"
|
||||
fab_pcie1_read = "event=0x02,evtype=0x02,portid=0xff"
|
||||
fab_pcie1_write = "event=0x03,evtype=0x02,portid=0xff"
|
||||
fab_upi_read = "event=0x04,evtype=0x02,portid=0xff"
|
||||
fab_upi_write = "event=0x05,evtype=0x02,portid=0xff"
|
||||
fab_mmio_read = "event=0x06,evtype=0x02,portid=0xff"
|
||||
fab_mmio_write = "event=0x07,evtype=0x02,portid=0xff"
|
||||
fab_port_pcie0_read = "event=0x00,evtype=0x02,portid=?"
|
||||
fab_port_pcie0_write = "event=0x01,evtype=0x02,portid=?"
|
||||
fab_port_pcie1_read = "event=0x02,evtype=0x02,portid=?"
|
||||
fab_port_pcie1_write = "event=0x03,evtype=0x02,portid=?"
|
||||
fab_port_upi_read = "event=0x04,evtype=0x02,portid=?"
|
||||
fab_port_upi_write = "event=0x05,evtype=0x02,portid=?"
|
||||
fab_port_mmio_read = "event=0x06,evtype=0x02,portid=?"
|
||||
fab_port_mmio_write = "event=0x07,evtype=0x02,portid=?"
|
||||
|
||||
VTD events (evtype=0x03)
|
||||
|
||||
vtd_port_read_transaction = "event=0x00,evtype=0x03,portid=?"
|
||||
vtd_port_write_transaction = "event=0x01,evtype=0x03,portid=?"
|
||||
vtd_port_devtlb_read_hit = "event=0x02,evtype=0x03,portid=?"
|
||||
vtd_port_devtlb_write_hit = "event=0x03,evtype=0x03,portid=?"
|
||||
vtd_port_devtlb_4k_fill = "event=0x04,evtype=0x03,portid=?"
|
||||
vtd_port_devtlb_2m_fill = "event=0x05,evtype=0x03,portid=?"
|
||||
vtd_port_devtlb_1g_fill = "event=0x06,evtype=0x03,portid=?"
|
||||
|
||||
VTD SIP events (evtype=0x04)
|
||||
|
||||
vtd_sip_iotlb_4k_hit = "event=0x00,evtype=0x04,portid=0xff"
|
||||
vtd_sip_iotlb_2m_hit = "event=0x01,evtype=0x04,portid=0xff"
|
||||
vtd_sip_iotlb_1g_hit = "event=0x02,evtype=0x04,portid=0xff"
|
||||
vtd_sip_slpwc_l3_hit = "event=0x03,evtype=0x04,portid=0xff"
|
||||
vtd_sip_slpwc_l4_hit = "event=0x04,evtype=0x04,portid=0xff"
|
||||
vtd_sip_rcc_hit = "event=0x05,evtype=0x04,portid=0xff"
|
||||
vtd_sip_iotlb_4k_miss = "event=0x06,evtype=0x04,portid=0xff"
|
||||
vtd_sip_iotlb_2m_miss = "event=0x07,evtype=0x04,portid=0xff"
|
||||
vtd_sip_iotlb_1g_miss = "event=0x08,evtype=0x04,portid=0xff"
|
||||
vtd_sip_slpwc_l3_miss = "event=0x09,evtype=0x04,portid=0xff"
|
||||
vtd_sip_slpwc_l4_miss = "event=0x0a,evtype=0x04,portid=0xff"
|
||||
vtd_sip_rcc_miss = "event=0x0b,evtype=0x04,portid=0xff"
|
||||
@@ -0,0 +1,10 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity_nearlevel
|
||||
Date: March 2020
|
||||
KernelVersion: 5.7
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Near level for proximity sensors. This is a single integer
|
||||
value that tells user space when an object should be
|
||||
considered close to the device. If the value read from the
|
||||
sensor is above or equal to the value in this file an object
|
||||
should typically be considered near.
|
||||
@@ -0,0 +1,10 @@
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity3_comb_raw
|
||||
Date: February 2019
|
||||
KernelVersion: 5.6
|
||||
Contact: Daniel Campello <campello@chromium.org>
|
||||
Description:
|
||||
Proximity measurement indicating that some object is
|
||||
near the combined sensor. The combined sensor presents
|
||||
proximity measurements constructed by hardware by
|
||||
combining measurements taken from a given set of
|
||||
physical sensors.
|
||||
@@ -1,14 +1,14 @@
|
||||
What: /sys/bus/most/devices/.../description
|
||||
What: /sys/bus/most/devices/<dev>/description
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Provides information about the interface type and the physical
|
||||
location of the device. Hardware attached via USB, for instance,
|
||||
Provides information about the physical location of the
|
||||
device. Hardware attached via USB, for instance,
|
||||
might return <1-1.1:1.0>
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../interface
|
||||
What: /sys/bus/most/devices/<dev>/interface
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -16,7 +16,7 @@ Description:
|
||||
Indicates the type of peripheral interface the device uses.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci
|
||||
What: /sys/bus/most/devices/<dev>/dci
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -26,7 +26,7 @@ Description:
|
||||
write the controller's DCI registers.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/arb_address
|
||||
What: /sys/bus/most/devices/<dev>/dci/arb_address
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -35,7 +35,7 @@ Description:
|
||||
application wants to read from or write to.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/arb_value
|
||||
What: /sys/bus/most/devices/<dev>/dci/arb_value
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -44,7 +44,7 @@ Description:
|
||||
is stored in arb_address.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_eui48_hi
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_eui48_hi
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -52,7 +52,7 @@ Description:
|
||||
This is used to check and configure the MAC address.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_eui48_lo
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_eui48_lo
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -60,7 +60,7 @@ Description:
|
||||
This is used to check and configure the MAC address.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_eui48_mi
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_eui48_mi
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -68,7 +68,7 @@ Description:
|
||||
This is used to check and configure the MAC address.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_filter
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_filter
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -76,7 +76,7 @@ Description:
|
||||
This is used to check and configure the MEP filter address.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_hash0
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_hash0
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -84,7 +84,7 @@ Description:
|
||||
This is used to check and configure the MEP hash table.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_hash1
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_hash1
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -92,7 +92,7 @@ Description:
|
||||
This is used to check and configure the MEP hash table.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_hash2
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_hash2
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -100,7 +100,7 @@ Description:
|
||||
This is used to check and configure the MEP hash table.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/mep_hash3
|
||||
What: /sys/bus/most/devices/<dev>/dci/mep_hash3
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -108,7 +108,7 @@ Description:
|
||||
This is used to check and configure the MEP hash table.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/ni_state
|
||||
What: /sys/bus/most/devices/<dev>/dci/ni_state
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -116,7 +116,7 @@ Description:
|
||||
Indicates the current network interface state.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/node_address
|
||||
What: /sys/bus/most/devices/<dev>/dci/node_address
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -124,7 +124,7 @@ Description:
|
||||
Indicates the current node address.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/node_position
|
||||
What: /sys/bus/most/devices/<dev>/dci/node_position
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -132,7 +132,7 @@ Description:
|
||||
Indicates the current node position.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/packet_bandwidth
|
||||
What: /sys/bus/most/devices/<dev>/dci/packet_bandwidth
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -140,7 +140,7 @@ Description:
|
||||
Indicates the configured packet bandwidth.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../dci/sync_ep
|
||||
What: /sys/bus/most/devices/<dev>/dci/sync_ep
|
||||
Date: June 2016
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -149,7 +149,7 @@ Description:
|
||||
endpoint.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
@@ -160,91 +160,92 @@ Description:
|
||||
configure it.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/available_datatypes
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/available_datatypes
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Indicates the data types the current channel can transport.
|
||||
Indicates the data types the channel can transport.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/available_directions
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/available_directions
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Indicates the directions the current channel is capable of.
|
||||
Indicates the directions the channel is capable of.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/number_of_packet_buffers
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/number_of_packet_buffers
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Indicates the number of packet buffers the current channel can
|
||||
Indicates the number of packet buffers the channel can
|
||||
handle.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/number_of_stream_buffers
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/number_of_stream_buffers
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Indicates the number of streaming buffers the current channel can
|
||||
Indicates the number of streaming buffers the channel can
|
||||
handle.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/size_of_packet_buffer
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/size_of_packet_buffer
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Indicates the size of a packet buffer the current channel can
|
||||
Indicates the size of a packet buffer the channel can
|
||||
handle.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/size_of_stream_buffer
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/size_of_stream_buffer
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Indicates the size of a streaming buffer the current channel can
|
||||
Indicates the size of a streaming buffer the channel can
|
||||
handle.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/set_number_of_buffers
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/set_number_of_buffers
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
This is to configure the number of buffers of the current channel.
|
||||
This is to read back the configured number of buffers of
|
||||
the channel.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/set_buffer_size
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/set_buffer_size
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
This is to configure the size of a buffer of the current channel.
|
||||
This is to read back the configured buffer size of the channel.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/set_direction
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/set_direction
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
This is to configure the direction of the current channel.
|
||||
This is to read back the configured direction of the channel.
|
||||
The following strings will be accepted:
|
||||
'dir_tx',
|
||||
'dir_rx'
|
||||
'tx',
|
||||
'rx'
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/set_datatype
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/set_datatype
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
This is to configure the data type of the current channel.
|
||||
This is to read back the configured data type of the channel.
|
||||
The following strings will be accepted:
|
||||
'control',
|
||||
'async',
|
||||
@@ -252,30 +253,31 @@ Description:
|
||||
'isoc_avp'
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/set_subbuffer_size
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/set_subbuffer_size
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
This is to configure the subbuffer size of the current channel.
|
||||
This is to read back the configured subbuffer size of
|
||||
the channel.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/set_packets_per_xact
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/set_packets_per_xact
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
This is to configure the number of packets per transaction of
|
||||
the current channel. This is only needed network interface
|
||||
controller is attached via USB.
|
||||
This is to read back the configured number of packets per
|
||||
transaction of the channel. This is only applicable when
|
||||
connected via USB.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/devices/.../<channel>/channel_starving
|
||||
What: /sys/bus/most/devices/<dev>/<channel>/channel_starving
|
||||
Date: March 2017
|
||||
KernelVersion: 4.15
|
||||
Contact: Christian Gromm <christian.gromm@microchip.com>
|
||||
Description:
|
||||
Indicates whether current channel ran out of buffers.
|
||||
Indicates whether channel ran out of buffers.
|
||||
Users:
|
||||
|
||||
What: /sys/bus/most/drivers/most_core/components
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
What: /sys/bus/soundwire/devices/sdw-master-N/revision
|
||||
/sys/bus/soundwire/devices/sdw-master-N/clk_stop_modes
|
||||
/sys/bus/soundwire/devices/sdw-master-N/clk_freq
|
||||
/sys/bus/soundwire/devices/sdw-master-N/clk_gears
|
||||
/sys/bus/soundwire/devices/sdw-master-N/default_col
|
||||
/sys/bus/soundwire/devices/sdw-master-N/default_frame_rate
|
||||
/sys/bus/soundwire/devices/sdw-master-N/default_row
|
||||
/sys/bus/soundwire/devices/sdw-master-N/dynamic_shape
|
||||
/sys/bus/soundwire/devices/sdw-master-N/err_threshold
|
||||
/sys/bus/soundwire/devices/sdw-master-N/max_clk_freq
|
||||
|
||||
Date: April 2020
|
||||
|
||||
Contact: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Bard Liao <yung-chuan.liao@linux.intel.com>
|
||||
Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
Description: SoundWire Master-N DisCo properties.
|
||||
These properties are defined by MIPI DisCo Specification
|
||||
for SoundWire. They define various properties of the Master
|
||||
and are used by the bus to configure the Master. clk_stop_modes
|
||||
is a bitmask for simplifications and combines the
|
||||
clock-stop-mode0 and clock-stop-mode1 properties.
|
||||
@@ -0,0 +1,91 @@
|
||||
What: /sys/bus/soundwire/devices/sdw:.../dev-properties/mipi_revision
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/wake_capable
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/test_mode_capable
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/clk_stop_mode1
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/simple_clk_stop_capable
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/clk_stop_timeout
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/ch_prep_timeout
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/reset_behave
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/high_PHY_capable
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/paging_support
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/bank_delay_support
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/p15_behave
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/master_count
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/source_ports
|
||||
/sys/bus/soundwire/devices/sdw:.../dev-properties/sink_ports
|
||||
|
||||
Date: May 2020
|
||||
|
||||
Contact: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Bard Liao <yung-chuan.liao@linux.intel.com>
|
||||
Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
Description: SoundWire Slave DisCo properties.
|
||||
These properties are defined by MIPI DisCo Specification
|
||||
for SoundWire. They define various properties of the
|
||||
SoundWire Slave and are used by the bus to configure
|
||||
the Slave
|
||||
|
||||
|
||||
What: /sys/bus/soundwire/devices/sdw:.../dp0/max_word
|
||||
/sys/bus/soundwire/devices/sdw:.../dp0/min_word
|
||||
/sys/bus/soundwire/devices/sdw:.../dp0/words
|
||||
/sys/bus/soundwire/devices/sdw:.../dp0/BRA_flow_controlled
|
||||
/sys/bus/soundwire/devices/sdw:.../dp0/simple_ch_prep_sm
|
||||
/sys/bus/soundwire/devices/sdw:.../dp0/imp_def_interrupts
|
||||
|
||||
Date: May 2020
|
||||
|
||||
Contact: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Bard Liao <yung-chuan.liao@linux.intel.com>
|
||||
Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
Description: SoundWire Slave Data Port-0 DisCo properties.
|
||||
These properties are defined by MIPI DisCo Specification
|
||||
for the SoundWire. They define various properties of the
|
||||
Data port 0 are used by the bus to configure the Data Port 0.
|
||||
|
||||
|
||||
What: /sys/bus/soundwire/devices/sdw:.../dpN_src/max_word
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/min_word
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/words
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/type
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/max_grouping
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/simple_ch_prep_sm
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/ch_prep_timeout
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/imp_def_interrupts
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/min_ch
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/max_ch
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/channels
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/ch_combinations
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/max_async_buffer
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/block_pack_mode
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_src/port_encoding
|
||||
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_word
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/min_word
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/words
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/type
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_grouping
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/simple_ch_prep_sm
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/ch_prep_timeout
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/imp_def_interrupts
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/min_ch
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_ch
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/channels
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/ch_combinations
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/max_async_buffer
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/block_pack_mode
|
||||
/sys/bus/soundwire/devices/sdw:.../dpN_sink/port_encoding
|
||||
|
||||
Date: May 2020
|
||||
|
||||
Contact: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
|
||||
Bard Liao <yung-chuan.liao@linux.intel.com>
|
||||
Vinod Koul <vkoul@kernel.org>
|
||||
|
||||
Description: SoundWire Slave Data Source/Sink Port-N DisCo properties.
|
||||
These properties are defined by MIPI DisCo Specification
|
||||
for SoundWire. They define various properties of the
|
||||
Source/Sink Data port N and are used by the bus to configure
|
||||
the Data Port N.
|
||||
@@ -10,6 +10,23 @@ KernelVersion: 5.1
|
||||
Contact: oded.gabbay@gmail.com
|
||||
Description: Version of the application running on the device's CPU
|
||||
|
||||
What: /sys/class/habanalabs/hl<n>/clk_max_freq_mhz
|
||||
Date: Jun 2019
|
||||
KernelVersion: not yet upstreamed
|
||||
Contact: oded.gabbay@gmail.com
|
||||
Description: Allows the user to set the maximum clock frequency, in MHz.
|
||||
The device clock might be set to lower value than the maximum.
|
||||
The user should read the clk_cur_freq_mhz to see the actual
|
||||
frequency value of the device clock. This property is valid
|
||||
only for the Gaudi ASIC family
|
||||
|
||||
What: /sys/class/habanalabs/hl<n>/clk_cur_freq_mhz
|
||||
Date: Jun 2019
|
||||
KernelVersion: not yet upstreamed
|
||||
Contact: oded.gabbay@gmail.com
|
||||
Description: Displays the current frequency, in MHz, of the device clock.
|
||||
This property is valid only for the Gaudi ASIC family
|
||||
|
||||
What: /sys/class/habanalabs/hl<n>/cpld_ver
|
||||
Date: Jan 2019
|
||||
KernelVersion: 5.1
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
What: /sys/bus/w1/devices/.../alarms
|
||||
Date: May 2020
|
||||
Contact: Akira Shimahara <akira215corp@gmail.com>
|
||||
Description:
|
||||
(RW) read or write TH and TL (Temperature High an Low) alarms.
|
||||
Values shall be space separated and in the device range
|
||||
(typical -55 degC to 125 degC), if not values will be trimmed
|
||||
to device min/max capabilities. Values are integer as they are
|
||||
stored in a 8bit register in the device. Lowest value is
|
||||
automatically put to TL. Once set, alarms could be search at
|
||||
master level, refer to Documentation/w1/w1_generic.rst for
|
||||
detailed information
|
||||
Users: any user space application which wants to communicate with
|
||||
w1_term device
|
||||
|
||||
|
||||
What: /sys/bus/w1/devices/.../eeprom
|
||||
Date: May 2020
|
||||
Contact: Akira Shimahara <akira215corp@gmail.com>
|
||||
Description:
|
||||
(WO) writing that file will either trigger a save of the
|
||||
device data to its embedded EEPROM, either restore data
|
||||
embedded in device EEPROM. Be aware that devices support
|
||||
limited EEPROM writing cycles (typical 50k)
|
||||
* 'save': save device RAM to EEPROM
|
||||
* 'restore': restore EEPROM data in device RAM
|
||||
Users: any user space application which wants to communicate with
|
||||
w1_term device
|
||||
|
||||
|
||||
What: /sys/bus/w1/devices/.../ext_power
|
||||
Date: May 2020
|
||||
Contact: Akira Shimahara <akira215corp@gmail.com>
|
||||
Description:
|
||||
(RO) return the power status by asking the device
|
||||
* '0': device parasite powered
|
||||
* '1': device externally powered
|
||||
* '-xx': xx is kernel error when reading power status
|
||||
Users: any user space application which wants to communicate with
|
||||
w1_term device
|
||||
|
||||
|
||||
What: /sys/bus/w1/devices/.../resolution
|
||||
Date: May 2020
|
||||
Contact: Akira Shimahara <akira215corp@gmail.com>
|
||||
Description:
|
||||
(RW) get or set the device resolution (on supported devices,
|
||||
if not, this entry is not present). Note that the resolution
|
||||
will be changed only in device RAM, so it will be cleared when
|
||||
power is lost. Trigger a 'save' to EEPROM command to keep
|
||||
values after power-on. Read or write are :
|
||||
* '9..12': device resolution in bit
|
||||
or resolution to set in bit
|
||||
* '-xx': xx is kernel error when reading the resolution
|
||||
* Anything else: do nothing
|
||||
Users: any user space application which wants to communicate with
|
||||
w1_term device
|
||||
|
||||
|
||||
What: /sys/bus/w1/devices/.../temperature
|
||||
Date: May 2020
|
||||
Contact: Akira Shimahara <akira215corp@gmail.com>
|
||||
Description:
|
||||
(RO) return the temperature in 1/1000 degC.
|
||||
* If a bulk read has been triggered, it will directly
|
||||
return the temperature computed when the bulk read
|
||||
occurred, if available. If not yet available, nothing
|
||||
is returned (a debug kernel message is sent), you
|
||||
should retry later on.
|
||||
* If no bulk read has been triggered, it will trigger
|
||||
a conversion and send the result. Note that the
|
||||
conversion duration depend on the resolution (if
|
||||
device support this feature). It takes 94ms in 9bits
|
||||
resolution, 750ms for 12bits.
|
||||
Users: any user space application which wants to communicate with
|
||||
w1_term device
|
||||
|
||||
|
||||
What: /sys/bus/w1/devices/.../w1_slave
|
||||
Date: May 2020
|
||||
Contact: Akira Shimahara <akira215corp@gmail.com>
|
||||
Description:
|
||||
(RW) return the temperature in 1/1000 degC.
|
||||
*read*: return 2 lines with the hexa output data sent on the
|
||||
bus, return the CRC check and temperature in 1/1000 degC
|
||||
*write* :
|
||||
* '0' : save the 2 or 3 bytes to the device EEPROM
|
||||
(i.e. TH, TL and config register)
|
||||
* '9..12' : set the device resolution in RAM
|
||||
(if supported)
|
||||
* Anything else: do nothing
|
||||
refer to Documentation/w1/slaves/w1_therm.rst for detailed
|
||||
information.
|
||||
Users: any user space application which wants to communicate with
|
||||
w1_term device
|
||||
|
||||
|
||||
What: /sys/bus/w1/devices/w1_bus_masterXX/therm_bulk_read
|
||||
Date: May 2020
|
||||
Contact: Akira Shimahara <akira215corp@gmail.com>
|
||||
Description:
|
||||
(RW) trigger a bulk read conversion. read the status
|
||||
*read*:
|
||||
* '-1': conversion in progress on at least 1 sensor
|
||||
* '1' : conversion complete but at least one sensor
|
||||
value has not been read yet
|
||||
* '0' : no bulk operation. Reading temperature will
|
||||
trigger a conversion on each device
|
||||
*write*: 'trigger': trigger a bulk read on all supporting
|
||||
devices on the bus
|
||||
Note that if a bulk read is sent but one sensor is not read
|
||||
immediately, the next access to temperature on this device
|
||||
will return the temperature measured at the time of issue
|
||||
of the bulk read command (not the current temperature).
|
||||
Users: any user space application which wants to communicate with
|
||||
w1_term device
|
||||
@@ -231,13 +231,13 @@ prints help, and C) an action_msg string, that will print right before your
|
||||
handler is called. Your handler must conform to the prototype in 'sysrq.h'.
|
||||
|
||||
After the ``sysrq_key_op`` is created, you can call the kernel function
|
||||
``register_sysrq_key(int key, struct sysrq_key_op *op_p);`` this will
|
||||
``register_sysrq_key(int key, const struct sysrq_key_op *op_p);`` this will
|
||||
register the operation pointed to by ``op_p`` at table key 'key',
|
||||
if that slot in the table is blank. At module unload time, you must call
|
||||
the function ``unregister_sysrq_key(int key, struct sysrq_key_op *op_p)``, which
|
||||
will remove the key op pointed to by 'op_p' from the key 'key', if and only if
|
||||
it is currently registered in that slot. This is in case the slot has been
|
||||
overwritten since you registered it.
|
||||
the function ``unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)``,
|
||||
which will remove the key op pointed to by 'op_p' from the key 'key', if and
|
||||
only if it is currently registered in that slot. This is in case the slot has
|
||||
been overwritten since you registered it.
|
||||
|
||||
The Magic SysRQ system works by registering key operations against a key op
|
||||
lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
|
||||
|
||||
@@ -108,7 +108,8 @@ This binding uses the i.MX common pinctrl binding[3].
|
||||
Required properties:
|
||||
- compatible: Should be one of:
|
||||
"fsl,imx8qm-iomuxc",
|
||||
"fsl,imx8qxp-iomuxc".
|
||||
"fsl,imx8qxp-iomuxc",
|
||||
"fsl,imx8dxl-iomuxc".
|
||||
|
||||
Required properties for Pinctrl sub nodes:
|
||||
- fsl,pins: Each entry consists of 3 integers which represents
|
||||
@@ -116,7 +117,8 @@ Required properties for Pinctrl sub nodes:
|
||||
integers <pin_id mux_mode> are specified using a
|
||||
PIN_FUNC_ID macro, which can be found in
|
||||
<dt-bindings/pinctrl/pads-imx8qm.h>,
|
||||
<dt-bindings/pinctrl/pads-imx8qxp.h>.
|
||||
<dt-bindings/pinctrl/pads-imx8qxp.h>,
|
||||
<dt-bindings/pinctrl/pads-imx8dxl.h>.
|
||||
The last integer CONFIG is the pad setting value like
|
||||
pull-up on this pin.
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ Required properties:
|
||||
The svc node has the following mandatory properties, must be located under
|
||||
the firmware node.
|
||||
|
||||
- compatible: "intel,stratix10-svc"
|
||||
- compatible: "intel,stratix10-svc" or "intel,agilex-svc"
|
||||
- method: smc or hvc
|
||||
smc - Secure Monitor Call
|
||||
hvc - Hypervisor Call
|
||||
|
||||
@@ -4,7 +4,8 @@ Required properties:
|
||||
The fpga_mgr node has the following mandatory property, must be located under
|
||||
firmware/svc node.
|
||||
|
||||
- compatible : should contain "intel,stratix10-soc-fpga-mgr"
|
||||
- compatible : should contain "intel,stratix10-soc-fpga-mgr" or
|
||||
"intel,agilex-soc-fpga-mgr"
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
* Bosch BMA180 / BMA25x triaxial acceleration sensor
|
||||
* Bosch BMA023 / BMA150/ BMA180 / BMA25x / SMB380 triaxial acceleration sensor
|
||||
|
||||
https://media.digikey.com/pdf/Data%20Sheets/Bosch/BMA150.pdf
|
||||
http://omapworld.com/BMA180_111_1002839.pdf
|
||||
http://ae-bst.resource.bosch.com/media/products/dokumente/bma250/bst-bma250-ds002-05.pdf
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be one of:
|
||||
"bosch,bma023"
|
||||
"bosch,bma150"
|
||||
"bosch,bma180"
|
||||
"bosch,bma250"
|
||||
"bosch,bma254"
|
||||
"bosch,smb380"
|
||||
- reg : the I2C address of the sensor
|
||||
- vdd-supply : regulator phandle connected to the VDD pin
|
||||
- vddio-supply : regulator phandle connected to the VDDIO pin
|
||||
|
||||
Optional properties:
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,ad9467.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD9467 High-Speed ADC
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
|
||||
description: |
|
||||
The AD9467 is a 16-bit, monolithic, IF sampling analog-to-digital
|
||||
converter (ADC).
|
||||
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/AD9467.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad9467
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: adc-clk
|
||||
|
||||
powerdown-gpios:
|
||||
description:
|
||||
Pin that controls the powerdown mode of the device.
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Reset pin for the device.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,ad9467";
|
||||
reg = <0>;
|
||||
clocks = <&adc_clk>;
|
||||
clock-names = "adc-clk";
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,axi-adc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AXI ADC IP core
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Alexandru Ardelean <alexandru.ardelean@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices Generic AXI ADC IP core for interfacing an ADC device
|
||||
with a high speed serial (JESD204B/C) or source synchronous parallel
|
||||
interface (LVDS/CMOS).
|
||||
Usually, some other interface type (i.e SPI) is used as a control
|
||||
interface for the actual ADC, while this IP core will interface
|
||||
to the data-lines of the ADC and handle the streaming of data into
|
||||
memory via DMA.
|
||||
|
||||
https://wiki.analog.com/resources/fpga/docs/axi_adc_ip
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,axi-adc-10.0.a
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx
|
||||
|
||||
adi,adc-dev:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
A reference to a the actual ADC to which this FPGA ADC interfaces to.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- dmas
|
||||
- reg
|
||||
- adi,adc-dev
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
axi-adc@44a00000 {
|
||||
compatible = "adi,axi-adc-10.0.a";
|
||||
reg = <0x44a00000 0x10000>;
|
||||
dmas = <&rx_dma 0>;
|
||||
dma-names = "rx";
|
||||
|
||||
adi,adc-dev = <&spi_adc>;
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,63 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright 2020 Alexandru Lazar
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/maxim,max1241.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Maxim MAX1241 12-bit, single-channel analog to digital converter
|
||||
|
||||
maintainers:
|
||||
- Alexandru Lazar <alazar@startmail.com>
|
||||
|
||||
description: |
|
||||
Bindings for the max1241 12-bit, single-channel ADC device. Datasheet
|
||||
can be found at:
|
||||
https://datasheets.maximintegrated.com/en/ds/MAX1240-MAX1241.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- maxim,max1241
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
Device tree identifier of the regulator that powers the ADC.
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
Device tree identifier of the regulator that provides the external
|
||||
reference voltage.
|
||||
|
||||
shutdown-gpios:
|
||||
description:
|
||||
GPIO spec for the GPIO pin connected to the ADC's /SHDN pin. If
|
||||
specified, the /SHDN pin will be asserted between conversions,
|
||||
thus enabling power-down mode.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vref-supply
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "maxim,max1241";
|
||||
reg = <0>;
|
||||
vdd-supply = <&adc_vdd>;
|
||||
vref-supply = <&adc_vref>;
|
||||
spi-max-frequency = <1000000>;
|
||||
shutdown-gpios = <&gpio 26 1>;
|
||||
};
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
Rockchip Successive Approximation Register (SAR) A/D Converter bindings
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "rockchip,<name>-saradc" or "rockchip,rk3066-tsadc"
|
||||
- "rockchip,saradc": for rk3188, rk3288
|
||||
- "rockchip,rk3066-tsadc": for rk3036
|
||||
- "rockchip,rk3328-saradc", "rockchip,rk3399-saradc": for rk3328
|
||||
- "rockchip,rk3399-saradc": for rk3399
|
||||
- "rockchip,rv1108-saradc", "rockchip,rk3399-saradc": for rv1108
|
||||
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: The interrupt number to the cpu. The interrupt specifier format
|
||||
depends on the interrupt controller.
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
- clock-names: Shall be "saradc" for the converter-clock, and "apb_pclk" for
|
||||
the peripheral clock.
|
||||
- vref-supply: The regulator supply ADC reference voltage.
|
||||
- #io-channel-cells: Should be 1, see ../iio-bindings.txt
|
||||
|
||||
Optional properties:
|
||||
- resets: Must contain an entry for each entry in reset-names if need support
|
||||
this option. See ../reset/reset.txt for details.
|
||||
- reset-names: Must include the name "saradc-apb".
|
||||
|
||||
Example:
|
||||
saradc: saradc@2006c000 {
|
||||
compatible = "rockchip,saradc";
|
||||
reg = <0x2006c000 0x100>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
|
||||
clock-names = "saradc", "apb_pclk";
|
||||
resets = <&cru SRST_SARADC>;
|
||||
reset-names = "saradc-apb";
|
||||
#io-channel-cells = <1>;
|
||||
vref-supply = <&vcc18>;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/rockchip-saradc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip Successive Approximation Register (SAR) A/D Converter
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: rockchip,saradc
|
||||
- const: rockchip,rk3066-tsadc
|
||||
- const: rockchip,rk3399-saradc
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-saradc
|
||||
- rockchip,rk3308-saradc
|
||||
- rockchip,rk3328-saradc
|
||||
- rockchip,rv1108-saradc
|
||||
- const: rockchip,rk3399-saradc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: converter clock
|
||||
- description: peripheral clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: saradc
|
||||
- const: apb_pclk
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
reset-names:
|
||||
const: saradc-apb
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
The regulator supply for the ADC reference voltage.
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- vref-supply
|
||||
- "#io-channel-cells"
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rk3288-cru.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
saradc: saradc@2006c000 {
|
||||
compatible = "rockchip,saradc";
|
||||
reg = <0x2006c000 0x100>;
|
||||
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
|
||||
clock-names = "saradc", "apb_pclk";
|
||||
resets = <&cru SRST_SARADC>;
|
||||
reset-names = "saradc-apb";
|
||||
vref-supply = <&vcc18>;
|
||||
#io-channel-cells = <1>;
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/chemical/ams,ccs811.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: AMS CCS811 VOC Sensor
|
||||
|
||||
maintainers:
|
||||
- Narcisa Vasile <narcisaanamaria12@gmail.com>
|
||||
|
||||
description: |
|
||||
Ultra-Low Power Digital Gas Sensor for Monitoring Indoor Air Quality.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ams,ccs811
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO connected to the nRESET line. This is an active low
|
||||
input to CCS811.
|
||||
maxItems: 1
|
||||
|
||||
wakeup-gpios:
|
||||
description: GPIO connected to the nWAKE line. This is an active low
|
||||
input to CCS811.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
voc@5b {
|
||||
compatible = "ams,ccs811";
|
||||
reg = <0x5b>;
|
||||
reset-gpios = <&gpioa 11 GPIO_ACTIVE_LOW>;
|
||||
wakeup-gpios = <&gpioa 12 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -4,19 +4,21 @@
|
||||
$id: http://devicetree.org/schemas/iio/chemical/atlas,sensor.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Atlas Scientific OEM sensors
|
||||
title: Atlas Scientific OEM + EZO sensors
|
||||
|
||||
maintainers:
|
||||
- Matt Ranostay <matt.ranostay@konsulko.com>
|
||||
|
||||
description: |
|
||||
Atlas Scientific OEM sensors connected via I2C
|
||||
Atlas Scientific OEM + EZO sensors connected via I2C
|
||||
|
||||
Datasheets:
|
||||
http://www.atlas-scientific.com/_files/_datasheets/_oem/DO_oem_datasheet.pdf
|
||||
http://www.atlas-scientific.com/_files/_datasheets/_oem/EC_oem_datasheet.pdf
|
||||
http://www.atlas-scientific.com/_files/_datasheets/_oem/ORP_oem_datasheet.pdf
|
||||
http://www.atlas-scientific.com/_files/_datasheets/_oem/pH_oem_datasheet.pdf
|
||||
http://www.atlas-scientific.com/_files/_datasheets/_oem/RTD_oem_datasheet.pdf
|
||||
http://www.atlas-scientific.com/_files/_datasheets/_probe/EZO_CO2_Datasheet.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@@ -25,6 +27,8 @@ properties:
|
||||
- atlas,ec-sm
|
||||
- atlas,orp-sm
|
||||
- atlas,ph-sm
|
||||
- atlas,rtd-sm
|
||||
- atlas,co2-ezo
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/common.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common properties for iio sensors
|
||||
|
||||
maintainers:
|
||||
- Jonathan Cameron <jic23@kernel.org>
|
||||
- Guido Günther <agx@sigxcpu.org>
|
||||
|
||||
description: |
|
||||
This document defines device tree properties common to several iio
|
||||
sensors. It doesn't constitue a device tree binding specification by itself but
|
||||
is meant to be referenced by device tree bindings.
|
||||
|
||||
When referenced from sensor tree bindings the properties defined in this
|
||||
document are defined as follows. The sensor tree bindings are responsible for
|
||||
defining whether each property is required or optional.
|
||||
|
||||
properties:
|
||||
proximity-near-level:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
For proximity sensors whether an object can be considered near to the
|
||||
device depends on parameters like sensor position, covering glass and
|
||||
aperture. This value gives an indication to userspace for which
|
||||
sensor readings this is the case.
|
||||
|
||||
Raw proximity values equal or above this level should be
|
||||
considered 'near' to the device (an object is near to the
|
||||
sensor).
|
||||
|
||||
...
|
||||
@@ -1,4 +1,4 @@
|
||||
Linear Technology LTC2632/2636 DAC
|
||||
Linear Technology LTC2632/2634/2636 DAC
|
||||
|
||||
Required properties:
|
||||
- compatible: Has to contain one of the following:
|
||||
@@ -8,6 +8,12 @@ Required properties:
|
||||
lltc,ltc2632-h12
|
||||
lltc,ltc2632-h10
|
||||
lltc,ltc2632-h8
|
||||
lltc,ltc2634-l12
|
||||
lltc,ltc2634-l10
|
||||
lltc,ltc2634-l8
|
||||
lltc,ltc2634-h12
|
||||
lltc,ltc2634-h10
|
||||
lltc,ltc2634-h8
|
||||
lltc,ltc2636-l12
|
||||
lltc,ltc2636-l10
|
||||
lltc,ltc2636-l8
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
STMicroelectronics STM32 DAC
|
||||
|
||||
The STM32 DAC is a 12-bit voltage output digital-to-analog converter. The DAC
|
||||
may be configured in 8 or 12-bit mode. It has two output channels, each with
|
||||
its own converter.
|
||||
It has built-in noise and triangle waveform generator and supports external
|
||||
triggers for conversions. The DAC's output buffer allows a high drive output
|
||||
current.
|
||||
|
||||
Contents of a stm32 dac root node:
|
||||
-----------------------------------
|
||||
Required properties:
|
||||
- compatible: Should be one of:
|
||||
"st,stm32f4-dac-core"
|
||||
"st,stm32h7-dac-core"
|
||||
- reg: Offset and length of the device's register set.
|
||||
- clocks: Must contain an entry for pclk (which feeds the peripheral bus
|
||||
interface)
|
||||
- clock-names: Must be "pclk".
|
||||
- vref-supply: Phandle to the vref+ input analog reference supply.
|
||||
- #address-cells = <1>;
|
||||
- #size-cells = <0>;
|
||||
|
||||
Optional properties:
|
||||
- resets: Must contain the phandle to the reset controller.
|
||||
- A pinctrl state named "default" for each DAC channel may be defined to set
|
||||
DAC_OUTx pin in mode of operation for analog output on external pin.
|
||||
|
||||
Contents of a stm32 dac child node:
|
||||
-----------------------------------
|
||||
DAC core node should contain at least one subnode, representing a
|
||||
DAC instance/channel available on the machine.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "st,stm32-dac".
|
||||
- reg: Must be either 1 or 2, to define (single) channel in use
|
||||
- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
|
||||
Documentation/devicetree/bindings/iio/iio-bindings.txt
|
||||
|
||||
Example:
|
||||
dac: dac@40007400 {
|
||||
compatible = "st,stm32h7-dac-core";
|
||||
reg = <0x40007400 0x400>;
|
||||
clocks = <&clk>;
|
||||
clock-names = "pclk";
|
||||
vref-supply = <®_vref>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dac_out1 &dac_out2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac1: dac@1 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channels-cells = <1>;
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
dac2: dac@2 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channels-cells = <1>;
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,110 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/iio/dac/st,stm32-dac.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: STMicroelectronics STM32 DAC bindings
|
||||
|
||||
description: |
|
||||
The STM32 DAC is a 12-bit voltage output digital-to-analog converter. The DAC
|
||||
may be configured in 8 or 12-bit mode. It has two output channels, each with
|
||||
its own converter.
|
||||
It has built-in noise and triangle waveform generator and supports external
|
||||
triggers for conversions. The DAC's output buffer allows a high drive output
|
||||
current.
|
||||
|
||||
maintainers:
|
||||
- Fabrice Gasnier <fabrice.gasnier@st.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- st,stm32f4-dac-core
|
||||
- st,stm32h7-dac-core
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
|
||||
vref-supply:
|
||||
description: Phandle to the vref input analog reference voltage.
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- vref-supply
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
patternProperties:
|
||||
"^dac@[1-2]+$":
|
||||
type: object
|
||||
description:
|
||||
A DAC block node should contain at least one subnode, representing an
|
||||
DAC instance/channel available on the machine.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: st,stm32-dac
|
||||
|
||||
reg:
|
||||
description: Must be either 1 or 2, to define (single) channel in use
|
||||
enum: [1, 2]
|
||||
|
||||
'#io-channel-cells':
|
||||
const: 1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#io-channel-cells'
|
||||
|
||||
examples:
|
||||
- |
|
||||
// Example on stm32mp157c
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
dac: dac@40017000 {
|
||||
compatible = "st,stm32h7-dac-core";
|
||||
reg = <0x40017000 0x400>;
|
||||
clocks = <&rcc DAC12>;
|
||||
clock-names = "pclk";
|
||||
vref-supply = <&vref>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac@1 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <1>;
|
||||
};
|
||||
|
||||
dac@2 {
|
||||
compatible = "st,stm32-dac";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "bosch,bmg160" or "bosch,bmi055_gyro"
|
||||
- compatible : should be "bosch,bmg160", "bosch,bmi055_gyro" or "bosch,bmi088_gyro"
|
||||
- reg : the I2C address of the sensor (0x69)
|
||||
|
||||
Optional properties:
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/imu/adi,adis16475.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices ADIS16475 and similar IMUs
|
||||
|
||||
maintainers:
|
||||
- Nuno Sá <nuno.sa@analog.com>
|
||||
|
||||
description: |
|
||||
Analog Devices ADIS16475 and similar IMUs
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ADIS16475.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,adis16475-1
|
||||
- adi,adis16475-2
|
||||
- adi,adis16475-3
|
||||
- adi,adis16477-1
|
||||
- adi,adis16477-2
|
||||
- adi,adis16477-3
|
||||
- adi,adis16470
|
||||
- adi,adis16465-1
|
||||
- adi,adis16465-2
|
||||
- adi,adis16465-3
|
||||
- adi,adis16467-1
|
||||
- adi,adis16467-2
|
||||
- adi,adis16467-3
|
||||
- adi,adis16500
|
||||
- adi,adis16505-1
|
||||
- adi,adis16505-2
|
||||
- adi,adis16505-3
|
||||
- adi,adis16507-1
|
||||
- adi,adis16507-2
|
||||
- adi,adis16507-3
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-cpha: true
|
||||
|
||||
spi-cpol: true
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 2000000
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
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 low,
|
||||
it should be marked GPIO_ACTIVE_LOW.
|
||||
maxItems: 1
|
||||
|
||||
adi,sync-mode:
|
||||
description:
|
||||
Configures the device SYNC pin. The following modes are supported
|
||||
0 - output_sync
|
||||
1 - direct_sync
|
||||
2 - scaled_sync
|
||||
3 - pulse_sync
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
|
||||
adi,scaled-output-hz:
|
||||
description:
|
||||
This property must be present if the clock mode is scaled-sync through
|
||||
clock-names property. In this mode, the input clock can have a range
|
||||
of 1Hz to 128HZ which must be scaled to originate an allowable sample
|
||||
rate. This property specifies that rate.
|
||||
minimum: 1900
|
||||
maximum: 2100
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- spi-cpha
|
||||
- spi-cpol
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,adis16500
|
||||
- adi,adis16505-1
|
||||
- adi,adis16505-2
|
||||
- adi,adis16505-3
|
||||
- adi,adis16507-1
|
||||
- adi,adis16507-2
|
||||
- adi,adis16507-3
|
||||
|
||||
then:
|
||||
properties:
|
||||
adi,sync-mode:
|
||||
minimum: 0
|
||||
maximum: 2
|
||||
|
||||
- if:
|
||||
properties:
|
||||
adi,sync-mode:
|
||||
enum: [1, 2, 3]
|
||||
|
||||
then:
|
||||
dependencies:
|
||||
adi,sync-mode: [ clocks ]
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adis16475: adis16475-3@0 {
|
||||
compatible = "adi,adis16475-3";
|
||||
reg = <0>;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
spi-max-frequency = <2000000>;
|
||||
interrupts = <4 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-parent = <&gpio>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/amstaos,tsl2563.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: AMS TAOS TSL2563 ambient light sensor
|
||||
|
||||
maintainers:
|
||||
- Sebastian Reichel <sre@kernel.org>
|
||||
|
||||
description: |
|
||||
Ambient light sensor with an i2c interface.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amstaos,tsl2560
|
||||
- amstaos,tsl2561
|
||||
- amstaos,tsl2562
|
||||
- amstaos,tsl2563
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
amstaos,cover-comp-gain:
|
||||
description: Multiplier for gain compensation
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [1, 16]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@29 {
|
||||
compatible = "amstaos,tsl2563";
|
||||
reg = <0x29>;
|
||||
amstaos,cover-comp-gain = <16>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -1,19 +0,0 @@
|
||||
* AMS TAOS TSL2563 ambient light sensor
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "amstaos,tsl2563"
|
||||
- reg : the I2C address of the sensor
|
||||
|
||||
Optional properties:
|
||||
|
||||
- amstaos,cover-comp-gain : integer used as multiplier for gain
|
||||
compensation (default = 1)
|
||||
|
||||
Example:
|
||||
|
||||
tsl2563@29 {
|
||||
compatible = "amstaos,tsl2563";
|
||||
reg = <0x29>;
|
||||
amstaos,cover-comp-gain = <16>;
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
VISHAY VCNL4000 - Ambient Light and proximity sensor
|
||||
|
||||
This driver supports the VCNL4000/10/20/40 and VCNL4200 chips
|
||||
|
||||
Required properties:
|
||||
|
||||
-compatible: must be one of :
|
||||
vishay,vcnl4000
|
||||
vishay,vcnl4010
|
||||
vishay,vcnl4020
|
||||
vishay,vcnl4040
|
||||
vishay,vcnl4200
|
||||
|
||||
-reg: I2C address of the sensor, should be one from below based on the model:
|
||||
0x13
|
||||
0x51
|
||||
0x60
|
||||
|
||||
Example:
|
||||
|
||||
light-sensor@51 {
|
||||
compatible = "vishay,vcnl4200";
|
||||
reg = <0x51>;
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/vishay,vcnl4000.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: VISHAY VCNL4000 ambient light and proximity sensor
|
||||
|
||||
maintainers:
|
||||
- Peter Meerwald <pmeerw@pmeerw.net>
|
||||
|
||||
description: |
|
||||
Ambient light sensing with proximity detection over an i2c
|
||||
interface.
|
||||
|
||||
allOf:
|
||||
- $ref: ../common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- vishay,vcnl4000
|
||||
- vishay,vcnl4010
|
||||
- vishay,vcnl4020
|
||||
- vishay,vcnl4040
|
||||
- vishay,vcnl4200
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
proximity-near-level: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@51 {
|
||||
compatible = "vishay,vcnl4200";
|
||||
reg = <0x51>;
|
||||
proximity-near-level = <220>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : should be "asahi-kasei,ak8974"
|
||||
- compatible:
|
||||
* "asahi-kasei,ak8974"
|
||||
* "alps,hscdtd008a"
|
||||
- reg : the I2C address of the magnetometer
|
||||
|
||||
Optional properties:
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/proximity/vishay,vcnl3020.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Integrated Proximity Sensor With Infrared Emitter
|
||||
|
||||
maintainers:
|
||||
- Ivan Mikhaylov <i.mikhaylov@yadro.com>
|
||||
|
||||
description: |
|
||||
The VCNL3020 is a fully integrated proximity sensor. Fully integrated means
|
||||
that the infrared emitter is included in the package. It has 16-bit
|
||||
resolution. It includes a signal processing IC and features standard I2C
|
||||
communication interface. It features an interrupt function.
|
||||
|
||||
Specifications about the devices can be found at:
|
||||
https://www.vishay.com/docs/84150/vcnl3020.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- vishay,vcnl3020
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Regulator that provides power to the sensor
|
||||
|
||||
vddio-supply:
|
||||
description: Regulator that provides power to the bus
|
||||
|
||||
vishay,led-current-microamp:
|
||||
description:
|
||||
The driver current for the LED used in proximity sensing.
|
||||
enum: [0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000,
|
||||
100000, 110000, 120000, 130000, 140000, 150000, 160000, 170000,
|
||||
180000, 190000, 200000]
|
||||
default: 20000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
proximity@13 {
|
||||
compatible = "vishay,vcnl3020";
|
||||
reg = <0x13>;
|
||||
vishay,led-current-microamp = <200000>;
|
||||
};
|
||||
};
|
||||
@@ -50,6 +50,7 @@ Accelerometers:
|
||||
- st,lis3dhh
|
||||
- st,lis3de
|
||||
- st,lis2de12
|
||||
- st,lis2hh12
|
||||
|
||||
Gyroscopes:
|
||||
- st,l3g4200d-gyro
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/interconnect/fsl,imx8m-noc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Generic i.MX bus frequency device
|
||||
|
||||
maintainers:
|
||||
- Leonard Crestez <leonard.crestez@nxp.com>
|
||||
|
||||
description: |
|
||||
The i.MX SoC family has multiple buses for which clock frequency (and
|
||||
sometimes voltage) can be adjusted.
|
||||
|
||||
Some of those buses expose register areas mentioned in the memory maps as GPV
|
||||
("Global Programmers View") but not all. Access to this area might be denied
|
||||
for normal (non-secure) world.
|
||||
|
||||
The buses are based on externally licensed IPs such as ARM NIC-301 and
|
||||
Arteris FlexNOC but DT bindings are specific to the integration of these bus
|
||||
interconnect IPs into imx SOCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx8mn-nic
|
||||
- fsl,imx8mm-nic
|
||||
- fsl,imx8mq-nic
|
||||
- const: fsl,imx8m-nic
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx8mn-noc
|
||||
- fsl,imx8mm-noc
|
||||
- fsl,imx8mq-noc
|
||||
- const: fsl,imx8m-noc
|
||||
- const: fsl,imx8m-nic
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
operating-points-v2: true
|
||||
opp-table: true
|
||||
|
||||
fsl,ddrc:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
description:
|
||||
Phandle to DDR Controller.
|
||||
|
||||
'#interconnect-cells':
|
||||
description:
|
||||
If specified then also act as an interconnect provider. Should only be
|
||||
set once per soc on the main noc.
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8mm-clock.h>
|
||||
#include <dt-bindings/interconnect/imx8mm.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
noc: interconnect@32700000 {
|
||||
compatible = "fsl,imx8mm-noc", "fsl,imx8m-noc";
|
||||
reg = <0x32700000 0x100000>;
|
||||
clocks = <&clk IMX8MM_CLK_NOC>;
|
||||
#interconnect-cells = <1>;
|
||||
fsl,ddrc = <&ddrc>;
|
||||
|
||||
operating-points-v2 = <&noc_opp_table>;
|
||||
noc_opp_table: opp-table {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp-133M {
|
||||
opp-hz = /bits/ 64 <133333333>;
|
||||
};
|
||||
opp-800M {
|
||||
opp-hz = /bits/ 64 <800000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
ddrc: memory-controller@3d400000 {
|
||||
compatible = "fsl,imx8mm-ddrc", "fsl,imx8m-ddrc";
|
||||
reg = <0x3d400000 0x400000>;
|
||||
clock-names = "core", "pll", "alt", "apb";
|
||||
clocks = <&clk IMX8MM_CLK_DRAM_CORE>,
|
||||
<&clk IMX8MM_DRAM_PLL>,
|
||||
<&clk IMX8MM_CLK_DRAM_ALT>,
|
||||
<&clk IMX8MM_CLK_DRAM_APB>;
|
||||
};
|
||||
@@ -9,13 +9,16 @@ Required properties:
|
||||
"brcm,bcm2835-gpio" - BCM2835 compatible pinctrl
|
||||
"brcm,bcm7211-gpio" - BCM7211 compatible pinctrl
|
||||
"brcm,bcm2711-gpio" - BCM2711 compatible pinctrl
|
||||
"brcm,bcm7211-gpio" - BCM7211 compatible pinctrl
|
||||
- reg: Should contain the physical address of the GPIO module's registers.
|
||||
- gpio-controller: Marks the device node as a GPIO controller.
|
||||
- #gpio-cells : Should be two. The first cell is the pin number and the
|
||||
second cell is used to specify optional parameters:
|
||||
- bit 0 specifies polarity (0 for normal, 1 for inverted)
|
||||
- interrupts : The interrupt outputs from the controller. One interrupt per
|
||||
individual bank followed by the "all banks" interrupt.
|
||||
individual bank followed by the "all banks" interrupt. For BCM7211, an
|
||||
additional set of per-bank interrupt line and an "all banks" wake-up
|
||||
interrupt may be specified.
|
||||
- interrupt-controller: Marks the device node as an interrupt controller.
|
||||
- #interrupt-cells : Should be 2.
|
||||
The first cell is the GPIO number.
|
||||
|
||||
@@ -2,8 +2,8 @@ Microsemi Ocelot pin controller Device Tree Bindings
|
||||
----------------------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "mscc,ocelot-pinctrl" or
|
||||
"mscc,jaguar2-pinctrl"
|
||||
- compatible : Should be "mscc,ocelot-pinctrl",
|
||||
"mscc,jaguar2-pinctrl" or "microchip,sparx5-pinctrl"
|
||||
- reg : Address and length of the register set for the device
|
||||
- gpio-controller : Indicates this device is a GPIO controller
|
||||
- #gpio-cells : Must be 2.
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/pinctrl/qcom,sm8250-pinctrl.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Technologies, Inc. SM8250 TLMM block
|
||||
|
||||
maintainers:
|
||||
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||
|
||||
description: |
|
||||
This binding describes the Top Level Mode Multiplexer block found in the
|
||||
SM8250 platform.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,sm8250-pinctrl
|
||||
|
||||
reg:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: "west"
|
||||
- const: "south"
|
||||
- const: "north"
|
||||
|
||||
interrupts:
|
||||
description: Specifies the TLMM summary IRQ
|
||||
maxItems: 1
|
||||
|
||||
interrupt-controller: true
|
||||
|
||||
'#interrupt-cells':
|
||||
description:
|
||||
Specifies the PIN numbers and Flags, as defined in defined in
|
||||
include/dt-bindings/interrupt-controller/irq.h
|
||||
const: 2
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
'#gpio-cells':
|
||||
description: Specifying the pin number and flags, as defined in
|
||||
include/dt-bindings/gpio/gpio.h
|
||||
const: 2
|
||||
|
||||
gpio-ranges:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-parent:
|
||||
maxItems: 1
|
||||
|
||||
#PIN CONFIGURATION NODES
|
||||
patternProperties:
|
||||
'^.*$':
|
||||
if:
|
||||
type: object
|
||||
then:
|
||||
properties:
|
||||
pins:
|
||||
description:
|
||||
List of gpio pins affected by the properties specified in this
|
||||
subnode.
|
||||
items:
|
||||
oneOf:
|
||||
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9])$"
|
||||
- enum: [ sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset ]
|
||||
minItems: 1
|
||||
maxItems: 36
|
||||
|
||||
function:
|
||||
description:
|
||||
Specify the alternative function to be configured for the specified
|
||||
pins.
|
||||
|
||||
enum: [ aoss_cti, atest, audio_ref, cam_mclk, cci_async, cci_i2c,
|
||||
cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, cri_trng,
|
||||
cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0, ddr_pxi1,
|
||||
ddr_pxi2, ddr_pxi3, dp_hot, dp_lcd, gcc_gp1, gcc_gp2, gcc_gp3, gpio,
|
||||
ibi_i3c, jitter_bist, lpass_slimbus, mdp_vsync, mdp_vsync0,
|
||||
mdp_vsync1, mdp_vsync2, mdp_vsync3, mi2s0_data0, mi2s0_data1,
|
||||
mi2s0_sck, mi2s0_ws, mi2s1_data0, mi2s1_data1, mi2s1_sck, mi2s1_ws,
|
||||
mi2s2_data0, mi2s2_data1, mi2s2_sck, mi2s2_ws, pci_e0, pci_e1,
|
||||
pci_e2, phase_flag, pll_bist, pll_bypassnl, pll_clk, pll_reset,
|
||||
pri_mi2s, prng_rosc, qdss_cti, qdss_gpio, qspi0, qspi1, qspi2, qspi3,
|
||||
qspi_clk, qspi_cs, qup0, qup1, qup10, qup11, qup12, qup13, qup14,
|
||||
qup15, qup16, qup17, qup18, qup19, qup2, qup3, qup4, qup5, qup6,
|
||||
qup7, qup8, qup9, qup_l4, qup_l5, qup_l6, sd_write, sdc40, sdc41,
|
||||
sdc42, sdc43, sdc4_clk, sdc4_cmd, sec_mi2s, sp_cmu, tgu_ch0, tgu_ch1,
|
||||
tgu_ch2, tgu_ch3, tsense_pwm1, tsense_pwm2, tsif0_clk, tsif0_data,
|
||||
tsif0_en, tsif0_error, tsif0_sync, tsif1_clk, tsif1_data, tsif1_en,
|
||||
tsif1_error, tsif1_sync, usb2phy_ac, usb_phy, vsense_trigger ]
|
||||
|
||||
drive-strength:
|
||||
enum: [2, 4, 6, 8, 10, 12, 14, 16]
|
||||
default: 2
|
||||
description:
|
||||
Selects the drive strength for the specified pins, in mA.
|
||||
|
||||
bias-pull-down: true
|
||||
|
||||
bias-pull-up: true
|
||||
|
||||
bias-disable: true
|
||||
|
||||
output-high: true
|
||||
|
||||
output-low: true
|
||||
|
||||
required:
|
||||
- pins
|
||||
- function
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- interrupt-controller
|
||||
- '#interrupt-cells'
|
||||
- gpio-controller
|
||||
- '#gpio-cells'
|
||||
- gpio-ranges
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
pinctrl@1f00000 {
|
||||
compatible = "qcom,sm8250-pinctrl";
|
||||
reg = <0x0f100000 0x300000>,
|
||||
<0x0f500000 0x300000>,
|
||||
<0x0f900000 0x300000>;
|
||||
reg-names = "west", "south", "north";
|
||||
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
gpio-ranges = <&tlmm 0 0 180>;
|
||||
wakeup-parent = <&pdc>;
|
||||
};
|
||||
@@ -13,6 +13,7 @@ Required Properties:
|
||||
- "renesas,pfc-emev2": for EMEV2 (EMMA Mobile EV2) compatible pin-controller.
|
||||
- "renesas,pfc-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7740": for R8A7740 (R-Mobile A1) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7742": for R8A7742 (RZ/G1H) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7743": for R8A7743 (RZ/G1M) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7744": for R8A7744 (RZ/G1N) compatible pin-controller.
|
||||
- "renesas,pfc-r8a7745": for R8A7745 (RZ/G1E) compatible pin-controller.
|
||||
|
||||
@@ -110,8 +110,8 @@ pinctrl@20008000 {
|
||||
|
||||
uart2 {
|
||||
uart2_xfer: uart2-xfer {
|
||||
rockchip,pins = <RK_GPIO1 8 1 &pcfg_pull_default>,
|
||||
<RK_GPIO1 9 1 &pcfg_pull_default>;
|
||||
rockchip,pins = <1 RK_PB0 1 &pcfg_pull_default>,
|
||||
<1 RK_PB1 1 &pcfg_pull_default>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -36,6 +36,9 @@ properties:
|
||||
pins-are-numbered: true
|
||||
hwlocks: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
st,syscfg:
|
||||
description: Should be phandle/offset/mask
|
||||
- Phandle to the syscon node which includes IRQ mux selection.
|
||||
|
||||
@@ -21,6 +21,8 @@ Optional properties:
|
||||
the second cell is used to specify the GPIO polarity:
|
||||
0 = active high,
|
||||
1 = active low.
|
||||
- irda-mode-ports: An array that lists the indices of the port that
|
||||
should operate in IrDA mode.
|
||||
|
||||
Example:
|
||||
sc16is750: sc16is750@51 {
|
||||
@@ -55,6 +57,8 @@ Optional properties:
|
||||
the second cell is used to specify the GPIO polarity:
|
||||
0 = active high,
|
||||
1 = active low.
|
||||
- irda-mode-ports: An array that lists the indices of the port that
|
||||
should operate in IrDA mode.
|
||||
|
||||
Example:
|
||||
sc16is750: sc16is750@0 {
|
||||
|
||||
@@ -41,4 +41,8 @@ properties:
|
||||
rs485-rx-during-tx:
|
||||
description: enables the receiving of data even while sending data.
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
rs485-term-gpios:
|
||||
description: GPIO pin to enable RS485 bus termination.
|
||||
maxItems: 1
|
||||
...
|
||||
|
||||
@@ -29,6 +29,14 @@ properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reg-io-width:
|
||||
description: |
|
||||
The size (in bytes) of the IO accesses that should be performed
|
||||
on the device.
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint32
|
||||
- enum: [ 1, 4 ]
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 5
|
||||
|
||||
@@ -48,6 +48,12 @@ properties:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
cts-gpios:
|
||||
maxItems: 1
|
||||
|
||||
rts-gpios:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
rs485-rts-delay: true
|
||||
@@ -55,6 +61,14 @@ properties:
|
||||
linux,rs485-enabled-at-boot-time: true
|
||||
rs485-rx-during-tx: true
|
||||
|
||||
if:
|
||||
required:
|
||||
- st,hw-flow-ctrl
|
||||
then:
|
||||
properties:
|
||||
cts-gpios: false
|
||||
rts-gpios: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
@@ -284,21 +284,13 @@ I2C
|
||||
|
||||
IIO
|
||||
devm_iio_device_alloc()
|
||||
devm_iio_device_free()
|
||||
devm_iio_device_register()
|
||||
devm_iio_device_unregister()
|
||||
devm_iio_kfifo_allocate()
|
||||
devm_iio_kfifo_free()
|
||||
devm_iio_triggered_buffer_setup()
|
||||
devm_iio_triggered_buffer_cleanup()
|
||||
devm_iio_trigger_alloc()
|
||||
devm_iio_trigger_free()
|
||||
devm_iio_trigger_register()
|
||||
devm_iio_trigger_unregister()
|
||||
devm_iio_channel_get()
|
||||
devm_iio_channel_release()
|
||||
devm_iio_channel_get_all()
|
||||
devm_iio_channel_release_all()
|
||||
|
||||
INPUT
|
||||
devm_input_allocate_device()
|
||||
|
||||
@@ -4,7 +4,6 @@ Device Drivers
|
||||
|
||||
See the kerneldoc for the struct device_driver.
|
||||
|
||||
|
||||
Allocation
|
||||
~~~~~~~~~~
|
||||
|
||||
@@ -167,9 +166,26 @@ the driver to that device.
|
||||
|
||||
A driver's probe() may return a negative errno value to indicate that
|
||||
the driver did not bind to this device, in which case it should have
|
||||
released all resources it allocated::
|
||||
released all resources it allocated.
|
||||
|
||||
void (*sync_state)(struct device *dev);
|
||||
Optionally, probe() may return -EPROBE_DEFER if the driver depends on
|
||||
resources that are not yet available (e.g., supplied by a driver that
|
||||
hasn't initialized yet). The driver core will put the device onto the
|
||||
deferred probe list and will try to call it again later. If a driver
|
||||
must defer, it should return -EPROBE_DEFER as early as possible to
|
||||
reduce the amount of time spent on setup work that will need to be
|
||||
unwound and reexecuted at a later time.
|
||||
|
||||
.. warning::
|
||||
-EPROBE_DEFER must not be returned if probe() has already created
|
||||
child devices, even if those child devices are removed again
|
||||
in a cleanup path. If -EPROBE_DEFER is returned after a child
|
||||
device has been registered, it may result in an infinite loop of
|
||||
.probe() calls to the same driver.
|
||||
|
||||
::
|
||||
|
||||
void (*sync_state) (struct device *dev);
|
||||
|
||||
sync_state is called only once for a device. It's called when all the consumer
|
||||
devices of the device have successfully probed. The list of consumers of the
|
||||
@@ -212,6 +228,8 @@ over management of devices from the bootloader, the usage of sync_state() is
|
||||
not restricted to that. Use it whenever it makes sense to take an action after
|
||||
all the consumers of a device have probed::
|
||||
|
||||
::
|
||||
|
||||
int (*remove) (struct device *dev);
|
||||
|
||||
remove is called to unbind a driver from a device. This may be
|
||||
@@ -224,11 +242,15 @@ not. It should free any resources allocated specifically for the
|
||||
device; i.e. anything in the device's driver_data field.
|
||||
|
||||
If the device is still present, it should quiesce the device and place
|
||||
it into a supported low-power state::
|
||||
it into a supported low-power state.
|
||||
|
||||
::
|
||||
|
||||
int (*suspend) (struct device *dev, pm_message_t state);
|
||||
|
||||
suspend is called to put the device in a low power state::
|
||||
suspend is called to put the device in a low power state.
|
||||
|
||||
::
|
||||
|
||||
int (*resume) (struct device *dev);
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@ Triggers
|
||||
|
||||
* struct :c:type:`iio_trigger` — industrial I/O trigger device
|
||||
* :c:func:`devm_iio_trigger_alloc` — Resource-managed iio_trigger_alloc
|
||||
* :c:func:`devm_iio_trigger_free` — Resource-managed iio_trigger_free
|
||||
* :c:func:`devm_iio_trigger_register` — Resource-managed iio_trigger_register
|
||||
* :c:func:`devm_iio_trigger_unregister` — Resource-managed
|
||||
iio_trigger_unregister
|
||||
* :c:func:`iio_trigger_validate_own_device` — Check if a trigger and IIO
|
||||
device belong to the same device
|
||||
|
||||
@@ -75,8 +75,33 @@ Slaves are using single port. ::
|
||||
| (Data) |
|
||||
+---------------+
|
||||
|
||||
Example 4: Stereo Stream with L and R channels is rendered by
|
||||
Master. Both of the L and R channels are received by two different
|
||||
Slaves. Master and both Slaves are using single port handling
|
||||
L+R. Each Slave device processes the L + R data locally, typically
|
||||
based on static configuration or dynamic orientation, and may drive
|
||||
one or more speakers. ::
|
||||
|
||||
Example 4: Stereo Stream with L and R channel is rendered by two different
|
||||
+---------------+ Clock Signal +---------------+
|
||||
| Master +---------+------------------------+ Slave |
|
||||
| Interface | | | Interface |
|
||||
| | | | 1 |
|
||||
| | | Data Signal | |
|
||||
| L + R +---+------------------------------+ L + R |
|
||||
| (Data) | | | Data Direction | (Data) |
|
||||
+---------------+ | | +-------------> +---------------+
|
||||
| |
|
||||
| |
|
||||
| | +---------------+
|
||||
| +----------------------> | Slave |
|
||||
| | Interface |
|
||||
| | 2 |
|
||||
| | |
|
||||
+----------------------------> | L + R |
|
||||
| (Data) |
|
||||
+---------------+
|
||||
|
||||
Example 5: Stereo Stream with L and R channel is rendered by two different
|
||||
Ports of the Master and is received by only single Port of the Slave
|
||||
interface. ::
|
||||
|
||||
@@ -101,7 +126,7 @@ interface. ::
|
||||
+--------------------+ | |
|
||||
+----------------+
|
||||
|
||||
Example 5: Stereo Stream with L and R channel is rendered by 2 Masters, each
|
||||
Example 6: Stereo Stream with L and R channel is rendered by 2 Masters, each
|
||||
rendering one channel, and is received by two different Slaves, each
|
||||
receiving one channel. Both Masters and both Slaves are using single port. ::
|
||||
|
||||
@@ -123,12 +148,70 @@ receiving one channel. Both Masters and both Slaves are using single port. ::
|
||||
| (Data) | Data Direction | (Data) |
|
||||
+---------------+ +-----------------------> +---------------+
|
||||
|
||||
Note: In multi-link cases like above, to lock, one would acquire a global
|
||||
Example 7: Stereo Stream with L and R channel is rendered by 2
|
||||
Masters, each rendering both channels. Each Slave receives L + R. This
|
||||
is the same application as Example 4 but with Slaves placed on
|
||||
separate links. ::
|
||||
|
||||
+---------------+ Clock Signal +---------------+
|
||||
| Master +----------------------------------+ Slave |
|
||||
| Interface | | Interface |
|
||||
| 1 | | 1 |
|
||||
| | Data Signal | |
|
||||
| L + R +----------------------------------+ L + R |
|
||||
| (Data) | Data Direction | (Data) |
|
||||
+---------------+ +-----------------------> +---------------+
|
||||
|
||||
+---------------+ Clock Signal +---------------+
|
||||
| Master +----------------------------------+ Slave |
|
||||
| Interface | | Interface |
|
||||
| 2 | | 2 |
|
||||
| | Data Signal | |
|
||||
| L + R +----------------------------------+ L + R |
|
||||
| (Data) | Data Direction | (Data) |
|
||||
+---------------+ +-----------------------> +---------------+
|
||||
|
||||
Example 8: 4-channel Stream is rendered by 2 Masters, each rendering a
|
||||
2 channels. Each Slave receives 2 channels. ::
|
||||
|
||||
+---------------+ Clock Signal +---------------+
|
||||
| Master +----------------------------------+ Slave |
|
||||
| Interface | | Interface |
|
||||
| 1 | | 1 |
|
||||
| | Data Signal | |
|
||||
| L1 + R1 +----------------------------------+ L1 + R1 |
|
||||
| (Data) | Data Direction | (Data) |
|
||||
+---------------+ +-----------------------> +---------------+
|
||||
|
||||
+---------------+ Clock Signal +---------------+
|
||||
| Master +----------------------------------+ Slave |
|
||||
| Interface | | Interface |
|
||||
| 2 | | 2 |
|
||||
| | Data Signal | |
|
||||
| L2 + R2 +----------------------------------+ L2 + R2 |
|
||||
| (Data) | Data Direction | (Data) |
|
||||
+---------------+ +-----------------------> +---------------+
|
||||
|
||||
Note1: In multi-link cases like above, to lock, one would acquire a global
|
||||
lock and then go on locking bus instances. But, in this case the caller
|
||||
framework(ASoC DPCM) guarantees that stream operations on a card are
|
||||
always serialized. So, there is no race condition and hence no need for
|
||||
global lock.
|
||||
|
||||
Note2: A Slave device may be configured to receive all channels
|
||||
transmitted on a link for a given Stream (Example 4) or just a subset
|
||||
of the data (Example 3). The configuration of the Slave device is not
|
||||
handled by a SoundWire subsystem API, but instead by the
|
||||
snd_soc_dai_set_tdm_slot() API. The platform or machine driver will
|
||||
typically configure which of the slots are used. For Example 4, the
|
||||
same slots would be used by all Devices, while for Example 3 the Slave
|
||||
Device1 would use e.g. Slot 0 and Slave device2 slot 1.
|
||||
|
||||
Note3: Multiple Sink ports can extract the same information for the
|
||||
same bitSlots in the SoundWire frame, however multiple Source ports
|
||||
shall be configured with different bitSlot configurations. This is the
|
||||
same limitation as with I2S/PCM TDM usages.
|
||||
|
||||
SoundWire Stream Management flow
|
||||
================================
|
||||
|
||||
|
||||
@@ -101,10 +101,11 @@ Following is the Bus API to register the SoundWire Bus:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int sdw_add_bus_master(struct sdw_bus *bus)
|
||||
int sdw_bus_master_add(struct sdw_bus *bus,
|
||||
struct device *parent,
|
||||
struct fwnode_handle)
|
||||
{
|
||||
if (!bus->dev)
|
||||
return -ENODEV;
|
||||
sdw_master_device_add(bus, parent, fwnode);
|
||||
|
||||
mutex_init(&bus->lock);
|
||||
INIT_LIST_HEAD(&bus->slaves);
|
||||
|
||||
@@ -118,6 +118,11 @@ More functions are exposed through sysfs
|
||||
management information (current temperature, thresholds, threshold status,
|
||||
etc.).
|
||||
|
||||
Performance reporting
|
||||
performance counters are exposed through perf PMU APIs. Standard perf tool
|
||||
can be used to monitor all available perf events. Please see performance
|
||||
counter section below for more detailed information.
|
||||
|
||||
|
||||
FIU - PORT
|
||||
==========
|
||||
@@ -378,6 +383,85 @@ The device nodes used for ioctl() or mmap() can be referenced through::
|
||||
/sys/class/fpga_region/<regionX>/<dfl-port.n>/dev
|
||||
|
||||
|
||||
Performance Counters
|
||||
====================
|
||||
Performance reporting is one private feature implemented in FME. It could
|
||||
supports several independent, system-wide, device counter sets in hardware to
|
||||
monitor and count for performance events, including "basic", "cache", "fabric",
|
||||
"vtd" and "vtd_sip" counters. Users could use standard perf tool to monitor
|
||||
FPGA cache hit/miss rate, transaction number, interface clock counter of AFU
|
||||
and other FPGA performance events.
|
||||
|
||||
Different FPGA devices may have different counter sets, depending on hardware
|
||||
implementation. E.g., some discrete FPGA cards don't have any cache. User could
|
||||
use "perf list" to check which perf events are supported by target hardware.
|
||||
|
||||
In order to allow user to use standard perf API to access these performance
|
||||
counters, driver creates a perf PMU, and related sysfs interfaces in
|
||||
/sys/bus/event_source/devices/dfl_fme* to describe available perf events and
|
||||
configuration options.
|
||||
|
||||
The "format" directory describes the format of the config field of struct
|
||||
perf_event_attr. There are 3 bitfields for config: "evtype" defines which type
|
||||
the perf event belongs to; "event" is the identity of the event within its
|
||||
category; "portid" is introduced to decide counters set to monitor on FPGA
|
||||
overall data or a specific port.
|
||||
|
||||
The "events" directory describes the configuration templates for all available
|
||||
events which can be used with perf tool directly. For example, fab_mmio_read
|
||||
has the configuration "event=0x06,evtype=0x02,portid=0xff", which shows this
|
||||
event belongs to fabric type (0x02), the local event id is 0x06 and it is for
|
||||
overall monitoring (portid=0xff).
|
||||
|
||||
Example usage of perf::
|
||||
|
||||
$# perf list |grep dfl_fme
|
||||
|
||||
dfl_fme0/fab_mmio_read/ [Kernel PMU event]
|
||||
<...>
|
||||
dfl_fme0/fab_port_mmio_read,portid=?/ [Kernel PMU event]
|
||||
<...>
|
||||
|
||||
$# perf stat -a -e dfl_fme0/fab_mmio_read/ <command>
|
||||
or
|
||||
$# perf stat -a -e dfl_fme0/event=0x06,evtype=0x02,portid=0xff/ <command>
|
||||
or
|
||||
$# perf stat -a -e dfl_fme0/config=0xff2006/ <command>
|
||||
|
||||
Another example, fab_port_mmio_read monitors mmio read of a specific port. So
|
||||
its configuration template is "event=0x06,evtype=0x01,portid=?". The portid
|
||||
should be explicitly set.
|
||||
|
||||
Its usage of perf::
|
||||
|
||||
$# perf stat -a -e dfl_fme0/fab_port_mmio_read,portid=0x0/ <command>
|
||||
or
|
||||
$# perf stat -a -e dfl_fme0/event=0x06,evtype=0x02,portid=0x0/ <command>
|
||||
or
|
||||
$# perf stat -a -e dfl_fme0/config=0x2006/ <command>
|
||||
|
||||
Please note for fabric counters, overall perf events (fab_*) and port perf
|
||||
events (fab_port_*) actually share one set of counters in hardware, so it can't
|
||||
monitor both at the same time. If this set of counters is configured to monitor
|
||||
overall data, then per port perf data is not supported. See below example::
|
||||
|
||||
$# perf stat -e dfl_fme0/fab_mmio_read/,dfl_fme0/fab_port_mmio_write,\
|
||||
portid=0/ sleep 1
|
||||
|
||||
Performance counter stats for 'system wide':
|
||||
|
||||
3 dfl_fme0/fab_mmio_read/
|
||||
<not supported> dfl_fme0/fab_port_mmio_write,portid=0x0/
|
||||
|
||||
1.001750904 seconds time elapsed
|
||||
|
||||
The driver also provides a "cpumask" sysfs attribute, which contains only one
|
||||
CPU id used to access these perf events. Counting on multiple CPU is not allowed
|
||||
since they are system-wide counters on FPGA device.
|
||||
|
||||
The current driver does not support sampling. So "perf record" is unsupported.
|
||||
|
||||
|
||||
Add new FIUs support
|
||||
====================
|
||||
It's possible that developers made some new function blocks (FIUs) under this
|
||||
|
||||
@@ -73,7 +73,7 @@ capable of generating or using trigger signals.::
|
||||
|
||||
>$ ls /sys/bus/coresight/devices/etm0/cti_cpu0
|
||||
channels ctmid enable nr_trigger_cons mgmt power powered regs
|
||||
subsystem triggers0 triggers1 uevent
|
||||
connections subsystem triggers0 triggers1 uevent
|
||||
|
||||
*Key file items are:-*
|
||||
* ``enable``: enables/disables the CTI. Read to determine current state.
|
||||
@@ -89,6 +89,9 @@ capable of generating or using trigger signals.::
|
||||
* ``channels``: Contains the channel API - CTI main programming interface.
|
||||
* ``regs``: Gives access to the raw programmable CTI regs.
|
||||
* ``mgmt``: the standard CoreSight management registers.
|
||||
* ``connections``: Links to connected *CoreSight* devices. The number of
|
||||
links can be 0 to ``nr_trigger_cons``. Actual number given by ``nr_links``
|
||||
in this directory.
|
||||
|
||||
|
||||
triggers<N> directories
|
||||
|
||||
@@ -241,6 +241,91 @@ to the newer scheme, to give a confirmation that what you see on your
|
||||
system is not unexpected. One must use the "names" as they appear on
|
||||
the system under specified locations.
|
||||
|
||||
Topology Representation
|
||||
-----------------------
|
||||
|
||||
Each CoreSight component has a ``connections`` directory which will contain
|
||||
links to other CoreSight components. This allows the user to explore the trace
|
||||
topology and for larger systems, determine the most appropriate sink for a
|
||||
given source. The connection information can also be used to establish
|
||||
which CTI devices are connected to a given component. This directory contains a
|
||||
``nr_links`` attribute detailing the number of links in the directory.
|
||||
|
||||
For an ETM source, in this case ``etm0`` on a Juno platform, a typical
|
||||
arrangement will be::
|
||||
|
||||
linaro-developer:~# ls - l /sys/bus/coresight/devices/etm0/connections
|
||||
<file details> cti_cpu0 -> ../../../23020000.cti/cti_cpu0
|
||||
<file details> nr_links
|
||||
<file details> out:0 -> ../../../230c0000.funnel/funnel2
|
||||
|
||||
Following the out port to ``funnel2``::
|
||||
|
||||
linaro-developer:~# ls -l /sys/bus/coresight/devices/funnel2/connections
|
||||
<file details> in:0 -> ../../../23040000.etm/etm0
|
||||
<file details> in:1 -> ../../../23140000.etm/etm3
|
||||
<file details> in:2 -> ../../../23240000.etm/etm4
|
||||
<file details> in:3 -> ../../../23340000.etm/etm5
|
||||
<file details> nr_links
|
||||
<file details> out:0 -> ../../../20040000.funnel/funnel0
|
||||
|
||||
And again to ``funnel0``::
|
||||
|
||||
linaro-developer:~# ls -l /sys/bus/coresight/devices/funnel0/connections
|
||||
<file details> in:0 -> ../../../220c0000.funnel/funnel1
|
||||
<file details> in:1 -> ../../../230c0000.funnel/funnel2
|
||||
<file details> nr_links
|
||||
<file details> out:0 -> ../../../20010000.etf/tmc_etf0
|
||||
|
||||
Finding the first sink ``tmc_etf0``. This can be used to collect data
|
||||
as a sink, or as a link to propagate further along the chain::
|
||||
|
||||
linaro-developer:~# ls -l /sys/bus/coresight/devices/tmc_etf0/connections
|
||||
<file details> cti_sys0 -> ../../../20020000.cti/cti_sys0
|
||||
<file details> in:0 -> ../../../20040000.funnel/funnel0
|
||||
<file details> nr_links
|
||||
<file details> out:0 -> ../../../20150000.funnel/funnel4
|
||||
|
||||
via ``funnel4``::
|
||||
|
||||
linaro-developer:~# ls -l /sys/bus/coresight/devices/funnel4/connections
|
||||
<file details> in:0 -> ../../../20010000.etf/tmc_etf0
|
||||
<file details> in:1 -> ../../../20140000.etf/tmc_etf1
|
||||
<file details> nr_links
|
||||
<file details> out:0 -> ../../../20120000.replicator/replicator0
|
||||
|
||||
and a ``replicator0``::
|
||||
|
||||
linaro-developer:~# ls -l /sys/bus/coresight/devices/replicator0/connections
|
||||
<file details> in:0 -> ../../../20150000.funnel/funnel4
|
||||
<file details> nr_links
|
||||
<file details> out:0 -> ../../../20030000.tpiu/tpiu0
|
||||
<file details> out:1 -> ../../../20070000.etr/tmc_etr0
|
||||
|
||||
Arriving at the final sink in the chain, ``tmc_etr0``::
|
||||
|
||||
linaro-developer:~# ls -l /sys/bus/coresight/devices/tmc_etr0/connections
|
||||
<file details> cti_sys0 -> ../../../20020000.cti/cti_sys0
|
||||
<file details> in:0 -> ../../../20120000.replicator/replicator0
|
||||
<file details> nr_links
|
||||
|
||||
As described below, when using sysfs it is sufficient to enable a sink and
|
||||
a source for successful trace. The framework will correctly enable all
|
||||
intermediate links as required.
|
||||
|
||||
Note: ``cti_sys0`` appears in two of the connections lists above.
|
||||
CTIs can connect to multiple devices and are arranged in a star topology
|
||||
via the CTM. See (:doc:`coresight-ect`) [#fourth]_ for further details.
|
||||
Looking at this device we see 4 connections::
|
||||
|
||||
linaro-developer:~# ls -l /sys/bus/coresight/devices/cti_sys0/connections
|
||||
<file details> nr_links
|
||||
<file details> stm0 -> ../../../20100000.stm/stm0
|
||||
<file details> tmc_etf0 -> ../../../20010000.etf/tmc_etf0
|
||||
<file details> tmc_etr0 -> ../../../20070000.etr/tmc_etr0
|
||||
<file details> tpiu0 -> ../../../20030000.tpiu/tpiu0
|
||||
|
||||
|
||||
How to use the tracer modules
|
||||
-----------------------------
|
||||
|
||||
|
||||
@@ -26,20 +26,31 @@ W1_THERM_DS1825 0x3B
|
||||
W1_THERM_DS28EA00 0x42
|
||||
==================== ====
|
||||
|
||||
Support is provided through the sysfs w1_slave file. Each open and
|
||||
Support is provided through the sysfs w1_slave file. Each open and
|
||||
read sequence will initiate a temperature conversion then provide two
|
||||
lines of ASCII output. The first line contains the nine hex bytes
|
||||
lines of ASCII output. The first line contains the nine hex bytes
|
||||
read along with a calculated crc value and YES or NO if it matched.
|
||||
If the crc matched the returned values are retained. The second line
|
||||
If the crc matched the returned values are retained. The second line
|
||||
displays the retained values along with a temperature in millidegrees
|
||||
Centigrade after t=.
|
||||
|
||||
Parasite powered devices are limited to one slave performing a
|
||||
temperature conversion at a time. If none of the devices are parasite
|
||||
powered it would be possible to convert all the devices at the same
|
||||
time and then go back to read individual sensors. That isn't
|
||||
currently supported. The driver also doesn't support reduced
|
||||
precision (which would also reduce the conversion time) when reading values.
|
||||
Alternatively, temperature can be read using temperature sysfs, it
|
||||
return only temperature in millidegrees Centigrade.
|
||||
|
||||
A bulk read of all devices on the bus could be done writing 'trigger'
|
||||
in the therm_bulk_read sysfs entry at w1_bus_master level. This will
|
||||
sent the convert command on all devices on the bus, and if parasite
|
||||
powered devices are detected on the bus (and strong pullup is enable
|
||||
in the module), it will drive the line high during the longer conversion
|
||||
time required by parasited powered device on the line. Reading
|
||||
therm_bulk_read will return 0 if no bulk conversion pending,
|
||||
-1 if at least one sensor still in conversion, 1 if conversion is complete
|
||||
but at least one sensor value has not been read yet. Result temperature is
|
||||
then accessed by reading the temperature sysfs entry of each device, which
|
||||
may return empty if conversion is still in progress. Note that if a bulk
|
||||
read is sent but one sensor is not read immediately, the next access to
|
||||
temperature on this device will return the temperature measured at the
|
||||
time of issue of the bulk read command (not the current temperature).
|
||||
|
||||
Writing a value between 9 and 12 to the sysfs w1_slave file will change the
|
||||
precision of the sensor for the next readings. This value is in (volatile)
|
||||
@@ -49,6 +60,27 @@ To store the current precision configuration into EEPROM, the value 0
|
||||
has to be written to the sysfs w1_slave file. Since the EEPROM has a limited
|
||||
amount of writes (>50k), this command should be used wisely.
|
||||
|
||||
Alternatively, resolution can be set or read (value from 9 to 12) using the
|
||||
dedicated resolution sysfs entry on each device. This sysfs entry is not
|
||||
present for devices not supporting this feature. Driver will adjust the
|
||||
correct conversion time for each device regarding to its resolution setting.
|
||||
In particular, strong pullup will be applied if required during the conversion
|
||||
duration.
|
||||
|
||||
The write-only sysfs entry eeprom is an alternative for EEPROM operations:
|
||||
* 'save': will save device RAM to EEPROM
|
||||
* 'restore': will restore EEPROM data in device RAM.
|
||||
|
||||
ext_power syfs entry allow tho check the power status of each device.
|
||||
* '0': device parasite powered
|
||||
* '1': device externally powered
|
||||
|
||||
sysfs alarms allow read or write TH and TL (Temperature High an Low) alarms.
|
||||
Values shall be space separated and in the device range (typical -55 degC
|
||||
to 125 degC). Values are integer as they are store in a 8bit register in
|
||||
the device. Lowest value is automatically put to TL.Once set, alarms could
|
||||
be search at master level.
|
||||
|
||||
The module parameter strong_pullup can be set to 0 to disable the
|
||||
strong pullup, 1 to enable autodetection or 2 to force strong pullup.
|
||||
In case of autodetection, the driver will use the "READ POWER SUPPLY"
|
||||
|
||||
+12
-1
@@ -294,6 +294,7 @@ F: drivers/gpio/gpio-104-idio-16.c
|
||||
|
||||
ACCES 104-QUAD-8 DRIVER
|
||||
M: William Breathitt Gray <vilhelm.gray@gmail.com>
|
||||
M: Syed Nayyar Waris <syednwaris@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-bus-counter-104-quad-8
|
||||
@@ -1042,6 +1043,14 @@ W: http://ez.analog.com/community/linux-device-drivers
|
||||
F: Documentation/devicetree/bindings/iio/imu/adi,adis16460.yaml
|
||||
F: drivers/iio/imu/adis16460.c
|
||||
|
||||
ANALOG DEVICES INC ADIS16475 DRIVER
|
||||
M: Nuno Sa <nuno.sa@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
W: http://ez.analog.com/community/linux-device-drivers
|
||||
S: Supported
|
||||
F: drivers/iio/imu/adis16475.c
|
||||
F: Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml
|
||||
|
||||
ANALOG DEVICES INC ADM1177 DRIVER
|
||||
M: Beniamin Bia <beniamin.bia@analog.com>
|
||||
M: Michael Hennerich <Michael.Hennerich@analog.com>
|
||||
@@ -7094,6 +7103,7 @@ GASKET DRIVER FRAMEWORK
|
||||
M: Rob Springer <rspringer@google.com>
|
||||
M: Todd Poynor <toddpoynor@google.com>
|
||||
M: Ben Chan <benchan@chromium.org>
|
||||
M: Richard Yeh <rcy@google.com>
|
||||
S: Maintained
|
||||
F: drivers/staging/gasket/
|
||||
|
||||
@@ -13492,8 +13502,9 @@ F: drivers/pinctrl/qcom/
|
||||
PIN CONTROLLER - RENESAS
|
||||
M: Geert Uytterhoeven <geert+renesas@glider.be>
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Maintained
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git sh-pfc
|
||||
F: Documentation/devicetree/bindings/pinctrl/renesas,*
|
||||
F: drivers/pinctrl/pinctrl-rz*
|
||||
F: drivers/pinctrl/sh-pfc/
|
||||
|
||||
|
||||
@@ -430,6 +430,15 @@ register_cpus(void)
|
||||
|
||||
arch_initcall(register_cpus);
|
||||
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
static const struct sysrq_key_op srm_sysrq_reboot_op = {
|
||||
.handler = machine_halt,
|
||||
.help_msg = "reboot(b)",
|
||||
.action_msg = "Resetting",
|
||||
.enable_mask = SYSRQ_ENABLE_BOOT,
|
||||
};
|
||||
#endif
|
||||
|
||||
void __init
|
||||
setup_arch(char **cmdline_p)
|
||||
{
|
||||
@@ -550,8 +559,8 @@ setup_arch(char **cmdline_p)
|
||||
/* If we're using SRM, make sysrq-b halt back to the prom,
|
||||
not auto-reboot. */
|
||||
if (alpha_using_srm) {
|
||||
struct sysrq_key_op *op = __sysrq_get_key_op('b');
|
||||
op->handler = (void *) machine_halt;
|
||||
unregister_sysrq_key('b', __sysrq_reboot_op);
|
||||
register_sysrq_key('b', &srm_sysrq_reboot_op);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -539,12 +539,12 @@
|
||||
|
||||
firmware {
|
||||
svc {
|
||||
compatible = "intel,stratix10-svc";
|
||||
compatible = "intel,agilex-svc";
|
||||
method = "smc";
|
||||
memory-region = <&service_reserved>;
|
||||
|
||||
fpga_mgr: fpga-mgr {
|
||||
compatible = "intel,stratix10-soc-fpga-mgr";
|
||||
compatible = "intel,agilex-soc-fpga-mgr";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ static void sysrq_handle_tlbdump(int key)
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_tlbdump_op = {
|
||||
static const struct sysrq_key_op sysrq_tlbdump_op = {
|
||||
.handler = sysrq_handle_tlbdump,
|
||||
.help_msg = "show-tlbs(x)",
|
||||
.action_msg = "Show TLB entries",
|
||||
|
||||
@@ -3919,7 +3919,7 @@ static void sysrq_handle_xmon(int key)
|
||||
xmon_init(0);
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sysrq_xmon_op = {
|
||||
static const struct sysrq_key_op sysrq_xmon_op = {
|
||||
.handler = sysrq_handle_xmon,
|
||||
.help_msg = "xmon(x)",
|
||||
.action_msg = "Entering xmon",
|
||||
|
||||
@@ -313,7 +313,7 @@ static void sysrq_handle_globreg(int key)
|
||||
trigger_all_cpu_backtrace();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sparc_globalreg_op = {
|
||||
static const struct sysrq_key_op sparc_globalreg_op = {
|
||||
.handler = sysrq_handle_globreg,
|
||||
.help_msg = "global-regs(y)",
|
||||
.action_msg = "Show Global CPU Regs",
|
||||
@@ -388,7 +388,7 @@ static void sysrq_handle_globpmu(int key)
|
||||
pmu_snapshot_all_cpus();
|
||||
}
|
||||
|
||||
static struct sysrq_key_op sparc_globalpmu_op = {
|
||||
static const struct sysrq_key_op sparc_globalpmu_op = {
|
||||
.handler = sysrq_handle_globpmu,
|
||||
.help_msg = "global-pmu(x)",
|
||||
.action_msg = "Show Global PMU Regs",
|
||||
|
||||
@@ -650,7 +650,7 @@ static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
struct binderfs_info *info;
|
||||
struct binderfs_mount_opts *ctx = fc->fs_private;
|
||||
struct inode *inode = NULL;
|
||||
struct binderfs_device device_info = { 0 };
|
||||
struct binderfs_device device_info = {};
|
||||
const char *name;
|
||||
size_t len;
|
||||
|
||||
@@ -747,7 +747,7 @@ static const struct fs_context_operations binderfs_fs_context_ops = {
|
||||
|
||||
static int binderfs_init_fs_context(struct fs_context *fc)
|
||||
{
|
||||
struct binderfs_mount_opts *ctx = fc->fs_private;
|
||||
struct binderfs_mount_opts *ctx;
|
||||
|
||||
ctx = kzalloc(sizeof(struct binderfs_mount_opts), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
|
||||
@@ -153,6 +153,7 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
|
||||
extern int devres_release_all(struct device *dev);
|
||||
extern void device_block_probing(void);
|
||||
extern void device_unblock_probing(void);
|
||||
extern void driver_deferred_probe_force_trigger(void);
|
||||
|
||||
/* /sys/devices directory */
|
||||
extern struct kset *devices_kset;
|
||||
|
||||
+179
-56
@@ -49,6 +49,9 @@ static LIST_HEAD(wait_for_suppliers);
|
||||
static DEFINE_MUTEX(wfs_lock);
|
||||
static LIST_HEAD(deferred_sync);
|
||||
static unsigned int defer_sync_state_count = 1;
|
||||
static unsigned int defer_fw_devlink_count;
|
||||
static DEFINE_MUTEX(defer_fw_devlink_lock);
|
||||
static bool fw_devlink_is_permissive(void);
|
||||
|
||||
#ifdef CONFIG_SRCU
|
||||
static DEFINE_MUTEX(device_links_lock);
|
||||
@@ -529,7 +532,7 @@ static void device_link_add_missing_supplier_links(void)
|
||||
int ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
|
||||
if (!ret)
|
||||
list_del_init(&dev->links.needs_suppliers);
|
||||
else if (ret != -ENODEV)
|
||||
else if (ret != -ENODEV || fw_devlink_is_permissive())
|
||||
dev->links.need_for_probe = false;
|
||||
}
|
||||
mutex_unlock(&wfs_lock);
|
||||
@@ -643,9 +646,17 @@ static void device_links_missing_supplier(struct device *dev)
|
||||
{
|
||||
struct device_link *link;
|
||||
|
||||
list_for_each_entry(link, &dev->links.suppliers, c_node)
|
||||
if (link->status == DL_STATE_CONSUMER_PROBE)
|
||||
list_for_each_entry(link, &dev->links.suppliers, c_node) {
|
||||
if (link->status != DL_STATE_CONSUMER_PROBE)
|
||||
continue;
|
||||
|
||||
if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
|
||||
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
|
||||
} else {
|
||||
WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
|
||||
WRITE_ONCE(link->status, DL_STATE_DORMANT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -684,11 +695,11 @@ int device_links_check_suppliers(struct device *dev)
|
||||
device_links_write_lock();
|
||||
|
||||
list_for_each_entry(link, &dev->links.suppliers, c_node) {
|
||||
if (!(link->flags & DL_FLAG_MANAGED) ||
|
||||
link->flags & DL_FLAG_SYNC_STATE_ONLY)
|
||||
if (!(link->flags & DL_FLAG_MANAGED))
|
||||
continue;
|
||||
|
||||
if (link->status != DL_STATE_AVAILABLE) {
|
||||
if (link->status != DL_STATE_AVAILABLE &&
|
||||
!(link->flags & DL_FLAG_SYNC_STATE_ONLY)) {
|
||||
device_links_missing_supplier(dev);
|
||||
ret = -EPROBE_DEFER;
|
||||
break;
|
||||
@@ -949,11 +960,21 @@ static void __device_links_no_driver(struct device *dev)
|
||||
if (!(link->flags & DL_FLAG_MANAGED))
|
||||
continue;
|
||||
|
||||
if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
|
||||
if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
|
||||
device_link_drop_managed(link);
|
||||
else if (link->status == DL_STATE_CONSUMER_PROBE ||
|
||||
link->status == DL_STATE_ACTIVE)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (link->status != DL_STATE_CONSUMER_PROBE &&
|
||||
link->status != DL_STATE_ACTIVE)
|
||||
continue;
|
||||
|
||||
if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
|
||||
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
|
||||
} else {
|
||||
WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
|
||||
WRITE_ONCE(link->status, DL_STATE_DORMANT);
|
||||
}
|
||||
}
|
||||
|
||||
dev->links.status = DL_DEV_NO_DRIVER;
|
||||
@@ -1162,6 +1183,150 @@ static void device_links_purge(struct device *dev)
|
||||
device_links_write_unlock();
|
||||
}
|
||||
|
||||
static u32 fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER;
|
||||
static int __init fw_devlink_setup(char *arg)
|
||||
{
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(arg, "off") == 0) {
|
||||
fw_devlink_flags = 0;
|
||||
} else if (strcmp(arg, "permissive") == 0) {
|
||||
fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY;
|
||||
} else if (strcmp(arg, "on") == 0) {
|
||||
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER;
|
||||
} else if (strcmp(arg, "rpm") == 0) {
|
||||
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER |
|
||||
DL_FLAG_PM_RUNTIME;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
early_param("fw_devlink", fw_devlink_setup);
|
||||
|
||||
u32 fw_devlink_get_flags(void)
|
||||
{
|
||||
return fw_devlink_flags;
|
||||
}
|
||||
|
||||
static bool fw_devlink_is_permissive(void)
|
||||
{
|
||||
return fw_devlink_flags == DL_FLAG_SYNC_STATE_ONLY;
|
||||
}
|
||||
|
||||
static void fw_devlink_link_device(struct device *dev)
|
||||
{
|
||||
int fw_ret;
|
||||
|
||||
if (!fw_devlink_flags)
|
||||
return;
|
||||
|
||||
mutex_lock(&defer_fw_devlink_lock);
|
||||
if (!defer_fw_devlink_count)
|
||||
device_link_add_missing_supplier_links();
|
||||
|
||||
/*
|
||||
* The device's fwnode not having add_links() doesn't affect if other
|
||||
* consumers can find this device as a supplier. So, this check is
|
||||
* intentionally placed after device_link_add_missing_supplier_links().
|
||||
*/
|
||||
if (!fwnode_has_op(dev->fwnode, add_links))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If fw_devlink is being deferred, assume all devices have mandatory
|
||||
* suppliers they need to link to later. Then, when the fw_devlink is
|
||||
* resumed, all these devices will get a chance to try and link to any
|
||||
* suppliers they have.
|
||||
*/
|
||||
if (!defer_fw_devlink_count) {
|
||||
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
|
||||
if (fw_ret == -ENODEV && fw_devlink_is_permissive())
|
||||
fw_ret = -EAGAIN;
|
||||
} else {
|
||||
fw_ret = -ENODEV;
|
||||
}
|
||||
|
||||
if (fw_ret == -ENODEV)
|
||||
device_link_wait_for_mandatory_supplier(dev);
|
||||
else if (fw_ret)
|
||||
device_link_wait_for_optional_supplier(dev);
|
||||
|
||||
out:
|
||||
mutex_unlock(&defer_fw_devlink_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* fw_devlink_pause - Pause parsing of fwnode to create device links
|
||||
*
|
||||
* Calling this function defers any fwnode parsing to create device links until
|
||||
* fw_devlink_resume() is called. Both these functions are ref counted and the
|
||||
* caller needs to match the calls.
|
||||
*
|
||||
* While fw_devlink is paused:
|
||||
* - Any device that is added won't have its fwnode parsed to create device
|
||||
* links.
|
||||
* - The probe of the device will also be deferred during this period.
|
||||
* - Any devices that were already added, but waiting for suppliers won't be
|
||||
* able to link to newly added devices.
|
||||
*
|
||||
* Once fw_devlink_resume():
|
||||
* - All the fwnodes that was not parsed will be parsed.
|
||||
* - All the devices that were deferred probing will be reattempted if they
|
||||
* aren't waiting for any more suppliers.
|
||||
*
|
||||
* This pair of functions, is mainly meant to optimize the parsing of fwnodes
|
||||
* when a lot of devices that need to link to each other are added in a short
|
||||
* interval of time. For example, adding all the top level devices in a system.
|
||||
*
|
||||
* For example, if N devices are added and:
|
||||
* - All the consumers are added before their suppliers
|
||||
* - All the suppliers of the N devices are part of the N devices
|
||||
*
|
||||
* Then:
|
||||
*
|
||||
* - With the use of fw_devlink_pause() and fw_devlink_resume(), each device
|
||||
* will only need one parsing of its fwnode because it is guaranteed to find
|
||||
* all the supplier devices already registered and ready to link to. It won't
|
||||
* have to do another pass later to find one or more suppliers it couldn't
|
||||
* find in the first parse of the fwnode. So, we'll only need O(N) fwnode
|
||||
* parses.
|
||||
*
|
||||
* - Without the use of fw_devlink_pause() and fw_devlink_resume(), we would
|
||||
* end up doing O(N^2) parses of fwnodes because every device that's added is
|
||||
* guaranteed to trigger a parse of the fwnode of every device added before
|
||||
* it. This O(N^2) parse is made worse by the fact that when a fwnode of a
|
||||
* device is parsed, all it descendant devices might need to have their
|
||||
* fwnodes parsed too (even if the devices themselves aren't added).
|
||||
*/
|
||||
void fw_devlink_pause(void)
|
||||
{
|
||||
mutex_lock(&defer_fw_devlink_lock);
|
||||
defer_fw_devlink_count++;
|
||||
mutex_unlock(&defer_fw_devlink_lock);
|
||||
}
|
||||
|
||||
/** fw_devlink_resume - Resume parsing of fwnode to create device links
|
||||
*
|
||||
* This function is used in conjunction with fw_devlink_pause() and is ref
|
||||
* counted. See documentation for fw_devlink_pause() for more details.
|
||||
*/
|
||||
void fw_devlink_resume(void)
|
||||
{
|
||||
mutex_lock(&defer_fw_devlink_lock);
|
||||
if (!defer_fw_devlink_count) {
|
||||
WARN(true, "Unmatched fw_devlink pause/resume!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
defer_fw_devlink_count--;
|
||||
if (defer_fw_devlink_count)
|
||||
goto out;
|
||||
|
||||
device_link_add_missing_supplier_links();
|
||||
driver_deferred_probe_force_trigger();
|
||||
out:
|
||||
mutex_unlock(&defer_fw_devlink_lock);
|
||||
}
|
||||
/* Device links support end. */
|
||||
|
||||
int (*platform_notify)(struct device *dev) = NULL;
|
||||
@@ -2364,36 +2529,6 @@ static int device_private_init(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER;
|
||||
static int __init fw_devlink_setup(char *arg)
|
||||
{
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (strcmp(arg, "off") == 0) {
|
||||
fw_devlink_flags = 0;
|
||||
} else if (strcmp(arg, "permissive") == 0) {
|
||||
fw_devlink_flags = DL_FLAG_SYNC_STATE_ONLY;
|
||||
} else if (strcmp(arg, "on") == 0) {
|
||||
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER;
|
||||
} else if (strcmp(arg, "rpm") == 0) {
|
||||
fw_devlink_flags = DL_FLAG_AUTOPROBE_CONSUMER |
|
||||
DL_FLAG_PM_RUNTIME;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
early_param("fw_devlink", fw_devlink_setup);
|
||||
|
||||
u32 fw_devlink_get_flags(void)
|
||||
{
|
||||
return fw_devlink_flags;
|
||||
}
|
||||
|
||||
static bool fw_devlink_is_permissive(void)
|
||||
{
|
||||
return fw_devlink_flags == DL_FLAG_SYNC_STATE_ONLY;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_add - add device to device hierarchy.
|
||||
* @dev: device.
|
||||
@@ -2426,9 +2561,8 @@ int device_add(struct device *dev)
|
||||
struct device *parent;
|
||||
struct kobject *kobj;
|
||||
struct class_interface *class_intf;
|
||||
int error = -EINVAL, fw_ret;
|
||||
int error = -EINVAL;
|
||||
struct kobject *glue_dir = NULL;
|
||||
bool is_fwnode_dev = false;
|
||||
|
||||
dev = get_device(dev);
|
||||
if (!dev)
|
||||
@@ -2526,11 +2660,6 @@ int device_add(struct device *dev)
|
||||
|
||||
kobject_uevent(&dev->kobj, KOBJ_ADD);
|
||||
|
||||
if (dev->fwnode && !dev->fwnode->dev) {
|
||||
dev->fwnode->dev = dev;
|
||||
is_fwnode_dev = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if any of the other devices (consumers) have been waiting for
|
||||
* this device (supplier) to be added so that they can create a device
|
||||
@@ -2539,19 +2668,13 @@ int device_add(struct device *dev)
|
||||
* This needs to happen after device_pm_add() because device_link_add()
|
||||
* requires the supplier be registered before it's called.
|
||||
*
|
||||
* But this also needs to happe before bus_probe_device() to make sure
|
||||
* But this also needs to happen before bus_probe_device() to make sure
|
||||
* waiting consumers can link to it before the driver is bound to the
|
||||
* device and the driver sync_state callback is called for this device.
|
||||
*/
|
||||
device_link_add_missing_supplier_links();
|
||||
|
||||
if (fw_devlink_flags && is_fwnode_dev &&
|
||||
fwnode_has_op(dev->fwnode, add_links)) {
|
||||
fw_ret = fwnode_call_int_op(dev->fwnode, add_links, dev);
|
||||
if (fw_ret == -ENODEV && !fw_devlink_is_permissive())
|
||||
device_link_wait_for_mandatory_supplier(dev);
|
||||
else if (fw_ret)
|
||||
device_link_wait_for_optional_supplier(dev);
|
||||
if (dev->fwnode && !dev->fwnode->dev) {
|
||||
dev->fwnode->dev = dev;
|
||||
fw_devlink_link_device(dev);
|
||||
}
|
||||
|
||||
bus_probe_device(dev);
|
||||
|
||||
+18
-15
@@ -164,6 +164,11 @@ static void driver_deferred_probe_trigger(void)
|
||||
if (!driver_deferred_probe_enable)
|
||||
return;
|
||||
|
||||
driver_deferred_probe_force_trigger();
|
||||
}
|
||||
|
||||
void driver_deferred_probe_force_trigger(void)
|
||||
{
|
||||
/*
|
||||
* A successful probe means that all the devices in the pending list
|
||||
* should be triggered to be reprobed. Move all the deferred devices
|
||||
@@ -254,12 +259,12 @@ __setup("deferred_probe_timeout=", deferred_probe_timeout_setup);
|
||||
int driver_deferred_probe_check_state(struct device *dev)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_MODULES) && initcalls_done) {
|
||||
dev_warn(dev, "ignoring dependency for device, assuming no driver");
|
||||
dev_warn(dev, "ignoring dependency for device, assuming no driver\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!driver_deferred_probe_timeout && initcalls_done) {
|
||||
dev_warn(dev, "deferred probe timeout, ignoring dependency");
|
||||
dev_warn(dev, "deferred probe timeout, ignoring dependency\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
@@ -275,7 +280,7 @@ static void deferred_probe_timeout_work_func(struct work_struct *work)
|
||||
flush_work(&deferred_probe_work);
|
||||
|
||||
list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe)
|
||||
dev_info(private->device, "deferred probe pending");
|
||||
dev_info(private->device, "deferred probe pending\n");
|
||||
wake_up(&probe_timeout_waitqueue);
|
||||
}
|
||||
static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func);
|
||||
@@ -336,7 +341,7 @@ bool device_is_bound(struct device *dev)
|
||||
static void driver_bound(struct device *dev)
|
||||
{
|
||||
if (device_is_bound(dev)) {
|
||||
printk(KERN_WARNING "%s: device %s already bound\n",
|
||||
pr_warn("%s: device %s already bound\n",
|
||||
__func__, kobject_name(&dev->kobj));
|
||||
return;
|
||||
}
|
||||
@@ -505,8 +510,8 @@ re_probe:
|
||||
}
|
||||
|
||||
if (driver_sysfs_add(dev)) {
|
||||
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
|
||||
__func__, dev_name(dev));
|
||||
pr_err("%s: driver_sysfs_add(%s) failed\n",
|
||||
__func__, dev_name(dev));
|
||||
goto probe_failed;
|
||||
}
|
||||
|
||||
@@ -597,9 +602,8 @@ pinctrl_bind_failed:
|
||||
break;
|
||||
default:
|
||||
/* driver matched but the probe failed */
|
||||
printk(KERN_WARNING
|
||||
"%s: probe of %s failed with error %d\n",
|
||||
drv->name, dev_name(dev), ret);
|
||||
pr_warn("%s: probe of %s failed with error %d\n",
|
||||
drv->name, dev_name(dev), ret);
|
||||
}
|
||||
/*
|
||||
* Ignore errors returned by ->probe so that the next driver can try
|
||||
@@ -624,8 +628,8 @@ static int really_probe_debug(struct device *dev, struct device_driver *drv)
|
||||
ret = really_probe(dev, drv);
|
||||
rettime = ktime_get();
|
||||
delta = ktime_sub(rettime, calltime);
|
||||
printk(KERN_DEBUG "probe of %s returned %d after %lld usecs\n",
|
||||
dev_name(dev), ret, (s64) ktime_to_us(delta));
|
||||
pr_debug("probe of %s returned %d after %lld usecs\n",
|
||||
dev_name(dev), ret, (s64) ktime_to_us(delta));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -713,8 +717,7 @@ static inline bool cmdline_requested_async_probing(const char *drv_name)
|
||||
static int __init save_async_options(char *buf)
|
||||
{
|
||||
if (strlen(buf) >= ASYNC_DRV_NAMES_MAX_LEN)
|
||||
printk(KERN_WARNING
|
||||
"Too long list of driver names for 'driver_async_probe'!\n");
|
||||
pr_warn("Too long list of driver names for 'driver_async_probe'!\n");
|
||||
|
||||
strlcpy(async_probe_drv_names, buf, ASYNC_DRV_NAMES_MAX_LEN);
|
||||
return 0;
|
||||
@@ -789,7 +792,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
|
||||
dev_dbg(dev, "Device match requests probe deferral\n");
|
||||
driver_deferred_probe_add(dev);
|
||||
} else if (ret < 0) {
|
||||
dev_dbg(dev, "Bus failed to match device: %d", ret);
|
||||
dev_dbg(dev, "Bus failed to match device: %d\n", ret);
|
||||
return ret;
|
||||
} /* ret > 0 means positive match */
|
||||
|
||||
@@ -1022,7 +1025,7 @@ static int __driver_attach(struct device *dev, void *data)
|
||||
dev_dbg(dev, "Device match requests probe deferral\n");
|
||||
driver_deferred_probe_add(dev);
|
||||
} else if (ret < 0) {
|
||||
dev_dbg(dev, "Bus failed to match device: %d", ret);
|
||||
dev_dbg(dev, "Bus failed to match device: %d\n", ret);
|
||||
return ret;
|
||||
} /* ret > 0 means positive match */
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/umh.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "fallback.h"
|
||||
#include "firmware.h"
|
||||
@@ -17,6 +18,8 @@
|
||||
* firmware fallback mechanism
|
||||
*/
|
||||
|
||||
MODULE_IMPORT_NS(FIRMWARE_LOADER_PRIVATE);
|
||||
|
||||
extern struct firmware_fallback_config fw_fallback_config;
|
||||
|
||||
/* These getters are vetted to use int properly */
|
||||
@@ -460,7 +463,7 @@ static const struct attribute_group *fw_dev_attr_groups[] = {
|
||||
|
||||
static struct fw_sysfs *
|
||||
fw_create_instance(struct firmware *firmware, const char *fw_name,
|
||||
struct device *device, enum fw_opt opt_flags)
|
||||
struct device *device, u32 opt_flags)
|
||||
{
|
||||
struct fw_sysfs *fw_sysfs;
|
||||
struct device *f_dev;
|
||||
@@ -493,7 +496,7 @@ exit:
|
||||
* In charge of constructing a sysfs fallback interface for firmware loading.
|
||||
**/
|
||||
static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs,
|
||||
enum fw_opt opt_flags, long timeout)
|
||||
u32 opt_flags, long timeout)
|
||||
{
|
||||
int retval = 0;
|
||||
struct device *f_dev = &fw_sysfs->dev;
|
||||
@@ -547,7 +550,7 @@ err_put_dev:
|
||||
|
||||
static int fw_load_from_user_helper(struct firmware *firmware,
|
||||
const char *name, struct device *device,
|
||||
enum fw_opt opt_flags)
|
||||
u32 opt_flags)
|
||||
{
|
||||
struct fw_sysfs *fw_sysfs;
|
||||
long timeout;
|
||||
@@ -588,7 +591,7 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool fw_force_sysfs_fallback(enum fw_opt opt_flags)
|
||||
static bool fw_force_sysfs_fallback(u32 opt_flags)
|
||||
{
|
||||
if (fw_fallback_config.force_sysfs_fallback)
|
||||
return true;
|
||||
@@ -597,7 +600,7 @@ static bool fw_force_sysfs_fallback(enum fw_opt opt_flags)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
|
||||
static bool fw_run_sysfs_fallback(u32 opt_flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -640,7 +643,7 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
|
||||
**/
|
||||
int firmware_fallback_sysfs(struct firmware *fw, const char *name,
|
||||
struct device *device,
|
||||
enum fw_opt opt_flags,
|
||||
u32 opt_flags,
|
||||
int ret)
|
||||
{
|
||||
if (!fw_run_sysfs_fallback(opt_flags))
|
||||
|
||||
@@ -33,7 +33,7 @@ struct firmware_fallback_config {
|
||||
#ifdef CONFIG_FW_LOADER_USER_HELPER
|
||||
int firmware_fallback_sysfs(struct firmware *fw, const char *name,
|
||||
struct device *device,
|
||||
enum fw_opt opt_flags,
|
||||
u32 opt_flags,
|
||||
int ret);
|
||||
void kill_pending_fw_fallback_reqs(bool only_kill_custom);
|
||||
|
||||
@@ -45,7 +45,7 @@ void unregister_sysfs_loader(void);
|
||||
#else /* CONFIG_FW_LOADER_USER_HELPER */
|
||||
static inline int firmware_fallback_sysfs(struct firmware *fw, const char *name,
|
||||
struct device *device,
|
||||
enum fw_opt opt_flags,
|
||||
u32 opt_flags,
|
||||
int ret)
|
||||
{
|
||||
/* Keep carrying over the same error */
|
||||
@@ -67,10 +67,10 @@ static inline void unregister_sysfs_loader(void)
|
||||
#endif /* CONFIG_FW_LOADER_USER_HELPER */
|
||||
|
||||
#ifdef CONFIG_EFI_EMBEDDED_FIRMWARE
|
||||
int firmware_fallback_platform(struct fw_priv *fw_priv, enum fw_opt opt_flags);
|
||||
int firmware_fallback_platform(struct fw_priv *fw_priv, u32 opt_flags);
|
||||
#else
|
||||
static inline int firmware_fallback_platform(struct fw_priv *fw_priv,
|
||||
enum fw_opt opt_flags)
|
||||
u32 opt_flags)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "fallback.h"
|
||||
#include "firmware.h"
|
||||
|
||||
int firmware_fallback_platform(struct fw_priv *fw_priv, enum fw_opt opt_flags)
|
||||
int firmware_fallback_platform(struct fw_priv *fw_priv, u32 opt_flags)
|
||||
{
|
||||
const u8 *data;
|
||||
size_t size;
|
||||
|
||||
@@ -21,7 +21,7 @@ struct firmware_fallback_config fw_fallback_config = {
|
||||
.loading_timeout = 60,
|
||||
.old_timeout = 60,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(fw_fallback_config);
|
||||
EXPORT_SYMBOL_NS_GPL(fw_fallback_config, FIRMWARE_LOADER_PRIVATE);
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct ctl_table firmware_config_table[] = {
|
||||
|
||||
@@ -136,8 +136,7 @@ static inline void fw_state_done(struct fw_priv *fw_priv)
|
||||
__fw_state_set(fw_priv, FW_STATUS_DONE);
|
||||
}
|
||||
|
||||
int assign_fw(struct firmware *fw, struct device *device,
|
||||
enum fw_opt opt_flags);
|
||||
int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags);
|
||||
|
||||
#ifdef CONFIG_FW_LOADER_PAGED_BUF
|
||||
void fw_free_paged_buf(struct fw_priv *fw_priv);
|
||||
|
||||
@@ -210,7 +210,7 @@ static struct fw_priv *__lookup_fw_priv(const char *fw_name)
|
||||
static int alloc_lookup_fw_priv(const char *fw_name,
|
||||
struct firmware_cache *fwc,
|
||||
struct fw_priv **fw_priv, void *dbuf,
|
||||
size_t size, enum fw_opt opt_flags)
|
||||
size_t size, u32 opt_flags)
|
||||
{
|
||||
struct fw_priv *tmp;
|
||||
|
||||
@@ -548,9 +548,6 @@ static void firmware_free_data(const struct firmware *fw)
|
||||
static void fw_set_page_data(struct fw_priv *fw_priv, struct firmware *fw)
|
||||
{
|
||||
fw->priv = fw_priv;
|
||||
#ifdef CONFIG_FW_LOADER_USER_HELPER
|
||||
fw->pages = fw_priv->pages;
|
||||
#endif
|
||||
fw->size = fw_priv->size;
|
||||
fw->data = fw_priv->data;
|
||||
|
||||
@@ -635,8 +632,7 @@ static int fw_add_devm_name(struct device *dev, const char *name)
|
||||
}
|
||||
#endif
|
||||
|
||||
int assign_fw(struct firmware *fw, struct device *device,
|
||||
enum fw_opt opt_flags)
|
||||
int assign_fw(struct firmware *fw, struct device *device, u32 opt_flags)
|
||||
{
|
||||
struct fw_priv *fw_priv = fw->priv;
|
||||
int ret;
|
||||
@@ -687,7 +683,7 @@ int assign_fw(struct firmware *fw, struct device *device,
|
||||
static int
|
||||
_request_firmware_prepare(struct firmware **firmware_p, const char *name,
|
||||
struct device *device, void *dbuf, size_t size,
|
||||
enum fw_opt opt_flags)
|
||||
u32 opt_flags)
|
||||
{
|
||||
struct firmware *firmware;
|
||||
struct fw_priv *fw_priv;
|
||||
@@ -753,7 +749,7 @@ static void fw_abort_batch_reqs(struct firmware *fw)
|
||||
static int
|
||||
_request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
struct device *device, void *buf, size_t size,
|
||||
enum fw_opt opt_flags)
|
||||
u32 opt_flags)
|
||||
{
|
||||
struct firmware *fw = NULL;
|
||||
int ret;
|
||||
@@ -990,7 +986,7 @@ struct firmware_work {
|
||||
struct device *device;
|
||||
void *context;
|
||||
void (*cont)(const struct firmware *fw, void *context);
|
||||
enum fw_opt opt_flags;
|
||||
u32 opt_flags;
|
||||
};
|
||||
|
||||
static void request_firmware_work_func(struct work_struct *work)
|
||||
|
||||
@@ -682,7 +682,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister);
|
||||
struct platform_device *platform_device_register_full(
|
||||
const struct platform_device_info *pdevinfo)
|
||||
{
|
||||
int ret = -ENOMEM;
|
||||
int ret;
|
||||
struct platform_device *pdev;
|
||||
|
||||
pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
|
||||
@@ -863,6 +863,8 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv,
|
||||
/* temporary section violation during probe() */
|
||||
drv->probe = probe;
|
||||
retval = code = __platform_driver_register(drv, module);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/*
|
||||
* Fixup that section violation, being paranoid about code scanning
|
||||
@@ -987,7 +989,7 @@ EXPORT_SYMBOL_GPL(__platform_register_drivers);
|
||||
* @drivers: an array of drivers to unregister
|
||||
* @count: the number of drivers to unregister
|
||||
*
|
||||
* Unegisters platform drivers specified by an array. This is typically used
|
||||
* Unregisters platform drivers specified by an array. This is typically used
|
||||
* to complement an earlier call to platform_register_drivers(). Drivers are
|
||||
* unregistered in the reverse order in which they were registered.
|
||||
*/
|
||||
|
||||
+11
-2
@@ -708,14 +708,23 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev,
|
||||
struct fwnode_handle *child)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
struct fwnode_handle *fwnode = NULL;
|
||||
struct fwnode_handle *fwnode = NULL, *next;
|
||||
|
||||
if (dev->of_node)
|
||||
fwnode = &dev->of_node->fwnode;
|
||||
else if (adev)
|
||||
fwnode = acpi_fwnode_handle(adev);
|
||||
|
||||
return fwnode_get_next_child_node(fwnode, child);
|
||||
/* Try to find a child in primary fwnode */
|
||||
next = fwnode_get_next_child_node(fwnode, child);
|
||||
if (next)
|
||||
return next;
|
||||
|
||||
/* When no more children in primary, continue with secondary */
|
||||
if (!IS_ERR_OR_NULL(fwnode->secondary))
|
||||
next = fwnode_get_next_child_node(fwnode->secondary, child);
|
||||
|
||||
return next;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_get_next_child_node);
|
||||
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ static umode_t soc_attribute_mode(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
int index)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct device *dev = kobj_to_dev(kobj);
|
||||
struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
|
||||
|
||||
if ((attr == &dev_attr_machine.attr)
|
||||
|
||||
+21
-6
@@ -712,17 +712,18 @@ EXPORT_SYMBOL_GPL(software_node_register_nodes);
|
||||
* @nodes: Zero terminated array of software nodes to be unregistered
|
||||
*
|
||||
* Unregister multiple software nodes at once.
|
||||
*
|
||||
* NOTE: Be careful using this call if the nodes had parent pointers set up in
|
||||
* them before registering. If so, it is wiser to remove the nodes
|
||||
* individually, in the correct order (child before parent) instead of relying
|
||||
* on the sequential order of the list of nodes in the array.
|
||||
*/
|
||||
void software_node_unregister_nodes(const struct software_node *nodes)
|
||||
{
|
||||
struct swnode *swnode;
|
||||
int i;
|
||||
|
||||
for (i = 0; nodes[i].name; i++) {
|
||||
swnode = software_node_to_swnode(&nodes[i]);
|
||||
if (swnode)
|
||||
fwnode_remove_software_node(&swnode->fwnode);
|
||||
}
|
||||
for (i = 0; nodes[i].name; i++)
|
||||
software_node_unregister(&nodes[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
|
||||
|
||||
@@ -789,6 +790,20 @@ int software_node_register(const struct software_node *node)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_register);
|
||||
|
||||
/**
|
||||
* software_node_unregister - Unregister static software node
|
||||
* @node: The software node to be unregistered
|
||||
*/
|
||||
void software_node_unregister(const struct software_node *node)
|
||||
{
|
||||
struct swnode *swnode;
|
||||
|
||||
swnode = software_node_to_swnode(node);
|
||||
if (swnode)
|
||||
fwnode_remove_software_node(&swnode->fwnode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_unregister);
|
||||
|
||||
struct fwnode_handle *
|
||||
fwnode_create_software_node(const struct property_entry *properties,
|
||||
const struct fwnode_handle *parent)
|
||||
|
||||
+39
-36
@@ -43,10 +43,7 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
|
||||
lower_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
|
||||
sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
|
||||
|
||||
if (unlikely(!sequence_id))
|
||||
sequence_id = 1;
|
||||
sequence_id = MHI_RANDOM_U32_NONZERO(BHIE_RXVECSTATUS_SEQNUM_BMSK);
|
||||
|
||||
mhi_write_reg_field(mhi_cntrl, base, BHIE_RXVECDB_OFFS,
|
||||
BHIE_RXVECDB_SEQNUM_BMSK, BHIE_RXVECDB_SEQNUM_SHFT,
|
||||
@@ -121,7 +118,8 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
|
||||
ee = mhi_get_exec_env(mhi_cntrl);
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Waiting for image download completion, current EE: %s\n",
|
||||
dev_dbg(dev,
|
||||
"Waiting for RDDM image download via BHIe, current EE:%s\n",
|
||||
TO_MHI_EXEC_STR(ee));
|
||||
|
||||
while (retry--) {
|
||||
@@ -152,11 +150,14 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
|
||||
int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic)
|
||||
{
|
||||
void __iomem *base = mhi_cntrl->bhie;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
u32 rx_status;
|
||||
|
||||
if (in_panic)
|
||||
return __mhi_download_rddm_in_panic(mhi_cntrl);
|
||||
|
||||
dev_dbg(dev, "Waiting for RDDM image download via BHIe\n");
|
||||
|
||||
/* Wait for the image download to complete */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_read_reg_field(mhi_cntrl, base,
|
||||
@@ -174,8 +175,10 @@ static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl,
|
||||
const struct mhi_buf *mhi_buf)
|
||||
{
|
||||
void __iomem *base = mhi_cntrl->bhie;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
rwlock_t *pm_lock = &mhi_cntrl->pm_lock;
|
||||
u32 tx_status, sequence_id;
|
||||
int ret;
|
||||
|
||||
read_lock_bh(pm_lock);
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
@@ -183,6 +186,9 @@ static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
sequence_id = MHI_RANDOM_U32_NONZERO(BHIE_TXVECSTATUS_SEQNUM_BMSK);
|
||||
dev_dbg(dev, "Starting AMSS download via BHIe. Sequence ID:%u\n",
|
||||
sequence_id);
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECADDR_HIGH_OFFS,
|
||||
upper_32_bits(mhi_buf->dma_addr));
|
||||
|
||||
@@ -191,26 +197,25 @@ static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl,
|
||||
|
||||
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECSIZE_OFFS, mhi_buf->len);
|
||||
|
||||
sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK;
|
||||
mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS,
|
||||
BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT,
|
||||
sequence_id);
|
||||
read_unlock_bh(pm_lock);
|
||||
|
||||
/* Wait for the image download to complete */
|
||||
wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
|
||||
mhi_read_reg_field(mhi_cntrl, base,
|
||||
BHIE_TXVECSTATUS_OFFS,
|
||||
BHIE_TXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_TXVECSTATUS_STATUS_SHFT,
|
||||
&tx_status) || tx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
|
||||
mhi_read_reg_field(mhi_cntrl, base,
|
||||
BHIE_TXVECSTATUS_OFFS,
|
||||
BHIE_TXVECSTATUS_STATUS_BMSK,
|
||||
BHIE_TXVECSTATUS_STATUS_SHFT,
|
||||
&tx_status) || tx_status,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state) ||
|
||||
tx_status != BHIE_TXVECSTATUS_STATUS_XFER_COMPL)
|
||||
return -EIO;
|
||||
|
||||
return (tx_status == BHIE_TXVECSTATUS_STATUS_XFER_COMPL) ? 0 : -EIO;
|
||||
return (!ret) ? -ETIMEDOUT : 0;
|
||||
}
|
||||
|
||||
static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl,
|
||||
@@ -239,14 +244,15 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl,
|
||||
goto invalid_pm_state;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Starting SBL download via BHI\n");
|
||||
session_id = MHI_RANDOM_U32_NONZERO(BHI_TXDB_SEQNUM_BMSK);
|
||||
dev_dbg(dev, "Starting SBL download via BHI. Session ID:%u\n",
|
||||
session_id);
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_STATUS, 0);
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_HIGH,
|
||||
upper_32_bits(dma_addr));
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGADDR_LOW,
|
||||
lower_32_bits(dma_addr));
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGSIZE, size);
|
||||
session_id = prandom_u32() & BHI_TXDB_SEQNUM_BMSK;
|
||||
mhi_write_reg(mhi_cntrl, base, BHI_IMGTXDB, session_id);
|
||||
read_unlock_bh(pm_lock);
|
||||
|
||||
@@ -377,30 +383,18 @@ static void mhi_firmware_copy(struct mhi_controller *mhi_cntrl,
|
||||
}
|
||||
}
|
||||
|
||||
void mhi_fw_load_worker(struct work_struct *work)
|
||||
void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl;
|
||||
const struct firmware *firmware = NULL;
|
||||
struct image_info *image_info;
|
||||
struct device *dev;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
const char *fw_name;
|
||||
void *buf;
|
||||
dma_addr_t dma_addr;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
mhi_cntrl = container_of(work, struct mhi_controller, fw_worker);
|
||||
dev = &mhi_cntrl->mhi_dev->dev;
|
||||
|
||||
dev_dbg(dev, "Waiting for device to enter PBL from: %s\n",
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee));
|
||||
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_IN_PBL(mhi_cntrl->ee) ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
dev_err(dev, "Device MHI is not in valid state\n");
|
||||
return;
|
||||
}
|
||||
@@ -446,7 +440,12 @@ void mhi_fw_load_worker(struct work_struct *work)
|
||||
release_firmware(firmware);
|
||||
|
||||
/* Error or in EDL mode, we're done */
|
||||
if (ret || mhi_cntrl->ee == MHI_EE_EDL)
|
||||
if (ret) {
|
||||
dev_err(dev, "MHI did not load SBL, ret:%d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mhi_cntrl->ee == MHI_EE_EDL)
|
||||
return;
|
||||
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
@@ -474,8 +473,10 @@ fw_load_ee_pthru:
|
||||
if (!mhi_cntrl->fbc_download)
|
||||
return;
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(dev, "MHI did not enter READY state\n");
|
||||
goto error_read;
|
||||
}
|
||||
|
||||
/* Wait for the SBL event */
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
@@ -493,6 +494,8 @@ fw_load_ee_pthru:
|
||||
ret = mhi_fw_load_amss(mhi_cntrl,
|
||||
/* Vector table is the last entry */
|
||||
&image_info->mhi_buf[image_info->entries - 1]);
|
||||
if (ret)
|
||||
dev_err(dev, "MHI did not load AMSS, ret:%d\n", ret);
|
||||
|
||||
release_firmware(firmware);
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX] = {
|
||||
[DEV_ST_TRANSITION_READY] = "READY",
|
||||
[DEV_ST_TRANSITION_SBL] = "SBL",
|
||||
[DEV_ST_TRANSITION_MISSION_MODE] = "MISSION_MODE",
|
||||
[DEV_ST_TRANSITION_SYS_ERR] = "SYS_ERR",
|
||||
[DEV_ST_TRANSITION_DISABLE] = "DISABLE",
|
||||
};
|
||||
|
||||
const char * const mhi_state_str[MHI_STATE_MAX] = {
|
||||
@@ -835,8 +837,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
|
||||
spin_lock_init(&mhi_cntrl->transition_lock);
|
||||
spin_lock_init(&mhi_cntrl->wlock);
|
||||
INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker);
|
||||
INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker);
|
||||
INIT_WORK(&mhi_cntrl->fw_worker, mhi_fw_load_worker);
|
||||
init_waitqueue_head(&mhi_cntrl->state_event);
|
||||
|
||||
mhi_cmd = mhi_cntrl->mhi_cmd;
|
||||
@@ -864,6 +864,10 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl,
|
||||
mutex_init(&mhi_chan->mutex);
|
||||
init_completion(&mhi_chan->completion);
|
||||
rwlock_init(&mhi_chan->lock);
|
||||
|
||||
/* used in setting bei field of TRE */
|
||||
mhi_event = &mhi_cntrl->mhi_event[mhi_chan->er_index];
|
||||
mhi_chan->intmod = mhi_event->intmod;
|
||||
}
|
||||
|
||||
if (mhi_cntrl->bounce_buf) {
|
||||
|
||||
@@ -386,6 +386,8 @@ enum dev_st_transition {
|
||||
DEV_ST_TRANSITION_READY,
|
||||
DEV_ST_TRANSITION_SBL,
|
||||
DEV_ST_TRANSITION_MISSION_MODE,
|
||||
DEV_ST_TRANSITION_SYS_ERR,
|
||||
DEV_ST_TRANSITION_DISABLE,
|
||||
DEV_ST_TRANSITION_MAX,
|
||||
};
|
||||
|
||||
@@ -452,6 +454,7 @@ enum mhi_pm_state {
|
||||
#define PRIMARY_CMD_RING 0
|
||||
#define MHI_DEV_WAKE_DB 127
|
||||
#define MHI_MAX_MTU 0xffff
|
||||
#define MHI_RANDOM_U32_NONZERO(bmsk) (prandom_u32_max(bmsk) + 1)
|
||||
|
||||
enum mhi_er_type {
|
||||
MHI_ER_TYPE_INVALID = 0x0,
|
||||
@@ -586,7 +589,7 @@ enum mhi_ee_type mhi_get_exec_env(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl,
|
||||
enum dev_st_transition state);
|
||||
void mhi_pm_st_worker(struct work_struct *work);
|
||||
void mhi_pm_sys_err_worker(struct work_struct *work);
|
||||
void mhi_pm_sys_err_handler(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_fw_load_worker(struct work_struct *work);
|
||||
int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_ctrl_ev_task(unsigned long data);
|
||||
@@ -627,6 +630,7 @@ int mhi_init_irq_setup(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_deinit_free_irq(struct mhi_controller *mhi_cntrl);
|
||||
void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
|
||||
struct image_info *img_info);
|
||||
void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl);
|
||||
int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_chan *mhi_chan);
|
||||
int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
|
||||
@@ -670,8 +674,7 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *dev);
|
||||
irqreturn_t mhi_intvec_handler(int irq_number, void *dev);
|
||||
|
||||
int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
void *buf, void *cb, size_t buf_len, enum mhi_flags flags);
|
||||
|
||||
struct mhi_buf_info *info, enum mhi_flags flags);
|
||||
int mhi_map_single_no_bb(struct mhi_controller *mhi_cntrl,
|
||||
struct mhi_buf_info *buf_info);
|
||||
int mhi_map_single_use_bb(struct mhi_controller *mhi_cntrl,
|
||||
|
||||
+108
-87
@@ -258,7 +258,7 @@ int mhi_destroy_device(struct device *dev, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mhi_notify(struct mhi_device *mhi_dev, enum mhi_callback cb_reason)
|
||||
void mhi_notify(struct mhi_device *mhi_dev, enum mhi_callback cb_reason)
|
||||
{
|
||||
struct mhi_driver *mhi_drv;
|
||||
|
||||
@@ -270,6 +270,7 @@ static void mhi_notify(struct mhi_device *mhi_dev, enum mhi_callback cb_reason)
|
||||
if (mhi_drv->status_cb)
|
||||
mhi_drv->status_cb(mhi_dev, cb_reason);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mhi_notify);
|
||||
|
||||
/* Bind MHI channels to MHI devices */
|
||||
void mhi_create_devices(struct mhi_controller *mhi_cntrl)
|
||||
@@ -368,30 +369,37 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *dev)
|
||||
irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *priv)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = dev;
|
||||
struct mhi_controller *mhi_cntrl = priv;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
enum mhi_state state = MHI_STATE_MAX;
|
||||
enum mhi_pm_state pm_state = 0;
|
||||
enum mhi_ee_type ee = 0;
|
||||
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
state = mhi_get_mhi_state(mhi_cntrl);
|
||||
ee = mhi_cntrl->ee;
|
||||
mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
|
||||
if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) {
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
goto exit_intvec;
|
||||
}
|
||||
|
||||
state = mhi_get_mhi_state(mhi_cntrl);
|
||||
ee = mhi_cntrl->ee;
|
||||
mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
|
||||
dev_dbg(dev, "local ee:%s device ee:%s dev_state:%s\n",
|
||||
TO_MHI_EXEC_STR(mhi_cntrl->ee), TO_MHI_EXEC_STR(ee),
|
||||
TO_MHI_STATE_STR(state));
|
||||
|
||||
if (state == MHI_STATE_SYS_ERR) {
|
||||
dev_dbg(&mhi_cntrl->mhi_dev->dev, "System error detected\n");
|
||||
dev_dbg(dev, "System error detected\n");
|
||||
pm_state = mhi_tryset_pm_state(mhi_cntrl,
|
||||
MHI_PM_SYS_ERR_DETECT);
|
||||
}
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
|
||||
/* If device in RDDM don't bother processing SYS error */
|
||||
if (mhi_cntrl->ee == MHI_EE_RDDM) {
|
||||
if (mhi_cntrl->ee != ee) {
|
||||
/* If device supports RDDM don't bother processing SYS error */
|
||||
if (mhi_cntrl->rddm_image) {
|
||||
if (mhi_cntrl->ee == MHI_EE_RDDM && mhi_cntrl->ee != ee) {
|
||||
mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_EE_RDDM);
|
||||
wake_up_all(&mhi_cntrl->state_event);
|
||||
}
|
||||
@@ -405,7 +413,7 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *dev)
|
||||
if (MHI_IN_PBL(ee))
|
||||
mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_FATAL_ERROR);
|
||||
else
|
||||
schedule_work(&mhi_cntrl->syserr_worker);
|
||||
mhi_pm_sys_err_handler(mhi_cntrl);
|
||||
}
|
||||
|
||||
exit_intvec:
|
||||
@@ -513,7 +521,10 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
|
||||
mhi_cntrl->unmap_single(mhi_cntrl, buf_info);
|
||||
|
||||
result.buf_addr = buf_info->cb_buf;
|
||||
result.bytes_xferd = xfer_len;
|
||||
|
||||
/* truncate to buf len if xfer_len is larger */
|
||||
result.bytes_xferd =
|
||||
min_t(u16, xfer_len, buf_info->len);
|
||||
mhi_del_ring_element(mhi_cntrl, buf_ring);
|
||||
mhi_del_ring_element(mhi_cntrl, tre_ring);
|
||||
local_rp = tre_ring->rp;
|
||||
@@ -597,7 +608,9 @@ static int parse_rsc_event(struct mhi_controller *mhi_cntrl,
|
||||
|
||||
result.transaction_status = (ev_code == MHI_EV_CC_OVERFLOW) ?
|
||||
-EOVERFLOW : 0;
|
||||
result.bytes_xferd = xfer_len;
|
||||
|
||||
/* truncate to buf len if xfer_len is larger */
|
||||
result.bytes_xferd = min_t(u16, xfer_len, buf_info->len);
|
||||
result.buf_addr = buf_info->cb_buf;
|
||||
result.dir = mhi_chan->dir;
|
||||
|
||||
@@ -722,13 +735,18 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
|
||||
{
|
||||
enum mhi_pm_state new_state;
|
||||
|
||||
/* skip SYS_ERROR handling if RDDM supported */
|
||||
if (mhi_cntrl->ee == MHI_EE_RDDM ||
|
||||
mhi_cntrl->rddm_image)
|
||||
break;
|
||||
|
||||
dev_dbg(dev, "System error detected\n");
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
new_state = mhi_tryset_pm_state(mhi_cntrl,
|
||||
MHI_PM_SYS_ERR_DETECT);
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
if (new_state == MHI_PM_SYS_ERR_DETECT)
|
||||
schedule_work(&mhi_cntrl->syserr_worker);
|
||||
mhi_pm_sys_err_handler(mhi_cntrl);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -774,9 +792,18 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
|
||||
}
|
||||
case MHI_PKT_TYPE_TX_EVENT:
|
||||
chan = MHI_TRE_GET_EV_CHID(local_rp);
|
||||
mhi_chan = &mhi_cntrl->mhi_chan[chan];
|
||||
parse_xfer_event(mhi_cntrl, local_rp, mhi_chan);
|
||||
event_quota--;
|
||||
|
||||
WARN_ON(chan >= mhi_cntrl->max_chan);
|
||||
|
||||
/*
|
||||
* Only process the event ring elements whose channel
|
||||
* ID is within the maximum supported range.
|
||||
*/
|
||||
if (chan < mhi_cntrl->max_chan) {
|
||||
mhi_chan = &mhi_cntrl->mhi_chan[chan];
|
||||
parse_xfer_event(mhi_cntrl, local_rp, mhi_chan);
|
||||
event_quota--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "Unhandled event type: %d\n", type);
|
||||
@@ -819,14 +846,23 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
|
||||
enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);
|
||||
|
||||
chan = MHI_TRE_GET_EV_CHID(local_rp);
|
||||
mhi_chan = &mhi_cntrl->mhi_chan[chan];
|
||||
|
||||
if (likely(type == MHI_PKT_TYPE_TX_EVENT)) {
|
||||
parse_xfer_event(mhi_cntrl, local_rp, mhi_chan);
|
||||
event_quota--;
|
||||
} else if (type == MHI_PKT_TYPE_RSC_TX_EVENT) {
|
||||
parse_rsc_event(mhi_cntrl, local_rp, mhi_chan);
|
||||
event_quota--;
|
||||
WARN_ON(chan >= mhi_cntrl->max_chan);
|
||||
|
||||
/*
|
||||
* Only process the event ring elements whose channel
|
||||
* ID is within the maximum supported range.
|
||||
*/
|
||||
if (chan < mhi_cntrl->max_chan) {
|
||||
mhi_chan = &mhi_cntrl->mhi_chan[chan];
|
||||
|
||||
if (likely(type == MHI_PKT_TYPE_TX_EVENT)) {
|
||||
parse_xfer_event(mhi_cntrl, local_rp, mhi_chan);
|
||||
event_quota--;
|
||||
} else if (type == MHI_PKT_TYPE_RSC_TX_EVENT) {
|
||||
parse_rsc_event(mhi_cntrl, local_rp, mhi_chan);
|
||||
event_quota--;
|
||||
}
|
||||
}
|
||||
|
||||
mhi_recycle_ev_ring_element(mhi_cntrl, ev_ring);
|
||||
@@ -896,7 +932,7 @@ void mhi_ctrl_ev_task(unsigned long data)
|
||||
}
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
if (pm_state == MHI_PM_SYS_ERR_DETECT)
|
||||
schedule_work(&mhi_cntrl->syserr_worker);
|
||||
mhi_pm_sys_err_handler(mhi_cntrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,9 +954,7 @@ int mhi_queue_skb(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? mhi_dev->ul_chan :
|
||||
mhi_dev->dl_chan;
|
||||
struct mhi_ring *tre_ring = &mhi_chan->tre_ring;
|
||||
struct mhi_ring *buf_ring = &mhi_chan->buf_ring;
|
||||
struct mhi_buf_info *buf_info;
|
||||
struct mhi_tre *mhi_tre;
|
||||
struct mhi_buf_info buf_info = { };
|
||||
int ret;
|
||||
|
||||
/* If MHI host pre-allocates buffers then client drivers cannot queue */
|
||||
@@ -945,27 +979,15 @@ int mhi_queue_skb(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
/* Toggle wake to exit out of M2 */
|
||||
mhi_cntrl->wake_toggle(mhi_cntrl);
|
||||
|
||||
/* Generate the TRE */
|
||||
buf_info = buf_ring->wp;
|
||||
buf_info.v_addr = skb->data;
|
||||
buf_info.cb_buf = skb;
|
||||
buf_info.len = len;
|
||||
|
||||
buf_info->v_addr = skb->data;
|
||||
buf_info->cb_buf = skb;
|
||||
buf_info->wp = tre_ring->wp;
|
||||
buf_info->dir = mhi_chan->dir;
|
||||
buf_info->len = len;
|
||||
ret = mhi_cntrl->map_single(mhi_cntrl, buf_info);
|
||||
if (ret)
|
||||
goto map_error;
|
||||
|
||||
mhi_tre = tre_ring->wp;
|
||||
|
||||
mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr);
|
||||
mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_info->len);
|
||||
mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(1, 1, 0, 0);
|
||||
|
||||
/* increment WP */
|
||||
mhi_add_ring_element(mhi_cntrl, tre_ring);
|
||||
mhi_add_ring_element(mhi_cntrl, buf_ring);
|
||||
ret = mhi_gen_tre(mhi_cntrl, mhi_chan, &buf_info, mflags);
|
||||
if (unlikely(ret)) {
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mhi_chan->dir == DMA_TO_DEVICE)
|
||||
atomic_inc(&mhi_cntrl->pending_pkts);
|
||||
@@ -979,11 +1001,6 @@ int mhi_queue_skb(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
map_error:
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mhi_queue_skb);
|
||||
|
||||
@@ -995,9 +1012,8 @@ int mhi_queue_dma(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
mhi_dev->dl_chan;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
struct mhi_ring *tre_ring = &mhi_chan->tre_ring;
|
||||
struct mhi_ring *buf_ring = &mhi_chan->buf_ring;
|
||||
struct mhi_buf_info *buf_info;
|
||||
struct mhi_tre *mhi_tre;
|
||||
struct mhi_buf_info buf_info = { };
|
||||
int ret;
|
||||
|
||||
/* If MHI host pre-allocates buffers then client drivers cannot queue */
|
||||
if (mhi_chan->pre_alloc)
|
||||
@@ -1024,25 +1040,16 @@ int mhi_queue_dma(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
/* Toggle wake to exit out of M2 */
|
||||
mhi_cntrl->wake_toggle(mhi_cntrl);
|
||||
|
||||
/* Generate the TRE */
|
||||
buf_info = buf_ring->wp;
|
||||
WARN_ON(buf_info->used);
|
||||
buf_info->p_addr = mhi_buf->dma_addr;
|
||||
buf_info->pre_mapped = true;
|
||||
buf_info->cb_buf = mhi_buf;
|
||||
buf_info->wp = tre_ring->wp;
|
||||
buf_info->dir = mhi_chan->dir;
|
||||
buf_info->len = len;
|
||||
buf_info.p_addr = mhi_buf->dma_addr;
|
||||
buf_info.cb_buf = mhi_buf;
|
||||
buf_info.pre_mapped = true;
|
||||
buf_info.len = len;
|
||||
|
||||
mhi_tre = tre_ring->wp;
|
||||
|
||||
mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr);
|
||||
mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_info->len);
|
||||
mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(1, 1, 0, 0);
|
||||
|
||||
/* increment WP */
|
||||
mhi_add_ring_element(mhi_cntrl, tre_ring);
|
||||
mhi_add_ring_element(mhi_cntrl, buf_ring);
|
||||
ret = mhi_gen_tre(mhi_cntrl, mhi_chan, &buf_info, mflags);
|
||||
if (unlikely(ret)) {
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mhi_chan->dir == DMA_TO_DEVICE)
|
||||
atomic_inc(&mhi_cntrl->pending_pkts);
|
||||
@@ -1060,7 +1067,7 @@ int mhi_queue_dma(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
EXPORT_SYMBOL_GPL(mhi_queue_dma);
|
||||
|
||||
int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
void *buf, void *cb, size_t buf_len, enum mhi_flags flags)
|
||||
struct mhi_buf_info *info, enum mhi_flags flags)
|
||||
{
|
||||
struct mhi_ring *buf_ring, *tre_ring;
|
||||
struct mhi_tre *mhi_tre;
|
||||
@@ -1072,15 +1079,22 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
tre_ring = &mhi_chan->tre_ring;
|
||||
|
||||
buf_info = buf_ring->wp;
|
||||
buf_info->v_addr = buf;
|
||||
buf_info->cb_buf = cb;
|
||||
WARN_ON(buf_info->used);
|
||||
buf_info->pre_mapped = info->pre_mapped;
|
||||
if (info->pre_mapped)
|
||||
buf_info->p_addr = info->p_addr;
|
||||
else
|
||||
buf_info->v_addr = info->v_addr;
|
||||
buf_info->cb_buf = info->cb_buf;
|
||||
buf_info->wp = tre_ring->wp;
|
||||
buf_info->dir = mhi_chan->dir;
|
||||
buf_info->len = buf_len;
|
||||
buf_info->len = info->len;
|
||||
|
||||
ret = mhi_cntrl->map_single(mhi_cntrl, buf_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!info->pre_mapped) {
|
||||
ret = mhi_cntrl->map_single(mhi_cntrl, buf_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
eob = !!(flags & MHI_EOB);
|
||||
eot = !!(flags & MHI_EOT);
|
||||
@@ -1089,7 +1103,7 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
|
||||
|
||||
mhi_tre = tre_ring->wp;
|
||||
mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr);
|
||||
mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(buf_len);
|
||||
mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
|
||||
mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain);
|
||||
|
||||
/* increment WP */
|
||||
@@ -1106,6 +1120,7 @@ int mhi_queue_buf(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? mhi_dev->ul_chan :
|
||||
mhi_dev->dl_chan;
|
||||
struct mhi_ring *tre_ring;
|
||||
struct mhi_buf_info buf_info = { };
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
@@ -1121,7 +1136,11 @@ int mhi_queue_buf(struct mhi_device *mhi_dev, enum dma_data_direction dir,
|
||||
if (mhi_is_ring_full(mhi_cntrl, tre_ring))
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mhi_gen_tre(mhi_cntrl, mhi_chan, buf, buf, len, mflags);
|
||||
buf_info.v_addr = buf;
|
||||
buf_info.cb_buf = buf;
|
||||
buf_info.len = len;
|
||||
|
||||
ret = mhi_gen_tre(mhi_cntrl, mhi_chan, &buf_info, mflags);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
@@ -1322,7 +1341,7 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
|
||||
|
||||
while (nr_el--) {
|
||||
void *buf;
|
||||
|
||||
struct mhi_buf_info info = { };
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
@@ -1330,8 +1349,10 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
|
||||
}
|
||||
|
||||
/* Prepare transfer descriptors */
|
||||
ret = mhi_gen_tre(mhi_cntrl, mhi_chan, buf, buf,
|
||||
len, MHI_EOT);
|
||||
info.v_addr = buf;
|
||||
info.cb_buf = buf;
|
||||
info.len = len;
|
||||
ret = mhi_gen_tre(mhi_cntrl, mhi_chan, &info, MHI_EOT);
|
||||
if (ret) {
|
||||
kfree(buf);
|
||||
goto error_pre_alloc;
|
||||
|
||||
+202
-27
@@ -288,14 +288,18 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
|
||||
for (i = 0; i < mhi_cntrl->max_chan; i++, mhi_chan++) {
|
||||
struct mhi_ring *tre_ring = &mhi_chan->tre_ring;
|
||||
|
||||
write_lock_irq(&mhi_chan->lock);
|
||||
if (mhi_chan->db_cfg.reset_req)
|
||||
if (mhi_chan->db_cfg.reset_req) {
|
||||
write_lock_irq(&mhi_chan->lock);
|
||||
mhi_chan->db_cfg.db_mode = true;
|
||||
write_unlock_irq(&mhi_chan->lock);
|
||||
}
|
||||
|
||||
read_lock_irq(&mhi_chan->lock);
|
||||
|
||||
/* Only ring DB if ring is not empty */
|
||||
if (tre_ring->base && tre_ring->wp != tre_ring->rp)
|
||||
mhi_ring_chan_db(mhi_cntrl, mhi_chan);
|
||||
write_unlock_irq(&mhi_chan->lock);
|
||||
read_unlock_irq(&mhi_chan->lock);
|
||||
}
|
||||
|
||||
mhi_cntrl->wake_put(mhi_cntrl, false);
|
||||
@@ -449,19 +453,8 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
|
||||
to_mhi_pm_state_str(transition_state));
|
||||
|
||||
/* We must notify MHI control driver so it can clean up first */
|
||||
if (transition_state == MHI_PM_SYS_ERR_PROCESS) {
|
||||
/*
|
||||
* If controller supports RDDM, we do not process
|
||||
* SYS error state, instead we will jump directly
|
||||
* to RDDM state
|
||||
*/
|
||||
if (mhi_cntrl->rddm_image) {
|
||||
dev_dbg(dev,
|
||||
"Controller supports RDDM, so skip SYS_ERR\n");
|
||||
return;
|
||||
}
|
||||
if (transition_state == MHI_PM_SYS_ERR_PROCESS)
|
||||
mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_SYS_ERROR);
|
||||
}
|
||||
|
||||
mutex_lock(&mhi_cntrl->pm_mutex);
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
@@ -527,8 +520,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl,
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
dev_dbg(dev, "Waiting for all pending threads to complete\n");
|
||||
wake_up_all(&mhi_cntrl->state_event);
|
||||
flush_work(&mhi_cntrl->st_worker);
|
||||
flush_work(&mhi_cntrl->fw_worker);
|
||||
|
||||
dev_dbg(dev, "Reset all active channels and remove MHI devices\n");
|
||||
device_for_each_child(mhi_cntrl->cntrl_dev, NULL, mhi_destroy_device);
|
||||
@@ -608,13 +599,17 @@ int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl,
|
||||
}
|
||||
|
||||
/* SYS_ERR worker */
|
||||
void mhi_pm_sys_err_worker(struct work_struct *work)
|
||||
void mhi_pm_sys_err_handler(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_controller *mhi_cntrl = container_of(work,
|
||||
struct mhi_controller,
|
||||
syserr_worker);
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
|
||||
mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS);
|
||||
/* skip if controller supports RDDM */
|
||||
if (mhi_cntrl->rddm_image) {
|
||||
dev_dbg(dev, "Controller supports RDDM, skip SYS_ERROR\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mhi_queue_state_transition(mhi_cntrl, DEV_ST_TRANSITION_SYS_ERR);
|
||||
}
|
||||
|
||||
/* Device State Transition worker */
|
||||
@@ -643,7 +638,7 @@ void mhi_pm_st_worker(struct work_struct *work)
|
||||
mhi_cntrl->ee = mhi_get_exec_env(mhi_cntrl);
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
if (MHI_IN_PBL(mhi_cntrl->ee))
|
||||
wake_up_all(&mhi_cntrl->state_event);
|
||||
mhi_fw_load_handler(mhi_cntrl);
|
||||
break;
|
||||
case DEV_ST_TRANSITION_SBL:
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
@@ -662,6 +657,14 @@ void mhi_pm_st_worker(struct work_struct *work)
|
||||
case DEV_ST_TRANSITION_READY:
|
||||
mhi_ready_state_transition(mhi_cntrl);
|
||||
break;
|
||||
case DEV_ST_TRANSITION_SYS_ERR:
|
||||
mhi_pm_disable_transition
|
||||
(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS);
|
||||
break;
|
||||
case DEV_ST_TRANSITION_DISABLE:
|
||||
mhi_pm_disable_transition
|
||||
(mhi_cntrl, MHI_PM_SHUTDOWN_PROCESS);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -669,6 +672,149 @@ void mhi_pm_st_worker(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
int mhi_pm_suspend(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_chan *itr, *tmp;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
enum mhi_pm_state new_state;
|
||||
int ret;
|
||||
|
||||
if (mhi_cntrl->pm_state == MHI_PM_DISABLE)
|
||||
return -EINVAL;
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
return -EIO;
|
||||
|
||||
/* Return busy if there are any pending resources */
|
||||
if (atomic_read(&mhi_cntrl->dev_wake))
|
||||
return -EBUSY;
|
||||
|
||||
/* Take MHI out of M2 state */
|
||||
read_lock_bh(&mhi_cntrl->pm_lock);
|
||||
mhi_cntrl->wake_get(mhi_cntrl, false);
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_cntrl->dev_state == MHI_STATE_M0 ||
|
||||
mhi_cntrl->dev_state == MHI_STATE_M1 ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
read_lock_bh(&mhi_cntrl->pm_lock);
|
||||
mhi_cntrl->wake_put(mhi_cntrl, false);
|
||||
read_unlock_bh(&mhi_cntrl->pm_lock);
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
dev_err(dev,
|
||||
"Could not enter M0/M1 state");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
|
||||
if (atomic_read(&mhi_cntrl->dev_wake)) {
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev_info(dev, "Allowing M3 transition\n");
|
||||
new_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3_ENTER);
|
||||
if (new_state != MHI_PM_M3_ENTER) {
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
dev_err(dev,
|
||||
"Error setting to PM state: %s from: %s\n",
|
||||
to_mhi_pm_state_str(MHI_PM_M3_ENTER),
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set MHI to M3 and wait for completion */
|
||||
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M3);
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
dev_info(dev, "Wait for M3 completion\n");
|
||||
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_cntrl->dev_state == MHI_STATE_M3 ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
dev_err(dev,
|
||||
"Did not enter M3 state, MHI state: %s, PM state: %s\n",
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state),
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Notify clients about entering LPM */
|
||||
list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) {
|
||||
mutex_lock(&itr->mutex);
|
||||
if (itr->mhi_dev)
|
||||
mhi_notify(itr->mhi_dev, MHI_CB_LPM_ENTER);
|
||||
mutex_unlock(&itr->mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mhi_pm_suspend);
|
||||
|
||||
int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
struct mhi_chan *itr, *tmp;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
enum mhi_pm_state cur_state;
|
||||
int ret;
|
||||
|
||||
dev_info(dev, "Entered with PM state: %s, MHI state: %s\n",
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state),
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state));
|
||||
|
||||
if (mhi_cntrl->pm_state == MHI_PM_DISABLE)
|
||||
return 0;
|
||||
|
||||
if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
|
||||
return -EIO;
|
||||
|
||||
/* Notify clients about exiting LPM */
|
||||
list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) {
|
||||
mutex_lock(&itr->mutex);
|
||||
if (itr->mhi_dev)
|
||||
mhi_notify(itr->mhi_dev, MHI_CB_LPM_EXIT);
|
||||
mutex_unlock(&itr->mutex);
|
||||
}
|
||||
|
||||
write_lock_irq(&mhi_cntrl->pm_lock);
|
||||
cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M3_EXIT);
|
||||
if (cur_state != MHI_PM_M3_EXIT) {
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
dev_info(dev,
|
||||
"Error setting to PM state: %s from: %s\n",
|
||||
to_mhi_pm_state_str(MHI_PM_M3_EXIT),
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set MHI to M0 and wait for completion */
|
||||
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M0);
|
||||
write_unlock_irq(&mhi_cntrl->pm_lock);
|
||||
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
mhi_cntrl->dev_state == MHI_STATE_M0 ||
|
||||
MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state),
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
|
||||
if (!ret || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
|
||||
dev_err(dev,
|
||||
"Did not enter M0 state, MHI state: %s, PM state: %s\n",
|
||||
TO_MHI_STATE_STR(mhi_cntrl->dev_state),
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mhi_pm_resume);
|
||||
|
||||
int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
int ret;
|
||||
@@ -760,6 +906,7 @@ static void mhi_deassert_dev_wake(struct mhi_controller *mhi_cntrl,
|
||||
|
||||
int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
enum mhi_state state;
|
||||
enum mhi_ee_type current_ee;
|
||||
enum dev_st_transition next_state;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
@@ -829,13 +976,36 @@ int mhi_async_power_up(struct mhi_controller *mhi_cntrl)
|
||||
goto error_bhi_offset;
|
||||
}
|
||||
|
||||
state = mhi_get_mhi_state(mhi_cntrl);
|
||||
if (state == MHI_STATE_SYS_ERR) {
|
||||
mhi_set_mhi_state(mhi_cntrl, MHI_STATE_RESET);
|
||||
ret = wait_event_timeout(mhi_cntrl->state_event,
|
||||
MHI_PM_IN_FATAL_STATE(mhi_cntrl->pm_state) ||
|
||||
mhi_read_reg_field(mhi_cntrl,
|
||||
mhi_cntrl->regs,
|
||||
MHICTRL,
|
||||
MHICTRL_RESET_MASK,
|
||||
MHICTRL_RESET_SHIFT,
|
||||
&val) ||
|
||||
!val,
|
||||
msecs_to_jiffies(mhi_cntrl->timeout_ms));
|
||||
if (ret) {
|
||||
ret = -EIO;
|
||||
dev_info(dev, "Failed to reset MHI due to syserr state\n");
|
||||
goto error_bhi_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* device cleares INTVEC as part of RESET processing,
|
||||
* re-program it
|
||||
*/
|
||||
mhi_write_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_INTVEC, 0);
|
||||
}
|
||||
|
||||
/* Transition to next state */
|
||||
next_state = MHI_IN_PBL(current_ee) ?
|
||||
DEV_ST_TRANSITION_PBL : DEV_ST_TRANSITION_READY;
|
||||
|
||||
if (next_state == DEV_ST_TRANSITION_PBL)
|
||||
schedule_work(&mhi_cntrl->fw_worker);
|
||||
|
||||
mhi_queue_state_transition(mhi_cntrl, next_state);
|
||||
|
||||
mutex_unlock(&mhi_cntrl->pm_mutex);
|
||||
@@ -876,7 +1046,12 @@ void mhi_power_down(struct mhi_controller *mhi_cntrl, bool graceful)
|
||||
to_mhi_pm_state_str(MHI_PM_LD_ERR_FATAL_DETECT),
|
||||
to_mhi_pm_state_str(mhi_cntrl->pm_state));
|
||||
}
|
||||
mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SHUTDOWN_PROCESS);
|
||||
|
||||
mhi_queue_state_transition(mhi_cntrl, DEV_ST_TRANSITION_DISABLE);
|
||||
|
||||
/* Wait for shutdown to complete */
|
||||
flush_work(&mhi_cntrl->st_worker);
|
||||
|
||||
mhi_deinit_free_irq(mhi_cntrl);
|
||||
|
||||
if (!mhi_cntrl->pre_init) {
|
||||
|
||||
+99
-2
@@ -31,11 +31,15 @@
|
||||
#include <linux/uio.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/pseudo_fs.h>
|
||||
#include <uapi/linux/magic.h>
|
||||
#include <linux/mount.h>
|
||||
|
||||
#ifdef CONFIG_IA64
|
||||
# include <linux/efi.h>
|
||||
#endif
|
||||
|
||||
#define DEVMEM_MINOR 1
|
||||
#define DEVPORT_MINOR 4
|
||||
|
||||
static inline unsigned long size_inside_page(unsigned long start,
|
||||
@@ -805,12 +809,64 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct inode *devmem_inode;
|
||||
|
||||
#ifdef CONFIG_IO_STRICT_DEVMEM
|
||||
void revoke_devmem(struct resource *res)
|
||||
{
|
||||
struct inode *inode = READ_ONCE(devmem_inode);
|
||||
|
||||
/*
|
||||
* Check that the initialization has completed. Losing the race
|
||||
* is ok because it means drivers are claiming resources before
|
||||
* the fs_initcall level of init and prevent /dev/mem from
|
||||
* establishing mappings.
|
||||
*/
|
||||
if (!inode)
|
||||
return;
|
||||
|
||||
/*
|
||||
* The expectation is that the driver has successfully marked
|
||||
* the resource busy by this point, so devmem_is_allowed()
|
||||
* should start returning false, however for performance this
|
||||
* does not iterate the entire resource range.
|
||||
*/
|
||||
if (devmem_is_allowed(PHYS_PFN(res->start)) &&
|
||||
devmem_is_allowed(PHYS_PFN(res->end))) {
|
||||
/*
|
||||
* *cringe* iomem=relaxed says "go ahead, what's the
|
||||
* worst that can happen?"
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
unmap_mapping_range(inode->i_mapping, res->start, resource_size(res), 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int open_port(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
|
||||
return security_locked_down(LOCKDOWN_DEV_MEM);
|
||||
rc = security_locked_down(LOCKDOWN_DEV_MEM);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (iminor(inode) != DEVMEM_MINOR)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Use a unified address space to have a single point to manage
|
||||
* revocations when drivers want to take over a /dev/mem mapped
|
||||
* range.
|
||||
*/
|
||||
inode->i_mapping = devmem_inode->i_mapping;
|
||||
filp->f_mapping = inode->i_mapping;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define zero_lseek null_lseek
|
||||
@@ -885,7 +941,7 @@ static const struct memdev {
|
||||
fmode_t fmode;
|
||||
} devlist[] = {
|
||||
#ifdef CONFIG_DEVMEM
|
||||
[1] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
|
||||
[DEVMEM_MINOR] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
|
||||
#endif
|
||||
#ifdef CONFIG_DEVKMEM
|
||||
[2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET },
|
||||
@@ -939,6 +995,45 @@ static char *mem_devnode(struct device *dev, umode_t *mode)
|
||||
|
||||
static struct class *mem_class;
|
||||
|
||||
static int devmem_fs_init_fs_context(struct fs_context *fc)
|
||||
{
|
||||
return init_pseudo(fc, DEVMEM_MAGIC) ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
static struct file_system_type devmem_fs_type = {
|
||||
.name = "devmem",
|
||||
.owner = THIS_MODULE,
|
||||
.init_fs_context = devmem_fs_init_fs_context,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
static int devmem_init_inode(void)
|
||||
{
|
||||
static struct vfsmount *devmem_vfs_mount;
|
||||
static int devmem_fs_cnt;
|
||||
struct inode *inode;
|
||||
int rc;
|
||||
|
||||
rc = simple_pin_fs(&devmem_fs_type, &devmem_vfs_mount, &devmem_fs_cnt);
|
||||
if (rc < 0) {
|
||||
pr_err("Cannot mount /dev/mem pseudo filesystem: %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
inode = alloc_anon_inode(devmem_vfs_mount->mnt_sb);
|
||||
if (IS_ERR(inode)) {
|
||||
rc = PTR_ERR(inode);
|
||||
pr_err("Cannot allocate inode for /dev/mem: %d\n", rc);
|
||||
simple_release_fs(&devmem_vfs_mount, &devmem_fs_cnt);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* publish /dev/mem initialized */
|
||||
WRITE_ONCE(devmem_inode, inode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init chr_dev_init(void)
|
||||
{
|
||||
int minor;
|
||||
@@ -960,6 +1055,8 @@ static int __init chr_dev_init(void)
|
||||
*/
|
||||
if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
|
||||
continue;
|
||||
if ((minor == DEVMEM_MINOR) && devmem_init_inode() != 0)
|
||||
continue;
|
||||
|
||||
device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
|
||||
NULL, devlist[minor].name);
|
||||
|
||||
+11
-8
@@ -777,18 +777,22 @@ static int __init tlclk_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
|
||||
return ret;
|
||||
}
|
||||
tlclk_major = ret;
|
||||
telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
|
||||
|
||||
alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
|
||||
if (!alarm_events) {
|
||||
ret = -ENOMEM;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
|
||||
kfree(alarm_events);
|
||||
return ret;
|
||||
}
|
||||
tlclk_major = ret;
|
||||
|
||||
/* Read telecom clock IRQ number (Set by BIOS) */
|
||||
if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
|
||||
printk(KERN_ERR "tlclk: request_region 0x%X failed.\n",
|
||||
@@ -796,7 +800,6 @@ static int __init tlclk_init(void)
|
||||
ret = -EBUSY;
|
||||
goto out2;
|
||||
}
|
||||
telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
|
||||
|
||||
if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
|
||||
printk(KERN_ERR "telclk_interrupt = 0x%x non-mcpbl0010 hw.\n",
|
||||
@@ -837,8 +840,8 @@ out3:
|
||||
release_region(TLCLK_BASE, 8);
|
||||
out2:
|
||||
kfree(alarm_events);
|
||||
out1:
|
||||
unregister_chrdev(tlclk_major, "telco_clock");
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,9 +37,8 @@ static int zynqmp_clk_gate_enable(struct clk_hw *hw)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
u32 clk_id = gate->clk_id;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_enable(clk_id);
|
||||
ret = zynqmp_pm_clock_enable(clk_id);
|
||||
|
||||
if (ret)
|
||||
pr_warn_once("%s() clock enabled failed for %s, ret = %d\n",
|
||||
@@ -58,9 +57,8 @@ static void zynqmp_clk_gate_disable(struct clk_hw *hw)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
u32 clk_id = gate->clk_id;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_disable(clk_id);
|
||||
ret = zynqmp_pm_clock_disable(clk_id);
|
||||
|
||||
if (ret)
|
||||
pr_warn_once("%s() clock disable failed for %s, ret = %d\n",
|
||||
@@ -79,9 +77,8 @@ static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
u32 clk_id = gate->clk_id;
|
||||
int state, ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_getstate(clk_id, &state);
|
||||
ret = zynqmp_pm_clock_getstate(clk_id, &state);
|
||||
if (ret) {
|
||||
pr_warn_once("%s() clock get state failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
|
||||
@@ -47,9 +47,8 @@ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw)
|
||||
u32 clk_id = mux->clk_id;
|
||||
u32 val;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_getparent(clk_id, &val);
|
||||
ret = zynqmp_pm_clock_getparent(clk_id, &val);
|
||||
|
||||
if (ret)
|
||||
pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n",
|
||||
@@ -71,9 +70,8 @@ static int zynqmp_clk_mux_set_parent(struct clk_hw *hw, u8 index)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
u32 clk_id = mux->clk_id;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_setparent(clk_id, index);
|
||||
ret = zynqmp_pm_clock_setparent(clk_id, index);
|
||||
|
||||
if (ret)
|
||||
pr_warn_once("%s() set parent failed for clock: %s, ret = %d\n",
|
||||
|
||||
@@ -134,7 +134,6 @@ static struct clk_hw *(* const clk_topology[]) (const char *name, u32 clk_id,
|
||||
static struct zynqmp_clock *clock;
|
||||
static struct clk_hw_onecell_data *zynqmp_data;
|
||||
static unsigned int clock_max_idx;
|
||||
static const struct zynqmp_eemi_ops *eemi_ops;
|
||||
|
||||
/**
|
||||
* zynqmp_is_valid_clock() - Check whether clock is valid or not
|
||||
@@ -206,7 +205,7 @@ static int zynqmp_pm_clock_get_num_clocks(u32 *nclocks)
|
||||
|
||||
qdata.qid = PM_QID_CLOCK_GET_NUM_CLOCKS;
|
||||
|
||||
ret = eemi_ops->query_data(qdata, ret_payload);
|
||||
ret = zynqmp_pm_query_data(qdata, ret_payload);
|
||||
*nclocks = ret_payload[1];
|
||||
|
||||
return ret;
|
||||
@@ -231,7 +230,7 @@ static int zynqmp_pm_clock_get_name(u32 clock_id,
|
||||
qdata.qid = PM_QID_CLOCK_GET_NAME;
|
||||
qdata.arg1 = clock_id;
|
||||
|
||||
eemi_ops->query_data(qdata, ret_payload);
|
||||
zynqmp_pm_query_data(qdata, ret_payload);
|
||||
memcpy(response, ret_payload, sizeof(*response));
|
||||
|
||||
return 0;
|
||||
@@ -265,7 +264,7 @@ static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index,
|
||||
qdata.arg1 = clock_id;
|
||||
qdata.arg2 = index;
|
||||
|
||||
ret = eemi_ops->query_data(qdata, ret_payload);
|
||||
ret = zynqmp_pm_query_data(qdata, ret_payload);
|
||||
memcpy(response, &ret_payload[1], sizeof(*response));
|
||||
|
||||
return ret;
|
||||
@@ -296,7 +295,7 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id,
|
||||
qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS;
|
||||
qdata.arg1 = clk_id;
|
||||
|
||||
ret = eemi_ops->query_data(qdata, ret_payload);
|
||||
ret = zynqmp_pm_query_data(qdata, ret_payload);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@@ -339,7 +338,7 @@ static int zynqmp_pm_clock_get_parents(u32 clock_id, u32 index,
|
||||
qdata.arg1 = clock_id;
|
||||
qdata.arg2 = index;
|
||||
|
||||
ret = eemi_ops->query_data(qdata, ret_payload);
|
||||
ret = zynqmp_pm_query_data(qdata, ret_payload);
|
||||
memcpy(response, &ret_payload[1], sizeof(*response));
|
||||
|
||||
return ret;
|
||||
@@ -364,7 +363,7 @@ static int zynqmp_pm_clock_get_attributes(u32 clock_id,
|
||||
qdata.qid = PM_QID_CLOCK_GET_ATTRIBUTES;
|
||||
qdata.arg1 = clock_id;
|
||||
|
||||
ret = eemi_ops->query_data(qdata, ret_payload);
|
||||
ret = zynqmp_pm_query_data(qdata, ret_payload);
|
||||
memcpy(response, &ret_payload[1], sizeof(*response));
|
||||
|
||||
return ret;
|
||||
@@ -738,10 +737,6 @@ static int zynqmp_clock_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
if (IS_ERR(eemi_ops))
|
||||
return PTR_ERR(eemi_ops);
|
||||
|
||||
ret = zynqmp_clk_setup(dev->of_node);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -83,9 +83,8 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw,
|
||||
u32 div_type = divider->div_type;
|
||||
u32 div, value;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_getdivider(clk_id, &div);
|
||||
ret = zynqmp_pm_clock_getdivider(clk_id, &div);
|
||||
|
||||
if (ret)
|
||||
pr_warn_once("%s() get divider failed for %s, ret = %d\n",
|
||||
@@ -163,11 +162,10 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw,
|
||||
u32 div_type = divider->div_type;
|
||||
u32 bestdiv;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
/* if read only, just return current value */
|
||||
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
|
||||
ret = eemi_ops->clock_getdivider(clk_id, &bestdiv);
|
||||
ret = zynqmp_pm_clock_getdivider(clk_id, &bestdiv);
|
||||
|
||||
if (ret)
|
||||
pr_warn_once("%s() get divider failed for %s, ret = %d\n",
|
||||
@@ -219,7 +217,6 @@ static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
u32 div_type = divider->div_type;
|
||||
u32 value, div;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
value = zynqmp_divider_get_val(parent_rate, rate, divider->flags);
|
||||
if (div_type == TYPE_DIV1) {
|
||||
@@ -233,7 +230,7 @@ static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
|
||||
div = __ffs(div);
|
||||
|
||||
ret = eemi_ops->clock_setdivider(clk_id, div);
|
||||
ret = zynqmp_pm_clock_setdivider(clk_id, div);
|
||||
|
||||
if (ret)
|
||||
pr_warn_once("%s() set divider failed for %s, ret = %d\n",
|
||||
@@ -258,7 +255,6 @@ static const struct clk_ops zynqmp_clk_divider_ops = {
|
||||
*/
|
||||
u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
|
||||
{
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
struct zynqmp_pm_query_data qdata = {0};
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -266,7 +262,7 @@ u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
|
||||
qdata.qid = PM_QID_CLOCK_GET_MAX_DIVISOR;
|
||||
qdata.arg1 = clk_id;
|
||||
qdata.arg2 = type;
|
||||
ret = eemi_ops->query_data(qdata, ret_payload);
|
||||
ret = zynqmp_pm_query_data(qdata, ret_payload);
|
||||
/*
|
||||
* To maintain backward compatibility return maximum possible value
|
||||
* (0xFFFF) if query for max divisor is not successful.
|
||||
|
||||
+10
-19
@@ -50,10 +50,8 @@ static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->ioctl(0, IOCTL_GET_PLL_FRAC_MODE, clk_id, 0,
|
||||
ret_payload);
|
||||
ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload);
|
||||
if (ret)
|
||||
pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
@@ -73,14 +71,13 @@ static inline void zynqmp_pll_set_mode(struct clk_hw *hw, bool on)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
int ret;
|
||||
u32 mode;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
if (on)
|
||||
mode = PLL_MODE_FRAC;
|
||||
else
|
||||
mode = PLL_MODE_INT;
|
||||
|
||||
ret = eemi_ops->ioctl(0, IOCTL_SET_PLL_FRAC_MODE, clk_id, mode, NULL);
|
||||
ret = zynqmp_pm_set_pll_frac_mode(clk_id, mode);
|
||||
if (ret)
|
||||
pr_warn_once("%s() PLL set frac mode failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
@@ -139,17 +136,15 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long rate, frac;
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_getdivider(clk_id, &fbdiv);
|
||||
ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv);
|
||||
if (ret)
|
||||
pr_warn_once("%s() get divider failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
|
||||
rate = parent_rate * fbdiv;
|
||||
if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) {
|
||||
eemi_ops->ioctl(0, IOCTL_GET_PLL_FRAC_DATA, clk_id, 0,
|
||||
ret_payload);
|
||||
zynqmp_pm_get_pll_frac_data(clk_id, ret_payload);
|
||||
data = ret_payload[1];
|
||||
frac = (parent_rate * data) / FRAC_DIV;
|
||||
rate = rate + frac;
|
||||
@@ -177,7 +172,6 @@ static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
u32 fbdiv;
|
||||
long rate_div, frac, m, f;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) {
|
||||
rate_div = (rate * FRAC_DIV) / parent_rate;
|
||||
@@ -187,21 +181,21 @@ static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
rate = parent_rate * m;
|
||||
frac = (parent_rate * f) / FRAC_DIV;
|
||||
|
||||
ret = eemi_ops->clock_setdivider(clk_id, m);
|
||||
ret = zynqmp_pm_clock_setdivider(clk_id, m);
|
||||
if (ret == -EUSERS)
|
||||
WARN(1, "More than allowed devices are using the %s, which is forbidden\n",
|
||||
clk_name);
|
||||
else if (ret)
|
||||
pr_warn_once("%s() set divider failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
eemi_ops->ioctl(0, IOCTL_SET_PLL_FRAC_DATA, clk_id, f, NULL);
|
||||
zynqmp_pm_set_pll_frac_data(clk_id, f);
|
||||
|
||||
return rate + frac;
|
||||
}
|
||||
|
||||
fbdiv = DIV_ROUND_CLOSEST(rate, parent_rate);
|
||||
fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
|
||||
ret = eemi_ops->clock_setdivider(clk_id, fbdiv);
|
||||
ret = zynqmp_pm_clock_setdivider(clk_id, fbdiv);
|
||||
if (ret)
|
||||
pr_warn_once("%s() set divider failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
@@ -222,9 +216,8 @@ static int zynqmp_pll_is_enabled(struct clk_hw *hw)
|
||||
u32 clk_id = clk->clk_id;
|
||||
unsigned int state;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
ret = eemi_ops->clock_getstate(clk_id, &state);
|
||||
ret = zynqmp_pm_clock_getstate(clk_id, &state);
|
||||
if (ret) {
|
||||
pr_warn_once("%s() clock get state failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
@@ -246,12 +239,11 @@ static int zynqmp_pll_enable(struct clk_hw *hw)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
u32 clk_id = clk->clk_id;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
if (zynqmp_pll_is_enabled(hw))
|
||||
return 0;
|
||||
|
||||
ret = eemi_ops->clock_enable(clk_id);
|
||||
ret = zynqmp_pm_clock_enable(clk_id);
|
||||
if (ret)
|
||||
pr_warn_once("%s() clock enable failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
@@ -269,12 +261,11 @@ static void zynqmp_pll_disable(struct clk_hw *hw)
|
||||
const char *clk_name = clk_hw_get_name(hw);
|
||||
u32 clk_id = clk->clk_id;
|
||||
int ret;
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
|
||||
if (!zynqmp_pll_is_enabled(hw))
|
||||
return;
|
||||
|
||||
ret = eemi_ops->clock_disable(clk_id);
|
||||
ret = zynqmp_pm_clock_disable(clk_id);
|
||||
if (ret)
|
||||
pr_warn_once("%s() clock disable failed for %s, ret = %d\n",
|
||||
__func__, clk_name, ret);
|
||||
|
||||
@@ -46,7 +46,6 @@ struct zynqmp_aead_drv_ctx {
|
||||
} alg;
|
||||
struct device *dev;
|
||||
struct crypto_engine *engine;
|
||||
const struct zynqmp_eemi_ops *eemi_ops;
|
||||
};
|
||||
|
||||
struct zynqmp_aead_hw_req {
|
||||
@@ -80,21 +79,15 @@ static int zynqmp_aes_aead_cipher(struct aead_request *req)
|
||||
struct zynqmp_aead_tfm_ctx *tfm_ctx = crypto_aead_ctx(aead);
|
||||
struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req);
|
||||
struct device *dev = tfm_ctx->dev;
|
||||
struct aead_alg *alg = crypto_aead_alg(aead);
|
||||
struct zynqmp_aead_drv_ctx *drv_ctx;
|
||||
struct zynqmp_aead_hw_req *hwreq;
|
||||
dma_addr_t dma_addr_data, dma_addr_hw_req;
|
||||
unsigned int data_size;
|
||||
unsigned int status;
|
||||
int ret;
|
||||
size_t dma_size;
|
||||
char *kbuf;
|
||||
int err;
|
||||
|
||||
drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead);
|
||||
|
||||
if (!drv_ctx->eemi_ops->aes)
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (tfm_ctx->keysrc == ZYNQMP_AES_KUP_KEY)
|
||||
dma_size = req->cryptlen + ZYNQMP_AES_KEY_SIZE
|
||||
+ GCM_AES_IV_SIZE;
|
||||
@@ -136,9 +129,12 @@ static int zynqmp_aes_aead_cipher(struct aead_request *req)
|
||||
hwreq->key = 0;
|
||||
}
|
||||
|
||||
drv_ctx->eemi_ops->aes(dma_addr_hw_req, &status);
|
||||
ret = zynqmp_pm_aes_engine(dma_addr_hw_req, &status);
|
||||
|
||||
if (status) {
|
||||
if (ret) {
|
||||
dev_err(dev, "ERROR: AES PM API failed\n");
|
||||
err = ret;
|
||||
} else if (status) {
|
||||
switch (status) {
|
||||
case ZYNQMP_AES_GCM_TAG_MISMATCH_ERR:
|
||||
dev_err(dev, "ERROR: Gcm Tag mismatch\n");
|
||||
@@ -388,12 +384,6 @@ static int zynqmp_aes_aead_probe(struct platform_device *pdev)
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
aes_drv_ctx.eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
if (IS_ERR(aes_drv_ctx.eemi_ops)) {
|
||||
dev_err(dev, "Failed to get ZynqMP EEMI interface\n");
|
||||
return PTR_ERR(aes_drv_ctx.eemi_ops);
|
||||
}
|
||||
|
||||
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(ZYNQMP_DMA_BIT_MASK));
|
||||
if (err < 0) {
|
||||
dev_err(dev, "No usable DMA configuration\n");
|
||||
|
||||
@@ -24,9 +24,7 @@ int dca_sysfs_add_req(struct dca_provider *dca, struct device *dev, int slot)
|
||||
|
||||
cd = device_create(dca_class, dca->cd, MKDEV(0, slot + 1), NULL,
|
||||
"requester%d", req_count++);
|
||||
if (IS_ERR(cd))
|
||||
return PTR_ERR(cd);
|
||||
return 0;
|
||||
return PTR_ERR_OR_ZERO(cd);
|
||||
}
|
||||
|
||||
void dca_sysfs_remove_req(struct dca_provider *dca, int slot)
|
||||
|
||||
@@ -124,7 +124,7 @@ static int adc_jack_probe(struct platform_device *pdev)
|
||||
for (i = 0; data->adc_conditions[i].id != EXTCON_NONE; i++);
|
||||
data->num_conditions = i;
|
||||
|
||||
data->chan = iio_channel_get(&pdev->dev, pdata->consumer_channel);
|
||||
data->chan = devm_iio_channel_get(&pdev->dev, pdata->consumer_channel);
|
||||
if (IS_ERR(data->chan))
|
||||
return PTR_ERR(data->chan);
|
||||
|
||||
@@ -164,7 +164,6 @@ static int adc_jack_remove(struct platform_device *pdev)
|
||||
|
||||
free_irq(data->irq, data);
|
||||
cancel_work_sync(&data->handler.work);
|
||||
iio_channel_release(data->chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1460,7 +1460,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
if (!info->input) {
|
||||
dev_err(arizona->dev, "Can't allocate input dev\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_register;
|
||||
return ret;
|
||||
}
|
||||
|
||||
info->input->name = "Headset";
|
||||
@@ -1492,7 +1492,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
if (ret != 0) {
|
||||
dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
|
||||
pdata->micd_pol_gpio, ret);
|
||||
goto err_register;
|
||||
return ret;
|
||||
}
|
||||
|
||||
info->micd_pol_gpio = gpio_to_desc(pdata->micd_pol_gpio);
|
||||
@@ -1515,7 +1515,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
dev_err(arizona->dev,
|
||||
"Failed to get microphone polarity GPIO: %d\n",
|
||||
ret);
|
||||
goto err_register;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1672,7 +1672,7 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
|
||||
ret);
|
||||
goto err_gpio;
|
||||
goto err_pm;
|
||||
}
|
||||
|
||||
ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
|
||||
@@ -1721,14 +1721,14 @@ static int arizona_extcon_probe(struct platform_device *pdev)
|
||||
dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
|
||||
ret);
|
||||
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
ret = input_register_device(info->input);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
|
||||
goto err_hpdet;
|
||||
}
|
||||
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_hpdet:
|
||||
@@ -1743,10 +1743,11 @@ err_rise_wake:
|
||||
arizona_set_irq_wake(arizona, jack_irq_rise, 0);
|
||||
err_rise:
|
||||
arizona_free_irq(arizona, jack_irq_rise, info);
|
||||
err_pm:
|
||||
pm_runtime_put(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
err_gpio:
|
||||
gpiod_put(info->micd_pol_gpio);
|
||||
err_register:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -782,9 +782,19 @@ static const struct platform_device_id max14577_muic_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, max14577_muic_id);
|
||||
|
||||
static const struct of_device_id of_max14577_muic_dt_match[] = {
|
||||
{ .compatible = "maxim,max14577-muic",
|
||||
.data = (void *)MAXIM_DEVICE_TYPE_MAX14577, },
|
||||
{ .compatible = "maxim,max77836-muic",
|
||||
.data = (void *)MAXIM_DEVICE_TYPE_MAX77836, },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_max14577_muic_dt_match);
|
||||
|
||||
static struct platform_driver max14577_muic_driver = {
|
||||
.driver = {
|
||||
.name = "max14577-muic",
|
||||
.of_match_table = of_max14577_muic_dt_match,
|
||||
},
|
||||
.probe = max14577_muic_probe,
|
||||
.remove = max14577_muic_remove,
|
||||
|
||||
@@ -900,7 +900,7 @@ int extcon_register_notifier(struct extcon_dev *edev, unsigned int id,
|
||||
struct notifier_block *nb)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret, idx = -EINVAL;
|
||||
int ret, idx;
|
||||
|
||||
if (!edev || !nb)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -72,7 +72,7 @@ static void rsu_status_callback(struct stratix10_svc_client *client,
|
||||
struct stratix10_rsu_priv *priv = client->priv;
|
||||
struct arm_smccc_res *res = (struct arm_smccc_res *)data->kaddr1;
|
||||
|
||||
if (data->status == BIT(SVC_STATUS_RSU_OK)) {
|
||||
if (data->status == BIT(SVC_STATUS_OK)) {
|
||||
priv->status.version = FIELD_GET(RSU_VERSION_MASK,
|
||||
res->a2);
|
||||
priv->status.state = FIELD_GET(RSU_STATE_MASK, res->a2);
|
||||
@@ -108,9 +108,9 @@ static void rsu_command_callback(struct stratix10_svc_client *client,
|
||||
{
|
||||
struct stratix10_rsu_priv *priv = client->priv;
|
||||
|
||||
if (data->status == BIT(SVC_STATUS_RSU_NO_SUPPORT))
|
||||
if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
|
||||
dev_warn(client->dev, "Secure FW doesn't support notify\n");
|
||||
else if (data->status == BIT(SVC_STATUS_RSU_ERROR))
|
||||
else if (data->status == BIT(SVC_STATUS_ERROR))
|
||||
dev_err(client->dev, "Failure, returned status is %lu\n",
|
||||
BIT(data->status));
|
||||
|
||||
@@ -133,9 +133,9 @@ static void rsu_retry_callback(struct stratix10_svc_client *client,
|
||||
struct stratix10_rsu_priv *priv = client->priv;
|
||||
unsigned int *counter = (unsigned int *)data->kaddr1;
|
||||
|
||||
if (data->status == BIT(SVC_STATUS_RSU_OK))
|
||||
if (data->status == BIT(SVC_STATUS_OK))
|
||||
priv->retry_counter = *counter;
|
||||
else if (data->status == BIT(SVC_STATUS_RSU_NO_SUPPORT))
|
||||
else if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
|
||||
dev_warn(client->dev, "Secure FW doesn't support retry\n");
|
||||
else
|
||||
dev_err(client->dev, "Failed to get retry counter %lu\n",
|
||||
|
||||
@@ -214,7 +214,7 @@ static void svc_thread_cmd_data_claim(struct stratix10_svc_controller *ctrl,
|
||||
complete(&ctrl->complete_status);
|
||||
break;
|
||||
}
|
||||
cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_DONE);
|
||||
cb_data->status = BIT(SVC_STATUS_BUFFER_DONE);
|
||||
cb_data->kaddr1 = svc_pa_to_va(res.a1);
|
||||
cb_data->kaddr2 = (res.a2) ?
|
||||
svc_pa_to_va(res.a2) : NULL;
|
||||
@@ -227,7 +227,7 @@ static void svc_thread_cmd_data_claim(struct stratix10_svc_controller *ctrl,
|
||||
__func__);
|
||||
}
|
||||
} while (res.a0 == INTEL_SIP_SMC_STATUS_OK ||
|
||||
res.a0 == INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY ||
|
||||
res.a0 == INTEL_SIP_SMC_STATUS_BUSY ||
|
||||
wait_for_completion_timeout(&ctrl->complete_status, timeout));
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl,
|
||||
cb_data->kaddr1 = NULL;
|
||||
cb_data->kaddr2 = NULL;
|
||||
cb_data->kaddr3 = NULL;
|
||||
cb_data->status = BIT(SVC_STATUS_RECONFIG_ERROR);
|
||||
cb_data->status = BIT(SVC_STATUS_ERROR);
|
||||
|
||||
pr_debug("%s: polling config status\n", __func__);
|
||||
|
||||
@@ -259,7 +259,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl,
|
||||
ctrl->invoke_fn(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE,
|
||||
0, 0, 0, 0, 0, 0, 0, &res);
|
||||
if ((res.a0 == INTEL_SIP_SMC_STATUS_OK) ||
|
||||
(res.a0 == INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR))
|
||||
(res.a0 == INTEL_SIP_SMC_STATUS_ERROR))
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -271,7 +271,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl,
|
||||
}
|
||||
|
||||
if (res.a0 == INTEL_SIP_SMC_STATUS_OK && count_in_sec)
|
||||
cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED);
|
||||
cb_data->status = BIT(SVC_STATUS_COMPLETED);
|
||||
|
||||
p_data->chan->scl->receive_cb(p_data->chan->scl, cb_data);
|
||||
}
|
||||
@@ -294,24 +294,18 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data,
|
||||
|
||||
switch (p_data->command) {
|
||||
case COMMAND_RECONFIG:
|
||||
cb_data->status = BIT(SVC_STATUS_RECONFIG_REQUEST_OK);
|
||||
break;
|
||||
case COMMAND_RECONFIG_DATA_SUBMIT:
|
||||
cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED);
|
||||
break;
|
||||
case COMMAND_NOOP:
|
||||
cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED);
|
||||
cb_data->kaddr1 = svc_pa_to_va(res.a1);
|
||||
break;
|
||||
case COMMAND_RECONFIG_STATUS:
|
||||
cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED);
|
||||
break;
|
||||
case COMMAND_RSU_UPDATE:
|
||||
case COMMAND_RSU_NOTIFY:
|
||||
cb_data->status = BIT(SVC_STATUS_RSU_OK);
|
||||
cb_data->status = BIT(SVC_STATUS_OK);
|
||||
break;
|
||||
case COMMAND_RECONFIG_DATA_SUBMIT:
|
||||
cb_data->status = BIT(SVC_STATUS_BUFFER_SUBMITTED);
|
||||
break;
|
||||
case COMMAND_RECONFIG_STATUS:
|
||||
cb_data->status = BIT(SVC_STATUS_COMPLETED);
|
||||
break;
|
||||
case COMMAND_RSU_RETRY:
|
||||
cb_data->status = BIT(SVC_STATUS_RSU_OK);
|
||||
cb_data->status = BIT(SVC_STATUS_OK);
|
||||
cb_data->kaddr1 = &res.a1;
|
||||
break;
|
||||
default:
|
||||
@@ -430,9 +424,9 @@ static int svc_normal_to_secure_thread(void *data)
|
||||
|
||||
if (pdata->command == COMMAND_RSU_STATUS) {
|
||||
if (res.a0 == INTEL_SIP_SMC_RSU_ERROR)
|
||||
cbdata->status = BIT(SVC_STATUS_RSU_ERROR);
|
||||
cbdata->status = BIT(SVC_STATUS_ERROR);
|
||||
else
|
||||
cbdata->status = BIT(SVC_STATUS_RSU_OK);
|
||||
cbdata->status = BIT(SVC_STATUS_OK);
|
||||
|
||||
cbdata->kaddr1 = &res;
|
||||
cbdata->kaddr2 = NULL;
|
||||
@@ -445,7 +439,7 @@ static int svc_normal_to_secure_thread(void *data)
|
||||
case INTEL_SIP_SMC_STATUS_OK:
|
||||
svc_thread_recv_status_ok(pdata, cbdata, res);
|
||||
break;
|
||||
case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY:
|
||||
case INTEL_SIP_SMC_STATUS_BUSY:
|
||||
switch (pdata->command) {
|
||||
case COMMAND_RECONFIG_DATA_SUBMIT:
|
||||
svc_thread_cmd_data_claim(ctrl,
|
||||
@@ -460,33 +454,13 @@ static int svc_normal_to_secure_thread(void *data)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_REJECTED:
|
||||
case INTEL_SIP_SMC_STATUS_REJECTED:
|
||||
pr_debug("%s: STATUS_REJECTED\n", __func__);
|
||||
break;
|
||||
case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR:
|
||||
case INTEL_SIP_SMC_STATUS_ERROR:
|
||||
case INTEL_SIP_SMC_RSU_ERROR:
|
||||
pr_err("%s: STATUS_ERROR\n", __func__);
|
||||
switch (pdata->command) {
|
||||
/* for FPGA mgr */
|
||||
case COMMAND_RECONFIG_DATA_CLAIM:
|
||||
case COMMAND_RECONFIG:
|
||||
case COMMAND_RECONFIG_DATA_SUBMIT:
|
||||
case COMMAND_RECONFIG_STATUS:
|
||||
cbdata->status =
|
||||
BIT(SVC_STATUS_RECONFIG_ERROR);
|
||||
break;
|
||||
|
||||
/* for RSU */
|
||||
case COMMAND_RSU_STATUS:
|
||||
case COMMAND_RSU_UPDATE:
|
||||
case COMMAND_RSU_NOTIFY:
|
||||
case COMMAND_RSU_RETRY:
|
||||
cbdata->status =
|
||||
BIT(SVC_STATUS_RSU_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
cbdata->status = BIT(SVC_STATUS_RECONFIG_ERROR);
|
||||
cbdata->status = BIT(SVC_STATUS_ERROR);
|
||||
cbdata->kaddr1 = NULL;
|
||||
cbdata->kaddr2 = NULL;
|
||||
cbdata->kaddr3 = NULL;
|
||||
@@ -502,7 +476,7 @@ static int svc_normal_to_secure_thread(void *data)
|
||||
if ((pdata->command == COMMAND_RSU_RETRY) ||
|
||||
(pdata->command == COMMAND_RSU_NOTIFY)) {
|
||||
cbdata->status =
|
||||
BIT(SVC_STATUS_RSU_NO_SUPPORT);
|
||||
BIT(SVC_STATUS_NO_SUPPORT);
|
||||
cbdata->kaddr1 = NULL;
|
||||
cbdata->kaddr2 = NULL;
|
||||
cbdata->kaddr3 = NULL;
|
||||
|
||||
@@ -85,14 +85,13 @@ static int get_pm_api_id(char *pm_api_req, u32 *pm_id)
|
||||
|
||||
static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
|
||||
{
|
||||
const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
|
||||
u32 pm_api_version;
|
||||
int ret;
|
||||
struct zynqmp_pm_query_data qdata = {0};
|
||||
|
||||
switch (pm_id) {
|
||||
case PM_GET_API_VERSION:
|
||||
ret = eemi_ops->get_api_version(&pm_api_version);
|
||||
ret = zynqmp_pm_get_api_version(&pm_api_version);
|
||||
sprintf(debugfs_buf, "PM-API Version = %d.%d\n",
|
||||
pm_api_version >> 16, pm_api_version & 0xffff);
|
||||
break;
|
||||
@@ -102,7 +101,7 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
|
||||
qdata.arg2 = pm_api_arg[2];
|
||||
qdata.arg3 = pm_api_arg[3];
|
||||
|
||||
ret = eemi_ops->query_data(qdata, pm_api_ret);
|
||||
ret = zynqmp_pm_query_data(qdata, pm_api_ret);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
|
||||
+518
-105
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Xilinx Zynq MPSoC Firmware layer
|
||||
*
|
||||
* Copyright (C) 2014-2018 Xilinx, Inc.
|
||||
* Copyright (C) 2014-2020 Xilinx, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
* Davorin Mista <davorin.mista@aggios.com>
|
||||
@@ -24,8 +24,6 @@
|
||||
#include <linux/firmware/xlnx-zynqmp.h>
|
||||
#include "zynqmp-debug.h"
|
||||
|
||||
static const struct zynqmp_eemi_ops *eemi_ops_tbl;
|
||||
|
||||
static bool feature_check_enabled;
|
||||
static u32 zynqmp_pm_features[PM_API_MAX];
|
||||
|
||||
@@ -219,7 +217,7 @@ static u32 pm_tz_version;
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_get_api_version(u32 *version)
|
||||
int zynqmp_pm_get_api_version(u32 *version)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -237,6 +235,7 @@ static int zynqmp_pm_get_api_version(u32 *version)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_get_chipid - Get silicon ID registers
|
||||
@@ -246,7 +245,7 @@ static int zynqmp_pm_get_api_version(u32 *version)
|
||||
* Return: Returns the status of the operation and the idcode and version
|
||||
* registers in @idcode and @version.
|
||||
*/
|
||||
static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
|
||||
int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -260,6 +259,7 @@ static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version
|
||||
@@ -324,7 +324,7 @@ static int get_set_conduit_method(struct device_node *np)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
|
||||
int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -338,6 +338,7 @@ static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
|
||||
*/
|
||||
return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_query_data);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_enable() - Enable the clock for given id
|
||||
@@ -348,10 +349,11 @@ static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_enable(u32 clock_id)
|
||||
int zynqmp_pm_clock_enable(u32 clock_id)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_disable() - Disable the clock for given id
|
||||
@@ -362,10 +364,11 @@ static int zynqmp_pm_clock_enable(u32 clock_id)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_disable(u32 clock_id)
|
||||
int zynqmp_pm_clock_disable(u32 clock_id)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_getstate() - Get the clock state for given id
|
||||
@@ -377,7 +380,7 @@ static int zynqmp_pm_clock_disable(u32 clock_id)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
|
||||
int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -388,6 +391,7 @@ static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_setdivider() - Set the clock divider for given id
|
||||
@@ -399,11 +403,12 @@ static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
|
||||
int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider,
|
||||
0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_getdivider() - Get the clock divider for given id
|
||||
@@ -415,7 +420,7 @@ static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
|
||||
int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -426,6 +431,7 @@ static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_setrate() - Set the clock rate for given id
|
||||
@@ -436,13 +442,14 @@ static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
|
||||
int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id,
|
||||
lower_32_bits(rate),
|
||||
upper_32_bits(rate),
|
||||
0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_getrate() - Get the clock rate for given id
|
||||
@@ -454,7 +461,7 @@ static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
|
||||
int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -465,6 +472,7 @@ static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_setparent() - Set the clock parent for given id
|
||||
@@ -475,11 +483,12 @@ static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
|
||||
int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id,
|
||||
parent_id, 0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_clock_getparent() - Get the clock parent for given id
|
||||
@@ -491,7 +500,7 @@ static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
|
||||
int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -502,48 +511,191 @@ static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent);
|
||||
|
||||
/**
|
||||
* zynqmp_is_valid_ioctl() - Check whether IOCTL ID is valid or not
|
||||
* @ioctl_id: IOCTL ID
|
||||
* zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode
|
||||
*
|
||||
* Return: 1 if IOCTL is valid else 0
|
||||
*/
|
||||
static inline int zynqmp_is_valid_ioctl(u32 ioctl_id)
|
||||
{
|
||||
switch (ioctl_id) {
|
||||
case IOCTL_SD_DLL_RESET:
|
||||
case IOCTL_SET_SD_TAPDELAY:
|
||||
case IOCTL_SET_PLL_FRAC_MODE:
|
||||
case IOCTL_GET_PLL_FRAC_MODE:
|
||||
case IOCTL_SET_PLL_FRAC_DATA:
|
||||
case IOCTL_GET_PLL_FRAC_DATA:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* zynqmp_pm_ioctl() - PM IOCTL API for device control and configs
|
||||
* @node_id: Node ID of the device
|
||||
* @ioctl_id: ID of the requested IOCTL
|
||||
* @arg1: Argument 1 to requested IOCTL call
|
||||
* @arg2: Argument 2 to requested IOCTL call
|
||||
* @out: Returned output value
|
||||
* @clk_id: PLL clock ID
|
||||
* @mode: PLL mode (PLL_MODE_FRAC/PLL_MODE_INT)
|
||||
*
|
||||
* This function calls IOCTL to firmware for device control and configuration.
|
||||
* This function sets PLL mode
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
|
||||
u32 *out)
|
||||
int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode)
|
||||
{
|
||||
if (!zynqmp_is_valid_ioctl(ioctl_id))
|
||||
return -EINVAL;
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE,
|
||||
clk_id, mode, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode);
|
||||
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, ioctl_id,
|
||||
arg1, arg2, out);
|
||||
/**
|
||||
* zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode
|
||||
*
|
||||
* @clk_id: PLL clock ID
|
||||
* @mode: PLL mode
|
||||
*
|
||||
* This function return current PLL mode
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE,
|
||||
clk_id, 0, mode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data
|
||||
*
|
||||
* @clk_id: PLL clock ID
|
||||
* @data: fraction data
|
||||
*
|
||||
* This function sets fraction data.
|
||||
* It is valid for fraction mode only.
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA,
|
||||
clk_id, data, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data
|
||||
*
|
||||
* @clk_id: PLL clock ID
|
||||
* @data: fraction data
|
||||
*
|
||||
* This function returns fraction data value.
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA,
|
||||
clk_id, 0, data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device
|
||||
*
|
||||
* @node_id Node ID of the device
|
||||
* @type Type of tap delay to set (input/output)
|
||||
* @value Value to set fot the tap delay
|
||||
*
|
||||
* This function sets input/output tap delay for the SD device.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
|
||||
type, value, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_sd_dll_reset() - Reset DLL logic
|
||||
*
|
||||
* @node_id Node ID of the device
|
||||
* @type Reset type
|
||||
*
|
||||
* This function resets DLL logic for the SD device.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY,
|
||||
type, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs)
|
||||
* @index GGS register index
|
||||
* @value Register value to be written
|
||||
*
|
||||
* This function writes value to GGS register.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_write_ggs(u32 index, u32 value)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS,
|
||||
index, value, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_write_ggs() - PM API for reading global general storage (ggs)
|
||||
* @index GGS register index
|
||||
* @value Register value to be written
|
||||
*
|
||||
* This function returns GGS register value.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_read_ggs(u32 index, u32 *value)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS,
|
||||
index, 0, value);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_write_pggs() - PM API for writing persistent global general
|
||||
* storage (pggs)
|
||||
* @index PGGS register index
|
||||
* @value Register value to be written
|
||||
*
|
||||
* This function writes value to PGGS register.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_write_pggs(u32 index, u32 value)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value,
|
||||
NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_write_pggs() - PM API for reading persistent global general
|
||||
* storage (pggs)
|
||||
* @index PGGS register index
|
||||
* @value Register value to be written
|
||||
*
|
||||
* This function returns PGGS register value.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_read_pggs(u32 index, u32 *value)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0,
|
||||
value);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
|
||||
* @value Status value to be written
|
||||
*
|
||||
* This function sets healthy bit value to indicate boot health status
|
||||
* to firmware.
|
||||
*
|
||||
* @return Returns status, either success or error+reason
|
||||
*/
|
||||
int zynqmp_pm_set_boot_health_status(u32 value)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS,
|
||||
value, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -554,12 +706,13 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
|
||||
const enum zynqmp_pm_reset_action assert_flag)
|
||||
int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
|
||||
const enum zynqmp_pm_reset_action assert_flag)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
|
||||
0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_reset_get_status - Get status of the reset
|
||||
@@ -568,8 +721,7 @@ static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
|
||||
u32 *status)
|
||||
int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -583,6 +735,7 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_fpga_load - Perform the fpga load
|
||||
@@ -597,12 +750,12 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_fpga_load(const u64 address, const u32 size,
|
||||
const u32 flags)
|
||||
int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
|
||||
upper_32_bits(address), size, flags, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_fpga_get_status - Read value from PCAP status register
|
||||
@@ -613,7 +766,7 @@ static int zynqmp_pm_fpga_load(const u64 address, const u32 size,
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_fpga_get_status(u32 *value)
|
||||
int zynqmp_pm_fpga_get_status(u32 *value)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -626,6 +779,7 @@ static int zynqmp_pm_fpga_get_status(u32 *value)
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
|
||||
@@ -636,10 +790,11 @@ static int zynqmp_pm_fpga_get_status(u32 *value)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_init_finalize(void)
|
||||
int zynqmp_pm_init_finalize(void)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_set_suspend_mode() - Set system suspend mode
|
||||
@@ -649,10 +804,11 @@ static int zynqmp_pm_init_finalize(void)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_set_suspend_mode(u32 mode)
|
||||
int zynqmp_pm_set_suspend_mode(u32 mode)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_request_node() - Request a node with specific capabilities
|
||||
@@ -666,13 +822,13 @@ static int zynqmp_pm_set_suspend_mode(u32 mode)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
|
||||
const u32 qos,
|
||||
const enum zynqmp_pm_request_ack ack)
|
||||
int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
|
||||
const u32 qos, const enum zynqmp_pm_request_ack ack)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities,
|
||||
qos, ack, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_request_node);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_release_node() - Release a node
|
||||
@@ -684,10 +840,11 @@ static int zynqmp_pm_request_node(const u32 node, const u32 capabilities,
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_release_node(const u32 node)
|
||||
int zynqmp_pm_release_node(const u32 node)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_release_node);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves
|
||||
@@ -701,13 +858,14 @@ static int zynqmp_pm_release_node(const u32 node)
|
||||
*
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
|
||||
const u32 qos,
|
||||
const enum zynqmp_pm_request_ack ack)
|
||||
int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
|
||||
const u32 qos,
|
||||
const enum zynqmp_pm_request_ack ack)
|
||||
{
|
||||
return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities,
|
||||
qos, ack, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_aes - Access AES hardware to encrypt/decrypt the data using
|
||||
@@ -717,7 +875,7 @@ static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities,
|
||||
*
|
||||
* Return: Returns status, either success or error code.
|
||||
*/
|
||||
static int zynqmp_pm_aes_engine(const u64 address, u32 *out)
|
||||
int zynqmp_pm_aes_engine(const u64 address, u32 *out)
|
||||
{
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
int ret;
|
||||
@@ -732,47 +890,304 @@ static int zynqmp_pm_aes_engine(const u64 address, u32 *out)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct zynqmp_eemi_ops eemi_ops = {
|
||||
.get_api_version = zynqmp_pm_get_api_version,
|
||||
.get_chipid = zynqmp_pm_get_chipid,
|
||||
.query_data = zynqmp_pm_query_data,
|
||||
.clock_enable = zynqmp_pm_clock_enable,
|
||||
.clock_disable = zynqmp_pm_clock_disable,
|
||||
.clock_getstate = zynqmp_pm_clock_getstate,
|
||||
.clock_setdivider = zynqmp_pm_clock_setdivider,
|
||||
.clock_getdivider = zynqmp_pm_clock_getdivider,
|
||||
.clock_setrate = zynqmp_pm_clock_setrate,
|
||||
.clock_getrate = zynqmp_pm_clock_getrate,
|
||||
.clock_setparent = zynqmp_pm_clock_setparent,
|
||||
.clock_getparent = zynqmp_pm_clock_getparent,
|
||||
.ioctl = zynqmp_pm_ioctl,
|
||||
.reset_assert = zynqmp_pm_reset_assert,
|
||||
.reset_get_status = zynqmp_pm_reset_get_status,
|
||||
.init_finalize = zynqmp_pm_init_finalize,
|
||||
.set_suspend_mode = zynqmp_pm_set_suspend_mode,
|
||||
.request_node = zynqmp_pm_request_node,
|
||||
.release_node = zynqmp_pm_release_node,
|
||||
.set_requirement = zynqmp_pm_set_requirement,
|
||||
.fpga_load = zynqmp_pm_fpga_load,
|
||||
.fpga_get_status = zynqmp_pm_fpga_get_status,
|
||||
.aes = zynqmp_pm_aes_engine,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
|
||||
|
||||
/**
|
||||
* zynqmp_pm_get_eemi_ops - Get eemi ops functions
|
||||
* zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
|
||||
* @type: Shutdown or restart? 0 for shutdown, 1 for restart
|
||||
* @subtype: Specifies which system should be restarted or shut down
|
||||
*
|
||||
* Return: Pointer of eemi_ops structure
|
||||
* Return: Returns status, either success or error+reason
|
||||
*/
|
||||
const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
|
||||
int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
|
||||
{
|
||||
if (eemi_ops_tbl)
|
||||
return eemi_ops_tbl;
|
||||
else
|
||||
return ERR_PTR(-EPROBE_DEFER);
|
||||
|
||||
return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
|
||||
0, 0, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops);
|
||||
|
||||
/**
|
||||
* struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
|
||||
* @subtype: Shutdown subtype
|
||||
* @name: Matching string for scope argument
|
||||
*
|
||||
* This struct encapsulates mapping between shutdown scope ID and string.
|
||||
*/
|
||||
struct zynqmp_pm_shutdown_scope {
|
||||
const enum zynqmp_pm_shutdown_subtype subtype;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
|
||||
[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
|
||||
.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
|
||||
.name = "subsystem",
|
||||
},
|
||||
[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
|
||||
.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
|
||||
.name = "ps_only",
|
||||
},
|
||||
[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
|
||||
.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
|
||||
.name = "system",
|
||||
},
|
||||
};
|
||||
|
||||
static struct zynqmp_pm_shutdown_scope *selected_scope =
|
||||
&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
|
||||
|
||||
/**
|
||||
* zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
|
||||
* @scope_string: Shutdown scope string
|
||||
*
|
||||
* Return: Return pointer to matching shutdown scope struct from
|
||||
* array of available options in system if string is valid,
|
||||
* otherwise returns NULL.
|
||||
*/
|
||||
static struct zynqmp_pm_shutdown_scope*
|
||||
zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
|
||||
{
|
||||
int count;
|
||||
|
||||
for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
|
||||
if (sysfs_streq(scope_string, shutdown_scopes[count].name))
|
||||
return &shutdown_scopes[count];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ssize_t shutdown_scope_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
|
||||
if (&shutdown_scopes[i] == selected_scope) {
|
||||
strcat(buf, "[");
|
||||
strcat(buf, shutdown_scopes[i].name);
|
||||
strcat(buf, "]");
|
||||
} else {
|
||||
strcat(buf, shutdown_scopes[i].name);
|
||||
}
|
||||
strcat(buf, " ");
|
||||
}
|
||||
strcat(buf, "\n");
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t shutdown_scope_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
struct zynqmp_pm_shutdown_scope *scope;
|
||||
|
||||
scope = zynqmp_pm_is_shutdown_scope_valid(buf);
|
||||
if (!scope)
|
||||
return -EINVAL;
|
||||
|
||||
ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
|
||||
scope->subtype);
|
||||
if (ret) {
|
||||
pr_err("unable to set shutdown scope %s\n", buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
selected_scope = scope;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(shutdown_scope);
|
||||
|
||||
static ssize_t health_status_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
unsigned int value;
|
||||
|
||||
ret = kstrtouint(buf, 10, &value);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = zynqmp_pm_set_boot_health_status(value);
|
||||
if (ret) {
|
||||
dev_err(device, "unable to set healthy bit value to %u\n",
|
||||
value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_WO(health_status);
|
||||
|
||||
static ssize_t ggs_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf,
|
||||
u32 reg)
|
||||
{
|
||||
int ret;
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
ret = zynqmp_pm_read_ggs(reg, ret_payload);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "0x%x\n", ret_payload[1]);
|
||||
}
|
||||
|
||||
static ssize_t ggs_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count,
|
||||
u32 reg)
|
||||
{
|
||||
long value;
|
||||
int ret;
|
||||
|
||||
if (reg >= GSS_NUM_REGS)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtol(buf, 16, &value);
|
||||
if (ret) {
|
||||
count = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = zynqmp_pm_write_ggs(reg, value);
|
||||
if (ret)
|
||||
count = -EFAULT;
|
||||
err:
|
||||
return count;
|
||||
}
|
||||
|
||||
/* GGS register show functions */
|
||||
#define GGS0_SHOW(N) \
|
||||
ssize_t ggs##N##_show(struct device *device, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return ggs_show(device, attr, buf, N); \
|
||||
}
|
||||
|
||||
static GGS0_SHOW(0);
|
||||
static GGS0_SHOW(1);
|
||||
static GGS0_SHOW(2);
|
||||
static GGS0_SHOW(3);
|
||||
|
||||
/* GGS register store function */
|
||||
#define GGS0_STORE(N) \
|
||||
ssize_t ggs##N##_store(struct device *device, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, \
|
||||
size_t count) \
|
||||
{ \
|
||||
return ggs_store(device, attr, buf, count, N); \
|
||||
}
|
||||
|
||||
static GGS0_STORE(0);
|
||||
static GGS0_STORE(1);
|
||||
static GGS0_STORE(2);
|
||||
static GGS0_STORE(3);
|
||||
|
||||
static ssize_t pggs_show(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
char *buf,
|
||||
u32 reg)
|
||||
{
|
||||
int ret;
|
||||
u32 ret_payload[PAYLOAD_ARG_CNT];
|
||||
|
||||
ret = zynqmp_pm_read_pggs(reg, ret_payload);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "0x%x\n", ret_payload[1]);
|
||||
}
|
||||
|
||||
static ssize_t pggs_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count,
|
||||
u32 reg)
|
||||
{
|
||||
long value;
|
||||
int ret;
|
||||
|
||||
if (reg >= GSS_NUM_REGS)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kstrtol(buf, 16, &value);
|
||||
if (ret) {
|
||||
count = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = zynqmp_pm_write_pggs(reg, value);
|
||||
if (ret)
|
||||
count = -EFAULT;
|
||||
|
||||
err:
|
||||
return count;
|
||||
}
|
||||
|
||||
#define PGGS0_SHOW(N) \
|
||||
ssize_t pggs##N##_show(struct device *device, \
|
||||
struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
{ \
|
||||
return pggs_show(device, attr, buf, N); \
|
||||
}
|
||||
|
||||
#define PGGS0_STORE(N) \
|
||||
ssize_t pggs##N##_store(struct device *device, \
|
||||
struct device_attribute *attr, \
|
||||
const char *buf, \
|
||||
size_t count) \
|
||||
{ \
|
||||
return pggs_store(device, attr, buf, count, N); \
|
||||
}
|
||||
|
||||
/* PGGS register show functions */
|
||||
static PGGS0_SHOW(0);
|
||||
static PGGS0_SHOW(1);
|
||||
static PGGS0_SHOW(2);
|
||||
static PGGS0_SHOW(3);
|
||||
|
||||
/* PGGS register store functions */
|
||||
static PGGS0_STORE(0);
|
||||
static PGGS0_STORE(1);
|
||||
static PGGS0_STORE(2);
|
||||
static PGGS0_STORE(3);
|
||||
|
||||
/* GGS register attributes */
|
||||
static DEVICE_ATTR_RW(ggs0);
|
||||
static DEVICE_ATTR_RW(ggs1);
|
||||
static DEVICE_ATTR_RW(ggs2);
|
||||
static DEVICE_ATTR_RW(ggs3);
|
||||
|
||||
/* PGGS register attributes */
|
||||
static DEVICE_ATTR_RW(pggs0);
|
||||
static DEVICE_ATTR_RW(pggs1);
|
||||
static DEVICE_ATTR_RW(pggs2);
|
||||
static DEVICE_ATTR_RW(pggs3);
|
||||
|
||||
static struct attribute *zynqmp_firmware_attrs[] = {
|
||||
&dev_attr_ggs0.attr,
|
||||
&dev_attr_ggs1.attr,
|
||||
&dev_attr_ggs2.attr,
|
||||
&dev_attr_ggs3.attr,
|
||||
&dev_attr_pggs0.attr,
|
||||
&dev_attr_pggs1.attr,
|
||||
&dev_attr_pggs2.attr,
|
||||
&dev_attr_pggs3.attr,
|
||||
&dev_attr_shutdown_scope.attr,
|
||||
&dev_attr_health_status.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
ATTRIBUTE_GROUPS(zynqmp_firmware);
|
||||
|
||||
static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||
{
|
||||
@@ -820,11 +1235,6 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||
pr_info("%s Trustzone version v%d.%d\n", __func__,
|
||||
pm_tz_version >> 16, pm_tz_version & 0xFFFF);
|
||||
|
||||
/* Assign eemi_ops_table */
|
||||
eemi_ops_tbl = &eemi_ops;
|
||||
|
||||
zynqmp_pm_api_debugfs_init();
|
||||
|
||||
ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
|
||||
ARRAY_SIZE(firmware_devs), NULL, 0, NULL);
|
||||
if (ret) {
|
||||
@@ -832,6 +1242,8 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
zynqmp_pm_api_debugfs_init();
|
||||
|
||||
return of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
@@ -854,6 +1266,7 @@ static struct platform_driver zynqmp_firmware_driver = {
|
||||
.driver = {
|
||||
.name = "zynqmp_firmware",
|
||||
.of_match_table = zynqmp_firmware_of_match,
|
||||
.dev_groups = zynqmp_firmware_groups,
|
||||
},
|
||||
.probe = zynqmp_firmware_probe,
|
||||
.remove = zynqmp_firmware_remove,
|
||||
|
||||
@@ -156,7 +156,7 @@ config FPGA_DFL
|
||||
|
||||
config FPGA_DFL_FME
|
||||
tristate "FPGA DFL FME Driver"
|
||||
depends on FPGA_DFL && HWMON
|
||||
depends on FPGA_DFL && HWMON && PERF_EVENTS
|
||||
help
|
||||
The FPGA Management Engine (FME) is a feature device implemented
|
||||
under Device Feature List (DFL) framework. Select this option to
|
||||
|
||||
@@ -40,6 +40,7 @@ obj-$(CONFIG_FPGA_DFL_FME_REGION) += dfl-fme-region.o
|
||||
obj-$(CONFIG_FPGA_DFL_AFU) += dfl-afu.o
|
||||
|
||||
dfl-fme-objs := dfl-fme-main.o dfl-fme-pr.o dfl-fme-error.o
|
||||
dfl-fme-objs += dfl-fme-perf.o
|
||||
dfl-afu-objs := dfl-afu-main.o dfl-afu-region.o dfl-afu-dma-region.o
|
||||
dfl-afu-objs += dfl-afu-error.o
|
||||
|
||||
|
||||
@@ -61,10 +61,10 @@ static int afu_dma_pin_pages(struct dfl_feature_platform_data *pdata,
|
||||
region->pages);
|
||||
if (pinned < 0) {
|
||||
ret = pinned;
|
||||
goto put_pages;
|
||||
goto free_pages;
|
||||
} else if (pinned != npages) {
|
||||
ret = -EFAULT;
|
||||
goto free_pages;
|
||||
goto put_pages;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "%d pages pinned\n", pinned);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user