mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
Merge tag 'char-misc-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc/IIO driver updates from Greg KH:
"Here is the big set of char/misc/iio driver updates for 6.19-rc1. Lots
of stuff in here including:
- lots of IIO driver updates, cleanups, and additions
- large interconnect driver changes as they get converted over to a
dynamic system of ids
- coresight driver updates
- mwave driver updates
- binder driver updates and changes
- comedi driver fixes now that the fuzzers are being set loose on
them
- nvmem driver updates
- new uio driver addition
- lots of other small char/misc driver updates, full details in the
shortlog
All of these have been in linux-next for a while now"
* tag 'char-misc-6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (304 commits)
char: applicom: fix NULL pointer dereference in ac_ioctl
hangcheck-timer: fix coding style spacing
hangcheck-timer: Replace %Ld with %lld
hangcheck-timer: replace printk(KERN_CRIT) with pr_crit
uio: Add SVA support for PCI devices via uio_pci_generic_sva.c
dt-bindings: slimbus: fix warning from example
intel_th: Fix error handling in intel_th_output_open
misc: rp1: Fix an error handling path in rp1_probe()
char: xillybus: add WQ_UNBOUND to alloc_workqueue users
misc: bh1770glc: use pm_runtime_resume_and_get() in power_state_store
misc: cb710: Fix a NULL vs IS_ERR() check in probe()
mux: mmio: Add suspend and resume support
virt: acrn: split acrn_mmio_dev_res out of acrn_mmiodev
greybus: gb-beagleplay: Fix timeout handling in bootloader functions
greybus: add WQ_PERCPU to alloc_workqueue users
char/mwave: drop typedefs
char/mwave: drop printk wrapper
char/mwave: remove printk tracing
char/mwave: remove unneeded fops
char/mwave: remove MWAVE_FUTZ_WITH_OTHER_DEVICES ifdeffery
...
This commit is contained in:
@@ -898,6 +898,7 @@ What: /sys/.../iio:deviceX/events/in_tempY_thresh_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_tempY_thresh_falling_en
|
||||
What: /sys/.../iio:deviceX/events/in_capacitanceY_thresh_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_capacitanceY_thresh_falling_en
|
||||
What: /sys/.../iio:deviceX/events/in_pressure_thresh_rising_en
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@@ -926,6 +927,7 @@ What: /sys/.../iio:deviceX/events/in_accel_y_roc_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_y_roc_falling_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_z_roc_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_z_roc_falling_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_x&y&z_roc_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_anglvel_x_roc_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_anglvel_x_roc_falling_en
|
||||
What: /sys/.../iio:deviceX/events/in_anglvel_y_roc_rising_en
|
||||
@@ -1001,6 +1003,7 @@ Description:
|
||||
to the raw signal, allowing slow tracking to resume and the
|
||||
adaptive threshold event detection to function as expected.
|
||||
|
||||
What: /sys/.../events/in_accel_mag_adaptive_rising_value
|
||||
What: /sys/.../events/in_accel_thresh_rising_value
|
||||
What: /sys/.../events/in_accel_thresh_falling_value
|
||||
What: /sys/.../events/in_accel_x_raw_thresh_rising_value
|
||||
@@ -1045,6 +1048,7 @@ What: /sys/.../events/in_capacitanceY_thresh_rising_value
|
||||
What: /sys/.../events/in_capacitanceY_thresh_falling_value
|
||||
What: /sys/.../events/in_capacitanceY_thresh_adaptive_rising_value
|
||||
What: /sys/.../events/in_capacitanceY_thresh_falling_rising_value
|
||||
What: /sys/.../events/in_pressure_thresh_rising_value
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
@@ -1147,6 +1151,7 @@ Description:
|
||||
will get activated once in_voltage0_raw goes above 1200 and will become
|
||||
deactivated again once the value falls below 1150.
|
||||
|
||||
What: /sys/.../events/in_accel_roc_rising_value
|
||||
What: /sys/.../events/in_accel_x_raw_roc_rising_value
|
||||
What: /sys/.../events/in_accel_x_raw_roc_falling_value
|
||||
What: /sys/.../events/in_accel_y_raw_roc_rising_value
|
||||
@@ -1193,6 +1198,8 @@ Description:
|
||||
value is in raw device units or in processed units (as _raw
|
||||
and _input do on sysfs direct channel read attributes).
|
||||
|
||||
What: /sys/.../events/in_accel_mag_adaptive_rising_period
|
||||
What: /sys/.../events/in_accel_roc_rising_period
|
||||
What: /sys/.../events/in_accel_x_thresh_rising_period
|
||||
What: /sys/.../events/in_accel_x_thresh_falling_period
|
||||
What: /sys/.../events/in_accel_x_roc_rising_period
|
||||
@@ -1362,6 +1369,15 @@ Description:
|
||||
number or direction is not specified, applies to all channels of
|
||||
this type.
|
||||
|
||||
What: /sys/.../iio:deviceX/events/in_accel_x_mag_adaptive_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_y_mag_adaptive_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_z_mag_adaptive_rising_en
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Similar to in_accel_x_thresh[_rising|_falling]_en, but here the
|
||||
magnitude of the channel is compared to the adaptive threshold.
|
||||
|
||||
What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_rising_en
|
||||
What: /sys/.../iio:deviceX/events/in_accel_mag_referenced_falling_en
|
||||
@@ -2422,3 +2438,23 @@ Description:
|
||||
Value representing the user's attention to the system expressed
|
||||
in units as percentage. This usually means if the user is
|
||||
looking at the screen or not.
|
||||
|
||||
What: /sys/.../events/in_accel_value_available
|
||||
KernelVersion: 6.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
List of available threshold values for acceleration event
|
||||
generation. Applies to all event types on in_accel channels.
|
||||
Units after application of scale and offset are m/s^2.
|
||||
Expressed as:
|
||||
|
||||
- a range specified as "[min step max]"
|
||||
|
||||
What: /sys/.../events/in_accel_period_available
|
||||
KernelVersion: 6.18
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
List of available periods for accelerometer event detection in
|
||||
seconds, expressed as:
|
||||
|
||||
- a range specified as "[min step max]"
|
||||
|
||||
29
Documentation/ABI/testing/sysfs-driver-uio_pci_sva-pasid
Normal file
29
Documentation/ABI/testing/sysfs-driver-uio_pci_sva-pasid
Normal file
@@ -0,0 +1,29 @@
|
||||
What: /sys/bus/pci/drivers/uio_pci_sva/<pci_dev>/pasid
|
||||
Date: September 2025
|
||||
Contact: Yaxing Guo <guoyaxing@bosc.ac.cn>
|
||||
Description:
|
||||
Process Address Space ID (PASID) assigned by IOMMU driver to
|
||||
the device for use with Shared Virtual Addressing (SVA).
|
||||
|
||||
This read-only attribute exposes the PASID (A 20-bit identifier
|
||||
used in PCIe Address Translation Services and iommu table walks)
|
||||
allocated by the IOMMU driver during sva device binding.
|
||||
|
||||
User-space UIO applications must read this attribute to obtain
|
||||
the PASID and program it into the device's configuration registers.
|
||||
This enables the device to perform DMA using user-space virtual
|
||||
address, with address translation handled by IOMMU.
|
||||
|
||||
UIO User-space applications must:
|
||||
- Opening device and Mapping the device's register space via /dev/uioX
|
||||
(This triggers the IOMMU driver to allocate the PASID)
|
||||
- Reading the PASID from sysfs
|
||||
- Writing the PASID to a device-specific register (with example offset)
|
||||
The code may be like:
|
||||
|
||||
map = mmap(..., "/dev/uio0", ...);
|
||||
|
||||
f = fopen("/sys/.../pasid", "r");
|
||||
fscanf(f, "%d", &pasid);
|
||||
|
||||
map[REG_PASID_OFFSET] = pasid;
|
||||
@@ -36,9 +36,12 @@ properties:
|
||||
$nodename:
|
||||
pattern: "^tpdm(@[0-9a-f]+)$"
|
||||
compatible:
|
||||
items:
|
||||
- const: qcom,coresight-tpdm
|
||||
- const: arm,primecell
|
||||
oneOf:
|
||||
- items:
|
||||
- const: qcom,coresight-static-tpdm
|
||||
- items:
|
||||
- const: qcom,coresight-tpdm
|
||||
- const: arm,primecell
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
@@ -147,4 +150,18 @@ examples:
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
turing-llm-tpdm {
|
||||
compatible = "qcom,coresight-static-tpdm";
|
||||
|
||||
qcom,cmb-element-bits = <32>;
|
||||
|
||||
out-ports {
|
||||
port {
|
||||
turing_llm_tpdm_out: endpoint {
|
||||
remote-endpoint = <&turing0_funnel_in1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
||||
@@ -210,9 +210,9 @@ description: |
|
||||
FPGA Bridges that exist on the FPGA fabric prior to the partial reconfiguration.
|
||||
|
||||
--
|
||||
[1] www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_partrecon.pdf
|
||||
[1] https://www.intel.com/programmable/technical-pdfs/683404.pdf
|
||||
[2] tspace.library.utoronto.ca/bitstream/1807/67932/1/Byma_Stuart_A_201411_MAS_thesis.pdf
|
||||
[3] https://www.xilinx.com/support/documentation/sw_manuals/xilinx14_1/ug702.pdf
|
||||
[3] https://docs.amd.com/v/u/en-US/ug702
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
|
||||
@@ -35,15 +35,17 @@ properties:
|
||||
spi-3wire: true
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- enum: [INT1, INT2]
|
||||
- const: INT2
|
||||
|
||||
dependencies:
|
||||
interrupts: [ interrupt-names ]
|
||||
interrupt-names: [ interrupts ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
@@ -84,7 +86,8 @@ examples:
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "INT2";
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<1 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "INT1", "INT2";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -11,16 +11,19 @@ maintainers:
|
||||
- Antoniu Miclaus <antoniu.miclaus@analog.com>
|
||||
|
||||
description: |
|
||||
The ADXL380/ADXL382 is a low noise density, low power, 3-axis
|
||||
accelerometer with selectable measurement ranges. The ADXL380
|
||||
supports the ±4 g, ±8 g, and ±16 g ranges, and the ADXL382 supports
|
||||
±15 g, ±30 g, and ±60 g ranges.
|
||||
The ADXL380/ADXL382 and ADXL318/ADXL319 are low noise density,
|
||||
low power, 3-axis accelerometers with selectable measurement ranges.
|
||||
The ADXL380 and ADXL318 support the ±4 g, ±8 g, and ±16 g ranges,
|
||||
while the ADXL382 and ADXL319 support ±15 g, ±30 g, and ±60 g ranges.
|
||||
|
||||
https://www.analog.com/en/products/adxl318.html
|
||||
https://www.analog.com/en/products/adxl380.html
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,adxl318
|
||||
- adi,adxl319
|
||||
- adi,adxl380
|
||||
- adi,adxl382
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
$id: http://devicetree.org/schemas/iio/accel/bosch,bma220.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Bosch BMA220 Trixial Acceleration Sensor
|
||||
title: Bosch BMA220 Triaxial Acceleration Sensor
|
||||
|
||||
maintainers:
|
||||
- Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
@@ -20,6 +20,9 @@ properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
vdda-supply: true
|
||||
vddd-supply: true
|
||||
vddio-supply: true
|
||||
@@ -44,8 +47,10 @@ examples:
|
||||
compatible = "bosch,bma220";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <2500000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupts = <0 IRQ_TYPE_EDGE_RISING>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
||||
@@ -26,6 +26,11 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad4080
|
||||
- adi,ad4081
|
||||
- adi,ad4083
|
||||
- adi,ad4084
|
||||
- adi,ad4086
|
||||
- adi,ad4087
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
89
Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml
Normal file
89
Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml
Normal file
@@ -0,0 +1,89 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
# Copyright 2023-2025 Analog Devices Inc.
|
||||
# Copyright 2023 Kim Seer Paller
|
||||
# Copyright 2025 Marilene Andrade Garcia
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/adi,max14001.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices MAX14001-MAX14002 ADC
|
||||
|
||||
maintainers:
|
||||
- Kim Seer Paller <kimseer.paller@analog.com>
|
||||
- Marilene Andrade Garcia <marilene.agarcia@gmail.com>
|
||||
|
||||
description: |
|
||||
Single channel 10 bit ADC with SPI interface.
|
||||
Datasheet can be found here
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/MAX14001-MAX14002.pdf
|
||||
|
||||
$ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: adi,max14002
|
||||
- items:
|
||||
- const: adi,max14001
|
||||
- const: adi,max14002
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 5000000
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
Isolated DC-DC power supply input voltage.
|
||||
|
||||
vddl-supply:
|
||||
description:
|
||||
Logic power supply.
|
||||
|
||||
refin-supply:
|
||||
description:
|
||||
ADC voltage reference supply.
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: |
|
||||
cout: comparator output signal that asserts high on the COUT pin
|
||||
when ADC readings exceed the upper threshold and low when readings
|
||||
fall below the lower threshold.
|
||||
- description: |
|
||||
fault: when fault reporting is enabled, the FAULT pin is asserted
|
||||
low whenever one of the monitored fault conditions occurs.
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: cout
|
||||
- const: fault
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vddl-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "adi,max14001", "adi,max14002";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <5000000>;
|
||||
spi-lsb-first;
|
||||
vdd-supply = <&vdd>;
|
||||
vddl-supply = <&vddl>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -29,6 +29,8 @@ properties:
|
||||
enum:
|
||||
- aspeed,ast2600-adc0
|
||||
- aspeed,ast2600-adc1
|
||||
- aspeed,ast2700-adc0
|
||||
- aspeed,ast2700-adc1
|
||||
description:
|
||||
Their trimming data, which is used to calibrate internal reference volage,
|
||||
locates in different address of OTP.
|
||||
|
||||
@@ -42,6 +42,7 @@ properties:
|
||||
- mediatek,mt8183-auxadc
|
||||
- mediatek,mt8186-auxadc
|
||||
- mediatek,mt8188-auxadc
|
||||
- mediatek,mt8189-auxadc
|
||||
- mediatek,mt8195-auxadc
|
||||
- mediatek,mt8516-auxadc
|
||||
- const: mediatek,mt8173-auxadc
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/renesas,r9a09g077-adc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas RZ/T2H / RZ/N2H ADC12
|
||||
|
||||
maintainers:
|
||||
- Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
|
||||
|
||||
description: |
|
||||
A/D Converter block is a successive approximation analog-to-digital converter
|
||||
with a 12-bit accuracy. Up to 16 analog input channels can be selected.
|
||||
Conversions can be performed in single or continuous mode. Result of the ADC
|
||||
is stored in a 16-bit data register corresponding to each channel.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: renesas,r9a09g087-adc # RZ/N2H
|
||||
- const: renesas,r9a09g077-adc # RZ/T2H
|
||||
- items:
|
||||
- const: renesas,r9a09g077-adc # RZ/T2H
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: A/D scan end interrupt
|
||||
- description: A/D scan end interrupt for Group B
|
||||
- description: A/D scan end interrupt for Group C
|
||||
- description: Window A compare match
|
||||
- description: Window B compare match
|
||||
- description: Compare match
|
||||
- description: Compare mismatch
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: adi
|
||||
- const: gbadi
|
||||
- const: gcadi
|
||||
- const: cmpai
|
||||
- const: cmpbi
|
||||
- const: wcmpm
|
||||
- const: wcmpum
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Converter clock
|
||||
- description: Peripheral clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: adclk
|
||||
- const: pclk
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-9a-f]$":
|
||||
$ref: adc.yaml
|
||||
type: object
|
||||
description: The external channels which are connected to the ADC.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: The channel number.
|
||||
maximum: 15
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/renesas,r9a09g077-cpg-mssr.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
adc@80008000 {
|
||||
compatible = "renesas,r9a09g077-adc";
|
||||
reg = <0x80008000 0x400>;
|
||||
interrupts = <GIC_SPI 708 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 709 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 710 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 711 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 712 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 855 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 856 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "adi", "gbadi", "gcadi",
|
||||
"cmpai", "cmpbi", "wcmpm", "wcmpum";
|
||||
clocks = <&cpg CPG_CORE R9A09G077_CLK_PCLKL>,
|
||||
<&cpg CPG_MOD 225>;
|
||||
clock-names = "adclk", "pclk";
|
||||
power-domains = <&cpg>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#io-channel-cells = <1>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0x0>;
|
||||
};
|
||||
channel@1 {
|
||||
reg = <0x1>;
|
||||
};
|
||||
channel@2 {
|
||||
reg = <0x2>;
|
||||
};
|
||||
channel@3 {
|
||||
reg = <0x3>;
|
||||
};
|
||||
};
|
||||
111
Documentation/devicetree/bindings/iio/adc/renesas,rzn1-adc.yaml
Normal file
111
Documentation/devicetree/bindings/iio/adc/renesas,rzn1-adc.yaml
Normal file
@@ -0,0 +1,111 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/renesas,rzn1-adc.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas RZ/N1 Analog to Digital Converter (ADC)
|
||||
|
||||
maintainers:
|
||||
- Herve Codina <herve.codina@bootlin.com>
|
||||
|
||||
description:
|
||||
The Renesas RZ/N1 ADC controller available in the Renesas RZ/N1 SoCs family
|
||||
can use up to two internal ADC cores (ADC1 and ADC2) those internal cores are
|
||||
handled through ADC controller virtual channels.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- const: renesas,r9a06g032-adc # RZ/N1D
|
||||
- const: renesas,rzn1-adc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: APB internal bus clock
|
||||
- description: ADC clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pclk
|
||||
- const: adc
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
adc1-avdd-supply:
|
||||
description:
|
||||
ADC1 analog power supply.
|
||||
|
||||
adc1-vref-supply:
|
||||
description:
|
||||
ADC1 reference voltage supply.
|
||||
|
||||
adc2-avdd-supply:
|
||||
description:
|
||||
ADC2 analog power supply.
|
||||
|
||||
adc2-vref-supply:
|
||||
description:
|
||||
ADC2 reference voltage supply.
|
||||
|
||||
'#io-channel-cells':
|
||||
const: 1
|
||||
description: |
|
||||
Channels numbers available:
|
||||
if ADC1 is used (i.e. adc1-{avdd,vref}-supply present):
|
||||
- 0: ADC1 IN0
|
||||
- 1: ADC1 IN1
|
||||
- 2: ADC1 IN2
|
||||
- 3: ADC1 IN3
|
||||
- 4: ADC1 IN4
|
||||
- 5: ADC1 IN6
|
||||
- 6: ADC1 IN7
|
||||
- 7: ADC1 IN8
|
||||
if ADC2 is used (i.e. adc2-{avdd,vref}-supply present):
|
||||
- 8: ADC2 IN0
|
||||
- 9: ADC2 IN1
|
||||
- 10: ADC2 IN2
|
||||
- 11: ADC2 IN3
|
||||
- 12: ADC2 IN4
|
||||
- 13: ADC2 IN6
|
||||
- 14: ADC2 IN7
|
||||
- 15: ADC2 IN8
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- '#io-channel-cells'
|
||||
|
||||
# At least one of avvd/vref supplies
|
||||
anyOf:
|
||||
- required:
|
||||
- adc1-vref-supply
|
||||
- adc1-avdd-supply
|
||||
- required:
|
||||
- adc2-vref-supply
|
||||
- adc2-avdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r9a06g032-sysctrl.h>
|
||||
|
||||
adc: adc@40065000 {
|
||||
compatible = "renesas,r9a06g032-adc", "renesas,rzn1-adc";
|
||||
reg = <0x40065000 0x200>;
|
||||
clocks = <&sysctrl R9A06G032_HCLK_ADC>, <&sysctrl R9A06G032_CLK_ADC>;
|
||||
clock-names = "pclk", "adc";
|
||||
power-domains = <&sysctrl>;
|
||||
adc1-avdd-supply = <&adc1_avdd>;
|
||||
adc1-vref-supply = <&adc1_vref>;
|
||||
#io-channel-cells = <1>;
|
||||
};
|
||||
...
|
||||
@@ -16,6 +16,9 @@ properties:
|
||||
- const: rockchip,rk3066-tsadc
|
||||
- const: rockchip,rk3399-saradc
|
||||
- const: rockchip,rk3528-saradc
|
||||
- items:
|
||||
- const: rockchip,rk3506-saradc
|
||||
- const: rockchip,rk3528-saradc
|
||||
- const: rockchip,rk3562-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
|
||||
138
Documentation/devicetree/bindings/iio/dac/adi,ad5446.yaml
Normal file
138
Documentation/devicetree/bindings/iio/dac/adi,ad5446.yaml
Normal file
@@ -0,0 +1,138 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/dac/adi,ad5446.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD5446 and similar DACs
|
||||
|
||||
maintainers:
|
||||
- Michael Hennerich <michael.hennerich@analog.com>
|
||||
- Nuno Sá <nuno.sa@analog.com>
|
||||
|
||||
description:
|
||||
Digital to Analog Converter devices supporting both SPI and I2C interfaces.
|
||||
These devices feature a range of resolutions from 8-bit to 16-bit.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- description: SPI DACs
|
||||
enum:
|
||||
- adi,ad5300
|
||||
- adi,ad5310
|
||||
- adi,ad5320
|
||||
- adi,ad5444
|
||||
- adi,ad5446
|
||||
- adi,ad5450
|
||||
- adi,ad5451
|
||||
- adi,ad5452
|
||||
- adi,ad5453
|
||||
- adi,ad5512a
|
||||
- adi,ad5541a
|
||||
- adi,ad5542
|
||||
- adi,ad5542a
|
||||
- adi,ad5543
|
||||
- adi,ad5553
|
||||
- adi,ad5600
|
||||
- adi,ad5601
|
||||
- adi,ad5611
|
||||
- adi,ad5621
|
||||
- adi,ad5641
|
||||
- adi,ad5620-2500
|
||||
- adi,ad5620-1250
|
||||
- adi,ad5640-2500
|
||||
- adi,ad5640-1250
|
||||
- adi,ad5660-2500
|
||||
- adi,ad5660-1250
|
||||
- adi,ad5662
|
||||
- ti,dac081s101
|
||||
- ti,dac101s101
|
||||
- ti,dac121s101
|
||||
- description: I2C DACs
|
||||
enum:
|
||||
- adi,ad5301
|
||||
- adi,ad5311
|
||||
- adi,ad5321
|
||||
- adi,ad5602
|
||||
- adi,ad5612
|
||||
- adi,ad5622
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply:
|
||||
description:
|
||||
Reference voltage supply. If not supplied, devices with internal
|
||||
voltage reference will use that.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- adi,ad5300
|
||||
- adi,ad5310
|
||||
- adi,ad5320
|
||||
- adi,ad5444
|
||||
- adi,ad5446
|
||||
- adi,ad5450
|
||||
- adi,ad5451
|
||||
- adi,ad5452
|
||||
- adi,ad5453
|
||||
- adi,ad5512a
|
||||
- adi,ad5541a
|
||||
- adi,ad5542
|
||||
- adi,ad5542a
|
||||
- adi,ad5543
|
||||
- adi,ad5553
|
||||
- adi,ad5600
|
||||
- adi,ad5601
|
||||
- adi,ad5611
|
||||
- adi,ad5621
|
||||
- adi,ad5641
|
||||
- adi,ad5620-2500
|
||||
- adi,ad5620-1250
|
||||
- adi,ad5640-2500
|
||||
- adi,ad5640-1250
|
||||
- adi,ad5660-2500
|
||||
- adi,ad5660-1250
|
||||
- adi,ad5662
|
||||
- ti,dac081s101
|
||||
- ti,dac101s101
|
||||
- ti,dac121s101
|
||||
then:
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac@0 {
|
||||
compatible = "adi,ad5446";
|
||||
reg = <0>;
|
||||
vcc-supply = <&dac_vref>;
|
||||
};
|
||||
};
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dac@42 {
|
||||
compatible = "adi,ad5622";
|
||||
reg = <0x42>;
|
||||
vcc-supply = <&dac_vref>;
|
||||
};
|
||||
};
|
||||
...
|
||||
@@ -27,6 +27,14 @@ properties:
|
||||
LED current whilst the engine is running. First indexed value is
|
||||
the configuration for the RED LED, and second value is for the IR LED.
|
||||
|
||||
maxim,pulse-width-us:
|
||||
description: |
|
||||
LED pulse width in microseconds. Appropriate pulse width depends on
|
||||
factors such as optical window absorption, LED-to-sensor distance,
|
||||
and expected reflectivity of the skin or contact surface.
|
||||
enum: [200, 400, 800, 1600]
|
||||
default: 1600
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
|
||||
90
Documentation/devicetree/bindings/iio/imu/bosch,smi330.yaml
Normal file
90
Documentation/devicetree/bindings/iio/imu/bosch,smi330.yaml
Normal file
@@ -0,0 +1,90 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/imu/bosch,smi330.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Bosch SMI330 6-Axis IMU
|
||||
|
||||
maintainers:
|
||||
- Stefan Gutmann <stefam.gutmann@de.bosch.com>
|
||||
|
||||
description:
|
||||
SMI330 is a 6-axis inertial measurement unit that supports acceleration and
|
||||
gyroscopic measurements with hardware fifo buffering. Sensor also provides
|
||||
events information such as motion, no-motion and tilt detection.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: bosch,smi330
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: provide VDD power to the sensor.
|
||||
|
||||
vddio-supply:
|
||||
description: provide VDD IO power to the sensor.
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
enum:
|
||||
- INT1
|
||||
- INT2
|
||||
|
||||
drive-open-drain:
|
||||
type: boolean
|
||||
description:
|
||||
set if the interrupt pin(s) should be configured as
|
||||
open drain. If not set, defaults to push-pull.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
// Example for I2C
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
imu@68 {
|
||||
compatible = "bosch,smi330";
|
||||
reg = <0x68>;
|
||||
vddio-supply = <&vddio>;
|
||||
vdd-supply = <&vdd>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <26 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "INT1";
|
||||
};
|
||||
};
|
||||
|
||||
// Example for SPI
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
imu@0 {
|
||||
compatible = "bosch,smi330";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <10000000>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <26 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "INT1";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,90 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/imu/invensense,icm45600.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: InvenSense ICM-45600 Inertial Measurement Unit
|
||||
|
||||
maintainers:
|
||||
- Remi Buisson <remi.buisson@tdk.com>
|
||||
|
||||
description: |
|
||||
6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis
|
||||
accelerometer.
|
||||
|
||||
It has a configurable host interface that supports I3C, I2C and SPI serial
|
||||
communication, features up to 8kB FIFO and 2 programmable interrupts with
|
||||
ultra-low-power wake-on-motion support to minimize system power consumption.
|
||||
|
||||
Other industry-leading features include InvenSense on-chip APEX Motion
|
||||
Processing engine for gesture recognition, activity classification, and
|
||||
pedometer, along with programmable digital filters, and an embedded
|
||||
temperature sensor.
|
||||
|
||||
https://invensense.tdk.com/wp-content/uploads/documentation/DS-000576_ICM-45605.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- invensense,icm45605
|
||||
- invensense,icm45606
|
||||
- invensense,icm45608
|
||||
- invensense,icm45634
|
||||
- invensense,icm45686
|
||||
- invensense,icm45687
|
||||
- invensense,icm45688p
|
||||
- invensense,icm45689
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- enum: [int1, int2]
|
||||
- const: int2
|
||||
description: Choose chip interrupt pin to be used as interrupt input.
|
||||
|
||||
drive-open-drain:
|
||||
type: boolean
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
vddio-supply: true
|
||||
|
||||
mount-matrix: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vddio-supply
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
imu@68 {
|
||||
compatible = "invensense,icm45605";
|
||||
reg = <0x68>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupt-names = "int1";
|
||||
interrupts = <7 IRQ_TYPE_EDGE_RISING>;
|
||||
vdd-supply = <&vdd>;
|
||||
vddio-supply = <&vddio>;
|
||||
mount-matrix = "0", "-1", "0",
|
||||
"1", "0", "0",
|
||||
"0", "0", "1";
|
||||
};
|
||||
};
|
||||
@@ -86,7 +86,6 @@ unevaluatedProperties: false
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/pressure/aosong,adp810.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: aosong adp810 differential pressure sensor
|
||||
|
||||
maintainers:
|
||||
- Akhilesh Patil <akhilesh@ee.iitb.ac.in>
|
||||
|
||||
description:
|
||||
ADP810 is differential pressure and temperature sensor. It has I2C bus
|
||||
interface with fixed address of 0x25. This sensor supports 8 bit CRC for
|
||||
reliable data transfer. It can measure differential pressure in the
|
||||
range -500 to 500Pa and temperate in the range -40 to +85 degree celsius.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- aosong,adp810
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
pressure-sensor@25 {
|
||||
compatible = "aosong,adp810";
|
||||
reg = <0x25>;
|
||||
vdd-supply = <&vdd_regulator>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/pressure/fsl,mpl3115.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MPL3115 precision pressure sensor with altimetry
|
||||
|
||||
maintainers:
|
||||
- Antoni Pokusinski <apokusinski01@gmail.com>
|
||||
|
||||
description: |
|
||||
MPL3115 is a pressure/altitude and temperature sensor with I2C interface.
|
||||
It features two programmable interrupt lines which indicate events such as
|
||||
data ready or pressure/temperature threshold reached.
|
||||
https://www.nxp.com/docs/en/data-sheet/MPL3115A2.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fsl,mpl3115
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
vddio-supply: true
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
enum:
|
||||
- INT1
|
||||
- INT2
|
||||
|
||||
drive-open-drain:
|
||||
type: boolean
|
||||
description:
|
||||
set if the specified interrupt pins should be configured as
|
||||
open drain. If not set, defaults to push-pull.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- vddio-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pressure@60 {
|
||||
compatible = "fsl,mpl3115";
|
||||
reg = <0x60>;
|
||||
vdd-supply = <&vdd>;
|
||||
vddio-supply = <&vddio>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-names = "INT2";
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/pressure/infineon,dps310.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Infineon DPS310 barometric pressure and temperature sensor
|
||||
|
||||
maintainers:
|
||||
- Eddie James <eajames@linux.ibm.com>
|
||||
|
||||
description:
|
||||
The DPS310 is a barometric pressure and temperature sensor with an I2C
|
||||
interface.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- infineon,dps310
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 0
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
Voltage supply for the chip's analog blocks.
|
||||
|
||||
vddio-supply:
|
||||
description:
|
||||
Digital voltage supply for the chip's digital blocks and I/O interface.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dps: pressure-sensor@76 {
|
||||
compatible = "infineon,dps310";
|
||||
reg = <0x76>;
|
||||
#io-channel-cells = <0>;
|
||||
vdd-supply = <&vref1>;
|
||||
vddio-supply = <&vref2>;
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,124 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/interconnect/qcom,kaanapali-rpmh.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm RPMh Network-On-Chip Interconnect on Kaanapali
|
||||
|
||||
maintainers:
|
||||
- Raviteja Laggyshetty <raviteja.laggyshetty@oss.qualcomm.com>
|
||||
|
||||
description: |
|
||||
RPMh interconnect providers support system bandwidth requirements through
|
||||
RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is
|
||||
able to communicate with the BCM through the Resource State Coordinator (RSC)
|
||||
associated with each execution environment. Provider nodes must point to at
|
||||
least one RPMh device child node pertaining to their RSC and each provider
|
||||
can map to multiple RPMh resources.
|
||||
|
||||
See also: include/dt-bindings/interconnect/qcom,kaanapali-rpmh.h
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,kaanapali-aggre-noc
|
||||
- qcom,kaanapali-clk-virt
|
||||
- qcom,kaanapali-cnoc-main
|
||||
- qcom,kaanapali-cnoc-cfg
|
||||
- qcom,kaanapali-gem-noc
|
||||
- qcom,kaanapali-lpass-ag-noc
|
||||
- qcom,kaanapali-lpass-lpiaon-noc
|
||||
- qcom,kaanapali-lpass-lpicx-noc
|
||||
- qcom,kaanapali-mc-virt
|
||||
- qcom,kaanapali-mmss-noc
|
||||
- qcom,kaanapali-nsp-noc
|
||||
- qcom,kaanapali-pcie-anoc
|
||||
- qcom,kaanapali-system-noc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: qcom,rpmh-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,kaanapali-clk-virt
|
||||
- qcom,kaanapali-mc-virt
|
||||
then:
|
||||
properties:
|
||||
reg: false
|
||||
else:
|
||||
required:
|
||||
- reg
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,kaanapali-pcie-anoc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: aggre-NOC PCIe AXI clock
|
||||
- description: cfg-NOC PCIe a-NOC AHB clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,kaanapali-aggre-noc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: aggre UFS PHY AXI clock
|
||||
- description: aggre USB3 PRIM AXI clock
|
||||
- description: RPMH CC IPA clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,kaanapali-aggre-noc
|
||||
- qcom,kaanapali-pcie-anoc
|
||||
then:
|
||||
required:
|
||||
- clocks
|
||||
else:
|
||||
properties:
|
||||
clocks: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
clk_virt: interconnect-0 {
|
||||
compatible = "qcom,kaanapali-clk-virt";
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
|
||||
aggre_noc: interconnect@16e0000 {
|
||||
compatible = "qcom,kaanapali-aggre-noc";
|
||||
reg = <0x016e0000 0x42400>;
|
||||
#interconnect-cells = <2>;
|
||||
clocks = <&gcc_aggre_ufs_phy_axi_clk>,
|
||||
<&gcc_aggre_usb3_prim_axi_clk>,
|
||||
<&rpmhcc_ipa_clk>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
@@ -25,6 +25,7 @@ properties:
|
||||
- const: qcom,msm8998-bwmon # BWMON v4
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,kaanapali-cpu-bwmon
|
||||
- qcom,qcm2290-cpu-bwmon
|
||||
- qcom,qcs615-cpu-bwmon
|
||||
- qcom,qcs8300-cpu-bwmon
|
||||
|
||||
@@ -33,18 +33,66 @@ properties:
|
||||
- qcom,sa8775p-pcie-anoc
|
||||
- qcom,sa8775p-system-noc
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 2
|
||||
maxItems: 5
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: qcom,rpmh-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sa8775p-aggre1-noc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: aggre UFS PHY AXI clock
|
||||
- description: aggre QUP PRIM AXI clock
|
||||
- description: aggre USB2 PRIM AXI clock
|
||||
- description: aggre USB3 PRIM AXI clock
|
||||
- description: aggre USB3 SEC AXI clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sa8775p-aggre2-noc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: aggre UFS CARD AXI clock
|
||||
- description: RPMH CC IPA clock
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
aggre1_noc: interconnect-aggre1-noc {
|
||||
compatible = "qcom,sa8775p-aggre1-noc";
|
||||
#include <dt-bindings/clock/qcom,sa8775p-gcc.h>
|
||||
clk_virt: interconnect-clk-virt {
|
||||
compatible = "qcom,sa8775p-clk-virt";
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
|
||||
aggre1_noc: interconnect@16c0000 {
|
||||
compatible = "qcom,sa8775p-aggre1-noc";
|
||||
reg = <0x016c0000 0x18080>;
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
clocks = <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>,
|
||||
<&gcc GCC_AGGRE_NOC_QUPV3_AXI_CLK>,
|
||||
<&gcc GCC_AGGRE_USB2_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&gcc GCC_AGGRE_USB3_SEC_AXI_CLK>;
|
||||
};
|
||||
|
||||
@@ -12,9 +12,6 @@ maintainers:
|
||||
description:
|
||||
Qualcomm RPMh-based interconnect provider on SM6350.
|
||||
|
||||
allOf:
|
||||
- $ref: qcom,rpmh-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
@@ -30,7 +27,9 @@ properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#interconnect-cells': true
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
patternProperties:
|
||||
'^interconnect-[a-z0-9\-]+$':
|
||||
@@ -46,8 +45,6 @@ patternProperties:
|
||||
- qcom,sm6350-clk-virt
|
||||
- qcom,sm6350-compute-noc
|
||||
|
||||
'#interconnect-cells': true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
@@ -57,10 +54,54 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: qcom,rpmh-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm6350-aggre1-noc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: aggre UFS PHY AXI clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm6350-aggre2-noc
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
items:
|
||||
- description: aggre USB3 PRIM AXI clock
|
||||
- description: RPMH CC IPA clock
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,sm6350-aggre1-noc
|
||||
- qcom,sm6350-aggre2-noc
|
||||
then:
|
||||
required:
|
||||
- clocks
|
||||
else:
|
||||
properties:
|
||||
clocks: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-sm6350.h>
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
|
||||
config_noc: interconnect@1500000 {
|
||||
compatible = "qcom,sm6350-config-noc";
|
||||
reg = <0x01500000 0x28000>;
|
||||
@@ -68,14 +109,16 @@ examples:
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
|
||||
system_noc: interconnect@1620000 {
|
||||
compatible = "qcom,sm6350-system-noc";
|
||||
reg = <0x01620000 0x17080>;
|
||||
aggre2_noc: interconnect@1700000 {
|
||||
compatible = "qcom,sm6350-aggre2-noc";
|
||||
reg = <0x01700000 0x1f880>;
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
clocks = <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
|
||||
<&rpmhcc RPMH_IPA_CLK>;
|
||||
|
||||
clk_virt: interconnect-clk-virt {
|
||||
compatible = "qcom,sm6350-clk-virt";
|
||||
compute_noc: interconnect-compute-noc {
|
||||
compatible = "qcom,sm6350-compute-noc";
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,8 @@ maintainers:
|
||||
description: |
|
||||
This binding represents the on-chip eFuse OTP controller found on
|
||||
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL,
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93/5 SoCs.
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP, i.MX93, i.MX94,
|
||||
and i.MX95.
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
@@ -36,6 +37,7 @@ properties:
|
||||
- fsl,imx8mq-ocotp
|
||||
- fsl,imx8mm-ocotp
|
||||
- fsl,imx93-ocotp
|
||||
- fsl,imx94-ocotp
|
||||
- fsl,imx95-ocotp
|
||||
- const: syscon
|
||||
- items:
|
||||
|
||||
@@ -46,6 +46,12 @@ properties:
|
||||
type: object
|
||||
description: Command to use for automatic booting
|
||||
|
||||
env-size:
|
||||
description:
|
||||
Size in bytes of the environment data used by U-Boot for CRC
|
||||
calculation. If omitted, the full NVMEM region size is used.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
ethaddr:
|
||||
type: object
|
||||
description: Ethernet interfaces base MAC address.
|
||||
@@ -104,6 +110,7 @@ examples:
|
||||
|
||||
partition-u-boot-env {
|
||||
compatible = "brcm,env";
|
||||
env-size = <0x20000>;
|
||||
|
||||
ethaddr {
|
||||
};
|
||||
|
||||
@@ -25,7 +25,9 @@ properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: mediatek,mt8188-efuse
|
||||
- enum:
|
||||
- mediatek,mt8188-efuse
|
||||
- mediatek,mt8189-efuse
|
||||
- const: mediatek,mt8186-efuse
|
||||
- const: mediatek,mt8186-efuse
|
||||
|
||||
@@ -48,6 +50,7 @@ properties:
|
||||
- mediatek,mt7988-efuse
|
||||
- mediatek,mt8173-efuse
|
||||
- mediatek,mt8183-efuse
|
||||
- mediatek,mt8189-efuse
|
||||
- mediatek,mt8192-efuse
|
||||
- mediatek,mt8195-efuse
|
||||
- mediatek,mt8516-efuse
|
||||
|
||||
@@ -39,6 +39,7 @@ properties:
|
||||
- qcom,qcs404-qfprom
|
||||
- qcom,qcs615-qfprom
|
||||
- qcom,qcs8300-qfprom
|
||||
- qcom,sa8775p-qfprom
|
||||
- qcom,sar2130p-qfprom
|
||||
- qcom,sc7180-qfprom
|
||||
- qcom,sc7280-qfprom
|
||||
|
||||
@@ -31,7 +31,7 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
"@[0-9a-f]+$":
|
||||
type: object
|
||||
$ref: layouts/fixed-cell.yaml
|
||||
unevaluatedProperties: false
|
||||
|
||||
@@ -75,16 +75,22 @@ examples:
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
slim@28080000 {
|
||||
controller@28080000 {
|
||||
compatible = "qcom,slim-ngd-v1.5.0";
|
||||
reg = <0x091c0000 0x2c000>;
|
||||
interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <2>;
|
||||
dmas = <&slimbam 3>, <&slimbam 4>;
|
||||
dma-names = "rx", "tx";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
audio-codec@1,0 {
|
||||
slim@1 {
|
||||
reg = <1>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
codec@1,0 {
|
||||
compatible = "slim217,1a0";
|
||||
reg = <1 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -121,8 +121,6 @@ properties:
|
||||
- fsl,mma7660
|
||||
# MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
|
||||
- fsl,mma8450
|
||||
# MPL3115: Absolute Digital Pressure Sensor
|
||||
- fsl,mpl3115
|
||||
# MPR121: Proximity Capacitive Touch Sensor Controller
|
||||
- fsl,mpr121
|
||||
# Honeywell Humidicon HIH-6130 humidity/temperature sensor
|
||||
@@ -135,8 +133,6 @@ properties:
|
||||
- ibm,cffps2
|
||||
# IBM On-Chip Controller hwmon device
|
||||
- ibm,p8-occ-hwmon
|
||||
# Infineon barometric pressure and temperature sensor
|
||||
- infineon,dps310
|
||||
# Infineon IR36021 digital POL buck controller
|
||||
- infineon,ir36021
|
||||
# Infineon IRPS5401 Voltage Regulator (PMIC)
|
||||
|
||||
@@ -264,5 +264,5 @@ Configure RMS voltage event thresholds (requires interrupts):
|
||||
8. IIO Interfacing Tools
|
||||
========================
|
||||
|
||||
See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO
|
||||
See Documentation/iio/iio_tools.rst for the description of the available IIO
|
||||
interfacing tools.
|
||||
|
||||
@@ -374,11 +374,11 @@ Obtain buffered data:
|
||||
00001740 01 1a 00 00 ff ff fe 31 00 00 46 aa 00 03 37 f7 |.......1..F...7.|
|
||||
...
|
||||
|
||||
See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered
|
||||
See Documentation/iio/iio_devbuf.rst for more information about how buffered
|
||||
data is structured.
|
||||
|
||||
4. IIO Interfacing Tools
|
||||
========================
|
||||
|
||||
See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO
|
||||
See Documentation/iio/iio_tools.rst for the description of the available IIO
|
||||
interfacing tools.
|
||||
|
||||
@@ -436,11 +436,11 @@ Obtain buffered data::
|
||||
00006b60 09 63 00 00 00 00 1b 13 00 00 22 2f 00 03 23 91 |.c........"/..#.|
|
||||
...
|
||||
|
||||
See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered
|
||||
See Documentation/iio/iio_devbuf.rst for more information about how buffered
|
||||
data is structured.
|
||||
|
||||
4. IIO Interfacing Tools
|
||||
========================
|
||||
|
||||
See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO
|
||||
See Documentation/iio/iio_tools.rst for the description of the available IIO
|
||||
interfacing tools.
|
||||
|
||||
@@ -366,11 +366,11 @@ Obtain buffered data:
|
||||
0000ceb0 00 00 0d 2f 00 00 05 25 00 00 07 8d 00 00 a2 ce |.../...%........|
|
||||
...
|
||||
|
||||
See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered
|
||||
See Documentation/iio/iio_devbuf.rst for more information about how buffered
|
||||
data is structured.
|
||||
|
||||
4. IIO Interfacing Tools
|
||||
========================
|
||||
|
||||
See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO
|
||||
See Documentation/iio/iio_tools.rst for the description of the available IIO
|
||||
interfacing tools.
|
||||
|
||||
@@ -433,11 +433,11 @@ Obtain buffered data:
|
||||
00000f0 00004 00014 00015 00005 00012 00011 00005 00012
|
||||
...
|
||||
|
||||
See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered
|
||||
See Documentation/iio/iio_devbuf.rst for more information about how buffered
|
||||
data is structured.
|
||||
|
||||
4. IIO Interfacing Tools
|
||||
========================
|
||||
|
||||
See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO
|
||||
See Documentation/iio/iio_tools.rst for the description of the available IIO
|
||||
interfacing tools.
|
||||
|
||||
@@ -223,11 +223,11 @@ Obtain buffered data:
|
||||
002bc3c0 f7 fd 00 cb fb 94 24 80 f7 e3 00 f2 fb b8 24 80 |......$.......$.|
|
||||
...
|
||||
|
||||
See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered
|
||||
See Documentation/iio/iio_devbuf.rst for more information about how buffered
|
||||
data is structured.
|
||||
|
||||
4. IIO Interfacing Tools
|
||||
========================
|
||||
|
||||
See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO
|
||||
See Documentation/iio/iio_tools.rst for the description of the available IIO
|
||||
interfacing tools.
|
||||
|
||||
68
MAINTAINERS
68
MAINTAINERS
@@ -440,6 +440,18 @@ W: http://wiki.analog.com/AD5398
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: drivers/regulator/ad5398.c
|
||||
|
||||
AD5446 ANALOG DEVICES INC AD5446 DAC DRIVER
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
M: Nuno Sá <nuno.sa@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ad5446.yaml
|
||||
F: drivers/iio/dac/ad5446-i2c.c
|
||||
F: drivers/iio/dac/ad5446-spi.c
|
||||
F: drivers/iio/dac/ad5446.c
|
||||
F: drivers/iio/dac/ad5446.h
|
||||
|
||||
AD714X CAPACITANCE TOUCH SENSOR DRIVER (AD7142/3/7/8/7A)
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
S: Supported
|
||||
@@ -1809,11 +1821,9 @@ ANDROID DRIVERS
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
M: Arve Hjønnevåg <arve@android.com>
|
||||
M: Todd Kjos <tkjos@android.com>
|
||||
M: Martijn Coenen <maco@android.com>
|
||||
M: Joel Fernandes <joelagnelf@nvidia.com>
|
||||
M: Christian Brauner <christian@brauner.io>
|
||||
M: Carlos Llamas <cmllamas@google.com>
|
||||
M: Suren Baghdasaryan <surenb@google.com>
|
||||
M: Alice Ryhl <aliceryhl@google.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
|
||||
@@ -3794,6 +3804,13 @@ S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/chemical/aosong,ags02ma.yaml
|
||||
F: drivers/iio/chemical/ags02ma.c
|
||||
|
||||
AOSONG ADP810 DIFFERENTIAL PRESSURE SENSOR DRIVER
|
||||
M: Akhilesh Patil <akhilesh@ee.iitb.ac.in>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/pressure/aosong,adp810.yaml
|
||||
F: drivers/iio/pressure/adp810.c
|
||||
|
||||
ASC7621 HARDWARE MONITOR DRIVER
|
||||
M: George Joseph <george.joseph@fairview5.com>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
@@ -4526,6 +4543,13 @@ F: include/net/bond*
|
||||
F: include/uapi/linux/if_bonding.h
|
||||
F: tools/testing/selftests/drivers/net/bonding/
|
||||
|
||||
BOSCH SENSORTEC BMA220 ACCELEROMETER IIO DRIVER
|
||||
M: Petre Rodan <petre.rodan@subdimension.ro>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/accel/bosch,bma220.yaml
|
||||
F: drivers/iio/accel/bma220*
|
||||
|
||||
BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER
|
||||
M: Dan Robertson <dan@dlrobertson.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
@@ -12312,11 +12336,13 @@ L: industrypack-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
W: http://industrypack.sourceforge.net
|
||||
F: drivers/ipack/
|
||||
F: include/linux/ipack.h
|
||||
|
||||
INFINEON DPS310 Driver
|
||||
M: Eddie James <eajames@linux.ibm.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/pressure/infineon,dps310.yaml
|
||||
F: drivers/iio/pressure/dps310.c
|
||||
|
||||
INFINEON PEB2466 ASoC CODEC
|
||||
@@ -12839,7 +12865,7 @@ F: drivers/mfd/intel-m10-bmc*
|
||||
F: include/linux/mfd/intel-m10-bmc.h
|
||||
|
||||
INTEL MAX10 BMC SECURE UPDATES
|
||||
M: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
M: Xu Yilun <yilun.xu@intel.com>
|
||||
L: linux-fpga@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
|
||||
@@ -13138,6 +13164,14 @@ F: Documentation/ABI/testing/sysfs-bus-iio-inv_icm42600
|
||||
F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
|
||||
F: drivers/iio/imu/inv_icm42600/
|
||||
|
||||
INVENSENSE ICM-456xx IMU DRIVER
|
||||
M: Remi Buisson <remi.buisson@tdk.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://invensense.tdk.com/
|
||||
F: Documentation/devicetree/bindings/iio/imu/invensense,icm45600.yaml
|
||||
F: drivers/iio/imu/inv_icm45600/
|
||||
|
||||
INVENSENSE MPU-3050 GYROSCOPE DRIVER
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
L: linux-iio@vger.kernel.org
|
||||
@@ -15300,6 +15334,15 @@ S: Orphan
|
||||
F: drivers/video/fbdev/matrox/matroxfb_*
|
||||
F: include/uapi/linux/matroxfb.h
|
||||
|
||||
MAX14001/MAX14002 IIO ADC DRIVER
|
||||
M: Kim Seer Paller <kimseer.paller@analog.com>
|
||||
M: Marilene Andrade Garcia <marilene.agarcia@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,max14001.yaml
|
||||
F: drivers/iio/adc/max14001.c
|
||||
|
||||
MAX15301 DRIVER
|
||||
M: Daniel Nilsson <daniel.nilsson@flex.com>
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
@@ -18946,7 +18989,7 @@ OCXL (Open Coherent Accelerator Processor Interface OpenCAPI) DRIVER
|
||||
M: Frederic Barrat <fbarrat@linux.ibm.com>
|
||||
M: Andrew Donnellan <ajd@linux.ibm.com>
|
||||
L: linuxppc-dev@lists.ozlabs.org
|
||||
S: Supported
|
||||
S: Odd Fixes
|
||||
F: Documentation/userspace-api/accelerators/ocxl.rst
|
||||
F: arch/powerpc/include/asm/pnv-ocxl.h
|
||||
F: arch/powerpc/platforms/powernv/ocxl.c
|
||||
@@ -22115,6 +22158,14 @@ S: Supported
|
||||
F: Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
|
||||
F: drivers/counter/rz-mtu3-cnt.c
|
||||
|
||||
RENESAS RZ/T2H / RZ/N2H A/D DRIVER
|
||||
M: Cosmin Tanislav <cosmin-gabriel.tanislav.xa@renesas.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/iio/adc/renesas,r9a09g077-adc.yaml
|
||||
F: drivers/iio/adc/rzt2h_adc.c
|
||||
|
||||
RENESAS RTCA-3 RTC DRIVER
|
||||
M: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
|
||||
L: linux-rtc@vger.kernel.org
|
||||
@@ -22136,6 +22187,13 @@ F: include/dt-bindings/net/pcs-rzn1-miic.h
|
||||
F: include/linux/pcs-rzn1-miic.h
|
||||
F: net/dsa/tag_rzn1_a5psw.c
|
||||
|
||||
RENESAS RZ/N1 ADC DRIVER
|
||||
M: Herve Codina <herve.codina@bootlin.com>
|
||||
L: linux-renesas-soc@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/iio/adc/renesas,rzn1-adc.yaml
|
||||
F: drivers/iio/adc/rzn1-adc.c
|
||||
|
||||
RENESAS RZ/N1 DWMAC GLUE LAYER
|
||||
M: Romain Gantois <romain.gantois@bootlin.com>
|
||||
S: Maintained
|
||||
|
||||
@@ -1371,7 +1371,7 @@ static void sa1111_bus_remove(struct device *dev)
|
||||
drv->remove(sadev);
|
||||
}
|
||||
|
||||
struct bus_type sa1111_bus_type = {
|
||||
const struct bus_type sa1111_bus_type = {
|
||||
.name = "sa1111-rab",
|
||||
.match = sa1111_match,
|
||||
.probe = sa1111_bus_probe,
|
||||
|
||||
@@ -368,7 +368,7 @@
|
||||
|
||||
|
||||
|
||||
extern struct bus_type sa1111_bus_type;
|
||||
extern const struct bus_type sa1111_bus_type;
|
||||
|
||||
#define SA1111_DEVID_SBI (1 << 0)
|
||||
#define SA1111_DEVID_SK (1 << 1)
|
||||
|
||||
@@ -3496,6 +3496,9 @@
|
||||
<&gcc GCC_USB20_MASTER_CLK>;
|
||||
assigned-clock-rates = <19200000>, <60000000>;
|
||||
|
||||
interconnects = <&pnoc MASTER_USB_HS &bimc SLAVE_EBI_CH0>,
|
||||
<&bimc MASTER_AMPSS_M0 &pnoc SLAVE_USB_HS>;
|
||||
interconnect-names = "usb-ddr", "apps-usb";
|
||||
power-domains = <&gcc USB30_GDSC>;
|
||||
qcom,select-utmi-as-pipe-clk;
|
||||
status = "disabled";
|
||||
|
||||
@@ -464,7 +464,7 @@ void spu_init_channels(struct spu *spu)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(spu_init_channels);
|
||||
|
||||
static struct bus_type spu_subsys = {
|
||||
static const struct bus_type spu_subsys = {
|
||||
.name = "spu",
|
||||
.dev_name = "spu",
|
||||
};
|
||||
|
||||
@@ -465,7 +465,7 @@ static struct attribute *ps3_system_bus_dev_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(ps3_system_bus_dev);
|
||||
|
||||
static struct bus_type ps3_system_bus_type = {
|
||||
static const struct bus_type ps3_system_bus_type = {
|
||||
.name = "ps3_system_bus",
|
||||
.match = ps3_system_bus_match,
|
||||
.uevent = ps3_system_bus_uevent,
|
||||
|
||||
@@ -375,7 +375,7 @@ static struct device_attribute *cmm_attrs[] = {
|
||||
static DEVICE_ULONG_ATTR(simulate_loan_target_kb, 0644,
|
||||
simulate_loan_target_kb);
|
||||
|
||||
static struct bus_type cmm_subsys = {
|
||||
static const struct bus_type cmm_subsys = {
|
||||
.name = "cmm",
|
||||
.dev_name = "cmm",
|
||||
};
|
||||
|
||||
@@ -126,7 +126,7 @@ static ssize_t show_hibernate(struct device *dev,
|
||||
|
||||
static DEVICE_ATTR(hibernate, 0644, show_hibernate, store_hibernate);
|
||||
|
||||
static struct bus_type suspend_subsys = {
|
||||
static const struct bus_type suspend_subsys = {
|
||||
.name = "power",
|
||||
.dev_name = "power",
|
||||
};
|
||||
|
||||
@@ -4669,6 +4669,8 @@ static int binder_wait_for_work(struct binder_thread *thread,
|
||||
*
|
||||
* If we fail to allocate an fd, skip the install and release
|
||||
* any fds that have already been allocated.
|
||||
*
|
||||
* Return: 0 on success, a negative errno code on failure.
|
||||
*/
|
||||
static int binder_apply_fd_fixups(struct binder_proc *proc,
|
||||
struct binder_transaction *t)
|
||||
|
||||
@@ -541,10 +541,10 @@ impl Node {
|
||||
guard = self.owner.inner.lock();
|
||||
}
|
||||
|
||||
let death_list = core::mem::take(&mut self.inner.access_mut(&mut guard).death_list);
|
||||
drop(guard);
|
||||
for death in death_list {
|
||||
while let Some(death) = self.inner.access_mut(&mut guard).death_list.pop_front() {
|
||||
drop(guard);
|
||||
death.into_arc().set_dead();
|
||||
guard = self.owner.inner.lock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1392,8 +1392,12 @@ impl Process {
|
||||
work.into_arc().cancel();
|
||||
}
|
||||
|
||||
let delivered_deaths = take(&mut self.inner.lock().delivered_deaths);
|
||||
drop(delivered_deaths);
|
||||
// Clear delivered_deaths list.
|
||||
//
|
||||
// Scope ensures that MutexGuard is dropped while executing the body.
|
||||
while let Some(delivered_death) = { self.inner.lock().delivered_deaths.pop_front() } {
|
||||
drop(delivered_death);
|
||||
}
|
||||
|
||||
// Free any resources kept alive by allocated buffers.
|
||||
let omapping = self.inner.lock().mapping.take();
|
||||
@@ -1653,15 +1657,6 @@ impl Process {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn compat_ioctl(
|
||||
this: ArcBorrow<'_, Process>,
|
||||
file: &File,
|
||||
cmd: u32,
|
||||
arg: usize,
|
||||
) -> Result {
|
||||
Self::ioctl(this, file, cmd, arg)
|
||||
}
|
||||
|
||||
pub(crate) fn mmap(
|
||||
this: ArcBorrow<'_, Process>,
|
||||
_file: &File,
|
||||
|
||||
@@ -313,8 +313,8 @@ pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = {
|
||||
let ops = kernel::bindings::file_operations {
|
||||
owner: THIS_MODULE.as_ptr(),
|
||||
poll: Some(rust_binder_poll),
|
||||
unlocked_ioctl: Some(rust_binder_unlocked_ioctl),
|
||||
compat_ioctl: Some(rust_binder_compat_ioctl),
|
||||
unlocked_ioctl: Some(rust_binder_ioctl),
|
||||
compat_ioctl: Some(bindings::compat_ptr_ioctl),
|
||||
mmap: Some(rust_binder_mmap),
|
||||
open: Some(rust_binder_open),
|
||||
release: Some(rust_binder_release),
|
||||
@@ -402,23 +402,7 @@ unsafe extern "C" fn rust_binder_release(
|
||||
|
||||
/// # Safety
|
||||
/// Only called by binderfs.
|
||||
unsafe extern "C" fn rust_binder_compat_ioctl(
|
||||
file: *mut bindings::file,
|
||||
cmd: kernel::ffi::c_uint,
|
||||
arg: kernel::ffi::c_ulong,
|
||||
) -> kernel::ffi::c_long {
|
||||
// SAFETY: We previously set `private_data` in `rust_binder_open`.
|
||||
let f = unsafe { Arc::<Process>::borrow((*file).private_data) };
|
||||
// SAFETY: The caller ensures that the file is valid.
|
||||
match Process::compat_ioctl(f, unsafe { File::from_raw_file(file) }, cmd as _, arg as _) {
|
||||
Ok(()) => 0,
|
||||
Err(err) => err.to_errno() as isize,
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Only called by binderfs.
|
||||
unsafe extern "C" fn rust_binder_unlocked_ioctl(
|
||||
unsafe extern "C" fn rust_binder_ioctl(
|
||||
file: *mut bindings::file,
|
||||
cmd: kernel::ffi::c_uint,
|
||||
arg: kernel::ffi::c_ulong,
|
||||
|
||||
@@ -1323,12 +1323,12 @@ impl Thread {
|
||||
}
|
||||
BC_FREE_BUFFER => {
|
||||
let buffer = self.process.buffer_get(reader.read()?);
|
||||
if let Some(buffer) = &buffer {
|
||||
if let Some(buffer) = buffer {
|
||||
if buffer.looper_need_return_on_free() {
|
||||
self.inner.lock().looper_need_return = true;
|
||||
}
|
||||
drop(buffer);
|
||||
}
|
||||
drop(buffer);
|
||||
}
|
||||
BC_INCREFS => {
|
||||
self.process
|
||||
|
||||
@@ -211,6 +211,9 @@ err:
|
||||
|
||||
/**
|
||||
* binder_ctl_ioctl - handle binder device node allocation requests
|
||||
* @file: The file pointer for the binder-control device node.
|
||||
* @cmd: The ioctl command.
|
||||
* @arg: The ioctl argument.
|
||||
*
|
||||
* The request handler for the binder-control device. All requests operate on
|
||||
* the binderfs mount the binder-control device resides in:
|
||||
|
||||
@@ -554,7 +554,7 @@ static void binder_alloc_test_exit(struct kunit *test)
|
||||
static struct kunit_case binder_alloc_test_cases[] = {
|
||||
KUNIT_CASE(binder_alloc_test_init_freelist),
|
||||
KUNIT_CASE(binder_alloc_test_mmap),
|
||||
KUNIT_CASE(binder_alloc_exhaustive_test),
|
||||
KUNIT_CASE_SLOW(binder_alloc_exhaustive_test),
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ config FW_LOADER_DEBUG
|
||||
config RUST_FW_LOADER_ABSTRACTIONS
|
||||
bool "Rust Firmware Loader abstractions"
|
||||
depends on RUST
|
||||
depends on FW_LOADER=y
|
||||
select FW_LOADER
|
||||
help
|
||||
This enables the Rust abstractions for the firmware loader API.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
extern struct bus_type mhi_ep_bus_type;
|
||||
extern const struct bus_type mhi_ep_bus_type;
|
||||
|
||||
#define MHI_REG_OFFSET 0x100
|
||||
#define BHI_REG_OFFSET 0x200
|
||||
|
||||
@@ -1494,7 +1494,7 @@ int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,
|
||||
INIT_WORK(&mhi_cntrl->cmd_ring_work, mhi_ep_cmd_ring_worker);
|
||||
INIT_WORK(&mhi_cntrl->ch_ring_work, mhi_ep_ch_ring_worker);
|
||||
|
||||
mhi_cntrl->wq = alloc_workqueue("mhi_ep_wq", 0, 0);
|
||||
mhi_cntrl->wq = alloc_workqueue("mhi_ep_wq", WQ_PERCPU, 0);
|
||||
if (!mhi_cntrl->wq) {
|
||||
ret = -ENOMEM;
|
||||
goto err_destroy_ring_item_cache;
|
||||
@@ -1703,7 +1703,7 @@ static int mhi_ep_match(struct device *dev, const struct device_driver *drv)
|
||||
return 0;
|
||||
};
|
||||
|
||||
struct bus_type mhi_ep_bus_type = {
|
||||
const struct bus_type mhi_ep_bus_type = {
|
||||
.name = "mhi_ep",
|
||||
.dev_name = "mhi_ep",
|
||||
.match = mhi_ep_match,
|
||||
|
||||
@@ -663,6 +663,17 @@ static const struct mhi_pci_dev_info mhi_foxconn_t99w696_info = {
|
||||
.sideband_wake = false,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_foxconn_t99w760_info = {
|
||||
.name = "foxconn-t99w760",
|
||||
.edl = "qcom/sdx35/foxconn/xbl_s_devprg_ns.melf",
|
||||
.edl_trigger = true,
|
||||
.config = &modem_foxconn_sdx61_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.mru_default = 32768,
|
||||
.sideband_wake = false,
|
||||
};
|
||||
|
||||
static const struct mhi_channel_config mhi_mv3x_channels[] = {
|
||||
MHI_CHANNEL_CONFIG_UL(0, "LOOPBACK", 64, 0),
|
||||
MHI_CHANNEL_CONFIG_DL(1, "LOOPBACK", 64, 0),
|
||||
@@ -877,6 +888,16 @@ static const struct mhi_pci_dev_info mhi_telit_fn990b40_info = {
|
||||
.edl_trigger = true,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_telit_fe990b40_info = {
|
||||
.name = "telit-fe990b40",
|
||||
.config = &modem_telit_fn920c04_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.sideband_wake = false,
|
||||
.mru_default = 32768,
|
||||
.edl_trigger = true,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = {
|
||||
.name = "netprisma-lcur57",
|
||||
.edl = "qcom/prog_firehose_sdx24.mbn",
|
||||
@@ -933,6 +954,9 @@ static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
/* Telit FN990B40 (sdx72) */
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0309, 0x1c5d, 0x201a),
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fn990b40_info },
|
||||
/* Telit FE990B40 (sdx72) */
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0309, 0x1c5d, 0x2025),
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fe990b40_info },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0309),
|
||||
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx75_info },
|
||||
/* QDU100, x100-DU */
|
||||
@@ -997,6 +1021,8 @@ static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
/* DW5934e(sdx72), Non-eSIM */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe11e),
|
||||
.driver_data = (kernel_ulong_t) &mhi_foxconn_dw5934e_info },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_FOXCONN, 0xe123),
|
||||
.driver_data = (kernel_ulong_t) &mhi_foxconn_t99w760_info },
|
||||
/* MV31-W (Cinterion) */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_THALES, 0x00b3),
|
||||
.driver_data = (kernel_ulong_t) &mhi_mv31_info },
|
||||
|
||||
@@ -170,7 +170,7 @@ static int cdx_unregister_device(struct device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cdx_unregister_devices(struct bus_type *bus)
|
||||
static void cdx_unregister_devices(const struct bus_type *bus)
|
||||
{
|
||||
/* Reset all the devices attached to cdx bus */
|
||||
bus_for_each_dev(bus, NULL, NULL, cdx_unregister_device);
|
||||
@@ -651,7 +651,7 @@ static struct attribute *cdx_bus_attrs[] = {
|
||||
};
|
||||
ATTRIBUTE_GROUPS(cdx_bus);
|
||||
|
||||
struct bus_type cdx_bus_type = {
|
||||
const struct bus_type cdx_bus_type = {
|
||||
.name = "cdx",
|
||||
.match = cdx_bus_match,
|
||||
.probe = cdx_probe,
|
||||
|
||||
@@ -80,8 +80,8 @@ static ssize_t adi_read(struct file *file, char __user *buf,
|
||||
bytes_read += ver_buf_sz;
|
||||
ver_buf_idx = 0;
|
||||
|
||||
ver_buf_sz = min(count - bytes_read,
|
||||
(size_t)MAX_BUF_SZ);
|
||||
ver_buf_sz = min_t(size_t, count - bytes_read,
|
||||
MAX_BUF_SZ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ static ssize_t adi_write(struct file *file, const char __user *buf,
|
||||
}
|
||||
|
||||
bytes_written += ver_buf_sz;
|
||||
ver_buf_sz = min(count - bytes_written, (size_t)MAX_BUF_SZ);
|
||||
ver_buf_sz = min_t(size_t, count - bytes_written, MAX_BUF_SZ);
|
||||
} while (bytes_written < count);
|
||||
|
||||
(*offp) += bytes_written;
|
||||
|
||||
@@ -142,18 +142,10 @@ static struct apm_queue kapmd_queue;
|
||||
static DEFINE_MUTEX(state_lock);
|
||||
|
||||
|
||||
/*
|
||||
* Compatibility cruft until the IPAQ people move over to the new
|
||||
* interface.
|
||||
*/
|
||||
static void __apm_get_power_status(struct apm_power_info *info)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* This allows machines to provide their own "apm get power status" function.
|
||||
*/
|
||||
void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
|
||||
void (*apm_get_power_status)(struct apm_power_info *);
|
||||
EXPORT_SYMBOL(apm_get_power_status);
|
||||
|
||||
|
||||
|
||||
@@ -835,7 +835,10 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
Dummy = readb(apbs[IndexCard].RamIO + VERS);
|
||||
|
||||
if (cmd != 6)
|
||||
Dummy = readb(apbs[IndexCard].RamIO + VERS);
|
||||
|
||||
kfree(adgl);
|
||||
mutex_unlock(&ac_mutex);
|
||||
return ret;
|
||||
|
||||
@@ -69,7 +69,8 @@ MODULE_VERSION(VERSION_STR);
|
||||
static int __init hangcheck_parse_tick(char *str)
|
||||
{
|
||||
int par;
|
||||
if (get_option(&str,&par))
|
||||
|
||||
if (get_option(&str, &par))
|
||||
hangcheck_tick = par;
|
||||
return 1;
|
||||
}
|
||||
@@ -77,7 +78,8 @@ static int __init hangcheck_parse_tick(char *str)
|
||||
static int __init hangcheck_parse_margin(char *str)
|
||||
{
|
||||
int par;
|
||||
if (get_option(&str,&par))
|
||||
|
||||
if (get_option(&str, &par))
|
||||
hangcheck_margin = par;
|
||||
return 1;
|
||||
}
|
||||
@@ -85,7 +87,8 @@ static int __init hangcheck_parse_margin(char *str)
|
||||
static int __init hangcheck_parse_reboot(char *str)
|
||||
{
|
||||
int par;
|
||||
if (get_option(&str,&par))
|
||||
|
||||
if (get_option(&str, &par))
|
||||
hangcheck_reboot = par;
|
||||
return 1;
|
||||
}
|
||||
@@ -93,7 +96,8 @@ static int __init hangcheck_parse_reboot(char *str)
|
||||
static int __init hangcheck_parse_dump_tasks(char *str)
|
||||
{
|
||||
int par;
|
||||
if (get_option(&str,&par))
|
||||
|
||||
if (get_option(&str, &par))
|
||||
hangcheck_dump_tasks = par;
|
||||
return 1;
|
||||
}
|
||||
@@ -126,23 +130,23 @@ static void hangcheck_fire(struct timer_list *unused)
|
||||
|
||||
if (tsc_diff > hangcheck_tsc_margin) {
|
||||
if (hangcheck_dump_tasks) {
|
||||
printk(KERN_CRIT "Hangcheck: Task state:\n");
|
||||
pr_crit("Hangcheck: Task state:\n");
|
||||
#ifdef CONFIG_MAGIC_SYSRQ
|
||||
handle_sysrq('t');
|
||||
#endif /* CONFIG_MAGIC_SYSRQ */
|
||||
}
|
||||
if (hangcheck_reboot) {
|
||||
printk(KERN_CRIT "Hangcheck: hangcheck is restarting the machine.\n");
|
||||
pr_crit("Hangcheck: hangcheck is restarting the machine.\n");
|
||||
emergency_restart();
|
||||
} else {
|
||||
printk(KERN_CRIT "Hangcheck: hangcheck value past margin!\n");
|
||||
pr_crit("Hangcheck: hangcheck value past margin!\n");
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
* Enable to investigate delays in detail
|
||||
*/
|
||||
printk("Hangcheck: called %Ld ns since last time (%Ld ns overshoot)\n",
|
||||
pr_debug("Hangcheck: called %lld ns since last time (%lld ns overshoot)\n",
|
||||
tsc_diff, tsc_diff - hangcheck_tick*TIMER_FREQ);
|
||||
#endif
|
||||
mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
|
||||
@@ -152,7 +156,7 @@ static void hangcheck_fire(struct timer_list *unused)
|
||||
|
||||
static int __init hangcheck_init(void)
|
||||
{
|
||||
printk("Hangcheck: starting hangcheck timer %s (tick is %d seconds, margin is %d seconds).\n",
|
||||
pr_debug("Hangcheck: starting hangcheck timer %s (tick is %d seconds, margin is %d seconds).\n",
|
||||
VERSION_STR, hangcheck_tick, hangcheck_margin);
|
||||
hangcheck_tsc_margin =
|
||||
(unsigned long long)hangcheck_margin + hangcheck_tick;
|
||||
@@ -168,7 +172,7 @@ static int __init hangcheck_init(void)
|
||||
static void __exit hangcheck_exit(void)
|
||||
{
|
||||
timer_delete_sync(&hangcheck_ticktock);
|
||||
printk("Hangcheck: Stopped hangcheck timer.\n");
|
||||
pr_debug("Hangcheck: Stopped hangcheck timer.\n");
|
||||
}
|
||||
|
||||
module_init(hangcheck_init);
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
* First release to the public
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "3780i: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/delay.h>
|
||||
@@ -75,18 +77,12 @@ unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
|
||||
unsigned long flags;
|
||||
unsigned short val;
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780i::dsp3780I_ReadMsaCfg entry usDspBaseIO %x ulMsaAddr %lx\n",
|
||||
usDspBaseIO, ulMsaAddr);
|
||||
|
||||
spin_lock_irqsave(&dsp_lock, flags);
|
||||
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulMsaAddr);
|
||||
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulMsaAddr >> 16));
|
||||
val = InWordDsp(DSP_MsaDataDSISHigh);
|
||||
spin_unlock_irqrestore(&dsp_lock, flags);
|
||||
|
||||
PRINTK_2(TRACE_3780I, "3780i::dsp3780I_ReadMsaCfg exit val %x\n", val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -95,10 +91,6 @@ void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
PRINTK_4(TRACE_3780I,
|
||||
"3780i::dsp3780i_WriteMsaCfg entry usDspBaseIO %x ulMsaAddr %lx usValue %x\n",
|
||||
usDspBaseIO, ulMsaAddr, usValue);
|
||||
|
||||
spin_lock_irqsave(&dsp_lock, flags);
|
||||
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulMsaAddr);
|
||||
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulMsaAddr >> 16));
|
||||
@@ -112,64 +104,18 @@ static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
|
||||
DSP_ISA_SLAVE_CONTROL rSlaveControl;
|
||||
DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
|
||||
|
||||
|
||||
PRINTK_4(TRACE_3780I,
|
||||
"3780i::dsp3780i_WriteGenCfg entry usDspBaseIO %x uIndex %x ucValue %x\n",
|
||||
usDspBaseIO, uIndex, ucValue);
|
||||
|
||||
MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780i_WriteGenCfg rSlaveControl %x\n",
|
||||
MKBYTE(rSlaveControl));
|
||||
|
||||
rSlaveControl_Save = rSlaveControl;
|
||||
rSlaveControl.ConfigMode = true;
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780i_WriteGenCfg entry rSlaveControl+ConfigMode %x\n",
|
||||
MKBYTE(rSlaveControl));
|
||||
|
||||
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
|
||||
OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
|
||||
OutByteDsp(DSP_ConfigData, ucValue);
|
||||
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));
|
||||
|
||||
PRINTK_1(TRACE_3780I, "3780i::dsp3780i_WriteGenCfg exit\n");
|
||||
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
|
||||
unsigned uIndex)
|
||||
{
|
||||
DSP_ISA_SLAVE_CONTROL rSlaveControl;
|
||||
DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
|
||||
unsigned char ucValue;
|
||||
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780i::dsp3780i_ReadGenCfg entry usDspBaseIO %x uIndex %x\n",
|
||||
usDspBaseIO, uIndex);
|
||||
|
||||
MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);
|
||||
rSlaveControl_Save = rSlaveControl;
|
||||
rSlaveControl.ConfigMode = true;
|
||||
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
|
||||
OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
|
||||
ucValue = InByteDsp(DSP_ConfigData);
|
||||
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780i_ReadGenCfg exit ucValue %x\n", ucValue);
|
||||
|
||||
|
||||
return ucValue;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
|
||||
int dsp3780I_EnableDSP(struct dsp_3780i_config_settings *pSettings,
|
||||
unsigned short *pIrqMap,
|
||||
unsigned short *pDmaMap)
|
||||
{
|
||||
@@ -191,25 +137,13 @@ int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
|
||||
DSP_CLOCK_CONTROL_2 rClockControl2;
|
||||
DSP_ISA_SLAVE_CONTROL rSlaveControl;
|
||||
DSP_HBRIDGE_CONTROL rHBridgeControl;
|
||||
unsigned short ChipID = 0;
|
||||
unsigned short tval;
|
||||
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780I_EnableDSP entry pSettings->bDSPEnabled %x\n",
|
||||
pSettings->bDSPEnabled);
|
||||
|
||||
|
||||
if (!pSettings->bDSPEnabled) {
|
||||
PRINTK_ERROR( KERN_ERR "3780i::dsp3780I_EnableDSP: Error: DSP not enabled. Aborting.\n" );
|
||||
pr_err("%s: Error: DSP not enabled. Aborting.\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780i_EnableDSP entry pSettings->bModemEnabled %x\n",
|
||||
pSettings->bModemEnabled);
|
||||
|
||||
if (pSettings->bModemEnabled) {
|
||||
rUartCfg1.Reserved = rUartCfg2.Reserved = 0;
|
||||
rUartCfg1.IrqActiveLow = pSettings->bUartIrqActiveLow;
|
||||
@@ -282,23 +216,10 @@ int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
|
||||
rSlaveControl.ConfigMode = false;
|
||||
rSlaveControl.Reserved = 0;
|
||||
|
||||
PRINTK_4(TRACE_3780I,
|
||||
"3780i::dsp3780i_EnableDSP usDspBaseIO %x index %x taddr %x\n",
|
||||
usDspBaseIO, DSP_IsaSlaveControl,
|
||||
usDspBaseIO + DSP_IsaSlaveControl);
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780i_EnableDSP rSlaveContrl %x\n",
|
||||
MKWORD(rSlaveControl));
|
||||
|
||||
spin_lock_irqsave(&dsp_lock, flags);
|
||||
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
|
||||
MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780i_EnableDSP rSlaveControl 2 %x\n", tval);
|
||||
|
||||
|
||||
for (i = 0; i < 11; i++)
|
||||
udelay(2000);
|
||||
|
||||
@@ -307,10 +228,6 @@ int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
|
||||
|
||||
MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780i_EnableDSP rSlaveControl 3 %x\n", tval);
|
||||
|
||||
|
||||
/* Program our general configuration registers */
|
||||
WriteGenCfg(DSP_HBridgeCfg1Index, MKBYTE(rHBridgeCfg1));
|
||||
WriteGenCfg(DSP_HBridgeCfg2Index, MKBYTE(rHBridgeCfg2));
|
||||
@@ -331,10 +248,6 @@ int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
|
||||
rHBridgeControl.IoAutoInc = false;
|
||||
rHBridgeControl.DiagnosticMode = false;
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780i::dsp3780i_EnableDSP DSP_HBridgeControl %x rHBridgeControl %x\n",
|
||||
DSP_HBridgeControl, MKWORD(rHBridgeControl));
|
||||
|
||||
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
|
||||
spin_unlock_irqrestore(&dsp_lock, flags);
|
||||
WriteMsaCfg(DSP_LBusTimeoutDisable, MKWORD(rLBusTimeoutDisable));
|
||||
@@ -342,24 +255,17 @@ int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
|
||||
WriteMsaCfg(DSP_ClockControl_2, MKWORD(rClockControl2));
|
||||
WriteMsaCfg(DSP_ChipReset, MKWORD(rChipReset));
|
||||
|
||||
ChipID = ReadMsaCfg(DSP_ChipID);
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780I_EnableDSP exiting bRC=true, ChipID %x\n",
|
||||
ChipID);
|
||||
ReadMsaCfg(DSP_ChipID);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings)
|
||||
int dsp3780I_DisableDSP(struct dsp_3780i_config_settings *pSettings)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
|
||||
DSP_ISA_SLAVE_CONTROL rSlaveControl;
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I, "3780i::dsp3780i_DisableDSP entry\n");
|
||||
|
||||
rSlaveControl.ClockControl = 0;
|
||||
rSlaveControl.SoftReset = true;
|
||||
rSlaveControl.ConfigMode = false;
|
||||
@@ -375,29 +281,20 @@ int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings)
|
||||
|
||||
udelay(5);
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I, "3780i::dsp3780i_DisableDSP exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
|
||||
int dsp3780I_Reset(struct dsp_3780i_config_settings *pSettings)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
|
||||
DSP_BOOT_DOMAIN rBootDomain;
|
||||
DSP_HBRIDGE_CONTROL rHBridgeControl;
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Reset entry\n");
|
||||
|
||||
spin_lock_irqsave(&dsp_lock, flags);
|
||||
/* Mask DSP to PC interrupt */
|
||||
MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
|
||||
|
||||
PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Reset rHBridgeControl %x\n",
|
||||
MKWORD(rHBridgeControl));
|
||||
|
||||
rHBridgeControl.EnableDspInt = false;
|
||||
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
|
||||
spin_unlock_irqrestore(&dsp_lock, flags);
|
||||
@@ -408,9 +305,6 @@ int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
|
||||
rBootDomain.NMI = true;
|
||||
rBootDomain.Reserved = 0;
|
||||
|
||||
PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Reset rBootDomain %x\n",
|
||||
MKWORD(rBootDomain));
|
||||
|
||||
WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
|
||||
|
||||
/* Reset all the chiplets and then reactivate them */
|
||||
@@ -419,24 +313,17 @@ int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings)
|
||||
WriteMsaCfg(DSP_ChipReset,
|
||||
(unsigned short) (~pSettings->usChipletEnable));
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Reset exit bRC=0\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings)
|
||||
int dsp3780I_Run(struct dsp_3780i_config_settings *pSettings)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
|
||||
DSP_BOOT_DOMAIN rBootDomain;
|
||||
DSP_HBRIDGE_CONTROL rHBridgeControl;
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Run entry\n");
|
||||
|
||||
|
||||
/* Transition the core to a running state */
|
||||
rBootDomain.ResetCore = true;
|
||||
rBootDomain.Halt = false;
|
||||
@@ -459,15 +346,9 @@ int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings)
|
||||
MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
|
||||
rHBridgeControl.EnableDspInt = true;
|
||||
|
||||
PRINTK_2(TRACE_3780I, "3780i::dsp3780i_Run rHBridgeControl %x\n",
|
||||
MKWORD(rHBridgeControl));
|
||||
|
||||
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
|
||||
spin_unlock_irqrestore(&dsp_lock, flags);
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I, "3780i::dsp3780i_Run exit bRC=true\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -479,12 +360,6 @@ int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
unsigned short __user *pusBuffer = pvBuffer;
|
||||
unsigned short val;
|
||||
|
||||
|
||||
PRINTK_5(TRACE_3780I,
|
||||
"3780i::dsp3780I_ReadDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
|
||||
usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
|
||||
|
||||
|
||||
/* Set the initial MSA address. No adjustments need to be made to data store addresses */
|
||||
spin_lock_irqsave(&dsp_lock, flags);
|
||||
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
|
||||
@@ -499,17 +374,9 @@ int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
if(put_user(val, pusBuffer++))
|
||||
return -EFAULT;
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780I::dsp3780I_ReadDStore uCount %x val %x\n",
|
||||
uCount, val);
|
||||
|
||||
PaceMsaAccess(usDspBaseIO);
|
||||
}
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I,
|
||||
"3780I::dsp3780I_ReadDStore exit bRC=true\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -521,12 +388,6 @@ int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
|
||||
unsigned short __user *pusBuffer = pvBuffer;
|
||||
unsigned short val;
|
||||
|
||||
|
||||
PRINTK_5(TRACE_3780I,
|
||||
"3780i::dsp3780I_ReadAndDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
|
||||
usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
|
||||
|
||||
|
||||
/* Set the initial MSA address. No adjustments need to be made to data store addresses */
|
||||
spin_lock_irqsave(&dsp_lock, flags);
|
||||
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
|
||||
@@ -541,17 +402,9 @@ int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
|
||||
if(put_user(val, pusBuffer++))
|
||||
return -EFAULT;
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780I::dsp3780I_ReadAndCleanDStore uCount %x val %x\n",
|
||||
uCount, val);
|
||||
|
||||
PaceMsaAccess(usDspBaseIO);
|
||||
}
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I,
|
||||
"3780I::dsp3780I_ReadAndClearDStore exit bRC=true\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -562,12 +415,6 @@ int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
unsigned long flags;
|
||||
unsigned short __user *pusBuffer = pvBuffer;
|
||||
|
||||
|
||||
PRINTK_5(TRACE_3780I,
|
||||
"3780i::dsp3780D_WriteDStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
|
||||
usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
|
||||
|
||||
|
||||
/* Set the initial MSA address. No adjustments need to be made to data store addresses */
|
||||
spin_lock_irqsave(&dsp_lock, flags);
|
||||
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
|
||||
@@ -583,17 +430,9 @@ int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
OutWordDsp(DSP_MsaDataDSISHigh, val);
|
||||
spin_unlock_irqrestore(&dsp_lock, flags);
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780I::dsp3780I_WriteDStore uCount %x val %x\n",
|
||||
uCount, val);
|
||||
|
||||
PaceMsaAccess(usDspBaseIO);
|
||||
}
|
||||
|
||||
|
||||
PRINTK_1(TRACE_3780I,
|
||||
"3780I::dsp3780D_WriteDStore exit bRC=true\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -604,10 +443,6 @@ int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
unsigned long flags;
|
||||
unsigned short __user *pusBuffer = pvBuffer;
|
||||
|
||||
PRINTK_5(TRACE_3780I,
|
||||
"3780i::dsp3780I_ReadIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
|
||||
usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
|
||||
|
||||
/*
|
||||
* Set the initial MSA address. To convert from an instruction store
|
||||
* address to an MSA address
|
||||
@@ -631,17 +466,10 @@ int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
if(put_user(val_hi, pusBuffer++))
|
||||
return -EFAULT;
|
||||
|
||||
PRINTK_4(TRACE_3780I,
|
||||
"3780I::dsp3780I_ReadIStore uCount %x val_lo %x val_hi %x\n",
|
||||
uCount, val_lo, val_hi);
|
||||
|
||||
PaceMsaAccess(usDspBaseIO);
|
||||
|
||||
}
|
||||
|
||||
PRINTK_1(TRACE_3780I,
|
||||
"3780I::dsp3780I_ReadIStore exit bRC=true\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -652,11 +480,6 @@ int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
unsigned long flags;
|
||||
unsigned short __user *pusBuffer = pvBuffer;
|
||||
|
||||
PRINTK_5(TRACE_3780I,
|
||||
"3780i::dsp3780I_WriteIStore entry usDspBaseIO %x, pusBuffer %p, uCount %x, ulDSPAddr %lx\n",
|
||||
usDspBaseIO, pusBuffer, uCount, ulDSPAddr);
|
||||
|
||||
|
||||
/*
|
||||
* Set the initial MSA address. To convert from an instruction store
|
||||
* address to an MSA address
|
||||
@@ -680,17 +503,9 @@ int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
OutWordDsp(DSP_MsaDataDSISHigh, val_hi);
|
||||
spin_unlock_irqrestore(&dsp_lock, flags);
|
||||
|
||||
PRINTK_4(TRACE_3780I,
|
||||
"3780I::dsp3780I_WriteIStore uCount %x val_lo %x val_hi %x\n",
|
||||
uCount, val_lo, val_hi);
|
||||
|
||||
PaceMsaAccess(usDspBaseIO);
|
||||
|
||||
}
|
||||
|
||||
PRINTK_1(TRACE_3780I,
|
||||
"3780I::dsp3780I_WriteIStore exit bRC=true\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -700,12 +515,6 @@ int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
|
||||
{
|
||||
unsigned long flags;
|
||||
DSP_HBRIDGE_CONTROL rHBridgeControl;
|
||||
unsigned short temp;
|
||||
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780i::dsp3780I_GetIPCSource entry usDspBaseIO %x pusIPCSource %p\n",
|
||||
usDspBaseIO, pusIPCSource);
|
||||
|
||||
/*
|
||||
* Disable DSP to PC interrupts, read the interrupt register,
|
||||
@@ -717,22 +526,11 @@ int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
|
||||
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
|
||||
|
||||
*pusIPCSource = InWordDsp(DSP_Interrupt);
|
||||
temp = (unsigned short) ~(*pusIPCSource);
|
||||
|
||||
PRINTK_3(TRACE_3780I,
|
||||
"3780i::dsp3780I_GetIPCSource, usIPCSource %x ~ %x\n",
|
||||
*pusIPCSource, temp);
|
||||
|
||||
OutWordDsp(DSP_Interrupt, (unsigned short) ~(*pusIPCSource));
|
||||
|
||||
rHBridgeControl.EnableDspInt = true;
|
||||
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
|
||||
spin_unlock_irqrestore(&dsp_lock, flags);
|
||||
|
||||
|
||||
PRINTK_2(TRACE_3780I,
|
||||
"3780i::dsp3780I_GetIPCSource exit usIPCSource %x\n",
|
||||
*pusIPCSource);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ typedef struct {
|
||||
* the only values maintained by the 3780i support layer are the saved UART
|
||||
* registers.
|
||||
*/
|
||||
typedef struct _DSP_3780I_CONFIG_SETTINGS {
|
||||
struct dsp_3780i_config_settings {
|
||||
|
||||
/* Location of base configuration register */
|
||||
unsigned short usBaseConfigIO;
|
||||
@@ -313,16 +313,16 @@ typedef struct _DSP_3780I_CONFIG_SETTINGS {
|
||||
unsigned char ucSCR; /* Scratch register */
|
||||
unsigned char ucDLL; /* Divisor latch, low byte */
|
||||
unsigned char ucDLM; /* Divisor latch, high byte */
|
||||
} DSP_3780I_CONFIG_SETTINGS;
|
||||
};
|
||||
|
||||
|
||||
/* 3780i support functions */
|
||||
int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
|
||||
int dsp3780I_EnableDSP(struct dsp_3780i_config_settings *pSettings,
|
||||
unsigned short *pIrqMap,
|
||||
unsigned short *pDmaMap);
|
||||
int dsp3780I_DisableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings);
|
||||
int dsp3780I_Reset(DSP_3780I_CONFIG_SETTINGS * pSettings);
|
||||
int dsp3780I_Run(DSP_3780I_CONFIG_SETTINGS * pSettings);
|
||||
int dsp3780I_DisableDSP(struct dsp_3780i_config_settings *pSettings);
|
||||
int dsp3780I_Reset(struct dsp_3780i_config_settings *pSettings);
|
||||
int dsp3780I_Run(struct dsp_3780i_config_settings *pSettings);
|
||||
int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
|
||||
unsigned uCount, unsigned long ulDSPAddr);
|
||||
int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
|
||||
|
||||
@@ -8,9 +8,3 @@
|
||||
obj-$(CONFIG_MWAVE) += mwave.o
|
||||
|
||||
mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o
|
||||
|
||||
# To have the mwave driver disable other uarts if necessary
|
||||
# ccflags-y := -DMWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
|
||||
# To compile in lots (~20 KiB) of run-time enablable printk()s for debugging:
|
||||
ccflags-y += -DMW_TRACE
|
||||
|
||||
@@ -4,16 +4,6 @@ Module options
|
||||
The mwave module takes the following options. Note that these options
|
||||
are not saved by the BIOS and so do not persist after unload and reload.
|
||||
|
||||
mwave_debug=value, where value is bitwise OR of trace flags:
|
||||
0x0001 mwavedd api tracing
|
||||
0x0002 smapi api tracing
|
||||
0x0004 3780i tracing
|
||||
0x0008 tp3780i tracing
|
||||
|
||||
Tracing only occurs if the driver has been compiled with the
|
||||
MW_TRACE macro #defined (i.e. let ccflags-y := -DMW_TRACE
|
||||
in the Makefile).
|
||||
|
||||
mwave_3780i_irq=5/7/10/11/15
|
||||
If the dsp irq has not been setup and stored in bios by the
|
||||
thinkpad configuration utility then this parameter allows the
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
* First release to the public
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "mwavedd: " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
@@ -75,131 +77,62 @@ MODULE_LICENSE("GPL");
|
||||
* We'll depend on users using the tpctl utility to do that for now
|
||||
*/
|
||||
static DEFINE_MUTEX(mwave_mutex);
|
||||
int mwave_debug = 0;
|
||||
int mwave_3780i_irq = 0;
|
||||
int mwave_3780i_io = 0;
|
||||
int mwave_uart_irq = 0;
|
||||
int mwave_uart_io = 0;
|
||||
module_param(mwave_debug, int, 0);
|
||||
module_param_hw(mwave_3780i_irq, int, irq, 0);
|
||||
module_param_hw(mwave_3780i_io, int, ioport, 0);
|
||||
module_param_hw(mwave_uart_irq, int, irq, 0);
|
||||
module_param_hw(mwave_uart_io, int, ioport, 0);
|
||||
|
||||
static int mwave_open(struct inode *inode, struct file *file);
|
||||
static int mwave_close(struct inode *inode, struct file *file);
|
||||
static long mwave_ioctl(struct file *filp, unsigned int iocmd,
|
||||
unsigned long ioarg);
|
||||
|
||||
MWAVE_DEVICE_DATA mwave_s_mdd;
|
||||
|
||||
static int mwave_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
unsigned int retval = 0;
|
||||
|
||||
PRINTK_3(TRACE_MWAVE,
|
||||
"mwavedd::mwave_open, entry inode %p file %p\n",
|
||||
inode, file);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_open, exit return retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int mwave_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
unsigned int retval = 0;
|
||||
|
||||
PRINTK_3(TRACE_MWAVE,
|
||||
"mwavedd::mwave_close, entry inode %p file %p\n",
|
||||
inode, file);
|
||||
|
||||
PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_close, exit retval %x\n",
|
||||
retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
struct mwave_device_data mwave_s_mdd;
|
||||
|
||||
static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
unsigned long ioarg)
|
||||
{
|
||||
unsigned int retval = 0;
|
||||
pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
|
||||
struct mwave_device_data *pDrvData = &mwave_s_mdd;
|
||||
void __user *arg = (void __user *)ioarg;
|
||||
|
||||
PRINTK_4(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n",
|
||||
file, iocmd, (int) ioarg);
|
||||
|
||||
switch (iocmd) {
|
||||
|
||||
case IOCTL_MW_RESET:
|
||||
PRINTK_1(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
|
||||
" calling tp3780I_ResetDSP\n");
|
||||
mutex_lock(&mwave_mutex);
|
||||
retval = tp3780I_ResetDSP(&pDrvData->rBDData);
|
||||
mutex_unlock(&mwave_mutex);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
|
||||
" retval %x from tp3780I_ResetDSP\n",
|
||||
retval);
|
||||
break;
|
||||
|
||||
case IOCTL_MW_RUN:
|
||||
PRINTK_1(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
|
||||
" calling tp3780I_StartDSP\n");
|
||||
mutex_lock(&mwave_mutex);
|
||||
retval = tp3780I_StartDSP(&pDrvData->rBDData);
|
||||
mutex_unlock(&mwave_mutex);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
|
||||
" retval %x from tp3780I_StartDSP\n",
|
||||
retval);
|
||||
break;
|
||||
|
||||
case IOCTL_MW_DSP_ABILITIES: {
|
||||
MW_ABILITIES rAbilities;
|
||||
struct mw_abilities rAbilities;
|
||||
|
||||
PRINTK_1(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl,"
|
||||
" IOCTL_MW_DSP_ABILITIES calling"
|
||||
" tp3780I_QueryAbilities\n");
|
||||
mutex_lock(&mwave_mutex);
|
||||
retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
|
||||
&rAbilities);
|
||||
mutex_unlock(&mwave_mutex);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
|
||||
" retval %x from tp3780I_QueryAbilities\n",
|
||||
retval);
|
||||
if (retval == 0) {
|
||||
if( copy_to_user(arg, &rAbilities,
|
||||
sizeof(MW_ABILITIES)) )
|
||||
if (copy_to_user(arg, &rAbilities, sizeof(rAbilities)))
|
||||
return -EFAULT;
|
||||
}
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
|
||||
" exit retval %x\n",
|
||||
retval);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_MW_READ_DATA:
|
||||
case IOCTL_MW_READCLEAR_DATA: {
|
||||
MW_READWRITE rReadData;
|
||||
struct mw_readwrite rReadData;
|
||||
unsigned short __user *pusBuffer = NULL;
|
||||
|
||||
if( copy_from_user(&rReadData, arg,
|
||||
sizeof(MW_READWRITE)) )
|
||||
sizeof(struct mw_readwrite)) )
|
||||
return -EFAULT;
|
||||
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
|
||||
|
||||
PRINTK_4(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
|
||||
" size %lx, ioarg %lx pusBuffer %p\n",
|
||||
rReadData.ulDataLength, ioarg, pusBuffer);
|
||||
mutex_lock(&mwave_mutex);
|
||||
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
|
||||
iocmd,
|
||||
@@ -211,19 +144,13 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
break;
|
||||
|
||||
case IOCTL_MW_READ_INST: {
|
||||
MW_READWRITE rReadData;
|
||||
struct mw_readwrite rReadData;
|
||||
unsigned short __user *pusBuffer = NULL;
|
||||
|
||||
if( copy_from_user(&rReadData, arg,
|
||||
sizeof(MW_READWRITE)) )
|
||||
if (copy_from_user(&rReadData, arg, sizeof(rReadData)))
|
||||
return -EFAULT;
|
||||
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
|
||||
|
||||
PRINTK_4(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_READ_INST,"
|
||||
" size %lx, ioarg %lx pusBuffer %p\n",
|
||||
rReadData.ulDataLength / 2, ioarg,
|
||||
pusBuffer);
|
||||
mutex_lock(&mwave_mutex);
|
||||
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
|
||||
iocmd, pusBuffer,
|
||||
@@ -234,19 +161,13 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
break;
|
||||
|
||||
case IOCTL_MW_WRITE_DATA: {
|
||||
MW_READWRITE rWriteData;
|
||||
struct mw_readwrite rWriteData;
|
||||
unsigned short __user *pusBuffer = NULL;
|
||||
|
||||
if( copy_from_user(&rWriteData, arg,
|
||||
sizeof(MW_READWRITE)) )
|
||||
if (copy_from_user(&rWriteData, arg, sizeof(rWriteData)))
|
||||
return -EFAULT;
|
||||
pusBuffer = (unsigned short __user *) (rWriteData.pBuf);
|
||||
|
||||
PRINTK_4(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA,"
|
||||
" size %lx, ioarg %lx pusBuffer %p\n",
|
||||
rWriteData.ulDataLength, ioarg,
|
||||
pusBuffer);
|
||||
mutex_lock(&mwave_mutex);
|
||||
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
|
||||
iocmd, pusBuffer,
|
||||
@@ -257,19 +178,13 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
break;
|
||||
|
||||
case IOCTL_MW_WRITE_INST: {
|
||||
MW_READWRITE rWriteData;
|
||||
struct mw_readwrite rWriteData;
|
||||
unsigned short __user *pusBuffer = NULL;
|
||||
|
||||
if( copy_from_user(&rWriteData, arg,
|
||||
sizeof(MW_READWRITE)) )
|
||||
if (copy_from_user(&rWriteData, arg, sizeof(rWriteData)))
|
||||
return -EFAULT;
|
||||
pusBuffer = (unsigned short __user *)(rWriteData.pBuf);
|
||||
|
||||
PRINTK_4(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST,"
|
||||
" size %lx, ioarg %lx pusBuffer %p\n",
|
||||
rWriteData.ulDataLength, ioarg,
|
||||
pusBuffer);
|
||||
mutex_lock(&mwave_mutex);
|
||||
retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
|
||||
iocmd, pusBuffer,
|
||||
@@ -283,30 +198,17 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
unsigned int ipcnum = (unsigned int) ioarg;
|
||||
|
||||
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd::mwave_ioctl:"
|
||||
" IOCTL_MW_REGISTER_IPC:"
|
||||
" Error: Invalid ipcnum %x\n",
|
||||
ipcnum);
|
||||
pr_err("%s: IOCTL_MW_REGISTER_IPC: Error: Invalid ipcnum %x\n",
|
||||
__func__, ipcnum);
|
||||
return -EINVAL;
|
||||
}
|
||||
ipcnum = array_index_nospec(ipcnum,
|
||||
ARRAY_SIZE(pDrvData->IPCs));
|
||||
PRINTK_3(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
|
||||
" ipcnum %x entry usIntCount %x\n",
|
||||
ipcnum,
|
||||
pDrvData->IPCs[ipcnum].usIntCount);
|
||||
|
||||
mutex_lock(&mwave_mutex);
|
||||
pDrvData->IPCs[ipcnum].bIsHere = false;
|
||||
pDrvData->IPCs[ipcnum].bIsEnabled = true;
|
||||
mutex_unlock(&mwave_mutex);
|
||||
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
|
||||
" ipcnum %x exit\n",
|
||||
ipcnum);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -314,28 +216,17 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
unsigned int ipcnum = (unsigned int) ioarg;
|
||||
|
||||
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd::mwave_ioctl:"
|
||||
" IOCTL_MW_GET_IPC: Error:"
|
||||
" Invalid ipcnum %x\n", ipcnum);
|
||||
pr_err("%s: IOCTL_MW_GET_IPC: Error: Invalid ipcnum %x\n", __func__,
|
||||
ipcnum);
|
||||
return -EINVAL;
|
||||
}
|
||||
ipcnum = array_index_nospec(ipcnum,
|
||||
ARRAY_SIZE(pDrvData->IPCs));
|
||||
PRINTK_3(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
|
||||
" ipcnum %x, usIntCount %x\n",
|
||||
ipcnum,
|
||||
pDrvData->IPCs[ipcnum].usIntCount);
|
||||
|
||||
mutex_lock(&mwave_mutex);
|
||||
if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl, thread for"
|
||||
" ipc %x going to sleep\n",
|
||||
ipcnum);
|
||||
add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
|
||||
pDrvData->IPCs[ipcnum].bIsHere = true;
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
@@ -343,31 +234,15 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
/* the interrupt handler while we were gone */
|
||||
if (pDrvData->IPCs[ipcnum].usIntCount == 1) { /* first int has occurred (race condition) */
|
||||
pDrvData->IPCs[ipcnum].usIntCount = 2; /* first int has been handled */
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl"
|
||||
" IOCTL_MW_GET_IPC ipcnum %x"
|
||||
" handling first int\n",
|
||||
ipcnum);
|
||||
} else { /* either 1st int has not yet occurred, or we have already handled the first int */
|
||||
schedule();
|
||||
if (pDrvData->IPCs[ipcnum].usIntCount == 1) {
|
||||
pDrvData->IPCs[ipcnum].usIntCount = 2;
|
||||
}
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl"
|
||||
" IOCTL_MW_GET_IPC ipcnum %x"
|
||||
" woke up and returning to"
|
||||
" application\n",
|
||||
ipcnum);
|
||||
}
|
||||
pDrvData->IPCs[ipcnum].bIsHere = false;
|
||||
remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_GET_IPC,"
|
||||
" returning thread for ipc %x"
|
||||
" processing\n",
|
||||
ipcnum);
|
||||
}
|
||||
mutex_unlock(&mwave_mutex);
|
||||
}
|
||||
@@ -376,16 +251,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
case IOCTL_MW_UNREGISTER_IPC: {
|
||||
unsigned int ipcnum = (unsigned int) ioarg;
|
||||
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC"
|
||||
" ipcnum %x\n",
|
||||
ipcnum);
|
||||
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd::mwave_ioctl:"
|
||||
" IOCTL_MW_UNREGISTER_IPC:"
|
||||
" Error: Invalid ipcnum %x\n",
|
||||
ipcnum);
|
||||
pr_err("%s: IOCTL_MW_UNREGISTER_IPC: Error: Invalid ipcnum %x\n",
|
||||
__func__, ipcnum);
|
||||
return -EINVAL;
|
||||
}
|
||||
ipcnum = array_index_nospec(ipcnum,
|
||||
@@ -405,35 +273,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
|
||||
return -ENOTTY;
|
||||
} /* switch */
|
||||
|
||||
PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t mwave_read(struct file *file, char __user *buf, size_t count,
|
||||
loff_t * ppos)
|
||||
{
|
||||
PRINTK_5(TRACE_MWAVE,
|
||||
"mwavedd::mwave_read entry file %p, buf %p, count %zx ppos %p\n",
|
||||
file, buf, count, ppos);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t mwave_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t * ppos)
|
||||
{
|
||||
PRINTK_5(TRACE_MWAVE,
|
||||
"mwavedd::mwave_write entry file %p, buf %p,"
|
||||
" count %zx ppos %p\n",
|
||||
file, buf, count, ppos);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
static int register_serial_portandirq(unsigned int port, int irq)
|
||||
{
|
||||
struct uart_8250_port uart;
|
||||
@@ -446,9 +288,7 @@ static int register_serial_portandirq(unsigned int port, int irq)
|
||||
/* OK */
|
||||
break;
|
||||
default:
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd::register_serial_portandirq:"
|
||||
" Error: Illegal port %x\n", port );
|
||||
pr_err("%s: Error: Illegal port %x\n", __func__, port);
|
||||
return -1;
|
||||
} /* switch */
|
||||
/* port is okay */
|
||||
@@ -461,9 +301,7 @@ static int register_serial_portandirq(unsigned int port, int irq)
|
||||
/* OK */
|
||||
break;
|
||||
default:
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd::register_serial_portandirq:"
|
||||
" Error: Illegal irq %x\n", irq );
|
||||
pr_err("%s: Error: Illegal irq %x\n", __func__, irq);
|
||||
return -1;
|
||||
} /* switch */
|
||||
/* irq is okay */
|
||||
@@ -478,56 +316,14 @@ static int register_serial_portandirq(unsigned int port, int irq)
|
||||
return serial8250_register_8250_port(&uart);
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations mwave_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = mwave_read,
|
||||
.write = mwave_write,
|
||||
.unlocked_ioctl = mwave_ioctl,
|
||||
.open = mwave_open,
|
||||
.release = mwave_close,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
|
||||
static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops };
|
||||
|
||||
#if 0 /* totally b0rked */
|
||||
/*
|
||||
* sysfs support <paulsch@us.ibm.com>
|
||||
*/
|
||||
|
||||
struct device mwave_device;
|
||||
|
||||
/* Prevent code redundancy, create a macro for mwave_show_* functions. */
|
||||
#define mwave_show_function(attr_name, format_string, field) \
|
||||
static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf) \
|
||||
{ \
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = \
|
||||
&mwave_s_mdd.rBDData.rDspSettings; \
|
||||
return sprintf(buf, format_string, pSettings->field); \
|
||||
}
|
||||
|
||||
/* All of our attributes are read attributes. */
|
||||
#define mwave_dev_rd_attr(attr_name, format_string, field) \
|
||||
mwave_show_function(attr_name, format_string, field) \
|
||||
static DEVICE_ATTR(attr_name, S_IRUGO, mwave_show_##attr_name, NULL)
|
||||
|
||||
mwave_dev_rd_attr (3780i_dma, "%i\n", usDspDma);
|
||||
mwave_dev_rd_attr (3780i_irq, "%i\n", usDspIrq);
|
||||
mwave_dev_rd_attr (3780i_io, "%#.4x\n", usDspBaseIO);
|
||||
mwave_dev_rd_attr (uart_irq, "%i\n", usUartIrq);
|
||||
mwave_dev_rd_attr (uart_io, "%#.4x\n", usUartBaseIO);
|
||||
|
||||
static struct device_attribute * const mwave_dev_attrs[] = {
|
||||
&dev_attr_3780i_dma,
|
||||
&dev_attr_3780i_irq,
|
||||
&dev_attr_3780i_io,
|
||||
&dev_attr_uart_irq,
|
||||
&dev_attr_uart_io,
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mwave_init is called on module load
|
||||
*
|
||||
@@ -536,20 +332,7 @@ static struct device_attribute * const mwave_dev_attrs[] = {
|
||||
*/
|
||||
static void mwave_exit(void)
|
||||
{
|
||||
pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
|
||||
|
||||
PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit entry\n");
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < pDrvData->nr_registered_attrs; i++)
|
||||
device_remove_file(&mwave_device, mwave_dev_attrs[i]);
|
||||
pDrvData->nr_registered_attrs = 0;
|
||||
|
||||
if (pDrvData->device_registered) {
|
||||
device_unregister(&mwave_device);
|
||||
pDrvData->device_registered = false;
|
||||
}
|
||||
#endif
|
||||
struct mwave_device_data *pDrvData = &mwave_s_mdd;
|
||||
|
||||
if ( pDrvData->sLine >= 0 ) {
|
||||
serial8250_unregister_port(pDrvData->sLine);
|
||||
@@ -566,8 +349,6 @@ static void mwave_exit(void)
|
||||
if (pDrvData->bBDInitialized) {
|
||||
tp3780I_Cleanup(&pDrvData->rBDData);
|
||||
}
|
||||
|
||||
PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit exit\n");
|
||||
}
|
||||
|
||||
module_exit(mwave_exit);
|
||||
@@ -576,11 +357,9 @@ static int __init mwave_init(void)
|
||||
{
|
||||
int i;
|
||||
int retval = 0;
|
||||
pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
|
||||
struct mwave_device_data *pDrvData = &mwave_s_mdd;
|
||||
|
||||
PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n");
|
||||
|
||||
memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA));
|
||||
memset(&mwave_s_mdd, 0, sizeof(mwave_s_mdd));
|
||||
|
||||
pDrvData->bBDInitialized = false;
|
||||
pDrvData->bResourcesClaimed = false;
|
||||
@@ -597,60 +376,34 @@ static int __init mwave_init(void)
|
||||
}
|
||||
|
||||
retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_init, return from tp3780I_InitializeBoardData"
|
||||
" retval %x\n",
|
||||
retval);
|
||||
if (retval) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd::mwave_init: Error:"
|
||||
" Failed to initialize board data\n");
|
||||
pr_err("%s: Error: Failed to initialize board data\n", __func__);
|
||||
goto cleanup_error;
|
||||
}
|
||||
pDrvData->bBDInitialized = true;
|
||||
|
||||
retval = tp3780I_CalcResources(&pDrvData->rBDData);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_init, return from tp3780I_CalcResources"
|
||||
" retval %x\n",
|
||||
retval);
|
||||
if (retval) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd:mwave_init: Error:"
|
||||
" Failed to calculate resources\n");
|
||||
pr_err("%s: Error: Failed to calculate resources\n", __func__);
|
||||
goto cleanup_error;
|
||||
}
|
||||
|
||||
retval = tp3780I_ClaimResources(&pDrvData->rBDData);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_init, return from tp3780I_ClaimResources"
|
||||
" retval %x\n",
|
||||
retval);
|
||||
if (retval) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd:mwave_init: Error:"
|
||||
" Failed to claim resources\n");
|
||||
pr_err("%s: Error: Failed to claim resources\n", __func__);
|
||||
goto cleanup_error;
|
||||
}
|
||||
pDrvData->bResourcesClaimed = true;
|
||||
|
||||
retval = tp3780I_EnableDSP(&pDrvData->rBDData);
|
||||
PRINTK_2(TRACE_MWAVE,
|
||||
"mwavedd::mwave_init, return from tp3780I_EnableDSP"
|
||||
" retval %x\n",
|
||||
retval);
|
||||
if (retval) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd:mwave_init: Error:"
|
||||
" Failed to enable DSP\n");
|
||||
pr_err("%s: Error: Failed to enable DSP\n", __func__);
|
||||
goto cleanup_error;
|
||||
}
|
||||
pDrvData->bDSPEnabled = true;
|
||||
|
||||
if (misc_register(&mwave_misc_dev) < 0) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd:mwave_init: Error:"
|
||||
" Failed to register misc device\n");
|
||||
pr_err("%s: Error: Failed to register misc device\n", __func__);
|
||||
goto cleanup_error;
|
||||
}
|
||||
pDrvData->bMwaveDevRegistered = true;
|
||||
@@ -660,40 +413,16 @@ static int __init mwave_init(void)
|
||||
pDrvData->rBDData.rDspSettings.usUartIrq
|
||||
);
|
||||
if (pDrvData->sLine < 0) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd:mwave_init: Error:"
|
||||
" Failed to register serial driver\n");
|
||||
pr_err("%s: Error: Failed to register serial driver\n", __func__);
|
||||
goto cleanup_error;
|
||||
}
|
||||
/* uart is registered */
|
||||
|
||||
#if 0
|
||||
/* sysfs */
|
||||
memset(&mwave_device, 0, sizeof (struct device));
|
||||
dev_set_name(&mwave_device, "mwave");
|
||||
|
||||
if (device_register(&mwave_device))
|
||||
goto cleanup_error;
|
||||
pDrvData->device_registered = true;
|
||||
for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) {
|
||||
if(device_create_file(&mwave_device, mwave_dev_attrs[i])) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd:mwave_init: Error:"
|
||||
" Failed to create sysfs file %s\n",
|
||||
mwave_dev_attrs[i]->attr.name);
|
||||
goto cleanup_error;
|
||||
}
|
||||
pDrvData->nr_registered_attrs++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* SUCCESS! */
|
||||
return 0;
|
||||
|
||||
cleanup_error:
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"mwavedd::mwave_init: Error:"
|
||||
" Failed to initialize\n");
|
||||
pr_err("%s: Error: Failed to initialize\n", __func__);
|
||||
mwave_exit(); /* clean up */
|
||||
|
||||
return -EIO;
|
||||
|
||||
@@ -56,97 +56,35 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
extern int mwave_debug;
|
||||
extern int mwave_3780i_irq;
|
||||
extern int mwave_3780i_io;
|
||||
extern int mwave_uart_irq;
|
||||
extern int mwave_uart_io;
|
||||
|
||||
#define PRINTK_ERROR printk
|
||||
#define KERN_ERR_MWAVE KERN_ERR "mwave: "
|
||||
|
||||
#define TRACE_MWAVE 0x0001
|
||||
#define TRACE_SMAPI 0x0002
|
||||
#define TRACE_3780I 0x0004
|
||||
#define TRACE_TP3780I 0x0008
|
||||
|
||||
#ifdef MW_TRACE
|
||||
#define PRINTK_1(f,s) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s); \
|
||||
}
|
||||
|
||||
#define PRINTK_2(f,s,v1) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s,v1); \
|
||||
}
|
||||
|
||||
#define PRINTK_3(f,s,v1,v2) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s,v1,v2); \
|
||||
}
|
||||
|
||||
#define PRINTK_4(f,s,v1,v2,v3) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s,v1,v2,v3); \
|
||||
}
|
||||
|
||||
#define PRINTK_5(f,s,v1,v2,v3,v4) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s,v1,v2,v3,v4); \
|
||||
}
|
||||
|
||||
#define PRINTK_6(f,s,v1,v2,v3,v4,v5) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s,v1,v2,v3,v4,v5); \
|
||||
}
|
||||
|
||||
#define PRINTK_7(f,s,v1,v2,v3,v4,v5,v6) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s,v1,v2,v3,v4,v5,v6); \
|
||||
}
|
||||
|
||||
#define PRINTK_8(f,s,v1,v2,v3,v4,v5,v6,v7) \
|
||||
if (f & (mwave_debug)) { \
|
||||
printk(s,v1,v2,v3,v4,v5,v6,v7); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define PRINTK_1(f,s)
|
||||
#define PRINTK_2(f,s,v1)
|
||||
#define PRINTK_3(f,s,v1,v2)
|
||||
#define PRINTK_4(f,s,v1,v2,v3)
|
||||
#define PRINTK_5(f,s,v1,v2,v3,v4)
|
||||
#define PRINTK_6(f,s,v1,v2,v3,v4,v5)
|
||||
#define PRINTK_7(f,s,v1,v2,v3,v4,v5,v6)
|
||||
#define PRINTK_8(f,s,v1,v2,v3,v4,v5,v6,v7)
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _MWAVE_IPC {
|
||||
struct mwave_ipc {
|
||||
unsigned short usIntCount; /* 0=none, 1=first, 2=greater than 1st */
|
||||
bool bIsEnabled;
|
||||
bool bIsHere;
|
||||
/* entry spin lock */
|
||||
wait_queue_head_t ipc_wait_queue;
|
||||
} MWAVE_IPC;
|
||||
};
|
||||
|
||||
typedef struct _MWAVE_DEVICE_DATA {
|
||||
THINKPAD_BD_DATA rBDData; /* board driver's data area */
|
||||
struct mwave_device_data {
|
||||
struct thinkpad_bd_data rBDData; /* board driver's data area */
|
||||
unsigned long ulIPCSource_ISR; /* IPC source bits for recently processed intr, set during ISR processing */
|
||||
unsigned long ulIPCSource_DPC; /* IPC source bits for recently processed intr, set during DPC processing */
|
||||
bool bBDInitialized;
|
||||
bool bResourcesClaimed;
|
||||
bool bDSPEnabled;
|
||||
bool bDSPReset;
|
||||
MWAVE_IPC IPCs[16];
|
||||
struct mwave_ipc IPCs[16];
|
||||
bool bMwaveDevRegistered;
|
||||
short sLine;
|
||||
int nr_registered_attrs;
|
||||
int device_registered;
|
||||
|
||||
} MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA;
|
||||
};
|
||||
|
||||
extern MWAVE_DEVICE_DATA mwave_s_mdd;
|
||||
extern struct mwave_device_data mwave_s_mdd;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
#include <linux/miscdevice.h>
|
||||
|
||||
|
||||
typedef struct _MW_ABILITIES {
|
||||
struct mw_abilities {
|
||||
unsigned long instr_per_sec;
|
||||
unsigned long data_size;
|
||||
unsigned long inst_size;
|
||||
@@ -63,27 +63,27 @@ typedef struct _MW_ABILITIES {
|
||||
unsigned long component_list[7];
|
||||
char mwave_os_name[16];
|
||||
char bios_task_name[16];
|
||||
} MW_ABILITIES, *pMW_ABILITIES;
|
||||
};
|
||||
|
||||
|
||||
typedef struct _MW_READWRITE {
|
||||
struct mw_readwrite {
|
||||
unsigned short usDspAddress; /* The dsp address */
|
||||
unsigned long ulDataLength; /* The size in bytes of the data or user buffer */
|
||||
void __user *pBuf; /* Input:variable sized buffer */
|
||||
} MW_READWRITE, *pMW_READWRITE;
|
||||
};
|
||||
|
||||
#define IOCTL_MW_RESET _IO(MWAVE_MINOR,1)
|
||||
#define IOCTL_MW_RUN _IO(MWAVE_MINOR,2)
|
||||
#define IOCTL_MW_DSP_ABILITIES _IOR(MWAVE_MINOR,3,MW_ABILITIES)
|
||||
#define IOCTL_MW_READ_DATA _IOR(MWAVE_MINOR,4,MW_READWRITE)
|
||||
#define IOCTL_MW_READCLEAR_DATA _IOR(MWAVE_MINOR,5,MW_READWRITE)
|
||||
#define IOCTL_MW_READ_INST _IOR(MWAVE_MINOR,6,MW_READWRITE)
|
||||
#define IOCTL_MW_WRITE_DATA _IOW(MWAVE_MINOR,7,MW_READWRITE)
|
||||
#define IOCTL_MW_WRITE_INST _IOW(MWAVE_MINOR,8,MW_READWRITE)
|
||||
#define IOCTL_MW_DSP_ABILITIES _IOR(MWAVE_MINOR,3,struct mw_abilities)
|
||||
#define IOCTL_MW_READ_DATA _IOR(MWAVE_MINOR,4,struct mw_readwrite)
|
||||
#define IOCTL_MW_READCLEAR_DATA _IOR(MWAVE_MINOR,5,struct mw_readwrite)
|
||||
#define IOCTL_MW_READ_INST _IOR(MWAVE_MINOR,6,struct mw_readwrite)
|
||||
#define IOCTL_MW_WRITE_DATA _IOW(MWAVE_MINOR,7,struct mw_readwrite)
|
||||
#define IOCTL_MW_WRITE_INST _IOW(MWAVE_MINOR,8,struct mw_readwrite)
|
||||
#define IOCTL_MW_REGISTER_IPC _IOW(MWAVE_MINOR,9,int)
|
||||
#define IOCTL_MW_UNREGISTER_IPC _IOW(MWAVE_MINOR,10,int)
|
||||
#define IOCTL_MW_GET_IPC _IOW(MWAVE_MINOR,11,int)
|
||||
#define IOCTL_MW_TRACE _IOR(MWAVE_MINOR,12,MW_READWRITE)
|
||||
#define IOCTL_MW_TRACE _IOR(MWAVE_MINOR,12,struct mw_readwrite)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
* First release to the public
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "smapi: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mc146818rtc.h> /* CMOS defines */
|
||||
#include "smapi.h"
|
||||
@@ -69,10 +71,6 @@ static int smapi_request(unsigned short inBX, unsigned short inCX,
|
||||
unsigned short usSmapiOK = -EIO, *pusSmapiOK = &usSmapiOK;
|
||||
unsigned int inBXCX = (inBX << 16) | inCX;
|
||||
unsigned int inDISI = (inDI << 16) | inSI;
|
||||
int retval = 0;
|
||||
|
||||
PRINTK_5(TRACE_SMAPI, "inBX %x inCX %x inDI %x inSI %x\n",
|
||||
inBX, inCX, inDI, inSI);
|
||||
|
||||
__asm__ __volatile__("movw $0x5380,%%ax\n\t"
|
||||
"movl %7,%%ebx\n\t"
|
||||
@@ -107,10 +105,6 @@ static int smapi_request(unsigned short inBX, unsigned short inCX,
|
||||
:"%eax", "%ebx", "%ecx", "%edx", "%edi",
|
||||
"%esi");
|
||||
|
||||
PRINTK_8(TRACE_SMAPI,
|
||||
"myoutAX %x myoutBX %x myoutCX %x myoutDX %x myoutDI %x myoutSI %x usSmapiOK %x\n",
|
||||
myoutAX, myoutBX, myoutCX, myoutDX, myoutDI, myoutSI,
|
||||
usSmapiOK);
|
||||
*outAX = myoutAX;
|
||||
*outBX = myoutBX;
|
||||
*outCX = myoutCX;
|
||||
@@ -118,13 +112,11 @@ static int smapi_request(unsigned short inBX, unsigned short inCX,
|
||||
*outDI = myoutDI;
|
||||
*outSI = myoutSI;
|
||||
|
||||
retval = (usSmapiOK == 1) ? 0 : -EIO;
|
||||
PRINTK_2(TRACE_SMAPI, "smapi::smapi_request exit retval %x\n", retval);
|
||||
return retval;
|
||||
return usSmapiOK == 1 ? 0 : -EIO;
|
||||
}
|
||||
|
||||
|
||||
int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings)
|
||||
int smapi_query_DSP_cfg(struct smapi_dsp_settings *pSettings)
|
||||
{
|
||||
int bRC;
|
||||
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
|
||||
@@ -134,17 +126,13 @@ int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings)
|
||||
static const unsigned short ausUartBases[] = {
|
||||
0x03F8, 0x02F8, 0x03E8, 0x02E8 };
|
||||
|
||||
PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg entry\n");
|
||||
|
||||
bRC = smapi_request(0x1802, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Error: Could not get DSP Settings. Aborting.\n");
|
||||
pr_err("%s: Error: Could not get DSP Settings. Aborting.\n", __func__);
|
||||
return bRC;
|
||||
}
|
||||
|
||||
PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg, smapi_request OK\n");
|
||||
|
||||
pSettings->bDSPPresent = ((usBX & 0x0100) != 0);
|
||||
pSettings->bDSPEnabled = ((usCX & 0x0001) != 0);
|
||||
pSettings->usDspIRQ = usSI & 0x00FF;
|
||||
@@ -154,27 +142,20 @@ int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings)
|
||||
} else {
|
||||
pSettings->usDspBaseIO = 0;
|
||||
}
|
||||
PRINTK_6(TRACE_SMAPI,
|
||||
"smapi::smapi_query_DSP_cfg get DSP Settings bDSPPresent %x bDSPEnabled %x usDspIRQ %x usDspDMA %x usDspBaseIO %x\n",
|
||||
pSettings->bDSPPresent, pSettings->bDSPEnabled,
|
||||
pSettings->usDspIRQ, pSettings->usDspDMA,
|
||||
pSettings->usDspBaseIO);
|
||||
|
||||
/* check for illegal values */
|
||||
if ( pSettings->usDspBaseIO == 0 )
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: DSP base I/O address is 0\n");
|
||||
pr_err("%s: Worry: DSP base I/O address is 0\n", __func__);
|
||||
if ( pSettings->usDspIRQ == 0 )
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: DSP IRQ line is 0\n");
|
||||
pr_err("%s: Worry: DSP IRQ line is 0\n", __func__);
|
||||
|
||||
bRC = smapi_request(0x1804, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) {
|
||||
PRINTK_ERROR("smapi::smapi_query_DSP_cfg: Error: Could not get DSP modem settings. Aborting.\n");
|
||||
pr_err("%s: Error: Could not get DSP modem settings. Aborting.\n", __func__);
|
||||
return bRC;
|
||||
}
|
||||
|
||||
PRINTK_1(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg, smapi_request OK\n");
|
||||
|
||||
pSettings->bModemEnabled = ((usCX & 0x0001) != 0);
|
||||
pSettings->usUartIRQ = usSI & 0x000F;
|
||||
if (((usSI & 0xFF00) >> 8) < ARRAY_SIZE(ausUartBases)) {
|
||||
@@ -183,19 +164,11 @@ int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings)
|
||||
pSettings->usUartBaseIO = 0;
|
||||
}
|
||||
|
||||
PRINTK_4(TRACE_SMAPI,
|
||||
"smapi::smapi_query_DSP_cfg get DSP modem settings bModemEnabled %x usUartIRQ %x usUartBaseIO %x\n",
|
||||
pSettings->bModemEnabled,
|
||||
pSettings->usUartIRQ,
|
||||
pSettings->usUartBaseIO);
|
||||
|
||||
/* check for illegal values */
|
||||
if ( pSettings->usUartBaseIO == 0 )
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: UART base I/O address is 0\n");
|
||||
pr_err("%s: Worry: UART base I/O address is 0\n", __func__);
|
||||
if ( pSettings->usUartIRQ == 0 )
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_query_DSP_cfg: Worry: UART IRQ line is 0\n");
|
||||
|
||||
PRINTK_2(TRACE_SMAPI, "smapi::smapi_query_DSP_cfg exit bRC %x\n", bRC);
|
||||
pr_err("%s: Worry: UART IRQ line is 0\n", __func__);
|
||||
|
||||
return bRC;
|
||||
}
|
||||
@@ -218,17 +191,14 @@ int smapi_set_DSP_cfg(void)
|
||||
|
||||
unsigned short dspio_index = 0, uartio_index = 0;
|
||||
|
||||
PRINTK_5(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg entry mwave_3780i_irq %x mwave_3780i_io %x mwave_uart_irq %x mwave_uart_io %x\n",
|
||||
mwave_3780i_irq, mwave_3780i_io, mwave_uart_irq, mwave_uart_io);
|
||||
|
||||
if (mwave_3780i_io) {
|
||||
for (i = 0; i < ARRAY_SIZE(ausDspBases); i++) {
|
||||
if (mwave_3780i_io == ausDspBases[i])
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(ausDspBases)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_io address %x. Aborting.\n", mwave_3780i_io);
|
||||
pr_err("%s: Error: Invalid mwave_3780i_io address %x. Aborting.\n",
|
||||
__func__, mwave_3780i_io);
|
||||
return bRC;
|
||||
}
|
||||
dspio_index = i;
|
||||
@@ -240,7 +210,8 @@ int smapi_set_DSP_cfg(void)
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(ausDspIrqs)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_3780i_irq %x. Aborting.\n", mwave_3780i_irq);
|
||||
pr_err("%s: Error: Invalid mwave_3780i_irq %x. Aborting.\n", __func__,
|
||||
mwave_3780i_irq);
|
||||
return bRC;
|
||||
}
|
||||
}
|
||||
@@ -251,7 +222,8 @@ int smapi_set_DSP_cfg(void)
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(ausUartBases)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_io address %x. Aborting.\n", mwave_uart_io);
|
||||
pr_err("%s: Error: Invalid mwave_uart_io address %x. Aborting.\n", __func__,
|
||||
mwave_uart_io);
|
||||
return bRC;
|
||||
}
|
||||
uartio_index = i;
|
||||
@@ -264,7 +236,8 @@ int smapi_set_DSP_cfg(void)
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(ausUartIrqs)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg: Error: Invalid mwave_uart_irq %x. Aborting.\n", mwave_uart_irq);
|
||||
pr_err("%s: Error: Invalid mwave_uart_irq %x. Aborting.\n", __func__,
|
||||
mwave_uart_irq);
|
||||
return bRC;
|
||||
}
|
||||
}
|
||||
@@ -279,46 +252,15 @@ int smapi_set_DSP_cfg(void)
|
||||
if (usBX & 0x0100) { /* serial port A is present */
|
||||
if (usCX & 1) { /* serial port is enabled */
|
||||
if ((usSI & 0xFF) == mwave_uart_irq) {
|
||||
#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
|
||||
#else
|
||||
PRINTK_3(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
|
||||
#endif
|
||||
#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_1(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n");
|
||||
bRC = smapi_request(0x1403, 0x0100, 0, usSI,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1402, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
#else
|
||||
pr_err("%s: Serial port A irq %x conflicts with mwave_uart_irq %x\n",
|
||||
__func__, usSI & 0xFF, mwave_uart_irq);
|
||||
goto exit_conflict;
|
||||
#endif
|
||||
} else {
|
||||
if ((usSI >> 8) == uartio_index) {
|
||||
#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
|
||||
#else
|
||||
PRINTK_3(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
|
||||
#endif
|
||||
#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_1(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg Disabling conflicting serial port A\n");
|
||||
bRC = smapi_request (0x1403, 0x0100, 0, usSI,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request (0x1402, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
#else
|
||||
pr_err("%s: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n",
|
||||
__func__, ausUartBases[usSI >> 8],
|
||||
ausUartBases[uartio_index]);
|
||||
goto exit_conflict;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,46 +274,15 @@ int smapi_set_DSP_cfg(void)
|
||||
if (usBX & 0x0100) { /* serial port B is present */
|
||||
if (usCX & 1) { /* serial port is enabled */
|
||||
if ((usSI & 0xFF) == mwave_uart_irq) {
|
||||
#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
|
||||
#else
|
||||
PRINTK_3(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq);
|
||||
#endif
|
||||
#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_1(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
|
||||
bRC = smapi_request(0x1405, 0x0100, 0, usSI,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1404, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
#else
|
||||
pr_err("%s: Serial port B irq %x conflicts with mwave_uart_irq %x\n",
|
||||
__func__, usSI & 0xFF, mwave_uart_irq);
|
||||
goto exit_conflict;
|
||||
#endif
|
||||
} else {
|
||||
if ((usSI >> 8) == uartio_index) {
|
||||
#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
|
||||
#else
|
||||
PRINTK_3(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]);
|
||||
#endif
|
||||
#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_1 (TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n");
|
||||
bRC = smapi_request (0x1405, 0x0100, 0, usSI,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request (0x1404, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
#else
|
||||
pr_err("%s: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n",
|
||||
__func__, ausUartBases[usSI >> 8],
|
||||
ausUartBases[uartio_index]);
|
||||
goto exit_conflict;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -387,58 +298,15 @@ int smapi_set_DSP_cfg(void)
|
||||
/* bRC == 0 */
|
||||
if ((usCX & 0xff) != 0xff) { /* IR port not disabled */
|
||||
if ((usCX & 0xff) == mwave_uart_irq) {
|
||||
#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
|
||||
#else
|
||||
PRINTK_3(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq);
|
||||
#endif
|
||||
#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_1(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
|
||||
bRC = smapi_request(0x1701, 0x0100, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1700, 0, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1704, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
#else
|
||||
pr_err("%s: IR port irq %x conflicts with mwave_uart_irq %x\n",
|
||||
__func__, usCX & 0xff, mwave_uart_irq);
|
||||
goto exit_conflict;
|
||||
#endif
|
||||
} else {
|
||||
if ((usSI & 0xff) == uartio_index) {
|
||||
#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE
|
||||
"smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]);
|
||||
#else
|
||||
PRINTK_3(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]);
|
||||
#endif
|
||||
#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES
|
||||
PRINTK_1(TRACE_SMAPI,
|
||||
"smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n");
|
||||
bRC = smapi_request(0x1701, 0x0100, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1700, 0, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1705, 0x01ff, 0, usSI,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
bRC = smapi_request(0x1704, 0x0000, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
#else
|
||||
pr_err("%s: IR port base I/O address %x conflicts with mwave uart I/O %x\n",
|
||||
__func__, ausUartBases[usSI & 0xff],
|
||||
ausUartBases[uartio_index]);
|
||||
goto exit_conflict;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -482,7 +350,6 @@ int smapi_set_DSP_cfg(void)
|
||||
if (bRC) goto exit_smapi_request_error;
|
||||
|
||||
/* normal exit: */
|
||||
PRINTK_1(TRACE_SMAPI, "smapi::smapi_set_DSP_cfg exit\n");
|
||||
return 0;
|
||||
|
||||
exit_conflict:
|
||||
@@ -490,64 +357,32 @@ exit_conflict:
|
||||
return -EIO;
|
||||
|
||||
exit_smapi_request_error:
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "smapi::smapi_set_DSP_cfg exit on smapi_request error bRC %x\n", bRC);
|
||||
pr_err("%s: exit on smapi_request error bRC %x\n", __func__, bRC);
|
||||
return bRC;
|
||||
}
|
||||
|
||||
|
||||
int smapi_set_DSP_power_state(bool bOn)
|
||||
{
|
||||
int bRC;
|
||||
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
|
||||
unsigned short usPowerFunction;
|
||||
|
||||
PRINTK_2(TRACE_SMAPI, "smapi::smapi_set_DSP_power_state entry bOn %x\n", bOn);
|
||||
|
||||
usPowerFunction = (bOn) ? 1 : 0;
|
||||
|
||||
bRC = smapi_request(0x4901, 0x0000, 0, usPowerFunction,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
|
||||
PRINTK_2(TRACE_SMAPI, "smapi::smapi_set_DSP_power_state exit bRC %x\n", bRC);
|
||||
|
||||
return bRC;
|
||||
return smapi_request(0x4901, 0x0000, 0, usPowerFunction, &usAX, &usBX, &usCX, &usDX, &usDI,
|
||||
&usSI);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int SmapiQuerySystemID(void)
|
||||
{
|
||||
int bRC = -EIO;
|
||||
unsigned short usAX = 0xffff, usBX = 0xffff, usCX = 0xffff,
|
||||
usDX = 0xffff, usDI = 0xffff, usSI = 0xffff;
|
||||
|
||||
printk("smapi::SmapiQUerySystemID entry\n");
|
||||
bRC = smapi_request(0x0000, 0, 0, 0,
|
||||
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
|
||||
|
||||
if (bRC == 0) {
|
||||
printk("AX=%x, BX=%x, CX=%x, DX=%x, DI=%x, SI=%x\n",
|
||||
usAX, usBX, usCX, usDX, usDI, usSI);
|
||||
} else {
|
||||
printk("smapi::SmapiQuerySystemID smapi_request error\n");
|
||||
}
|
||||
|
||||
return bRC;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
int smapi_init(void)
|
||||
{
|
||||
int retval = -EIO;
|
||||
unsigned short usSmapiID = 0;
|
||||
unsigned long flags;
|
||||
|
||||
PRINTK_1(TRACE_SMAPI, "smapi::smapi_init entry\n");
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
usSmapiID = CMOS_READ(0x7C);
|
||||
usSmapiID |= (CMOS_READ(0x7D) << 8);
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
PRINTK_2(TRACE_SMAPI, "smapi::smapi_init usSmapiID %x\n", usSmapiID);
|
||||
|
||||
if (usSmapiID == 0x5349) {
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
@@ -555,16 +390,13 @@ int smapi_init(void)
|
||||
g_usSmapiPort |= (CMOS_READ(0x7F) << 8);
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
if (g_usSmapiPort == 0) {
|
||||
PRINTK_ERROR("smapi::smapi_init, ERROR unable to read from SMAPI port\n");
|
||||
pr_err("%s: ERROR unable to read from SMAPI port\n", __func__);
|
||||
} else {
|
||||
PRINTK_2(TRACE_SMAPI,
|
||||
"smapi::smapi_init, exit true g_usSmapiPort %x\n",
|
||||
g_usSmapiPort);
|
||||
retval = 0;
|
||||
//SmapiQuerySystemID();
|
||||
}
|
||||
} else {
|
||||
PRINTK_ERROR("smapi::smapi_init, ERROR invalid usSmapiID\n");
|
||||
pr_err("%s: ERROR invalid usSmapiID\n", __func__);
|
||||
retval = -ENXIO;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
#ifndef _LINUX_SMAPI_H
|
||||
#define _LINUX_SMAPI_H
|
||||
|
||||
typedef struct {
|
||||
struct smapi_dsp_settings {
|
||||
int bDSPPresent;
|
||||
int bDSPEnabled;
|
||||
int bModemEnabled;
|
||||
@@ -65,10 +65,10 @@ typedef struct {
|
||||
unsigned short usSndblstIRQ;
|
||||
unsigned short usSndblstDMA;
|
||||
unsigned short usSndblstBaseIO;
|
||||
} SMAPI_DSP_SETTINGS;
|
||||
};
|
||||
|
||||
int smapi_init(void);
|
||||
int smapi_query_DSP_cfg(SMAPI_DSP_SETTINGS * pSettings);
|
||||
int smapi_query_DSP_cfg(struct smapi_dsp_settings *pSettings);
|
||||
int smapi_set_DSP_cfg(void);
|
||||
int smapi_set_DSP_power_state(bool bOn);
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
* First release to the public
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "tp3780i: " fmt
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/ptrace.h>
|
||||
@@ -65,16 +67,14 @@ static unsigned short s_ausThinkpadDmaToField[8] =
|
||||
static unsigned short s_numIrqs = 16, s_numDmas = 8;
|
||||
|
||||
|
||||
static void EnableSRAM(THINKPAD_BD_DATA * pBDData)
|
||||
static void EnableSRAM(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
|
||||
DSP_GPIO_OUTPUT_DATA_15_8 rGpioOutputData;
|
||||
DSP_GPIO_DRIVER_ENABLE_15_8 rGpioDriverEnable;
|
||||
DSP_GPIO_MODE_15_8 rGpioMode;
|
||||
|
||||
PRINTK_1(TRACE_TP3780I, "tp3780i::EnableSRAM, entry\n");
|
||||
|
||||
MKWORD(rGpioMode) = ReadMsaCfg(DSP_GpioModeControl_15_8);
|
||||
rGpioMode.GpioMode10 = 0;
|
||||
WriteMsaCfg(DSP_GpioModeControl_15_8, MKWORD(rGpioMode));
|
||||
@@ -88,54 +88,31 @@ static void EnableSRAM(THINKPAD_BD_DATA * pBDData)
|
||||
rGpioOutputData.Latch10 = 0;
|
||||
rGpioOutputData.Mask10 = true;
|
||||
WriteMsaCfg(DSP_GpioOutputData_15_8, MKWORD(rGpioOutputData));
|
||||
|
||||
PRINTK_1(TRACE_TP3780I, "tp3780i::EnableSRAM exit\n");
|
||||
}
|
||||
|
||||
|
||||
static irqreturn_t UartInterrupt(int irq, void *dev_id)
|
||||
{
|
||||
PRINTK_3(TRACE_TP3780I,
|
||||
"tp3780i::UartInterrupt entry irq %x dev_id %p\n", irq, dev_id);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t DspInterrupt(int irq, void *dev_id)
|
||||
{
|
||||
pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pDrvData->rBDData.rDspSettings;
|
||||
struct mwave_device_data *pDrvData = &mwave_s_mdd;
|
||||
struct dsp_3780i_config_settings *pSettings = &pDrvData->rBDData.rDspSettings;
|
||||
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
|
||||
unsigned short usIPCSource = 0, usIsolationMask, usPCNum;
|
||||
|
||||
PRINTK_3(TRACE_TP3780I,
|
||||
"tp3780i::DspInterrupt entry irq %x dev_id %p\n", irq, dev_id);
|
||||
|
||||
if (dsp3780I_GetIPCSource(usDspBaseIO, &usIPCSource) == 0) {
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::DspInterrupt, return from dsp3780i_GetIPCSource, usIPCSource %x\n",
|
||||
usIPCSource);
|
||||
usIsolationMask = 1;
|
||||
for (usPCNum = 1; usPCNum <= 16; usPCNum++) {
|
||||
if (usIPCSource & usIsolationMask) {
|
||||
usIPCSource &= ~usIsolationMask;
|
||||
PRINTK_3(TRACE_TP3780I,
|
||||
"tp3780i::DspInterrupt usPCNum %x usIPCSource %x\n",
|
||||
usPCNum, usIPCSource);
|
||||
if (pDrvData->IPCs[usPCNum - 1].usIntCount == 0) {
|
||||
pDrvData->IPCs[usPCNum - 1].usIntCount = 1;
|
||||
}
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::DspInterrupt usIntCount %x\n",
|
||||
pDrvData->IPCs[usPCNum - 1].usIntCount);
|
||||
if (pDrvData->IPCs[usPCNum - 1].bIsEnabled == true) {
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::DspInterrupt, waking up usPCNum %x\n",
|
||||
usPCNum - 1);
|
||||
wake_up_interruptible(&pDrvData->IPCs[usPCNum - 1].ipc_wait_queue);
|
||||
} else {
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::DspInterrupt, no one waiting for IPC %x\n",
|
||||
usPCNum - 1);
|
||||
}
|
||||
}
|
||||
if (usIPCSource == 0)
|
||||
@@ -143,56 +120,42 @@ static irqreturn_t DspInterrupt(int irq, void *dev_id)
|
||||
/* try next IPC */
|
||||
usIsolationMask = usIsolationMask << 1;
|
||||
}
|
||||
} else {
|
||||
PRINTK_1(TRACE_TP3780I,
|
||||
"tp3780i::DspInterrupt, return false from dsp3780i_GetIPCSource\n");
|
||||
}
|
||||
PRINTK_1(TRACE_TP3780I, "tp3780i::DspInterrupt exit\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
int tp3780I_InitializeBoardData(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_InitializeBoardData(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_InitializeBoardData entry pBDData %p\n", pBDData);
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
pBDData->bDSPEnabled = false;
|
||||
pSettings->bInterruptClaimed = false;
|
||||
|
||||
retval = smapi_init();
|
||||
if (retval) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_InitializeBoardData: Error: SMAPI is not available on this machine\n");
|
||||
pr_err("%s: Error: SMAPI is not available on this machine\n", __func__);
|
||||
} else {
|
||||
if (mwave_3780i_irq || mwave_3780i_io || mwave_uart_irq || mwave_uart_io) {
|
||||
retval = smapi_set_DSP_cfg();
|
||||
}
|
||||
}
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_InitializeBoardData exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void tp3780I_Cleanup(THINKPAD_BD_DATA *pBDData)
|
||||
void tp3780I_Cleanup(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_Cleanup entry and exit pBDData %p\n", pBDData);
|
||||
}
|
||||
|
||||
int tp3780I_CalcResources(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_CalcResources(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
SMAPI_DSP_SETTINGS rSmapiInfo;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_CalcResources entry pBDData %p\n", pBDData);
|
||||
struct smapi_dsp_settings rSmapiInfo;
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
if (smapi_query_DSP_cfg(&rSmapiInfo)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_CalcResources: Error: Could not query DSP config. Aborting.\n");
|
||||
pr_err("%s: Error: Could not query DSP config. Aborting.\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -203,7 +166,7 @@ int tp3780I_CalcResources(THINKPAD_BD_DATA * pBDData)
|
||||
|| ( rSmapiInfo.usUartIRQ == 0 )
|
||||
|| ( rSmapiInfo.usUartBaseIO == 0 )
|
||||
) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_CalcResources: Error: Illegal resource setting. Aborting.\n");
|
||||
pr_err("%s: Error: Illegal resource setting. Aborting.\n", __func__);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -225,41 +188,31 @@ int tp3780I_CalcResources(THINKPAD_BD_DATA * pBDData)
|
||||
pBDData->bShareDspIrq = pBDData->bShareUartIrq = 0;
|
||||
}
|
||||
|
||||
PRINTK_1(TRACE_TP3780I, "tp3780i::tp3780I_CalcResources exit\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_ClaimResources(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
struct resource *pres;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData);
|
||||
|
||||
pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
|
||||
if ( pres == NULL ) retval = -EIO;
|
||||
|
||||
if (retval) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO);
|
||||
retval = -EIO;
|
||||
pr_err("%s: Error: Could not claim I/O region starting at %x\n", __func__,
|
||||
pSettings->usDspBaseIO);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ClaimResources exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_ReleaseResources(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_ReleaseResources entry pBDData %p\n", pBDData);
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
release_region(pSettings->usDspBaseIO & (~3), 16);
|
||||
|
||||
@@ -268,28 +221,23 @@ int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData)
|
||||
pSettings->bInterruptClaimed = false;
|
||||
}
|
||||
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_ReleaseResources exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_EnableDSP(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
bool bDSPPoweredUp = false, bInterruptAllocated = false;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData);
|
||||
|
||||
if (pBDData->bDSPEnabled) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: DSP already enabled!\n");
|
||||
pr_err("%s: Error: DSP already enabled!\n", __func__);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
if (!pSettings->bDSPEnabled) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780::tp3780I_EnableDSP: Error: pSettings->bDSPEnabled not set\n");
|
||||
pr_err("%s: Error: pSettings->bDSPEnabled not set\n", __func__);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
@@ -299,7 +247,7 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
|| (s_ausThinkpadIrqToField[pSettings->usDspIrq] == 0xFFFF)
|
||||
|| (s_ausThinkpadDmaToField[pSettings->usDspDma] == 0xFFFF)
|
||||
) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: invalid irq %x\n", pSettings->usDspIrq);
|
||||
pr_err("%s: Error: invalid irq %x\n", __func__, pSettings->usDspIrq);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
@@ -307,7 +255,8 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
((pSettings->usDspBaseIO & 0xF00F) != 0)
|
||||
|| (pSettings->usDspBaseIO & 0x0FF0) == 0
|
||||
) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Invalid DSP base I/O address %x\n", pSettings->usDspBaseIO);
|
||||
pr_err("%s: Error: Invalid DSP base I/O address %x\n", __func__,
|
||||
pSettings->usDspBaseIO);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
@@ -316,7 +265,7 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
pSettings->usUartIrq >= s_numIrqs
|
||||
|| s_ausThinkpadIrqToField[pSettings->usUartIrq] == 0xFFFF
|
||||
) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Invalid UART IRQ %x\n", pSettings->usUartIrq);
|
||||
pr_err("%s: Error: Invalid UART IRQ %x\n", __func__, pSettings->usUartIrq);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
switch (pSettings->usUartBaseIO) {
|
||||
@@ -327,7 +276,8 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
break;
|
||||
|
||||
default:
|
||||
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: Invalid UART base I/O address %x\n", pSettings->usUartBaseIO);
|
||||
pr_err("%s: Error: Invalid UART base I/O address %x\n", __func__,
|
||||
pSettings->usUartBaseIO);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
}
|
||||
@@ -356,33 +306,30 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
pSettings->usChipletEnable = TP_CFG_ChipletEnable;
|
||||
|
||||
if (request_irq(pSettings->usUartIrq, &UartInterrupt, 0, "mwave_uart", NULL)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: Could not get UART IRQ %x\n", pSettings->usUartIrq);
|
||||
pr_err("%s: Error: Could not get UART IRQ %x\n", __func__, pSettings->usUartIrq);
|
||||
goto exit_cleanup;
|
||||
} else { /* no conflict just release */
|
||||
free_irq(pSettings->usUartIrq, NULL);
|
||||
}
|
||||
|
||||
if (request_irq(pSettings->usDspIrq, &DspInterrupt, 0, "mwave_3780i", NULL)) {
|
||||
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: Could not get 3780i IRQ %x\n", pSettings->usDspIrq);
|
||||
pr_err("%s: Error: Could not get 3780i IRQ %x\n", __func__, pSettings->usDspIrq);
|
||||
goto exit_cleanup;
|
||||
} else {
|
||||
PRINTK_3(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_EnableDSP, got interrupt %x bShareDspIrq %x\n",
|
||||
pSettings->usDspIrq, pBDData->bShareDspIrq);
|
||||
bInterruptAllocated = true;
|
||||
pSettings->bInterruptClaimed = true;
|
||||
}
|
||||
|
||||
smapi_set_DSP_power_state(false);
|
||||
if (smapi_set_DSP_power_state(true)) {
|
||||
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_EnableDSP: Error: smapi_set_DSP_power_state(true) failed\n");
|
||||
pr_err("%s: Error: smapi_set_DSP_power_state(true) failed\n", __func__);
|
||||
goto exit_cleanup;
|
||||
} else {
|
||||
bDSPPoweredUp = true;
|
||||
}
|
||||
|
||||
if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
|
||||
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n");
|
||||
pr_err("%s: Error: dsp7880I_EnableDSP() failed\n", __func__);
|
||||
goto exit_cleanup;
|
||||
}
|
||||
|
||||
@@ -390,12 +337,10 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
|
||||
pBDData->bDSPEnabled = true;
|
||||
|
||||
PRINTK_1(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP exit\n");
|
||||
|
||||
return 0;
|
||||
|
||||
exit_cleanup:
|
||||
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n");
|
||||
pr_err("%s: Cleaning up\n", __func__);
|
||||
if (bDSPPoweredUp)
|
||||
smapi_set_DSP_power_state(false);
|
||||
if (bInterruptAllocated) {
|
||||
@@ -406,12 +351,9 @@ exit_cleanup:
|
||||
}
|
||||
|
||||
|
||||
int tp3780I_DisableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_DisableDSP(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_DisableDSP entry pBDData %p\n", pBDData);
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
if (pBDData->bDSPEnabled) {
|
||||
dsp3780I_DisableDSP(&pBDData->rDspSettings);
|
||||
@@ -423,56 +365,38 @@ int tp3780I_DisableDSP(THINKPAD_BD_DATA * pBDData)
|
||||
pBDData->bDSPEnabled = false;
|
||||
}
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_DisableDSP exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tp3780I_ResetDSP(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_ResetDSP(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ResetDSP entry pBDData %p\n",
|
||||
pBDData);
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
if (dsp3780I_Reset(pSettings) == 0) {
|
||||
EnableSRAM(pBDData);
|
||||
} else {
|
||||
retval = -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ResetDSP exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
int tp3780I_StartDSP(THINKPAD_BD_DATA * pBDData)
|
||||
int tp3780I_StartDSP(struct thinkpad_bd_data *pBDData)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_StartDSP entry pBDData %p\n", pBDData);
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
|
||||
if (dsp3780I_Run(pSettings) == 0) {
|
||||
// @BUG @TBD EnableSRAM(pBDData);
|
||||
} else {
|
||||
retval = -EIO;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_StartDSP exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities)
|
||||
int tp3780I_QueryAbilities(struct thinkpad_bd_data *pBDData, struct mw_abilities *pAbilities)
|
||||
{
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_QueryAbilities entry pBDData %p\n", pBDData);
|
||||
|
||||
memset(pAbilities, 0, sizeof(*pAbilities));
|
||||
/* fill out standard constant fields */
|
||||
pAbilities->instr_per_sec = pBDData->rDspSettings.uIps;
|
||||
@@ -497,25 +421,17 @@ int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities
|
||||
memcpy(pAbilities->bios_task_name, TP_ABILITIES_BIOSTASK_NAME,
|
||||
sizeof(TP_ABILITIES_BIOSTASK_NAME));
|
||||
|
||||
PRINTK_1(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_QueryAbilities exit retval=SUCCESSFUL\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
|
||||
int tp3780I_ReadWriteDspDStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
|
||||
void __user *pvBuffer, unsigned int uCount,
|
||||
unsigned long ulDSPAddr)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
|
||||
bool bRC = 0;
|
||||
|
||||
PRINTK_6(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_ReadWriteDspDStore entry pBDData %p, uOpcode %x, pvBuffer %p, uCount %x, ulDSPAddr %lx\n",
|
||||
pBDData, uOpcode, pvBuffer, uCount, ulDSPAddr);
|
||||
|
||||
if (pBDData->bDSPEnabled) {
|
||||
switch (uOpcode) {
|
||||
case IOCTL_MW_READ_DATA:
|
||||
@@ -532,26 +448,18 @@ int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
|
||||
}
|
||||
}
|
||||
|
||||
retval = (bRC) ? -EIO : 0;
|
||||
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_ReadWriteDspDStore exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
return bRC ? -EIO : 0;
|
||||
}
|
||||
|
||||
|
||||
int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
|
||||
int tp3780I_ReadWriteDspIStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
|
||||
void __user *pvBuffer, unsigned int uCount,
|
||||
unsigned long ulDSPAddr)
|
||||
{
|
||||
int retval = 0;
|
||||
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
|
||||
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
|
||||
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
|
||||
bool bRC = 0;
|
||||
|
||||
PRINTK_6(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_ReadWriteDspIStore entry pBDData %p, uOpcode %x, pvBuffer %p, uCount %x, ulDSPAddr %lx\n",
|
||||
pBDData, uOpcode, pvBuffer, uCount, ulDSPAddr);
|
||||
|
||||
if (pBDData->bDSPEnabled) {
|
||||
switch (uOpcode) {
|
||||
case IOCTL_MW_READ_INST:
|
||||
@@ -564,11 +472,6 @@ int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
|
||||
}
|
||||
}
|
||||
|
||||
retval = (bRC) ? -EIO : 0;
|
||||
|
||||
PRINTK_2(TRACE_TP3780I,
|
||||
"tp3780i::tp3780I_ReadWriteDspIStore exit retval %x\n", retval);
|
||||
|
||||
return retval;
|
||||
return bRC ? -EIO : 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,27 +75,27 @@
|
||||
#define TP_CFG_PllBypass 0 /* don't bypass */
|
||||
#define TP_CFG_ChipletEnable 0xFFFF /* Enable all chiplets */
|
||||
|
||||
typedef struct {
|
||||
struct thinkpad_bd_data {
|
||||
int bDSPEnabled;
|
||||
int bShareDspIrq;
|
||||
int bShareUartIrq;
|
||||
DSP_3780I_CONFIG_SETTINGS rDspSettings;
|
||||
} THINKPAD_BD_DATA;
|
||||
struct dsp_3780i_config_settings rDspSettings;
|
||||
};
|
||||
|
||||
int tp3780I_InitializeBoardData(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_CalcResources(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_DisableDSP(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_ResetDSP(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_StartDSP(THINKPAD_BD_DATA * pBDData);
|
||||
int tp3780I_QueryAbilities(THINKPAD_BD_DATA * pBDData, MW_ABILITIES * pAbilities);
|
||||
void tp3780I_Cleanup(THINKPAD_BD_DATA *pBDData);
|
||||
int tp3780I_ReadWriteDspDStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
|
||||
int tp3780I_InitializeBoardData(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_CalcResources(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_ClaimResources(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_ReleaseResources(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_EnableDSP(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_DisableDSP(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_ResetDSP(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_StartDSP(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_QueryAbilities(struct thinkpad_bd_data *pBDData, struct mw_abilities *pAbilities);
|
||||
void tp3780I_Cleanup(struct thinkpad_bd_data *pBDData);
|
||||
int tp3780I_ReadWriteDspDStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
|
||||
void __user *pvBuffer, unsigned int uCount,
|
||||
unsigned long ulDSPAddr);
|
||||
int tp3780I_ReadWriteDspIStore(THINKPAD_BD_DATA * pBDData, unsigned int uOpcode,
|
||||
int tp3780I_ReadWriteDspIStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
|
||||
void __user *pvBuffer, unsigned int uCount,
|
||||
unsigned long ulDSPAddr);
|
||||
|
||||
|
||||
@@ -1973,7 +1973,7 @@ EXPORT_SYMBOL(xillybus_endpoint_remove);
|
||||
|
||||
static int __init xillybus_init(void)
|
||||
{
|
||||
xillybus_wq = alloc_workqueue(xillyname, 0, 0);
|
||||
xillybus_wq = alloc_workqueue(xillyname, WQ_UNBOUND, 0);
|
||||
if (!xillybus_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -2163,7 +2163,7 @@ static int xillyusb_probe(struct usb_interface *interface,
|
||||
spin_lock_init(&xdev->error_lock);
|
||||
xdev->in_counter = 0;
|
||||
xdev->in_bytes_left = 0;
|
||||
xdev->workq = alloc_workqueue(xillyname, WQ_HIGHPRI, 0);
|
||||
xdev->workq = alloc_workqueue(xillyname, WQ_HIGHPRI | WQ_UNBOUND, 0);
|
||||
|
||||
if (!xdev->workq) {
|
||||
dev_err(&interface->dev, "Failed to allocate work queue\n");
|
||||
@@ -2275,7 +2275,7 @@ static int __init xillyusb_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
wakeup_wq = alloc_workqueue(xillyname, 0, 0);
|
||||
wakeup_wq = alloc_workqueue(xillyname, WQ_UNBOUND, 0);
|
||||
if (!wakeup_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
@@ -273,19 +273,8 @@ unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s)
|
||||
return free_end - async->buf_write_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_buf_write_alloc() - Reserve buffer space for writing
|
||||
* @s: COMEDI subdevice.
|
||||
* @nbytes: Maximum space to reserve in bytes.
|
||||
*
|
||||
* Reserve up to @nbytes bytes of space to be written in the COMEDI acquisition
|
||||
* data buffer associated with the subdevice. The amount reserved is limited
|
||||
* by the space available.
|
||||
*
|
||||
* Return: The amount of space reserved in bytes.
|
||||
*/
|
||||
unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
unsigned int _comedi_buf_write_alloc(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int unalloc = comedi_buf_write_n_unalloc(s);
|
||||
@@ -303,6 +292,29 @@ unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s,
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_buf_write_alloc() - Reserve buffer space for writing
|
||||
* @s: COMEDI subdevice.
|
||||
* @nbytes: Maximum space to reserve in bytes.
|
||||
*
|
||||
* Reserve up to @nbytes bytes of space to be written in the COMEDI acquisition
|
||||
* data buffer associated with the subdevice. The amount reserved is limited
|
||||
* by the space available.
|
||||
*
|
||||
* Return: The amount of space reserved in bytes.
|
||||
*/
|
||||
unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nbytes = _comedi_buf_write_alloc(s, nbytes);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nbytes = 0;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_write_alloc);
|
||||
|
||||
/*
|
||||
@@ -362,6 +374,24 @@ unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s)
|
||||
return async->buf_write_alloc_count - async->buf_write_count;
|
||||
}
|
||||
|
||||
unsigned int _comedi_buf_write_free(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int allocated = comedi_buf_write_n_allocated(s);
|
||||
|
||||
if (nbytes > allocated)
|
||||
nbytes = allocated;
|
||||
|
||||
async->buf_write_count += nbytes;
|
||||
async->buf_write_ptr += nbytes;
|
||||
comedi_buf_munge(s, async->buf_write_count - async->munge_count);
|
||||
if (async->buf_write_ptr >= async->prealloc_bufsz)
|
||||
async->buf_write_ptr %= async->prealloc_bufsz;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_buf_write_free() - Free buffer space after it is written
|
||||
* @s: COMEDI subdevice.
|
||||
@@ -380,34 +410,17 @@ unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s)
|
||||
unsigned int comedi_buf_write_free(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int allocated = comedi_buf_write_n_allocated(s);
|
||||
|
||||
if (nbytes > allocated)
|
||||
nbytes = allocated;
|
||||
|
||||
async->buf_write_count += nbytes;
|
||||
async->buf_write_ptr += nbytes;
|
||||
comedi_buf_munge(s, async->buf_write_count - async->munge_count);
|
||||
if (async->buf_write_ptr >= async->prealloc_bufsz)
|
||||
async->buf_write_ptr %= async->prealloc_bufsz;
|
||||
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nbytes = _comedi_buf_write_free(s, nbytes);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nbytes = 0;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_write_free);
|
||||
|
||||
/**
|
||||
* comedi_buf_read_n_available() - Determine amount of readable buffer space
|
||||
* @s: COMEDI subdevice.
|
||||
*
|
||||
* Determine the amount of readable buffer space in the COMEDI acquisition data
|
||||
* buffer associated with the subdevice. The readable buffer space is that
|
||||
* which has been freed by the writer and "munged" to the sample data format
|
||||
* expected by COMEDI if necessary.
|
||||
*
|
||||
* Return: The amount of readable buffer space.
|
||||
*/
|
||||
unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s)
|
||||
unsigned int _comedi_buf_read_n_available(struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int num_bytes;
|
||||
@@ -425,8 +438,53 @@ unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s)
|
||||
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_buf_read_n_available() - Determine amount of readable buffer space
|
||||
* @s: COMEDI subdevice.
|
||||
*
|
||||
* Determine the amount of readable buffer space in the COMEDI acquisition data
|
||||
* buffer associated with the subdevice. The readable buffer space is that
|
||||
* which has been freed by the writer and "munged" to the sample data format
|
||||
* expected by COMEDI if necessary.
|
||||
*
|
||||
* Return: The amount of readable buffer space.
|
||||
*/
|
||||
unsigned int comedi_buf_read_n_available(struct comedi_subdevice *s)
|
||||
{
|
||||
unsigned int num_bytes;
|
||||
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
num_bytes = _comedi_buf_read_n_available(s);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
num_bytes = 0;
|
||||
}
|
||||
return num_bytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_read_n_available);
|
||||
|
||||
unsigned int _comedi_buf_read_alloc(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int available;
|
||||
|
||||
available = async->munge_count - async->buf_read_alloc_count;
|
||||
if (nbytes > available)
|
||||
nbytes = available;
|
||||
|
||||
async->buf_read_alloc_count += nbytes;
|
||||
|
||||
/*
|
||||
* ensure the async buffer 'counts' are read before we
|
||||
* attempt to read data from the read-alloc'ed buffer space
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_buf_read_alloc() - Reserve buffer space for reading
|
||||
* @s: COMEDI subdevice.
|
||||
@@ -445,21 +503,12 @@ EXPORT_SYMBOL_GPL(comedi_buf_read_n_available);
|
||||
unsigned int comedi_buf_read_alloc(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int available;
|
||||
|
||||
available = async->munge_count - async->buf_read_alloc_count;
|
||||
if (nbytes > available)
|
||||
nbytes = available;
|
||||
|
||||
async->buf_read_alloc_count += nbytes;
|
||||
|
||||
/*
|
||||
* ensure the async buffer 'counts' are read before we
|
||||
* attempt to read data from the read-alloc'ed buffer space
|
||||
*/
|
||||
smp_rmb();
|
||||
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nbytes = _comedi_buf_read_alloc(s, nbytes);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nbytes = 0;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_read_alloc);
|
||||
@@ -469,6 +518,28 @@ static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async)
|
||||
return async->buf_read_alloc_count - async->buf_read_count;
|
||||
}
|
||||
|
||||
unsigned int _comedi_buf_read_free(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int allocated;
|
||||
|
||||
/*
|
||||
* ensure data has been read out of buffer before
|
||||
* the async read count is incremented
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
allocated = comedi_buf_read_n_allocated(async);
|
||||
if (nbytes > allocated)
|
||||
nbytes = allocated;
|
||||
|
||||
async->buf_read_count += nbytes;
|
||||
async->buf_read_ptr += nbytes;
|
||||
async->buf_read_ptr %= async->prealloc_bufsz;
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_buf_read_free() - Free buffer space after it has been read
|
||||
* @s: COMEDI subdevice.
|
||||
@@ -485,22 +556,12 @@ static unsigned int comedi_buf_read_n_allocated(struct comedi_async *async)
|
||||
unsigned int comedi_buf_read_free(struct comedi_subdevice *s,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int allocated;
|
||||
|
||||
/*
|
||||
* ensure data has been read out of buffer before
|
||||
* the async read count is incremented
|
||||
*/
|
||||
smp_mb();
|
||||
|
||||
allocated = comedi_buf_read_n_allocated(async);
|
||||
if (nbytes > allocated)
|
||||
nbytes = allocated;
|
||||
|
||||
async->buf_read_count += nbytes;
|
||||
async->buf_read_ptr += nbytes;
|
||||
async->buf_read_ptr %= async->prealloc_bufsz;
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nbytes = _comedi_buf_read_free(s, nbytes);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nbytes = 0;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_read_free);
|
||||
@@ -558,6 +619,38 @@ static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int _comedi_buf_write_samples(struct comedi_subdevice *s,
|
||||
const void *data,
|
||||
unsigned int nsamples)
|
||||
{
|
||||
unsigned int max_samples;
|
||||
unsigned int nbytes;
|
||||
|
||||
/*
|
||||
* Make sure there is enough room in the buffer for all the samples.
|
||||
* If not, clamp the nsamples to the number that will fit, flag the
|
||||
* buffer overrun and add the samples that fit.
|
||||
*/
|
||||
max_samples = comedi_bytes_to_samples(s, comedi_buf_write_n_unalloc(s));
|
||||
if (nsamples > max_samples) {
|
||||
dev_warn(s->device->class_dev, "buffer overrun\n");
|
||||
s->async->events |= COMEDI_CB_OVERFLOW;
|
||||
nsamples = max_samples;
|
||||
}
|
||||
|
||||
if (nsamples == 0)
|
||||
return 0;
|
||||
|
||||
nbytes = comedi_samples_to_bytes(s, nsamples);
|
||||
nbytes = _comedi_buf_write_alloc(s, nbytes);
|
||||
comedi_buf_memcpy_to(s, data, nbytes);
|
||||
_comedi_buf_write_free(s, nbytes);
|
||||
_comedi_inc_scan_progress(s, nbytes);
|
||||
s->async->events |= COMEDI_CB_BLOCK;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_buf_write_samples() - Write sample data to COMEDI buffer
|
||||
* @s: COMEDI subdevice.
|
||||
@@ -577,35 +670,43 @@ static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
|
||||
*/
|
||||
unsigned int comedi_buf_write_samples(struct comedi_subdevice *s,
|
||||
const void *data, unsigned int nsamples)
|
||||
{
|
||||
unsigned int nbytes;
|
||||
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nbytes = _comedi_buf_write_samples(s, data, nsamples);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nbytes = 0;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_write_samples);
|
||||
|
||||
static unsigned int _comedi_buf_read_samples(struct comedi_subdevice *s,
|
||||
void *data, unsigned int nsamples)
|
||||
{
|
||||
unsigned int max_samples;
|
||||
unsigned int nbytes;
|
||||
|
||||
/*
|
||||
* Make sure there is enough room in the buffer for all the samples.
|
||||
* If not, clamp the nsamples to the number that will fit, flag the
|
||||
* buffer overrun and add the samples that fit.
|
||||
*/
|
||||
max_samples = comedi_bytes_to_samples(s, comedi_buf_write_n_unalloc(s));
|
||||
if (nsamples > max_samples) {
|
||||
dev_warn(s->device->class_dev, "buffer overrun\n");
|
||||
s->async->events |= COMEDI_CB_OVERFLOW;
|
||||
/* clamp nsamples to the number of full samples available */
|
||||
max_samples = comedi_bytes_to_samples(s,
|
||||
_comedi_buf_read_n_available(s));
|
||||
if (nsamples > max_samples)
|
||||
nsamples = max_samples;
|
||||
}
|
||||
|
||||
if (nsamples == 0)
|
||||
return 0;
|
||||
|
||||
nbytes = comedi_buf_write_alloc(s,
|
||||
nbytes = _comedi_buf_read_alloc(s,
|
||||
comedi_samples_to_bytes(s, nsamples));
|
||||
comedi_buf_memcpy_to(s, data, nbytes);
|
||||
comedi_buf_write_free(s, nbytes);
|
||||
comedi_inc_scan_progress(s, nbytes);
|
||||
comedi_buf_memcpy_from(s, data, nbytes);
|
||||
_comedi_buf_read_free(s, nbytes);
|
||||
_comedi_inc_scan_progress(s, nbytes);
|
||||
s->async->events |= COMEDI_CB_BLOCK;
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_write_samples);
|
||||
|
||||
/**
|
||||
* comedi_buf_read_samples() - Read sample data from COMEDI buffer
|
||||
@@ -624,25 +725,14 @@ EXPORT_SYMBOL_GPL(comedi_buf_write_samples);
|
||||
unsigned int comedi_buf_read_samples(struct comedi_subdevice *s,
|
||||
void *data, unsigned int nsamples)
|
||||
{
|
||||
unsigned int max_samples;
|
||||
unsigned int nbytes;
|
||||
|
||||
/* clamp nsamples to the number of full samples available */
|
||||
max_samples = comedi_bytes_to_samples(s,
|
||||
comedi_buf_read_n_available(s));
|
||||
if (nsamples > max_samples)
|
||||
nsamples = max_samples;
|
||||
|
||||
if (nsamples == 0)
|
||||
return 0;
|
||||
|
||||
nbytes = comedi_buf_read_alloc(s,
|
||||
comedi_samples_to_bytes(s, nsamples));
|
||||
comedi_buf_memcpy_from(s, data, nbytes);
|
||||
comedi_buf_read_free(s, nbytes);
|
||||
comedi_inc_scan_progress(s, nbytes);
|
||||
s->async->events |= COMEDI_CB_BLOCK;
|
||||
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nbytes = _comedi_buf_read_samples(s, data, nsamples);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nbytes = 0;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_buf_read_samples);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
* COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred
|
||||
* since the last command was started
|
||||
* COMEDI_SRF_RUNNING: command is running
|
||||
* COMEDI_SRF_BUSY: command was started and subdevice still busy
|
||||
* COMEDI_SRF_FREE_SPRIV: free s->private on detach
|
||||
*
|
||||
* COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy"
|
||||
@@ -45,9 +46,11 @@
|
||||
#define COMEDI_SRF_RT BIT(1)
|
||||
#define COMEDI_SRF_ERROR BIT(2)
|
||||
#define COMEDI_SRF_RUNNING BIT(27)
|
||||
#define COMEDI_SRF_BUSY BIT(28)
|
||||
#define COMEDI_SRF_FREE_SPRIV BIT(31)
|
||||
|
||||
#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING)
|
||||
#define COMEDI_SRF_BUSY_MASK \
|
||||
(COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING | COMEDI_SRF_BUSY)
|
||||
|
||||
/**
|
||||
* struct comedi_file - Per-file private data for COMEDI device
|
||||
@@ -665,6 +668,11 @@ static bool comedi_is_runflags_in_error(unsigned int runflags)
|
||||
return runflags & COMEDI_SRF_ERROR;
|
||||
}
|
||||
|
||||
static bool comedi_is_runflags_busy(unsigned int runflags)
|
||||
{
|
||||
return runflags & COMEDI_SRF_BUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_is_subdevice_running() - Check if async command running on subdevice
|
||||
* @s: COMEDI subdevice.
|
||||
@@ -687,6 +695,46 @@ static bool __comedi_is_subdevice_running(struct comedi_subdevice *s)
|
||||
return comedi_is_runflags_running(runflags);
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_get_is_subdevice_running() - Get if async command running on subdevice
|
||||
* @s: COMEDI subdevice.
|
||||
*
|
||||
* If an asynchronous COMEDI command is running on the subdevice, increment
|
||||
* a reference counter. If the function return value indicates that a
|
||||
* command is running, then the details of the command will not be destroyed
|
||||
* before a matching call to comedi_put_is_subdevice_running().
|
||||
*
|
||||
* Return: %true if an asynchronous COMEDI command is active on the
|
||||
* subdevice, else %false.
|
||||
*/
|
||||
bool comedi_get_is_subdevice_running(struct comedi_subdevice *s)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool running;
|
||||
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
running = __comedi_is_subdevice_running(s);
|
||||
if (running)
|
||||
refcount_inc(&s->async->run_active);
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
return running;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_get_is_subdevice_running);
|
||||
|
||||
/**
|
||||
* comedi_put_is_subdevice_running() - Put if async command running on subdevice
|
||||
* @s: COMEDI subdevice.
|
||||
*
|
||||
* Decrements the reference counter that was incremented when
|
||||
* comedi_get_is_subdevice_running() returned %true.
|
||||
*/
|
||||
void comedi_put_is_subdevice_running(struct comedi_subdevice *s)
|
||||
{
|
||||
if (refcount_dec_and_test(&s->async->run_active))
|
||||
complete_all(&s->async->run_complete);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_put_is_subdevice_running);
|
||||
|
||||
bool comedi_can_auto_free_spriv(struct comedi_subdevice *s)
|
||||
{
|
||||
unsigned int runflags = __comedi_get_subdevice_runflags(s);
|
||||
@@ -736,20 +784,28 @@ static void do_become_nonbusy(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int runflags;
|
||||
unsigned long flags;
|
||||
|
||||
lockdep_assert_held(&dev->mutex);
|
||||
comedi_update_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0);
|
||||
if (async) {
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
runflags = __comedi_get_subdevice_runflags(s);
|
||||
__comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING |
|
||||
COMEDI_SRF_BUSY);
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
if (comedi_is_runflags_busy(runflags)) {
|
||||
/*
|
||||
* "Run active" counter was set to 1 when setting up the
|
||||
* command. Decrement it and wait for it to become 0.
|
||||
*/
|
||||
comedi_put_is_subdevice_running(s);
|
||||
wait_for_completion(&async->run_complete);
|
||||
comedi_buf_reset(s);
|
||||
async->inttrig = NULL;
|
||||
kfree(async->cmd.chanlist);
|
||||
async->cmd.chanlist = NULL;
|
||||
s->busy = NULL;
|
||||
wake_up_interruptible_all(&async->wait_head);
|
||||
} else {
|
||||
dev_err(dev->class_dev,
|
||||
"BUG: (?) %s called with async=NULL\n", __func__);
|
||||
s->busy = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1150,15 +1206,15 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
|
||||
if (!(async->cmd.flags & CMDF_WRITE)) {
|
||||
/* command was set up in "read" direction */
|
||||
if (bi.bytes_read) {
|
||||
comedi_buf_read_alloc(s, bi.bytes_read);
|
||||
bi.bytes_read = comedi_buf_read_free(s, bi.bytes_read);
|
||||
_comedi_buf_read_alloc(s, bi.bytes_read);
|
||||
bi.bytes_read = _comedi_buf_read_free(s, bi.bytes_read);
|
||||
}
|
||||
/*
|
||||
* If nothing left to read, and command has stopped, and
|
||||
* {"read" position not updated or command stopped normally},
|
||||
* then become non-busy.
|
||||
*/
|
||||
if (comedi_buf_read_n_available(s) == 0 &&
|
||||
if (_comedi_buf_read_n_available(s) == 0 &&
|
||||
!comedi_is_runflags_running(runflags) &&
|
||||
(bi.bytes_read == 0 ||
|
||||
!comedi_is_runflags_in_error(runflags))) {
|
||||
@@ -1175,9 +1231,9 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
|
||||
if (comedi_is_runflags_in_error(runflags))
|
||||
retval = -EPIPE;
|
||||
} else if (bi.bytes_written) {
|
||||
comedi_buf_write_alloc(s, bi.bytes_written);
|
||||
_comedi_buf_write_alloc(s, bi.bytes_written);
|
||||
bi.bytes_written =
|
||||
comedi_buf_write_free(s, bi.bytes_written);
|
||||
_comedi_buf_write_free(s, bi.bytes_written);
|
||||
}
|
||||
bi.bytes_read = 0;
|
||||
}
|
||||
@@ -1860,8 +1916,14 @@ static int do_cmd_ioctl(struct comedi_device *dev,
|
||||
if (async->cmd.flags & CMDF_WAKE_EOS)
|
||||
async->cb_mask |= COMEDI_CB_EOS;
|
||||
|
||||
/*
|
||||
* Set the "run active" counter with an initial count of 1 that will
|
||||
* complete the "safe to reset" event when it is decremented to 0.
|
||||
*/
|
||||
refcount_set(&s->async->run_active, 1);
|
||||
reinit_completion(&s->async->run_complete);
|
||||
comedi_update_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK,
|
||||
COMEDI_SRF_RUNNING);
|
||||
COMEDI_SRF_RUNNING | COMEDI_SRF_BUSY);
|
||||
|
||||
/*
|
||||
* Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid
|
||||
@@ -2284,15 +2346,10 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
|
||||
rc = check_insnlist_len(dev, insnlist.n_insns);
|
||||
if (rc)
|
||||
break;
|
||||
insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL);
|
||||
if (!insns) {
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
if (copy_from_user(insns, insnlist.insns,
|
||||
sizeof(*insns) * insnlist.n_insns)) {
|
||||
rc = -EFAULT;
|
||||
kfree(insns);
|
||||
insns = memdup_array_user(insnlist.insns, insnlist.n_insns,
|
||||
sizeof(*insns));
|
||||
if (IS_ERR(insns)) {
|
||||
rc = PTR_ERR(insns);
|
||||
break;
|
||||
}
|
||||
rc = do_insnlist_ioctl(dev, insns, insnlist.n_insns, file);
|
||||
@@ -2512,7 +2569,7 @@ static __poll_t comedi_poll(struct file *file, poll_table *wait)
|
||||
poll_wait(file, &s->async->wait_head, wait);
|
||||
if (s->busy != file || !comedi_is_subdevice_running(s) ||
|
||||
(s->async->cmd.flags & CMDF_WRITE) ||
|
||||
comedi_buf_read_n_available(s) > 0)
|
||||
_comedi_buf_read_n_available(s) > 0)
|
||||
mask |= EPOLLIN | EPOLLRDNORM;
|
||||
}
|
||||
|
||||
@@ -2645,7 +2702,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
|
||||
break;
|
||||
|
||||
/* Allocate all free buffer space. */
|
||||
comedi_buf_write_alloc(s, async->prealloc_bufsz);
|
||||
_comedi_buf_write_alloc(s, async->prealloc_bufsz);
|
||||
m = comedi_buf_write_n_allocated(s);
|
||||
n = min_t(size_t, m, nbytes);
|
||||
|
||||
@@ -2673,7 +2730,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
|
||||
n -= m;
|
||||
retval = -EFAULT;
|
||||
}
|
||||
comedi_buf_write_free(s, n);
|
||||
_comedi_buf_write_free(s, n);
|
||||
|
||||
count += n;
|
||||
nbytes -= n;
|
||||
@@ -2759,7 +2816,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
|
||||
while (count == 0 && !retval) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
m = comedi_buf_read_n_available(s);
|
||||
m = _comedi_buf_read_n_available(s);
|
||||
n = min_t(size_t, m, nbytes);
|
||||
|
||||
if (n == 0) {
|
||||
@@ -2799,8 +2856,8 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
|
||||
retval = -EFAULT;
|
||||
}
|
||||
|
||||
comedi_buf_read_alloc(s, n);
|
||||
comedi_buf_read_free(s, n);
|
||||
_comedi_buf_read_alloc(s, n);
|
||||
_comedi_buf_read_free(s, n);
|
||||
|
||||
count += n;
|
||||
nbytes -= n;
|
||||
@@ -2834,7 +2891,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
|
||||
s == new_s && new_s->async == async && s->busy == file &&
|
||||
!(async->cmd.flags & CMDF_WRITE) &&
|
||||
!comedi_is_subdevice_running(s) &&
|
||||
comedi_buf_read_n_available(s) == 0)
|
||||
_comedi_buf_read_n_available(s) == 0)
|
||||
do_become_nonbusy(dev, s);
|
||||
mutex_unlock(&dev->mutex);
|
||||
}
|
||||
@@ -3023,7 +3080,12 @@ static int compat_chaninfo(struct file *file, unsigned long arg)
|
||||
chaninfo.rangelist = compat_ptr(chaninfo32.rangelist);
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
err = do_chaninfo_ioctl(dev, &chaninfo);
|
||||
if (!dev->attached) {
|
||||
dev_dbg(dev->class_dev, "no driver attached\n");
|
||||
err = -ENODEV;
|
||||
} else {
|
||||
err = do_chaninfo_ioctl(dev, &chaninfo);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
return err;
|
||||
}
|
||||
@@ -3044,7 +3106,12 @@ static int compat_rangeinfo(struct file *file, unsigned long arg)
|
||||
rangeinfo.range_ptr = compat_ptr(rangeinfo32.range_ptr);
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
err = do_rangeinfo_ioctl(dev, &rangeinfo);
|
||||
if (!dev->attached) {
|
||||
dev_dbg(dev->class_dev, "no driver attached\n");
|
||||
err = -ENODEV;
|
||||
} else {
|
||||
err = do_rangeinfo_ioctl(dev, &rangeinfo);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
return err;
|
||||
}
|
||||
@@ -3120,7 +3187,12 @@ static int compat_cmd(struct file *file, unsigned long arg)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
rc = do_cmd_ioctl(dev, &cmd, ©, file);
|
||||
if (!dev->attached) {
|
||||
dev_dbg(dev->class_dev, "no driver attached\n");
|
||||
rc = -ENODEV;
|
||||
} else {
|
||||
rc = do_cmd_ioctl(dev, &cmd, ©, file);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
if (copy) {
|
||||
/* Special case: copy cmd back to user. */
|
||||
@@ -3145,7 +3217,12 @@ static int compat_cmdtest(struct file *file, unsigned long arg)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
rc = do_cmdtest_ioctl(dev, &cmd, ©, file);
|
||||
if (!dev->attached) {
|
||||
dev_dbg(dev->class_dev, "no driver attached\n");
|
||||
rc = -ENODEV;
|
||||
} else {
|
||||
rc = do_cmdtest_ioctl(dev, &cmd, ©, file);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
if (copy) {
|
||||
err = put_compat_cmd(compat_ptr(arg), &cmd);
|
||||
@@ -3205,7 +3282,12 @@ static int compat_insnlist(struct file *file, unsigned long arg)
|
||||
}
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
rc = do_insnlist_ioctl(dev, insns, insnlist32.n_insns, file);
|
||||
if (!dev->attached) {
|
||||
dev_dbg(dev->class_dev, "no driver attached\n");
|
||||
rc = -ENODEV;
|
||||
} else {
|
||||
rc = do_insnlist_ioctl(dev, insns, insnlist32.n_insns, file);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
kfree(insns);
|
||||
return rc;
|
||||
@@ -3224,7 +3306,12 @@ static int compat_insn(struct file *file, unsigned long arg)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&dev->mutex);
|
||||
rc = do_insn_ioctl(dev, &insn, file);
|
||||
if (!dev->attached) {
|
||||
dev_dbg(dev->class_dev, "no driver attached\n");
|
||||
rc = -ENODEV;
|
||||
} else {
|
||||
rc = do_insn_ioctl(dev, &insn, file);
|
||||
}
|
||||
mutex_unlock(&dev->mutex);
|
||||
return rc;
|
||||
}
|
||||
@@ -3299,18 +3386,7 @@ static const struct file_operations comedi_fops = {
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
/**
|
||||
* comedi_event() - Handle events for asynchronous COMEDI command
|
||||
* @dev: COMEDI device.
|
||||
* @s: COMEDI subdevice.
|
||||
* Context: in_interrupt() (usually), @s->spin_lock spin-lock not held.
|
||||
*
|
||||
* If an asynchronous COMEDI command is active on the subdevice, process
|
||||
* any %COMEDI_CB_... event flags that have been set, usually by an
|
||||
* interrupt handler. These may change the run state of the asynchronous
|
||||
* command, wake a task, and/or send a %SIGIO signal.
|
||||
*/
|
||||
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
|
||||
void _comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
unsigned int events;
|
||||
@@ -3346,6 +3422,25 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
|
||||
if (si_code)
|
||||
kill_fasync(&dev->async_queue, SIGIO, si_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_event() - Handle events for asynchronous COMEDI command
|
||||
* @dev: COMEDI device.
|
||||
* @s: COMEDI subdevice.
|
||||
* Context: in_interrupt() (usually), @s->spin_lock spin-lock not held.
|
||||
*
|
||||
* If an asynchronous COMEDI command is active on the subdevice, process
|
||||
* any %COMEDI_CB_... event flags that have been set, usually by an
|
||||
* interrupt handler. These may change the run state of the asynchronous
|
||||
* command, wake a task, and/or send a %SIGIO signal.
|
||||
*/
|
||||
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
|
||||
{
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
comedi_event(dev, s);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_event);
|
||||
|
||||
/* Note: the ->mutex is pre-locked on successful return */
|
||||
|
||||
@@ -36,6 +36,18 @@ struct comedi_buf_map *
|
||||
comedi_buf_map_from_subdev_get(struct comedi_subdevice *s);
|
||||
unsigned int comedi_buf_write_n_available(struct comedi_subdevice *s);
|
||||
unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s);
|
||||
unsigned int _comedi_buf_write_alloc(struct comedi_subdevice *s,
|
||||
unsigned int nbytes);
|
||||
unsigned int _comedi_buf_write_free(struct comedi_subdevice *s,
|
||||
unsigned int nbytes);
|
||||
unsigned int _comedi_buf_read_n_available(struct comedi_subdevice *s);
|
||||
unsigned int _comedi_buf_read_alloc(struct comedi_subdevice *s,
|
||||
unsigned int nbytes);
|
||||
unsigned int _comedi_buf_read_free(struct comedi_subdevice *s,
|
||||
unsigned int nbytes);
|
||||
void _comedi_inc_scan_progress(struct comedi_subdevice *s,
|
||||
unsigned int num_bytes);
|
||||
void _comedi_event(struct comedi_device *dev, struct comedi_subdevice *s);
|
||||
void comedi_device_cancel_all(struct comedi_device *dev);
|
||||
bool comedi_can_auto_free_spriv(struct comedi_subdevice *s);
|
||||
|
||||
|
||||
@@ -441,6 +441,13 @@ unsigned int comedi_bytes_per_scan_cmd(struct comedi_subdevice *s,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan_cmd);
|
||||
|
||||
static unsigned int _comedi_bytes_per_scan(struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_cmd *cmd = &s->async->cmd;
|
||||
|
||||
return comedi_bytes_per_scan_cmd(s, cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_bytes_per_scan() - Get length of asynchronous command "scan" in bytes
|
||||
* @s: COMEDI subdevice.
|
||||
@@ -458,9 +465,16 @@ EXPORT_SYMBOL_GPL(comedi_bytes_per_scan_cmd);
|
||||
*/
|
||||
unsigned int comedi_bytes_per_scan(struct comedi_subdevice *s)
|
||||
{
|
||||
struct comedi_cmd *cmd = &s->async->cmd;
|
||||
unsigned int num_bytes;
|
||||
|
||||
return comedi_bytes_per_scan_cmd(s, cmd);
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
num_bytes = _comedi_bytes_per_scan(s);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
/* Use nomimal, single sample scan length. */
|
||||
num_bytes = comedi_samples_to_bytes(s, 1);
|
||||
}
|
||||
return num_bytes;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_bytes_per_scan);
|
||||
|
||||
@@ -482,6 +496,17 @@ static unsigned int __comedi_nscans_left(struct comedi_subdevice *s,
|
||||
return nscans;
|
||||
}
|
||||
|
||||
static unsigned int _comedi_nscans_left(struct comedi_subdevice *s,
|
||||
unsigned int nscans)
|
||||
{
|
||||
if (nscans == 0) {
|
||||
unsigned int nbytes = _comedi_buf_read_n_available(s);
|
||||
|
||||
nscans = nbytes / _comedi_bytes_per_scan(s);
|
||||
}
|
||||
return __comedi_nscans_left(s, nscans);
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_nscans_left() - Return the number of scans left in the command
|
||||
* @s: COMEDI subdevice.
|
||||
@@ -499,25 +524,18 @@ static unsigned int __comedi_nscans_left(struct comedi_subdevice *s,
|
||||
unsigned int comedi_nscans_left(struct comedi_subdevice *s,
|
||||
unsigned int nscans)
|
||||
{
|
||||
if (nscans == 0) {
|
||||
unsigned int nbytes = comedi_buf_read_n_available(s);
|
||||
|
||||
nscans = nbytes / comedi_bytes_per_scan(s);
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nscans = _comedi_nscans_left(s, nscans);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nscans = 0;
|
||||
}
|
||||
return __comedi_nscans_left(s, nscans);
|
||||
return nscans;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_nscans_left);
|
||||
|
||||
/**
|
||||
* comedi_nsamples_left() - Return the number of samples left in the command
|
||||
* @s: COMEDI subdevice.
|
||||
* @nsamples: The expected number of samples.
|
||||
*
|
||||
* Returns the number of samples remaining to complete the command, or the
|
||||
* specified expected number of samples (@nsamples), whichever is fewer.
|
||||
*/
|
||||
unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
|
||||
unsigned int nsamples)
|
||||
static unsigned int _comedi_nsamples_left(struct comedi_subdevice *s,
|
||||
unsigned int nsamples)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
struct comedi_cmd *cmd = &async->cmd;
|
||||
@@ -538,24 +556,34 @@ unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
|
||||
return samples_left;
|
||||
return nsamples;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_nsamples_left);
|
||||
|
||||
/**
|
||||
* comedi_inc_scan_progress() - Update scan progress in asynchronous command
|
||||
* comedi_nsamples_left() - Return the number of samples left in the command
|
||||
* @s: COMEDI subdevice.
|
||||
* @num_bytes: Amount of data in bytes to increment scan progress.
|
||||
* @nsamples: The expected number of samples.
|
||||
*
|
||||
* Increments the scan progress by the number of bytes specified by @num_bytes.
|
||||
* If the scan progress reaches or exceeds the scan length in bytes, reduce
|
||||
* it modulo the scan length in bytes and set the "end of scan" asynchronous
|
||||
* event flag (%COMEDI_CB_EOS) to be processed later.
|
||||
* Returns the number of samples remaining to complete the command, or the
|
||||
* specified expected number of samples (@nsamples), whichever is fewer.
|
||||
*/
|
||||
void comedi_inc_scan_progress(struct comedi_subdevice *s,
|
||||
unsigned int num_bytes)
|
||||
unsigned int comedi_nsamples_left(struct comedi_subdevice *s,
|
||||
unsigned int nsamples)
|
||||
{
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
nsamples = _comedi_nsamples_left(s, nsamples);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
nsamples = 0;
|
||||
}
|
||||
return nsamples;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_nsamples_left);
|
||||
|
||||
void _comedi_inc_scan_progress(struct comedi_subdevice *s,
|
||||
unsigned int num_bytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
struct comedi_cmd *cmd = &async->cmd;
|
||||
unsigned int scan_length = comedi_bytes_per_scan(s);
|
||||
unsigned int scan_length = _comedi_bytes_per_scan(s);
|
||||
|
||||
/* track the 'cur_chan' for non-SDF_PACKED subdevices */
|
||||
if (!(s->subdev_flags & SDF_PACKED)) {
|
||||
@@ -576,8 +604,43 @@ void comedi_inc_scan_progress(struct comedi_subdevice *s,
|
||||
async->events |= COMEDI_CB_EOS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_inc_scan_progress() - Update scan progress in asynchronous command
|
||||
* @s: COMEDI subdevice.
|
||||
* @num_bytes: Amount of data in bytes to increment scan progress.
|
||||
*
|
||||
* Increments the scan progress by the number of bytes specified by @num_bytes.
|
||||
* If the scan progress reaches or exceeds the scan length in bytes, reduce
|
||||
* it modulo the scan length in bytes and set the "end of scan" asynchronous
|
||||
* event flag (%COMEDI_CB_EOS) to be processed later.
|
||||
*/
|
||||
void comedi_inc_scan_progress(struct comedi_subdevice *s,
|
||||
unsigned int num_bytes)
|
||||
{
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
_comedi_inc_scan_progress(s, num_bytes);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_inc_scan_progress);
|
||||
|
||||
static unsigned int _comedi_handle_events(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s)
|
||||
{
|
||||
unsigned int events = s->async->events;
|
||||
|
||||
if (events == 0)
|
||||
return events;
|
||||
|
||||
if ((events & COMEDI_CB_CANCEL_MASK) && s->cancel)
|
||||
s->cancel(dev, s);
|
||||
|
||||
_comedi_event(dev, s);
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_handle_events() - Handle events and possibly stop acquisition
|
||||
* @dev: COMEDI device.
|
||||
@@ -597,16 +660,14 @@ EXPORT_SYMBOL_GPL(comedi_inc_scan_progress);
|
||||
unsigned int comedi_handle_events(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s)
|
||||
{
|
||||
unsigned int events = s->async->events;
|
||||
|
||||
if (events == 0)
|
||||
return events;
|
||||
|
||||
if ((events & COMEDI_CB_CANCEL_MASK) && s->cancel)
|
||||
s->cancel(dev, s);
|
||||
|
||||
comedi_event(dev, s);
|
||||
unsigned int events;
|
||||
|
||||
if (comedi_get_is_subdevice_running(s)) {
|
||||
events = _comedi_handle_events(dev, s);
|
||||
comedi_put_is_subdevice_running(s);
|
||||
} else {
|
||||
events = 0;
|
||||
}
|
||||
return events;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_handle_events);
|
||||
@@ -677,6 +738,7 @@ static int __comedi_device_postconfig_async(struct comedi_device *dev,
|
||||
return -ENOMEM;
|
||||
|
||||
init_waitqueue_head(&async->wait_head);
|
||||
init_completion(&async->run_complete);
|
||||
s->async = async;
|
||||
|
||||
async->max_bufsize = comedi_default_buf_maxsize_kb * 1024;
|
||||
|
||||
@@ -77,19 +77,17 @@ static int dev_8255_attach(struct comedi_device *dev,
|
||||
* base address of the chip.
|
||||
*/
|
||||
ret = __comedi_request_region(dev, iobase, I8255_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = subdev_8255_io_init(dev, s, iobase);
|
||||
if (ret) {
|
||||
/*
|
||||
* Release the I/O port region here, as the
|
||||
* "detach" handler cannot find it.
|
||||
*/
|
||||
release_region(iobase, I8255_SIZE);
|
||||
s->type = COMEDI_SUBD_UNUSED;
|
||||
} else {
|
||||
ret = subdev_8255_io_init(dev, s, iobase);
|
||||
if (ret) {
|
||||
/*
|
||||
* Release the I/O port region here, as the
|
||||
* "detach" handler cannot find it.
|
||||
*/
|
||||
release_region(iobase, I8255_SIZE);
|
||||
s->type = COMEDI_SUBD_UNUSED;
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -249,9 +249,6 @@ static int c6xdigio_attach(struct comedi_device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Make sure that PnP ports get activated */
|
||||
pnp_register_driver(&c6xdigio_pnp_driver);
|
||||
|
||||
s = &dev->subdevices[0];
|
||||
/* pwm output subdevice */
|
||||
s->type = COMEDI_SUBD_PWM;
|
||||
@@ -278,19 +275,46 @@ static int c6xdigio_attach(struct comedi_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void c6xdigio_detach(struct comedi_device *dev)
|
||||
{
|
||||
comedi_legacy_detach(dev);
|
||||
pnp_unregister_driver(&c6xdigio_pnp_driver);
|
||||
}
|
||||
|
||||
static struct comedi_driver c6xdigio_driver = {
|
||||
.driver_name = "c6xdigio",
|
||||
.module = THIS_MODULE,
|
||||
.attach = c6xdigio_attach,
|
||||
.detach = c6xdigio_detach,
|
||||
.detach = comedi_legacy_detach,
|
||||
};
|
||||
module_comedi_driver(c6xdigio_driver);
|
||||
|
||||
static bool c6xdigio_pnp_registered = false;
|
||||
|
||||
static int __init c6xdigio_module_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = comedi_driver_register(&c6xdigio_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PNP)) {
|
||||
/* Try to activate the PnP ports */
|
||||
ret = pnp_register_driver(&c6xdigio_pnp_driver);
|
||||
if (ret) {
|
||||
pr_warn("failed to register pnp driver - err %d\n",
|
||||
ret);
|
||||
ret = 0; /* ignore the error. */
|
||||
} else {
|
||||
c6xdigio_pnp_registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(c6xdigio_module_init);
|
||||
|
||||
static void __exit c6xdigio_module_exit(void)
|
||||
{
|
||||
if (c6xdigio_pnp_registered)
|
||||
pnp_unregister_driver(&c6xdigio_pnp_driver);
|
||||
comedi_driver_unregister(&c6xdigio_driver);
|
||||
}
|
||||
module_exit(c6xdigio_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Comedi https://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi driver for the C6x_DIGIO DSP daughter card");
|
||||
|
||||
@@ -205,7 +205,7 @@ static int do_dev_config(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||
snprintf(file, sizeof(file), "/dev/comedi%d", minor);
|
||||
file[sizeof(file) - 1] = 0;
|
||||
|
||||
d = comedi_open(file);
|
||||
d = comedi_open_from(file, dev->minor);
|
||||
|
||||
if (!d) {
|
||||
dev_err(dev->class_dev,
|
||||
@@ -326,7 +326,7 @@ static void bonding_detach(struct comedi_device *dev)
|
||||
if (!bdev)
|
||||
continue;
|
||||
if (!test_and_set_bit(bdev->minor, devs_closed))
|
||||
comedi_close(bdev->dev);
|
||||
comedi_close_from(bdev->dev, dev->minor);
|
||||
kfree(bdev);
|
||||
}
|
||||
kfree(devpriv->devs);
|
||||
|
||||
@@ -67,6 +67,11 @@
|
||||
#define MULTIQ3_TRSFRCNTR_OL 0x10 /* xfer CNTR to OL (x and y) */
|
||||
#define MULTIQ3_EFLAG_RESET 0x06 /* reset E bit of flag reg */
|
||||
|
||||
/*
|
||||
* Limit on the number of optional encoder channels
|
||||
*/
|
||||
#define MULTIQ3_MAX_ENC_CHANS 8
|
||||
|
||||
static void multiq3_set_ctrl(struct comedi_device *dev, unsigned int bits)
|
||||
{
|
||||
/*
|
||||
@@ -312,6 +317,10 @@ static int multiq3_attach(struct comedi_device *dev,
|
||||
s->insn_read = multiq3_encoder_insn_read;
|
||||
s->insn_config = multiq3_encoder_insn_config;
|
||||
|
||||
/* sanity check for number of encoder channels */
|
||||
if (s->n_chan > MULTIQ3_MAX_ENC_CHANS)
|
||||
s->n_chan = MULTIQ3_MAX_ENC_CHANS;
|
||||
|
||||
for (i = 0; i < s->n_chan; i++)
|
||||
multiq3_encoder_reset(dev, i);
|
||||
|
||||
|
||||
@@ -1111,10 +1111,9 @@ static void pcl818_detach(struct comedi_device *dev)
|
||||
{
|
||||
struct pcl818_private *devpriv = dev->private;
|
||||
|
||||
if (devpriv) {
|
||||
pcl818_ai_cancel(dev, dev->read_subdev);
|
||||
if (devpriv)
|
||||
pcl818_reset(dev);
|
||||
}
|
||||
|
||||
pcl818_free_dma(dev);
|
||||
comedi_legacy_detach(dev);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/bitmap.h>
|
||||
|
||||
#include <linux/comedi.h>
|
||||
#include <linux/comedi/comedidev.h>
|
||||
@@ -24,7 +25,104 @@ MODULE_AUTHOR("David Schleef <ds@schleef.org>");
|
||||
MODULE_DESCRIPTION("Comedi kernel library");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct comedi_device *comedi_open(const char *filename)
|
||||
static DEFINE_MUTEX(kcomedilib_to_from_lock);
|
||||
|
||||
/*
|
||||
* Row index is the "to" node, column index is the "from" node, element value
|
||||
* is the number of links from the "from" node to the "to" node.
|
||||
*/
|
||||
static unsigned char
|
||||
kcomedilib_to_from[COMEDI_NUM_BOARD_MINORS][COMEDI_NUM_BOARD_MINORS];
|
||||
|
||||
static bool kcomedilib_set_link_from_to(unsigned int from, unsigned int to)
|
||||
{
|
||||
DECLARE_BITMAP(destinations[2], COMEDI_NUM_BOARD_MINORS);
|
||||
unsigned int cur = 0;
|
||||
bool okay = true;
|
||||
|
||||
/*
|
||||
* Allow "from" node to be out of range (no loop checking),
|
||||
* but require "to" node to be in range.
|
||||
*/
|
||||
if (to >= COMEDI_NUM_BOARD_MINORS)
|
||||
return false;
|
||||
if (from >= COMEDI_NUM_BOARD_MINORS)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Check that kcomedilib_to_from[to][from] can be made non-zero
|
||||
* without creating a loop.
|
||||
*
|
||||
* Termination of the loop-testing code relies on the assumption that
|
||||
* kcomedilib_to_from[][] does not contain any loops.
|
||||
*
|
||||
* Start with a set destinations set containing "from" as the only
|
||||
* element and work backwards looking for loops.
|
||||
*/
|
||||
bitmap_zero(destinations[cur], COMEDI_NUM_BOARD_MINORS);
|
||||
set_bit(from, destinations[cur]);
|
||||
mutex_lock(&kcomedilib_to_from_lock);
|
||||
do {
|
||||
unsigned int next = 1 - cur;
|
||||
unsigned int t = 0;
|
||||
|
||||
if (test_bit(to, destinations[cur])) {
|
||||
/* Loop detected. */
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
/* Create next set of destinations. */
|
||||
bitmap_zero(destinations[next], COMEDI_NUM_BOARD_MINORS);
|
||||
while ((t = find_next_bit(destinations[cur],
|
||||
COMEDI_NUM_BOARD_MINORS,
|
||||
t)) < COMEDI_NUM_BOARD_MINORS) {
|
||||
unsigned int f;
|
||||
|
||||
for (f = 0; f < COMEDI_NUM_BOARD_MINORS; f++) {
|
||||
if (kcomedilib_to_from[t][f])
|
||||
set_bit(f, destinations[next]);
|
||||
}
|
||||
t++;
|
||||
}
|
||||
cur = next;
|
||||
} while (!bitmap_empty(destinations[cur], COMEDI_NUM_BOARD_MINORS));
|
||||
if (okay) {
|
||||
/* Allow a maximum of 255 links from "from" to "to". */
|
||||
if (kcomedilib_to_from[to][from] < 255)
|
||||
kcomedilib_to_from[to][from]++;
|
||||
else
|
||||
okay = false;
|
||||
}
|
||||
mutex_unlock(&kcomedilib_to_from_lock);
|
||||
return okay;
|
||||
}
|
||||
|
||||
static void kcomedilib_clear_link_from_to(unsigned int from, unsigned int to)
|
||||
{
|
||||
if (to < COMEDI_NUM_BOARD_MINORS && from < COMEDI_NUM_BOARD_MINORS) {
|
||||
mutex_lock(&kcomedilib_to_from_lock);
|
||||
if (kcomedilib_to_from[to][from])
|
||||
kcomedilib_to_from[to][from]--;
|
||||
mutex_unlock(&kcomedilib_to_from_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* comedi_open_from() - Open a COMEDI device from the kernel with loop checks
|
||||
* @filename: Fake pathname of the form "/dev/comediN".
|
||||
* @from: Device number it is being opened from (if in range).
|
||||
*
|
||||
* Converts @filename to a COMEDI device number and "opens" it if it exists
|
||||
* and is attached to a low-level COMEDI driver.
|
||||
*
|
||||
* If @from is in range, refuse to open the device if doing so would form a
|
||||
* loop of devices opening each other. There is also a limit of 255 on the
|
||||
* number of concurrent opens from one device to another.
|
||||
*
|
||||
* Return: A pointer to the COMEDI device on success.
|
||||
* Return %NULL on failure.
|
||||
*/
|
||||
struct comedi_device *comedi_open_from(const char *filename, int from)
|
||||
{
|
||||
struct comedi_device *dev, *retval = NULL;
|
||||
unsigned int minor;
|
||||
@@ -43,7 +141,7 @@ struct comedi_device *comedi_open(const char *filename)
|
||||
return NULL;
|
||||
|
||||
down_read(&dev->attach_lock);
|
||||
if (dev->attached)
|
||||
if (dev->attached && kcomedilib_set_link_from_to(from, minor))
|
||||
retval = dev;
|
||||
else
|
||||
retval = NULL;
|
||||
@@ -54,14 +152,26 @@ struct comedi_device *comedi_open(const char *filename)
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_open);
|
||||
EXPORT_SYMBOL_GPL(comedi_open_from);
|
||||
|
||||
int comedi_close(struct comedi_device *dev)
|
||||
/**
|
||||
* comedi_close_from() - Close a COMEDI device from the kernel with loop checks
|
||||
* @dev: COMEDI device.
|
||||
* @from: Device number it was opened from (if in range).
|
||||
*
|
||||
* Closes a COMEDI device previously opened by comedi_open_from().
|
||||
*
|
||||
* If @from is in range, it should be match the one used by comedi_open_from().
|
||||
*
|
||||
* Returns: 0
|
||||
*/
|
||||
int comedi_close_from(struct comedi_device *dev, int from)
|
||||
{
|
||||
kcomedilib_clear_link_from_to(from, dev->minor);
|
||||
comedi_dev_put(dev);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_close);
|
||||
EXPORT_SYMBOL_GPL(comedi_close_from);
|
||||
|
||||
static int comedi_do_insn(struct comedi_device *dev,
|
||||
struct comedi_insn *insn,
|
||||
|
||||
@@ -135,7 +135,7 @@ static int eisa_bus_uevent(const struct device *dev, struct kobj_uevent_env *env
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bus_type eisa_bus_type = {
|
||||
const struct bus_type eisa_bus_type = {
|
||||
.name = "eisa",
|
||||
.match = eisa_bus_match,
|
||||
.uevent = eisa_bus_uevent,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018-2019, Intel Corporation
|
||||
* Copyright (C) 2025, Altera Corporation
|
||||
*/
|
||||
|
||||
#include <linux/arm-smccc.h>
|
||||
@@ -14,11 +15,9 @@
|
||||
#include <linux/firmware/intel/stratix10-svc-client.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#define RSU_STATE_MASK GENMASK_ULL(31, 0)
|
||||
#define RSU_VERSION_MASK GENMASK_ULL(63, 32)
|
||||
#define RSU_ERROR_LOCATION_MASK GENMASK_ULL(31, 0)
|
||||
#define RSU_ERROR_DETAIL_MASK GENMASK_ULL(63, 32)
|
||||
#define RSU_ERASE_SIZE_MASK GENMASK_ULL(63, 32)
|
||||
#define RSU_DCMF0_MASK GENMASK_ULL(31, 0)
|
||||
#define RSU_DCMF1_MASK GENMASK_ULL(63, 32)
|
||||
#define RSU_DCMF2_MASK GENMASK_ULL(31, 0)
|
||||
@@ -35,7 +34,8 @@
|
||||
#define INVALID_DCMF_STATUS 0xFFFFFFFF
|
||||
#define INVALID_SPT_ADDRESS 0x0
|
||||
|
||||
#define RSU_GET_SPT_CMD 0x5A
|
||||
#define RSU_RETRY_SLEEP_MS (1U)
|
||||
#define RSU_ASYNC_MSG_RETRY (3U)
|
||||
#define RSU_GET_SPT_RESP_LEN (4 * sizeof(unsigned int))
|
||||
|
||||
typedef void (*rsu_callback)(struct stratix10_svc_client *client,
|
||||
@@ -64,7 +64,6 @@ typedef void (*rsu_callback)(struct stratix10_svc_client *client,
|
||||
* @max_retry: the preset max retry value
|
||||
* @spt0_address: address of spt0
|
||||
* @spt1_address: address of spt1
|
||||
* @get_spt_response_buf: response from sdm for get_spt command
|
||||
*/
|
||||
struct stratix10_rsu_priv {
|
||||
struct stratix10_svc_chan *chan;
|
||||
@@ -99,47 +98,32 @@ struct stratix10_rsu_priv {
|
||||
|
||||
unsigned long spt0_address;
|
||||
unsigned long spt1_address;
|
||||
|
||||
unsigned int *get_spt_response_buf;
|
||||
};
|
||||
|
||||
typedef void (*rsu_async_callback)(struct device *dev,
|
||||
struct stratix10_rsu_priv *priv, struct stratix10_svc_cb_data *data);
|
||||
|
||||
/**
|
||||
* rsu_status_callback() - Status callback from Intel Service Layer
|
||||
* @client: pointer to service client
|
||||
* rsu_async_status_callback() - Status callback from rsu_async_send()
|
||||
* @dev: pointer to device object
|
||||
* @priv: pointer to priv object
|
||||
* @data: pointer to callback data structure
|
||||
*
|
||||
* Callback from Intel service layer for RSU status request. Status is
|
||||
* only updated after a system reboot, so a get updated status call is
|
||||
* made during driver probe.
|
||||
* Callback from rsu_async_send() to get the system rsu error status.
|
||||
*/
|
||||
static void rsu_status_callback(struct stratix10_svc_client *client,
|
||||
struct stratix10_svc_cb_data *data)
|
||||
static void rsu_async_status_callback(struct device *dev,
|
||||
struct stratix10_rsu_priv *priv,
|
||||
struct stratix10_svc_cb_data *data)
|
||||
{
|
||||
struct stratix10_rsu_priv *priv = client->priv;
|
||||
struct arm_smccc_res *res = (struct arm_smccc_res *)data->kaddr1;
|
||||
struct arm_smccc_1_2_regs *res = (struct arm_smccc_1_2_regs *)data->kaddr1;
|
||||
|
||||
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);
|
||||
priv->status.fail_image = res->a1;
|
||||
priv->status.current_image = res->a0;
|
||||
priv->status.error_location =
|
||||
FIELD_GET(RSU_ERROR_LOCATION_MASK, res->a3);
|
||||
priv->status.error_details =
|
||||
FIELD_GET(RSU_ERROR_DETAIL_MASK, res->a3);
|
||||
} else {
|
||||
dev_err(client->dev, "COMMAND_RSU_STATUS returned 0x%lX\n",
|
||||
res->a0);
|
||||
priv->status.version = 0;
|
||||
priv->status.state = 0;
|
||||
priv->status.fail_image = 0;
|
||||
priv->status.current_image = 0;
|
||||
priv->status.error_location = 0;
|
||||
priv->status.error_details = 0;
|
||||
}
|
||||
|
||||
complete(&priv->completion);
|
||||
priv->status.current_image = res->a2;
|
||||
priv->status.fail_image = res->a3;
|
||||
priv->status.state = res->a4;
|
||||
priv->status.version = res->a5;
|
||||
priv->status.error_location = res->a7;
|
||||
priv->status.error_details = res->a8;
|
||||
priv->retry_counter = res->a9;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,32 +147,6 @@ static void rsu_command_callback(struct stratix10_svc_client *client,
|
||||
complete(&priv->completion);
|
||||
}
|
||||
|
||||
/**
|
||||
* rsu_retry_callback() - Callback from Intel service layer for getting
|
||||
* the current image's retry counter from the firmware
|
||||
* @client: pointer to client
|
||||
* @data: pointer to callback data structure
|
||||
*
|
||||
* Callback from Intel service layer for retry counter, which is used by
|
||||
* user to know how many times the images is still allowed to reload
|
||||
* itself before giving up and starting RSU fail-over flow.
|
||||
*/
|
||||
static void rsu_retry_callback(struct stratix10_svc_client *client,
|
||||
struct stratix10_svc_cb_data *data)
|
||||
{
|
||||
struct stratix10_rsu_priv *priv = client->priv;
|
||||
unsigned int *counter = (unsigned int *)data->kaddr1;
|
||||
|
||||
if (data->status == BIT(SVC_STATUS_OK))
|
||||
priv->retry_counter = *counter;
|
||||
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",
|
||||
BIT(data->status));
|
||||
|
||||
complete(&priv->completion);
|
||||
}
|
||||
|
||||
/**
|
||||
* rsu_max_retry_callback() - Callback from Intel service layer for getting
|
||||
@@ -270,34 +228,19 @@ static void rsu_dcmf_status_callback(struct stratix10_svc_client *client,
|
||||
complete(&priv->completion);
|
||||
}
|
||||
|
||||
static void rsu_get_spt_callback(struct stratix10_svc_client *client,
|
||||
struct stratix10_svc_cb_data *data)
|
||||
/**
|
||||
* rsu_async_get_spt_table_callback() - Callback to be used by the rsu_async_send()
|
||||
* to retrieve the SPT table information.
|
||||
* @dev: pointer to device object
|
||||
* @priv: pointer to priv object
|
||||
* @data: pointer to callback data structure
|
||||
*/
|
||||
static void rsu_async_get_spt_table_callback(struct device *dev,
|
||||
struct stratix10_rsu_priv *priv,
|
||||
struct stratix10_svc_cb_data *data)
|
||||
{
|
||||
struct stratix10_rsu_priv *priv = client->priv;
|
||||
unsigned long *mbox_err = (unsigned long *)data->kaddr1;
|
||||
unsigned long *resp_len = (unsigned long *)data->kaddr2;
|
||||
|
||||
if (data->status != BIT(SVC_STATUS_OK) || (*mbox_err) ||
|
||||
(*resp_len != RSU_GET_SPT_RESP_LEN))
|
||||
goto error;
|
||||
|
||||
priv->spt0_address = priv->get_spt_response_buf[0];
|
||||
priv->spt0_address <<= 32;
|
||||
priv->spt0_address |= priv->get_spt_response_buf[1];
|
||||
|
||||
priv->spt1_address = priv->get_spt_response_buf[2];
|
||||
priv->spt1_address <<= 32;
|
||||
priv->spt1_address |= priv->get_spt_response_buf[3];
|
||||
|
||||
goto complete;
|
||||
|
||||
error:
|
||||
dev_err(client->dev, "failed to get SPTs\n");
|
||||
|
||||
complete:
|
||||
stratix10_svc_free_memory(priv->chan, priv->get_spt_response_buf);
|
||||
priv->get_spt_response_buf = NULL;
|
||||
complete(&priv->completion);
|
||||
priv->spt0_address = *((unsigned long *)data->kaddr1);
|
||||
priv->spt1_address = *((unsigned long *)data->kaddr2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,14 +272,6 @@ static int rsu_send_msg(struct stratix10_rsu_priv *priv,
|
||||
if (arg)
|
||||
msg.arg[0] = arg;
|
||||
|
||||
if (command == COMMAND_MBOX_SEND_CMD) {
|
||||
msg.arg[1] = 0;
|
||||
msg.payload = NULL;
|
||||
msg.payload_length = 0;
|
||||
msg.payload_output = priv->get_spt_response_buf;
|
||||
msg.payload_length_output = RSU_GET_SPT_RESP_LEN;
|
||||
}
|
||||
|
||||
ret = stratix10_svc_send(priv->chan, &msg);
|
||||
if (ret < 0)
|
||||
goto status_done;
|
||||
@@ -362,6 +297,95 @@ status_done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* soc64_async_callback() - Callback from Intel service layer for async requests
|
||||
* @ptr: pointer to the completion object
|
||||
*/
|
||||
static void soc64_async_callback(void *ptr)
|
||||
{
|
||||
if (ptr)
|
||||
complete(ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* rsu_send_async_msg() - send an async message to Intel service layer
|
||||
* @dev: pointer to device object
|
||||
* @priv: pointer to rsu private data
|
||||
* @command: RSU status or update command
|
||||
* @arg: the request argument, notify status
|
||||
* @callback: function pointer for the callback (status or update)
|
||||
*/
|
||||
static int rsu_send_async_msg(struct device *dev, struct stratix10_rsu_priv *priv,
|
||||
enum stratix10_svc_command_code command,
|
||||
unsigned long arg,
|
||||
rsu_async_callback callback)
|
||||
{
|
||||
struct stratix10_svc_client_msg msg = {0};
|
||||
struct stratix10_svc_cb_data data = {0};
|
||||
struct completion completion;
|
||||
int status, index, ret;
|
||||
void *handle = NULL;
|
||||
|
||||
msg.command = command;
|
||||
msg.arg[0] = arg;
|
||||
|
||||
init_completion(&completion);
|
||||
|
||||
for (index = 0; index < RSU_ASYNC_MSG_RETRY; index++) {
|
||||
status = stratix10_svc_async_send(priv->chan, &msg,
|
||||
&handle, soc64_async_callback,
|
||||
&completion);
|
||||
if (status == 0)
|
||||
break;
|
||||
dev_warn(dev, "Failed to send async message\n");
|
||||
msleep(RSU_RETRY_SLEEP_MS);
|
||||
}
|
||||
|
||||
if (status && !handle) {
|
||||
dev_err(dev, "Failed to send async message\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_io_timeout(&completion, RSU_TIMEOUT);
|
||||
if (ret > 0)
|
||||
dev_dbg(dev, "Received async interrupt\n");
|
||||
else if (ret == 0)
|
||||
dev_dbg(dev, "Timeout occurred. Trying to poll the response\n");
|
||||
|
||||
for (index = 0; index < RSU_ASYNC_MSG_RETRY; index++) {
|
||||
status = stratix10_svc_async_poll(priv->chan, handle, &data);
|
||||
if (status == -EAGAIN) {
|
||||
dev_dbg(dev, "Async message is still in progress\n");
|
||||
} else if (status < 0) {
|
||||
dev_alert(dev, "Failed to poll async message\n");
|
||||
ret = -ETIMEDOUT;
|
||||
} else if (status == 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
msleep(RSU_RETRY_SLEEP_MS);
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to get async response\n");
|
||||
goto status_done;
|
||||
}
|
||||
|
||||
if (data.status == 0) {
|
||||
ret = 0;
|
||||
if (callback)
|
||||
callback(dev, priv, &data);
|
||||
} else {
|
||||
dev_err(dev, "%s returned 0x%x from SDM\n", __func__,
|
||||
data.status);
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
status_done:
|
||||
stratix10_svc_async_done(priv->chan, handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This driver exposes some optional features of the Intel Stratix 10 SoC FPGA.
|
||||
* The sysfs interfaces exposed here are FPGA Remote System Update (RSU)
|
||||
@@ -454,8 +478,7 @@ static ssize_t max_retry_show(struct device *dev,
|
||||
if (!priv)
|
||||
return -ENODEV;
|
||||
|
||||
return scnprintf(buf, sizeof(priv->max_retry),
|
||||
"0x%08x\n", priv->max_retry);
|
||||
return sysfs_emit(buf, "0x%08x\n", priv->max_retry);
|
||||
}
|
||||
|
||||
static ssize_t dcmf0_show(struct device *dev,
|
||||
@@ -597,27 +620,20 @@ static ssize_t notify_store(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rsu_send_msg(priv, COMMAND_RSU_NOTIFY,
|
||||
status, rsu_command_callback);
|
||||
ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_NOTIFY, status, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error, RSU notify returned %i\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* to get the updated state */
|
||||
ret = rsu_send_msg(priv, COMMAND_RSU_STATUS,
|
||||
0, rsu_status_callback);
|
||||
ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_STATUS, 0,
|
||||
rsu_async_status_callback);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error, getting RSU status %i\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error, getting RSU retry %i\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -632,7 +648,7 @@ static ssize_t spt0_address_show(struct device *dev,
|
||||
if (priv->spt0_address == INVALID_SPT_ADDRESS)
|
||||
return -EIO;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt0_address);
|
||||
return sysfs_emit(buf, "0x%08lx\n", priv->spt0_address);
|
||||
}
|
||||
|
||||
static ssize_t spt1_address_show(struct device *dev,
|
||||
@@ -646,7 +662,7 @@ static ssize_t spt1_address_show(struct device *dev,
|
||||
if (priv->spt1_address == INVALID_SPT_ADDRESS)
|
||||
return -EIO;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt1_address);
|
||||
return sysfs_emit(buf, "0x%08lx\n", priv->spt1_address);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(current_image);
|
||||
@@ -737,12 +753,19 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(priv->chan);
|
||||
}
|
||||
|
||||
ret = stratix10_svc_add_async_client(priv->chan, false);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add async client\n");
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
init_completion(&priv->completion);
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
/* get the initial state from firmware */
|
||||
ret = rsu_send_msg(priv, COMMAND_RSU_STATUS,
|
||||
0, rsu_status_callback);
|
||||
ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_STATUS, 0,
|
||||
rsu_async_status_callback);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error, getting RSU status %i\n", ret);
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
@@ -763,12 +786,6 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
}
|
||||
|
||||
ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error, getting RSU retry %i\n", ret);
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
}
|
||||
|
||||
ret = rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0,
|
||||
rsu_max_retry_callback);
|
||||
if (ret) {
|
||||
@@ -776,18 +793,12 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
}
|
||||
|
||||
priv->get_spt_response_buf =
|
||||
stratix10_svc_allocate_memory(priv->chan, RSU_GET_SPT_RESP_LEN);
|
||||
|
||||
if (IS_ERR(priv->get_spt_response_buf)) {
|
||||
dev_err(dev, "failed to allocate get spt buffer\n");
|
||||
} else {
|
||||
ret = rsu_send_msg(priv, COMMAND_MBOX_SEND_CMD,
|
||||
RSU_GET_SPT_CMD, rsu_get_spt_callback);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error, getting SPT table %i\n", ret);
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
}
|
||||
ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_GET_SPT_TABLE, 0,
|
||||
rsu_async_get_spt_table_callback);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error, getting SPT table %i\n", ret);
|
||||
stratix10_svc_free_channel(priv->chan);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2017-2018, Intel Corporation
|
||||
* Copyright (C) 2025, Altera Corporation
|
||||
*/
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/genalloc.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/kthread.h>
|
||||
@@ -34,7 +38,7 @@
|
||||
* timeout is set to 30 seconds (30 * 1000) at Intel Stratix10 SoC.
|
||||
*/
|
||||
#define SVC_NUM_DATA_IN_FIFO 32
|
||||
#define SVC_NUM_CHANNEL 3
|
||||
#define SVC_NUM_CHANNEL 4
|
||||
#define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS 200
|
||||
#define FPGA_CONFIG_STATUS_TIMEOUT_SEC 30
|
||||
#define BYTE_TO_WORD_SIZE 4
|
||||
@@ -43,6 +47,55 @@
|
||||
#define STRATIX10_RSU "stratix10-rsu"
|
||||
#define INTEL_FCS "intel-fcs"
|
||||
|
||||
/* Maximum number of SDM client IDs. */
|
||||
#define MAX_SDM_CLIENT_IDS 16
|
||||
/* Client ID for SIP Service Version 1. */
|
||||
#define SIP_SVC_V1_CLIENT_ID 0x1
|
||||
/* Maximum number of SDM job IDs. */
|
||||
#define MAX_SDM_JOB_IDS 16
|
||||
/* Number of bits used for asynchronous transaction hashing. */
|
||||
#define ASYNC_TRX_HASH_BITS 3
|
||||
/*
|
||||
* Total number of transaction IDs, which is a combination of
|
||||
* client ID and job ID.
|
||||
*/
|
||||
#define TOTAL_TRANSACTION_IDS \
|
||||
(MAX_SDM_CLIENT_IDS * MAX_SDM_JOB_IDS)
|
||||
|
||||
/* Minimum major version of the ATF for Asynchronous transactions. */
|
||||
#define ASYNC_ATF_MINIMUM_MAJOR_VERSION 0x3
|
||||
/* Minimum minor version of the ATF for Asynchronous transactions.*/
|
||||
#define ASYNC_ATF_MINIMUM_MINOR_VERSION 0x0
|
||||
|
||||
/* Job ID field in the transaction ID */
|
||||
#define STRATIX10_JOB_FIELD GENMASK(3, 0)
|
||||
/* Client ID field in the transaction ID */
|
||||
#define STRATIX10_CLIENT_FIELD GENMASK(7, 4)
|
||||
/* Transaction ID mask for Stratix10 service layer */
|
||||
#define STRATIX10_TRANS_ID_FIELD GENMASK(7, 0)
|
||||
|
||||
/* Macro to extract the job ID from a transaction ID. */
|
||||
#define STRATIX10_GET_JOBID(transaction_id) \
|
||||
(FIELD_GET(STRATIX10_JOB_FIELD, transaction_id))
|
||||
/* Macro to set the job ID in a transaction ID. */
|
||||
#define STRATIX10_SET_JOBID(jobid) \
|
||||
(FIELD_PREP(STRATIX10_JOB_FIELD, jobid))
|
||||
/* Macro to set the client ID in a transaction ID. */
|
||||
#define STRATIX10_SET_CLIENTID(clientid) \
|
||||
(FIELD_PREP(STRATIX10_CLIENT_FIELD, clientid))
|
||||
/* Macro to set a transaction ID using a client ID and a job ID. */
|
||||
#define STRATIX10_SET_TRANSACTIONID(clientid, jobid) \
|
||||
(STRATIX10_SET_CLIENTID(clientid) | STRATIX10_SET_JOBID(jobid))
|
||||
/* Macro to set a transaction ID for SIP SMC Async transactions */
|
||||
#define STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(transaction_id) \
|
||||
(FIELD_PREP(STRATIX10_TRANS_ID_FIELD, transaction_id))
|
||||
|
||||
/* 10-bit mask for extracting the SDM status code */
|
||||
#define STRATIX10_SDM_STATUS_MASK GENMASK(9, 0)
|
||||
/* Macro to get the SDM mailbox error status */
|
||||
#define STRATIX10_GET_SDM_STATUS_CODE(status) \
|
||||
(FIELD_GET(STRATIX10_SDM_STATUS_MASK, status))
|
||||
|
||||
typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long,
|
||||
unsigned long, unsigned long, unsigned long,
|
||||
unsigned long, unsigned long,
|
||||
@@ -52,6 +105,7 @@ struct stratix10_svc_chan;
|
||||
/**
|
||||
* struct stratix10_svc - svc private data
|
||||
* @stratix10_svc_rsu: pointer to stratix10 RSU device
|
||||
* @intel_svc_fcs: pointer to the FCS device
|
||||
*/
|
||||
struct stratix10_svc {
|
||||
struct platform_device *stratix10_svc_rsu;
|
||||
@@ -63,7 +117,7 @@ struct stratix10_svc {
|
||||
* @sync_complete: state for a completion
|
||||
* @addr: physical address of shared memory block
|
||||
* @size: size of shared memory block
|
||||
* @invoke_fn: function to issue secure monitor or hypervisor call
|
||||
* @invoke_fn: service clients to handle secure monitor or hypervisor calls
|
||||
*
|
||||
* This struct is used to save physical address and size of shared memory
|
||||
* block. The shared memory blocked is allocated by secure monitor software
|
||||
@@ -121,6 +175,74 @@ struct stratix10_svc_data {
|
||||
u64 arg[3];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct stratix10_svc_async_handler - Asynchronous handler for Stratix10
|
||||
* service layer
|
||||
* @transaction_id: Unique identifier for the transaction
|
||||
* @achan: Pointer to the asynchronous channel structure
|
||||
* @cb_arg: Argument to be passed to the callback function
|
||||
* @cb: Callback function to be called upon completion
|
||||
* @msg: Pointer to the client message structure
|
||||
* @next: Node in the hash list
|
||||
* @res: Response structure to store result from the secure firmware
|
||||
*
|
||||
* This structure is used to handle asynchronous transactions in the
|
||||
* Stratix10 service layer. It maintains the necessary information
|
||||
* for processing and completing asynchronous requests.
|
||||
*/
|
||||
|
||||
struct stratix10_svc_async_handler {
|
||||
u8 transaction_id;
|
||||
struct stratix10_async_chan *achan;
|
||||
void *cb_arg;
|
||||
async_callback_t cb;
|
||||
struct stratix10_svc_client_msg *msg;
|
||||
struct hlist_node next;
|
||||
struct arm_smccc_1_2_regs res;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct stratix10_async_chan - Structure representing an asynchronous channel
|
||||
* @async_client_id: Unique client identifier for the asynchronous operation
|
||||
* @job_id_pool: Pointer to the job ID pool associated with this channel
|
||||
*/
|
||||
|
||||
struct stratix10_async_chan {
|
||||
unsigned long async_client_id;
|
||||
struct ida job_id_pool;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct stratix10_async_ctrl - Control structure for Stratix10
|
||||
* asynchronous operations
|
||||
* @initialized: Flag indicating whether the control structure has
|
||||
* been initialized
|
||||
* @invoke_fn: Function pointer for invoking Stratix10 service calls
|
||||
* to EL3 secure firmware
|
||||
* @async_id_pool: Pointer to the ID pool used for asynchronous
|
||||
* operations
|
||||
* @common_achan_refcount: Atomic reference count for the common
|
||||
* asynchronous channel usage
|
||||
* @common_async_chan: Pointer to the common asynchronous channel
|
||||
* structure
|
||||
* @trx_list_lock: Spinlock for protecting the transaction list
|
||||
* operations
|
||||
* @trx_list: Hash table for managing asynchronous transactions
|
||||
*/
|
||||
|
||||
struct stratix10_async_ctrl {
|
||||
bool initialized;
|
||||
void (*invoke_fn)(struct stratix10_async_ctrl *actrl,
|
||||
const struct arm_smccc_1_2_regs *args,
|
||||
struct arm_smccc_1_2_regs *res);
|
||||
struct ida async_id_pool;
|
||||
atomic_t common_achan_refcount;
|
||||
struct stratix10_async_chan *common_async_chan;
|
||||
/* spinlock to protect trx_list hash table */
|
||||
spinlock_t trx_list_lock;
|
||||
DECLARE_HASHTABLE(trx_list, ASYNC_TRX_HASH_BITS);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct stratix10_svc_controller - service controller
|
||||
* @dev: device
|
||||
@@ -135,6 +257,7 @@ struct stratix10_svc_data {
|
||||
* @svc_fifo_lock: protect access to service message data queue
|
||||
* @invoke_fn: function to issue secure monitor call or hypervisor call
|
||||
* @svc: manages the list of client svc drivers
|
||||
* @actrl: async control structure
|
||||
*
|
||||
* This struct is used to create communication channels for service clients, to
|
||||
* handle secure monitor or hypervisor call.
|
||||
@@ -152,6 +275,7 @@ struct stratix10_svc_controller {
|
||||
spinlock_t svc_fifo_lock;
|
||||
svc_invoke_fn *invoke_fn;
|
||||
struct stratix10_svc *svc;
|
||||
struct stratix10_async_ctrl actrl;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -160,20 +284,28 @@ struct stratix10_svc_controller {
|
||||
* @scl: pointer to service client which owns the channel
|
||||
* @name: service client name associated with the channel
|
||||
* @lock: protect access to the channel
|
||||
* @async_chan: reference to asynchronous channel object for this channel
|
||||
*
|
||||
* This struct is used by service client to communicate with service layer, each
|
||||
* service client has its own channel created by service controller.
|
||||
* This struct is used by service client to communicate with service layer.
|
||||
* Each service client has its own channel created by service controller.
|
||||
*/
|
||||
struct stratix10_svc_chan {
|
||||
struct stratix10_svc_controller *ctrl;
|
||||
struct stratix10_svc_client *scl;
|
||||
char *name;
|
||||
spinlock_t lock;
|
||||
struct stratix10_async_chan *async_chan;
|
||||
};
|
||||
|
||||
static LIST_HEAD(svc_ctrl);
|
||||
static LIST_HEAD(svc_data_mem);
|
||||
|
||||
/*
|
||||
* svc_mem_lock protects access to the svc_data_mem list for
|
||||
* concurrent multi-client operations
|
||||
*/
|
||||
static DEFINE_MUTEX(svc_mem_lock);
|
||||
|
||||
/**
|
||||
* svc_pa_to_va() - translate physical address to virtual address
|
||||
* @addr: to be translated physical address
|
||||
@@ -186,6 +318,7 @@ static void *svc_pa_to_va(unsigned long addr)
|
||||
struct stratix10_svc_data_mem *pmem;
|
||||
|
||||
pr_debug("claim back P-addr=0x%016x\n", (unsigned int)addr);
|
||||
guard(mutex)(&svc_mem_lock);
|
||||
list_for_each_entry(pmem, &svc_data_mem, node)
|
||||
if (pmem->paddr == addr)
|
||||
return pmem->vaddr;
|
||||
@@ -343,6 +476,8 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data,
|
||||
case COMMAND_RSU_MAX_RETRY:
|
||||
case COMMAND_RSU_DCMF_STATUS:
|
||||
case COMMAND_FIRMWARE_VERSION:
|
||||
case COMMAND_HWMON_READTEMP:
|
||||
case COMMAND_HWMON_READVOLT:
|
||||
cb_data->status = BIT(SVC_STATUS_OK);
|
||||
cb_data->kaddr1 = &res.a1;
|
||||
break;
|
||||
@@ -527,7 +662,17 @@ static int svc_normal_to_secure_thread(void *data)
|
||||
a1 = (unsigned long)pdata->paddr;
|
||||
a2 = 0;
|
||||
break;
|
||||
|
||||
/* for HWMON */
|
||||
case COMMAND_HWMON_READTEMP:
|
||||
a0 = INTEL_SIP_SMC_HWMON_READTEMP;
|
||||
a1 = pdata->arg[0];
|
||||
a2 = 0;
|
||||
break;
|
||||
case COMMAND_HWMON_READVOLT:
|
||||
a0 = INTEL_SIP_SMC_HWMON_READVOLT;
|
||||
a1 = pdata->arg[0];
|
||||
a2 = 0;
|
||||
break;
|
||||
/* for polling */
|
||||
case COMMAND_POLL_SERVICE_STATUS:
|
||||
a0 = INTEL_SIP_SMC_SERVICE_COMPLETED;
|
||||
@@ -924,6 +1069,591 @@ struct stratix10_svc_chan *stratix10_svc_request_channel_byname(
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stratix10_svc_request_channel_byname);
|
||||
|
||||
/**
|
||||
* stratix10_svc_add_async_client - Add an asynchronous client to the
|
||||
* Stratix10 service channel.
|
||||
* @chan: Pointer to the Stratix10 service channel structure.
|
||||
* @use_unique_clientid: Boolean flag indicating whether to use a
|
||||
* unique client ID.
|
||||
*
|
||||
* This function adds an asynchronous client to the specified
|
||||
* Stratix10 service channel. If the `use_unique_clientid` flag is
|
||||
* set to true, a unique client ID is allocated for the asynchronous
|
||||
* channel. Otherwise, a common asynchronous channel is used.
|
||||
*
|
||||
* Return: 0 on success, or a negative error code on failure:
|
||||
* -EINVAL if the channel is NULL or the async controller is
|
||||
* not initialized.
|
||||
* -EALREADY if the async channel is already allocated.
|
||||
* -ENOMEM if memory allocation fails.
|
||||
* Other negative values if ID allocation fails.
|
||||
*/
|
||||
int stratix10_svc_add_async_client(struct stratix10_svc_chan *chan,
|
||||
bool use_unique_clientid)
|
||||
{
|
||||
struct stratix10_svc_controller *ctrl;
|
||||
struct stratix10_async_ctrl *actrl;
|
||||
struct stratix10_async_chan *achan;
|
||||
int ret = 0;
|
||||
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
ctrl = chan->ctrl;
|
||||
actrl = &ctrl->actrl;
|
||||
|
||||
if (!actrl->initialized) {
|
||||
dev_err(ctrl->dev, "Async controller not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (chan->async_chan) {
|
||||
dev_err(ctrl->dev, "async channel already allocated\n");
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (use_unique_clientid &&
|
||||
atomic_read(&actrl->common_achan_refcount) > 0) {
|
||||
chan->async_chan = actrl->common_async_chan;
|
||||
atomic_inc(&actrl->common_achan_refcount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
achan = kzalloc(sizeof(*achan), GFP_KERNEL);
|
||||
if (!achan)
|
||||
return -ENOMEM;
|
||||
|
||||
ida_init(&achan->job_id_pool);
|
||||
|
||||
ret = ida_alloc_max(&actrl->async_id_pool, MAX_SDM_CLIENT_IDS,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
dev_err(ctrl->dev,
|
||||
"Failed to allocate async client id\n");
|
||||
ida_destroy(&achan->job_id_pool);
|
||||
kfree(achan);
|
||||
return ret;
|
||||
}
|
||||
|
||||
achan->async_client_id = ret;
|
||||
chan->async_chan = achan;
|
||||
|
||||
if (use_unique_clientid &&
|
||||
atomic_read(&actrl->common_achan_refcount) == 0) {
|
||||
actrl->common_async_chan = achan;
|
||||
atomic_inc(&actrl->common_achan_refcount);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stratix10_svc_add_async_client);
|
||||
|
||||
/**
|
||||
* stratix10_svc_remove_async_client - Remove an asynchronous client
|
||||
* from the Stratix10 service
|
||||
* channel.
|
||||
* @chan: Pointer to the Stratix10 service channel structure.
|
||||
*
|
||||
* This function removes an asynchronous client associated with the
|
||||
* given service channel. It checks if the channel and the
|
||||
* asynchronous channel are valid, and then proceeds to decrement
|
||||
* the reference count for the common asynchronous channel if
|
||||
* applicable. If the reference count reaches zero, it destroys the
|
||||
* job ID pool and deallocates the asynchronous client ID. For
|
||||
* non-common asynchronous channels, it directly destroys the job ID
|
||||
* pool, deallocates the asynchronous client ID, and frees the
|
||||
* memory allocated for the asynchronous channel.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if the channel or asynchronous
|
||||
* channel is invalid.
|
||||
*/
|
||||
int stratix10_svc_remove_async_client(struct stratix10_svc_chan *chan)
|
||||
{
|
||||
struct stratix10_svc_controller *ctrl;
|
||||
struct stratix10_async_ctrl *actrl;
|
||||
struct stratix10_async_chan *achan;
|
||||
|
||||
if (!chan)
|
||||
return -EINVAL;
|
||||
|
||||
ctrl = chan->ctrl;
|
||||
actrl = &ctrl->actrl;
|
||||
achan = chan->async_chan;
|
||||
|
||||
if (!achan) {
|
||||
dev_err(ctrl->dev, "async channel not allocated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (achan == actrl->common_async_chan) {
|
||||
atomic_dec(&actrl->common_achan_refcount);
|
||||
if (atomic_read(&actrl->common_achan_refcount) == 0) {
|
||||
ida_destroy(&achan->job_id_pool);
|
||||
ida_free(&actrl->async_id_pool,
|
||||
achan->async_client_id);
|
||||
kfree(achan);
|
||||
actrl->common_async_chan = NULL;
|
||||
}
|
||||
} else {
|
||||
ida_destroy(&achan->job_id_pool);
|
||||
ida_free(&actrl->async_id_pool, achan->async_client_id);
|
||||
kfree(achan);
|
||||
}
|
||||
chan->async_chan = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stratix10_svc_remove_async_client);
|
||||
|
||||
/**
|
||||
* stratix10_svc_async_send - Send an asynchronous message to the
|
||||
* Stratix10 service
|
||||
* @chan: Pointer to the service channel structure
|
||||
* @msg: Pointer to the message to be sent
|
||||
* @handler: Pointer to the handler for the asynchronous message
|
||||
* used by caller for later reference.
|
||||
* @cb: Callback function to be called upon completion
|
||||
* @cb_arg: Argument to be passed to the callback function
|
||||
*
|
||||
* This function sends an asynchronous message to the SDM mailbox in
|
||||
* EL3 secure firmware. It performs various checks and setups,
|
||||
* including allocating a job ID, setting up the transaction ID and
|
||||
* packaging it to El3 firmware. The function handles different
|
||||
* commands by setting up the appropriate arguments for the SMC call.
|
||||
* If the SMC call is successful, the handler is set up and the
|
||||
* function returns 0. If the SMC call fails, appropriate error
|
||||
* handling is performed along with cleanup of resources.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL for invalid argument, -ENOMEM if
|
||||
* memory is not available, -EAGAIN if EL3 firmware is busy, -EBADF
|
||||
* if the message is rejected by EL3 firmware and -EIO on other
|
||||
* errors from EL3 firmware.
|
||||
*/
|
||||
int stratix10_svc_async_send(struct stratix10_svc_chan *chan, void *msg,
|
||||
void **handler, async_callback_t cb, void *cb_arg)
|
||||
{
|
||||
struct arm_smccc_1_2_regs args = { 0 }, res = { 0 };
|
||||
struct stratix10_svc_async_handler *handle = NULL;
|
||||
struct stratix10_svc_client_msg *p_msg =
|
||||
(struct stratix10_svc_client_msg *)msg;
|
||||
struct stratix10_svc_controller *ctrl;
|
||||
struct stratix10_async_ctrl *actrl;
|
||||
struct stratix10_async_chan *achan;
|
||||
int ret = 0;
|
||||
|
||||
if (!chan || !msg || !handler)
|
||||
return -EINVAL;
|
||||
|
||||
achan = chan->async_chan;
|
||||
ctrl = chan->ctrl;
|
||||
actrl = &ctrl->actrl;
|
||||
|
||||
if (!actrl->initialized) {
|
||||
dev_err(ctrl->dev, "Async controller not initialized\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!achan) {
|
||||
dev_err(ctrl->dev, "Async channel not allocated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
|
||||
if (!handle)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = ida_alloc_max(&achan->job_id_pool, MAX_SDM_JOB_IDS,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
dev_err(ctrl->dev, "Failed to allocate job id\n");
|
||||
kfree(handle);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
handle->transaction_id =
|
||||
STRATIX10_SET_TRANSACTIONID(achan->async_client_id, ret);
|
||||
handle->cb = cb;
|
||||
handle->msg = p_msg;
|
||||
handle->cb_arg = cb_arg;
|
||||
handle->achan = achan;
|
||||
|
||||
/*set the transaction jobid in args.a1*/
|
||||
args.a1 =
|
||||
STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(handle->transaction_id);
|
||||
|
||||
switch (p_msg->command) {
|
||||
case COMMAND_RSU_GET_SPT_TABLE:
|
||||
args.a0 = INTEL_SIP_SMC_ASYNC_RSU_GET_SPT;
|
||||
break;
|
||||
case COMMAND_RSU_STATUS:
|
||||
args.a0 = INTEL_SIP_SMC_ASYNC_RSU_GET_ERROR_STATUS;
|
||||
break;
|
||||
case COMMAND_RSU_NOTIFY:
|
||||
args.a0 = INTEL_SIP_SMC_ASYNC_RSU_NOTIFY;
|
||||
args.a2 = p_msg->arg[0];
|
||||
break;
|
||||
default:
|
||||
dev_err(ctrl->dev, "Invalid command ,%d\n", p_msg->command);
|
||||
ret = -EINVAL;
|
||||
goto deallocate_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* There is a chance that during the execution of async_send()
|
||||
* in one core, an interrupt might be received in another core;
|
||||
* to mitigate this we are adding the handle to the DB and then
|
||||
* send the smc call. If the smc call is rejected or busy then
|
||||
* we will deallocate the handle for the client to retry again.
|
||||
*/
|
||||
scoped_guard(spinlock_bh, &actrl->trx_list_lock) {
|
||||
hash_add(actrl->trx_list, &handle->next,
|
||||
handle->transaction_id);
|
||||
}
|
||||
|
||||
actrl->invoke_fn(actrl, &args, &res);
|
||||
|
||||
switch (res.a0) {
|
||||
case INTEL_SIP_SMC_STATUS_OK:
|
||||
dev_dbg(ctrl->dev,
|
||||
"Async message sent with transaction_id 0x%02x\n",
|
||||
handle->transaction_id);
|
||||
*handler = handle;
|
||||
return 0;
|
||||
case INTEL_SIP_SMC_STATUS_BUSY:
|
||||
dev_warn(ctrl->dev, "Mailbox is busy, try after some time\n");
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
case INTEL_SIP_SMC_STATUS_REJECTED:
|
||||
dev_err(ctrl->dev, "Async message rejected\n");
|
||||
ret = -EBADF;
|
||||
break;
|
||||
default:
|
||||
dev_err(ctrl->dev,
|
||||
"Failed to send async message ,got status as %ld\n",
|
||||
res.a0);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
scoped_guard(spinlock_bh, &actrl->trx_list_lock) {
|
||||
hash_del(&handle->next);
|
||||
}
|
||||
|
||||
deallocate_id:
|
||||
ida_free(&achan->job_id_pool,
|
||||
STRATIX10_GET_JOBID(handle->transaction_id));
|
||||
kfree(handle);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stratix10_svc_async_send);
|
||||
|
||||
/**
|
||||
* stratix10_svc_async_prepare_response - Prepare the response data for
|
||||
* an asynchronous transaction.
|
||||
* @chan: Pointer to the service channel structure.
|
||||
* @handle: Pointer to the asynchronous handler structure.
|
||||
* @data: Pointer to the callback data structure.
|
||||
*
|
||||
* This function prepares the response data for an asynchronous transaction. It
|
||||
* extracts the response data from the SMC response structure and stores it in
|
||||
* the callback data structure. The function also logs the completion of the
|
||||
* asynchronous transaction.
|
||||
*
|
||||
* Return: 0 on success, -ENOENT if the command is invalid
|
||||
*/
|
||||
static int stratix10_svc_async_prepare_response(struct stratix10_svc_chan *chan,
|
||||
struct stratix10_svc_async_handler *handle,
|
||||
struct stratix10_svc_cb_data *data)
|
||||
{
|
||||
struct stratix10_svc_client_msg *p_msg =
|
||||
(struct stratix10_svc_client_msg *)handle->msg;
|
||||
struct stratix10_svc_controller *ctrl = chan->ctrl;
|
||||
|
||||
data->status = STRATIX10_GET_SDM_STATUS_CODE(handle->res.a1);
|
||||
|
||||
switch (p_msg->command) {
|
||||
case COMMAND_RSU_NOTIFY:
|
||||
break;
|
||||
case COMMAND_RSU_GET_SPT_TABLE:
|
||||
data->kaddr1 = (void *)&handle->res.a2;
|
||||
data->kaddr2 = (void *)&handle->res.a3;
|
||||
break;
|
||||
case COMMAND_RSU_STATUS:
|
||||
/* COMMAND_RSU_STATUS has more elements than the cb_data
|
||||
* can acomodate, so passing the response structure to the
|
||||
* response function to be handled before done command is
|
||||
* executed by the client.
|
||||
*/
|
||||
data->kaddr1 = (void *)&handle->res;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_alert(ctrl->dev, "Invalid command\n ,%d", p_msg->command);
|
||||
return -ENOENT;
|
||||
}
|
||||
dev_dbg(ctrl->dev, "Async message completed transaction_id 0x%02x\n",
|
||||
handle->transaction_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* stratix10_svc_async_poll - Polls the status of an asynchronous
|
||||
* transaction.
|
||||
* @chan: Pointer to the service channel structure.
|
||||
* @tx_handle: Handle to the transaction being polled.
|
||||
* @data: Pointer to the callback data structure.
|
||||
*
|
||||
* This function polls the status of an asynchronous transaction
|
||||
* identified by the given transaction handle. It ensures that the
|
||||
* necessary structures are initialized and valid before proceeding
|
||||
* with the poll operation. The function sets up the necessary
|
||||
* arguments for the SMC call, invokes the call, and prepares the
|
||||
* response data if the call is successful. If the call fails, the
|
||||
* function returns the error mapped to the SVC status error.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if any input parameter is invalid,
|
||||
* -EAGAIN if the transaction is still in progress,
|
||||
* -EPERM if the command is invalid, or other negative
|
||||
* error codes on failure.
|
||||
*/
|
||||
int stratix10_svc_async_poll(struct stratix10_svc_chan *chan,
|
||||
void *tx_handle,
|
||||
struct stratix10_svc_cb_data *data)
|
||||
{
|
||||
struct stratix10_svc_async_handler *handle;
|
||||
struct arm_smccc_1_2_regs args = { 0 };
|
||||
struct stratix10_svc_controller *ctrl;
|
||||
struct stratix10_async_ctrl *actrl;
|
||||
struct stratix10_async_chan *achan;
|
||||
int ret;
|
||||
|
||||
if (!chan || !tx_handle || !data)
|
||||
return -EINVAL;
|
||||
|
||||
ctrl = chan->ctrl;
|
||||
actrl = &ctrl->actrl;
|
||||
achan = chan->async_chan;
|
||||
|
||||
if (!achan) {
|
||||
dev_err(ctrl->dev, "Async channel not allocated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
handle = (struct stratix10_svc_async_handler *)tx_handle;
|
||||
scoped_guard(spinlock_bh, &actrl->trx_list_lock) {
|
||||
if (!hash_hashed(&handle->next)) {
|
||||
dev_err(ctrl->dev, "Invalid transaction handler");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
args.a0 = INTEL_SIP_SMC_ASYNC_POLL;
|
||||
args.a1 =
|
||||
STRATIX10_SIP_SMC_SET_TRANSACTIONID_X1(handle->transaction_id);
|
||||
|
||||
actrl->invoke_fn(actrl, &args, &handle->res);
|
||||
|
||||
/*clear data for response*/
|
||||
memset(data, 0, sizeof(*data));
|
||||
|
||||
if (handle->res.a0 == INTEL_SIP_SMC_STATUS_OK) {
|
||||
ret = stratix10_svc_async_prepare_response(chan, handle, data);
|
||||
if (ret) {
|
||||
dev_err(ctrl->dev, "Error in preparation of response,%d\n", ret);
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
return 0;
|
||||
} else if (handle->res.a0 == INTEL_SIP_SMC_STATUS_BUSY) {
|
||||
dev_dbg(ctrl->dev, "async message is still in progress\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
dev_err(ctrl->dev,
|
||||
"Failed to poll async message ,got status as %ld\n",
|
||||
handle->res.a0);
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stratix10_svc_async_poll);
|
||||
|
||||
/**
|
||||
* stratix10_svc_async_done - Completes an asynchronous transaction.
|
||||
* @chan: Pointer to the service channel structure.
|
||||
* @tx_handle: Handle to the transaction being completed.
|
||||
*
|
||||
* This function completes an asynchronous transaction identified by
|
||||
* the given transaction handle. It ensures that the necessary
|
||||
* structures are initialized and valid before proceeding with the
|
||||
* completion operation. The function deallocates the transaction ID,
|
||||
* frees the memory allocated for the handler, and removes the handler
|
||||
* from the transaction list.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if any input parameter is invalid,
|
||||
* or other negative error codes on failure.
|
||||
*/
|
||||
int stratix10_svc_async_done(struct stratix10_svc_chan *chan, void *tx_handle)
|
||||
{
|
||||
struct stratix10_svc_async_handler *handle;
|
||||
struct stratix10_svc_controller *ctrl;
|
||||
struct stratix10_async_chan *achan;
|
||||
struct stratix10_async_ctrl *actrl;
|
||||
|
||||
if (!chan || !tx_handle)
|
||||
return -EINVAL;
|
||||
|
||||
ctrl = chan->ctrl;
|
||||
achan = chan->async_chan;
|
||||
actrl = &ctrl->actrl;
|
||||
|
||||
if (!achan) {
|
||||
dev_err(ctrl->dev, "async channel not allocated\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
handle = (struct stratix10_svc_async_handler *)tx_handle;
|
||||
scoped_guard(spinlock_bh, &actrl->trx_list_lock) {
|
||||
if (!hash_hashed(&handle->next)) {
|
||||
dev_err(ctrl->dev, "Invalid transaction handle");
|
||||
return -EINVAL;
|
||||
}
|
||||
hash_del(&handle->next);
|
||||
}
|
||||
ida_free(&achan->job_id_pool,
|
||||
STRATIX10_GET_JOBID(handle->transaction_id));
|
||||
kfree(handle);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stratix10_svc_async_done);
|
||||
|
||||
static inline void stratix10_smc_1_2(struct stratix10_async_ctrl *actrl,
|
||||
const struct arm_smccc_1_2_regs *args,
|
||||
struct arm_smccc_1_2_regs *res)
|
||||
{
|
||||
arm_smccc_1_2_smc(args, res);
|
||||
}
|
||||
|
||||
/**
|
||||
* stratix10_svc_async_init - Initialize the Stratix10 service
|
||||
* controller for asynchronous operations.
|
||||
* @controller: Pointer to the Stratix10 service controller structure.
|
||||
*
|
||||
* This function initializes the asynchronous service controller by
|
||||
* setting up the necessary data structures and initializing the
|
||||
* transaction list.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if the controller is NULL or already
|
||||
* initialized, -ENOMEM if memory allocation fails,
|
||||
* -EADDRINUSE if the client ID is already reserved, or other
|
||||
* negative error codes on failure.
|
||||
*/
|
||||
static int stratix10_svc_async_init(struct stratix10_svc_controller *controller)
|
||||
{
|
||||
struct stratix10_async_ctrl *actrl;
|
||||
struct arm_smccc_res res;
|
||||
struct device *dev;
|
||||
int ret;
|
||||
|
||||
if (!controller)
|
||||
return -EINVAL;
|
||||
|
||||
actrl = &controller->actrl;
|
||||
|
||||
if (actrl->initialized)
|
||||
return -EINVAL;
|
||||
|
||||
dev = controller->dev;
|
||||
|
||||
controller->invoke_fn(INTEL_SIP_SMC_SVC_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
|
||||
if (res.a0 != INTEL_SIP_SMC_STATUS_OK ||
|
||||
!(res.a1 > ASYNC_ATF_MINIMUM_MAJOR_VERSION ||
|
||||
(res.a1 == ASYNC_ATF_MINIMUM_MAJOR_VERSION &&
|
||||
res.a2 >= ASYNC_ATF_MINIMUM_MINOR_VERSION))) {
|
||||
dev_err(dev,
|
||||
"Intel Service Layer Driver: ATF version is not compatible for async operation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
actrl->invoke_fn = stratix10_smc_1_2;
|
||||
|
||||
ida_init(&actrl->async_id_pool);
|
||||
|
||||
/**
|
||||
* SIP_SVC_V1_CLIENT_ID is used by V1/stratix10_svc_send() clients
|
||||
* for communicating with SDM synchronously. We need to restrict
|
||||
* this in V3/stratix10_svc_async_send() usage to distinguish
|
||||
* between V1 and V3 messages in El3 firmware.
|
||||
*/
|
||||
ret = ida_alloc_range(&actrl->async_id_pool, SIP_SVC_V1_CLIENT_ID,
|
||||
SIP_SVC_V1_CLIENT_ID, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
dev_err(dev,
|
||||
"Intel Service Layer Driver: Error on reserving SIP_SVC_V1_CLIENT_ID\n");
|
||||
ida_destroy(&actrl->async_id_pool);
|
||||
actrl->invoke_fn = NULL;
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
|
||||
spin_lock_init(&actrl->trx_list_lock);
|
||||
hash_init(actrl->trx_list);
|
||||
atomic_set(&actrl->common_achan_refcount, 0);
|
||||
|
||||
actrl->initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* stratix10_svc_async_exit - Clean up and exit the asynchronous
|
||||
* service controller
|
||||
* @ctrl: Pointer to the stratix10_svc_controller structure
|
||||
*
|
||||
* This function performs the necessary cleanup for the asynchronous
|
||||
* service controller. It checks if the controller is valid and if it
|
||||
* has been initialized. It then locks the transaction list and safely
|
||||
* removes and deallocates each handler in the list. The function also
|
||||
* removes any asynchronous clients associated with the controller's
|
||||
* channels and destroys the asynchronous ID pool. Finally, it resets
|
||||
* the asynchronous ID pool and invoke function pointers to NULL.
|
||||
*
|
||||
* Return: 0 on success, -EINVAL if the controller is invalid or not
|
||||
* initialized.
|
||||
*/
|
||||
static int stratix10_svc_async_exit(struct stratix10_svc_controller *ctrl)
|
||||
{
|
||||
struct stratix10_svc_async_handler *handler;
|
||||
struct stratix10_async_ctrl *actrl;
|
||||
struct hlist_node *tmp;
|
||||
int i;
|
||||
|
||||
if (!ctrl)
|
||||
return -EINVAL;
|
||||
|
||||
actrl = &ctrl->actrl;
|
||||
|
||||
if (!actrl->initialized)
|
||||
return -EINVAL;
|
||||
|
||||
actrl->initialized = false;
|
||||
|
||||
scoped_guard(spinlock_bh, &actrl->trx_list_lock) {
|
||||
hash_for_each_safe(actrl->trx_list, i, tmp, handler, next) {
|
||||
ida_free(&handler->achan->job_id_pool,
|
||||
STRATIX10_GET_JOBID(handler->transaction_id));
|
||||
hash_del(&handler->next);
|
||||
kfree(handler);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < SVC_NUM_CHANNEL; i++) {
|
||||
if (ctrl->chans[i].async_chan) {
|
||||
stratix10_svc_remove_async_client(&ctrl->chans[i]);
|
||||
ctrl->chans[i].async_chan = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ida_destroy(&actrl->async_id_pool);
|
||||
actrl->invoke_fn = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* stratix10_svc_free_channel() - free service channel
|
||||
* @chan: service channel to be freed
|
||||
@@ -992,6 +1722,7 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg)
|
||||
p_data->flag = ct->flags;
|
||||
}
|
||||
} else {
|
||||
guard(mutex)(&svc_mem_lock);
|
||||
list_for_each_entry(p_mem, &svc_data_mem, node)
|
||||
if (p_mem->vaddr == p_msg->payload) {
|
||||
p_data->paddr = p_mem->paddr;
|
||||
@@ -1074,6 +1805,7 @@ void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan,
|
||||
if (!pmem)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
guard(mutex)(&svc_mem_lock);
|
||||
va = gen_pool_alloc(genpool, s);
|
||||
if (!va)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -1102,6 +1834,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate_memory);
|
||||
void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
|
||||
{
|
||||
struct stratix10_svc_data_mem *pmem;
|
||||
guard(mutex)(&svc_mem_lock);
|
||||
|
||||
list_for_each_entry(pmem, &svc_data_mem, node)
|
||||
if (pmem->vaddr == kaddr) {
|
||||
@@ -1176,11 +1909,18 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
|
||||
controller->invoke_fn = invoke_fn;
|
||||
init_completion(&controller->complete_status);
|
||||
|
||||
ret = stratix10_svc_async_init(controller);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "Intel Service Layer Driver: Error on stratix10_svc_async_init %d\n",
|
||||
ret);
|
||||
goto err_destroy_pool;
|
||||
}
|
||||
|
||||
fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
|
||||
ret = kfifo_alloc(&controller->svc_fifo, fifo_size, GFP_KERNEL);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to allocate FIFO\n");
|
||||
goto err_destroy_pool;
|
||||
goto err_async_exit;
|
||||
}
|
||||
spin_lock_init(&controller->svc_fifo_lock);
|
||||
|
||||
@@ -1199,6 +1939,11 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev)
|
||||
chans[2].name = SVC_CLIENT_FCS;
|
||||
spin_lock_init(&chans[2].lock);
|
||||
|
||||
chans[3].scl = NULL;
|
||||
chans[3].ctrl = controller;
|
||||
chans[3].name = SVC_CLIENT_HWMON;
|
||||
spin_lock_init(&chans[3].lock);
|
||||
|
||||
list_add_tail(&controller->node, &svc_ctrl);
|
||||
platform_set_drvdata(pdev, controller);
|
||||
|
||||
@@ -1250,6 +1995,8 @@ err_unregister_rsu_dev:
|
||||
platform_device_unregister(svc->stratix10_svc_rsu);
|
||||
err_free_kfifo:
|
||||
kfifo_free(&controller->svc_fifo);
|
||||
err_async_exit:
|
||||
stratix10_svc_async_exit(controller);
|
||||
err_destroy_pool:
|
||||
gen_pool_destroy(genpool);
|
||||
return ret;
|
||||
@@ -1260,6 +2007,8 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
|
||||
struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
|
||||
struct stratix10_svc *svc = ctrl->svc;
|
||||
|
||||
stratix10_svc_async_exit(ctrl);
|
||||
|
||||
of_platform_depopulate(ctrl->dev);
|
||||
|
||||
platform_device_unregister(svc->intel_svc_fcs);
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
#define TIMEOUT_US 2000 /* CVP STATUS timeout for USERMODE polling */
|
||||
|
||||
/* Vendor Specific Extended Capability Registers */
|
||||
#define VSE_PCIE_EXT_CAP_ID 0x0
|
||||
#define VSE_PCIE_EXT_CAP_ID_VAL 0x000b /* 16bit */
|
||||
|
||||
#define VSE_CVP_STATUS 0x1c /* 32bit */
|
||||
#define VSE_CVP_STATUS_CFG_RDY BIT(18) /* CVP_CONFIG_READY */
|
||||
#define VSE_CVP_STATUS_CFG_ERR BIT(19) /* CVP_CONFIG_ERROR */
|
||||
@@ -577,25 +574,18 @@ static int altera_cvp_probe(struct pci_dev *pdev,
|
||||
{
|
||||
struct altera_cvp_conf *conf;
|
||||
struct fpga_manager *mgr;
|
||||
int ret, offset;
|
||||
u16 cmd, val;
|
||||
u16 cmd, offset;
|
||||
u32 regval;
|
||||
|
||||
/* Discover the Vendor Specific Offset for this device */
|
||||
offset = pci_find_next_ext_capability(pdev, 0, PCI_EXT_CAP_ID_VNDR);
|
||||
if (!offset) {
|
||||
dev_err(&pdev->dev, "No Vendor Specific Offset.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* First check if this is the expected FPGA device. PCI config
|
||||
* space access works without enabling the PCI device, memory
|
||||
* space access is enabled further down.
|
||||
*/
|
||||
pci_read_config_word(pdev, offset + VSE_PCIE_EXT_CAP_ID, &val);
|
||||
if (val != VSE_PCIE_EXT_CAP_ID_VAL) {
|
||||
dev_err(&pdev->dev, "Wrong EXT_CAP_ID value 0x%x\n", val);
|
||||
offset = pci_find_vsec_capability(pdev, PCI_VENDOR_ID_ALTERA, 0x1172);
|
||||
if (!offset) {
|
||||
dev_err(&pdev->dev, "Wrong VSEC ID value\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,12 @@ static int xilinx_spi_probe(struct spi_device *spi)
|
||||
return xilinx_core_probe(core);
|
||||
}
|
||||
|
||||
static const struct spi_device_id xilinx_spi_ids[] = {
|
||||
{ "fpga-slave-serial" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(spi, xilinx_spi_ids);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id xlnx_spi_of_match[] = {
|
||||
{
|
||||
@@ -73,6 +79,7 @@ static struct spi_driver xilinx_slave_spi_driver = {
|
||||
.of_match_table = of_match_ptr(xlnx_spi_of_match),
|
||||
},
|
||||
.probe = xilinx_spi_probe,
|
||||
.id_table = xilinx_spi_ids,
|
||||
};
|
||||
|
||||
module_spi_driver(xilinx_slave_spi_driver)
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/unaligned.h>
|
||||
|
||||
#define OCC_SRAM_BYTES 4096
|
||||
#define OCC_CMD_DATA_BYTES 4090
|
||||
#define OCC_RESP_DATA_BYTES 4089
|
||||
#define OCC_SRAM_BYTES 8192
|
||||
#define OCC_CMD_DATA_BYTES 8186
|
||||
#define OCC_RESP_DATA_BYTES 8185
|
||||
|
||||
#define OCC_P9_SRAM_CMD_ADDR 0xFFFBE000
|
||||
#define OCC_P9_SRAM_RSP_ADDR 0xFFFBF000
|
||||
@@ -86,7 +86,7 @@ static int occ_open(struct inode *inode, struct file *file)
|
||||
if (!client)
|
||||
return -ENOMEM;
|
||||
|
||||
client->buffer = (u8 *)__get_free_page(GFP_KERNEL);
|
||||
client->buffer = kvmalloc(OCC_SRAM_BYTES, GFP_KERNEL);
|
||||
if (!client->buffer) {
|
||||
kfree(client);
|
||||
return -ENOMEM;
|
||||
@@ -97,10 +97,6 @@ static int occ_open(struct inode *inode, struct file *file)
|
||||
file->private_data = client;
|
||||
get_device(occ->dev);
|
||||
|
||||
/* We allocate a 1-page buffer, make sure it all fits */
|
||||
BUILD_BUG_ON((OCC_CMD_DATA_BYTES + 3) > PAGE_SIZE);
|
||||
BUILD_BUG_ON((OCC_RESP_DATA_BYTES + 7) > PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -176,7 +172,7 @@ static ssize_t occ_write(struct file *file, const char __user *buf,
|
||||
}
|
||||
|
||||
/* Submit command; 4 bytes before the data and 2 bytes after */
|
||||
rlen = PAGE_SIZE;
|
||||
rlen = OCC_SRAM_BYTES;
|
||||
rc = fsi_occ_submit(client->occ->dev, cmd, data_length + 6, cmd,
|
||||
&rlen);
|
||||
if (rc)
|
||||
@@ -200,7 +196,7 @@ static int occ_release(struct inode *inode, struct file *file)
|
||||
struct occ_client *client = file->private_data;
|
||||
|
||||
put_device(client->occ->dev);
|
||||
free_page((unsigned long)client->buffer);
|
||||
kvfree(client->buffer);
|
||||
kfree(client);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -644,8 +644,8 @@ static int cc1352_bootloader_wait_for_ack(struct gb_beagleplay *bg)
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_ack_com, msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
if (!ret)
|
||||
return dev_err_probe(&bg->sd->dev, -ETIMEDOUT,
|
||||
"Failed to acquire ack semaphore");
|
||||
|
||||
switch (READ_ONCE(bg->fwl_ack)) {
|
||||
@@ -683,8 +683,8 @@ static int cc1352_bootloader_get_status(struct gb_beagleplay *bg)
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_cmd_response_com,
|
||||
msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
if (!ret)
|
||||
return dev_err_probe(&bg->sd->dev, -ETIMEDOUT,
|
||||
"Failed to acquire last status semaphore");
|
||||
|
||||
switch (READ_ONCE(bg->fwl_cmd_response)) {
|
||||
@@ -768,8 +768,8 @@ static int cc1352_bootloader_crc32(struct gb_beagleplay *bg, u32 *crc32)
|
||||
ret = wait_for_completion_timeout(
|
||||
&bg->fwl_cmd_response_com,
|
||||
msecs_to_jiffies(CC1352_BOOTLOADER_TIMEOUT));
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&bg->sd->dev, ret,
|
||||
if (!ret)
|
||||
return dev_err_probe(&bg->sd->dev, -ETIMEDOUT,
|
||||
"Failed to acquire last status semaphore");
|
||||
|
||||
*crc32 = READ_ONCE(bg->fwl_cmd_response);
|
||||
|
||||
@@ -1238,7 +1238,7 @@ int __init gb_operation_init(void)
|
||||
goto err_destroy_message_cache;
|
||||
|
||||
gb_operation_completion_wq = alloc_workqueue("greybus_completion",
|
||||
0, 0);
|
||||
WQ_PERCPU, 0);
|
||||
if (!gb_operation_completion_wq)
|
||||
goto err_destroy_operation_cache;
|
||||
|
||||
|
||||
@@ -397,7 +397,7 @@ static int catu_wait_for_ready(struct catu_drvdata *drvdata)
|
||||
}
|
||||
|
||||
static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
|
||||
void *data)
|
||||
struct coresight_path *path)
|
||||
{
|
||||
int rc;
|
||||
u32 control, mode;
|
||||
@@ -425,7 +425,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
|
||||
etrdev = coresight_find_input_type(
|
||||
csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype);
|
||||
if (etrdev) {
|
||||
etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data);
|
||||
etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, path);
|
||||
if (IS_ERR(etr_buf))
|
||||
return PTR_ERR(etr_buf);
|
||||
}
|
||||
@@ -455,7 +455,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
|
||||
}
|
||||
|
||||
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
void *data)
|
||||
struct coresight_path *path)
|
||||
{
|
||||
int rc = 0;
|
||||
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
||||
@@ -463,7 +463,7 @@ static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
|
||||
if (csdev->refcnt == 0) {
|
||||
CS_UNLOCK(catu_drvdata->base);
|
||||
rc = catu_enable_hw(catu_drvdata, mode, data);
|
||||
rc = catu_enable_hw(catu_drvdata, mode, path);
|
||||
CS_LOCK(catu_drvdata->base);
|
||||
}
|
||||
if (!rc)
|
||||
@@ -488,7 +488,7 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int catu_disable(struct coresight_device *csdev, void *__unused)
|
||||
static int catu_disable(struct coresight_device *csdev, struct coresight_path *path)
|
||||
{
|
||||
int rc = 0;
|
||||
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
||||
|
||||
@@ -300,9 +300,10 @@ unlock:
|
||||
EXPORT_SYMBOL_GPL(coresight_add_helper);
|
||||
|
||||
static int coresight_enable_sink(struct coresight_device *csdev,
|
||||
enum cs_mode mode, void *data)
|
||||
enum cs_mode mode,
|
||||
struct coresight_path *path)
|
||||
{
|
||||
return sink_ops(csdev)->enable(csdev, mode, data);
|
||||
return sink_ops(csdev)->enable(csdev, mode, path);
|
||||
}
|
||||
|
||||
static void coresight_disable_sink(struct coresight_device *csdev)
|
||||
@@ -355,17 +356,20 @@ static bool coresight_is_helper(struct coresight_device *csdev)
|
||||
}
|
||||
|
||||
static int coresight_enable_helper(struct coresight_device *csdev,
|
||||
enum cs_mode mode, void *data)
|
||||
enum cs_mode mode,
|
||||
struct coresight_path *path)
|
||||
{
|
||||
return helper_ops(csdev)->enable(csdev, mode, data);
|
||||
return helper_ops(csdev)->enable(csdev, mode, path);
|
||||
}
|
||||
|
||||
static void coresight_disable_helper(struct coresight_device *csdev, void *data)
|
||||
static void coresight_disable_helper(struct coresight_device *csdev,
|
||||
struct coresight_path *path)
|
||||
{
|
||||
helper_ops(csdev)->disable(csdev, data);
|
||||
helper_ops(csdev)->disable(csdev, path);
|
||||
}
|
||||
|
||||
static void coresight_disable_helpers(struct coresight_device *csdev, void *data)
|
||||
static void coresight_disable_helpers(struct coresight_device *csdev,
|
||||
struct coresight_path *path)
|
||||
{
|
||||
int i;
|
||||
struct coresight_device *helper;
|
||||
@@ -373,7 +377,7 @@ static void coresight_disable_helpers(struct coresight_device *csdev, void *data
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
|
||||
helper = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (helper && coresight_is_helper(helper))
|
||||
coresight_disable_helper(helper, data);
|
||||
coresight_disable_helper(helper, path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +483,8 @@ void coresight_disable_path(struct coresight_path *path)
|
||||
EXPORT_SYMBOL_GPL(coresight_disable_path);
|
||||
|
||||
static int coresight_enable_helpers(struct coresight_device *csdev,
|
||||
enum cs_mode mode, void *data)
|
||||
enum cs_mode mode,
|
||||
struct coresight_path *path)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct coresight_device *helper;
|
||||
@@ -489,7 +494,7 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
|
||||
if (!helper || !coresight_is_helper(helper))
|
||||
continue;
|
||||
|
||||
ret = coresight_enable_helper(helper, mode, data);
|
||||
ret = coresight_enable_helper(helper, mode, path);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -497,8 +502,7 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
|
||||
void *sink_data)
|
||||
int coresight_enable_path(struct coresight_path *path, enum cs_mode mode)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 type;
|
||||
@@ -528,7 +532,7 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
|
||||
|
||||
switch (type) {
|
||||
case CORESIGHT_DEV_TYPE_SINK:
|
||||
ret = coresight_enable_sink(csdev, mode, sink_data);
|
||||
ret = coresight_enable_sink(csdev, mode, path);
|
||||
/*
|
||||
* Sink is the first component turned on. If we
|
||||
* failed to enable the sink, there are no components
|
||||
|
||||
@@ -156,17 +156,14 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight
|
||||
return __ctcu_set_etr_traceid(csdev, traceid, port_num, enable);
|
||||
}
|
||||
|
||||
static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
|
||||
static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
struct coresight_path *path)
|
||||
{
|
||||
struct coresight_path *path = (struct coresight_path *)data;
|
||||
|
||||
return ctcu_set_etr_traceid(csdev, path, true);
|
||||
}
|
||||
|
||||
static int ctcu_disable(struct coresight_device *csdev, void *data)
|
||||
static int ctcu_disable(struct coresight_device *csdev, struct coresight_path *path)
|
||||
{
|
||||
struct coresight_path *path = (struct coresight_path *)data;
|
||||
|
||||
return ctcu_set_etr_traceid(csdev, path, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -799,14 +799,15 @@ static void cti_pm_release(struct cti_drvdata *drvdata)
|
||||
}
|
||||
|
||||
/** cti ect operations **/
|
||||
int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
|
||||
int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
struct coresight_path *path)
|
||||
{
|
||||
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
|
||||
|
||||
return cti_enable_hw(drvdata);
|
||||
}
|
||||
|
||||
int cti_disable(struct coresight_device *csdev, void *data)
|
||||
int cti_disable(struct coresight_device *csdev, struct coresight_path *path)
|
||||
{
|
||||
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
|
||||
|
||||
|
||||
@@ -216,8 +216,9 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
|
||||
const char *assoc_dev_name);
|
||||
struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
|
||||
int out_sigs);
|
||||
int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data);
|
||||
int cti_disable(struct coresight_device *csdev, void *data);
|
||||
int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
struct coresight_path *path);
|
||||
int cti_disable(struct coresight_device *csdev, struct coresight_path *path);
|
||||
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
|
||||
void cti_write_intack(struct device *dev, u32 ackval);
|
||||
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
|
||||
|
||||
@@ -52,7 +52,7 @@ static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused
|
||||
}
|
||||
|
||||
static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
void *data)
|
||||
struct coresight_path *path)
|
||||
{
|
||||
dev_dbg(csdev->dev.parent, "Dummy sink enabled\n");
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user