Char/Misc/IIO driver changes for 7.0-rc1

Here is the big set of char/misc/iio and other smaller driver subsystem
 changes for 7.0-rc1.  Lots of little things in here, including:
   - Loads of iio driver changes and updates and additions
   - gpib driver updates
   - interconnect driver updates
   - i3c driver updates
   - hwtracing (coresight and intel) driver updates
   - deletion of the obsolete mwave driver
   - binder driver updates (rust and c versions)
   - mhi driver updates (causing a merge conflict, see below)
   - mei driver updates
   - fsi driver updates
   - eeprom driver updates
   - lots of other small char and misc driver updates and cleanups
 
 All of these have been in linux-next for a while, with no reported
 issues except for a merge conflict with your tree due to the mhi driver
 changes in the drivers/net/wireless/ath/ath12k/mhi.c file.  To fix that
 up, just delete the "auto_queue" structure fields being set, see this
 message for the full change needed:
 	https://lore.kernel.org/r/aXD6X23btw8s-RZP@sirena.org.uk
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaZRxOg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+ykIrACgs9S+A/GG9X0Kvc+ND/J1XYZpj3QAoKl0yXGj
 SV1SR/giEBc7iKV6Dn6O
 =jbok
 -----END PGP SIGNATURE-----

Merge tag 'char-misc-7.0-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 and other smaller driver
  subsystem changes for 7.0-rc1. Lots of little things in here,
  including:

   - Loads of iio driver changes and updates and additions

   - gpib driver updates

   - interconnect driver updates

   - i3c driver updates

   - hwtracing (coresight and intel) driver updates

   - deletion of the obsolete mwave driver

   - binder driver updates (rust and c versions)

   - mhi driver updates (causing a merge conflict, see below)

   - mei driver updates

   - fsi driver updates

   - eeprom driver updates

   - lots of other small char and misc driver updates and cleanups

  All of these have been in linux-next for a while, with no reported
  issues"

* tag 'char-misc-7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (297 commits)
  mux: mmio: fix regmap leak on probe failure
  rust_binder: return p from rust_binder_transaction_target_node()
  drivers: android: binder: Update ARef imports from sync::aref
  rust_binder: fix needless borrow in context.rs
  iio: magn: mmc5633: Fix Kconfig for combination of I3C as module and driver builtin
  iio: sca3000: Fix a resource leak in sca3000_probe()
  iio: proximity: rfd77402: Add interrupt handling support
  iio: proximity: rfd77402: Document device private data structure
  iio: proximity: rfd77402: Use devm-managed mutex initialization
  iio: proximity: rfd77402: Use kernel helper for result polling
  iio: proximity: rfd77402: Align polling timeout with datasheet
  iio: cros_ec: Allow enabling/disabling calibration mode
  iio: frequency: ad9523: correct kernel-doc bad line warning
  iio: buffer: buffer_impl.h: fix kernel-doc warnings
  iio: gyro: itg3200: Fix unchecked return value in read_raw
  MAINTAINERS: add entry for ADE9000 driver
  iio: accel: sca3000: remove unused last_timestamp field
  iio: accel: adxl372: remove unused int2_bitmask field
  iio: adc: ad7766: Use iio_trigger_generic_data_rdy_poll()
  iio: magnetometer: Remove IRQF_ONESHOT
  ...
This commit is contained in:
Linus Torvalds 2026-02-17 09:11:04 -08:00
commit 505d195b0f
273 changed files with 15801 additions and 5395 deletions

View file

@ -23,8 +23,7 @@ What: /sys/accessibility/speakup/bleep_time
KernelVersion: 2.6
Contact: speakup@linux-speakup.org
Description: This controls the duration of the PC speaker beeps speakup
produces.
TODO: What are the units? Jiffies?
produces, in milliseconds.
What: /sys/accessibility/speakup/cursor_time
KernelVersion: 2.6

View file

@ -1,7 +1,7 @@
What: /sys/bus/coresight/devices/dummy_source<N>/enable_source
Date: Dec 2024
KernelVersion: 6.14
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
Contact: Mao Jinlong <jinlong.mao@oss.qualcomm.com>
Description: (RW) Enable/disable tracing of dummy source. A sink should be activated
before enabling the source. The path of coresight components linking
the source to the sink is configured and managed automatically by the
@ -10,7 +10,7 @@ Description: (RW) Enable/disable tracing of dummy source. A sink should be activ
What: /sys/bus/coresight/devices/dummy_source<N>/traceid
Date: Dec 2024
KernelVersion: 6.14
Contact: Mao Jinlong <quic_jinlmao@quicinc.com>
Contact: Mao Jinlong <jinlong.mao@oss.qualcomm.com>
Description: (R) Show the trace ID that will appear in the trace stream
coming from this trace entity.

View file

@ -0,0 +1,69 @@
What: /sys/bus/coresight/devices/<tpda-name>/trig_async_enable
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Enable/disable cross trigger synchronization sequence interface.
What: /sys/bus/coresight/devices/<tpda-name>/trig_flag_ts_enable
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Enable/disable cross trigger FLAG packet request interface.
What: /sys/bus/coresight/devices/<tpda-name>/trig_freq_enable
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Enable/disable cross trigger FREQ packet request interface.
What: /sys/bus/coresight/devices/<tpda-name>/freq_ts_enable
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Enable/disable the timestamp for all FREQ packets.
What: /sys/bus/coresight/devices/<tpda-name>/cmbchan_mode
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Configure the CMB/MCMB channel mode for all enabled ports.
Value 0 means raw channel mapping mode. Value 1 means channel pair marking mode.
What: /sys/bus/coresight/devices/<tpda-name>/global_flush_req
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Set global (all ports) flush request bit. The bit remains set until a
global flush request sequence completes.
What: /sys/bus/coresight/devices/<tpda-name>/syncr_mode
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Set mode the of the syncr counter.
mode 0 - COUNT[11:0] value represents the approximate number of bytes moved between two ASYNC packet requests
mode 1 - the bits COUNT[11:7] are used as a power of 2. for example, we could insert an async packet every 8K
data by writing a value 13 to the COUNT[11:7] field.
What: /sys/bus/coresight/devices/<tpda-name>/syncr_count
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Set value the of the syncr counter.
Range: 0-4095
What: /sys/bus/coresight/devices/<tpda-name>/port_flush_req
Date: December 2025
KernelVersion: 6.20
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>, Jie Gan <jie.gan@oss.qualcomm.com>
Description:
(RW) Configure the bit i to requests a flush operation of port i on the TPDA.
The requested bit(s) remain set until the flush request completes.

View file

@ -1,7 +1,7 @@
What: /sys/bus/coresight/devices/<tpdm-name>/integration_test
Date: January 2023
KernelVersion: 6.2
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(Write) Run integration test for tpdm. Integration test
will generate test data for tpdm. It can help to make
@ -15,7 +15,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/reset_dataset
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(Write) Reset the dataset of the tpdm.
@ -25,7 +25,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_type
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the trigger type of the DSB for tpdm.
@ -36,7 +36,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_ts
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the trigger timestamp of the DSB for tpdm.
@ -47,7 +47,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_mode
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the programming mode of the DSB for tpdm.
@ -61,7 +61,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_idx
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the index number of the edge detection for the DSB
subunit TPDM. Since there are at most 256 edge detections, this
@ -70,7 +70,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_val
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
Write a data to control the edge detection corresponding to
the index number. Before writing data to this sysfs file,
@ -86,7 +86,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/ctrl_mask
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
Write a data to mask the edge detection corresponding to the index
number. Before writing data to this sysfs file, "ctrl_idx" should
@ -98,21 +98,21 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/edcr[0:15]
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
Read a set of the edge control value of the DSB in TPDM.
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_edge/edcmr[0:7]
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
Read a set of the edge control mask of the DSB in TPDM.
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpr[0:7]
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the value of the trigger pattern for the DSB
subunit TPDM.
@ -120,7 +120,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_trig_patt/xpmr[0:7]
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the mask of the trigger pattern for the DSB
subunit TPDM.
@ -128,21 +128,21 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[0:7]
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the value of the pattern for the DSB subunit TPDM.
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[0:7]
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the mask of the pattern for the DSB subunit TPDM.
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/enable_ts
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(Write) Set the pattern timestamp of DSB tpdm. Read
the pattern timestamp of DSB tpdm.
@ -154,7 +154,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/set_type
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(Write) Set the pattern type of DSB tpdm. Read
the pattern type of DSB tpdm.
@ -166,7 +166,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_msr/msr[0:31]
Date: March 2023
KernelVersion: 6.7
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the MSR(mux select register) for the DSB subunit
TPDM.
@ -174,7 +174,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_mode
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description: (Write) Set the data collection mode of CMB tpdm. Continuous
change creates CMB data set elements on every CMBCLK edge.
Trace-on-change creates CMB data set elements only when a new
@ -188,7 +188,7 @@ Description: (Write) Set the data collection mode of CMB tpdm. Continuous
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpr[0:1]
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the value of the trigger pattern for the CMB
subunit TPDM.
@ -196,7 +196,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpmr[0:1]
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the mask of the trigger pattern for the CMB
subunit TPDM.
@ -204,21 +204,21 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[0:1]
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the value of the pattern for the CMB subunit TPDM.
What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[0:1]
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the mask of the pattern for the CMB subunit TPDM.
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_patt/enable_ts
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(Write) Set the pattern timestamp of CMB tpdm. Read
the pattern timestamp of CMB tpdm.
@ -230,7 +230,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_ts
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the trigger timestamp of the CMB for tpdm.
@ -241,7 +241,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_ts_all
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Read or write the status of timestamp upon all interface.
Only value 0 and 1 can be written to this node. Set this node to 1 to request
@ -253,7 +253,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/cmb_msr/msr[0:31]
Date: January 2024
KernelVersion: 6.9
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the MSR(mux select register) for the CMB subunit
TPDM.
@ -261,7 +261,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/mcmb_trig_lane
Date: Feb 2025
KernelVersion 6.15
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get which lane participates in the output pattern
match cross trigger mechanism for the MCMB subunit TPDM.
@ -269,7 +269,7 @@ Description:
What: /sys/bus/coresight/devices/<tpdm-name>/mcmb_lanes_select
Date: Feb 2025
KernelVersion 6.15
Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
Contact: Jinlong Mao <jinlong.mao@oss.qualcomm.com>, Tao Zhang <tao.zhang@oss.qualcomm.com>
Description:
(RW) Set/Get the enablement of the individual lane.

View file

@ -3,9 +3,12 @@ Date: July 2015
KernelVersion: 4.7
Contact: linux-iio@vger.kernel.org
Description:
Writing '1' will perform a FOC (Fast Online Calibration). The
corresponding calibration offsets can be read from `*_calibbias`
entries.
Writing '1' either perform a FOC (Fast Online Calibration) or
enter calibration mode.
Writing '0` exits calibration mode. It is a NOP for FOC enabled
sensors.
The corresponding calibration offsets can be read from `*_calibbias`
entries.
What: /sys/bus/iio/devices/iio:deviceX/id
Date: September 2017

View file

@ -17,3 +17,14 @@ Description:
from the device.
This is a read-only attribute.
What: /sys/class/spi_master/spi<bus>/spi<bus>.<dev>/jedec_id
Date: January 2026
KernelVersion: 6.19
Contact: Patrick Wicki <patrick.wicki@siemens.com>
Description:
Contains the raw JEDEC ID bytes returned by the RDID (0x9f) command. The
bytes are exposed as a hex string in big-endian order as read from the
device.
This is a read-only attribute.

View file

@ -352,7 +352,7 @@
216 = /dev/fujitsu/apanel Fujitsu/Siemens application panel
217 = /dev/ni/natmotn National Instruments Motion
218 = /dev/kchuid Inter-process chuid control
219 = /dev/modems/mwave MWave modem firmware upload
219 =
220 = /dev/mptctl Message passing technology (MPT) control
221 = /dev/mvista/hssdsi Montavista PICMG hot swap system driver
222 = /dev/mvista/hasi Montavista PICMG high availability

View file

@ -31,7 +31,7 @@ maintainers:
- Mike Leach <mike.leach@linaro.org>
- Suzuki K Poulose <suzuki.poulose@arm.com>
- James Clark <james.clark@linaro.org>
- Mao Jinlong <quic_jinlmao@quicinc.com>
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
- Hao Zhang <quic_hazha@quicinc.com>
properties:

View file

@ -30,7 +30,7 @@ maintainers:
- Mike Leach <mike.leach@linaro.org>
- Suzuki K Poulose <suzuki.poulose@arm.com>
- James Clark <james.clark@linaro.org>
- Mao Jinlong <quic_jinlmao@quicinc.com>
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
- Hao Zhang <quic_hazha@quicinc.com>
properties:

View file

@ -7,9 +7,9 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: CoreSight TMC Control Unit
maintainers:
- Yuanfang Zhang <quic_yuanfang@quicinc.com>
- Mao Jinlong <quic_jinlmao@quicinc.com>
- Jie Gan <quic_jiegan@quicinc.com>
- Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
- Jie Gan <jie.gan@oss.qualcomm.com>
description: |
The Trace Memory Controller(TMC) is used for Embedded Trace Buffer(ETB),
@ -26,8 +26,13 @@ description: |
properties:
compatible:
enum:
- qcom,sa8775p-ctcu
oneOf:
- items:
- enum:
- qcom,qcs8300-ctcu
- const: qcom,sa8775p-ctcu
- enum:
- qcom,sa8775p-ctcu
reg:
maxItems: 1

View file

@ -0,0 +1,90 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/qcom,coresight-itnoc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Interconnect Trace Network On Chip - ITNOC
maintainers:
- Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
description:
The Interconnect TNOC is a CoreSight graph link that forwards trace data
from a subsystem to the Aggregator TNOC. Compared to Aggregator TNOC, it
does not have aggregation and ATID functionality.
properties:
$nodename:
pattern: "^itnoc(@[0-9a-f]+)?$"
compatible:
const: qcom,coresight-itnoc
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: apb
in-ports:
$ref: /schemas/graph.yaml#/properties/ports
patternProperties:
'^port(@[0-9a-f]{1,2})?$':
description: Input connections from CoreSight Trace Bus
$ref: /schemas/graph.yaml#/properties/port
out-ports:
$ref: /schemas/graph.yaml#/properties/ports
additionalProperties: false
properties:
port:
description: out connections to aggregator TNOC
$ref: /schemas/graph.yaml#/properties/port
required:
- compatible
- reg
- clocks
- clock-names
- in-ports
- out-ports
additionalProperties: false
examples:
- |
itnoc@109ac000 {
compatible = "qcom,coresight-itnoc";
reg = <0x109ac000 0x1000>;
clocks = <&aoss_qmp>;
clock-names = "apb";
in-ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
tn_ic_in_tpdm_dcc: endpoint {
remote-endpoint = <&tpdm_dcc_out_tn_ic>;
};
};
};
out-ports {
port {
tn_ic_out_tnoc_aggr: endpoint {
/* to Aggregator TNOC input */
remote-endpoint = <&tn_ag_in_tn_ic>;
};
};
};
};
...

View file

@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Coresight Remote ETM(Embedded Trace Macrocell)
maintainers:
- Jinlong Mao <quic_jinlmao@quicinc.com>
- Tao Zhang <quic_taozha@quicinc.com>
- Jinlong Mao <jinlong.mao@oss.qualcomm.com>
- Tao Zhang <tao.zhang@oss.qualcomm.com>
description:
Support for ETM trace collection on remote processor using coresight

View file

@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Trace Network On Chip - TNOC
maintainers:
- Yuanfang Zhang <quic_yuanfang@quicinc.com>
- Yuanfang Zhang <yuanfang.zhang@oss.qualcomm.com>
description: >
The Trace Network On Chip (TNOC) is an integration hierarchy hardware

View file

@ -33,8 +33,8 @@ description: |
to sink.
maintainers:
- Mao Jinlong <quic_jinlmao@quicinc.com>
- Tao Zhang <quic_taozha@quicinc.com>
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
- Tao Zhang <tao.zhang@oss.qualcomm.com>
# Need a custom select here or 'arm,primecell' will match on lots of nodes
select:

View file

@ -19,8 +19,8 @@ description: |
sources and send it to a TPDA for packetization, timestamping, and funneling.
maintainers:
- Mao Jinlong <quic_jinlmao@quicinc.com>
- Tao Zhang <quic_taozha@quicinc.com>
- Mao Jinlong <jinlong.mao@oss.qualcomm.com>
- Tao Zhang <tao.zhang@oss.qualcomm.com>
# Need a custom select here or 'arm,primecell' will match on lots of nodes
select:

View file

@ -1,17 +0,0 @@
Android Goldfish QEMU Pipe
Android pipe virtual device generated by android emulator.
Required properties:
- compatible : should contain "google,android-pipe" to match emulator
- reg : <registers mapping>
- interrupts : <interrupt mapping>
Example:
android_pipe@a010000 {
compatible = "google,android-pipe";
reg = <ff018000 0x2000>;
interrupts = <0x12>;
};

View file

@ -0,0 +1,120 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright 2025 Analog Devices Inc.
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/adi,ad4062.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD4062 ADC family device driver
maintainers:
- Jorge Marques <jorge.marques@analog.com>
description: |
Analog Devices AD4062 Single Channel Precision SAR ADC family
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4060.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4062.pdf
properties:
compatible:
enum:
- adi,ad4060
- adi,ad4062
reg:
maxItems: 1
interrupts:
description:
Two pins are available that can be configured as either a general purpose
digital output, device enable signal (used to synchronise other parts of
the signal chain with ADC sampling), device ready (GP1 only) or various
interrupt signals. If intended for use as a GPIO or device enable, will not
present here.
minItems: 1
items:
- description:
GP0 pin, cannot be configured as DEV_RDY.
- description:
GP1 pin, can be configured to any setting.
interrupt-names:
minItems: 1
items:
- const: gp0
- const: gp1
gpio-controller:
description:
Marks the device node as a GPIO controller. GPs not listed as interrupts
are exposed as a GPO.
'#gpio-cells':
const: 2
description:
The first cell is the GPIO number and the second cell specifies
GPIO flags, as defined in <dt-bindings/gpio/gpio.h>.
vdd-supply:
description: Analog power supply.
vio-supply:
description: Digital interface logic power supply.
ref-supply:
description:
Reference voltage to set the ADC full-scale range. If not present,
vdd-supply is used as the reference voltage.
required:
- compatible
- reg
- vdd-supply
- vio-supply
allOf:
- $ref: /schemas/i3c/i3c.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i3c {
#address-cells = <3>;
#size-cells = <0>;
adc@0,2ee007c0000 {
reg = <0x0 0x2ee 0x7c0000>;
vdd-supply = <&vdd>;
vio-supply = <&vio>;
ref-supply = <&ref>;
interrupt-parent = <&gpio>;
interrupts = <0 0 IRQ_TYPE_EDGE_RISING>,
<0 1 IRQ_TYPE_EDGE_FALLING>;
interrupt-names = "gp0", "gp1";
};
};
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i3c {
#address-cells = <3>;
#size-cells = <0>;
adc@0,2ee007c0000 {
reg = <0x0 0x2ee 0x7c0000>;
vdd-supply = <&vdd>;
vio-supply = <&vio>;
ref-supply = <&ref>;
gpio-controller;
#gpio-cells = <2>;
};
};

View file

@ -0,0 +1,191 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/adi,ad4134.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD4134 ADC
maintainers:
- Marcelo Schmitt <marcelo.schmitt@analog.com>
description: |
The AD4134 is a quad channel, low noise, simultaneous sampling, precision
analog-to-digital converter (ADC).
Specifications can be found at:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad4134.pdf
$ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
enum:
- adi,ad4134
reg:
maxItems: 1
spi-max-frequency:
maximum: 50000000
avdd5-supply:
description: A 5V supply that powers the chip's analog circuitry.
dvdd5-supply:
description: A 5V supply that powers the chip's digital circuitry.
iovdd-supply:
description:
A 1.8V supply that sets the logic levels for the digital interface pins.
refin-supply:
description:
A 4.096V or 5V supply that serves as reference for ADC conversions.
avdd1v8-supply:
description: A 1.8V supply used by the analog circuitry.
dvdd1v8-supply:
description: A 1.8V supply used by the digital circuitry.
clkvdd-supply:
description: A 1.8V supply for the chip's clock management circuit.
ldoin-supply:
description:
A 2.6V to 5.5V supply that generates 1.8V for AVDD1V8, DVDD1V8, and CLKVDD
pins.
clocks:
maxItems: 1
description:
Required external clock source. Can specify either a crystal or CMOS clock
source. If an external crystal is set, connect the CLKSEL pin to IOVDD.
Otherwise, connect the CLKSEL pin to IOGND and the external CMOS clock
signal to the XTAL2/CLKIN pin.
clock-names:
enum:
- xtal
- clkin
default: clkin
'#clock-cells':
const: 0
clock-output-names:
maxItems: 1
regulators:
type: object
description:
list of regulators provided by this controller.
properties:
vcm-output:
$ref: /schemas/regulator/regulator.yaml#
type: object
unevaluatedProperties: false
additionalProperties: false
reset-gpios:
maxItems: 1
powerdown-gpios:
description:
Active low GPIO connected to the /PDN pin. Forces the device into full
power-down mode when brought low. Pull this input to IOVDD for normal
operation.
maxItems: 1
odr-gpios:
description:
GPIO connected to ODR pin. Used to sample ADC data in minimum I/O mode.
maxItems: 1
adi,asrc-mode:
$ref: /schemas/types.yaml#/definitions/string
description:
Asynchronous Sample Rate Converter (ASRC) operation mode control input.
Describes whether the MODE pin is set to a high level (for master mode
operation) or to a low level (for slave mode operation).
enum: [ high, low ]
default: low
adi,dclkio:
description:
DCLK pin I/O direction control for when the device operates in Pin Control
Slave Mode or in SPI Control Mode. Describes if DEC0/DCLKIO pin is at a
high level (which configures DCLK as an output) or to set to a low level
(configuring DCLK for input).
enum: [ out, in ]
default: in
adi,dclkmode:
description:
DCLK mode control for when the device operates in Pin Control Slave Mode
or in SPI Control Mode. Describes whether the DEC1/DCLKMODE pin is set to
a high level (configuring the DCLK to operate in free running mode) or
to a low level (to configure DCLK to operate in gated mode).
enum: [ free-running, gated ]
default: gated
required:
- compatible
- reg
- avdd5-supply
- dvdd5-supply
- iovdd-supply
- refin-supply
- clocks
- clock-names
oneOf:
- required:
- ldoin-supply
- required:
- avdd1v8-supply
- dvdd1v8-supply
- clkvdd-supply
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "adi,ad4134";
reg = <0>;
spi-max-frequency = <1000000>;
reset-gpios = <&gpio0 86 GPIO_ACTIVE_LOW>;
odr-gpios = <&gpio0 87 GPIO_ACTIVE_HIGH>;
powerdown-gpios = <&gpio0 88 GPIO_ACTIVE_LOW>;
clocks = <&sys_clk>;
clock-names = "clkin";
avdd5-supply = <&avdd5>;
dvdd5-supply = <&dvdd5>;
iovdd-supply = <&iovdd>;
refin-supply = <&refin>;
avdd1v8-supply = <&avdd1v8>;
dvdd1v8-supply = <&dvdd1v8>;
clkvdd-supply = <&clkvdd>;
regulators {
vcm_reg: vcm-output {
regulator-name = "ad4134-vcm";
};
};
};
};
...

View file

@ -4,18 +4,26 @@
$id: http://devicetree.org/schemas/iio/adc/adi,ad7768-1.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices AD7768-1 ADC device driver
title: Analog Devices AD7768-1 ADC family
maintainers:
- Michael Hennerich <michael.hennerich@analog.com>
description: |
Datasheet at:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-1.pdf
Analog Devices AD7768-1 24-Bit Single Channel Low Power sigma-delta ADC family
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-1.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7767-1.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7768-1.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/adaq7769-1.pdf
properties:
compatible:
const: adi,ad7768-1
enum:
- adi,ad7768-1
- adi,adaq7767-1
- adi,adaq7768-1
- adi,adaq7769-1
reg:
maxItems: 1
@ -58,6 +66,25 @@ properties:
description:
ADC reference voltage supply
adi,aaf-gain-bp:
description: |
Specifies the gain applied by the Analog Anti-Aliasing Filter (AAF)
to the ADC input in basis points (one hundredth of a percent).
The hardware gain is determined by which input pin(s) the signal goes
through into the AAF. The possible connections are:
* For the ADAQ7767-1: Input connected to IN1±, IN2± or IN3±.
* For the ADAQ7769-1: OUT_PGA pin connected to IN1_AAF+, IN2_AAF+,
or IN3_AAF+.
enum: [1430, 3640, 10000]
default: 10000
pga-gpios:
description:
GAIN 0, GAIN1 and GAIN2 pins for gain selection. For devices that have
PGA configuration input pins, pga-gpios must be defined.
minItems: 3
maxItems: 3
adi,sync-in-gpios:
maxItems: 1
description:
@ -147,6 +174,35 @@ patternProperties:
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
# AAF Gain property only applies to ADAQ7767-1 and ADAQ7769-1 devices
- if:
properties:
compatible:
contains:
enum:
- adi,adaq7767-1
- adi,adaq7769-1
then:
required:
- adi,aaf-gain-bp
else:
properties:
adi,aaf-gain-bp: false
- if:
properties:
compatible:
contains:
enum:
- adi,adaq7768-1
- adi,adaq7769-1
then:
required:
- pga-gpios
else:
properties:
pga-gpios: false
unevaluatedProperties: false
examples:

View file

@ -18,6 +18,7 @@ description: |
All the parts support the register map described by Application Note AN-877
https://www.analog.com/media/en/technical-documentation/application-notes/AN-877.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD9211.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD9265.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD9434.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD9467.pdf
@ -25,6 +26,7 @@ description: |
properties:
compatible:
enum:
- adi,ad9211
- adi,ad9265
- adi,ad9434
- adi,ad9467

View file

@ -44,6 +44,9 @@ properties:
Input clock used to derive the sample clock. Expected to be the
SoC's APB clock.
interrupts:
maxItems: 1
resets:
maxItems: 1

View file

@ -0,0 +1,63 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/nxp,s32g2-sar-adc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NXP Successive Approximation ADC
description:
The NXP SAR ADC provides fast and accurate analog-to-digital
conversion using the Successive Approximation Register (SAR) method.
It has 12-bit resolution with 8 input channels. Conversions can be
launched in software or using hardware triggers. It supports
continuous and one-shot modes with separate registers.
maintainers:
- Daniel Lezcano <daniel.lezcano@kernel.org>
properties:
compatible:
oneOf:
- const: nxp,s32g2-sar-adc
- items:
- const: nxp,s32g3-sar-adc
- const: nxp,s32g2-sar-adc
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
dmas:
maxItems: 1
dma-names:
const: rx
required:
- compatible
- reg
- interrupts
- clocks
- dmas
- dma-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
adc@401f8000 {
compatible = "nxp,s32g2-sar-adc";
reg = <0x401f8000 0x1000>;
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks 0x41>;
dmas = <&edma0 0 32>;
dma-names = "rx";
};

View file

@ -0,0 +1,82 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/ti,ads1018.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI ADS1018/ADS1118 SPI analog to digital converter
maintainers:
- Kurt Borja <kuurtb@gmail.com>
description: |
The ADS1018/ADS1118 is a precision, low-power, 12-bit/16-bit, analog to
digital converter (ADC). It integrates a programmable gain amplifier (PGA),
internal voltage reference, oscillator and high-accuracy temperature sensor.
Datasheets:
- ADS1018: https://www.ti.com/lit/ds/symlink/ads1018.pdf
- ADS1118: https://www.ti.com/lit/ds/symlink/ads1118.pdf
properties:
compatible:
enum:
- ti,ads1018
- ti,ads1118
reg:
maxItems: 1
vdd-supply: true
spi-max-frequency:
maximum: 4000000
spi-cpha: true
interrupts:
description: DOUT/DRDY (Data Out/Data Ready) line.
maxItems: 1
drdy-gpios:
description:
Extra GPIO line connected to DOUT/DRDY (Data Out/Data Ready). This allows
distinguishing between interrupts triggered by the data-ready signal and
interrupts triggered by an SPI transfer.
maxItems: 1
'#io-channel-cells':
const: 1
required:
- compatible
- reg
- vdd-supply
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "ti,ads1118";
reg = <0>;
spi-max-frequency = <4000000>;
spi-cpha;
vdd-supply = <&vdd_3v3_reg>;
interrupts-extended = <&gpio 14 IRQ_TYPE_EDGE_FALLING>;
drdy-gpios = <&gpio 14 GPIO_ACTIVE_LOW>;
};
};

View file

@ -0,0 +1,208 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/adc/ti,ads131m02.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments ADS131M0x 2-, 3-, 4-, 6- and 8-Channel ADCs
maintainers:
- Oleksij Rempel <o.rempel@pengutronix.de>
description: |
The ADS131M0x are a family of multichannel, simultaneous sampling,
24-bit, delta-sigma, analog-to-digital converters (ADCs) with a
built-in programmable gain amplifier (PGA) and internal reference.
Communication with the ADC chip is via SPI.
Datasheets:
- ADS131M02: https://www.ti.com/lit/ds/symlink/ads131m02.pdf
- ADS131M03: https://www.ti.com/lit/ds/symlink/ads131m03.pdf
- ADS131M04: https://www.ti.com/lit/ds/symlink/ads131m04.pdf
- ADS131M06: https://www.ti.com/lit/ds/symlink/ads131m06.pdf
- ADS131M08: https://www.ti.com/lit/ds/symlink/ads131m08.pdf
properties:
compatible:
enum:
- ti,ads131m02
- ti,ads131m03
- ti,ads131m04
- ti,ads131m06
- ti,ads131m08
reg:
description: SPI chip select number.
clocks:
description:
Phandle to the external clock source required by the ADC's CLKIN pin.
The datasheet recommends specific frequencies based on the desired power
mode (e.g., 8.192 MHz for High-Resolution mode).
maxItems: 1
avdd-supply:
description: Analog power supply (AVDD).
dvdd-supply:
description: Digital power supply (DVDD).
interrupts:
description: DRDY (Data Ready) output signal.
maxItems: 1
reset-gpios:
description: Optional RESET signal.
maxItems: 1
clock-names:
description:
Indicates if a crystal oscillator (XTAL) or CMOS signal is connected
(CLKIN). Note that XTAL mode is only supported on ADS131M06 and ADS131M08.
enum: [xtal, clkin]
refin-supply:
description: Optional external reference supply (REFIN).
'#address-cells':
const: 1
'#size-cells':
const: 0
required:
- compatible
- reg
- clocks
- clock-names
- avdd-supply
- dvdd-supply
patternProperties:
"^channel@[0-7]$":
type: object
$ref: /schemas/iio/adc/adc.yaml#
description: Properties for a single ADC channel.
properties:
reg:
description: The channel index (0-7).
minimum: 0
maximum: 7 # Max channels on ADS131M08
label: true
required:
- reg
unevaluatedProperties: false
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
- if:
# 20-pin devices: M02, M03, M04
# These do not support XTAL or REFIN.
properties:
compatible:
enum:
- ti,ads131m02
- ti,ads131m03
- ti,ads131m04
then:
properties:
clock-names:
const: clkin
refin-supply: false
- if:
# ADS131M02: 2 channels max (0-1)
properties:
compatible:
contains:
const: ti,ads131m02
then:
patternProperties:
"^channel@[0-1]$":
properties:
reg:
maximum: 1
"^channel@[2-7]$": false
- if:
# ADS131M03: 3 channels max (0-2)
properties:
compatible:
contains:
const: ti,ads131m03
then:
patternProperties:
"^channel@[0-2]$":
properties:
reg:
maximum: 2
"^channel@[3-7]$": false
- if:
# ADS131M04: 4 channels max (0-3)
properties:
compatible:
contains:
const: ti,ads131m04
then:
patternProperties:
"^channel@[0-3]$":
properties:
reg:
maximum: 3
"^channel@[4-7]$": false
- if:
# ADS131M06: 6 channels max (0-5)
properties:
compatible:
contains:
const: ti,ads131m06
then:
patternProperties:
"^channel@[0-5]$":
properties:
reg:
maximum: 5
"^channel@[6-7]$": false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/stm32mp1-clks.h>
spi1 {
#address-cells = <1>;
#size-cells = <0>;
adc@0 {
compatible = "ti,ads131m02";
reg = <0>;
spi-max-frequency = <8000000>;
clocks = <&rcc CK_MCO2>;
clock-names = "clkin";
avdd-supply = <&vdd_ana>;
dvdd-supply = <&vdd_dig>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
label = "input_voltage";
};
channel@1 {
reg = <1>;
label = "input_current";
};
};
};

View file

@ -0,0 +1,87 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/amplifiers/adi,adl8113.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADL8113 Low Noise Amplifier with integrated bypass switches
maintainers:
- Antoniu Miclaus <antoniu.miclaus@analog.com>
description: |
The ADL8113 is a 10MHz to 12GHz Low Noise Amplifier with integrated bypass
switches controlled by two GPIO pins (VA and VB). The device supports four
operation modes:
- Internal Amplifier: VA=0, VB=0 - Signal passes through the internal LNA
- Internal Bypass: VA=1, VB=1 - Signal bypasses through internal path
- External Bypass A: VA=0, VB=1 - Signal routes from RFIN to OUT_A and from IN_A to RFOUT
- External Bypass B: VA=1, VB=0 - Signal routes from RFIN to OUT_B and from IN_B to RFOUT
https://www.analog.com/en/products/adl8113.html
properties:
compatible:
const: adi,adl8113
vdd1-supply: true
vdd2-supply: true
vss2-supply: true
ctrl-gpios:
items:
- description: VA control pin
- description: VB control pin
adi,external-bypass-a-gain-db:
description:
Gain in dB of external amplifier connected to bypass path A (OUT_A/IN_A).
When specified, this gain value becomes selectable via the hardwaregain
attribute and automatically routes through the external A path.
adi,external-bypass-b-gain-db:
description:
Gain in dB of external amplifier connected to bypass path B (OUT_B/IN_B).
When specified, this gain value becomes selectable via the hardwaregain
attribute and automatically routes through the external B path.
required:
- compatible
- ctrl-gpios
- vdd1-supply
- vdd2-supply
- vss2-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
/* Basic configuration with only internal paths */
amplifier {
compatible = "adi,adl8113";
ctrl-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>,
<&gpio 23 GPIO_ACTIVE_HIGH>;
vdd1-supply = <&vdd1_5v>;
vdd2-supply = <&vdd2_3v3>;
vss2-supply = <&vss2_neg>;
};
- |
#include <dt-bindings/gpio/gpio.h>
/* Configuration with external bypass amplifiers */
amplifier {
compatible = "adi,adl8113";
ctrl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>,
<&gpio 25 GPIO_ACTIVE_HIGH>;
vdd1-supply = <&vdd1_5v>;
vdd2-supply = <&vdd2_3v3>;
vss2-supply = <&vss2_neg>;
adi,external-bypass-a-gain-db = <20>; /* 20dB external amp on path A */
adi,external-bypass-b-gain-db = <6>; /* 6dB external amp on path B */
};
...

View file

@ -0,0 +1,120 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/dac/adi,max22007.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices MAX22007 DAC
maintainers:
- Janani Sunil <janani.sunil@analog.com>
description:
The MAX22007 is a quad-channel, 12-bit digital-to-analog converter (DAC)
with integrated precision output amplifiers and current output capability.
Each channel can be independently configured for voltage or current output.
Datasheet available at https://www.analog.com/en/products/max22007.html
$ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
const: adi,max22007
reg:
maxItems: 1
spi-max-frequency:
maximum: 500000
'#address-cells':
const: 1
'#size-cells':
const: 0
vdd-supply:
description: Low-Voltage Power Supply from +2.7V to +5.5V.
hvdd-supply:
description:
Positive High-Voltage Power Supply from +8V to (HVSS +24V) for
the Output Channels.
hvss-supply:
description:
Optional Negative High-Voltage Power Supply from -2V to 0V for the Output
Channels. For most applications HVSS can be connected to GND (0V), but for
applications requiring output down to true 0V or 0mA, connect to a -2V supply.
reset-gpios:
maxItems: 1
description:
Active low GPIO.
patternProperties:
"^channel@[0-3]$":
$ref: /schemas/iio/dac/dac.yaml#
type: object
description:
Represents the external channels which are connected to the DAC.
properties:
reg:
description: Channel number
items:
minimum: 0
maximum: 3
adi,ch-func:
description:
Channel output type. Use CH_FUNC_VOLTAGE_OUTPUT for voltage
output or CH_FUNC_CURRENT_OUTPUT for current output.
$ref: /schemas/types.yaml#/definitions/uint32
enum: [1, 2]
required:
- reg
- adi,ch-func
unevaluatedProperties: false
required:
- compatible
- reg
- vdd-supply
- hvdd-supply
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/iio/addac/adi,ad74413r.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
dac@0 {
compatible = "adi,max22007";
reg = <0>;
spi-max-frequency = <500000>;
reset-gpios = <&gpio 19 GPIO_ACTIVE_LOW>;
vdd-supply = <&vdd_reg>;
hvdd-supply = <&hvdd_reg>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
adi,ch-func = <CH_FUNC_VOLTAGE_OUTPUT>;
};
channel@1 {
reg = <1>;
adi,ch-func = <CH_FUNC_CURRENT_OUTPUT>;
};
};
};
...

View file

@ -0,0 +1,302 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/dac/microchip,mcp47feb02.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip MCP47F(E/V)B(0/1/2)(1/2/4/8) DAC with I2C Interface Families
maintainers:
- Ariana Lazar <ariana.lazar@microchip.com>
description: |
Datasheet for MCP47FEB01, MCP47FEB11, MCP47FEB21, MCP47FEB02, MCP47FEB12,
MCP47FEB22 can be found here:
https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005375A.pdf
Datasheet for MCP47FVB01, MCP47FVB11, MCP47FVB21, MCP47FVB02, MCP47FVB12,
MCP47FVB22 can be found here:
https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005405A.pdf
Datasheet for MCP47FEB04, MCP47FEB14, MCP47FEB24, MCP47FEB08, MCP47FEB18,
MCP47FEB28, MCP47FVB04, MCP47FVB14, MCP47FVB24, MCP47FVB08, MCP47FVB18,
MCP47FVB28 can be found here:
https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP47FXBX48-Data-Sheet-DS200006368A.pdf
+------------+--------------+-------------+-------------+------------+
| Device | Resolution | Channels | Vref number | Memory |
|------------|--------------|-------------|-------------|------------|
| MCP47FEB01 | 8-bit | 1 | 1 | EEPROM |
| MCP47FEB11 | 10-bit | 1 | 1 | EEPROM |
| MCP47FEB21 | 12-bit | 1 | 1 | EEPROM |
|------------|--------------|-------------|-------------|------------|
| MCP47FEB02 | 8-bit | 2 | 1 | EEPROM |
| MCP47FEB12 | 10-bit | 2 | 1 | EEPROM |
| MCP47FEB22 | 12-bit | 2 | 1 | EEPROM |
|------------|--------------|-------------|-------------|------------|
| MCP47FVB01 | 8-bit | 1 | 1 | RAM |
| MCP47FVB11 | 10-bit | 1 | 1 | RAM |
| MCP47FVB21 | 12-bit | 1 | 1 | RAM |
|------------|--------------|-------------|-------------|------------|
| MCP47FVB02 | 8-bit | 2 | 1 | RAM |
| MCP47FVB12 | 10-bit | 2 | 1 | RAM |
| MCP47FVB22 | 12-bit | 2 | 1 | RAM |
|------------|--------------|-------------|-------------|------------|
| MCP47FVB04 | 8-bit | 4 | 2 | RAM |
| MCP47FVB14 | 10-bit | 4 | 2 | RAM |
| MCP47FVB24 | 12-bit | 4 | 2 | RAM |
|------------|--------------|-------------|-------------|------------|
| MCP47FVB08 | 8-bit | 8 | 2 | RAM |
| MCP47FVB18 | 10-bit | 8 | 2 | RAM |
| MCP47FVB28 | 12-bit | 8 | 2 | RAM |
|------------|--------------|-------------|-------------|------------|
| MCP47FEB04 | 8-bit | 4 | 2 | EEPROM |
| MCP47FEB14 | 10-bit | 4 | 2 | EEPROM |
| MCP47FEB24 | 12-bit | 4 | 2 | EEPROM |
|------------|--------------|-------------|-------------|------------|
| MCP47FEB08 | 8-bit | 8 | 2 | EEPROM |
| MCP47FEB18 | 10-bit | 8 | 2 | EEPROM |
| MCP47FEB28 | 12-bit | 8 | 2 | EEPROM |
+------------+--------------+-------------+-------------+------------+
properties:
compatible:
enum:
- microchip,mcp47feb01
- microchip,mcp47feb11
- microchip,mcp47feb21
- microchip,mcp47feb02
- microchip,mcp47feb12
- microchip,mcp47feb22
- microchip,mcp47fvb01
- microchip,mcp47fvb11
- microchip,mcp47fvb21
- microchip,mcp47fvb02
- microchip,mcp47fvb12
- microchip,mcp47fvb22
- microchip,mcp47fvb04
- microchip,mcp47fvb14
- microchip,mcp47fvb24
- microchip,mcp47fvb08
- microchip,mcp47fvb18
- microchip,mcp47fvb28
- microchip,mcp47feb04
- microchip,mcp47feb14
- microchip,mcp47feb24
- microchip,mcp47feb08
- microchip,mcp47feb18
- microchip,mcp47feb28
reg:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 0
vdd-supply:
description:
Provides power to the chip and it could be used as reference voltage. The
voltage is used to calculate scale. For parts without EEPROM at powerup
this will be the selected as voltage reference.
vref-supply:
description: |
Vref pin (it could be found as Vref0 into the datasheet) may be used as a
voltage reference when this supply is specified. The internal reference
will be taken into account for voltage reference besides VDD if this supply
does not exist.
This supply will be voltage reference for the following outputs:
- for single-channel device: Vout0;
- for dual-channel device: Vout0, Vout1;
- for quad-channel device: Vout0, Vout2;
- for octal-channel device: Vout0, Vout2, Vout6, Vout8;
vref1-supply:
description: |
Vref1 pin may be used as a voltage reference when this supply is specified.
The internal reference will be taken into account for voltage reference
beside VDD if this supply does not exist.
This supply will be voltage reference for the following outputs:
- for quad-channel device: Vout1, Vout3;
- for octal-channel device: Vout1, Vout3, Vout5, Vout7;
lat-gpios:
description:
LAT pin to be used as a hardware trigger to synchronously update the DAC
channels. The pin is active Low. It could be also found as LAT0 in
datasheet.
maxItems: 1
lat1-gpios:
description:
LAT1 pin to be used as a hardware trigger to synchronously update the odd
DAC channels on devices with 4 and 8 channels. The pin is active Low.
maxItems: 1
microchip,vref-buffered:
type: boolean
description:
Enable buffering of the external Vref/Vref0 pin in cases where the
external reference voltage does not have sufficient current capability in
order not to drop its voltage when connected to the internal resistor
ladder circuit.
microchip,vref1-buffered:
type: boolean
description:
Enable buffering of the external Vref1 pin in cases where the external
reference voltage does not have sufficient current capability in order not
to drop its voltage when connected to the internal resistor ladder
circuit.
patternProperties:
"^channel@[0-7]$":
$ref: dac.yaml
type: object
description: Voltage output channel.
properties:
reg:
description: The channel number.
minItems: 1
maxItems: 8
label:
description: Unique name to identify which channel this is.
required:
- reg
unevaluatedProperties: false
required:
- compatible
- reg
- vdd-supply
allOf:
- if:
properties:
compatible:
contains:
enum:
- microchip,mcp47feb01
- microchip,mcp47feb11
- microchip,mcp47feb21
- microchip,mcp47fvb01
- microchip,mcp47fvb11
- microchip,mcp47fvb21
then:
properties:
lat1-gpios: false
vref1-supply: false
microchip,vref1-buffered: false
channel@0:
properties:
reg:
const: 0
patternProperties:
"^channel@[1-7]$": false
- if:
properties:
compatible:
contains:
enum:
- microchip,mcp47feb02
- microchip,mcp47feb12
- microchip,mcp47feb22
- microchip,mcp47fvb02
- microchip,mcp47fvb12
- microchip,mcp47fvb22
then:
properties:
lat1-gpios: false
vref1-supply: false
microchip,vref1-buffered: false
patternProperties:
"^channel@[0-1]$":
properties:
reg:
enum: [0, 1]
"^channel@[2-7]$": false
- if:
properties:
compatible:
contains:
enum:
- microchip,mcp47fvb04
- microchip,mcp47fvb14
- microchip,mcp47fvb24
- microchip,mcp47feb04
- microchip,mcp47feb14
- microchip,mcp47feb24
then:
patternProperties:
"^channel@[0-3]$":
properties:
reg:
enum: [0, 1, 2, 3]
"^channel@[4-7]$": false
- if:
properties:
compatible:
contains:
enum:
- microchip,mcp47fvb08
- microchip,mcp47fvb18
- microchip,mcp47fvb28
- microchip,mcp47feb08
- microchip,mcp47feb18
- microchip,mcp47feb28
then:
patternProperties:
"^channel@[0-7]$":
properties:
reg:
enum: [0, 1, 2, 3, 4, 5, 6, 7]
- if:
not:
required:
- vref-supply
then:
properties:
microchip,vref-buffered: false
- if:
not:
required:
- vref1-supply
then:
properties:
microchip,vref1-buffered: false
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
dac@0 {
compatible = "microchip,mcp47feb02";
reg = <0>;
vdd-supply = <&vdac_vdd>;
vref-supply = <&vref_reg>;
#address-cells = <1>;
#size-cells = <0>;
channel@0 {
reg = <0>;
label = "Adjustable_voltage_ch0";
};
channel@1 {
reg = <0x1>;
label = "Adjustable_voltage_ch1";
};
};
};
...

View file

@ -40,6 +40,12 @@ properties:
items:
- const: ref_in
'#clock-cells':
const: 0
clock-output-names:
maxItems: 1
chip-enable-gpios:
description:
GPIO that controls the Chip Enable Pin.
@ -97,6 +103,8 @@ examples:
spi-max-frequency = <10000000>;
clocks = <&adf4377_ref_in>;
clock-names = "ref_in";
#clock-cells = <0>;
clock-output-names = "adf4377";
};
};
...

View file

@ -0,0 +1,132 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/pressure/honeywell,abp2030pa.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Honeywell abp2030pa pressure sensor
maintainers:
- Petre Rodan <petre.rodan@subdimension.ro>
description: |
Honeywell pressure sensor of model abp2030pa.
This sensor has an I2C and SPI interface.
There are many models with different pressure ranges available. The vendor
calls them "ABP2 series". All of them have an identical programming model and
differ in the pressure range and measurement unit.
To support different models one needs to specify its pressure triplet.
For custom silicon chips not covered by the Honeywell ABP2 series datasheet,
the pressure values can be specified manually via honeywell,pmin-pascal and
honeywell,pmax-pascal.
Specifications about the devices can be found at:
https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/basic-abp2-series/documents/sps-siot-abp2-series-datasheet-32350268-en.pdf
properties:
compatible:
const: honeywell,abp2030pa
reg:
maxItems: 1
interrupts:
description:
Optional interrupt for indicating end of conversion.
SPI variants of ABP2 chips do not provide this feature.
maxItems: 1
honeywell,pressure-triplet:
description: |
Case-sensitive five character string that defines pressure range, unit
and type as part of the device nomenclature. In the unlikely case of a
custom chip, unset and provide pmin-pascal and pmax-pascal instead.
enum: [001BA, 1.6BA, 2.5BA, 004BA, 006BA, 008BA, 010BA, 012BA, 001BD,
1.6BD, 2.5BD, 004BD, 001BG, 1.6BG, 2.5BG, 004BG, 006BG, 008BG,
010BG, 012BG, 001GG, 1.2GG, 100KA, 160KA, 250KA, 001KD, 1.6KD,
2.5KD, 004KD, 006KD, 010KD, 016KD, 025KD, 040KD, 060KD, 100KD,
160KD, 250KD, 400KD, 001KG, 1.6KG, 2.5KG, 004KG, 006KG, 010KG,
016KG, 025KG, 040KG, 060KG, 100KG, 160KG, 250KG, 400KG, 600KG,
800KG, 250LD, 600LD, 600LG, 2.5MD, 006MD, 010MD, 016MD, 025MD,
040MD, 060MD, 100MD, 160MD, 250MD, 400MD, 600MD, 006MG, 010MG,
016MG, 025MG, 040MG, 060MG, 100MG, 160MG, 250MG, 400MG, 600MG,
001ND, 002ND, 004ND, 005ND, 010ND, 020ND, 030ND, 002NG, 004NG,
005NG, 010NG, 020NG, 030NG, 015PA, 030PA, 060PA, 100PA, 150PA,
175PA, 001PD, 005PD, 015PD, 030PD, 060PD, 001PG, 005PG, 015PG,
030PG, 060PG, 100PG, 150PG, 175PG]
$ref: /schemas/types.yaml#/definitions/string
honeywell,pmin-pascal:
description:
Minimum pressure value the sensor can measure in pascal.
honeywell,pmax-pascal:
description:
Maximum pressure value the sensor can measure in pascal.
spi-max-frequency:
maximum: 800000
vdd-supply: true
required:
- compatible
- reg
- vdd-supply
oneOf:
- required:
- honeywell,pressure-triplet
- required:
- honeywell,pmin-pascal
- honeywell,pmax-pascal
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml
- if:
required:
- honeywell,pressure-triplet
then:
properties:
honeywell,pmin-pascal: false
honeywell,pmax-pascal: false
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
pressure@18 {
compatible = "honeywell,abp2030pa";
reg = <0x18>;
interrupt-parent = <&gpio3>;
interrupts = <21 IRQ_TYPE_EDGE_RISING>;
honeywell,pressure-triplet = "001BA";
vdd-supply = <&vcc_3v3>;
};
};
- |
spi {
#address-cells = <1>;
#size-cells = <0>;
pressure@0 {
compatible = "honeywell,abp2030pa";
reg = <0>;
spi-max-frequency = <800000>;
honeywell,pressure-triplet = "001PD";
vdd-supply = <&vcc_3v3>;
};
};
...

View file

@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/iio/proximity/rfdigital,rfd77402.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: RF Digital RFD77402 ToF sensor
maintainers:
- Shrikant Raskar <raskar.shree97@gmail.com>
description:
The RF Digital RFD77402 is a Time-of-Flight (ToF) proximity and distance
sensor providing up to 200 mm range measurement over an I2C interface.
properties:
compatible:
const: rfdigital,rfd77402
reg:
maxItems: 1
interrupts:
maxItems: 1
description:
Interrupt asserted when a new distance measurement is available.
vdd-supply:
description: Regulator that provides power to the sensor.
required:
- compatible
- reg
- vdd-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
proximity@4c {
compatible = "rfdigital,rfd77402";
reg = <0x4c>;
vdd-supply = <&vdd_3v3>;
interrupt-parent = <&gpio>;
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
};
};
...

View file

@ -40,6 +40,7 @@ properties:
enum:
- mediatek,mt8183-emi
- mediatek,mt8195-emi
- mediatek,mt8196-emi
'#interconnect-cells':
const: 1

View file

@ -25,6 +25,7 @@ properties:
- const: qcom,msm8998-bwmon # BWMON v4
- items:
- enum:
- qcom,glymur-cpu-bwmon
- qcom,kaanapali-cpu-bwmon
- qcom,qcm2290-cpu-bwmon
- qcom,qcs615-cpu-bwmon

View file

@ -27,7 +27,6 @@ properties:
- qcom,qcs615-config-noc
- qcom,qcs615-dc-noc
- qcom,qcs615-gem-noc
- qcom,qcs615-ipa-virt
- qcom,qcs615-mc-virt
- qcom,qcs615-mmss-noc
- qcom,qcs615-system-noc
@ -46,7 +45,6 @@ allOf:
contains:
enum:
- qcom,qcs615-camnoc-virt
- qcom,qcs615-ipa-virt
- qcom,qcs615-mc-virt
then:
properties:

View file

@ -0,0 +1,38 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/misc/google,android-pipe.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Android Goldfish QEMU Pipe
maintainers:
- Kuan-Wei Chiu <visitorckw@gmail.com>
description:
Android QEMU pipe virtual device generated by Android emulator.
properties:
compatible:
const: google,android-pipe
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
- interrupts
additionalProperties: false
examples:
- |
pipe@ff018000 {
compatible = "google,android-pipe";
reg = <0xff018000 0x2000>;
interrupts = <18>;
};

View file

@ -18,7 +18,9 @@ description: |
properties:
compatible:
const: qcom,fastrpc
enum:
- qcom,kaanapali-fastrpc
- qcom,fastrpc
label:
enum:

View file

@ -55,6 +55,7 @@ properties:
- qcom,sm8450-qfprom
- qcom,sm8550-qfprom
- qcom,sm8650-qfprom
- qcom,sm8750-qfprom
- qcom,x1e80100-qfprom
- const: qcom,qfprom

View file

@ -0,0 +1,138 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spmi/mediatek,mt8196-spmi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: MediaTek MT8196 SPMI 2.0 Controller
maintainers:
- Hsin-Hsiung Wang <hsin-hsiung.wang@mediatek.com>
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
description:
The MediaTek MT8196 SoC features a SPMI version 2.0 compliant controller,
with internal wrapping arbitration logic to allow for multiple on-chip
devices to control up to two SPMI buses.
The main arbiter also acts as an interrupt controller, arbitering also
the interrupts coming from SPMI-connected devices into each of the nested
interrupt controllers from any of the present SPMI buses.
properties:
compatible:
oneOf:
- enum:
- mediatek,mt8196-spmi
- items:
- enum:
- mediatek,mt6991-spmi
- const: mediatek,mt8196-spmi
ranges: true
'#address-cells':
const: 1
'#size-cells':
const: 1
patternProperties:
"^spmi@[a-f0-9]+$":
type: object
$ref: /schemas/spmi/spmi.yaml
unevaluatedProperties: false
properties:
reg:
items:
- description: controller interface registers
- description: spmi master controller registers
reg-names:
items:
- const: pmif
- const: spmimst
clocks:
items:
- description: controller interface system clock
- description: controller interface timer clock
- description: spmi controller master clock
clock-names:
items:
- const: pmif_sys_ck
- const: pmif_tmr_ck
- const: spmimst_clk_mux
interrupts:
maxItems: 1
interrupt-names:
const: rcs
interrupt-controller: true
"#interrupt-cells":
const: 3
description: |
cell 1: slave ID for the requested interrupt (0-15)
cell 2: the requested peripheral interrupt (0-7)
cell 3: interrupt flags indicating level-sense information,
as defined in dt-bindings/interrupt-controller/irq.h
required:
- reg
- reg-names
- clocks
- clock-names
- interrupts
- interrupt-names
- interrupt-controller
- "#interrupt-cells"
required:
- compatible
- ranges
- '#address-cells'
- '#size-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
spmi-arbiter@1c018000 {
compatible = "mediatek,mt8196-spmi";
ranges = <0 0 0x1c018000 0x4900>;
#address-cells = <1>;
#size-cells = <1>;
spmi@0 {
reg = <0 0x900>, <0x4800 0x100>;
reg-names = "pmif", "spmimst";
interrupts-extended = <&pio 292 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "rcs";
interrupt-controller;
#interrupt-cells = <3>;
clocks = <&pmif_sys>, <&pmif_tmr>, <&spmi_mst>;
clock-names = "pmif_sys_ck", "pmif_tmr_ck", "spmimst_clk_mux";
};
spmi@2000 {
reg = <0x2000 0x900>, <0x4000 0x100>;
reg-names = "pmif", "spmimst";
interrupts-extended = <&pio 291 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "rcs";
interrupt-controller;
#interrupt-cells = <3>;
clocks = <&pmif_sys>, <&pmif_tmr>, <&spmi_mst>;
clock-names = "pmif_sys_ck", "pmif_tmr_ck", "spmimst_clk_mux";
};
};
};
...

View file

@ -26,6 +26,7 @@ properties:
- enum:
- mediatek,mt8186-spmi
- mediatek,mt8188-spmi
- mediatek,mt8189-spmi
- const: mediatek,mt8195-spmi
reg:

View file

@ -0,0 +1,150 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spmi/qcom,glymur-spmi-pmic-arb.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. Glymur SPMI Controller (PMIC Arbiter v8)
maintainers:
- David Collins <david.collins@oss.qualcomm.com>
description: |
The Glymur SPMI PMIC Arbiter implements HW version 8 and it's an SPMI
controller with wrapping arbitration logic to allow for multiple on-chip
devices to control up to 4 SPMI separate buses.
The PMIC Arbiter can also act as an interrupt controller, providing interrupts
to slave devices.
allOf:
- $ref: /schemas/spmi/qcom,spmi-pmic-arb-common.yaml
properties:
compatible:
oneOf:
- items:
- enum:
- qcom,kaanapali-spmi-pmic-arb
- const: qcom,glymur-spmi-pmic-arb
- enum:
- qcom,glymur-spmi-pmic-arb
reg:
items:
- description: core registers
- description: tx-channel per virtual slave registers
- description: rx-channel (called observer) per virtual slave registers
- description: channel to PMIC peripheral mapping registers
reg-names:
items:
- const: core
- const: chnls
- const: obsrvr
- const: chnl_map
ranges: true
'#address-cells':
const: 2
'#size-cells':
const: 2
patternProperties:
"^spmi@[a-f0-9]+$":
type: object
$ref: /schemas/spmi/spmi.yaml
unevaluatedProperties: false
properties:
reg:
items:
- description: configuration registers
- description: interrupt controller registers
- description: channel owner EE mapping registers
reg-names:
items:
- const: cnfg
- const: intr
- const: chnl_owner
interrupts:
maxItems: 1
interrupt-names:
const: periph_irq
interrupt-controller: true
'#interrupt-cells':
const: 4
description: |
cell 1: slave ID for the requested interrupt (0-15)
cell 2: peripheral ID for requested interrupt (0-255)
cell 3: the requested peripheral interrupt (0-7)
cell 4: interrupt flags indicating level-sense information,
as defined in dt-bindings/interrupt-controller/irq.h
required:
- compatible
- reg-names
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
arbiter@c400000 {
compatible = "qcom,glymur-spmi-pmic-arb";
reg = <0x0 0xc400000 0x0 0x3000>,
<0x0 0xc900000 0x0 0x400000>,
<0x0 0xc4c0000 0x0 0x400000>,
<0x0 0xc403000 0x0 0x8000>;
reg-names = "core", "chnls", "obsrvr", "chnl_map";
qcom,ee = <0>;
qcom,channel = <0>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
spmi@c426000 {
reg = <0x0 0xc426000 0x0 0x4000>,
<0x0 0xc8c0000 0x0 0x10000>,
<0x0 0xc42a000 0x0 0x8000>;
reg-names = "cnfg", "intr", "chnl_owner";
interrupts-extended = <&pdc 1 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "periph_irq";
interrupt-controller;
#interrupt-cells = <4>;
#address-cells = <2>;
#size-cells = <0>;
};
spmi@c437000 {
reg = <0x0 0xc437000 0x0 0x4000>,
<0x0 0xc8d0000 0x0 0x10000>,
<0x0 0xc43b000 0x0 0x8000>;
reg-names = "cnfg", "intr", "chnl_owner";
interrupts-extended = <&pdc 3 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "periph_irq";
interrupt-controller;
#interrupt-cells = <4>;
#address-cells = <2>;
#size-cells = <0>;
};
};
};

View file

@ -0,0 +1,35 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/spmi/qcom,spmi-pmic-arb-common.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SPMI Controller (common)
maintainers:
- David Collins <david.collins@oss.qualcomm.com>
description: |
This defines some common properties used to define Qualcomm SPMI controllers
for PMIC arbiter.
properties:
qcom,ee:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 5
description:
indicates the active Execution Environment identifier
qcom,channel:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 5
description:
which of the PMIC Arb provided channels to use for accesses
required:
- qcom,ee
- qcom,channel
additionalProperties: true

View file

@ -19,6 +19,7 @@ description: |
allOf:
- $ref: spmi.yaml
- $ref: qcom,spmi-pmic-arb-common.yaml
properties:
compatible:
@ -71,20 +72,6 @@ properties:
'#size-cells': true
qcom,ee:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 5
description: >
indicates the active Execution Environment identifier
qcom,channel:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 5
description: >
which of the PMIC Arb provided channels to use for accesses
qcom,bus-id:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
@ -97,8 +84,6 @@ properties:
required:
- compatible
- reg-names
- qcom,ee
- qcom,channel
unevaluatedProperties: false

View file

@ -17,6 +17,9 @@ description: |
The PMIC Arbiter can also act as an interrupt controller, providing interrupts
to slave devices.
allOf:
- $ref: qcom,spmi-pmic-arb-common.yaml
properties:
compatible:
oneOf:
@ -45,20 +48,6 @@ properties:
'#size-cells':
const: 2
qcom,ee:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 5
description: >
indicates the active Execution Environment identifier
qcom,channel:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 5
description: >
which of the PMIC Arb provided channels to use for accesses
patternProperties:
"^spmi@[a-f0-9]+$":
type: object
@ -96,10 +85,8 @@ patternProperties:
required:
- compatible
- reg-names
- qcom,ee
- qcom,channel
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View file

@ -237,6 +237,10 @@ properties:
- meas,tsys01
# MEMSIC magnetometer
- memsic,mmc35240
# MEMSIC 3-axis magnetometer
- memsic,mmc5603
# MEMSIC 3-axis magnetometer (Support I3C HDR)
- memsic,mmc5633
# MEMSIC 3-axis accelerometer
- memsic,mxc4005
# MEMSIC 2-axis 8-bit digital accelerometer

View file

@ -1373,6 +1373,8 @@ patternProperties:
description: Revolution Robotics, Inc. (Revotics)
"^rex,.*":
description: iMX6 Rex Project
"^rfdigital,.*":
description: RF Digital Corporation
"^richtek,.*":
description: Richtek Technology Corporation
"^ricoh,.*":

View file

@ -0,0 +1,148 @@
.. SPDX-License-Identifier: GPL-2.0-only
=============
AD4062 driver
=============
ADC driver for Analog Devices Inc. AD4060/AD4062 devices. The module name is
``ad4062``.
Supported devices
=================
The following chips are supported by this driver:
* `AD4060 <https://www.analog.com/AD4060>`_
* `AD4062 <https://www.analog.com/AD4062>`_
Wiring modes
============
The ADC is interfaced through an I3C bus, and contains two programmable GPIOs.
The ADC convert-start happens on the SDA rising edge of the I3C stop (P) bit
at the end of the read command.
The two programmable GPIOS are optional and have a role assigned if present in
the devicetree ``interrupt-names`` property:
- GP0: Is assigned the role of Threshold Either signal.
- GP1: Is assigned the role of Data Ready signal.
If the property ``gpio-controller`` is present in the devicetree, then the GPO
not present in the ``interrupt-names`` is exposed as a GPO.
Device attributes
=================
The ADC contains only one channel with following attributes:
.. list-table:: Channel attributes
:header-rows: 1
* - Attribute
- Description
* - ``in_voltage_calibscale``
- Sets the gain scaling factor that the hardware applies to the sample,
to compensate for system gain error.
* - ``in_voltage_oversampling_ratio``
- Sets device's burst averaging mode to over sample using the
internal sample rate. Value 1 disable the burst averaging mode.
* - ``in_voltage_oversampling_ratio_available``
- List of available oversampling values.
* - ``in_voltage_raw``
- Returns the raw ADC voltage value.
* - ``in_voltage_scale``
- Returns the channel scale in reference to the reference voltage
``ref-supply`` or ``vdd-supply`` if the former not present.
Also contain the following device attributes:
.. list-table:: Device attributes
:header-rows: 1
* - Attribute
- Description
* - ``sampling_frequency``
- Sets the duration of a single scan, used in the burst averaging mode.
The duration is described by ``(n_avg - 1) / fosc + tconv``, where
``n_avg`` is the oversampling ratio, ``fosc`` is the internal sample
rate and ``tconv`` is the ADC conversion time.
* - ``sampling_frequency_available``
- Lists the available sampling frequencies, computed on the current
oversampling ratio. If the ratio is 1, the frequency is ``1/tconv``.
Interrupts
==========
The interrupts are mapped through the ``interrupt-names`` and ``interrupts``
properties.
The ``interrupt-names`` ``gp0`` entry sets the role of Threshold signal, and
entry ``gp1`` the role of Data Ready signal.
If each is not present, the driver fallback to enabling the same role as an
I3C IBI.
Low-power mode
==============
The device enters low-power mode on idle to save power. Enabling an event puts
the device out of the low-power since the ADC autonomously samples to assert
the event condition.
IIO trigger support
===================
An IIO trigger ``ad4062-devX`` is registered by the driver to be used by the
same device, to capture samples to a software buffer. It is required to attach
the trigger to the device by setting the ``current_trigger`` before enabling
and reading the buffer.
The acquisition is sequential and bounded by the protocol timings, software
latency and internal timings, the sample rate is not configurable. The burst
averaging mode does impact the effective sample rate, since it increases the
internal timing to output a single sample.
Threshold events
================
The ADC supports a monitoring mode to raise threshold events. The driver
supports a single interrupt for both rising and falling readings.
The feature is enabled/disabled by setting ``thresh_either_en``. During monitor
mode, the device continuously operates in autonomous mode. Any register access
puts the device back in configuration mode, due to this, any access disables
monitor mode.
The following event attributes are available:
.. list-table:: Event attributes
:header-rows: 1
* - Attribute
- Description
* - ``sampling_frequency``
- Frequency used in the monitoring mode, sets the device internal sample
rate when the mode is activated.
* - ``sampling_frequency_available``
- List of available sample rates.
* - ``thresh_either_en``
- Enable monitoring mode.
* - ``thresh_falling_hysteresis``
- Set the hysteresis value for the minimum threshold.
* - ``thresh_falling_value``
- Set the minimum threshold value.
* - ``thresh_rising_hysteresis``
- Set the hysteresis value for the maximum threshold.
* - ``thresh_rising_value``
- Set the maximum threshold value.
GPO controller support
======================
The device supports using GP0 and GP1 as GPOs. If the devicetree contains the
node ``gpio-controller```, the device is marked as a GPIO controller and the
GPs not listed in ``interrupt-names`` are exposed as a GPO. The GPIO index
matches the pin name, so if GP0 is not exposed but GP1 is, index 0 is masked
out and only index 1 can be set.

View file

@ -22,6 +22,7 @@ Industrial I/O Kernel Drivers
ad3552r
ad4000
ad4030
ad4062
ad4695
ad7191
ad7380

View file

@ -613,8 +613,20 @@ They are also listed in the folder /sys/bus/event_source/devices/cs_etm/format/
- Session local version of the system wide setting: :ref:`ETM_MODE_RETURNSTACK
<coresight-return-stack>`
* - timestamp
- Session local version of the system wide setting: :ref:`ETMv4_MODE_TIMESTAMP
<coresight-timestamp>`
- Controls generation and interval of timestamps.
0 = off, 1 = minimum interval .. 15 = maximum interval.
Values 1 - 14 use a counter that decrements every cycle to generate a
timestamp on underflow. The reload value for the counter is 2 ^ (interval
- 1). If the value is 1 then the reload value is 1, if the value is 11
then the reload value is 1024 etc.
Setting the maximum interval (15) will disable the counter generated
timestamps, freeing the counter resource, leaving only ones emitted when
a SYNC packet is generated. The sync interval is controlled with
TRCSYNCPR.PERIOD which is every 4096 bytes of trace by default.
* - cc_threshold
- Cycle count threshold value. If nothing is provided here or the provided value is 0, then the
default value i.e 0x100 will be used. If provided value is less than minimum cycles threshold

View file

@ -397,7 +397,6 @@ Code Seq# Include File Comments
0xCD 01 linux/reiserfs_fs.h Dead since 6.13
0xCE 01-02 uapi/linux/cxl_mem.h Compute Express Link Memory Devices
0xCF 02 fs/smb/client/cifs_ioctl.h
0xDB 00-0F drivers/char/mwave/mwavepub.h
0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
<mailto:aherrman@de.ibm.com>
0xE5 00-3F linux/fuse.h

View file

@ -1444,6 +1444,14 @@ F: Documentation/devicetree/bindings/iio/adc/adi,ad4030.yaml
F: Documentation/iio/ad4030.rst
F: drivers/iio/adc/ad4030.c
ANALOG DEVICES INC AD4062 DRIVER
M: Jorge Marques <jorge.marques@analog.com>
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ad4062.yaml
F: Documentation/iio/ad4062.rst
F: drivers/iio/adc/ad4062.c
ANALOG DEVICES INC AD4080 DRIVER
M: Antoniu Miclaus <antoniu.miclaus@analog.com>
L: linux-iio@vger.kernel.org
@ -1461,6 +1469,14 @@ F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
F: drivers/iio/adc/ad4130.c
ANALOG DEVICES INC AD4134 DRIVER
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ad4134.yaml
F: drivers/iio/adc/ad4134.c
ANALOG DEVICES INC AD4170-4 DRIVER
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
L: linux-iio@vger.kernel.org
@ -1605,6 +1621,14 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/dac/adi,ad9739a.yaml
F: drivers/iio/dac/ad9739a.c
ANALOG DEVICES INC MAX22007 DRIVER
M: Janani Sunil <janani.sunil@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,max22007.yaml
F: drivers/iio/dac/max22007.c
ANALOG DEVICES INC ADA4250 DRIVER
M: Antoniu Miclaus <antoniu.miclaus@analog.com>
L: linux-iio@vger.kernel.org
@ -1613,6 +1637,14 @@ W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/amplifiers/adi,ada4250.yaml
F: drivers/iio/amplifiers/ada4250.c
ANALOG DEVICES INC ADE9000 DRIVER
M: Antoniu Miclaus <antoniu.miclaus@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
F: Documentation/devicetree/bindings/iio/adc/adi,ade9000.yaml
F: drivers/iio/adc/ade9000.c
ANALOG DEVICES INC ADF4377 DRIVER
M: Antoniu Miclaus <antoniu.miclaus@analog.com>
L: linux-iio@vger.kernel.org
@ -11620,6 +11652,13 @@ F: lib/test_hmm*
F: mm/hmm*
F: tools/testing/selftests/mm/*hmm*
HONEYWELL ABP2030PA PRESSURE SENSOR SERIES IIO DRIVER
M: Petre Rodan <petre.rodan@subdimension.ro>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/iio/pressure/honeywell,abp2030pa.yaml
F: drivers/iio/pressure/abp2030pa*
HONEYWELL HSC030PA PRESSURE SENSOR SERIES IIO DRIVER
M: Petre Rodan <petre.rodan@subdimension.ro>
L: linux-iio@vger.kernel.org
@ -13090,8 +13129,9 @@ S: Orphan
F: drivers/ptp/ptp_dfl_tod.c
INTEL QUADRATURE ENCODER PERIPHERAL DRIVER
M: Jarkko Nikula <jarkko.nikula@linux.intel.com>
M: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
L: linux-iio@vger.kernel.org
S: Supported
F: drivers/counter/intel-qep.c
INTEL SCU DRIVERS
@ -15785,6 +15825,13 @@ F: Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
F: drivers/iio/potentiometer/mcp4018.c
F: drivers/iio/potentiometer/mcp4531.c
MCP47FEB02 MICROCHIP DAC DRIVER
M: Ariana Lazar <ariana.lazar@microchip.com>
L: linux-iio@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
F: drivers/iio/dac/mcp47feb02.c
MCP4821 DAC DRIVER
M: Anshul Dalal <anshulusr@gmail.com>
L: linux-iio@vger.kernel.org
@ -26287,6 +26334,13 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/adc/ti,ads1119.yaml
F: drivers/iio/adc/ti-ads1119.c
TI ADS1018 ADC DRIVER
M: Kurt Borja <kuurtb@gmail.com>
L: linux-iio@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/iio/adc/ti,ads1018.yaml
F: drivers/iio/adc/ti-ads1018.c
TI ADS7924 ADC DRIVER
M: Hugo Villeneuve <hvilleneuve@dimonoff.com>
L: linux-iio@vger.kernel.org

View file

@ -39,7 +39,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -55,7 +54,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -71,7 +69,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -87,7 +84,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -103,7 +99,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -119,7 +114,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -135,7 +129,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -151,7 +144,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -167,7 +159,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -183,7 +174,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -199,7 +189,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -215,7 +204,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -231,7 +219,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -247,7 +234,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -263,7 +249,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -279,7 +264,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -295,7 +279,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -311,7 +294,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -327,7 +309,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -343,7 +324,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -359,7 +339,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -375,7 +354,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -391,7 +369,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -407,7 +384,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -423,7 +399,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -439,7 +414,6 @@ static const struct mhi_channel_config aic100_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = true,
.wake_capable = false,
},
};
@ -458,7 +432,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -474,7 +447,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -490,7 +462,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -506,7 +477,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -522,7 +492,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -538,7 +507,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -554,7 +522,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -570,7 +537,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -586,7 +552,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -602,7 +567,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -618,7 +582,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -634,7 +597,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -650,7 +612,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -666,7 +627,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -682,7 +642,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -698,7 +657,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -714,7 +672,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.wake_capable = false,
},
{
@ -730,7 +687,6 @@ static const struct mhi_channel_config aic200_channels[] = {
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = true,
.wake_capable = false,
},
};

View file

@ -4523,7 +4523,7 @@ static int binder_thread_write(struct binder_proc *proc,
}
}
binder_debug(BINDER_DEBUG_DEAD_BINDER,
"%d:%d BC_DEAD_BINDER_DONE %016llx found %pK\n",
"%d:%d BC_DEAD_BINDER_DONE %016llx found %p\n",
proc->pid, thread->pid, (u64)cookie,
death);
if (death == NULL) {

View file

@ -3,8 +3,8 @@
// Copyright (C) 2025 Google LLC.
use kernel::{
error::Error,
list::{List, ListArc, ListLinks},
alloc::kvec::KVVec,
error::code::*,
prelude::*,
security,
str::{CStr, CString},
@ -17,22 +17,19 @@ use crate::{error::BinderError, node::NodeRef, process::Process};
kernel::sync::global_lock! {
// SAFETY: We call `init` in the module initializer, so it's initialized before first use.
pub(crate) unsafe(uninit) static CONTEXTS: Mutex<ContextList> = ContextList {
list: List::new(),
contexts: KVVec::new(),
};
}
pub(crate) struct ContextList {
list: List<Context>,
contexts: KVVec<Arc<Context>>,
}
pub(crate) fn get_all_contexts() -> Result<KVec<Arc<Context>>> {
pub(crate) fn get_all_contexts() -> Result<KVVec<Arc<Context>>> {
let lock = CONTEXTS.lock();
let count = lock.list.iter().count();
let mut ctxs = KVec::with_capacity(count, GFP_KERNEL)?;
for ctx in &lock.list {
ctxs.push(Arc::from(ctx), GFP_KERNEL)?;
let mut ctxs = KVVec::with_capacity(lock.contexts.len(), GFP_KERNEL)?;
for ctx in lock.contexts.iter() {
ctxs.push(ctx.clone(), GFP_KERNEL)?;
}
Ok(ctxs)
}
@ -42,7 +39,7 @@ pub(crate) fn get_all_contexts() -> Result<KVec<Arc<Context>>> {
struct Manager {
node: Option<NodeRef>,
uid: Option<Kuid>,
all_procs: List<Process>,
all_procs: KVVec<Arc<Process>>,
}
/// There is one context per binder file (/dev/binder, /dev/hwbinder, etc)
@ -51,28 +48,16 @@ pub(crate) struct Context {
#[pin]
manager: Mutex<Manager>,
pub(crate) name: CString,
#[pin]
links: ListLinks,
}
kernel::list::impl_list_arc_safe! {
impl ListArcSafe<0> for Context { untracked; }
}
kernel::list::impl_list_item! {
impl ListItem<0> for Context {
using ListLinks { self.links };
}
}
impl Context {
pub(crate) fn new(name: &CStr) -> Result<Arc<Self>> {
let name = CString::try_from(name)?;
let list_ctx = ListArc::pin_init::<Error>(
let ctx = Arc::pin_init(
try_pin_init!(Context {
name,
links <- ListLinks::new(),
manager <- kernel::new_mutex!(Manager {
all_procs: List::new(),
all_procs: KVVec::new(),
node: None,
uid: None,
}, "Context::manager"),
@ -80,8 +65,7 @@ impl Context {
GFP_KERNEL,
)?;
let ctx = list_ctx.clone_arc();
CONTEXTS.lock().list.push_back(list_ctx);
CONTEXTS.lock().contexts.push(ctx.clone(), GFP_KERNEL)?;
Ok(ctx)
}
@ -89,27 +73,27 @@ impl Context {
/// Called when the file for this context is unlinked.
///
/// No-op if called twice.
pub(crate) fn deregister(&self) {
// SAFETY: We never add the context to any other linked list than this one, so it is either
// in this list, or not in any list.
unsafe { CONTEXTS.lock().list.remove(self) };
pub(crate) fn deregister(self: &Arc<Self>) {
// Safe removal using retain
CONTEXTS.lock().contexts.retain(|c| !Arc::ptr_eq(c, self));
}
pub(crate) fn register_process(self: &Arc<Self>, proc: ListArc<Process>) {
pub(crate) fn register_process(self: &Arc<Self>, proc: Arc<Process>) -> Result {
if !Arc::ptr_eq(self, &proc.ctx) {
pr_err!("Context::register_process called on the wrong context.");
return;
return Err(EINVAL);
}
self.manager.lock().all_procs.push_back(proc);
self.manager.lock().all_procs.push(proc, GFP_KERNEL)?;
Ok(())
}
pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Process) {
pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Arc<Process>) {
if !Arc::ptr_eq(self, &proc.ctx) {
pr_err!("Context::deregister_process called on the wrong context.");
return;
}
// SAFETY: We just checked that this is the right list.
unsafe { self.manager.lock().all_procs.remove(proc) };
let mut manager = self.manager.lock();
manager.all_procs.retain(|p| !Arc::ptr_eq(p, proc));
}
pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result {
@ -154,27 +138,27 @@ impl Context {
{
let lock = self.manager.lock();
for proc in &lock.all_procs {
func(&proc);
func(proc);
}
}
pub(crate) fn get_all_procs(&self) -> Result<KVec<Arc<Process>>> {
pub(crate) fn get_all_procs(&self) -> Result<KVVec<Arc<Process>>> {
let lock = self.manager.lock();
let count = lock.all_procs.iter().count();
let mut procs = KVec::with_capacity(count, GFP_KERNEL)?;
for proc in &lock.all_procs {
procs.push(Arc::from(proc), GFP_KERNEL)?;
let mut procs = KVVec::with_capacity(lock.all_procs.len(), GFP_KERNEL)?;
for proc in lock.all_procs.iter() {
procs.push(Arc::clone(proc), GFP_KERNEL)?;
}
Ok(procs)
}
pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result<KVec<Arc<Process>>> {
let orig = self.get_all_procs()?;
let mut backing = KVec::with_capacity(orig.len(), GFP_KERNEL)?;
for proc in orig.into_iter().filter(|proc| proc.task.pid() == pid) {
backing.push(proc, GFP_KERNEL)?;
pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result<KVVec<Arc<Process>>> {
let lock = self.manager.lock();
let mut matching_procs = KVVec::new();
for proc in lock.all_procs.iter() {
if proc.task.pid() == pid {
matching_procs.push(Arc::clone(proc), GFP_KERNEL)?;
}
}
Ok(backing)
Ok(matching_procs)
}
}

View file

@ -178,6 +178,14 @@ struct NodeInner {
refs: List<NodeRefInfo, { NodeRefInfo::LIST_NODE }>,
}
use kernel::bindings::rb_node_layout;
use mem::offset_of;
pub(crate) const NODE_LAYOUT: rb_node_layout = rb_node_layout {
arc_offset: Arc::<Node>::DATA_OFFSET + offset_of!(DTRWrap<Node>, wrapped),
debug_id: offset_of!(Node, debug_id),
ptr: offset_of!(Node, ptr),
};
#[pin_data]
pub(crate) struct Node {
pub(crate) debug_id: usize,

View file

@ -28,11 +28,11 @@ use kernel::{
seq_print,
sync::poll::PollTable,
sync::{
aref::ARef,
lock::{spinlock::SpinLockBackend, Guard},
Arc, ArcBorrow, CondVar, CondVarTimeoutResult, Mutex, SpinLock, UniqueArc,
},
task::Task,
types::ARef,
uaccess::{UserSlice, UserSliceReader},
uapi,
workqueue::{self, Work},
@ -418,6 +418,13 @@ impl ProcessNodeRefs {
}
}
use core::mem::offset_of;
use kernel::bindings::rb_process_layout;
pub(crate) const PROCESS_LAYOUT: rb_process_layout = rb_process_layout {
arc_offset: Arc::<Process>::DATA_OFFSET,
task: offset_of!(Process, task),
};
/// A process using binder.
///
/// Strictly speaking, there can be multiple of these per process. There is one for each binder fd
@ -496,7 +503,7 @@ impl workqueue::WorkItem for Process {
impl Process {
fn new(ctx: Arc<Context>, cred: ARef<Credential>) -> Result<Arc<Self>> {
let current = kernel::current!();
let list_process = ListArc::pin_init::<Error>(
let process = Arc::pin_init::<Error>(
try_pin_init!(Process {
ctx,
cred,
@ -512,8 +519,7 @@ impl Process {
GFP_KERNEL,
)?;
let process = list_process.clone_arc();
process.ctx.register_process(list_process);
process.ctx.register_process(process.clone())?;
Ok(process)
}

View file

@ -20,4 +20,83 @@ struct inode;
struct dentry *rust_binderfs_create_proc_file(struct inode *nodp, int pid);
void rust_binderfs_remove_file(struct dentry *dentry);
/*
* The internal data types in the Rust Binder driver are opaque to C, so we use
* void pointer typedefs for these types.
*/
typedef void *rust_binder_transaction;
typedef void *rust_binder_process;
typedef void *rust_binder_node;
struct rb_process_layout {
size_t arc_offset;
size_t task;
};
struct rb_transaction_layout {
size_t debug_id;
size_t code;
size_t flags;
size_t from_thread;
size_t to_proc;
size_t target_node;
};
struct rb_node_layout {
size_t arc_offset;
size_t debug_id;
size_t ptr;
};
struct rust_binder_layout {
struct rb_transaction_layout t;
struct rb_process_layout p;
struct rb_node_layout n;
};
extern const struct rust_binder_layout RUST_BINDER_LAYOUT;
static inline size_t rust_binder_transaction_debug_id(rust_binder_transaction t)
{
return *(size_t *) (t + RUST_BINDER_LAYOUT.t.debug_id);
}
static inline u32 rust_binder_transaction_code(rust_binder_transaction t)
{
return *(u32 *) (t + RUST_BINDER_LAYOUT.t.code);
}
static inline u32 rust_binder_transaction_flags(rust_binder_transaction t)
{
return *(u32 *) (t + RUST_BINDER_LAYOUT.t.flags);
}
// Nullable!
static inline rust_binder_node rust_binder_transaction_target_node(rust_binder_transaction t)
{
void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.target_node);
if (p)
p = p + RUST_BINDER_LAYOUT.n.arc_offset;
return p;
}
static inline rust_binder_process rust_binder_transaction_to_proc(rust_binder_transaction t)
{
void *p = *(void **) (t + RUST_BINDER_LAYOUT.t.to_proc);
return p + RUST_BINDER_LAYOUT.p.arc_offset;
}
static inline struct task_struct *rust_binder_process_task(rust_binder_process t)
{
return *(struct task_struct **) (t + RUST_BINDER_LAYOUT.p.task);
}
static inline size_t rust_binder_node_debug_id(rust_binder_node t)
{
return *(size_t *) (t + RUST_BINDER_LAYOUT.n.debug_id);
}
#endif

View file

@ -30,6 +30,36 @@ TRACE_EVENT(rust_binder_ioctl,
TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
);
TRACE_EVENT(rust_binder_transaction,
TP_PROTO(bool reply, rust_binder_transaction t, struct task_struct *thread),
TP_ARGS(reply, t, thread),
TP_STRUCT__entry(
__field(int, debug_id)
__field(int, target_node)
__field(int, to_proc)
__field(int, to_thread)
__field(int, reply)
__field(unsigned int, code)
__field(unsigned int, flags)
),
TP_fast_assign(
rust_binder_process to = rust_binder_transaction_to_proc(t);
rust_binder_node target_node = rust_binder_transaction_target_node(t);
__entry->debug_id = rust_binder_transaction_debug_id(t);
__entry->target_node = target_node ? rust_binder_node_debug_id(target_node) : 0;
__entry->to_proc = rust_binder_process_task(to)->pid;
__entry->to_thread = thread ? thread->pid : 0;
__entry->reply = reply;
__entry->code = rust_binder_transaction_code(t);
__entry->flags = rust_binder_transaction_flags(t);
),
TP_printk("transaction=%d dest_node=%d dest_proc=%d dest_thread=%d reply=%d flags=0x%x code=0x%x",
__entry->debug_id, __entry->target_node,
__entry->to_proc, __entry->to_thread,
__entry->reply, __entry->flags, __entry->code)
);
#endif /* _RUST_BINDER_TRACE_H */
/* This part must be outside protection */

View file

@ -87,6 +87,14 @@ module! {
license: "GPL",
}
use kernel::bindings::rust_binder_layout;
#[no_mangle]
static RUST_BINDER_LAYOUT: rust_binder_layout = rust_binder_layout {
t: transaction::TRANSACTION_LAYOUT,
p: process::PROCESS_LAYOUT,
n: node::NODE_LAYOUT,
};
fn next_debug_id() -> usize {
static NEXT_DEBUG_ID: Atomic<usize> = Atomic::new(0);
@ -286,7 +294,7 @@ impl kernel::Module for BinderModule {
pr_warn!("Loaded Rust Binder.");
BINDER_SHRINKER.register(kernel::c_str!("android-binder"))?;
BINDER_SHRINKER.register(c"android-binder")?;
// SAFETY: The module is being loaded, so we can initialize binderfs.
unsafe { kernel::error::to_result(binderfs::init_rust_binderfs())? };
@ -312,7 +320,7 @@ pub static rust_binder_fops: AssertSync<kernel::bindings::file_operations> = {
owner: THIS_MODULE.as_ptr(),
poll: Some(rust_binder_poll),
unlocked_ioctl: Some(rust_binder_ioctl),
compat_ioctl: Some(bindings::compat_ptr_ioctl),
compat_ioctl: bindings::compat_ptr_ioctl,
mmap: Some(rust_binder_mmap),
open: Some(rust_binder_open),
release: Some(rust_binder_release),

View file

@ -17,9 +17,8 @@ use kernel::{
seq_print,
sync::atomic::{ordering::Relaxed, Atomic},
sync::poll::{PollCondVar, PollTable},
sync::{Arc, SpinLock},
sync::{aref::ARef, Arc, SpinLock},
task::Task,
types::ARef,
uaccess::UserSlice,
uapi,
};
@ -1146,6 +1145,7 @@ impl Thread {
transaction: &DArc<Transaction>,
) -> bool {
if let Ok(transaction) = &reply {
crate::trace::trace_transaction(true, transaction, Some(&self.task));
transaction.set_outstanding(&mut self.process.inner.lock());
}

View file

@ -2,11 +2,21 @@
// Copyright (C) 2025 Google LLC.
use crate::transaction::Transaction;
use kernel::bindings::{rust_binder_transaction, task_struct};
use kernel::ffi::{c_uint, c_ulong};
use kernel::task::Task;
use kernel::tracepoint::declare_trace;
declare_trace! {
unsafe fn rust_binder_ioctl(cmd: c_uint, arg: c_ulong);
unsafe fn rust_binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct);
}
#[inline]
fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
t as *const Transaction as rust_binder_transaction
}
#[inline]
@ -14,3 +24,14 @@ pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
// SAFETY: Always safe to call.
unsafe { rust_binder_ioctl(cmd, arg as c_ulong) }
}
#[inline]
pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Task>) {
let thread = match thread {
Some(thread) => thread.as_ptr(),
None => core::ptr::null_mut(),
};
// SAFETY: The raw transaction is valid for the duration of this call. The thread pointer is
// valid or null.
unsafe { rust_binder_transaction(reply, raw_transaction(t), thread) }
}

View file

@ -24,6 +24,17 @@ use crate::{
BinderReturnWriter, DArc, DLArc, DTRWrap, DeliverToRead,
};
use core::mem::offset_of;
use kernel::bindings::rb_transaction_layout;
pub(crate) const TRANSACTION_LAYOUT: rb_transaction_layout = rb_transaction_layout {
debug_id: offset_of!(Transaction, debug_id),
code: offset_of!(Transaction, code),
flags: offset_of!(Transaction, flags),
from_thread: offset_of!(Transaction, from),
to_proc: offset_of!(Transaction, to),
target_node: offset_of!(Transaction, target_node),
};
#[pin_data(PinnedDrop)]
pub(crate) struct Transaction {
pub(crate) debug_id: usize,
@ -249,6 +260,7 @@ impl Transaction {
if oneway {
if let Some(target_node) = self.target_node.clone() {
crate::trace::trace_transaction(false, &self, None);
if process_inner.is_frozen.is_frozen() {
process_inner.async_recv = true;
if self.flags & TF_UPDATE_TXN != 0 {
@ -286,11 +298,13 @@ impl Transaction {
}
let res = if let Some(thread) = self.find_target_thread() {
crate::trace::trace_transaction(false, &self, Some(&thread.task));
match thread.push_work(self) {
PushWorkRes::Ok => Ok(()),
PushWorkRes::FailedDead(me) => Err((BinderError::new_dead(), me)),
}
} else {
crate::trace::trace_transaction(false, &self, None);
process_inner.push_work(self)
};
drop(process_inner);

View file

@ -81,7 +81,7 @@ static void binder_insert_free_buffer(struct binder_alloc *alloc,
new_buffer_size = binder_alloc_buffer_size(alloc, new_buffer);
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: add free buffer, size %zd, at %pK\n",
"%d: add free buffer, size %zd, at %p\n",
alloc->pid, new_buffer_size, new_buffer);
while (*p) {
@ -572,7 +572,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
}
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: binder_alloc_buf size %zd got buffer %pK size %zd\n",
"%d: binder_alloc_buf size %zd got buffer %p size %zd\n",
alloc->pid, size, buffer, buffer_size);
/*
@ -748,7 +748,7 @@ static void binder_free_buf_locked(struct binder_alloc *alloc,
ALIGN(buffer->extra_buffers_size, sizeof(void *));
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
"%d: binder_free_buf %pK size %zd buffer_size %zd\n",
"%d: binder_free_buf %p size %zd buffer_size %zd\n",
alloc->pid, buffer, size, buffer_size);
BUG_ON(buffer->free);

View file

@ -432,10 +432,9 @@ const struct device_type fsl_mc_bus_dpdmai_type = {
};
EXPORT_SYMBOL_GPL(fsl_mc_bus_dpdmai_type);
const struct device_type fsl_mc_bus_dpdbg_type = {
static const struct device_type fsl_mc_bus_dpdbg_type = {
.name = "fsl_mc_bus_dpdbg"
};
EXPORT_SYMBOL_GPL(fsl_mc_bus_dpdbg_type);
static const struct device_type *fsl_mc_get_device_type(const char *type)
{

View file

@ -1596,7 +1596,7 @@ void mhi_ep_unregister_controller(struct mhi_ep_cntrl *mhi_cntrl)
}
EXPORT_SYMBOL_GPL(mhi_ep_unregister_controller);
static int mhi_ep_driver_probe(struct device *dev)
static int mhi_ep_probe(struct device *dev)
{
struct mhi_ep_device *mhi_dev = to_mhi_ep_device(dev);
struct mhi_ep_driver *mhi_drv = to_mhi_ep_driver(dev->driver);
@ -1609,7 +1609,7 @@ static int mhi_ep_driver_probe(struct device *dev)
return mhi_drv->probe(mhi_dev, mhi_dev->id);
}
static int mhi_ep_driver_remove(struct device *dev)
static void mhi_ep_remove(struct device *dev)
{
struct mhi_ep_device *mhi_dev = to_mhi_ep_device(dev);
struct mhi_ep_driver *mhi_drv = to_mhi_ep_driver(dev->driver);
@ -1619,7 +1619,7 @@ static int mhi_ep_driver_remove(struct device *dev)
/* Skip if it is a controller device */
if (mhi_dev->dev_type == MHI_DEVICE_CONTROLLER)
return 0;
return;
/* Disconnect the channels associated with the driver */
for (dir = 0; dir < 2; dir++) {
@ -1643,8 +1643,6 @@ static int mhi_ep_driver_remove(struct device *dev)
/* Remove the client driver now */
mhi_drv->remove(mhi_dev);
return 0;
}
int __mhi_ep_driver_register(struct mhi_ep_driver *mhi_drv, struct module *owner)
@ -1660,8 +1658,6 @@ int __mhi_ep_driver_register(struct mhi_ep_driver *mhi_drv, struct module *owner
driver->bus = &mhi_ep_bus_type;
driver->owner = owner;
driver->probe = mhi_ep_driver_probe;
driver->remove = mhi_ep_driver_remove;
return driver_register(driver);
}
@ -1708,6 +1704,8 @@ const struct bus_type mhi_ep_bus_type = {
.dev_name = "mhi_ep",
.match = mhi_ep_match,
.uevent = mhi_ep_uevent,
.probe = mhi_ep_probe,
.remove = mhi_ep_remove,
};
static int __init mhi_ep_init(void)

View file

@ -584,6 +584,16 @@ skip_req_fw:
* device transitioning into MHI READY state
*/
if (fw_load_type == MHI_FW_LOAD_FBC) {
/*
* Some FW combine two separate ELF images (SBL + WLAN FW) in a single
* file. Hence, check for the existence of the second ELF header after
* SBL. If present, load the second image separately.
*/
if (!memcmp(fw_data + mhi_cntrl->sbl_size, ELFMAG, SELFMAG)) {
fw_data += mhi_cntrl->sbl_size;
fw_sz -= mhi_cntrl->sbl_size;
}
ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);
if (ret) {
release_firmware(firmware);

View file

@ -841,18 +841,8 @@ static int parse_ch_cfg(struct mhi_controller *mhi_cntrl,
mhi_chan->lpm_notify = ch_cfg->lpm_notify;
mhi_chan->offload_ch = ch_cfg->offload_channel;
mhi_chan->db_cfg.reset_req = ch_cfg->doorbell_mode_switch;
mhi_chan->pre_alloc = ch_cfg->auto_queue;
mhi_chan->wake_capable = ch_cfg->wake_capable;
/*
* If MHI host allocates buffers, then the channel direction
* should be DMA_FROM_DEVICE
*/
if (mhi_chan->pre_alloc && mhi_chan->dir != DMA_FROM_DEVICE) {
dev_err(dev, "Invalid channel configuration\n");
goto error_chan_cfg;
}
/*
* Bi-directional and direction less channel must be an
* offload channel
@ -1265,7 +1255,7 @@ struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl)
return mhi_dev;
}
static int mhi_driver_probe(struct device *dev)
static int mhi_probe(struct device *dev)
{
struct mhi_device *mhi_dev = to_mhi_device(dev);
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
@ -1341,7 +1331,7 @@ exit_probe:
return ret;
}
static int mhi_driver_remove(struct device *dev)
static void mhi_remove(struct device *dev)
{
struct mhi_device *mhi_dev = to_mhi_device(dev);
struct mhi_driver *mhi_drv = to_mhi_driver(dev->driver);
@ -1355,7 +1345,7 @@ static int mhi_driver_remove(struct device *dev)
/* Skip if it is a controller device */
if (mhi_dev->dev_type == MHI_DEVICE_CONTROLLER)
return 0;
return;
/* Reset both channels */
for (dir = 0; dir < 2; dir++) {
@ -1407,8 +1397,6 @@ static int mhi_driver_remove(struct device *dev)
while (mhi_dev->dev_wake)
mhi_device_put(mhi_dev);
return 0;
}
int __mhi_driver_register(struct mhi_driver *mhi_drv, struct module *owner)
@ -1420,8 +1408,6 @@ int __mhi_driver_register(struct mhi_driver *mhi_drv, struct module *owner)
driver->bus = &mhi_bus_type;
driver->owner = owner;
driver->probe = mhi_driver_probe;
driver->remove = mhi_driver_remove;
return driver_register(driver);
}
@ -1468,6 +1454,8 @@ const struct bus_type mhi_bus_type = {
.dev_name = "mhi",
.match = mhi_match,
.uevent = mhi_uevent,
.probe = mhi_probe,
.remove = mhi_remove,
.dev_groups = mhi_dev_groups,
};

View file

@ -286,7 +286,6 @@ struct mhi_chan {
bool lpm_notify;
bool configured;
bool offload_ch;
bool pre_alloc;
bool wake_capable;
};
@ -389,8 +388,6 @@ int mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
struct image_info *img_info);
void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl);
/* Automatically allocate and queue inbound buffers */
#define MHI_CH_INBOUND_ALLOC_BUFS BIT(0)
int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
struct mhi_chan *mhi_chan);
void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,

View file

@ -664,23 +664,6 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
mhi_cntrl->runtime_put(mhi_cntrl);
}
/*
* Recycle the buffer if buffer is pre-allocated,
* if there is an error, not much we can do apart
* from dropping the packet
*/
if (mhi_chan->pre_alloc) {
if (mhi_queue_buf(mhi_chan->mhi_dev,
mhi_chan->dir,
buf_info->cb_buf,
buf_info->len, MHI_EOT)) {
dev_err(dev,
"Error recycling buffer for chan:%d\n",
mhi_chan->chan);
kfree(buf_info->cb_buf);
}
}
read_lock_bh(&mhi_chan->lock);
}
break;
@ -1177,17 +1160,12 @@ static int mhi_queue(struct mhi_device *mhi_dev, struct mhi_buf_info *buf_info,
int mhi_queue_skb(struct mhi_device *mhi_dev, enum dma_data_direction dir,
struct sk_buff *skb, size_t len, enum mhi_flags mflags)
{
struct mhi_chan *mhi_chan = (dir == DMA_TO_DEVICE) ? mhi_dev->ul_chan :
mhi_dev->dl_chan;
struct mhi_buf_info buf_info = { };
buf_info.v_addr = skb->data;
buf_info.cb_buf = skb;
buf_info.len = len;
if (unlikely(mhi_chan->pre_alloc))
return -EINVAL;
return mhi_queue(mhi_dev, &buf_info, dir, mflags);
}
EXPORT_SYMBOL_GPL(mhi_queue_skb);
@ -1472,45 +1450,6 @@ static int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
if (ret)
goto error_pm_state;
if (mhi_chan->dir == DMA_FROM_DEVICE)
mhi_chan->pre_alloc = !!(flags & MHI_CH_INBOUND_ALLOC_BUFS);
/* Pre-allocate buffer for xfer ring */
if (mhi_chan->pre_alloc) {
int nr_el = get_nr_avail_ring_elements(mhi_cntrl,
&mhi_chan->tre_ring);
size_t len = mhi_cntrl->buffer_len;
while (nr_el--) {
void *buf;
struct mhi_buf_info info = { };
buf = kmalloc(len, GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto error_pre_alloc;
}
/* Prepare transfer descriptors */
info.v_addr = buf;
info.cb_buf = buf;
info.len = len;
ret = mhi_gen_tre(mhi_cntrl, mhi_chan, &info, MHI_EOT);
if (ret) {
kfree(buf);
goto error_pre_alloc;
}
}
read_lock_bh(&mhi_cntrl->pm_lock);
if (MHI_DB_ACCESS_VALID(mhi_cntrl)) {
read_lock_irq(&mhi_chan->lock);
mhi_ring_chan_db(mhi_cntrl, mhi_chan);
read_unlock_irq(&mhi_chan->lock);
}
read_unlock_bh(&mhi_cntrl->pm_lock);
}
mutex_unlock(&mhi_chan->mutex);
return 0;
@ -1522,12 +1461,6 @@ error_pm_state:
error_init_chan:
mutex_unlock(&mhi_chan->mutex);
return ret;
error_pre_alloc:
mutex_unlock(&mhi_chan->mutex);
mhi_unprepare_channel(mhi_cntrl, mhi_chan);
return ret;
}
@ -1600,12 +1533,8 @@ static void mhi_reset_data_chan(struct mhi_controller *mhi_cntrl,
mhi_del_ring_element(mhi_cntrl, buf_ring);
mhi_del_ring_element(mhi_cntrl, tre_ring);
if (mhi_chan->pre_alloc) {
kfree(buf_info->cb_buf);
} else {
result.buf_addr = buf_info->cb_buf;
mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result);
}
result.buf_addr = buf_info->cb_buf;
mhi_chan->xfer_cb(mhi_chan->mhi_dev, &result);
}
}
@ -1666,12 +1595,6 @@ int mhi_prepare_for_transfer(struct mhi_device *mhi_dev)
}
EXPORT_SYMBOL_GPL(mhi_prepare_for_transfer);
int mhi_prepare_for_transfer_autoqueue(struct mhi_device *mhi_dev)
{
return __mhi_prepare_for_transfer(mhi_dev, MHI_CH_INBOUND_ALLOC_BUFS);
}
EXPORT_SYMBOL_GPL(mhi_prepare_for_transfer_autoqueue);
void mhi_unprepare_from_transfer(struct mhi_device *mhi_dev)
{
struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;

View file

@ -94,22 +94,6 @@ struct mhi_pci_dev_info {
.doorbell_mode_switch = false, \
}
#define MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(ch_num, ch_name, el_count, ev_ring) \
{ \
.num = ch_num, \
.name = ch_name, \
.num_elements = el_count, \
.event_ring = ev_ring, \
.dir = DMA_FROM_DEVICE, \
.ee_mask = BIT(MHI_EE_AMSS), \
.pollcfg = 0, \
.doorbell = MHI_DB_BRST_DISABLE, \
.lpm_notify = false, \
.offload_channel = false, \
.doorbell_mode_switch = false, \
.auto_queue = true, \
}
#define MHI_EVENT_CONFIG_CTRL(ev_ring, el_count) \
{ \
.num_elements = el_count, \
@ -329,7 +313,7 @@ static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 64, 2),
@ -762,7 +746,7 @@ static const struct mhi_channel_config mhi_telit_fn980_hw_v1_channels[] = {
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
MHI_CHANNEL_CONFIG_UL(20, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_DL_AUTOQUEUE(21, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_DL(21, "IPCR", 16, 0),
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 1),
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 2),
};

View file

@ -249,32 +249,6 @@ config SONYPI
To compile this driver as a module, choose M here: the
module will be called sonypi.
config MWAVE
tristate "ACP Modem (Mwave) support"
depends on X86 && TTY
select SERIAL_8250
help
The ACP modem (Mwave) for Linux is a WinModem. It is composed of a
kernel driver and a user level application. Together these components
support direct attachment to public switched telephone networks (PSTNs)
and support selected world wide countries.
This version of the ACP Modem driver supports the IBM Thinkpad 600E,
600, and 770 that include on board ACP modem hardware.
The modem also supports the standard communications port interface
(ttySx) and is compatible with the Hayes AT Command Set.
The user level application needed to use this driver can be found at
the IBM Linux Technology Center (LTC) web site:
<http://www.ibm.com/linux/ltc/>.
If you own one of the above IBM Thinkpads which has the Mwave chipset
in it, say Y.
To compile this driver as a module, choose M here: the
module will be called mwave.
config SCx200_GPIO
tristate "NatSemi SCx200 GPIO Support"
depends on SCx200

View file

@ -33,7 +33,6 @@ obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o
obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o
obj-$(CONFIG_TELCLOCK) += tlclk.o
obj-$(CONFIG_MWAVE) += mwave/
obj-y += agp/
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o

View file

@ -166,7 +166,7 @@ static void __init miscdev_test_can_open(struct kunit *test, struct miscdevice *
KUNIT_FAIL(test, "failed to create node\n");
filp = filp_open(devname, O_RDONLY, 0);
if (IS_ERR_OR_NULL(filp))
if (IS_ERR(filp))
KUNIT_FAIL(test, "failed to open misc device: %ld\n", PTR_ERR(filp));
else
fput(filp);

View file

@ -1,536 +0,0 @@
/*
*
* 3780i.c -- helper routines for the 3780i DSP
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "3780i: " fmt
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/bitops.h>
#include <linux/sched.h> /* cond_resched() */
#include <asm/io.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
#include "smapi.h"
#include "mwavedd.h"
#include "3780i.h"
static DEFINE_SPINLOCK(dsp_lock);
static void PaceMsaAccess(unsigned short usDspBaseIO)
{
cond_resched();
udelay(100);
cond_resched();
}
unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr)
{
unsigned long flags;
unsigned short val;
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);
return val;
}
void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr, unsigned short usValue)
{
unsigned long flags;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulMsaAddr);
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulMsaAddr >> 16));
OutWordDsp(DSP_MsaDataDSISHigh, usValue);
spin_unlock_irqrestore(&dsp_lock, flags);
}
static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
unsigned char ucValue)
{
DSP_ISA_SLAVE_CONTROL rSlaveControl;
DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
MKBYTE(rSlaveControl) = InByteDsp(DSP_IsaSlaveControl);
rSlaveControl_Save = rSlaveControl;
rSlaveControl.ConfigMode = true;
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl));
OutByteDsp(DSP_ConfigAddress, (unsigned char) uIndex);
OutByteDsp(DSP_ConfigData, ucValue);
OutByteDsp(DSP_IsaSlaveControl, MKBYTE(rSlaveControl_Save));
}
int dsp3780I_EnableDSP(struct dsp_3780i_config_settings *pSettings,
unsigned short *pIrqMap,
unsigned short *pDmaMap)
{
unsigned long flags;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
int i;
DSP_UART_CFG_1 rUartCfg1;
DSP_UART_CFG_2 rUartCfg2;
DSP_HBRIDGE_CFG_1 rHBridgeCfg1;
DSP_HBRIDGE_CFG_2 rHBridgeCfg2;
DSP_BUSMASTER_CFG_1 rBusmasterCfg1;
DSP_BUSMASTER_CFG_2 rBusmasterCfg2;
DSP_ISA_PROT_CFG rIsaProtCfg;
DSP_POWER_MGMT_CFG rPowerMgmtCfg;
DSP_HBUS_TIMER_CFG rHBusTimerCfg;
DSP_LBUS_TIMEOUT_DISABLE rLBusTimeoutDisable;
DSP_CHIP_RESET rChipReset;
DSP_CLOCK_CONTROL_1 rClockControl1;
DSP_CLOCK_CONTROL_2 rClockControl2;
DSP_ISA_SLAVE_CONTROL rSlaveControl;
DSP_HBRIDGE_CONTROL rHBridgeControl;
unsigned short tval;
if (!pSettings->bDSPEnabled) {
pr_err("%s: Error: DSP not enabled. Aborting.\n", __func__);
return -EIO;
}
if (pSettings->bModemEnabled) {
rUartCfg1.Reserved = rUartCfg2.Reserved = 0;
rUartCfg1.IrqActiveLow = pSettings->bUartIrqActiveLow;
rUartCfg1.IrqPulse = pSettings->bUartIrqPulse;
rUartCfg1.Irq =
(unsigned char) pIrqMap[pSettings->usUartIrq];
switch (pSettings->usUartBaseIO) {
case 0x03F8:
rUartCfg1.BaseIO = 0;
break;
case 0x02F8:
rUartCfg1.BaseIO = 1;
break;
case 0x03E8:
rUartCfg1.BaseIO = 2;
break;
case 0x02E8:
rUartCfg1.BaseIO = 3;
break;
}
rUartCfg2.Enable = true;
}
rHBridgeCfg1.Reserved = rHBridgeCfg2.Reserved = 0;
rHBridgeCfg1.IrqActiveLow = pSettings->bDspIrqActiveLow;
rHBridgeCfg1.IrqPulse = pSettings->bDspIrqPulse;
rHBridgeCfg1.Irq = (unsigned char) pIrqMap[pSettings->usDspIrq];
rHBridgeCfg1.AccessMode = 1;
rHBridgeCfg2.Enable = true;
rBusmasterCfg2.Reserved = 0;
rBusmasterCfg1.Dma = (unsigned char) pDmaMap[pSettings->usDspDma];
rBusmasterCfg1.NumTransfers =
(unsigned char) pSettings->usNumTransfers;
rBusmasterCfg1.ReRequest = (unsigned char) pSettings->usReRequest;
rBusmasterCfg1.MEMCS16 = pSettings->bEnableMEMCS16;
rBusmasterCfg2.IsaMemCmdWidth =
(unsigned char) pSettings->usIsaMemCmdWidth;
rIsaProtCfg.Reserved = 0;
rIsaProtCfg.GateIOCHRDY = pSettings->bGateIOCHRDY;
rPowerMgmtCfg.Reserved = 0;
rPowerMgmtCfg.Enable = pSettings->bEnablePwrMgmt;
rHBusTimerCfg.LoadValue =
(unsigned char) pSettings->usHBusTimerLoadValue;
rLBusTimeoutDisable.Reserved = 0;
rLBusTimeoutDisable.DisableTimeout =
pSettings->bDisableLBusTimeout;
MKWORD(rChipReset) = ~pSettings->usChipletEnable;
rClockControl1.Reserved1 = rClockControl1.Reserved2 = 0;
rClockControl1.N_Divisor = pSettings->usN_Divisor;
rClockControl1.M_Multiplier = pSettings->usM_Multiplier;
rClockControl2.Reserved = 0;
rClockControl2.PllBypass = pSettings->bPllBypass;
/* Issue a soft reset to the chip */
/* Note: Since we may be coming in with 3780i clocks suspended, we must keep
* soft-reset active for 10ms.
*/
rSlaveControl.ClockControl = 0;
rSlaveControl.SoftReset = true;
rSlaveControl.ConfigMode = false;
rSlaveControl.Reserved = 0;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
for (i = 0; i < 11; i++)
udelay(2000);
rSlaveControl.SoftReset = false;
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
MKWORD(tval) = InWordDsp(DSP_IsaSlaveControl);
/* Program our general configuration registers */
WriteGenCfg(DSP_HBridgeCfg1Index, MKBYTE(rHBridgeCfg1));
WriteGenCfg(DSP_HBridgeCfg2Index, MKBYTE(rHBridgeCfg2));
WriteGenCfg(DSP_BusMasterCfg1Index, MKBYTE(rBusmasterCfg1));
WriteGenCfg(DSP_BusMasterCfg2Index, MKBYTE(rBusmasterCfg2));
WriteGenCfg(DSP_IsaProtCfgIndex, MKBYTE(rIsaProtCfg));
WriteGenCfg(DSP_PowerMgCfgIndex, MKBYTE(rPowerMgmtCfg));
WriteGenCfg(DSP_HBusTimerCfgIndex, MKBYTE(rHBusTimerCfg));
if (pSettings->bModemEnabled) {
WriteGenCfg(DSP_UartCfg1Index, MKBYTE(rUartCfg1));
WriteGenCfg(DSP_UartCfg2Index, MKBYTE(rUartCfg2));
}
rHBridgeControl.EnableDspInt = false;
rHBridgeControl.MemAutoInc = true;
rHBridgeControl.IoAutoInc = false;
rHBridgeControl.DiagnosticMode = false;
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
spin_unlock_irqrestore(&dsp_lock, flags);
WriteMsaCfg(DSP_LBusTimeoutDisable, MKWORD(rLBusTimeoutDisable));
WriteMsaCfg(DSP_ClockControl_1, MKWORD(rClockControl1));
WriteMsaCfg(DSP_ClockControl_2, MKWORD(rClockControl2));
WriteMsaCfg(DSP_ChipReset, MKWORD(rChipReset));
ReadMsaCfg(DSP_ChipID);
return 0;
}
int dsp3780I_DisableDSP(struct dsp_3780i_config_settings *pSettings)
{
unsigned long flags;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
DSP_ISA_SLAVE_CONTROL rSlaveControl;
rSlaveControl.ClockControl = 0;
rSlaveControl.SoftReset = true;
rSlaveControl.ConfigMode = false;
rSlaveControl.Reserved = 0;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
udelay(5);
rSlaveControl.ClockControl = 1;
OutWordDsp(DSP_IsaSlaveControl, MKWORD(rSlaveControl));
spin_unlock_irqrestore(&dsp_lock, flags);
udelay(5);
return 0;
}
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;
spin_lock_irqsave(&dsp_lock, flags);
/* Mask DSP to PC interrupt */
MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
rHBridgeControl.EnableDspInt = false;
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
spin_unlock_irqrestore(&dsp_lock, flags);
/* Reset the core via the boot domain register */
rBootDomain.ResetCore = true;
rBootDomain.Halt = true;
rBootDomain.NMI = true;
rBootDomain.Reserved = 0;
WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
/* Reset all the chiplets and then reactivate them */
WriteMsaCfg(DSP_ChipReset, 0xFFFF);
udelay(5);
WriteMsaCfg(DSP_ChipReset,
(unsigned short) (~pSettings->usChipletEnable));
return 0;
}
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;
/* Transition the core to a running state */
rBootDomain.ResetCore = true;
rBootDomain.Halt = false;
rBootDomain.NMI = true;
rBootDomain.Reserved = 0;
WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
udelay(5);
rBootDomain.ResetCore = false;
WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
udelay(5);
rBootDomain.NMI = false;
WriteMsaCfg(DSP_MspBootDomain, MKWORD(rBootDomain));
udelay(5);
/* Enable DSP to PC interrupt */
spin_lock_irqsave(&dsp_lock, flags);
MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
rHBridgeControl.EnableDspInt = true;
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
spin_unlock_irqrestore(&dsp_lock, flags);
return 0;
}
int dsp3780I_ReadDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
unsigned short val;
/* 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);
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
spin_unlock_irqrestore(&dsp_lock, flags);
/* Transfer the memory block */
while (uCount-- != 0) {
spin_lock_irqsave(&dsp_lock, flags);
val = InWordDsp(DSP_MsaDataDSISHigh);
spin_unlock_irqrestore(&dsp_lock, flags);
if(put_user(val, pusBuffer++))
return -EFAULT;
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_ReadAndClearDStore(unsigned short usDspBaseIO,
void __user *pvBuffer, unsigned uCount,
unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
unsigned short val;
/* 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);
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
spin_unlock_irqrestore(&dsp_lock, flags);
/* Transfer the memory block */
while (uCount-- != 0) {
spin_lock_irqsave(&dsp_lock, flags);
val = InWordDsp(DSP_ReadAndClear);
spin_unlock_irqrestore(&dsp_lock, flags);
if(put_user(val, pusBuffer++))
return -EFAULT;
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
/* 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);
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
spin_unlock_irqrestore(&dsp_lock, flags);
/* Transfer the memory block */
while (uCount-- != 0) {
unsigned short val;
if(get_user(val, pusBuffer++))
return -EFAULT;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_MsaDataDSISHigh, val);
spin_unlock_irqrestore(&dsp_lock, flags);
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
/*
* Set the initial MSA address. To convert from an instruction store
* address to an MSA address
* shift the address two bits to the left and set bit 22
*/
ulDSPAddr = (ulDSPAddr << 2) | (1 << 22);
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
spin_unlock_irqrestore(&dsp_lock, flags);
/* Transfer the memory block */
while (uCount-- != 0) {
unsigned short val_lo, val_hi;
spin_lock_irqsave(&dsp_lock, flags);
val_lo = InWordDsp(DSP_MsaDataISLow);
val_hi = InWordDsp(DSP_MsaDataDSISHigh);
spin_unlock_irqrestore(&dsp_lock, flags);
if(put_user(val_lo, pusBuffer++))
return -EFAULT;
if(put_user(val_hi, pusBuffer++))
return -EFAULT;
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr)
{
unsigned long flags;
unsigned short __user *pusBuffer = pvBuffer;
/*
* Set the initial MSA address. To convert from an instruction store
* address to an MSA address
* shift the address two bits to the left and set bit 22
*/
ulDSPAddr = (ulDSPAddr << 2) | (1 << 22);
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_MsaAddrLow, (unsigned short) ulDSPAddr);
OutWordDsp(DSP_MsaAddrHigh, (unsigned short) (ulDSPAddr >> 16));
spin_unlock_irqrestore(&dsp_lock, flags);
/* Transfer the memory block */
while (uCount-- != 0) {
unsigned short val_lo, val_hi;
if(get_user(val_lo, pusBuffer++))
return -EFAULT;
if(get_user(val_hi, pusBuffer++))
return -EFAULT;
spin_lock_irqsave(&dsp_lock, flags);
OutWordDsp(DSP_MsaDataISLow, val_lo);
OutWordDsp(DSP_MsaDataDSISHigh, val_hi);
spin_unlock_irqrestore(&dsp_lock, flags);
PaceMsaAccess(usDspBaseIO);
}
return 0;
}
int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
unsigned short *pusIPCSource)
{
unsigned long flags;
DSP_HBRIDGE_CONTROL rHBridgeControl;
/*
* Disable DSP to PC interrupts, read the interrupt register,
* clear the pending IPC bits, and reenable DSP to PC interrupts
*/
spin_lock_irqsave(&dsp_lock, flags);
MKWORD(rHBridgeControl) = InWordDsp(DSP_HBridgeControl);
rHBridgeControl.EnableDspInt = false;
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
*pusIPCSource = InWordDsp(DSP_Interrupt);
OutWordDsp(DSP_Interrupt, (unsigned short) ~(*pusIPCSource));
rHBridgeControl.EnableDspInt = true;
OutWordDsp(DSP_HBridgeControl, MKWORD(rHBridgeControl));
spin_unlock_irqrestore(&dsp_lock, flags);
return 0;
}

View file

@ -1,358 +0,0 @@
/*
*
* 3780i.h -- declarations for 3780i.c
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_3780I_H
#define _LINUX_3780I_H
#include <asm/io.h>
/* DSP I/O port offsets and definitions */
#define DSP_IsaSlaveControl 0x0000 /* ISA slave control register */
#define DSP_IsaSlaveStatus 0x0001 /* ISA slave status register */
#define DSP_ConfigAddress 0x0002 /* General config address register */
#define DSP_ConfigData 0x0003 /* General config data register */
#define DSP_HBridgeControl 0x0002 /* HBridge control register */
#define DSP_MsaAddrLow 0x0004 /* MSP System Address, low word */
#define DSP_MsaAddrHigh 0x0006 /* MSP System Address, high word */
#define DSP_MsaDataDSISHigh 0x0008 /* MSA data register: d-store word or high byte of i-store */
#define DSP_MsaDataISLow 0x000A /* MSA data register: low word of i-store */
#define DSP_ReadAndClear 0x000C /* MSA read and clear data register */
#define DSP_Interrupt 0x000E /* Interrupt register (IPC source) */
typedef struct {
unsigned char ClockControl:1; /* RW: Clock control: 0=normal, 1=stop 3780i clocks */
unsigned char SoftReset:1; /* RW: Soft reset 0=normal, 1=soft reset active */
unsigned char ConfigMode:1; /* RW: Configuration mode, 0=normal, 1=config mode */
unsigned short Reserved:13; /* 0: Reserved */
} DSP_ISA_SLAVE_CONTROL;
typedef struct {
unsigned short EnableDspInt:1; /* RW: Enable DSP to X86 ISA interrupt 0=mask it, 1=enable it */
unsigned short MemAutoInc:1; /* RW: Memory address auto increment, 0=disable, 1=enable */
unsigned short IoAutoInc:1; /* RW: I/O address auto increment, 0=disable, 1=enable */
unsigned short DiagnosticMode:1; /* RW: Disgnostic mode 0=nromal, 1=diagnostic mode */
unsigned short IsaPacingTimer:12; /* R: ISA access pacing timer: count of core cycles stolen */
} DSP_HBRIDGE_CONTROL;
/* DSP register indexes used with the configuration register address (index) register */
#define DSP_UartCfg1Index 0x0003 /* UART config register 1 */
#define DSP_UartCfg2Index 0x0004 /* UART config register 2 */
#define DSP_HBridgeCfg1Index 0x0007 /* HBridge config register 1 */
#define DSP_HBridgeCfg2Index 0x0008 /* HBridge config register 2 */
#define DSP_BusMasterCfg1Index 0x0009 /* ISA bus master config register 1 */
#define DSP_BusMasterCfg2Index 0x000A /* ISA bus master config register 2 */
#define DSP_IsaProtCfgIndex 0x000F /* ISA protocol control register */
#define DSP_PowerMgCfgIndex 0x0010 /* Low poser suspend/resume enable */
#define DSP_HBusTimerCfgIndex 0x0011 /* HBUS timer load value */
typedef struct {
unsigned char IrqActiveLow:1; /* RW: IRQ active high or low: 0=high, 1=low */
unsigned char IrqPulse:1; /* RW: IRQ pulse or level: 0=level, 1=pulse */
unsigned char Irq:3; /* RW: IRQ selection */
unsigned char BaseIO:2; /* RW: Base I/O selection */
unsigned char Reserved:1; /* 0: Reserved */
} DSP_UART_CFG_1;
typedef struct {
unsigned char Enable:1; /* RW: Enable I/O and IRQ: 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_UART_CFG_2;
typedef struct {
unsigned char IrqActiveLow:1; /* RW: IRQ active high=0 or low=1 */
unsigned char IrqPulse:1; /* RW: IRQ pulse=1 or level=0 */
unsigned char Irq:3; /* RW: IRQ selection */
unsigned char AccessMode:1; /* RW: 16-bit register access method 0=byte, 1=word */
unsigned char Reserved:2; /* 0: Reserved */
} DSP_HBRIDGE_CFG_1;
typedef struct {
unsigned char Enable:1; /* RW: enable I/O and IRQ: 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_HBRIDGE_CFG_2;
typedef struct {
unsigned char Dma:3; /* RW: DMA channel selection */
unsigned char NumTransfers:2; /* RW: Maximum # of transfers once being granted the ISA bus */
unsigned char ReRequest:2; /* RW: Minimum delay between releasing the ISA bus and requesting it again */
unsigned char MEMCS16:1; /* RW: ISA signal MEMCS16: 0=disabled, 1=enabled */
} DSP_BUSMASTER_CFG_1;
typedef struct {
unsigned char IsaMemCmdWidth:2; /* RW: ISA memory command width */
unsigned char Reserved:6; /* 0: Reserved */
} DSP_BUSMASTER_CFG_2;
typedef struct {
unsigned char GateIOCHRDY:1; /* RW: Enable IOCHRDY gating: 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_ISA_PROT_CFG;
typedef struct {
unsigned char Enable:1; /* RW: Enable low power suspend/resume 0=false, 1=true */
unsigned char Reserved:7; /* 0: Reserved */
} DSP_POWER_MGMT_CFG;
typedef struct {
unsigned char LoadValue:8; /* RW: HBUS timer load value */
} DSP_HBUS_TIMER_CFG;
/* DSP registers that exist in MSA I/O space */
#define DSP_ChipID 0x80000000
#define DSP_MspBootDomain 0x80000580
#define DSP_LBusTimeoutDisable 0x80000580
#define DSP_ClockControl_1 0x8000058A
#define DSP_ClockControl_2 0x8000058C
#define DSP_ChipReset 0x80000588
#define DSP_GpioModeControl_15_8 0x80000082
#define DSP_GpioDriverEnable_15_8 0x80000076
#define DSP_GpioOutputData_15_8 0x80000072
typedef struct {
unsigned short NMI:1; /* RW: non maskable interrupt */
unsigned short Halt:1; /* RW: Halt MSP clock */
unsigned short ResetCore:1; /* RW: Reset MSP core interface */
unsigned short Reserved:13; /* 0: Reserved */
} DSP_BOOT_DOMAIN;
typedef struct {
unsigned short DisableTimeout:1; /* RW: Disable LBus timeout */
unsigned short Reserved:15; /* 0: Reserved */
} DSP_LBUS_TIMEOUT_DISABLE;
typedef struct {
unsigned short Memory:1; /* RW: Reset memory interface */
unsigned short SerialPort1:1; /* RW: Reset serial port 1 interface */
unsigned short SerialPort2:1; /* RW: Reset serial port 2 interface */
unsigned short SerialPort3:1; /* RW: Reset serial port 3 interface */
unsigned short Gpio:1; /* RW: Reset GPIO interface */
unsigned short Dma:1; /* RW: Reset DMA interface */
unsigned short SoundBlaster:1; /* RW: Reset soundblaster interface */
unsigned short Uart:1; /* RW: Reset UART interface */
unsigned short Midi:1; /* RW: Reset MIDI interface */
unsigned short IsaMaster:1; /* RW: Reset ISA master interface */
unsigned short Reserved:6; /* 0: Reserved */
} DSP_CHIP_RESET;
typedef struct {
unsigned short N_Divisor:6; /* RW: (N) PLL output clock divisor */
unsigned short Reserved1:2; /* 0: reserved */
unsigned short M_Multiplier:6; /* RW: (M) PLL feedback clock multiplier */
unsigned short Reserved2:2; /* 0: reserved */
} DSP_CLOCK_CONTROL_1;
typedef struct {
unsigned short PllBypass:1; /* RW: PLL Bypass */
unsigned short Reserved:15; /* 0: Reserved */
} DSP_CLOCK_CONTROL_2;
typedef struct {
unsigned short Latch8:1;
unsigned short Latch9:1;
unsigned short Latch10:1;
unsigned short Latch11:1;
unsigned short Latch12:1;
unsigned short Latch13:1;
unsigned short Latch14:1;
unsigned short Latch15:1;
unsigned short Mask8:1;
unsigned short Mask9:1;
unsigned short Mask10:1;
unsigned short Mask11:1;
unsigned short Mask12:1;
unsigned short Mask13:1;
unsigned short Mask14:1;
unsigned short Mask15:1;
} DSP_GPIO_OUTPUT_DATA_15_8;
typedef struct {
unsigned short Enable8:1;
unsigned short Enable9:1;
unsigned short Enable10:1;
unsigned short Enable11:1;
unsigned short Enable12:1;
unsigned short Enable13:1;
unsigned short Enable14:1;
unsigned short Enable15:1;
unsigned short Mask8:1;
unsigned short Mask9:1;
unsigned short Mask10:1;
unsigned short Mask11:1;
unsigned short Mask12:1;
unsigned short Mask13:1;
unsigned short Mask14:1;
unsigned short Mask15:1;
} DSP_GPIO_DRIVER_ENABLE_15_8;
typedef struct {
unsigned short GpioMode8:2;
unsigned short GpioMode9:2;
unsigned short GpioMode10:2;
unsigned short GpioMode11:2;
unsigned short GpioMode12:2;
unsigned short GpioMode13:2;
unsigned short GpioMode14:2;
unsigned short GpioMode15:2;
} DSP_GPIO_MODE_15_8;
/* Component masks that are defined in dspmgr.h */
#define MW_ADC_MASK 0x0001
#define MW_AIC2_MASK 0x0006
#define MW_MIDI_MASK 0x0008
#define MW_CDDAC_MASK 0x8001
#define MW_AIC1_MASK 0xE006
#define MW_UART_MASK 0xE00A
#define MW_ACI_MASK 0xE00B
/*
* Definition of 3780i configuration structure. Unless otherwise stated,
* these values are provided as input to the 3780i support layer. At present,
* the only values maintained by the 3780i support layer are the saved UART
* registers.
*/
struct dsp_3780i_config_settings {
/* Location of base configuration register */
unsigned short usBaseConfigIO;
/* Enables for various DSP components */
int bDSPEnabled;
int bModemEnabled;
int bInterruptClaimed;
/* IRQ, DMA, and Base I/O addresses for various DSP components */
unsigned short usDspIrq;
unsigned short usDspDma;
unsigned short usDspBaseIO;
unsigned short usUartIrq;
unsigned short usUartBaseIO;
/* IRQ modes for various DSP components */
int bDspIrqActiveLow;
int bUartIrqActiveLow;
int bDspIrqPulse;
int bUartIrqPulse;
/* Card abilities */
unsigned uIps;
unsigned uDStoreSize;
unsigned uIStoreSize;
unsigned uDmaBandwidth;
/* Adapter specific 3780i settings */
unsigned short usNumTransfers;
unsigned short usReRequest;
int bEnableMEMCS16;
unsigned short usIsaMemCmdWidth;
int bGateIOCHRDY;
int bEnablePwrMgmt;
unsigned short usHBusTimerLoadValue;
int bDisableLBusTimeout;
unsigned short usN_Divisor;
unsigned short usM_Multiplier;
int bPllBypass;
unsigned short usChipletEnable; /* Used with the chip reset register to enable specific chiplets */
/* Saved UART registers. These are maintained by the 3780i support layer. */
int bUartSaved; /* True after a successful save of the UART registers */
unsigned char ucIER; /* Interrupt enable register */
unsigned char ucFCR; /* FIFO control register */
unsigned char ucLCR; /* Line control register */
unsigned char ucMCR; /* Modem control register */
unsigned char ucSCR; /* Scratch register */
unsigned char ucDLL; /* Divisor latch, low byte */
unsigned char ucDLM; /* Divisor latch, high byte */
};
/* 3780i support functions */
int dsp3780I_EnableDSP(struct dsp_3780i_config_settings *pSettings,
unsigned short *pIrqMap,
unsigned short *pDmaMap);
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,
void __user *pvBuffer, unsigned uCount,
unsigned long ulDSPAddr);
int dsp3780I_WriteDStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr);
int dsp3780I_ReadIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr);
int dsp3780I_WriteIStore(unsigned short usDspBaseIO, void __user *pvBuffer,
unsigned uCount, unsigned long ulDSPAddr);
unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr);
void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr, unsigned short usValue);
int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
unsigned short *pusIPCSource);
/* I/O port access macros */
#define MKWORD(var) (*((unsigned short *)(&var)))
#define MKBYTE(var) (*((unsigned char *)(&var)))
#define WriteMsaCfg(addr,value) dsp3780I_WriteMsaCfg(usDspBaseIO,addr,value)
#define ReadMsaCfg(addr) dsp3780I_ReadMsaCfg(usDspBaseIO,addr)
#define WriteGenCfg(index,value) dsp3780I_WriteGenCfg(usDspBaseIO,index,value)
#define ReadGenCfg(index) dsp3780I_ReadGenCfg(usDspBaseIO,index)
#define InWordDsp(index) inw(usDspBaseIO+index)
#define InByteDsp(index) inb(usDspBaseIO+index)
#define OutWordDsp(index,value) outw(value,usDspBaseIO+index)
#define OutByteDsp(index,value) outb(value,usDspBaseIO+index)
#endif

View file

@ -1,10 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Makefile for ACP Modem (Mwave).
#
# See the README file in this directory for more info. <paulsch@us.ibm.com>
#
obj-$(CONFIG_MWAVE) += mwave.o
mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o

View file

@ -1,37 +0,0 @@
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_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
irq used by the dsp to be configured.
mwave_3780i_io=0x130/0x350/0x0070/0xDB0
If the dsp io range has not been setup and stored in bios by the
thinkpad configuration utility then this parameter allows the
io range used by the dsp to be configured.
mwave_uart_irq=3/4
If the mwave's uart irq has not been setup and stored in bios by the
thinkpad configuration utility then this parameter allows the
irq used by the mwave uart to be configured.
mwave_uart_io=0x3f8/0x2f8/0x3E8/0x2E8
If the uart io range has not been setup and stored in bios by the
thinkpad configuration utility then this parameter allows the
io range used by the mwave uart to be configured.
Example to enable the 3780i DSP using ttyS1 resources:
insmod mwave mwave_3780i_irq=10 mwave_3780i_io=0x0130 mwave_uart_irq=3 mwave_uart_io=0x2f8
Accessing the driver
--------------------
You must also create a node for the driver:
mkdir -p /dev/modems
mknod --mode=660 /dev/modems/mwave c 10 219

View file

@ -1,432 +0,0 @@
/*
*
* mwavedd.c -- mwave device driver
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "mwavedd: " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/serial.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/serial_8250.h>
#include <linux/nospec.h>
#include "smapi.h"
#include "mwavedd.h"
#include "3780i.h"
#include "tp3780i.h"
MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver");
MODULE_AUTHOR("Mike Sullivan and Paul Schroeder");
MODULE_LICENSE("GPL");
/*
* These parameters support the setting of MWave resources. Note that no
* checks are made against other devices (ie. superio) for conflicts.
* We'll depend on users using the tpctl utility to do that for now
*/
static DEFINE_MUTEX(mwave_mutex);
int mwave_3780i_irq = 0;
int mwave_3780i_io = 0;
int mwave_uart_irq = 0;
int mwave_uart_io = 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);
struct mwave_device_data mwave_s_mdd;
static long mwave_ioctl(struct file *file, unsigned int iocmd,
unsigned long ioarg)
{
unsigned int retval = 0;
struct mwave_device_data *pDrvData = &mwave_s_mdd;
void __user *arg = (void __user *)ioarg;
switch (iocmd) {
case IOCTL_MW_RESET:
mutex_lock(&mwave_mutex);
retval = tp3780I_ResetDSP(&pDrvData->rBDData);
mutex_unlock(&mwave_mutex);
break;
case IOCTL_MW_RUN:
mutex_lock(&mwave_mutex);
retval = tp3780I_StartDSP(&pDrvData->rBDData);
mutex_unlock(&mwave_mutex);
break;
case IOCTL_MW_DSP_ABILITIES: {
struct mw_abilities rAbilities;
mutex_lock(&mwave_mutex);
retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
&rAbilities);
mutex_unlock(&mwave_mutex);
if (retval == 0) {
if (copy_to_user(arg, &rAbilities, sizeof(rAbilities)))
return -EFAULT;
}
}
break;
case IOCTL_MW_READ_DATA:
case IOCTL_MW_READCLEAR_DATA: {
struct mw_readwrite rReadData;
unsigned short __user *pusBuffer = NULL;
if( copy_from_user(&rReadData, arg,
sizeof(struct mw_readwrite)) )
return -EFAULT;
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd,
pusBuffer,
rReadData.ulDataLength,
rReadData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_READ_INST: {
struct mw_readwrite rReadData;
unsigned short __user *pusBuffer = NULL;
if (copy_from_user(&rReadData, arg, sizeof(rReadData)))
return -EFAULT;
pusBuffer = (unsigned short __user *) (rReadData.pBuf);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rReadData.ulDataLength / 2,
rReadData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_WRITE_DATA: {
struct mw_readwrite rWriteData;
unsigned short __user *pusBuffer = NULL;
if (copy_from_user(&rWriteData, arg, sizeof(rWriteData)))
return -EFAULT;
pusBuffer = (unsigned short __user *) (rWriteData.pBuf);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_WRITE_INST: {
struct mw_readwrite rWriteData;
unsigned short __user *pusBuffer = NULL;
if (copy_from_user(&rWriteData, arg, sizeof(rWriteData)))
return -EFAULT;
pusBuffer = (unsigned short __user *)(rWriteData.pBuf);
mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_REGISTER_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
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));
mutex_lock(&mwave_mutex);
pDrvData->IPCs[ipcnum].bIsHere = false;
pDrvData->IPCs[ipcnum].bIsEnabled = true;
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_GET_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
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));
mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
pDrvData->IPCs[ipcnum].bIsHere = true;
set_current_state(TASK_INTERRUPTIBLE);
/* check whether an event was signalled by */
/* 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 */
} 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;
}
}
pDrvData->IPCs[ipcnum].bIsHere = false;
remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait);
set_current_state(TASK_RUNNING);
}
mutex_unlock(&mwave_mutex);
}
break;
case IOCTL_MW_UNREGISTER_IPC: {
unsigned int ipcnum = (unsigned int) ioarg;
if (ipcnum >= ARRAY_SIZE(pDrvData->IPCs)) {
pr_err("%s: IOCTL_MW_UNREGISTER_IPC: Error: Invalid ipcnum %x\n",
__func__, ipcnum);
return -EINVAL;
}
ipcnum = array_index_nospec(ipcnum,
ARRAY_SIZE(pDrvData->IPCs));
mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
pDrvData->IPCs[ipcnum].bIsEnabled = false;
if (pDrvData->IPCs[ipcnum].bIsHere == true) {
wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue);
}
}
mutex_unlock(&mwave_mutex);
}
break;
default:
return -ENOTTY;
} /* switch */
return retval;
}
static int register_serial_portandirq(unsigned int port, int irq)
{
struct uart_8250_port uart;
switch ( port ) {
case 0x3f8:
case 0x2f8:
case 0x3e8:
case 0x2e8:
/* OK */
break;
default:
pr_err("%s: Error: Illegal port %x\n", __func__, port);
return -1;
} /* switch */
/* port is okay */
switch ( irq ) {
case 3:
case 4:
case 5:
case 7:
/* OK */
break;
default:
pr_err("%s: Error: Illegal irq %x\n", __func__, irq);
return -1;
} /* switch */
/* irq is okay */
memset(&uart, 0, sizeof(uart));
uart.port.uartclk = 1843200;
uart.port.iobase = port;
uart.port.irq = irq;
uart.port.iotype = UPIO_PORT;
uart.port.flags = UPF_SHARE_IRQ;
return serial8250_register_8250_port(&uart);
}
static const struct file_operations mwave_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = mwave_ioctl,
.llseek = default_llseek,
};
static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops };
/*
* mwave_init is called on module load
*
* mwave_exit is called on module unload
* mwave_exit is also used to clean up after an aborted mwave_init
*/
static void mwave_exit(void)
{
struct mwave_device_data *pDrvData = &mwave_s_mdd;
if ( pDrvData->sLine >= 0 ) {
serial8250_unregister_port(pDrvData->sLine);
}
if (pDrvData->bMwaveDevRegistered) {
misc_deregister(&mwave_misc_dev);
}
if (pDrvData->bDSPEnabled) {
tp3780I_DisableDSP(&pDrvData->rBDData);
}
if (pDrvData->bResourcesClaimed) {
tp3780I_ReleaseResources(&pDrvData->rBDData);
}
if (pDrvData->bBDInitialized) {
tp3780I_Cleanup(&pDrvData->rBDData);
}
}
module_exit(mwave_exit);
static int __init mwave_init(void)
{
int i;
int retval = 0;
struct mwave_device_data *pDrvData = &mwave_s_mdd;
memset(&mwave_s_mdd, 0, sizeof(mwave_s_mdd));
pDrvData->bBDInitialized = false;
pDrvData->bResourcesClaimed = false;
pDrvData->bDSPEnabled = false;
pDrvData->bDSPReset = false;
pDrvData->bMwaveDevRegistered = false;
pDrvData->sLine = -1;
for (i = 0; i < ARRAY_SIZE(pDrvData->IPCs); i++) {
pDrvData->IPCs[i].bIsEnabled = false;
pDrvData->IPCs[i].bIsHere = false;
pDrvData->IPCs[i].usIntCount = 0; /* no ints received yet */
init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue);
}
retval = tp3780I_InitializeBoardData(&pDrvData->rBDData);
if (retval) {
pr_err("%s: Error: Failed to initialize board data\n", __func__);
goto cleanup_error;
}
pDrvData->bBDInitialized = true;
retval = tp3780I_CalcResources(&pDrvData->rBDData);
if (retval) {
pr_err("%s: Error: Failed to calculate resources\n", __func__);
goto cleanup_error;
}
retval = tp3780I_ClaimResources(&pDrvData->rBDData);
if (retval) {
pr_err("%s: Error: Failed to claim resources\n", __func__);
goto cleanup_error;
}
pDrvData->bResourcesClaimed = true;
retval = tp3780I_EnableDSP(&pDrvData->rBDData);
if (retval) {
pr_err("%s: Error: Failed to enable DSP\n", __func__);
goto cleanup_error;
}
pDrvData->bDSPEnabled = true;
if (misc_register(&mwave_misc_dev) < 0) {
pr_err("%s: Error: Failed to register misc device\n", __func__);
goto cleanup_error;
}
pDrvData->bMwaveDevRegistered = true;
pDrvData->sLine = register_serial_portandirq(
pDrvData->rBDData.rDspSettings.usUartBaseIO,
pDrvData->rBDData.rDspSettings.usUartIrq
);
if (pDrvData->sLine < 0) {
pr_err("%s: Error: Failed to register serial driver\n", __func__);
goto cleanup_error;
}
/* uart is registered */
/* SUCCESS! */
return 0;
cleanup_error:
pr_err("%s: Error: Failed to initialize\n", __func__);
mwave_exit(); /* clean up */
return -EIO;
}
module_init(mwave_init);

View file

@ -1,90 +0,0 @@
/*
*
* mwavedd.h -- declarations for mwave device driver
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_MWAVEDD_H
#define _LINUX_MWAVEDD_H
#include "3780i.h"
#include "tp3780i.h"
#include "smapi.h"
#include "mwavepub.h"
#include <linux/ioctl.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
extern int mwave_3780i_irq;
extern int mwave_3780i_io;
extern int mwave_uart_irq;
extern int mwave_uart_io;
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;
};
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;
struct mwave_ipc IPCs[16];
bool bMwaveDevRegistered;
short sLine;
int nr_registered_attrs;
int device_registered;
};
extern struct mwave_device_data mwave_s_mdd;
#endif

View file

@ -1,89 +0,0 @@
/*
*
* mwavepub.h -- PUBLIC declarations for the mwave driver
* and applications using it
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_MWAVEPUB_H
#define _LINUX_MWAVEPUB_H
#include <linux/miscdevice.h>
struct mw_abilities {
unsigned long instr_per_sec;
unsigned long data_size;
unsigned long inst_size;
unsigned long bus_dma_bw;
unsigned short uart_enable;
short component_count;
unsigned long component_list[7];
char mwave_os_name[16];
char bios_task_name[16];
};
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 */
};
#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,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,struct mw_readwrite)
#endif

View file

@ -1,404 +0,0 @@
/*
*
* smapi.c -- SMAPI interface routines
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "smapi: " fmt
#include <linux/kernel.h>
#include <linux/mc146818rtc.h> /* CMOS defines */
#include "smapi.h"
#include "mwavedd.h"
static unsigned short g_usSmapiPort = 0;
static int smapi_request(unsigned short inBX, unsigned short inCX,
unsigned short inDI, unsigned short inSI,
unsigned short *outAX, unsigned short *outBX,
unsigned short *outCX, unsigned short *outDX,
unsigned short *outDI, unsigned short *outSI)
{
unsigned short myoutAX = 2, *pmyoutAX = &myoutAX;
unsigned short myoutBX = 3, *pmyoutBX = &myoutBX;
unsigned short myoutCX = 4, *pmyoutCX = &myoutCX;
unsigned short myoutDX = 5, *pmyoutDX = &myoutDX;
unsigned short myoutDI = 6, *pmyoutDI = &myoutDI;
unsigned short myoutSI = 7, *pmyoutSI = &myoutSI;
unsigned short usSmapiOK = -EIO, *pusSmapiOK = &usSmapiOK;
unsigned int inBXCX = (inBX << 16) | inCX;
unsigned int inDISI = (inDI << 16) | inSI;
__asm__ __volatile__("movw $0x5380,%%ax\n\t"
"movl %7,%%ebx\n\t"
"shrl $16, %%ebx\n\t"
"movw %7,%%cx\n\t"
"movl %8,%%edi\n\t"
"shrl $16,%%edi\n\t"
"movw %8,%%si\n\t"
"movw %9,%%dx\n\t"
"out %%al,%%dx\n\t"
"out %%al,$0x4F\n\t"
"cmpb $0x53,%%ah\n\t"
"je 2f\n\t"
"1:\n\t"
"orb %%ah,%%ah\n\t"
"jnz 2f\n\t"
"movw %%ax,%0\n\t"
"movw %%bx,%1\n\t"
"movw %%cx,%2\n\t"
"movw %%dx,%3\n\t"
"movw %%di,%4\n\t"
"movw %%si,%5\n\t"
"movw $1,%6\n\t"
"2:\n\t":"=m"(*(unsigned short *) pmyoutAX),
"=m"(*(unsigned short *) pmyoutBX),
"=m"(*(unsigned short *) pmyoutCX),
"=m"(*(unsigned short *) pmyoutDX),
"=m"(*(unsigned short *) pmyoutDI),
"=m"(*(unsigned short *) pmyoutSI),
"=m"(*(unsigned short *) pusSmapiOK)
:"m"(inBXCX), "m"(inDISI), "m"(g_usSmapiPort)
:"%eax", "%ebx", "%ecx", "%edx", "%edi",
"%esi");
*outAX = myoutAX;
*outBX = myoutBX;
*outCX = myoutCX;
*outDX = myoutDX;
*outDI = myoutDI;
*outSI = myoutSI;
return usSmapiOK == 1 ? 0 : -EIO;
}
int smapi_query_DSP_cfg(struct smapi_dsp_settings *pSettings)
{
int bRC;
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
static const unsigned short ausDspBases[] = {
0x0030, 0x4E30, 0x8E30, 0xCE30,
0x0130, 0x0350, 0x0070, 0x0DB0 };
static const unsigned short ausUartBases[] = {
0x03F8, 0x02F8, 0x03E8, 0x02E8 };
bRC = smapi_request(0x1802, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) {
pr_err("%s: Error: Could not get DSP Settings. Aborting.\n", __func__);
return bRC;
}
pSettings->bDSPPresent = ((usBX & 0x0100) != 0);
pSettings->bDSPEnabled = ((usCX & 0x0001) != 0);
pSettings->usDspIRQ = usSI & 0x00FF;
pSettings->usDspDMA = (usSI & 0xFF00) >> 8;
if ((usDI & 0x00FF) < ARRAY_SIZE(ausDspBases)) {
pSettings->usDspBaseIO = ausDspBases[usDI & 0x00FF];
} else {
pSettings->usDspBaseIO = 0;
}
/* check for illegal values */
if ( pSettings->usDspBaseIO == 0 )
pr_err("%s: Worry: DSP base I/O address is 0\n", __func__);
if ( pSettings->usDspIRQ == 0 )
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) {
pr_err("%s: Error: Could not get DSP modem settings. Aborting.\n", __func__);
return bRC;
}
pSettings->bModemEnabled = ((usCX & 0x0001) != 0);
pSettings->usUartIRQ = usSI & 0x000F;
if (((usSI & 0xFF00) >> 8) < ARRAY_SIZE(ausUartBases)) {
pSettings->usUartBaseIO = ausUartBases[(usSI & 0xFF00) >> 8];
} else {
pSettings->usUartBaseIO = 0;
}
/* check for illegal values */
if ( pSettings->usUartBaseIO == 0 )
pr_err("%s: Worry: UART base I/O address is 0\n", __func__);
if ( pSettings->usUartIRQ == 0 )
pr_err("%s: Worry: UART IRQ line is 0\n", __func__);
return bRC;
}
int smapi_set_DSP_cfg(void)
{
int bRC = -EIO;
int i;
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
static const unsigned short ausDspBases[] = {
0x0030, 0x4E30, 0x8E30, 0xCE30,
0x0130, 0x0350, 0x0070, 0x0DB0 };
static const unsigned short ausUartBases[] = {
0x03F8, 0x02F8, 0x03E8, 0x02E8 };
static const unsigned short ausDspIrqs[] = {
5, 7, 10, 11, 15 };
static const unsigned short ausUartIrqs[] = {
3, 4 };
unsigned short dspio_index = 0, uartio_index = 0;
if (mwave_3780i_io) {
for (i = 0; i < ARRAY_SIZE(ausDspBases); i++) {
if (mwave_3780i_io == ausDspBases[i])
break;
}
if (i == ARRAY_SIZE(ausDspBases)) {
pr_err("%s: Error: Invalid mwave_3780i_io address %x. Aborting.\n",
__func__, mwave_3780i_io);
return bRC;
}
dspio_index = i;
}
if (mwave_3780i_irq) {
for (i = 0; i < ARRAY_SIZE(ausDspIrqs); i++) {
if (mwave_3780i_irq == ausDspIrqs[i])
break;
}
if (i == ARRAY_SIZE(ausDspIrqs)) {
pr_err("%s: Error: Invalid mwave_3780i_irq %x. Aborting.\n", __func__,
mwave_3780i_irq);
return bRC;
}
}
if (mwave_uart_io) {
for (i = 0; i < ARRAY_SIZE(ausUartBases); i++) {
if (mwave_uart_io == ausUartBases[i])
break;
}
if (i == ARRAY_SIZE(ausUartBases)) {
pr_err("%s: Error: Invalid mwave_uart_io address %x. Aborting.\n", __func__,
mwave_uart_io);
return bRC;
}
uartio_index = i;
}
if (mwave_uart_irq) {
for (i = 0; i < ARRAY_SIZE(ausUartIrqs); i++) {
if (mwave_uart_irq == ausUartIrqs[i])
break;
}
if (i == ARRAY_SIZE(ausUartIrqs)) {
pr_err("%s: Error: Invalid mwave_uart_irq %x. Aborting.\n", __func__,
mwave_uart_irq);
return bRC;
}
}
if (mwave_uart_irq || mwave_uart_io) {
/* Check serial port A */
bRC = smapi_request(0x1402, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
/* bRC == 0 */
if (usBX & 0x0100) { /* serial port A is present */
if (usCX & 1) { /* serial port is enabled */
if ((usSI & 0xFF) == mwave_uart_irq) {
pr_err("%s: Serial port A irq %x conflicts with mwave_uart_irq %x\n",
__func__, usSI & 0xFF, mwave_uart_irq);
goto exit_conflict;
} else {
if ((usSI >> 8) == uartio_index) {
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;
}
}
}
}
/* Check serial port B */
bRC = smapi_request(0x1404, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
/* bRC == 0 */
if (usBX & 0x0100) { /* serial port B is present */
if (usCX & 1) { /* serial port is enabled */
if ((usSI & 0xFF) == mwave_uart_irq) {
pr_err("%s: Serial port B irq %x conflicts with mwave_uart_irq %x\n",
__func__, usSI & 0xFF, mwave_uart_irq);
goto exit_conflict;
} else {
if ((usSI >> 8) == uartio_index) {
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;
}
}
}
}
/* Check IR port */
bRC = smapi_request(0x1700, 0x0000, 0, 0,
&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;
/* bRC == 0 */
if ((usCX & 0xff) != 0xff) { /* IR port not disabled */
if ((usCX & 0xff) == mwave_uart_irq) {
pr_err("%s: IR port irq %x conflicts with mwave_uart_irq %x\n",
__func__, usCX & 0xff, mwave_uart_irq);
goto exit_conflict;
} else {
if ((usSI & 0xff) == uartio_index) {
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;
}
}
}
}
bRC = smapi_request(0x1802, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
if (mwave_3780i_io) {
usDI = dspio_index;
}
if (mwave_3780i_irq) {
usSI = (usSI & 0xff00) | mwave_3780i_irq;
}
bRC = smapi_request(0x1803, 0x0101, usDI, usSI,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
bRC = smapi_request(0x1804, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
if (mwave_uart_io) {
usSI = (usSI & 0x00ff) | (uartio_index << 8);
}
if (mwave_uart_irq) {
usSI = (usSI & 0xff00) | mwave_uart_irq;
}
bRC = smapi_request(0x1805, 0x0101, 0, usSI,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
bRC = smapi_request(0x1802, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
bRC = smapi_request(0x1804, 0x0000, 0, 0,
&usAX, &usBX, &usCX, &usDX, &usDI, &usSI);
if (bRC) goto exit_smapi_request_error;
/* normal exit: */
return 0;
exit_conflict:
/* Message has already been printed */
return -EIO;
exit_smapi_request_error:
pr_err("%s: exit on smapi_request error bRC %x\n", __func__, bRC);
return bRC;
}
int smapi_set_DSP_power_state(bool bOn)
{
unsigned short usAX, usBX, usCX, usDX, usDI, usSI;
unsigned short usPowerFunction;
usPowerFunction = (bOn) ? 1 : 0;
return smapi_request(0x4901, 0x0000, 0, usPowerFunction, &usAX, &usBX, &usCX, &usDX, &usDI,
&usSI);
}
int smapi_init(void)
{
int retval = -EIO;
unsigned short usSmapiID = 0;
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
usSmapiID = CMOS_READ(0x7C);
usSmapiID |= (CMOS_READ(0x7D) << 8);
spin_unlock_irqrestore(&rtc_lock, flags);
if (usSmapiID == 0x5349) {
spin_lock_irqsave(&rtc_lock, flags);
g_usSmapiPort = CMOS_READ(0x7E);
g_usSmapiPort |= (CMOS_READ(0x7F) << 8);
spin_unlock_irqrestore(&rtc_lock, flags);
if (g_usSmapiPort == 0) {
pr_err("%s: ERROR unable to read from SMAPI port\n", __func__);
} else {
retval = 0;
//SmapiQuerySystemID();
}
} else {
pr_err("%s: ERROR invalid usSmapiID\n", __func__);
retval = -ENXIO;
}
return retval;
}

View file

@ -1,76 +0,0 @@
/*
*
* smapi.h -- declarations for SMAPI interface routines
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_SMAPI_H
#define _LINUX_SMAPI_H
struct smapi_dsp_settings {
int bDSPPresent;
int bDSPEnabled;
int bModemEnabled;
int bMIDIEnabled;
int bSblstEnabled;
unsigned short usDspIRQ;
unsigned short usDspDMA;
unsigned short usDspBaseIO;
unsigned short usUartIRQ;
unsigned short usUartBaseIO;
unsigned short usMidiIRQ;
unsigned short usMidiBaseIO;
unsigned short usSndblstIRQ;
unsigned short usSndblstDMA;
unsigned short usSndblstBaseIO;
};
int smapi_init(void);
int smapi_query_DSP_cfg(struct smapi_dsp_settings *pSettings);
int smapi_set_DSP_cfg(void);
int smapi_set_DSP_power_state(bool bOn);
#endif

View file

@ -1,477 +0,0 @@
/*
*
* tp3780i.c -- board driver for 3780i on ThinkPads
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#define pr_fmt(fmt) "tp3780i: " fmt
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include "smapi.h"
#include "mwavedd.h"
#include "tp3780i.h"
#include "3780i.h"
#include "mwavepub.h"
static unsigned short s_ausThinkpadIrqToField[16] =
{ 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004,
0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 };
static unsigned short s_ausThinkpadDmaToField[8] =
{ 0x0001, 0x0002, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0003, 0x0004 };
static unsigned short s_numIrqs = 16, s_numDmas = 8;
static void EnableSRAM(struct thinkpad_bd_data *pBDData)
{
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;
MKWORD(rGpioMode) = ReadMsaCfg(DSP_GpioModeControl_15_8);
rGpioMode.GpioMode10 = 0;
WriteMsaCfg(DSP_GpioModeControl_15_8, MKWORD(rGpioMode));
MKWORD(rGpioDriverEnable) = 0;
rGpioDriverEnable.Enable10 = true;
rGpioDriverEnable.Mask10 = true;
WriteMsaCfg(DSP_GpioDriverEnable_15_8, MKWORD(rGpioDriverEnable));
MKWORD(rGpioOutputData) = 0;
rGpioOutputData.Latch10 = 0;
rGpioOutputData.Mask10 = true;
WriteMsaCfg(DSP_GpioOutputData_15_8, MKWORD(rGpioOutputData));
}
static irqreturn_t UartInterrupt(int irq, void *dev_id)
{
return IRQ_HANDLED;
}
static irqreturn_t DspInterrupt(int irq, void *dev_id)
{
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;
if (dsp3780I_GetIPCSource(usDspBaseIO, &usIPCSource) == 0) {
usIsolationMask = 1;
for (usPCNum = 1; usPCNum <= 16; usPCNum++) {
if (usIPCSource & usIsolationMask) {
usIPCSource &= ~usIsolationMask;
if (pDrvData->IPCs[usPCNum - 1].usIntCount == 0) {
pDrvData->IPCs[usPCNum - 1].usIntCount = 1;
}
if (pDrvData->IPCs[usPCNum - 1].bIsEnabled == true) {
wake_up_interruptible(&pDrvData->IPCs[usPCNum - 1].ipc_wait_queue);
}
}
if (usIPCSource == 0)
break;
/* try next IPC */
usIsolationMask = usIsolationMask << 1;
}
}
return IRQ_HANDLED;
}
int tp3780I_InitializeBoardData(struct thinkpad_bd_data *pBDData)
{
int retval = 0;
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
pBDData->bDSPEnabled = false;
pSettings->bInterruptClaimed = false;
retval = smapi_init();
if (retval) {
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();
}
}
return retval;
}
void tp3780I_Cleanup(struct thinkpad_bd_data *pBDData)
{
}
int tp3780I_CalcResources(struct thinkpad_bd_data *pBDData)
{
struct smapi_dsp_settings rSmapiInfo;
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
if (smapi_query_DSP_cfg(&rSmapiInfo)) {
pr_err("%s: Error: Could not query DSP config. Aborting.\n", __func__);
return -EIO;
}
/* Sanity check */
if (
( rSmapiInfo.usDspIRQ == 0 )
|| ( rSmapiInfo.usDspBaseIO == 0 )
|| ( rSmapiInfo.usUartIRQ == 0 )
|| ( rSmapiInfo.usUartBaseIO == 0 )
) {
pr_err("%s: Error: Illegal resource setting. Aborting.\n", __func__);
return -EIO;
}
pSettings->bDSPEnabled = (rSmapiInfo.bDSPEnabled && rSmapiInfo.bDSPPresent);
pSettings->bModemEnabled = rSmapiInfo.bModemEnabled;
pSettings->usDspIrq = rSmapiInfo.usDspIRQ;
pSettings->usDspDma = rSmapiInfo.usDspDMA;
pSettings->usDspBaseIO = rSmapiInfo.usDspBaseIO;
pSettings->usUartIrq = rSmapiInfo.usUartIRQ;
pSettings->usUartBaseIO = rSmapiInfo.usUartBaseIO;
pSettings->uDStoreSize = TP_ABILITIES_DATA_SIZE;
pSettings->uIStoreSize = TP_ABILITIES_INST_SIZE;
pSettings->uIps = TP_ABILITIES_INTS_PER_SEC;
if (pSettings->bDSPEnabled && pSettings->bModemEnabled && pSettings->usDspIrq == pSettings->usUartIrq) {
pBDData->bShareDspIrq = pBDData->bShareUartIrq = 1;
} else {
pBDData->bShareDspIrq = pBDData->bShareUartIrq = 0;
}
return 0;
}
int tp3780I_ClaimResources(struct thinkpad_bd_data *pBDData)
{
int retval = 0;
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
struct resource *pres;
pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
if ( pres == NULL ) retval = -EIO;
if (retval) {
pr_err("%s: Error: Could not claim I/O region starting at %x\n", __func__,
pSettings->usDspBaseIO);
return -EIO;
}
return retval;
}
int tp3780I_ReleaseResources(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
release_region(pSettings->usDspBaseIO & (~3), 16);
if (pSettings->bInterruptClaimed) {
free_irq(pSettings->usDspIrq, NULL);
pSettings->bInterruptClaimed = false;
}
return 0;
}
int tp3780I_EnableDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
bool bDSPPoweredUp = false, bInterruptAllocated = false;
if (pBDData->bDSPEnabled) {
pr_err("%s: Error: DSP already enabled!\n", __func__);
goto exit_cleanup;
}
if (!pSettings->bDSPEnabled) {
pr_err("%s: Error: pSettings->bDSPEnabled not set\n", __func__);
goto exit_cleanup;
}
if (
(pSettings->usDspIrq >= s_numIrqs)
|| (pSettings->usDspDma >= s_numDmas)
|| (s_ausThinkpadIrqToField[pSettings->usDspIrq] == 0xFFFF)
|| (s_ausThinkpadDmaToField[pSettings->usDspDma] == 0xFFFF)
) {
pr_err("%s: Error: invalid irq %x\n", __func__, pSettings->usDspIrq);
goto exit_cleanup;
}
if (
((pSettings->usDspBaseIO & 0xF00F) != 0)
|| (pSettings->usDspBaseIO & 0x0FF0) == 0
) {
pr_err("%s: Error: Invalid DSP base I/O address %x\n", __func__,
pSettings->usDspBaseIO);
goto exit_cleanup;
}
if (pSettings->bModemEnabled) {
if (
pSettings->usUartIrq >= s_numIrqs
|| s_ausThinkpadIrqToField[pSettings->usUartIrq] == 0xFFFF
) {
pr_err("%s: Error: Invalid UART IRQ %x\n", __func__, pSettings->usUartIrq);
goto exit_cleanup;
}
switch (pSettings->usUartBaseIO) {
case 0x03F8:
case 0x02F8:
case 0x03E8:
case 0x02E8:
break;
default:
pr_err("%s: Error: Invalid UART base I/O address %x\n", __func__,
pSettings->usUartBaseIO);
goto exit_cleanup;
}
}
pSettings->bDspIrqActiveLow = pSettings->bDspIrqPulse = true;
pSettings->bUartIrqActiveLow = pSettings->bUartIrqPulse = true;
if (pBDData->bShareDspIrq) {
pSettings->bDspIrqActiveLow = false;
}
if (pBDData->bShareUartIrq) {
pSettings->bUartIrqActiveLow = false;
}
pSettings->usNumTransfers = TP_CFG_NumTransfers;
pSettings->usReRequest = TP_CFG_RerequestTimer;
pSettings->bEnableMEMCS16 = TP_CFG_MEMCS16;
pSettings->usIsaMemCmdWidth = TP_CFG_IsaMemCmdWidth;
pSettings->bGateIOCHRDY = TP_CFG_GateIOCHRDY;
pSettings->bEnablePwrMgmt = TP_CFG_EnablePwrMgmt;
pSettings->usHBusTimerLoadValue = TP_CFG_HBusTimerValue;
pSettings->bDisableLBusTimeout = TP_CFG_DisableLBusTimeout;
pSettings->usN_Divisor = TP_CFG_N_Divisor;
pSettings->usM_Multiplier = TP_CFG_M_Multiplier;
pSettings->bPllBypass = TP_CFG_PllBypass;
pSettings->usChipletEnable = TP_CFG_ChipletEnable;
if (request_irq(pSettings->usUartIrq, &UartInterrupt, 0, "mwave_uart", NULL)) {
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)) {
pr_err("%s: Error: Could not get 3780i IRQ %x\n", __func__, pSettings->usDspIrq);
goto exit_cleanup;
} else {
bInterruptAllocated = true;
pSettings->bInterruptClaimed = true;
}
smapi_set_DSP_power_state(false);
if (smapi_set_DSP_power_state(true)) {
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)) {
pr_err("%s: Error: dsp7880I_EnableDSP() failed\n", __func__);
goto exit_cleanup;
}
EnableSRAM(pBDData);
pBDData->bDSPEnabled = true;
return 0;
exit_cleanup:
pr_err("%s: Cleaning up\n", __func__);
if (bDSPPoweredUp)
smapi_set_DSP_power_state(false);
if (bInterruptAllocated) {
free_irq(pSettings->usDspIrq, NULL);
pSettings->bInterruptClaimed = false;
}
return -EIO;
}
int tp3780I_DisableDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
if (pBDData->bDSPEnabled) {
dsp3780I_DisableDSP(&pBDData->rDspSettings);
if (pSettings->bInterruptClaimed) {
free_irq(pSettings->usDspIrq, NULL);
pSettings->bInterruptClaimed = false;
}
smapi_set_DSP_power_state(false);
pBDData->bDSPEnabled = false;
}
return 0;
}
int tp3780I_ResetDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
if (dsp3780I_Reset(pSettings) == 0) {
EnableSRAM(pBDData);
return 0;
}
return -EIO;
}
int tp3780I_StartDSP(struct thinkpad_bd_data *pBDData)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
if (dsp3780I_Run(pSettings) == 0) {
// @BUG @TBD EnableSRAM(pBDData);
} else {
return -EIO;
}
return 0;
}
int tp3780I_QueryAbilities(struct thinkpad_bd_data *pBDData, struct mw_abilities *pAbilities)
{
memset(pAbilities, 0, sizeof(*pAbilities));
/* fill out standard constant fields */
pAbilities->instr_per_sec = pBDData->rDspSettings.uIps;
pAbilities->data_size = pBDData->rDspSettings.uDStoreSize;
pAbilities->inst_size = pBDData->rDspSettings.uIStoreSize;
pAbilities->bus_dma_bw = pBDData->rDspSettings.uDmaBandwidth;
/* fill out dynamically determined fields */
pAbilities->component_list[0] = 0x00010000 | MW_ADC_MASK;
pAbilities->component_list[1] = 0x00010000 | MW_ACI_MASK;
pAbilities->component_list[2] = 0x00010000 | MW_AIC1_MASK;
pAbilities->component_list[3] = 0x00010000 | MW_AIC2_MASK;
pAbilities->component_list[4] = 0x00010000 | MW_CDDAC_MASK;
pAbilities->component_list[5] = 0x00010000 | MW_MIDI_MASK;
pAbilities->component_list[6] = 0x00010000 | MW_UART_MASK;
pAbilities->component_count = 7;
/* Fill out Mwave OS and BIOS task names */
memcpy(pAbilities->mwave_os_name, TP_ABILITIES_MWAVEOS_NAME,
sizeof(TP_ABILITIES_MWAVEOS_NAME));
memcpy(pAbilities->bios_task_name, TP_ABILITIES_BIOSTASK_NAME,
sizeof(TP_ABILITIES_BIOSTASK_NAME));
return 0;
}
int tp3780I_ReadWriteDspDStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
void __user *pvBuffer, unsigned int uCount,
unsigned long ulDSPAddr)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
bool bRC = 0;
if (pBDData->bDSPEnabled) {
switch (uOpcode) {
case IOCTL_MW_READ_DATA:
bRC = dsp3780I_ReadDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
case IOCTL_MW_READCLEAR_DATA:
bRC = dsp3780I_ReadAndClearDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
case IOCTL_MW_WRITE_DATA:
bRC = dsp3780I_WriteDStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
}
}
return bRC ? -EIO : 0;
}
int tp3780I_ReadWriteDspIStore(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
void __user *pvBuffer, unsigned int uCount,
unsigned long ulDSPAddr)
{
struct dsp_3780i_config_settings *pSettings = &pBDData->rDspSettings;
unsigned short usDspBaseIO = pSettings->usDspBaseIO;
bool bRC = 0;
if (pBDData->bDSPEnabled) {
switch (uOpcode) {
case IOCTL_MW_READ_INST:
bRC = dsp3780I_ReadIStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
case IOCTL_MW_WRITE_INST:
bRC = dsp3780I_WriteIStore(usDspBaseIO, pvBuffer, uCount, ulDSPAddr);
break;
}
}
return bRC ? -EIO : 0;
}

View file

@ -1,103 +0,0 @@
/*
*
* tp3780i.h -- declarations for tp3780i.c
*
*
* Written By: Mike Sullivan IBM Corporation
*
* Copyright (C) 1999 IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* NO WARRANTY
* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
* solely responsible for determining the appropriateness of using and
* distributing the Program and assumes all risks associated with its
* exercise of rights under this Agreement, including but not limited to
* the risks and costs of program errors, damage to or loss of data,
* programs or equipment, and unavailability or interruption of operations.
*
* DISCLAIMER OF LIABILITY
* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* 10/23/2000 - Alpha Release
* First release to the public
*/
#ifndef _LINUX_TP3780I_H
#define _LINUX_TP3780I_H
#include <asm/io.h>
#include "mwavepub.h"
/* DSP abilities constants for 3780i based Thinkpads */
#define TP_ABILITIES_INTS_PER_SEC 39160800
#define TP_ABILITIES_DATA_SIZE 32768
#define TP_ABILITIES_INST_SIZE 32768
#define TP_ABILITIES_MWAVEOS_NAME "mwaveos0700.dsp"
#define TP_ABILITIES_BIOSTASK_NAME "mwbio701.dsp"
/* DSP configuration values for 3780i based Thinkpads */
#define TP_CFG_NumTransfers 3 /* 16 transfers */
#define TP_CFG_RerequestTimer 1 /* 2 usec */
#define TP_CFG_MEMCS16 0 /* Disabled, 16-bit memory assumed */
#define TP_CFG_IsaMemCmdWidth 3 /* 295 nsec (16-bit) */
#define TP_CFG_GateIOCHRDY 0 /* No IOCHRDY gating */
#define TP_CFG_EnablePwrMgmt 1 /* Enable low poser suspend/resume */
#define TP_CFG_HBusTimerValue 255 /* HBus timer load value */
#define TP_CFG_DisableLBusTimeout 0 /* Enable LBus timeout */
#define TP_CFG_N_Divisor 32 /* Clock = 39.1608 Mhz */
#define TP_CFG_M_Multiplier 37 /* " */
#define TP_CFG_PllBypass 0 /* don't bypass */
#define TP_CFG_ChipletEnable 0xFFFF /* Enable all chiplets */
struct thinkpad_bd_data {
int bDSPEnabled;
int bShareDspIrq;
int bShareUartIrq;
struct dsp_3780i_config_settings rDspSettings;
};
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(struct thinkpad_bd_data *pBDData, unsigned int uOpcode,
void __user *pvBuffer, unsigned int uCount,
unsigned long ulDSPAddr);
#endif

View file

@ -48,7 +48,7 @@
#define XHI_GIER_GIE_MASK 0x80000000 /* Global Interrupt enable Mask */
/**
/*
* HwIcap Device Interrupt Status/Enable Registers
*
* Interrupt Status Register (IPISR) : This register holds the
@ -102,6 +102,8 @@ static inline void fifo_icap_fifo_write(struct hwicap_drvdata *drvdata,
* @drvdata: a pointer to the drvdata.
*
* This function will silently fail if the fifo is empty.
*
* Returns: 32-bit data from the Read FIFO
**/
static inline u32 fifo_icap_fifo_read(struct hwicap_drvdata *drvdata)
{
@ -156,6 +158,8 @@ static inline void fifo_icap_start_readback(struct hwicap_drvdata *drvdata)
* D2 - Always 1
* D1 - Always 1
* D0 - Done bit
*
* Returns: the 32-bit ICAP status register
**/
u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata)
{
@ -165,8 +169,11 @@ u32 fifo_icap_get_status(struct hwicap_drvdata *drvdata)
}
/**
* fifo_icap_busy - Return true if the ICAP is still processing a transaction.
* fifo_icap_busy - Check the ICAP busy status.
* @drvdata: a pointer to the drvdata.
*
* Returns: %true if the ICAP is still processing a transaction,
* otherwise %false
**/
static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
{
@ -178,7 +185,7 @@ static inline u32 fifo_icap_busy(struct hwicap_drvdata *drvdata)
* fifo_icap_write_fifo_vacancy - Query the write fifo available space.
* @drvdata: a pointer to the drvdata.
*
* Return the number of words that can be safely pushed into the write fifo.
* Returns: the number of words that can be safely pushed into the write fifo.
**/
static inline u32 fifo_icap_write_fifo_vacancy(
struct hwicap_drvdata *drvdata)
@ -190,7 +197,7 @@ static inline u32 fifo_icap_write_fifo_vacancy(
* fifo_icap_read_fifo_occupancy - Query the read fifo available data.
* @drvdata: a pointer to the drvdata.
*
* Return the number of words that can be safely read from the read fifo.
* Returns: the number of words that can be safely read from the read fifo.
**/
static inline u32 fifo_icap_read_fifo_occupancy(
struct hwicap_drvdata *drvdata)
@ -205,10 +212,12 @@ static inline u32 fifo_icap_read_fifo_occupancy(
* ICAP device.
* @num_words: the number of words (32 bit) to write to the ICAP
* device.
*
* This function writes the given user data to the Write FIFO in
* polled mode and starts the transfer of the data to
* the ICAP device.
*
* Returns: %0 on success or %-errno on failure.
**/
int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,
u32 *frame_buffer, u32 num_words)
@ -280,11 +289,13 @@ int fifo_icap_set_configuration(struct hwicap_drvdata *drvdata,
/**
* fifo_icap_get_configuration - Read configuration data from the device.
* @drvdata: a pointer to the drvdata.
* @data: Address of the data representing the partial bitstream
* @size: the size of the partial bitstream in 32 bit words.
* @frame_buffer: Address of the data representing the partial bitstream
* @num_words: the size of the partial bitstream in 32 bit words.
*
* This function reads the specified number of words from the ICAP device in
* the polled mode.
*
* Returns: %0 on success or %-errno on failure.
*/
int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,
u32 *frame_buffer, u32 num_words)
@ -347,7 +358,7 @@ int fifo_icap_get_configuration(struct hwicap_drvdata *drvdata,
}
/**
* buffer_icap_reset - Reset the logic of the icap device.
* fifo_icap_reset - Reset the logic of the icap device.
* @drvdata: a pointer to the drvdata.
*
* This function forces the software reset of the complete HWICAP device.

View file

@ -1169,6 +1169,8 @@ static int do_chaninfo_ioctl(struct comedi_device *dev,
* COMEDI_BUFINFO ioctl
* buffer information
*
* Note that the comedi device's mutex has not been locked for this ioctl.
*
* arg:
* pointer to comedi_bufinfo structure
*
@ -1186,24 +1188,42 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
struct comedi_async *async;
unsigned int runflags;
int retval = 0;
unsigned int old_detach_count;
unsigned int cmd_flags;
bool become_nonbusy = false;
bool attach_locked;
lockdep_assert_held(&dev->mutex);
if (copy_from_user(&bi, arg, sizeof(bi)))
return -EFAULT;
if (bi.subdevice >= dev->n_subdevices)
return -EINVAL;
/* Protect against device detachment during operation. */
down_read(&dev->attach_lock);
attach_locked = true;
old_detach_count = dev->detach_count;
if (!dev->attached) {
dev_dbg(dev->class_dev, "no driver attached\n");
retval = -ENODEV;
goto out;
}
if (bi.subdevice >= dev->n_subdevices) {
retval = -EINVAL;
goto out;
}
s = &dev->subdevices[bi.subdevice];
async = s->async;
if (!async || s->busy != file)
return -EINVAL;
if (!async || s->busy != file) {
retval = -EINVAL;
goto out;
}
runflags = comedi_get_subdevice_runflags(s);
if (!(async->cmd.flags & CMDF_WRITE)) {
cmd_flags = async->cmd.flags;
if (!(cmd_flags & CMDF_WRITE)) {
/* command was set up in "read" direction */
if (bi.bytes_read) {
_comedi_buf_read_alloc(s, bi.bytes_read);
@ -1243,8 +1263,41 @@ static int do_bufinfo_ioctl(struct comedi_device *dev,
bi.buf_read_count = async->buf_read_count;
bi.buf_read_ptr = async->buf_read_ptr;
if (become_nonbusy)
do_become_nonbusy(dev, s);
if (become_nonbusy) {
struct comedi_subdevice *new_s = NULL;
/*
* To avoid deadlock, cannot acquire dev->mutex
* while dev->attach_lock is held.
*/
up_read(&dev->attach_lock);
attach_locked = false;
mutex_lock(&dev->mutex);
/*
* Check device hasn't become detached behind our back.
* Checking dev->detach_count is unchanged ought to be
* sufficient, but check the subdevice pointer as well,
* and check the subdevice is still in a suitable state
* to become non-busy. It should still be "busy" after
* running an asynchronous commands, which should now have
* stopped, and for a command in the "read" direction, all
* available data should have been read.
*/
if (dev->attached && old_detach_count == dev->detach_count &&
bi.subdevice < dev->n_subdevices)
new_s = &dev->subdevices[bi.subdevice];
if (s == new_s && new_s->async == async && s->busy == file &&
async->cmd.flags == cmd_flags &&
!comedi_is_subdevice_running(s) &&
((cmd_flags & CMDF_WRITE) != 0 ||
_comedi_buf_read_n_available(s) == 0))
do_become_nonbusy(dev, s);
mutex_unlock(&dev->mutex);
}
out:
if (attach_locked)
up_read(&dev->attach_lock);
if (retval)
return retval;
@ -2225,6 +2278,13 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
struct comedi_device *dev = cfp->dev;
int rc;
/* Handle COMEDI_BUFINFO without locking the mutex first. */
if (cmd == COMEDI_BUFINFO) {
return do_bufinfo_ioctl(dev,
(struct comedi_bufinfo __user *)arg,
file);
}
mutex_lock(&dev->mutex);
/*
@ -2294,11 +2354,6 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
rc = do_rangeinfo_ioctl(dev, &it);
break;
}
case COMEDI_BUFINFO:
rc = do_bufinfo_ioctl(dev,
(struct comedi_bufinfo __user *)arg,
file);
break;
case COMEDI_LOCK:
rc = do_lock_ioctl(dev, arg, file);
break;

View file

@ -692,6 +692,44 @@ static int waveform_ao_insn_config(struct comedi_device *dev,
return -EINVAL;
}
static int waveform_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
u32 driven_low;
u16 wires;
/* Update the channel outputs. */
comedi_dio_update_state(s, data);
/*
* We are modelling the outputs as NPN open collector (0 = driven low,
* 1 = high impedance), with the lower 16 channels wired to the upper
* 16 channels in pairs (0 to 16, 1 to 17, ..., 15 to 31), with a
* pull-up resistor on each wire. When reading back each channel, we
* read back the state of the wire to which it is connected.
*
* The state of each wire and the value read back from both channels
* connected to it will be logic 1 unless either channel connected to
* the wire is configured as an output in the logic 0 state.
*/
driven_low = s->io_bits & ~s->state;
wires = 0xFFFF & ~driven_low & ~(driven_low >> 16);
/* Read back the state of the wires for each pair of channels. */
data[1] = wires | (wires << 16);
return insn->n;
}
static int waveform_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
/* configure each channel as input or output individually */
return comedi_dio_insn_config(dev, s, insn, data, 0);
}
static int waveform_common_attach(struct comedi_device *dev,
int amplitude, int period)
{
@ -707,7 +745,7 @@ static int waveform_common_attach(struct comedi_device *dev,
devpriv->wf_amplitude = amplitude;
devpriv->wf_period = period;
ret = comedi_alloc_subdevices(dev, 2);
ret = comedi_alloc_subdevices(dev, 3);
if (ret)
return ret;
@ -746,6 +784,16 @@ static int waveform_common_attach(struct comedi_device *dev,
for (i = 0; i < s->n_chan; i++)
devpriv->ao_loopbacks[i] = s->maxdata / 2;
s = &dev->subdevices[2];
/* digital input/output subdevice */
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 32;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = waveform_dio_insn_bits;
s->insn_config = waveform_dio_insn_config;
devpriv->dev = dev;
timer_setup(&devpriv->ai_timer, waveform_ai_timer, 0);
timer_setup(&devpriv->ao_timer, waveform_ao_timer, 0);

View file

@ -1317,7 +1317,7 @@ int stratix10_svc_async_send(struct stratix10_svc_chan *chan, void *msg,
dev_dbg(ctrl->dev,
"Async message sent with transaction_id 0x%02x\n",
handle->transaction_id);
*handler = handle;
*handler = handle;
return 0;
case INTEL_SIP_SMC_STATUS_BUSY:
dev_warn(ctrl->dev, "Mailbox is busy, try after some time\n");
@ -1702,12 +1702,12 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg)
kthread_run_on_cpu(svc_normal_to_secure_thread,
(void *)chan->ctrl,
cpu, "svc_smc_hvc_thread");
if (IS_ERR(chan->ctrl->task)) {
dev_err(chan->ctrl->dev,
"failed to create svc_smc_hvc_thread\n");
kfree(p_data);
return -EINVAL;
}
if (IS_ERR(chan->ctrl->task)) {
dev_err(chan->ctrl->dev,
"failed to create svc_smc_hvc_thread\n");
kfree(p_data);
return -EINVAL;
}
}
pr_debug("%s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__,

View file

@ -2018,7 +2018,7 @@ static void __exit dfl_fpga_exit(void)
bus_unregister(&dfl_bus_type);
}
module_init(dfl_fpga_init);
subsys_initcall(dfl_fpga_init);
module_exit(dfl_fpga_exit);
MODULE_DESCRIPTION("FPGA Device Feature List (DFL) Support");

View file

@ -82,7 +82,7 @@
#define DFH_TYPE_FIU 4
/*
* DFHv1 Register Offset definitons
* DFHv1 Register Offset definitions
* In DHFv1, DFH + GUID + CSR_START + CSR_SIZE_GROUP + PARAM_HDR + PARAM_DATA
* as common header registers
*/

View file

@ -83,7 +83,7 @@ static struct fpga_manager *of_fpga_region_get_mgr(struct device_node *np)
* done with the bridges.
*
* Return: 0 for success (even if there are no bridges specified)
* or -EBUSY if any of the bridges are in use.
* or an error code if any of the bridges are not available.
*/
static int of_fpga_region_get_bridges(struct fpga_region *region)
{
@ -130,10 +130,10 @@ static int of_fpga_region_get_bridges(struct fpga_region *region)
&region->bridge_list);
of_node_put(br);
/* If any of the bridges are in use, give up */
if (ret == -EBUSY) {
/* If any of the bridges are not available, give up */
if (ret) {
fpga_bridges_put(&region->bridge_list);
return -EBUSY;
return ret;
}
}

View file

@ -173,5 +173,5 @@ module_platform_driver(xlnx_pr_decoupler_driver);
MODULE_DESCRIPTION("Xilinx Partial Reconfiguration Decoupler");
MODULE_AUTHOR("Moritz Fischer <mdf@kernel.org>");
MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>");
MODULE_AUTHOR("Michal Simek <michal.simek@amd.com>");
MODULE_LICENSE("GPL v2");

View file

@ -652,6 +652,6 @@ static struct platform_driver zynq_fpga_driver = {
module_platform_driver(zynq_fpga_driver);
MODULE_AUTHOR("Moritz Fischer <moritz.fischer@ettus.com>");
MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>");
MODULE_AUTHOR("Michal Simek <michal.simek@amd.com>");
MODULE_DESCRIPTION("Xilinx Zynq FPGA Manager");
MODULE_LICENSE("GPL v2");

View file

@ -100,6 +100,61 @@ static int fsi_master_write(struct fsi_master *master, int link,
uint8_t slave_id, uint32_t addr, const void *val, size_t size);
static int fsi_master_break(struct fsi_master *master, int link);
/* FSI core & Linux bus type definitions */
static int fsi_bus_match(struct device *dev, const struct device_driver *drv)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
const struct fsi_driver *fsi_drv = to_fsi_drv(drv);
const struct fsi_device_id *id;
if (!fsi_drv->id_table)
return 0;
for (id = fsi_drv->id_table; id->engine_type; id++) {
if (id->engine_type != fsi_dev->engine_type)
continue;
if (id->version == FSI_VERSION_ANY ||
id->version == fsi_dev->version) {
if (drv->of_match_table) {
if (of_driver_match_device(dev, drv))
return 1;
} else {
return 1;
}
}
}
return 0;
}
static int fsi_probe(struct device *dev)
{
struct fsi_device *fsidev = to_fsi_dev(dev);
struct fsi_driver *fsidrv = to_fsi_drv(dev->driver);
if (fsidrv->probe)
return fsidrv->probe(fsidev);
else
return 0;
}
static void fsi_remove(struct device *dev)
{
struct fsi_device *fsidev = to_fsi_dev(dev);
struct fsi_driver *fsidrv = to_fsi_drv(dev->driver);
if (fsidrv->remove)
fsidrv->remove(fsidev);
}
static const struct bus_type fsi_bus_type = {
.name = "fsi",
.match = fsi_bus_match,
.probe = fsi_probe,
.remove = fsi_remove,
};
/*
* fsi_device_read() / fsi_device_write() / fsi_device_peek()
*
@ -1359,32 +1414,23 @@ void fsi_master_unregister(struct fsi_master *master)
}
EXPORT_SYMBOL_GPL(fsi_master_unregister);
/* FSI core & Linux bus type definitions */
static int fsi_bus_match(struct device *dev, const struct device_driver *drv)
static int fsi_legacy_probe(struct fsi_device *fsidev)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
const struct fsi_driver *fsi_drv = to_fsi_drv(drv);
const struct fsi_device_id *id;
struct device *dev = &fsidev->dev;
struct device_driver *driver = dev->driver;
if (!fsi_drv->id_table)
return 0;
return driver->probe(dev);
}
for (id = fsi_drv->id_table; id->engine_type; id++) {
if (id->engine_type != fsi_dev->engine_type)
continue;
if (id->version == FSI_VERSION_ANY ||
id->version == fsi_dev->version) {
if (drv->of_match_table) {
if (of_driver_match_device(dev, drv))
return 1;
} else {
return 1;
}
}
}
static void fsi_legacy_remove(struct fsi_device *fsidev)
{
struct device *dev = &fsidev->dev;
struct device_driver *driver = dev->driver;
int ret;
return 0;
ret = driver->remove(dev);
if (unlikely(ret))
dev_warn(dev, "Ignoring return value of remove callback (%pe)\n", ERR_PTR(ret));
}
int fsi_driver_register(struct fsi_driver *fsi_drv)
@ -1394,6 +1440,17 @@ int fsi_driver_register(struct fsi_driver *fsi_drv)
if (!fsi_drv->id_table)
return -EINVAL;
fsi_drv->drv.bus = &fsi_bus_type;
/*
* This driver needs updating. Note that driver_register() warns about
* this, so we're not adding another warning here.
*/
if (!fsi_drv->probe && fsi_drv->drv.probe)
fsi_drv->probe = fsi_legacy_probe;
if (!fsi_drv->remove && fsi_drv->drv.remove)
fsi_drv->remove = fsi_legacy_remove;
return driver_register(&fsi_drv->drv);
}
EXPORT_SYMBOL_GPL(fsi_driver_register);
@ -1404,12 +1461,6 @@ void fsi_driver_unregister(struct fsi_driver *fsi_drv)
}
EXPORT_SYMBOL_GPL(fsi_driver_unregister);
const struct bus_type fsi_bus_type = {
.name = "fsi",
.match = fsi_bus_match,
};
EXPORT_SYMBOL_GPL(fsi_bus_type);
static int __init fsi_init(void)
{
int rc;

View file

@ -192,9 +192,9 @@ static int hub_master_init(struct fsi_master_hub *hub)
return fsi_device_write(dev, FSI_MRESB0, &reg, sizeof(reg));
}
static int hub_master_probe(struct device *dev)
static int hub_master_probe(struct fsi_device *fsi_dev)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
struct device *dev = &fsi_dev->dev;
struct fsi_master_hub *hub;
uint32_t reg, links;
__be32 __reg;
@ -235,7 +235,7 @@ static int hub_master_probe(struct device *dev)
hub->master.send_break = hub_master_break;
hub->master.link_enable = hub_master_link_enable;
dev_set_drvdata(dev, hub);
fsi_set_drvdata(fsi_dev, hub);
hub_master_init(hub);
@ -259,9 +259,9 @@ err_release:
return rc;
}
static int hub_master_remove(struct device *dev)
static void hub_master_remove(struct fsi_device *fsi_dev)
{
struct fsi_master_hub *hub = dev_get_drvdata(dev);
struct fsi_master_hub *hub = fsi_get_drvdata(fsi_dev);
fsi_master_unregister(&hub->master);
fsi_slave_release_range(hub->upstream->slave, hub->addr, hub->size);
@ -272,8 +272,6 @@ static int hub_master_remove(struct device *dev)
* the hub
*/
put_device(&hub->master.dev);
return 0;
}
static const struct fsi_device_id hub_master_ids[] = {
@ -286,11 +284,10 @@ static const struct fsi_device_id hub_master_ids[] = {
static struct fsi_driver hub_master_driver = {
.id_table = hub_master_ids,
.probe = hub_master_probe,
.remove = hub_master_remove,
.drv = {
.name = "fsi-master-hub",
.bus = &fsi_bus_type,
.probe = hub_master_probe,
.remove = hub_master_remove,
}
};

View file

@ -1022,9 +1022,9 @@ static void sbefifo_free(struct device *dev)
* Probe/remove
*/
static int sbefifo_probe(struct device *dev)
static int sbefifo_probe(struct fsi_device *fsi_dev)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
struct device *dev = &fsi_dev->dev;
struct sbefifo *sbefifo;
struct device_node *np;
struct platform_device *child;
@ -1045,7 +1045,7 @@ static int sbefifo_probe(struct device *dev)
sbefifo->magic = SBEFIFO_MAGIC;
sbefifo->fsi_dev = fsi_dev;
dev_set_drvdata(dev, sbefifo);
fsi_set_drvdata(fsi_dev, sbefifo);
mutex_init(&sbefifo->lock);
sbefifo->timeout_in_cmd_ms = SBEFIFO_TIMEOUT_IN_CMD;
sbefifo->timeout_start_rsp_ms = SBEFIFO_TIMEOUT_START_RSP;
@ -1101,9 +1101,10 @@ static int sbefifo_unregister_child(struct device *dev, void *data)
return 0;
}
static int sbefifo_remove(struct device *dev)
static void sbefifo_remove(struct fsi_device *fsi_dev)
{
struct sbefifo *sbefifo = dev_get_drvdata(dev);
struct device *dev = &fsi_dev->dev;
struct sbefifo *sbefifo = fsi_get_drvdata(fsi_dev);
dev_dbg(dev, "Removing sbefifo device...\n");
@ -1117,8 +1118,6 @@ static int sbefifo_remove(struct device *dev)
fsi_free_minor(sbefifo->dev.devt);
device_for_each_child(dev, NULL, sbefifo_unregister_child);
put_device(&sbefifo->dev);
return 0;
}
static const struct fsi_device_id sbefifo_ids[] = {
@ -1131,26 +1130,14 @@ static const struct fsi_device_id sbefifo_ids[] = {
static struct fsi_driver sbefifo_drv = {
.id_table = sbefifo_ids,
.probe = sbefifo_probe,
.remove = sbefifo_remove,
.drv = {
.name = DEVICE_NAME,
.bus = &fsi_bus_type,
.probe = sbefifo_probe,
.remove = sbefifo_remove,
}
};
static int sbefifo_init(void)
{
return fsi_driver_register(&sbefifo_drv);
}
static void sbefifo_exit(void)
{
fsi_driver_unregister(&sbefifo_drv);
}
module_init(sbefifo_init);
module_exit(sbefifo_exit);
module_fsi_driver(sbefifo_drv);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Brad Bishop <bradleyb@fuzziesquirrel.com>");
MODULE_AUTHOR("Eddie James <eajames@linux.vnet.ibm.com>");

View file

@ -527,16 +527,16 @@ static void scom_free(struct device *dev)
kfree(scom);
}
static int scom_probe(struct device *dev)
static int scom_probe(struct fsi_device *fsi_dev)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
struct device *dev = &fsi_dev->dev;
struct scom_device *scom;
int rc, didx;
scom = kzalloc(sizeof(*scom), GFP_KERNEL);
if (!scom)
return -ENOMEM;
dev_set_drvdata(dev, scom);
fsi_set_drvdata(fsi_dev, scom);
mutex_init(&scom->lock);
/* Grab a reference to the device (parent of our cdev), we'll drop it later */
@ -574,9 +574,9 @@ static int scom_probe(struct device *dev)
return rc;
}
static int scom_remove(struct device *dev)
static void scom_remove(struct fsi_device *fsi_dev)
{
struct scom_device *scom = dev_get_drvdata(dev);
struct scom_device *scom = fsi_get_drvdata(fsi_dev);
mutex_lock(&scom->lock);
scom->dead = true;
@ -584,8 +584,6 @@ static int scom_remove(struct device *dev)
cdev_device_del(&scom->cdev, &scom->dev);
fsi_free_minor(scom->dev.devt);
put_device(&scom->dev);
return 0;
}
static const struct of_device_id scom_of_ids[] = {
@ -604,26 +602,14 @@ static const struct fsi_device_id scom_ids[] = {
static struct fsi_driver scom_drv = {
.id_table = scom_ids,
.probe = scom_probe,
.remove = scom_remove,
.drv = {
.name = "scom",
.bus = &fsi_bus_type,
.of_match_table = scom_of_ids,
.probe = scom_probe,
.remove = scom_remove,
}
};
static int scom_init(void)
{
return fsi_driver_register(&scom_drv);
}
static void scom_exit(void)
{
fsi_driver_unregister(&scom_drv);
}
module_init(scom_init);
module_exit(scom_exit);
module_fsi_driver(scom_drv);
MODULE_DESCRIPTION("SCOM FSI Client device driver");
MODULE_LICENSE("GPL");

View file

@ -81,9 +81,9 @@ static const struct file_operations i2cr_scom_fops = {
.write = i2cr_scom_write,
};
static int i2cr_scom_probe(struct device *dev)
static int i2cr_scom_probe(struct fsi_device *fsi_dev)
{
struct fsi_device *fsi_dev = to_fsi_dev(dev);
struct device *dev = &fsi_dev->dev;
struct i2cr_scom *scom;
int didx;
int ret;
@ -115,14 +115,12 @@ static int i2cr_scom_probe(struct device *dev)
return ret;
}
static int i2cr_scom_remove(struct device *dev)
static void i2cr_scom_remove(struct fsi_device *fsi_dev)
{
struct i2cr_scom *scom = dev_get_drvdata(dev);
struct i2cr_scom *scom = dev_get_drvdata(&fsi_dev->dev);
cdev_device_del(&scom->cdev, &scom->dev);
fsi_free_minor(scom->dev.devt);
return 0;
}
static const struct of_device_id i2cr_scom_of_ids[] = {
@ -137,13 +135,12 @@ static const struct fsi_device_id i2cr_scom_ids[] = {
};
static struct fsi_driver i2cr_scom_driver = {
.probe = i2cr_scom_probe,
.remove = i2cr_scom_remove,
.id_table = i2cr_scom_ids,
.drv = {
.name = "i2cr_scom",
.bus = &fsi_bus_type,
.of_match_table = i2cr_scom_of_ids,
.probe = i2cr_scom_probe,
.remove = i2cr_scom_remove,
}
};

View file

@ -599,8 +599,9 @@ static int agilent_82350b_generic_attach(struct gpib_board *board,
board->status = 0;
if (agilent_82350b_allocate_private(board))
return -ENOMEM;
retval = agilent_82350b_allocate_private(board);
if (retval)
return retval;
a_priv = board->private_data;
a_priv->using_fifos = use_fifos;
tms_priv = &a_priv->tms9914_priv;

View file

@ -1316,7 +1316,7 @@ static int agilent_82357a_attach(struct gpib_board *board, const struct gpib_boa
return -ERESTARTSYS;
retval = agilent_82357a_allocate_private(board);
if (retval < 0) {
if (retval) {
mutex_unlock(&agilent_82357a_hotplug_lock);
return retval;
}

View file

@ -856,11 +856,10 @@ static int cb7210_allocate_private(struct gpib_board *board)
{
struct cb7210_priv *priv;
board->private_data = kmalloc(sizeof(struct cb7210_priv), GFP_KERNEL);
board->private_data = kzalloc(sizeof(struct cb7210_priv), GFP_KERNEL);
if (!board->private_data)
return -ENOMEM;
priv = board->private_data;
memset(priv, 0, sizeof(struct cb7210_priv));
init_nec7210_private(&priv->nec7210_priv);
return 0;
}
@ -876,11 +875,13 @@ static int cb7210_generic_attach(struct gpib_board *board)
{
struct cb7210_priv *cb_priv;
struct nec7210_priv *nec_priv;
int retval;
board->status = 0;
if (cb7210_allocate_private(board))
return -ENOMEM;
retval = cb7210_allocate_private(board);
if (retval)
return retval;
cb_priv = board->private_data;
nec_priv = &cb_priv->nec7210_priv;
nec_priv->read_byte = nec7210_locking_ioport_read_byte;

View file

@ -220,11 +220,10 @@ static int cec_allocate_private(struct gpib_board *board)
{
struct cec_priv *priv;
board->private_data = kmalloc(sizeof(struct cec_priv), GFP_KERNEL);
board->private_data = kzalloc(sizeof(struct cec_priv), GFP_KERNEL);
if (!board->private_data)
return -1;
return -ENOMEM;
priv = board->private_data;
memset(priv, 0, sizeof(struct cec_priv));
init_nec7210_private(&priv->nec7210_priv);
return 0;
}
@ -239,11 +238,13 @@ static int cec_generic_attach(struct gpib_board *board)
{
struct cec_priv *cec_priv;
struct nec7210_priv *nec_priv;
int retval;
board->status = 0;
if (cec_allocate_private(board))
return -ENOMEM;
retval = cec_allocate_private(board);
if (retval)
return retval;
cec_priv = board->private_data;
nec_priv = &cec_priv->nec7210_priv;
nec_priv->read_byte = nec7210_ioport_read_byte;

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