History

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

Pull char/misc and other driver subsystem updates from Greg KH: "Here is the big set of char/misc and a number of other driver subsystem updates for 6.9-rc1. Included in here are: - IIO driver updates, loads of new ones and evolution of existing ones - coresight driver updates - const cleanups for many driver subsystems - speakup driver additions - platform remove callback void cleanups - mei driver updates - mhi driver updates - cdx driver updates for MSI interrupt handling - nvmem driver updates - other smaller driver updates and cleanups, full details in the shortlog All of these have been in linux-next for a long time with no reported issue, other than a build warning for the speakup driver" The build warning hits clang and is a gcc (and C23) extension, and is fixed up in the merge. Link: https://lore.kernel.org/all/20240321134831.GA2762840@dev-arch.thelio-3990X/ * tag 'char-misc-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (279 commits) binder: remove redundant variable page_addr uio_dmem_genirq: UIO_MEM_DMA_COHERENT conversion uio_pruss: UIO_MEM_DMA_COHERENT conversion cnic,bnx2,bnx2x: use UIO_MEM_DMA_COHERENT uio: introduce UIO_MEM_DMA_COHERENT type cdx: add MSI support for CDX bus pps: use cflags-y instead of EXTRA_CFLAGS speakup: Add /dev/synthu device speakup: Fix 8bit characters from direct synth parport: sunbpp: Convert to platform remove callback returning void parport: amiga: Convert to platform remove callback returning void char: xillybus: Convert to platform remove callback returning void vmw_balloon: change maintainership MAINTAINERS: change the maintainer for hpilo driver char: xilinx_hwicap: Fix NULL vs IS_ERR() bug hpet: remove hpets::hp_clocksource platform: goldfish: move the separate 'default' propery for CONFIG_GOLDFISH char: xilinx_hwicap: drop casting to void in dev_set_drvdata greybus: move is_gb_* functions out of greybus.h greybus: Remove usage of the deprecated ida_simple_xx() API ...

Linus Torvalds committed 2 years ago

Commit bb41fe32 parents 0a59b3f 367b356305 files · +15165 −4492Browse files

Unified · Split

305 files
  1. .mailmap +2 −0
  2. Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm +87 −0
  3. Documentation/ABI/testing/sysfs-bus-iio-adc-pac1934 +9 −0
  4. Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml +37 −3
  5. Documentation/devicetree/bindings/iio/adc/adc.yaml +0 −1
  6. Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml +4 −0
  7. Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml +5 −3
  8. Documentation/devicetree/bindings/iio/adc/microchip,pac1934.yaml +120 −0
  9. Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml +1 −3
  10. Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml +0 −1
  11. Documentation/devicetree/bindings/iio/adc/richtek,rtq6056.yaml +8 −1
  12. Documentation/devicetree/bindings/iio/adc/ti,ads1298.yaml +80 −0
  13. Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml +11 −0
  14. Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml +44 −3
  15. Documentation/devicetree/bindings/iio/frequency/adi,admfm2000.yaml +127 −0
  16. Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml +7 −1
  17. Documentation/devicetree/bindings/iio/humidity/ti,hdc2010.yaml +3 −0
  18. Documentation/devicetree/bindings/iio/humidity/ti,hdc3020.yaml +3 −0
  19. Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml +3 −1
  20. Documentation/devicetree/bindings/iio/light/ams,as73211.yaml +5 −2
  21. Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml +1 −0
  22. Documentation/devicetree/bindings/iio/magnetometer/voltafield,af8133j.yaml +60 −0
  23. Documentation/devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml +3 −0
  24. Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml +77 −21
  25. Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml +8 −0
  26. Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml +3 −0
  27. Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml +1 −1
  28. Documentation/devicetree/bindings/interconnect/qcom,sm7150-rpmh.yaml +84 −0
  29. Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml +10 −12
  30. Documentation/devicetree/bindings/nvmem/nvmem-provider.yaml +18 −0
  31. Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt +0 −46
  32. Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml +42 −0
  33. Documentation/devicetree/bindings/vendor-prefixes.yaml +2 −0
  34. Documentation/iio/adis16475.rst +407 −0
  35. Documentation/iio/iio_devbuf.rst +152 −0
  36. Documentation/iio/index.rst +8 −1
  37. MAINTAINERS +44 −5
  38. arch/x86/Kconfig +0 −4
  39. drivers/accessibility/speakup/devsynth.c +134 −15
  40. drivers/accessibility/speakup/synth.c +3 −1
  41. drivers/android/binder_alloc.c +0 −2
  42. drivers/bus/mhi/common.h +19 −19
  43. drivers/bus/mhi/ep/main.c +4 −3
  44. drivers/bus/mhi/host/boot.c +1 −10
  45. drivers/bus/mhi/host/init.c +43 −48
  46. drivers/bus/mhi/host/internal.h +47 −9
  47. drivers/bus/mhi/host/main.c +9 −10
  48. drivers/bus/mhi/host/pci_generic.c +1 −1
  49. drivers/bus/mhi/host/pm.c +21 −6
  50. drivers/bus/mhi/host/trace.h +282 −0
  51. drivers/cdx/Makefile +4 −0
  52. drivers/cdx/cdx.c +20 −0
  53. drivers/cdx/cdx.h +12 −0
  54. drivers/cdx/cdx_msi.c +192 −0
  55. drivers/cdx/controller/Kconfig +1 −0
  56. drivers/cdx/controller/cdx_controller.c +25 −0
  57. drivers/cdx/controller/mc_cdx_pcol.h +64 −0
  58. drivers/cdx/controller/mcdi_functions.c +31 −2
  59. drivers/cdx/controller/mcdi_functions.h +33 −0
  60. drivers/char/hpet.c +0 −1
  61. drivers/char/xilinx_hwicap/xilinx_hwicap.c +3 −3
  62. drivers/char/xillybus/xillybus_of.c +2 −4
  63. drivers/comedi/drivers/das08.c +0 −1
  64. drivers/dio/dio-driver.c +1 −1
  65. drivers/firmware/xilinx/zynqmp.c +25 −0
  66. drivers/fpga/dfl.c +1 −1
  67. drivers/fpga/fpga-bridge.c +4 −4
  68. drivers/greybus/bundle.c +1 −1
  69. drivers/greybus/control.c +1 −1
  70. drivers/greybus/core.c +31 −1
  71. drivers/greybus/es2.c +4 −4
  72. drivers/greybus/hd.c +9 −9
  73. drivers/greybus/interface.c +5 −6
  74. drivers/greybus/module.c +1 −1
  75. drivers/greybus/svc.c +1 −1
  76. drivers/hwtracing/coresight/Makefile +20 −0
  77. drivers/hwtracing/coresight/coresight-cfg-afdo.c +1 −0
  78. drivers/hwtracing/coresight/coresight-core.c +29 −467
  79. drivers/hwtracing/coresight/coresight-cti-core.c +1 −1
  80. drivers/hwtracing/coresight/coresight-etb10.c +15 −16
  81. drivers/hwtracing/coresight/coresight-etm-perf.c +1 −1
  82. drivers/hwtracing/coresight/coresight-etm.h +0 −2
  83. drivers/hwtracing/coresight/coresight-etm3x-core.c +12 −15
  84. drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +2 −2
  85. drivers/hwtracing/coresight/coresight-etm4x-core.c +17 −21
  86. drivers/hwtracing/coresight/coresight-etm4x.h +0 −1
  87. drivers/hwtracing/coresight/coresight-funnel.c +2 −2
  88. drivers/hwtracing/coresight/coresight-priv.h +4 −5
  89. drivers/hwtracing/coresight/coresight-replicator.c +1 −1
  90. drivers/hwtracing/coresight/coresight-stm.c +14 −18
  91. drivers/hwtracing/coresight/coresight-sysfs.c +391 −0
  92. drivers/hwtracing/coresight/coresight-tmc-core.c +2 −2
  93. drivers/hwtracing/coresight/coresight-tmc-etf.c +24 −22
  94. drivers/hwtracing/coresight/coresight-tmc-etr.c +17 −16
  95. drivers/hwtracing/coresight/coresight-tmc.h +0 −2
  96. drivers/hwtracing/coresight/coresight-tpda.c +86 −59
  97. drivers/hwtracing/coresight/coresight-tpda.h +6 −0
  98. drivers/hwtracing/coresight/coresight-tpdm.c +414 −43
  99. drivers/hwtracing/coresight/coresight-tpdm.h +114 −0
  100. drivers/hwtracing/coresight/coresight-tpiu.c +13 −3
  101. drivers/hwtracing/coresight/ultrasoc-smb.c +13 −11
  102. drivers/hwtracing/coresight/ultrasoc-smb.h +0 −2
  103. drivers/hwtracing/ptt/hisi_ptt.c +3 −3
  104. drivers/iio/Kconfig +9 −0
  105. drivers/iio/Makefile +1 −0
  106. drivers/iio/accel/Kconfig +6 −2
  107. drivers/iio/accel/Makefile +1 −0
  108. drivers/iio/accel/adxl367.c +118 −179
  109. drivers/iio/accel/adxl372_spi.c +1 −1
  110. drivers/iio/accel/bma180.c +1 −1
  111. drivers/iio/accel/bmc150-accel-i2c.c +14 −1
  112. drivers/iio/accel/bmc150-accel-spi.c +1 −2
  113. drivers/iio/accel/bmi088-accel-i2c.c +70 −0
  114. drivers/iio/accel/da280.c +26 −40
  115. drivers/iio/accel/kxcjk-1013.c +101 −19
  116. drivers/iio/accel/kxsd9-spi.c +1 −1
  117. drivers/iio/accel/mma9551.c +2 −2
  118. drivers/iio/accel/mma9553.c +2 −2
  119. drivers/iio/accel/mxc4005.c +3 −2
  120. drivers/iio/accel/mxc6255.c +2 −2
  121. drivers/iio/accel/st_accel_i2c.c +1 −4
  122. drivers/iio/accel/stk8ba50.c +2 −2
  123. drivers/iio/adc/Kconfig +24 −2
  124. drivers/iio/adc/Makefile +2 −0
  125. drivers/iio/adc/ad4130.c +52 −79
  126. drivers/iio/adc/ad7091r-base.c +8 −17
  127. drivers/iio/adc/ad9467.c +177 −90
  128. drivers/iio/adc/ad_sigma_delta.c +6 −1
  129. drivers/iio/adc/adi-axi-adc.c +96 −289
  130. drivers/iio/adc/max1363.c +79 −92
  131. drivers/iio/adc/mcp320x.c +9 −20
  132. drivers/iio/adc/pac1934.c +1636 −0
  133. drivers/iio/adc/qcom-pm8xxx-xoadc.c +0 −1
  134. drivers/iio/adc/rockchip_saradc.c +6 −11
  135. drivers/iio/adc/rtq6056.c +255 −20
  136. drivers/iio/adc/ti-adc108s102.c +1 −3
  137. drivers/iio/adc/ti-ads1015.c +1 −1
  138. drivers/iio/adc/ti-ads1298.c +771 −0
  139. drivers/iio/adc/ti-ads8688.c +1 −1
  140. drivers/iio/amplifiers/hmc425a.c +216 −58
  141. drivers/iio/buffer/industrialio-buffer-dmaengine.c +6 −5
  142. drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +1 −1
  143. drivers/iio/dac/mcp4821.c +1 −1
  144. drivers/iio/dummy/iio_dummy_evgen.c +0 −2
  145. drivers/iio/dummy/iio_simple_dummy.c +89 −96
  146. drivers/iio/frequency/Kconfig +10 −0
  147. drivers/iio/frequency/Makefile +1 −0
  148. drivers/iio/frequency/admfm2000.c +282 −0
  149. drivers/iio/gyro/bmg160_i2c.c +2 −2
  150. drivers/iio/health/afe4403.c +24 −41
  151. drivers/iio/health/afe4404.c +24 −41
  152. drivers/iio/humidity/hdc3020.c +309 −136
  153. drivers/iio/humidity/hts221_i2c.c +2 −2
  154. drivers/iio/imu/adis16475.c +1 −7
  155. drivers/iio/imu/adis16480.c +1 −8
  156. drivers/iio/imu/bmi160/bmi160_i2c.c +9 −0
  157. drivers/iio/imu/bmi323/bmi323_core.c +31 −47
  158. drivers/iio/imu/bmi323/bmi323_i2c.c +21 −0
  159. drivers/iio/imu/fxos8700_i2c.c +1 −2
  160. drivers/iio/imu/fxos8700_spi.c +1 −2
  161. drivers/iio/imu/kmx61.c +1 −1
  162. drivers/iio/imu/st_lsm6dsx/Kconfig +26 −5
  163. drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +2 −0
  164. drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +25 −3
  165. drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +27 −6
  166. drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c +5 −0
  167. drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c +5 −0
  168. drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h +4 −1
  169. drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c +9 −12
  170. drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c +4 −2
  171. drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c +3 −1
  172. drivers/iio/industrialio-backend.c +418 −0
  173. drivers/iio/industrialio-core.c +2 −4
  174. drivers/iio/industrialio-gts-helper.c +1 −14
  175. drivers/iio/light/Kconfig +3 −2
  176. drivers/iio/light/al3010.c +1 −1
  177. drivers/iio/light/al3320a.c +0 −1
  178. drivers/iio/light/as73211.c +115 −27
  179. drivers/iio/light/hid-sensor-als.c +104 −18
  180. drivers/iio/light/jsa1212.c +2 −2
  181. drivers/iio/light/ltr501.c +2 −1
  182. drivers/iio/light/max44000.c +2 −4
  183. drivers/iio/light/rpr0521.c +2 −2
  184. drivers/iio/light/stk3310.c +2 −2
  185. drivers/iio/light/us5182d.c +2 −2
  186. drivers/iio/light/vcnl4000.c +35 −1
  187. drivers/iio/light/vl6180.c +0 −1
  188. drivers/iio/magnetometer/Kconfig +12 −0
  189. drivers/iio/magnetometer/Makefile +1 −0
  190. drivers/iio/magnetometer/af8133j.c +528 −0
  191. drivers/iio/magnetometer/bmc150_magn_i2c.c +1 −2
  192. drivers/iio/magnetometer/bmc150_magn_spi.c +1 −2
  193. drivers/iio/magnetometer/mmc35240.c +2 −2
  194. drivers/iio/potentiometer/max5487.c +2 −2
  195. drivers/iio/pressure/Kconfig +15 −1
  196. drivers/iio/pressure/Makefile +2 −0
  197. drivers/iio/pressure/hp206c.c +2 −4
  198. drivers/iio/pressure/hsc030pa.c +48 −1
  199. drivers/iio/pressure/hsc030pa.h +7 −0
  200. drivers/iio/pressure/hsc030pa_i2c.c +7 −2
  201. drivers/iio/pressure/hsc030pa_spi.c +6 −1
  202. drivers/iio/pressure/mprls0025pa.c +159 −154
  203. drivers/iio/pressure/mprls0025pa.h +102 −0
  204. drivers/iio/pressure/mprls0025pa_i2c.c +100 −0
  205. drivers/iio/pressure/mprls0025pa_spi.c +92 −0
  206. drivers/iio/pressure/st_pressure_i2c.c +1 −4
  207. drivers/iio/proximity/isl29501.c +1 −2
  208. drivers/iio/proximity/sx9310.c +39 −75
  209. drivers/iio/proximity/sx9324.c +79 −99
  210. drivers/iio/proximity/sx9360.c +39 −76
  211. drivers/iio/temperature/ltc2983.c +18 −10
  212. drivers/iio/temperature/tmp117.c +9 −0
  213. drivers/iio/test/Kconfig +14 −0
  214. drivers/iio/test/Makefile +1 −0
  215. drivers/iio/test/iio-test-gts.c +513 −0
  216. drivers/interconnect/core.c +2 −2
  217. drivers/interconnect/qcom/Kconfig +18 −0
  218. drivers/interconnect/qcom/Makefile +4 −0
  219. drivers/interconnect/qcom/icc-common.c +2 −1
  220. drivers/interconnect/qcom/icc-common.h +2 −1
  221. drivers/interconnect/qcom/msm8909.c +1329 −0
  222. drivers/interconnect/qcom/sa8775p.c +28 −28
  223. drivers/interconnect/qcom/sm6115.c +6 −6
  224. drivers/interconnect/qcom/sm7150.c +1754 −0
  225. drivers/interconnect/qcom/sm7150.h +140 −0
  226. drivers/interconnect/qcom/sm8250.c +1 −1
  227. drivers/interconnect/qcom/sm8550.c +0 −574
  228. drivers/interconnect/qcom/sm8550.h +122 −162
  229. drivers/interconnect/qcom/x1e80100.c +6 −321
  230. drivers/interconnect/samsung/exynos.c +1 −1
  231. drivers/ipack/ipack.c +1 −1
  232. drivers/mcb/mcb-core.c +2 −2
  233. drivers/memory/tegra/mc.c +1 −1
  234. drivers/memory/tegra/tegra124-emc.c +1 −1
  235. drivers/memory/tegra/tegra124.c +1 −1
  236. drivers/memory/tegra/tegra186-emc.c +1 −1
  237. drivers/memory/tegra/tegra20-emc.c +1 −1
  238. drivers/memory/tegra/tegra20.c +1 −1
  239. drivers/memory/tegra/tegra30-emc.c +1 −1
  240. drivers/memory/tegra/tegra30.c +1 −1
  241. drivers/misc/atmel-ssc.c +2 −4
  242. drivers/misc/cxl/of.c +2 −3
  243. drivers/misc/eeprom/eeprom_93xx46.c +0 −1
  244. drivers/misc/eeprom/idt_89hpesx.c +3 −3
  245. drivers/misc/fastrpc.c +2 −4
  246. drivers/misc/hi6421v600-irq.c +0 −1
  247. drivers/misc/hisi_hikey_usb.c +2 −5
  248. drivers/misc/hpilo.c +4 −4
  249. drivers/misc/mei/gsc-me.c +5 −17
  250. drivers/misc/mei/hdcp/Kconfig +1 −1
  251. drivers/misc/mei/hdcp/mei_hdcp.c +12 −2
  252. drivers/misc/mei/pci-me.c +6 −32
  253. drivers/misc/mei/pci-txe.c +6 −34
  254. drivers/misc/mei/platform-vsc.c +2 −4
  255. drivers/misc/mei/pxp/Kconfig +1 −1
  256. drivers/misc/mei/pxp/mei_pxp.c +12 −2
  257. drivers/misc/mei/vsc-tp.c +18 −15
  258. drivers/misc/open-dice.c +2 −3
  259. drivers/misc/sram.c +2 −4
  260. drivers/misc/ti-st/st_kim.c +2 −3
  261. drivers/misc/tifm_core.c +1 −1
  262. drivers/misc/vcpu_stall_detector.c +2 −4
  263. drivers/misc/xilinx_sdfec.c +2 −3
  264. drivers/misc/xilinx_tmr_inject.c +2 −3
  265. drivers/most/core.c +1 −1
  266. drivers/net/ethernet/broadcom/bnx2.c +1 −0
  267. drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +2 −0
  268. drivers/net/ethernet/broadcom/cnic.c +17 −8
  269. drivers/net/ethernet/broadcom/cnic.h +1 −0
  270. drivers/net/ethernet/broadcom/cnic_if.h +1 −0
  271. drivers/nvmem/core.c +5 −0
  272. drivers/nvmem/layouts.c +1 −1
  273. drivers/nvmem/meson-efuse.c +3 −22
  274. drivers/nvmem/mtk-efuse.c +19 −1
  275. drivers/nvmem/zynqmp_nvmem.c +184 −31
  276. drivers/of/property.c +2 −0
  277. drivers/parport/parport_amiga.c +2 −3
  278. drivers/parport/parport_sunbpp.c +2 −4
  279. drivers/platform/goldfish/Kconfig +1 −0
  280. drivers/pps/generators/Makefile +1 −3
  281. drivers/siox/siox-core.c +3 −3
  282. drivers/slimbus/core.c +3 −3
  283. drivers/slimbus/qcom-ngd-ctrl.c +4 −4
  284. drivers/uio/uio.c +47 −0
  285. drivers/uio/uio_dmem_genirq.c +8 −14
  286. drivers/uio/uio_pruss.c +4 −2
  287. include/dt-bindings/interconnect/qcom,msm8909.h +93 −0
  288. include/dt-bindings/interconnect/qcom,sm7150-rpmh.h +150 −0
  289. include/dt-bindings/interconnect/qcom,x1e80100-rpmh.h +0 −24
  290. include/linux/cdx/cdx_bus.h +52 −1
  291. include/linux/coresight.h +57 −91
  292. include/linux/dio.h +1 −1
  293. include/linux/firmware/xlnx-zynqmp.h +8 −0
  294. include/linux/greybus.h +8 −38
  295. include/linux/hid-sensor-ids.h +4 −0
  296. include/linux/iio/adc/adi-axi-adc.h +0 −68
  297. include/linux/iio/backend.h +72 −0
  298. include/linux/iio/buffer-dmaengine.h +3 −0
  299. include/linux/iio/iio.h +29 −1
  300. include/linux/interconnect-provider.h +6 −5
  301. include/linux/mhi.h +0 −19
  302. include/linux/slimbus.h +1 −1
  303. include/linux/uio_driver.h +13 −0
  304. include/soc/tegra/mc.h +4 −3
  305. tools/iio/iio_utils.c +1 −1
.mailmap+2−0
@@ -439,6 +439,8 @@ Mukesh Ojha <quic_mojha@quicinc.com> <mojha@codeaurora.org> · 438 unmodified lines
439Muna Sinada <quic_msinada@quicinc.com> <msinada@codeaurora.org>439Muna Sinada <quic_msinada@quicinc.com> <msinada@codeaurora.org>
440Murali Nalajala <quic_mnalajal@quicinc.com> <mnalajal@codeaurora.org>440Murali Nalajala <quic_mnalajal@quicinc.com> <mnalajal@codeaurora.org>
441Mythri P K <mythripk@ti.com>441Mythri P K <mythripk@ti.com>
442Nadav Amit <nadav.amit@gmail.com> <namit@vmware.com>
443Nadav Amit <nadav.amit@gmail.com> <namit@cs.technion.ac.il>
442Nadia Yvette Chambers <nyc@holomorphy.com> William Lee Irwin III <wli@holomorphy.com>444Nadia Yvette Chambers <nyc@holomorphy.com> William Lee Irwin III <wli@holomorphy.com>
443Naoya Horiguchi <naoya.horiguchi@nec.com> <n-horiguchi@ah.jp.nec.com>445Naoya Horiguchi <naoya.horiguchi@nec.com> <n-horiguchi@ah.jp.nec.com>
444Nathan Chancellor <nathan@kernel.org> <natechancellor@gmail.com>446Nathan Chancellor <nathan@kernel.org> <natechancellor@gmail.com>
Documentation/ABI/testing/sysfs-bus-coresight-devices-tpdm+87−0
@@ -170,3 +170,90 @@ Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_t · 169 unmodified lines
170Description:170Description:
171 (RW) Set/Get the MSR(mux select register) for the DSB subunit171 (RW) Set/Get the MSR(mux select register) for the DSB subunit
172 TPDM.172 TPDM.
173
174What: /sys/bus/coresight/devices/<tpdm-name>/cmb_mode
175Date: January 2024
176KernelVersion 6.9
177Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
178Description: (Write) Set the data collection mode of CMB tpdm. Continuous
179 change creates CMB data set elements on every CMBCLK edge.
180 Trace-on-change creates CMB data set elements only when a new
181 data set element differs in value from the previous element
182 in a CMB data set.
183
184 Accepts only one of the 2 values - 0 or 1.
185 0 : Continuous CMB collection mode.
186 1 : Trace-on-change CMB collection mode.
187
188What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpr[0:1]
189Date: January 2024
190KernelVersion 6.9
191Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
192Description:
193 (RW) Set/Get the value of the trigger pattern for the CMB
194 subunit TPDM.
195
196What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_patt/xpmr[0:1]
197Date: January 2024
198KernelVersion 6.9
199Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
200Description:
201 (RW) Set/Get the mask of the trigger pattern for the CMB
202 subunit TPDM.
203
204What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpr[0:1]
205Date: January 2024
206KernelVersion 6.9
207Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
208Description:
209 (RW) Set/Get the value of the pattern for the CMB subunit TPDM.
210
211What: /sys/bus/coresight/devices/<tpdm-name>/dsb_patt/tpmr[0:1]
212Date: January 2024
213KernelVersion 6.9
214Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
215Description:
216 (RW) Set/Get the mask of the pattern for the CMB subunit TPDM.
217
218What: /sys/bus/coresight/devices/<tpdm-name>/cmb_patt/enable_ts
219Date: January 2024
220KernelVersion 6.9
221Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
222Description:
223 (Write) Set the pattern timestamp of CMB tpdm. Read
224 the pattern timestamp of CMB tpdm.
225
226 Accepts only one of the 2 values - 0 or 1.
227 0 : Disable CMB pattern timestamp.
228 1 : Enable CMB pattern timestamp.
229
230What: /sys/bus/coresight/devices/<tpdm-name>/cmb_trig_ts
231Date: January 2024
232KernelVersion 6.9
233Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
234Description:
235 (RW) Set/Get the trigger timestamp of the CMB for tpdm.
236
237 Accepts only one of the 2 values - 0 or 1.
238 0 : Set the CMB trigger type to false
239 1 : Set the CMB trigger type to true
240
241What: /sys/bus/coresight/devices/<tpdm-name>/cmb_ts_all
242Date: January 2024
243KernelVersion 6.9
244Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
245Description:
246 (RW) Read or write the status of timestamp upon all interface.
247 Only value 0 and 1 can be written to this node. Set this node to 1 to requeset
248 timestamp to all trace packet.
249 Accepts only one of the 2 values - 0 or 1.
250 0 : Disable the timestamp of all trace packets.
251 1 : Enable the timestamp of all trace packets.
252
253What: /sys/bus/coresight/devices/<tpdm-name>/cmb_msr/msr[0:31]
254Date: January 2024
255KernelVersion 6.9
256Contact: Jinlong Mao (QUIC) <quic_jinlmao@quicinc.com>, Tao Zhang (QUIC) <quic_taozha@quicinc.com>
257Description:
258 (RW) Set/Get the MSR(mux select register) for the CMB subunit
259 TPDM.
Documentation/ABI/testing/sysfs-bus-iio-adc-pac1934+9−0
@@ -0,0 +1,9 @@
1What: /sys/bus/iio/devices/iio:deviceX/in_shunt_resistorY
2KernelVersion: 6.7
3Contact: linux-iio@vger.kernel.org
4Description:
5 The value of the shunt resistor may be known only at runtime
6 and set by a client application. This attribute allows to
7 set its value in micro-ohms. X is the IIO index of the device.
8 Y is the channel number. The value is used to calculate
9 current, power and accumulated energy.
Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml+37−3
@@ -44,14 +44,21 @@ properties: · 43 unmodified lines
44 minItems: 144 minItems: 1
45 maxItems: 245 maxItems: 2
46 46
47 qcom,dsb-element-size:47 qcom,dsb-element-bits:
48 description:48 description:
49 Specifies the DSB(Discrete Single Bit) element size supported by49 Specifies the DSB(Discrete Single Bit) element size supported by
50 the monitor. The associated aggregator will read this size before it50 the monitor. The associated aggregator will read this size before it
51 is enabled. DSB element size currently only supports 32-bit and 64-bit.51 is enabled. DSB element size currently only supports 32-bit and 64-bit.
52 $ref: /schemas/types.yaml#/definitions/uint8
53 enum: [32, 64]52 enum: [32, 64]
54 53
54 qcom,cmb-element-bits:
55 description:
56 Specifies the CMB(Continuous Multi-Bit) element size supported by
57 the monitor. The associated aggregator will read this size before it
58 is enabled. CMB element size currently only supports 8-bit, 32-bit
59 and 64-bit.
60 enum: [8, 32, 64]
61
55 qcom,dsb-msrs-num:62 qcom,dsb-msrs-num:
56 description:63 description:
57 Specifies the number of DSB(Discrete Single Bit) MSR(mux select register)64 Specifies the number of DSB(Discrete Single Bit) MSR(mux select register)
@@ -61,6 +68,15 @@ properties: · 3 unmodified lines
61 minimum: 068 minimum: 0
62 maximum: 3269 maximum: 32
63 70
71 qcom,cmb-msrs-num:
72 description:
73 Specifies the number of CMB MSR(mux select register) registers supported
74 by the monitor. If this property is not configured or set to 0, it means
75 this TPDM doesn't support CMB MSR.
76 $ref: /schemas/types.yaml#/definitions/uint32
77 minimum: 0
78 maximum: 32
79
64 clocks:80 clocks:
65 maxItems: 181 maxItems: 1
66 82
@@ -94,7 +110,7 @@ examples: · 27 unmodified lines
94 compatible = "qcom,coresight-tpdm", "arm,primecell";110 compatible = "qcom,coresight-tpdm", "arm,primecell";
95 reg = <0x0684c000 0x1000>;111 reg = <0x0684c000 0x1000>;
96 112
97 qcom,dsb-element-size = /bits/ 8 <32>;113 qcom,dsb-element-bits = <32>;
98 qcom,dsb-msrs-num = <16>;114 qcom,dsb-msrs-num = <16>;
99 115
100 clocks = <&aoss_qmp>;116 clocks = <&aoss_qmp>;
@@ -110,4 +126,22 @@ examples: · 9 unmodified lines
110 };126 };
111 };127 };
112 128
129 tpdm@6c29000 {
130 compatible = "qcom,coresight-tpdm", "arm,primecell";
131 reg = <0x06c29000 0x1000>;
132
133 qcom,cmb-element-bits = <64>;
134 qcom,cmb-msrs-num = <32>;
135
136 clocks = <&aoss_qmp>;
137 clock-names = "apb_pclk";
138
139 out-ports {
140 port {
141 tpdm_ipcc_out_funnel_center: endpoint {
142 remote-endpoint = <&funnel_center_in_tpdm_ipcc>;
143 };
144 };
145 };
146 };
113...147...
Documentation/devicetree/bindings/iio/adc/adc.yaml+0−1
@@ -22,7 +22,6 @@ properties: · 21 unmodified lines
22 maxItems: 122 maxItems: 1
23 23
24 label:24 label:
25 $ref: /schemas/types.yaml#/definitions/string
26 description: Unique name to identify which channel this is.25 description: Unique name to identify which channel this is.
27 26
28 bipolar:27 bipolar:
Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml+4−0
@@ -44,6 +44,9 @@ properties: · 43 unmodified lines
44 Pin that controls the powerdown mode of the device.44 Pin that controls the powerdown mode of the device.
45 maxItems: 145 maxItems: 1
46 46
47 io-backends:
48 maxItems: 1
49
47 reset-gpios:50 reset-gpios:
48 description:51 description:
49 Reset pin for the device.52 Reset pin for the device.
@@ -68,6 +71,7 @@ examples: · 18 unmodified lines
68 reg = <0>;71 reg = <0>;
69 clocks = <&adc_clk>;72 clocks = <&adc_clk>;
70 clock-names = "adc-clk";73 clock-names = "adc-clk";
74 io-backends = <&iio_backend>;
71 };75 };
72 };76 };
73...77...
Documentation/devicetree/bindings/iio/adc/adi,axi-adc.yaml+5−3
@@ -39,12 +39,15 @@ properties: · 38 unmodified lines
39 $ref: /schemas/types.yaml#/definitions/phandle39 $ref: /schemas/types.yaml#/definitions/phandle
40 description:40 description:
41 A reference to a the actual ADC to which this FPGA ADC interfaces to.41 A reference to a the actual ADC to which this FPGA ADC interfaces to.
42 deprecated: true
43
44 '#io-backend-cells':
45 const: 0
42 46
43required:47required:
44 - compatible48 - compatible
45 - dmas49 - dmas
46 - reg50 - reg
47 - adi,adc-dev
48 51
49additionalProperties: false52additionalProperties: false
50 53
@@ -55,7 +58,6 @@ examples: · 4 unmodified lines
55 reg = <0x44a00000 0x10000>;58 reg = <0x44a00000 0x10000>;
56 dmas = <&rx_dma 0>;59 dmas = <&rx_dma 0>;
57 dma-names = "rx";60 dma-names = "rx";
58 61 #io-backend-cells = <0>;
59 adi,adc-dev = <&spi_adc>;
60 };62 };
61...63...
Documentation/devicetree/bindings/iio/adc/microchip,pac1934.yaml+120−0
@@ -0,0 +1,120 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/iio/adc/microchip,pac1934.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Microchip PAC1934 Power Monitors with Accumulator
8
9maintainers:
10 - Marius Cristea <marius.cristea@microchip.com>
11
12description: |
13 This device is part of the Microchip family of Power Monitors with
14 Accumulator.
15 The datasheet for PAC1931, PAC1932, PAC1933 and PAC1934 can be found here:
16 https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/PAC1931-Family-Data-Sheet-DS20005850E.pdf
17
18properties:
19 compatible:
20 enum:
21 - microchip,pac1931
22 - microchip,pac1932
23 - microchip,pac1933
24 - microchip,pac1934
25
26 reg:
27 maxItems: 1
28
29 "#address-cells":
30 const: 1
31
32 "#size-cells":
33 const: 0
34
35 interrupts:
36 maxItems: 1
37
38 slow-io-gpios:
39 description:
40 A GPIO used to trigger a change is sampling rate (lowering the chip power
41 consumption). If configured in SLOW mode, if this pin is forced high,
42 sampling rate is forced to eight samples/second. When it is forced low,
43 the sampling rate is 1024 samples/second unless a different sample rate
44 has been programmed.
45
46patternProperties:
47 "^channel@[1-4]+$":
48 type: object
49 $ref: adc.yaml
50 description:
51 Represents the external channels which are connected to the ADC.
52
53 properties:
54 reg:
55 items:
56 minimum: 1
57 maximum: 4
58
59 shunt-resistor-micro-ohms:
60 description:
61 Value in micro Ohms of the shunt resistor connected between
62 the SENSE+ and SENSE- inputs, across which the current is measured.
63 Value is needed to compute the scaling of the measured current.
64
65 required:
66 - reg
67 - shunt-resistor-micro-ohms
68
69 unevaluatedProperties: false
70
71required:
72 - compatible
73 - reg
74 - "#address-cells"
75 - "#size-cells"
76
77additionalProperties: false
78
79examples:
80 - |
81 i2c {
82 #address-cells = <1>;
83 #size-cells = <0>;
84
85 power-monitor@10 {
86 compatible = "microchip,pac1934";
87 reg = <0x10>;
88
89 #address-cells = <1>;
90 #size-cells = <0>;
91
92 channel@1 {
93 reg = <0x1>;
94 shunt-resistor-micro-ohms = <24900000>;
95 label = "CPU";
96 };
97
98 channel@2 {
99 reg = <0x2>;
100 shunt-resistor-micro-ohms = <49900000>;
101 label = "GPU";
102 };
103
104 channel@3 {
105 reg = <0x3>;
106 shunt-resistor-micro-ohms = <75000000>;
107 label = "MEM";
108 bipolar;
109 };
110
111 channel@4 {
112 reg = <0x4>;
113 shunt-resistor-micro-ohms = <100000000>;
114 label = "NET";
115 bipolar;
116 };
117 };
118 };
119
120...
Documentation/devicetree/bindings/iio/adc/nxp,imx93-adc.yaml+1−3
@@ -31,7 +31,6 @@ properties: · 30 unmodified lines
31 - description: normal conversion, include EOC (End of Conversion),31 - description: normal conversion, include EOC (End of Conversion),
32 ECH (End of Chain), JEOC (End of Injected Conversion) and32 ECH (End of Chain), JEOC (End of Injected Conversion) and
33 JECH (End of injected Chain).33 JECH (End of injected Chain).
34 - description: Self-testing Interrupts.
35 34
36 clocks:35 clocks:
37 maxItems: 136 maxItems: 1
@@ -70,8 +69,7 @@ examples: · 32 unmodified lines
70 reg = <0x44530000 0x10000>;69 reg = <0x44530000 0x10000>;
71 interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>,70 interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>,
72 <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,71 <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,
73 <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>,72 <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
74 <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
75 clocks = <&clk IMX93_CLK_ADC1_GATE>;73 clocks = <&clk IMX93_CLK_ADC1_GATE>;
76 clock-names = "ipg";74 clock-names = "ipg";
77 vref-supply = <&reg_vref_1v8>;75 vref-supply = <&reg_vref_1v8>;
Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml+0−1
@@ -75,7 +75,6 @@ patternProperties: · 74 unmodified lines
75 in the PMIC-specific files in include/dt-bindings/iio/.75 in the PMIC-specific files in include/dt-bindings/iio/.
76 76
77 label:77 label:
78 $ref: /schemas/types.yaml#/definitions/string
79 description: |78 description: |
80 ADC input of the platform as seen in the schematics.79 ADC input of the platform as seen in the schematics.
81 For thermistor inputs connected to generic AMUX or GPIO inputs80 For thermistor inputs connected to generic AMUX or GPIO inputs
Documentation/devicetree/bindings/iio/adc/richtek,rtq6056.yaml+8−1
@@ -25,7 +25,14 @@ description: | · 24 unmodified lines
25 25
26properties:26properties:
27 compatible:27 compatible:
28 const: richtek,rtq605628 oneOf:
29 - enum:
30 - richtek,rtq6056
31 - richtek,rtq6059
32 - items:
33 - enum:
34 - richtek,rtq6053
35 - const: richtek,rtq6056
29 36
30 reg:37 reg:
31 maxItems: 138 maxItems: 1
Documentation/devicetree/bindings/iio/adc/ti,ads1298.yaml+80−0
@@ -0,0 +1,80 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/iio/adc/ti,ads1298.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Texas Instruments' ads1298 medical ADC chips
8
9description: |
10 Datasheet at: https://www.ti.com/product/ADS1298
11 Bindings for this chip aren't complete.
12
13maintainers:
14 - Mike Looijmans <mike.looijmans@topic.nl>
15
16properties:
17 compatible:
18 enum:
19 - ti,ads1298
20
21 reg:
22 maxItems: 1
23
24 spi-cpha: true
25
26 reset-gpios:
27 maxItems: 1
28
29 avdd-supply:
30 description:
31 Analog power supply, voltage between AVDD and AVSS. When providing a
32 symmetric +/- 2.5V, the regulator should report 5V.
33
34 vref-supply:
35 description:
36 Optional reference voltage. If omitted, internal reference is used,
37 which is 2.4V when analog supply is below 4.4V, 4V otherwise.
38
39 clocks:
40 description: Optional 2.048 MHz external source clock on CLK pin
41 maxItems: 1
42
43 interrupts:
44 description: Interrupt on DRDY pin, triggers on falling edge
45 maxItems: 1
46
47 label: true
48
49required:
50 - compatible
51 - reg
52 - avdd-supply
53 - interrupts
54
55allOf:
56 - $ref: /schemas/spi/spi-peripheral-props.yaml#
57
58unevaluatedProperties: false
59
60examples:
61 - |
62 #include <dt-bindings/gpio/gpio.h>
63 #include <dt-bindings/interrupt-controller/irq.h>
64 spi {
65 #address-cells = <1>;
66 #size-cells = <0>;
67
68 adc@1 {
69 reg = <1>;
70 compatible = "ti,ads1298";
71 label = "ads1298-1-ecg";
72 avdd-supply = <&reg_iso_5v_a>;
73 clocks = <&clk_ads1298>;
74 interrupt-parent = <&gpio0>;
75 interrupts = <78 IRQ_TYPE_EDGE_FALLING>;
76 spi-max-frequency = <20000000>;
77 spi-cpha;
78 };
79 };
80...
Documentation/devicetree/bindings/iio/afe/voltage-divider.yaml+11−0
@@ -39,6 +39,17 @@ properties: · 38 unmodified lines
39 description: |39 description: |
40 Channel node of a voltage io-channel.40 Channel node of a voltage io-channel.
41 41
42 '#io-channel-cells':
43 description:
44 In addition to consuming the measurement services of a voltage
45 output channel, the voltage divider can act as a provider of
46 measurement services to other devices. This is particularly
47 useful in scenarios wherein an ADC has an analog frontend,
48 such as a voltage divider, and then consuming its raw value
49 isn't interesting. In this case, the voltage before the divider
50 is desired.
51 const: 1
52
42 output-ohms:53 output-ohms:
43 description:54 description:
44 Resistance Rout over which the output voltage is measured. See full-ohms.55 Resistance Rout over which the output voltage is measured. See full-ohms.
Documentation/devicetree/bindings/iio/amplifiers/adi,hmc425a.yaml+44−3
@@ -21,6 +21,8 @@ description: | · 20 unmodified lines
21 HMC540S 1 dB LSB Silicon MMIC 4-Bit Digital Positive Control Attenuator, 0.1 - 8 GHz21 HMC540S 1 dB LSB Silicon MMIC 4-Bit Digital Positive Control Attenuator, 0.1 - 8 GHz
22 https://www.analog.com/media/en/technical-documentation/data-sheets/hmc540s.pdf22 https://www.analog.com/media/en/technical-documentation/data-sheets/hmc540s.pdf
23 23
24 LTC6373 is a 3-Bit precision instrumentation amplifier with fully differential outputs
25 https://www.analog.com/media/en/technical-documentation/data-sheets/ltc6373.pdf
24 26
25properties:27properties:
26 compatible:28 compatible:
@@ -28,16 +30,55 @@ properties: · 1 unmodified line
28 - adi,adrf574030 - adi,adrf5740
29 - adi,hmc425a31 - adi,hmc425a
30 - adi,hmc540s32 - adi,hmc540s
33 - adi,ltc6373
31 34
32 vcc-supply: true35 vcc-supply: true
33 36
34 ctrl-gpios:37 ctrl-gpios:
35 description:38 description:
36 Must contain an array of 6 GPIO specifiers, referring to the GPIO pins39 Must contain an array of GPIO specifiers, referring to the GPIO pins
37 connected to the control pins V1-V6.40 connected to the control pins.
38 minItems: 641 ADRF5740 - 4 GPIO connected to D2-D5
42 HMC540S - 4 GPIO connected to V1-V4
43 HMC425A - 6 GPIO connected to V1-V6
44 LTC6373 - 3 GPIO connected to A0-A2
45 minItems: 1
39 maxItems: 646 maxItems: 6
40 47
48allOf:
49 - if:
50 properties:
51 compatible:
52 contains:
53 const: adi,hmc425a
54 then:
55 properties:
56 ctrl-gpios:
57 minItems: 6
58 maxItems: 6
59 - if:
60 properties:
61 compatible:
62 contains:
63 anyOf:
64 - const: adi,adrf5740
65 - const: adi,hmc540s
66 then:
67 properties:
68 ctrl-gpios:
69 minItems: 4
70 maxItems: 4
71 - if:
72 properties:
73 compatible:
74 contains:
75 const: adi,ltc6373
76 then:
77 properties:
78 ctrl-gpios:
79 minItems: 3
80 maxItems: 3
81
41required:82required:
42 - compatible83 - compatible
43 - ctrl-gpios84 - ctrl-gpios
Documentation/devicetree/bindings/iio/frequency/adi,admfm2000.yaml+127−0
@@ -0,0 +1,127 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2# Copyright 2024 Analog Devices Inc.
3%YAML 1.2
4---
5$id: http://devicetree.org/schemas/iio/frequency/adi,admfm2000.yaml#
6$schema: http://devicetree.org/meta-schemas/core.yaml#
7
8title: ADMFM2000 Dual Microwave Down Converter
9
10maintainers:
11 - Kim Seer Paller <kimseer.paller@analog.com>
12
13description:
14 Dual microwave down converter module with input RF and LO frequency ranges
15 from 0.5 to 32 GHz and an output IF frequency range from 0.1 to 8 GHz.
16 It consists of a LNA, mixer, IF filter, DSA, and IF amplifier for each down
17 conversion path.
18
19properties:
20 compatible:
21 enum:
22 - adi,admfm2000
23
24 '#address-cells':
25 const: 1
26
27 '#size-cells':
28 const: 0
29
30patternProperties:
31 "^channel@[0-1]$":
32 type: object
33 description: Represents a channel of the device.
34
35 additionalProperties: false
36
37 properties:
38 reg:
39 description:
40 The channel number.
41 minimum: 0
42 maximum: 1
43
44 adi,mixer-mode:
45 description:
46 Enable mixer mode for the channel. It downconverts RF between 5 GHz
47 and 32 GHz to IF between 0.5 GHz and 8 GHz. If not present, the channel
48 is in direct IF mode which bypasses the mixer and downconverts RF
49 between 2 GHz and 8 GHz to IF between 0.5 GHz and 8 GHz.
50 type: boolean
51
52 switch-gpios:
53 description: |
54 GPIOs to select the RF path for the channel. The same state of CTRL-A
55 and CTRL-B GPIOs is not permitted.
56 CTRL-A CTRL-B CH1 Status CH2 Status
57 1 0 Direct IF mode Mixer mode
58 0 1 Mixer mode Direct IF mode
59
60 items:
61 - description: CTRL-A GPIO
62 - description: CTRL-B GPIO
63
64 attenuation-gpios:
65 description: |
66 Choice of attenuation:
67 DSA-V4 DSA-V3 DSA-V2 DSA-V1 DSA-V0
68 1 1 1 1 1 0 dB
69 1 1 1 1 0 -1 dB
70 1 1 1 0 1 -2 dB
71 1 1 0 1 1 -4 dB
72 1 0 1 1 1 -8 dB
73 0 1 1 1 1 -16 dB
74 0 0 0 0 0 -31 dB
75
76 items:
77 - description: DSA-V0 GPIO
78 - description: DSA-V1 GPIO
79 - description: DSA-V2 GPIO
80 - description: DSA-V3 GPIO
81 - description: DSA-V4 GPIO
82
83 required:
84 - reg
85 - switch-gpios
86 - attenuation-gpios
87
88required:
89 - compatible
90
91additionalProperties: false
92
93examples:
94 - |
95 #include <dt-bindings/gpio/gpio.h>
96 converter {
97 compatible = "adi,admfm2000";
98
99 #address-cells = <1>;
100 #size-cells = <0>;
101
102 channel@0 {
103 reg = <0>;
104 switch-gpios = <&gpio 1 GPIO_ACTIVE_LOW>,
105 <&gpio 2 GPIO_ACTIVE_HIGH>;
106
107 attenuation-gpios = <&gpio 17 GPIO_ACTIVE_LOW>,
108 <&gpio 22 GPIO_ACTIVE_LOW>,
109 <&gpio 23 GPIO_ACTIVE_LOW>,
110 <&gpio 24 GPIO_ACTIVE_LOW>,
111 <&gpio 25 GPIO_ACTIVE_LOW>;
112 };
113
114 channel@1 {
115 reg = <1>;
116 adi,mixer-mode;
117 switch-gpios = <&gpio 3 GPIO_ACTIVE_LOW>,
118 <&gpio 4 GPIO_ACTIVE_HIGH>;
119
120 attenuation-gpios = <&gpio 0 GPIO_ACTIVE_LOW>,
121 <&gpio 5 GPIO_ACTIVE_LOW>,
122 <&gpio 6 GPIO_ACTIVE_LOW>,
123 <&gpio 16 GPIO_ACTIVE_LOW>,
124 <&gpio 26 GPIO_ACTIVE_LOW>;
125 };
126 };
127...
Documentation/devicetree/bindings/iio/gyroscope/bosch,bmg160.yaml+7−1
@@ -22,6 +22,9 @@ properties: · 21 unmodified lines
22 vdd-supply: true22 vdd-supply: true
23 vddio-supply: true23 vddio-supply: true
24 24
25 spi-max-frequency:
26 maximum: 10000000
27
25 interrupts:28 interrupts:
26 minItems: 129 minItems: 1
27 maxItems: 230 maxItems: 2
@@ -33,7 +36,10 @@ required: · 5 unmodified lines
33 - compatible36 - compatible
34 - reg37 - reg
35 38
36additionalProperties: false39allOf:
40 - $ref: /schemas/spi/spi-peripheral-props.yaml#
41
42unevaluatedProperties: false
37 43
38examples:44examples:
39 - |45 - |
Documentation/devicetree/bindings/iio/humidity/ti,hdc2010.yaml+3−0
@@ -27,6 +27,9 @@ properties: · 26 unmodified lines
27 reg:27 reg:
28 maxItems: 128 maxItems: 1
29 29
30 interrupts:
31 maxItems: 1
32
30required:33required:
31 - compatible34 - compatible
32 - reg35 - reg
Documentation/devicetree/bindings/iio/humidity/ti,hdc3020.yaml+3−0
@@ -43,6 +43,7 @@ additionalProperties: false · 42 unmodified lines
43 43
44examples:44examples:
45 - |45 - |
46 #include <dt-bindings/interrupt-controller/irq.h>
46 i2c {47 i2c {
47 #address-cells = <1>;48 #address-cells = <1>;
48 #size-cells = <0>;49 #size-cells = <0>;
@@ -51,5 +52,7 @@ examples: · 2 unmodified lines
51 compatible = "ti,hdc3021", "ti,hdc3020";52 compatible = "ti,hdc3021", "ti,hdc3020";
52 reg = <0x47>;53 reg = <0x47>;
53 vdd-supply = <&vcc_3v3>;54 vdd-supply = <&vcc_3v3>;
55 interrupt-parent = <&gpio3>;
56 interrupts = <23 IRQ_TYPE_EDGE_RISING>;
54 };57 };
55 };58 };
Documentation/devicetree/bindings/iio/imu/st,lsm6dsx.yaml+3−1
@@ -35,7 +35,9 @@ properties: · 34 unmodified lines
35 - st,lsm6dsv35 - st,lsm6dsv
36 - st,lsm6dso16is36 - st,lsm6dso16is
37 - items:37 - items:
38 - const: st,asm330lhhx38 - enum:
39 - st,asm330lhhx
40 - st,asm330lhhxg1
39 - const: st,lsm6dsr41 - const: st,lsm6dsr
40 - items:42 - items:
41 - const: st,lsm6dstx43 - const: st,lsm6dstx
Documentation/devicetree/bindings/iio/light/ams,as73211.yaml+5−2
@@ -4,19 +4,22 @@ · 3 unmodified lines
4$id: http://devicetree.org/schemas/iio/light/ams,as73211.yaml#4$id: http://devicetree.org/schemas/iio/light/ams,as73211.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#5$schema: http://devicetree.org/meta-schemas/core.yaml#
6 6
7title: AMS AS73211 JENCOLOR(R) Digital XYZ Sensor7title: AMS AS73211 JENCOLOR(R) Digital XYZ Sensor and AMS AS7331 UV Sensor
8 8
9maintainers:9maintainers:
10 - Christian Eggers <ceggers@arri.de>10 - Christian Eggers <ceggers@arri.de>
11 11
12description: |12description: |
13 XYZ True Color Sensor with I2C Interface13 AMS AS73211 XYZ True Color Sensor with I2C Interface
14 https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf/a65474c0-b302-c2fd-e30a-c98df87616df14 https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf/a65474c0-b302-c2fd-e30a-c98df87616df
15 AMS AS7331 UVA, UVB and UVC Sensor with I2C Interface
16 https://ams.com/documents/20143/9106314/AS7331_DS001047_4-00.pdf
15 17
16properties:18properties:
17 compatible:19 compatible:
18 enum:20 enum:
19 - ams,as7321121 - ams,as73211
22 - ams,as7331
20 23
21 reg:24 reg:
22 description:25 description:
Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml+1−0
@@ -21,6 +21,7 @@ properties: · 20 unmodified lines
21required:21required:
22 - compatible22 - compatible
23 - reg23 - reg
24 - vdd-supply
24 25
25additionalProperties: false26additionalProperties: false
26 27
Documentation/devicetree/bindings/iio/magnetometer/voltafield,af8133j.yaml+60−0
@@ -0,0 +1,60 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/iio/magnetometer/voltafield,af8133j.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Voltafield AF8133J magnetometer sensor
8
9maintainers:
10 - Ondřej Jirman <megi@xff.cz>
11
12properties:
13 compatible:
14 const: voltafield,af8133j
15
16 reg:
17 maxItems: 1
18
19 reset-gpios:
20 description:
21 A signal for active low reset input of the sensor. (optional; if not
22 used, software reset over I2C will be used instead)
23
24 avdd-supply:
25 description:
26 A regulator that provides AVDD power (Working power, usually 3.3V) to
27 the sensor.
28
29 dvdd-supply:
30 description:
31 A regulator that provides DVDD power (Digital IO power, 1.8V - AVDD)
32 to the sensor.
33
34 mount-matrix:
35 description: An optional 3x3 mounting rotation matrix.
36
37required:
38 - compatible
39 - reg
40 - avdd-supply
41 - dvdd-supply
42
43additionalProperties: false
44
45examples:
46 - |
47 #include <dt-bindings/interrupt-controller/irq.h>
48 #include <dt-bindings/gpio/gpio.h>
49 i2c {
50 #address-cells = <1>;
51 #size-cells = <0>;
52
53 magnetometer@1c {
54 compatible = "voltafield,af8133j";
55 reg = <0x1c>;
56 avdd-supply = <&reg_dldo1>;
57 dvdd-supply = <&reg_dldo1>;
58 reset-gpios = <&pio 1 1 GPIO_ACTIVE_LOW>;
59 };
60 };
Documentation/devicetree/bindings/iio/pressure/honeywell,hsc030pa.yaml+3−0
@@ -99,6 +99,9 @@ required: · 98 unmodified lines
99 - honeywell,transfer-function99 - honeywell,transfer-function
100 - honeywell,pressure-triplet100 - honeywell,pressure-triplet
101 101
102allOf:
103 - $ref: /schemas/spi/spi-peripheral-props.yaml
104
102additionalProperties: false105additionalProperties: false
103 106
104dependentSchemas:107dependentSchemas:
Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml+77−21
@@ -8,25 +8,28 @@ title: Honeywell mprls0025pa pressure sensor · 7 unmodified lines
8 8
9maintainers:9maintainers:
10 - Andreas Klinger <ak@it-klinger.de>10 - Andreas Klinger <ak@it-klinger.de>
11 - Petre Rodan <petre.rodan@subdimension.ro>
11 12
12description: |13description: |
13 Honeywell pressure sensor of model mprls0025pa.14 Honeywell pressure sensor of model mprls0025pa.
14 15
15 This sensor has an I2C and SPI interface. Only the I2C interface is16 This sensor has an I2C and SPI interface.
16 implemented.
17 17
18 There are many models with different pressure ranges available. The vendor18 There are many models with different pressure ranges available. The vendor
19 calls them "mpr series". All of them have the identical programming model and19 calls them "mpr series". All of them have the identical programming model and
20 differ in the pressure range, unit and transfer function.20 differ in the pressure range, unit and transfer function.
21 21
22 To support different models one need to specify the pressure range as well as22 To support different models one need to specify its pressure triplet as well
23 the transfer function. Pressure range needs to be converted from its unit to23 as the transfer function.
24 pascal.24
25 For custom silicon chips not covered by the Honeywell MPR series datasheet,
26 the pressure values can be specified manually via honeywell,pmin-pascal and
27 honeywell,pmax-pascal.
28 The minimal range value stands for the minimum pressure and the maximum value
29 also for the maximum pressure with linear relation inside the range.
25 30
26 The transfer function defines the ranges of numerical values delivered by the31 The transfer function defines the ranges of numerical values delivered by the
27 sensor. The minimal range value stands for the minimum pressure and the32 sensor.
28 maximum value also for the maximum pressure with linear relation inside the
29 range.
30 33
31 Specifications about the devices can be found at:34 Specifications about the devices can be found at:
32 https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/35 https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/
@@ -42,6 +45,10 @@ properties: · 9 unmodified lines
42 maxItems: 145 maxItems: 1
43 46
44 interrupts:47 interrupts:
48 description:
49 Optional interrupt for indicating End-of-conversion.
50 If not present, the driver loops for a while until the received status
51 byte indicates correct measurement.
45 maxItems: 152 maxItems: 1
46 53
47 reset-gpios:54 reset-gpios:
@@ -50,14 +57,6 @@ properties: · 2 unmodified lines
50 If not present the device is not reset during the probe.57 If not present the device is not reset during the probe.
51 maxItems: 158 maxItems: 1
52 59
53 honeywell,pmin-pascal:
54 description:
55 Minimum pressure value the sensor can measure in pascal.
56
57 honeywell,pmax-pascal:
58 description:
59 Maximum pressure value the sensor can measure in pascal.
60
61 honeywell,transfer-function:60 honeywell,transfer-function:
62 description: |61 description: |
63 Transfer function which defines the range of valid values delivered by the62 Transfer function which defines the range of valid values delivered by the
@@ -65,19 +64,57 @@ properties: · 1 unmodified line
65 1 - A, 10% to 90% of 2^24 (1677722 .. 15099494)64 1 - A, 10% to 90% of 2^24 (1677722 .. 15099494)
66 2 - B, 2.5% to 22.5% of 2^24 (419430 .. 3774874)65 2 - B, 2.5% to 22.5% of 2^24 (419430 .. 3774874)
67 3 - C, 20% to 80% of 2^24 (3355443 .. 13421773)66 3 - C, 20% to 80% of 2^24 (3355443 .. 13421773)
67 enum: [1, 2, 3]
68 $ref: /schemas/types.yaml#/definitions/uint3268 $ref: /schemas/types.yaml#/definitions/uint32
69 69
70 honeywell,pressure-triplet:
71 description: |
72 Case-sensitive five character string that defines pressure range, unit
73 and type as part of the device nomenclature. In the unlikely case of a
74 custom chip, unset and provide pmin-pascal and pmax-pascal instead.
75 enum: [0001BA, 01.6BA, 02.5BA, 0060MG, 0100MG, 0160MG, 0250MG, 0400MG,
76 0600MG, 0001BG, 01.6BG, 02.5BG, 0100KA, 0160KA, 0250KA, 0006KG,
77 0010KG, 0016KG, 0025KG, 0040KG, 0060KG, 0100KG, 0160KG, 0250KG,
78 0015PA, 0025PA, 0030PA, 0001PG, 0005PG, 0015PG, 0030PG, 0300YG]
79 $ref: /schemas/types.yaml#/definitions/string
80
81 honeywell,pmin-pascal:
82 description:
83 Minimum pressure value the sensor can measure in pascal.
84
85 honeywell,pmax-pascal:
86 description:
87 Maximum pressure value the sensor can measure in pascal.
88
89 spi-max-frequency:
90 maximum: 800000
91
70 vdd-supply:92 vdd-supply:
71 description: provide VDD power to the sensor.93 description: provide VDD power to the sensor.
72 94
73required:95required:
74 - compatible96 - compatible
75 - reg97 - reg
76 - honeywell,pmin-pascal
77 - honeywell,pmax-pascal
78 - honeywell,transfer-function98 - honeywell,transfer-function
79 - vdd-supply99 - vdd-supply
80 100
101oneOf:
102 - required:
103 - honeywell,pressure-triplet
104 - required:
105 - honeywell,pmin-pascal
106 - honeywell,pmax-pascal
107
108allOf:
109 - $ref: /schemas/spi/spi-peripheral-props.yaml
110 - if:
111 required:
112 - honeywell,pressure-triplet
113 then:
114 properties:
115 honeywell,pmin-pascal: false
116 honeywell,pmax-pascal: false
117
81additionalProperties: false118additionalProperties: false
82 119
83examples:120examples:
@@ -93,10 +130,29 @@ examples: · 9 unmodified lines
93 reg = <0x18>;130 reg = <0x18>;
94 reset-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;131 reset-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
95 interrupt-parent = <&gpio3>;132 interrupt-parent = <&gpio3>;
96 interrupts = <21 IRQ_TYPE_EDGE_FALLING>;133 interrupts = <21 IRQ_TYPE_EDGE_RISING>;
97 honeywell,pmin-pascal = <0>;134
98 honeywell,pmax-pascal = <172369>;135 honeywell,pressure-triplet = "0025PA";
136 honeywell,transfer-function = <1>;
137 vdd-supply = <&vcc_3v3>;
138 };
139 };
140 - |
141 spi {
142 #address-cells = <1>;
143 #size-cells = <0>;
144
145 pressure@0 {
146 compatible = "honeywell,mprls0025pa";
147 reg = <0>;
148 spi-max-frequency = <800000>;
149 reset-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
150 interrupt-parent = <&gpio0>;
151 interrupts = <30 IRQ_TYPE_EDGE_RISING>;
152
153 honeywell,pressure-triplet = "0015PA";
99 honeywell,transfer-function = <1>;154 honeywell,transfer-function = <1>;
100 vdd-supply = <&vcc_3v3>;155 vdd-supply = <&vcc_3v3>;
101 };156 };
102 };157 };
158...
Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml+8−0
@@ -24,9 +24,16 @@ properties: · 23 unmodified lines
24 reg:24 reg:
25 maxItems: 125 maxItems: 1
26 26
27 vcc-supply:
28 description: provide VCC power to the sensor.
29
30 label:
31 description: Unique name to identify which device this is.
32
27required:33required:
28 - compatible34 - compatible
29 - reg35 - reg
36 - vcc-supply
30 37
31additionalProperties: false38additionalProperties: false
32 39
@@ -39,5 +46,6 @@ examples: · 6 unmodified lines
39 tmp117@48 {46 tmp117@48 {
40 compatible = "ti,tmp117";47 compatible = "ti,tmp117";
41 reg = <0x48>;48 reg = <0x48>;
49 vcc-supply = <&pmic_reg_3v3>;
42 };50 };
43 };51 };
Documentation/devicetree/bindings/interconnect/qcom,rpm.yaml+3−0
@@ -23,6 +23,9 @@ properties: · 22 unmodified lines
23 23
24 compatible:24 compatible:
25 enum:25 enum:
26 - qcom,msm8909-bimc
27 - qcom,msm8909-pcnoc
28 - qcom,msm8909-snoc
26 - qcom,msm8916-bimc29 - qcom,msm8916-bimc
27 - qcom,msm8916-pcnoc30 - qcom,msm8916-pcnoc
28 - qcom,msm8916-snoc31 - qcom,msm8916-snoc
Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml+1−1
@@ -8,7 +8,7 @@ title: Qualcomm RPMh Network-On-Chip Interconnect · 7 unmodified lines
8 8
9maintainers:9maintainers:
10 - Georgi Djakov <georgi.djakov@linaro.org>10 - Georgi Djakov <georgi.djakov@linaro.org>
11 - Odelu Kukatla <okukatla@codeaurora.org>11 - Odelu Kukatla <quic_okukatla@quicinc.com>
12 12
13description: |13description: |
14 RPMh interconnect providers support system bandwidth requirements through14 RPMh interconnect providers support system bandwidth requirements through
Documentation/devicetree/bindings/interconnect/qcom,sm7150-rpmh.yaml+84−0
@@ -0,0 +1,84 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/interconnect/qcom,sm7150-rpmh.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Qualcomm RPMh Network-On-Chip Interconnect on SM7150
8
9maintainers:
10 - Danila Tikhonov <danila@jiaxyga.com>
11
12description: |
13 RPMh interconnect providers support system bandwidth requirements through
14 RPMh hardware accelerators known as Bus Clock Manager (BCM).
15
16 See also:: include/dt-bindings/interconnect/qcom,sm7150-rpmh.h
17
18allOf:
19 - $ref: qcom,rpmh-common.yaml#
20
21properties:
22 compatible:
23 enum:
24 - qcom,sm7150-aggre1-noc
25 - qcom,sm7150-aggre2-noc
26 - qcom,sm7150-compute-noc
27 - qcom,sm7150-config-noc
28 - qcom,sm7150-dc-noc
29 - qcom,sm7150-gem-noc
30 - qcom,sm7150-mc-virt
31 - qcom,sm7150-mmss-noc
32 - qcom,sm7150-system-noc
33
34 reg:
35 maxItems: 1
36
37# Child node's properties
38patternProperties:
39 '^interconnect-[0-9]+$':
40 type: object
41 description:
42 The interconnect providers do not have a separate QoS register space,
43 but share parent's space.
44
45 allOf:
46 - $ref: qcom,rpmh-common.yaml#
47
48 properties:
49 compatible:
50 enum:
51 - qcom,sm7150-camnoc-virt
52
53 required:
54 - compatible
55
56 unevaluatedProperties: false
57
58required:
59 - compatible
60 - reg
61
62unevaluatedProperties: false
63
64examples:
65 - |
66 mc_virt: interconnect@1380000 {
67 compatible = "qcom,sm7150-mc-virt";
68 reg = <0x01380000 0x40000>;
69 #interconnect-cells = <2>;
70 qcom,bcm-voters = <&apps_bcm_voter>;
71 };
72
73 system_noc: interconnect@1620000 {
74 compatible = "qcom,sm7150-system-noc";
75 reg = <0x01620000 0x40000>;
76 #interconnect-cells = <2>;
77 qcom,bcm-voters = <&apps_bcm_voter>;
78
79 camnoc_virt: interconnect-0 {
80 compatible = "qcom,sm7150-camnoc-virt";
81 #interconnect-cells = <2>;
82 qcom,bcm-voters = <&apps_bcm_voter>;
83 };
84 };
Documentation/devicetree/bindings/nvmem/layouts/fixed-cell.yaml+10−12
@@ -36,20 +36,18 @@ properties: · 35 unmodified lines
36 36
37allOf:37allOf:
38 - if:38 - if:
39 properties:
40 compatible:
41 contains:
42 const: mac-base
39 required: [ compatible ]43 required: [ compatible ]
40 then:44 then:
41 if:45 properties:
42 properties:46 "#nvmem-cell-cells":
43 compatible:47 description: The first argument is a MAC address offset.
44 contains:48 const: 1
45 const: mac-base49 required:
46 then:50 - "#nvmem-cell-cells"
47 properties:
48 "#nvmem-cell-cells":
49 description: The first argument is a MAC address offset.
50 const: 1
51 required:
52 - "#nvmem-cell-cells"
53 51
54required:52required:
55 - reg53 - reg
Documentation/devicetree/bindings/nvmem/nvmem-provider.yaml+18−0
@@ -0,0 +1,18 @@
1# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/nvmem/nvmem-provider.yaml#
5$schema: http://devicetree.org/meta-schemas/base.yaml#
6
7title: NVMEM (Non Volatile Memory) Provider
8
9maintainers:
10 - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
11
12select: true
13
14properties:
15 '#nvmem-cell-cells':
16 enum: [0, 1]
17
18additionalProperties: true
Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt+0−46
@@ -1,46 +0,0 @@
1--------------------------------------------------------------------------
2= Zynq UltraScale+ MPSoC nvmem firmware driver binding =
3--------------------------------------------------------------------------
4The nvmem_firmware node provides access to the hardware related data
5like soc revision, IDCODE... etc, By using the firmware interface.
6
7Required properties:
8- compatible: should be "xlnx,zynqmp-nvmem-fw"
9
10= Data cells =
11Are child nodes of silicon id, bindings of which as described in
12bindings/nvmem/nvmem.txt
13
14-------
15 Example
16-------
17firmware {
18 zynqmp_firmware: zynqmp-firmware {
19 compatible = "xlnx,zynqmp-firmware";
20 method = "smc";
21
22 nvmem_firmware {
23 compatible = "xlnx,zynqmp-nvmem-fw";
24 #address-cells = <1>;
25 #size-cells = <1>;
26
27 /* Data cells */
28 soc_revision: soc_revision {
29 reg = <0x0 0x4>;
30 };
31 };
32 };
33};
34
35= Data consumers =
36Are device nodes which consume nvmem data cells.
37
38For example:
39 pcap {
40 ...
41
42 nvmem-cells = <&soc_revision>;
43 nvmem-cell-names = "soc_revision";
44
45 ...
46 };
Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml+42−0
@@ -0,0 +1,42 @@
1# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2%YAML 1.2
3---
4$id: http://devicetree.org/schemas/nvmem/xlnx,zynqmp-nvmem.yaml#
5$schema: http://devicetree.org/meta-schemas/core.yaml#
6
7title: Zynq UltraScale+ MPSoC Non Volatile Memory interface
8
9description: |
10 The ZynqMP MPSoC provides access to the hardware related data
11 like SOC revision, IDCODE and specific purpose efuses.
12
13maintainers:
14 - Kalyani Akula <kalyani.akula@amd.com>
15 - Praveen Teja Kundanala <praveen.teja.kundanala@amd.com>
16
17allOf:
18 - $ref: nvmem.yaml#
19
20properties:
21 compatible:
22 const: xlnx,zynqmp-nvmem-fw
23
24required:
25 - compatible
26
27unevaluatedProperties: false
28
29examples:
30 - |
31 nvmem {
32 compatible = "xlnx,zynqmp-nvmem-fw";
33 nvmem-layout {
34 compatible = "fixed-layout";
35 #address-cells = <1>;
36 #size-cells = <1>;
37
38 soc_revision: soc-revision@0 {
39 reg = <0x0 0x4>;
40 };
41 };
42 };
Documentation/devicetree/bindings/vendor-prefixes.yaml+2−0
@@ -1573,6 +1573,8 @@ patternProperties: · 1572 unmodified lines
1573 description: VoCore Studio1573 description: VoCore Studio
1574 "^voipac,.*":1574 "^voipac,.*":
1575 description: Voipac Technologies s.r.o.1575 description: Voipac Technologies s.r.o.
1576 "^voltafield,.*":
1577 description: Voltafield Technology Corp.
1576 "^vot,.*":1578 "^vot,.*":
1577 description: Vision Optical Technology Co., Ltd.1579 description: Vision Optical Technology Co., Ltd.
1578 "^vscom,.*":1580 "^vscom,.*":
Documentation/iio/adis16475.rst+407−0
@@ -0,0 +1,407 @@
1.. SPDX-License-Identifier: GPL-2.0
2
3================
4ADIS16475 driver
5================
6
7This driver supports Analog Device's IMUs on SPI bus.
8
91. Supported devices
10====================
11
12* `ADIS16465 <https://www.analog.com/ADIS16465>`_
13* `ADIS16467 <https://www.analog.com/ADIS16467>`_
14* `ADIS16470 <https://www.analog.com/ADIS16470>`_
15* `ADIS16475 <https://www.analog.com/ADIS16475>`_
16* `ADIS16477 <https://www.analog.com/ADIS16477>`_
17* `ADIS16500 <https://www.analog.com/ADIS16500>`_
18* `ADIS16505 <https://www.analog.com/ADIS16505>`_
19* `ADIS16507 <https://www.analog.com/ADIS16507>`_
20
21Each supported device is a precision, miniature microelectromechanical system
22(MEMS) inertial measurement unit (IMU) that includes a triaxial gyroscope and a
23triaxial accelerometer. Each inertial sensor in the IMU device combines with
24signal conditioning that optimizes dynamic performance. The factory calibration
25characterizes each sensor for sensitivity, bias, alignment, linear acceleration
26(gyroscope bias), and point of percussion (accelerometer location). As a result,
27each sensor has dynamic compensation formulas that provide accurate sensor
28measurements over a broad set of conditions.
29
302. Device attributes
31====================
32
33Accelerometer, gyroscope measurements are always provided. Furthermore, the
34driver offers the capability to retrieve the delta angle and the delta velocity
35measurements computed by the device.
36
37The delta angle measurements represent a calculation of angular displacement
38between each sample update, while the delta velocity measurements represent a
39calculation of linear velocity change between each sample update.
40
41Finally, temperature data are provided which show a coarse measurement of
42the temperature inside of the IMU device. This data is most useful for
43monitoring relative changes in the thermal environment.
44
45The signal chain of each inertial sensor (accelerometers and gyroscopes)
46includes the application of unique correction formulas, which are derived from
47extensive characterization of bias, sensitivity, alignment, response to linear
48acceleration (gyroscopes), and point of percussion (accelerometer location)
49over a temperature range of −40°C to +85°C, for each ADIS device. These
50correction formulas are not accessible, but users do have the opportunity to
51adjust the bias for each sensor individually through the calibbias attribute.
52
53Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``,
54where X is the IIO index of the device. Under these folders reside a set of
55device files, depending on the characteristics and features of the hardware
56device in questions. These files are consistently generalized and documented in
57the IIO ABI documentation.
58
59The following tables show the adis16475 related device files, found in the
60specific device folder path ``/sys/bus/iio/devices/iio:deviceX``.
61
62+-------------------------------------------+----------------------------------------------------------+
63| 3-Axis Accelerometer related device files | Description |
64+-------------------------------------------+----------------------------------------------------------+
65| in_accel_scale | Scale for the accelerometer channels. |
66+-------------------------------------------+----------------------------------------------------------+
67| in_accel_x_calibbias | Calibration offset for the X-axis accelerometer channel. |
68+-------------------------------------------+----------------------------------------------------------+
69| in_accel_calibbias_x | x-axis acceleration offset correction |
70+-------------------------------------------+----------------------------------------------------------+
71| in_accel_x_raw | Raw X-axis accelerometer channel value. |
72+-------------------------------------------+----------------------------------------------------------+
73| in_accel_calibbias_y | y-axis acceleration offset correction |
74+-------------------------------------------+----------------------------------------------------------+
75| in_accel_y_raw | Raw Y-axis accelerometer channel value. |
76+-------------------------------------------+----------------------------------------------------------+
77| in_accel_z_calibbias | Calibration offset for the Z-axis accelerometer channel. |
78+-------------------------------------------+----------------------------------------------------------+
79| in_accel_z_raw | Raw Z-axis accelerometer channel value. |
80+-------------------------------------------+----------------------------------------------------------+
81| in_deltavelocity_scale | Scale for delta velocity channels. |
82+-------------------------------------------+----------------------------------------------------------+
83| in_deltavelocity_x_raw | Raw X-axis delta velocity channel value. |
84+-------------------------------------------+----------------------------------------------------------+
85| in_deltavelocity_y_raw | Raw Y-axis delta velocity channel value. |
86+-------------------------------------------+----------------------------------------------------------+
87| in_deltavelocity_z_raw | Raw Z-axis delta velocity channel value. |
88+-------------------------------------------+----------------------------------------------------------+
89
90+---------------------------------------+------------------------------------------------------+
91| 3-Axis Gyroscope related device files | Description |
92+---------------------------------------+------------------------------------------------------+
93| in_anglvel_scale | Scale for the gyroscope channels. |
94+---------------------------------------+------------------------------------------------------+
95| in_anglvel_x_calibbias | Calibration offset for the X-axis gyroscope channel. |
96+---------------------------------------+------------------------------------------------------+
97| in_anglvel_calibbias_x | x-axis gyroscope offset correction |
98+---------------------------------------+------------------------------------------------------+
99| in_anglvel_x_raw | Raw X-axis gyroscope channel value. |
100+---------------------------------------+------------------------------------------------------+
101| in_anglvel_calibbias_y | y-axis gyroscope offset correction |
102+---------------------------------------+------------------------------------------------------+
103| in_anglvel_y_raw | Raw Y-axis gyroscope channel value. |
104+---------------------------------------+------------------------------------------------------+
105| in_anglvel_z_calibbias | Calibration offset for the Z-axis gyroscope channel. |
106+---------------------------------------+------------------------------------------------------+
107| in_anglvel_z_raw | Raw Z-axis gyroscope channel value. |
108+---------------------------------------+------------------------------------------------------+
109| in_deltaangl_scale | Scale for delta angle channels. |
110+---------------------------------------+------------------------------------------------------+
111| in_deltaangl_x_raw | Raw X-axis delta angle channel value. |
112+---------------------------------------+------------------------------------------------------+
113| in_deltaangl_y_raw | Raw Y-axis delta angle channel value. |
114+---------------------------------------+------------------------------------------------------+
115| in_deltaangl_z_raw | Raw Z-axis delta angle channel value. |
116+---------------------------------------+------------------------------------------------------+
117
118+----------------------------------+-------------------------------------------+
119| Temperature sensor related files | Description |
120+----------------------------------+-------------------------------------------+
121| in_temp0_raw | Raw temperature channel value. |
122+----------------------------------+-------------------------------------------+
123| in_temp0_scale | Scale for the temperature sensor channel. |
124+----------------------------------+-------------------------------------------+
125
126+-------------------------------+---------------------------------------------------------+
127| Miscellaneous device files | Description |
128+-------------------------------+---------------------------------------------------------+
129| name | Name of the IIO device. |
130+-------------------------------+---------------------------------------------------------+
131| sampling_frequency | Currently selected sample rate. |
132+-------------------------------+---------------------------------------------------------+
133| filter_low_pass_3db_frequency | Bandwidth for the accelerometer and gyroscope channels. |
134+-------------------------------+---------------------------------------------------------+
135
136The following table shows the adis16475 related device debug files, found in the
137specific device debug folder path ``/sys/kernel/debug/iio/iio:deviceX``.
138
139+----------------------+-------------------------------------------------------------------------+
140| Debugfs device files | Description |
141+----------------------+-------------------------------------------------------------------------+
142| serial_number | The serial number of the chip in hexadecimal format. |
143+----------------------+-------------------------------------------------------------------------+
144| product_id | Chip specific product id (e.g. 16475, 16500, 16505, etc.). |
145+----------------------+-------------------------------------------------------------------------+
146| flash_count | The number of flash writes performed on the device. |
147+----------------------+-------------------------------------------------------------------------+
148| firmware_revision | String containing the firmware revision in the following format ##.##. |
149+----------------------+-------------------------------------------------------------------------+
150| firmware_date | String containing the firmware date in the following format mm-dd-yyyy. |
151+----------------------+-------------------------------------------------------------------------+
152
153Channels processed values
154-------------------------
155
156A channel value can be read from its _raw attribute. The value returned is the
157raw value as reported by the devices. To get the processed value of the channel,
158apply the following formula:
159
160.. code-block:: bash
161
162 processed value = (_raw + _offset) * _scale
163
164Where _offset and _scale are device attributes. If no _offset attribute is
165present, simply assume its value is 0.
166
167The adis16475 driver offers data for 5 types of channels, the table below shows
168the measurement units for the processed value, which are defined by the IIO
169framework:
170
171+-------------------------------------+---------------------------+
172| Channel type | Measurement unit |
173+-------------------------------------+---------------------------+
174| Acceleration on X, Y, and Z axis | Meters per Second squared |
175+-------------------------------------+---------------------------+
176| Angular velocity on X, Y and Z axis | Radians per second |
177+-------------------------------------+---------------------------+
178| Delta velocity on X. Y, and Z axis | Meters per Second |
179+-------------------------------------+---------------------------+
180| Delta angle on X, Y, and Z axis | Radians |
181+-------------------------------------+---------------------------+
182| Temperature | Millidegrees Celsius |
183+-------------------------------------+---------------------------+
184
185Usage examples
186--------------
187
188Show device name:
189
190.. code-block:: bash
191
192 root:/sys/bus/iio/devices/iio:device0> cat name
193 adis16505-2
194
195Show accelerometer channels value:
196
197.. code-block:: bash
198
199 root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_raw
200 -275924
201 root:/sys/bus/iio/devices/iio:device0> cat in_accel_y_raw
202 -30142222
203 root:/sys/bus/iio/devices/iio:device0> cat in_accel_z_raw
204 261265769
205 root:/sys/bus/iio/devices/iio:device0> cat in_accel_scale
206 0.000000037
207
208- X-axis acceleration = in_accel_x_raw * in_accel_scale = −0.010209188 m/s^2
209- Y-axis acceleration = in_accel_y_raw * in_accel_scale = −1.115262214 m/s^2
210- Z-axis acceleration = in_accel_z_raw * in_accel_scale = 9.666833453 m/s^2
211
212Show gyroscope channels value:
213
214.. code-block:: bash
215
216 root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_x_raw
217 -3324626
218 root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_raw
219 1336980
220 root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_z_raw
221 -602983
222 root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_scale
223 0.000000006
224
225- X-axis angular velocity = in_anglvel_x_raw * in_anglvel_scale = −0.019947756 rad/s
226- Y-axis angular velocity = in_anglvel_y_raw * in_anglvel_scale = 0.00802188 rad/s
227- Z-axis angular velocity = in_anglvel_z_raw * in_anglvel_scale = −0.003617898 rad/s
228
229Set calibration offset for accelerometer channels:
230
231.. code-block:: bash
232
233 root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias
234 0
235
236 root:/sys/bus/iio/devices/iio:device0> echo 5000 > in_accel_x_calibbias
237 root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias
238 5000
239
240Set calibration offset for gyroscope channels:
241
242.. code-block:: bash
243
244 root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_calibbias
245 0
246
247 root:/sys/bus/iio/devices/iio:device0> echo -5000 > in_anglvel_y_calibbias
248 root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_calibbias
249 -5000
250
251Set sampling frequency:
252
253.. code-block:: bash
254
255 root:/sys/bus/iio/devices/iio:device0> cat sampling_frequency
256 2000.000000
257
258 root:/sys/bus/iio/devices/iio:device0> echo 1000 > sampling_frequency
259 1000.000000
260
261Set bandwidth for accelerometer and gyroscope:
262
263.. code-block:: bash
264
265 root:/sys/bus/iio/devices/iio:device0> cat filter_low_pass_3db_frequency
266 720
267
268 root:/sys/bus/iio/devices/iio:device0> echo 360 > filter_low_pass_3db_frequency
269 root:/sys/bus/iio/devices/iio:device0> cat filter_low_pass_3db_frequency
270 360
271
272Show serial number:
273
274.. code-block:: bash
275
276 root:/sys/kernel/debug/iio/iio:device0> cat serial_number
277 0x04f9
278
279Show product id:
280
281.. code-block:: bash
282
283 root:/sys/kernel/debug/iio/iio:device0> cat product_id
284 16505
285
286Show flash count:
287
288.. code-block:: bash
289
290 root:/sys/kernel/debug/iio/iio:device0> cat flash_count
291 150
292
293Show firmware revision:
294
295.. code-block:: bash
296
297 root:/sys/kernel/debug/iio/iio:device0> cat firmware_revision
298 1.6
299
300Show firmware date:
301
302.. code-block:: bash
303
304 root:/sys/kernel/debug/iio/iio:device0> cat firmware_date
305 06-27-2019
306
3073. Device buffers
308=================
309
310This driver supports IIO buffers.
311
312All devices support retrieving the raw acceleration, gyroscope and temperature
313measurements using buffers.
314
315The following device families also support retrieving the delta velocity, delta
316angle and temperature measurements using buffers:
317
318- ADIS16477
319- ADIS16500
320- ADIS16505
321- ADIS16507
322
323However, when retrieving acceleration or gyroscope data using buffers, delta
324readings will not be available and vice versa.
325
326Usage examples
327--------------
328
329Set device trigger in current_trigger, if not already set:
330
331.. code-block:: bash
332
333 root:/sys/bus/iio/devices/iio:device0> cat trigger/current_trigger
334
335 root:/sys/bus/iio/devices/iio:device0> echo adis16505-2-dev0 > trigger/current_trigger
336 root:/sys/bus/iio/devices/iio:device0> cat trigger/current_trigger
337 adis16505-2-dev0
338
339Select channels for buffer read:
340
341.. code-block:: bash
342
343 root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_x_en
344 root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_y_en
345 root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_z_en
346 root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_temp0_en
347
348Set the number of samples to be stored in the buffer:
349
350.. code-block:: bash
351
352 root:/sys/bus/iio/devices/iio:device0> echo 10 > buffer/length
353
354Enable buffer readings:
355
356.. code-block:: bash
357
358 root:/sys/bus/iio/devices/iio:device0> echo 1 > buffer/enable
359
360Obtain buffered data:
361
362.. code-block:: bash
363
364 root:/sys/bus/iio/devices/iio:device0> hexdump -C /dev/iio\:device0
365 ...
366 00001680 01 1f 00 00 ff ff fe ef 00 00 47 bf 00 03 35 55 |..........G...5U|
367 00001690 01 1f 00 00 ff ff ff d9 00 00 46 f1 00 03 35 35 |..........F...55|
368 000016a0 01 1f 00 00 ff ff fe fc 00 00 46 cb 00 03 35 7b |..........F...5{|
369 000016b0 01 1f 00 00 ff ff fe 41 00 00 47 0d 00 03 35 8b |.......A..G...5.|
370 000016c0 01 1f 00 00 ff ff fe 37 00 00 46 b4 00 03 35 90 |.......7..F...5.|
371 000016d0 01 1d 00 00 ff ff fe 5a 00 00 45 d7 00 03 36 08 |.......Z..E...6.|
372 000016e0 01 1b 00 00 ff ff fe fb 00 00 45 e7 00 03 36 60 |..........E...6`|
373 000016f0 01 1a 00 00 ff ff ff 17 00 00 46 bc 00 03 36 de |..........F...6.|
374 00001700 01 1a 00 00 ff ff fe 59 00 00 46 d7 00 03 37 b8 |.......Y..F...7.|
375 00001710 01 1a 00 00 ff ff fe ae 00 00 46 95 00 03 37 ba |..........F...7.|
376 00001720 01 1a 00 00 ff ff fe c5 00 00 46 63 00 03 37 9f |..........Fc..7.|
377 00001730 01 1a 00 00 ff ff fe 55 00 00 46 89 00 03 37 c1 |.......U..F...7.|
378 00001740 01 1a 00 00 ff ff fe 31 00 00 46 aa 00 03 37 f7 |.......1..F...7.|
379 ...
380
381See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered
382data is structured.
383
3844. IIO Interfacing Tools
385========================
386
387Linux Kernel Tools
388------------------
389
390Linux Kernel provides some userspace tools that can be used to retrieve data
391from IIO sysfs:
392
393* lsiio: example application that provides a list of IIO devices and triggers
394* iio_event_monitor: example application that reads events from an IIO device
395 and prints them
396* iio_generic_buffer: example application that reads data from buffer
397* iio_utils: set of APIs, typically used to access sysfs files.
398
399LibIIO
400------
401
402LibIIO is a C/C++ library that provides generic access to IIO devices. The
403library abstracts the low-level details of the hardware, and provides a simple
404yet complete programming interface that can be used for advanced projects.
405
406For more information about LibIIO, please see:
407https://github.com/analogdevicesinc/libiio
Documentation/iio/iio_devbuf.rst+152−0
@@ -0,0 +1,152 @@
1.. SPDX-License-Identifier: GPL-2.0
2
3=============================
4Industrial IIO device buffers
5=============================
6
71. Overview
8===========
9
10The Industrial I/O core offers a way for continuous data capture based on a
11trigger source. Multiple data channels can be read at once from
12``/dev/iio:deviceX`` character device node, thus reducing the CPU load.
13
14Devices with buffer support feature an additional sub-directory in the
15``/sys/bus/iio/devices/iio:deviceX/`` directory hierarchy, called bufferY, where
16Y defaults to 0, for devices with a single buffer.
17
182. Buffer attributes
19====================
20
21An IIO buffer has an associated attributes directory under
22``/sys/bus/iio/iio:deviceX/bufferY/``. The attributes are described below.
23
24``length``
25----------
26
27Read / Write attribute which states the total number of data samples (capacity)
28that can be stored by the buffer.
29
30``enable``
31----------
32
33Read / Write attribute which starts / stops the buffer capture. This file should
34be written last, after length and selection of scan elements. Writing a non-zero
35value may result in an error, such as EINVAL, if, for example, an unsupported
36combination of channels is given.
37
38``watermark``
39-------------
40
41Read / Write positive integer attribute specifying the maximum number of scan
42elements to wait for.
43
44Poll will block until the watermark is reached.
45
46Blocking read will wait until the minimum between the requested read amount or
47the low watermark is available.
48
49Non-blocking read will retrieve the available samples from the buffer even if
50there are less samples than the watermark level. This allows the application to
51block on poll with a timeout and read the available samples after the timeout
52expires and thus have a maximum delay guarantee.
53
54Data available
55--------------
56
57Read-only attribute indicating the bytes of data available in the buffer. In the
58case of an output buffer, this indicates the amount of empty space available to
59write data to. In the case of an input buffer, this indicates the amount of data
60available for reading.
61
62Scan elements
63-------------
64
65The meta information associated with a channel data placed in a buffer is called
66a scan element. The scan elements attributes are presented below.
67
68**_en**
69
70Read / Write attribute used for enabling a channel. If and only if its value
71is non-zero, then a triggered capture will contain data samples for this
72channel.
73
74**_index**
75
76Read-only unsigned integer attribute specifying the position of the channel in
77the buffer. Note these are not dependent on what is enabled and may not be
78contiguous. Thus for userspace to establish the full layout these must be used
79in conjunction with all _en attributes to establish which channels are present,
80and the relevant _type attributes to establish the data storage format.
81
82**_type**
83
84Read-only attribute containing the description of the scan element data storage
85within the buffer and hence the form in which it is read from userspace. Format
86is [be|le]:[s|u]bits/storagebits[Xrepeat][>>shift], where:
87
88- **be** or **le** specifies big or little-endian.
89- **s** or **u** specifies if signed (2's complement) or unsigned.
90- **bits** is the number of valid data bits.
91- **storagebits** is the number of bits (after padding) that it occupies in the
92 buffer.
93- **repeat** specifies the number of bits/storagebits repetitions. When the
94 repeat element is 0 or 1, then the repeat value is omitted.
95- **shift** if specified, is the shift that needs to be applied prior to
96 masking out unused bits.
97
98For example, a driver for a 3-axis accelerometer with 12-bit resolution where
99data is stored in two 8-bit registers is as follows::
100
101 7 6 5 4 3 2 1 0
102 +---+---+---+---+---+---+---+---+
103 |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
104 +---+---+---+---+---+---+---+---+
105
106 7 6 5 4 3 2 1 0
107 +---+---+---+---+---+---+---+---+
108 |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
109 +---+---+---+---+---+---+---+---+
110
111will have the following scan element type for each axis:
112
113.. code-block:: bash
114
115 $ cat /sys/bus/iio/devices/iio:device0/buffer0/in_accel_y_type
116 le:s12/16>>4
117
118A userspace application will interpret data samples read from the buffer as
119two-byte little-endian signed data, that needs a 4 bits right shift before
120masking out the 12 valid bits of data.
121
122It is also worth mentioning that the data in the buffer will be naturally
123aligned, so the userspace application has to handle the buffers accordingly.
124
125Take for example, a driver with four channels with the following description:
126- channel0: index: 0, type: be:u16/16>>0
127- channel1: index: 1, type: be:u32/32>>0
128- channel2: index: 2, type: be:u32/32>>0
129- channel3: index: 3, type: be:u64/64>>0
130
131If all channels are enabled, the data will be aligned in the buffer as follows::
132
133 0-1 2 3 4-7 8-11 12 13 14 15 16-23 -> buffer byte number
134 +-----+---+---+-----+-----+---+---+---+---+-----+
135 |CHN_0|PAD|PAD|CHN_1|CHN_2|PAD|PAD|PAD|PAD|CHN_3| -> buffer content
136 +-----+---+---+-----+-----+---+---+---+---+-----+
137
138If only channel0 and channel3 are enabled, the data will be aligned in the
139buffer as follows::
140
141 0-1 2 3 4 5 6 7 8-15 -> buffer byte number
142 +-----+---+---+---+---+---+---+-----+
143 |CHN_0|PAD|PAD|PAD|PAD|PAD|PAD|CHN_3| -> buffer content
144 +-----+---+---+---+---+---+---+-----+
145
146Typically the buffered data is found in raw format (unscaled with no offset
147applied), however there are corner cases in which the buffered data may be found
148in a processed form. Please note that these corner cases are not addressed by
149this documentation.
150
151Please see ``Documentation/ABI/testing/sysfs-bus-iio`` for a complete
152description of the attributes.
Documentation/iio/index.rst+8−1
@@ -8,7 +8,14 @@ Industrial I/O · 7 unmodified lines
8 :maxdepth: 18 :maxdepth: 1
9 9
10 iio_configfs10 iio_configfs
11 iio_devbuf
11 12
12 ep93xx_adc13Industrial I/O Kernel Drivers
14=============================
13 15
16.. toctree::
17 :maxdepth: 1
18
19 adis16475
14 bno05520 bno055
21 ep93xx_adc
MAINTAINERS+44−5
@@ -579,6 +579,12 @@ F: drivers/iio/accel/adxl372.c · 578 unmodified lines
579F: drivers/iio/accel/adxl372_i2c.c579F: drivers/iio/accel/adxl372_i2c.c
580F: drivers/iio/accel/adxl372_spi.c580F: drivers/iio/accel/adxl372_spi.c
581 581
582AF8133J THREE-AXIS MAGNETOMETER DRIVER
583M: Ondřej Jirman <megi@xff.cz>
584S: Maintained
585F: Documentation/devicetree/bindings/iio/magnetometer/voltafield,af8133j.yaml
586F: drivers/iio/magnetometer/af8133j.c
587
582AF9013 MEDIA DRIVER588AF9013 MEDIA DRIVER
583L: linux-media@vger.kernel.org589L: linux-media@vger.kernel.org
584S: Orphan590S: Orphan
@@ -1158,7 +1164,7 @@ L: linux-iio@vger.kernel.org · 573 unmodified lines
1158S: Supported1164S: Supported
1159W: http://ez.analog.com/community/linux-device-drivers1165W: http://ez.analog.com/community/linux-device-drivers
1160F: Documentation/devicetree/bindings/iio/adc/adi,ad7091r*1166F: Documentation/devicetree/bindings/iio/adc/adi,ad7091r*
1161F: drivers/iio/adc/drivers/iio/adc/ad7091r*1167F: drivers/iio/adc/ad7091r*
1162 1168
1163ANALOG DEVICES INC AD7192 DRIVER1169ANALOG DEVICES INC AD7192 DRIVER
1164M: Alexandru Tachici <alexandru.tachici@analog.com>1170M: Alexandru Tachici <alexandru.tachici@analog.com>
@@ -1281,6 +1287,14 @@ W: https://ez.analog.com/linux-software-drivers · 116 unmodified lines
1281F: Documentation/devicetree/bindings/hwmon/adi,adm1177.yaml1287F: Documentation/devicetree/bindings/hwmon/adi,adm1177.yaml
1282F: drivers/hwmon/adm1177.c1288F: drivers/hwmon/adm1177.c
1283 1289
1290ANALOG DEVICES INC ADMFM2000 DRIVER
1291M: Kim Seer Paller <kimseer.paller@analog.com>
1292L: linux-iio@vger.kernel.org
1293S: Supported
1294W: https://ez.analog.com/linux-software-drivers
1295F: Documentation/devicetree/bindings/iio/frequency/adi,admfm2000.yaml
1296F: drivers/iio/frequency/admfm2000.c
1297
1284ANALOG DEVICES INC ADMV1013 DRIVER1298ANALOG DEVICES INC ADMV1013 DRIVER
1285M: Antoniu Miclaus <antoniu.miclaus@analog.com>1299M: Antoniu Miclaus <antoniu.miclaus@analog.com>
1286L: linux-iio@vger.kernel.org1300L: linux-iio@vger.kernel.org
@@ -9509,7 +9523,7 @@ T: git git://linuxtv.org/media_tree.git · 8222 unmodified lines
9509F: drivers/media/usb/hdpvr/9523F: drivers/media/usb/hdpvr/
9510 9524
9511HEWLETT PACKARD ENTERPRISE ILO CHIF DRIVER9525HEWLETT PACKARD ENTERPRISE ILO CHIF DRIVER
9512M: Matt Hsiao <matt.hsiao@hpe.com>9526M: Keng-Yu Lin <keng-yu.lin@hpe.com>
9513S: Supported9527S: Supported
9514F: drivers/misc/hpilo.[ch]9528F: drivers/misc/hpilo.[ch]
9515 9529
@@ -9879,10 +9893,11 @@ F: drivers/iio/pressure/hsc030pa* · 363 unmodified lines
9879 9893
9880HONEYWELL MPRLS0025PA PRESSURE SENSOR SERIES IIO DRIVER9894HONEYWELL MPRLS0025PA PRESSURE SENSOR SERIES IIO DRIVER
9881M: Andreas Klinger <ak@it-klinger.de>9895M: Andreas Klinger <ak@it-klinger.de>
9896M: Petre Rodan <petre.rodan@subdimension.ro>
9882L: linux-iio@vger.kernel.org9897L: linux-iio@vger.kernel.org
9883S: Maintained9898S: Maintained
9884F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml9899F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
9885F: drivers/iio/pressure/mprls0025pa.c9900F: drivers/iio/pressure/mprls0025pa*
9886 9901
9887HP BIOSCFG DRIVER9902HP BIOSCFG DRIVER
9888M: Jorge Lopez <jorge.lopez2@hp.com>9903M: Jorge Lopez <jorge.lopez2@hp.com>
@@ -10475,6 +10490,14 @@ L: linux-media@vger.kernel.org · 586 unmodified lines
10475S: Maintained10490S: Maintained
10476F: drivers/media/rc/iguanair.c10491F: drivers/media/rc/iguanair.c
10477 10492
10493IIO BACKEND FRAMEWORK
10494M: Nuno Sa <nuno.sa@analog.com>
10495R: Olivier Moysan <olivier.moysan@foss.st.com>
10496L: linux-iio@vger.kernel.org
10497S: Maintained
10498F: drivers/iio/industrialio-backend.c
10499F: include/linux/iio/backend.h
10500
10478IIO DIGITAL POTENTIOMETER DAC10501IIO DIGITAL POTENTIOMETER DAC
10479M: Peter Rosin <peda@axentia.se>10502M: Peter Rosin <peda@axentia.se>
10480L: linux-iio@vger.kernel.org10503L: linux-iio@vger.kernel.org
@@ -10497,6 +10520,7 @@ L: linux-iio@vger.kernel.org · 16 unmodified lines
10497S: Maintained10520S: Maintained
10498F: drivers/iio/industrialio-gts-helper.c10521F: drivers/iio/industrialio-gts-helper.c
10499F: include/linux/iio/iio-gts-helper.h10522F: include/linux/iio/iio-gts-helper.h
10523F: drivers/iio/test/iio-test-gts.c
10500 10524
10501IIO MULTIPLEXER10525IIO MULTIPLEXER
10502M: Peter Rosin <peda@axentia.se>10526M: Peter Rosin <peda@axentia.se>
@@ -14487,6 +14511,13 @@ F: Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml · 3984 unmodified lines
14487F: drivers/nvmem/microchip-otpc.c14511F: drivers/nvmem/microchip-otpc.c
14488F: include/dt-bindings/nvmem/microchip,sama7g5-otpc.h14512F: include/dt-bindings/nvmem/microchip,sama7g5-otpc.h
14489 14513
14514MICROCHIP PAC1934 POWER/ENERGY MONITOR DRIVER
14515M: Marius Cristea <marius.cristea@microchip.com>
14516L: linux-iio@vger.kernel.org
14517S: Supported
14518F: Documentation/devicetree/bindings/iio/adc/microchip,pac1934.yaml
14519F: drivers/iio/adc/pac1934.c
14520
14490MICROCHIP PCI1XXXX GP DRIVER14521MICROCHIP PCI1XXXX GP DRIVER
14491M: Vaibhaav Ram T.L <vaibhaavram.tl@microchip.com>14522M: Vaibhaav Ram T.L <vaibhaavram.tl@microchip.com>
14492M: Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>14523M: Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>
@@ -23566,8 +23597,8 @@ F: Documentation/driver-api/vme.rst · 9073 unmodified lines
23566F: drivers/staging/vme_user/23597F: drivers/staging/vme_user/
23567 23598
23568VMWARE BALLOON DRIVER23599VMWARE BALLOON DRIVER
23569M: Nadav Amit <namit@vmware.com>23600M: Jerrin Shaji George <jerrin.shaji-george@broadcom.com>
23570R: VMware PV-Drivers Reviewers <pv-drivers@vmware.com>23601R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
23571L: linux-kernel@vger.kernel.org23602L: linux-kernel@vger.kernel.org
23572S: Supported23603S: Supported
23573F: drivers/misc/vmw_balloon.c23604F: drivers/misc/vmw_balloon.c
@@ -24344,6 +24375,14 @@ M: Harsha <harsha.harsha@amd.com> · 770 unmodified lines
24344S: Maintained24375S: Maintained
24345F: drivers/crypto/xilinx/zynqmp-sha.c24376F: drivers/crypto/xilinx/zynqmp-sha.c
24346 24377
24378XILINX ZYNQMP NVMEM DRIVER
24379M: Praveen Teja Kundanala <praveen.teja.kundanala@amd.com>
24380M: Kalyani Akula <kalyani.akula@amd.com>
24381R: Michal Simek <michal.simek@amd.com>
24382S: Maintained
24383F: Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.yaml
24384F: drivers/nvmem/zynqmp_nvmem.c
24385
24347XILLYBUS DRIVER24386XILLYBUS DRIVER
24348M: Eli Billauer <eli.billauer@gmail.com>24387M: Eli Billauer <eli.billauer@gmail.com>
24349L: linux-kernel@vger.kernel.org24388L: linux-kernel@vger.kernel.org
arch/x86/Kconfig+0−4
@@ -472,10 +472,6 @@ config X86_MPPARSE · 471 unmodified lines
472 For old smp systems that do not have proper acpi support. Newer systems472 For old smp systems that do not have proper acpi support. Newer systems
473 (esp with 64bit cpus) with acpi support, MADT and DSDT will override it473 (esp with 64bit cpus) with acpi support, MADT and DSDT will override it
474 474
475config GOLDFISH
476 def_bool y
477 depends on X86_GOLDFISH
478
479config X86_CPU_RESCTRL475config X86_CPU_RESCTRL
480 bool "x86 CPU resource control support"476 bool "x86 CPU resource control support"
481 depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)477 depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
drivers/accessibility/speakup/devsynth.c+134−15
@@ -7,9 +7,10 @@ · 6 unmodified lines
7#include "speakup.h"7#include "speakup.h"
8#include "spk_priv.h"8#include "spk_priv.h"
9 9
10static int misc_registered;10static int synth_registered, synthu_registered;
11static int dev_opened;11static int dev_opened;
12 12
13/* Latin1 version */
13static ssize_t speakup_file_write(struct file *fp, const char __user *buffer,14static ssize_t speakup_file_write(struct file *fp, const char __user *buffer,
14 size_t nbytes, loff_t *ppos)15 size_t nbytes, loff_t *ppos)
15{16{
@@ -34,6 +35,98 @@ static ssize_t speakup_file_write(struct file *fp, const char __user *buffer, · 18 unmodified lines
34 return (ssize_t)nbytes;35 return (ssize_t)nbytes;
35}36}
36 37
38/* UTF-8 version */
39static ssize_t speakup_file_writeu(struct file *fp, const char __user *buffer,
40 size_t nbytes, loff_t *ppos)
41{
42 size_t count = nbytes, want;
43 const char __user *ptr = buffer;
44 size_t bytes;
45 unsigned long flags;
46 unsigned char buf[256];
47 u16 ubuf[256];
48 size_t in, in2, out;
49
50 if (!synth)
51 return -ENODEV;
52
53 want = 1;
54 while (count >= want) {
55 /* Copy some UTF-8 piece from userland */
56 bytes = min(count, sizeof(buf));
57 if (copy_from_user(buf, ptr, bytes))
58 return -EFAULT;
59
60 /* Convert to u16 */
61 for (in = 0, out = 0; in < bytes; in++) {
62 unsigned char c = buf[in];
63 int nbytes = 8 - fls(c ^ 0xff);
64 u32 value;
65
66 switch (nbytes) {
67 case 8: /* 0xff */
68 case 7: /* 0xfe */
69 case 1: /* 0x80 */
70 /* Invalid, drop */
71 goto drop;
72
73 case 0:
74 /* ASCII, copy */
75 ubuf[out++] = c;
76 continue;
77
78 default:
79 /* 2..6-byte UTF-8 */
80
81 if (bytes - in < nbytes) {
82 /* We don't have it all yet, stop here
83 * and wait for the rest
84 */
85 bytes = in;
86 want = nbytes;
87 continue;
88 }
89
90 /* First byte */
91 value = c & ((1u << (7 - nbytes)) - 1);
92
93 /* Other bytes */
94 for (in2 = 2; in2 <= nbytes; in2++) {
95 c = buf[in + 1];
96 if ((c & 0xc0) != 0x80) {
97 /* Invalid, drop the head */
98 want = 1;
99 goto drop;
100 }
101 value = (value << 6) | (c & 0x3f);
102 in++;
103 }
104
105 if (value < 0x10000)
106 ubuf[out++] = value;
107 want = 1;
108 break;
109 }
110drop:
111 /* empty statement */;
112 }
113
114 count -= bytes;
115 ptr += bytes;
116
117 /* And speak this up */
118 if (out) {
119 spin_lock_irqsave(&speakup_info.spinlock, flags);
120 for (in = 0; in < out; in++)
121 synth_buffer_add(ubuf[in]);
122 synth_start();
123 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
124 }
125 }
126
127 return (ssize_t)(nbytes - count);
128}
129
37static ssize_t speakup_file_read(struct file *fp, char __user *buf,130static ssize_t speakup_file_read(struct file *fp, char __user *buf,
38 size_t nbytes, loff_t *ppos)131 size_t nbytes, loff_t *ppos)
39{132{
@@ -62,31 +155,57 @@ static const struct file_operations synth_fops = { · 22 unmodified lines
62 .release = speakup_file_release,155 .release = speakup_file_release,
63};156};
64 157
158static const struct file_operations synthu_fops = {
159 .read = speakup_file_read,
160 .write = speakup_file_writeu,
161 .open = speakup_file_open,
162 .release = speakup_file_release,
163};
164
65static struct miscdevice synth_device = {165static struct miscdevice synth_device = {
66 .minor = MISC_DYNAMIC_MINOR,166 .minor = MISC_DYNAMIC_MINOR,
67 .name = "synth",167 .name = "synth",
68 .fops = &synth_fops,168 .fops = &synth_fops,
69};169};
70 170
171static struct miscdevice synthu_device = {
172 .minor = MISC_DYNAMIC_MINOR,
173 .name = "synthu",
174 .fops = &synthu_fops,
175};
176
71void speakup_register_devsynth(void)177void speakup_register_devsynth(void)
72{178{
73 if (misc_registered != 0)179 if (!synth_registered) {
74 return;180 if (misc_register(&synth_device)) {
75/* zero it so if register fails, deregister will not ref invalid ptrs */181 pr_warn("Couldn't initialize miscdevice /dev/synth.\n");
76 if (misc_register(&synth_device)) {182 } else {
77 pr_warn("Couldn't initialize miscdevice /dev/synth.\n");183 pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n",
78 } else {184 MISC_MAJOR, synth_device.minor);
79 pr_info("initialized device: /dev/synth, node (MAJOR %d, MINOR %d)\n",185 synth_registered = 1;
80 MISC_MAJOR, synth_device.minor);186 }
81 misc_registered = 1;187 }
188 if (!synthu_registered) {
189 if (misc_register(&synthu_device)) {
190 pr_warn("Couldn't initialize miscdevice /dev/synthu.\n");
191 } else {
192 pr_info("initialized device: /dev/synthu, node (MAJOR %d, MINOR %d)\n",
193 MISC_MAJOR, synthu_device.minor);
194 synthu_registered = 1;
195 }
82 }196 }
83}197}
84 198
85void speakup_unregister_devsynth(void)199void speakup_unregister_devsynth(void)
86{200{
87 if (!misc_registered)201 if (synth_registered) {
88 return;202 pr_info("speakup: unregistering synth device /dev/synth\n");
89 pr_info("speakup: unregistering synth device /dev/synth\n");203 misc_deregister(&synth_device);
90 misc_deregister(&synth_device);204 synth_registered = 0;
91 misc_registered = 0;205 }
206 if (synthu_registered) {
207 pr_info("speakup: unregistering synth device /dev/synthu\n");
208 misc_deregister(&synthu_device);
209 synthu_registered = 0;
210 }
92}211}
drivers/accessibility/speakup/synth.c+3−1
@@ -208,8 +208,10 @@ void spk_do_flush(void) · 207 unmodified lines
208 wake_up_process(speakup_task);208 wake_up_process(speakup_task);
209}209}
210 210
211void synth_write(const char *buf, size_t count)211void synth_write(const char *_buf, size_t count)
212{212{
213 const unsigned char *buf = (const unsigned char *) _buf;
214
213 while (count--)215 while (count--)
214 synth_buffer_add(*buf++);216 synth_buffer_add(*buf++);
215 synth_start();217 synth_start();
drivers/android/binder_alloc.c+0−2
@@ -925,7 +925,6 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) · 924 unmodified lines
925 int i;925 int i;
926 926
927 for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {927 for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
928 unsigned long page_addr;
929 bool on_lru;928 bool on_lru;
930 929
931 if (!alloc->pages[i].page_ptr)930 if (!alloc->pages[i].page_ptr)
@@ -933,7 +932,6 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) · 1 unmodified line
933 932
934 on_lru = list_lru_del_obj(&binder_freelist,933 on_lru = list_lru_del_obj(&binder_freelist,
935 &alloc->pages[i].lru);934 &alloc->pages[i].lru);
936 page_addr = alloc->buffer + i * PAGE_SIZE;
937 binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,935 binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
938 "%s: %d: page %d %s\n",936 "%s: %d: page %d %s\n",
939 __func__, alloc->pid, i,937 __func__, alloc->pid, i,
drivers/bus/mhi/common.h+19−19
@@ -297,30 +297,30 @@ struct mhi_ring_element { · 296 unmodified lines
297 __le32 dword[2];297 __le32 dword[2];
298};298};
299 299
300#define MHI_STATE_LIST \
301 mhi_state(RESET, "RESET") \
302 mhi_state(READY, "READY") \
303 mhi_state(M0, "M0") \
304 mhi_state(M1, "M1") \
305 mhi_state(M2, "M2") \
306 mhi_state(M3, "M3") \
307 mhi_state(M3_FAST, "M3_FAST") \
308 mhi_state(BHI, "BHI") \
309 mhi_state_end(SYS_ERR, "SYS ERROR")
310
311#undef mhi_state
312#undef mhi_state_end
313
314#define mhi_state(a, b) case MHI_STATE_##a: return b;
315#define mhi_state_end(a, b) case MHI_STATE_##a: return b;
316
300static inline const char *mhi_state_str(enum mhi_state state)317static inline const char *mhi_state_str(enum mhi_state state)
301{318{
302 switch (state) {319 switch (state) {
303 case MHI_STATE_RESET:320 MHI_STATE_LIST
304 return "RESET";
305 case MHI_STATE_READY:
306 return "READY";
307 case MHI_STATE_M0:
308 return "M0";
309 case MHI_STATE_M1:
310 return "M1";
311 case MHI_STATE_M2:
312 return "M2";
313 case MHI_STATE_M3:
314 return "M3";
315 case MHI_STATE_M3_FAST:
316 return "M3 FAST";
317 case MHI_STATE_BHI:
318 return "BHI";
319 case MHI_STATE_SYS_ERR:
320 return "SYS ERROR";
321 default:321 default:
322 return "Unknown state";322 return "Unknown state";
323 }323 }
324};324}
325 325
326#endif /* _MHI_COMMON_H */326#endif /* _MHI_COMMON_H */
drivers/bus/mhi/ep/main.c+4−3
@@ -1149,8 +1149,9 @@ int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl) · 1148 unmodified lines
1149 mhi_ep_mmio_mask_interrupts(mhi_cntrl);1149 mhi_ep_mmio_mask_interrupts(mhi_cntrl);
1150 mhi_ep_mmio_init(mhi_cntrl);1150 mhi_ep_mmio_init(mhi_cntrl);
1151 1151
1152 mhi_cntrl->mhi_event = kzalloc(mhi_cntrl->event_rings * (sizeof(*mhi_cntrl->mhi_event)),1152 mhi_cntrl->mhi_event = kcalloc(mhi_cntrl->event_rings,
1153 GFP_KERNEL);1153 sizeof(*mhi_cntrl->mhi_event),
1154 GFP_KERNEL);
1154 if (!mhi_cntrl->mhi_event)1155 if (!mhi_cntrl->mhi_event)
1155 return -ENOMEM;1156 return -ENOMEM;
1156 1157
@@ -1496,7 +1497,7 @@ int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl, · 339 unmodified lines
1496 mhi_cntrl->ring_item_cache = kmem_cache_create("mhi_ep_ring_item",1497 mhi_cntrl->ring_item_cache = kmem_cache_create("mhi_ep_ring_item",
1497 sizeof(struct mhi_ep_ring_item), 0,1498 sizeof(struct mhi_ep_ring_item), 0,
1498 0, NULL);1499 0, NULL);
1499 if (!mhi_cntrl->ev_ring_el_cache) {1500 if (!mhi_cntrl->ring_item_cache) {
1500 ret = -ENOMEM;1501 ret = -ENOMEM;
1501 goto err_destroy_tre_buf_cache;1502 goto err_destroy_tre_buf_cache;
1502 }1503 }
drivers/bus/mhi/host/boot.c+1−10
@@ -395,7 +395,7 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) · 394 unmodified lines
395 void *buf;395 void *buf;
396 dma_addr_t dma_addr;396 dma_addr_t dma_addr;
397 size_t size, fw_sz;397 size_t size, fw_sz;
398 int i, ret;398 int ret;
399 399
400 if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {400 if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) {
401 dev_err(dev, "Device MHI is not in valid state\n");401 dev_err(dev, "Device MHI is not in valid state\n");
@@ -408,15 +408,6 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) · 6 unmodified lines
408 if (ret)408 if (ret)
409 dev_err(dev, "Could not capture serial number via BHI\n");409 dev_err(dev, "Could not capture serial number via BHI\n");
410 410
411 for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++) {
412 ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i),
413 &mhi_cntrl->oem_pk_hash[i]);
414 if (ret) {
415 dev_err(dev, "Could not capture OEM PK HASH via BHI\n");
416 break;
417 }
418 }
419
420 /* wait for ready on pass through or any other execution environment */411 /* wait for ready on pass through or any other execution environment */
421 if (!MHI_FW_LOAD_CAPABLE(mhi_cntrl->ee))412 if (!MHI_FW_LOAD_CAPABLE(mhi_cntrl->ee))
422 goto fw_load_ready_state;413 goto fw_load_ready_state;
drivers/bus/mhi/host/init.c+43−48
@@ -20,50 +20,49 @@ · 19 unmodified lines
20#include <linux/wait.h>20#include <linux/wait.h>
21#include "internal.h"21#include "internal.h"
22 22
23#define CREATE_TRACE_POINTS
24#include "trace.h"
25
23static DEFINE_IDA(mhi_controller_ida);26static DEFINE_IDA(mhi_controller_ida);
24 27
28#undef mhi_ee
29#undef mhi_ee_end
30
31#define mhi_ee(a, b) [MHI_EE_##a] = b,
32#define mhi_ee_end(a, b) [MHI_EE_##a] = b,
33
25const char * const mhi_ee_str[MHI_EE_MAX] = {34const char * const mhi_ee_str[MHI_EE_MAX] = {
26 [MHI_EE_PBL] = "PRIMARY BOOTLOADER",35 MHI_EE_LIST
27 [MHI_EE_SBL] = "SECONDARY BOOTLOADER",
28 [MHI_EE_AMSS] = "MISSION MODE",
29 [MHI_EE_RDDM] = "RAMDUMP DOWNLOAD MODE",
30 [MHI_EE_WFW] = "WLAN FIRMWARE",
31 [MHI_EE_PTHRU] = "PASS THROUGH",
32 [MHI_EE_EDL] = "EMERGENCY DOWNLOAD",
33 [MHI_EE_FP] = "FLASH PROGRAMMER",
34 [MHI_EE_DISABLE_TRANSITION] = "DISABLE",
35 [MHI_EE_NOT_SUPPORTED] = "NOT SUPPORTED",
36};36};
37 37
38#undef dev_st_trans
39#undef dev_st_trans_end
40
41#define dev_st_trans(a, b) [DEV_ST_TRANSITION_##a] = b,
42#define dev_st_trans_end(a, b) [DEV_ST_TRANSITION_##a] = b,
43
38const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX] = {44const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX] = {
39 [DEV_ST_TRANSITION_PBL] = "PBL",45 DEV_ST_TRANSITION_LIST
40 [DEV_ST_TRANSITION_READY] = "READY",
41 [DEV_ST_TRANSITION_SBL] = "SBL",
42 [DEV_ST_TRANSITION_MISSION_MODE] = "MISSION MODE",
43 [DEV_ST_TRANSITION_FP] = "FLASH PROGRAMMER",
44 [DEV_ST_TRANSITION_SYS_ERR] = "SYS ERROR",
45 [DEV_ST_TRANSITION_DISABLE] = "DISABLE",
46};46};
47 47
48#undef ch_state_type
49#undef ch_state_type_end
50
51#define ch_state_type(a, b) [MHI_CH_STATE_TYPE_##a] = b,
52#define ch_state_type_end(a, b) [MHI_CH_STATE_TYPE_##a] = b,
53
48const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX] = {54const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX] = {
49 [MHI_CH_STATE_TYPE_RESET] = "RESET",55 MHI_CH_STATE_TYPE_LIST
50 [MHI_CH_STATE_TYPE_STOP] = "STOP",
51 [MHI_CH_STATE_TYPE_START] = "START",
52};56};
53 57
58#undef mhi_pm_state
59#undef mhi_pm_state_end
60
61#define mhi_pm_state(a, b) [MHI_PM_STATE_##a] = b,
62#define mhi_pm_state_end(a, b) [MHI_PM_STATE_##a] = b,
63
54static const char * const mhi_pm_state_str[] = {64static const char * const mhi_pm_state_str[] = {
55 [MHI_PM_STATE_DISABLE] = "DISABLE",65 MHI_PM_STATE_LIST
56 [MHI_PM_STATE_POR] = "POWER ON RESET",
57 [MHI_PM_STATE_M0] = "M0",
58 [MHI_PM_STATE_M2] = "M2",
59 [MHI_PM_STATE_M3_ENTER] = "M?->M3",
60 [MHI_PM_STATE_M3] = "M3",
61 [MHI_PM_STATE_M3_EXIT] = "M3->M0",
62 [MHI_PM_STATE_FW_DL_ERR] = "Firmware Download Error",
63 [MHI_PM_STATE_SYS_ERR_DETECT] = "SYS ERROR Detect",
64 [MHI_PM_STATE_SYS_ERR_PROCESS] = "SYS ERROR Process",
65 [MHI_PM_STATE_SHUTDOWN_PROCESS] = "SHUTDOWN Process",
66 [MHI_PM_STATE_LD_ERR_FATAL_DETECT] = "Linkdown or Error Fatal Detect",
67};66};
68 67
69const char *to_mhi_pm_state_str(u32 state)68const char *to_mhi_pm_state_str(u32 state)
@@ -97,11 +96,19 @@ static ssize_t oem_pk_hash_show(struct device *dev, · 27 unmodified lines
97{96{
98 struct mhi_device *mhi_dev = to_mhi_device(dev);97 struct mhi_device *mhi_dev = to_mhi_device(dev);
99 struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;98 struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
100 int i, cnt = 0;99 u32 hash_segment[MHI_MAX_OEM_PK_HASH_SEGMENTS];
100 int i, cnt = 0, ret;
101 101
102 for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++)102 for (i = 0; i < MHI_MAX_OEM_PK_HASH_SEGMENTS; i++) {
103 cnt += sysfs_emit_at(buf, cnt, "OEMPKHASH[%d]: 0x%x\n",103 ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i), &hash_segment[i]);
104 i, mhi_cntrl->oem_pk_hash[i]);104 if (ret) {
105 dev_err(dev, "Could not capture OEM PK HASH\n");
106 return ret;
107 }
108 }
109
110 for (i = 0; i < MHI_MAX_OEM_PK_HASH_SEGMENTS; i++)
111 cnt += sysfs_emit_at(buf, cnt, "OEMPKHASH[%d]: 0x%x\n", i, hash_segment[i]);
105 112
106 return cnt;113 return cnt;
107}114}
@@ -907,7 +914,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, · 799 unmodified lines
907 struct mhi_chan *mhi_chan;914 struct mhi_chan *mhi_chan;
908 struct mhi_cmd *mhi_cmd;915 struct mhi_cmd *mhi_cmd;
909 struct mhi_device *mhi_dev;916 struct mhi_device *mhi_dev;
910 u32 soc_info;
911 int ret, i;917 int ret, i;
912 918
913 if (!mhi_cntrl || !mhi_cntrl->cntrl_dev || !mhi_cntrl->regs ||919 if (!mhi_cntrl || !mhi_cntrl->cntrl_dev || !mhi_cntrl->regs ||
@@ -982,17 +988,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, · 68 unmodified lines
982 mhi_cntrl->unmap_single = mhi_unmap_single_no_bb;988 mhi_cntrl->unmap_single = mhi_unmap_single_no_bb;
983 }989 }
984 990
985 /* Read the MHI device info */
986 ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs,
987 SOC_HW_VERSION_OFFS, &soc_info);
988 if (ret)
989 goto err_destroy_wq;
990
991 mhi_cntrl->family_number = FIELD_GET(SOC_HW_VERSION_FAM_NUM_BMSK, soc_info);
992 mhi_cntrl->device_number = FIELD_GET(SOC_HW_VERSION_DEV_NUM_BMSK, soc_info);
993 mhi_cntrl->major_version = FIELD_GET(SOC_HW_VERSION_MAJOR_VER_BMSK, soc_info);
994 mhi_cntrl->minor_version = FIELD_GET(SOC_HW_VERSION_MINOR_VER_BMSK, soc_info);
995
996 mhi_cntrl->index = ida_alloc(&mhi_controller_ida, GFP_KERNEL);991 mhi_cntrl->index = ida_alloc(&mhi_controller_ida, GFP_KERNEL);
997 if (mhi_cntrl->index < 0) {992 if (mhi_cntrl->index < 0) {
998 ret = mhi_cntrl->index;993 ret = mhi_cntrl->index;
drivers/bus/mhi/host/internal.h+47−9
@@ -15,12 +15,6 @@ extern struct bus_type mhi_bus_type; · 14 unmodified lines
15#define MHI_SOC_RESET_REQ_OFFSET 0xb015#define MHI_SOC_RESET_REQ_OFFSET 0xb0
16#define MHI_SOC_RESET_REQ BIT(0)16#define MHI_SOC_RESET_REQ BIT(0)
17 17
18#define SOC_HW_VERSION_OFFS 0x224
19#define SOC_HW_VERSION_FAM_NUM_BMSK GENMASK(31, 28)
20#define SOC_HW_VERSION_DEV_NUM_BMSK GENMASK(27, 16)
21#define SOC_HW_VERSION_MAJOR_VER_BMSK GENMASK(15, 8)
22#define SOC_HW_VERSION_MINOR_VER_BMSK GENMASK(7, 0)
23
24struct mhi_ctxt {18struct mhi_ctxt {
25 struct mhi_event_ctxt *er_ctxt;19 struct mhi_event_ctxt *er_ctxt;
26 struct mhi_chan_ctxt *chan_ctxt;20 struct mhi_chan_ctxt *chan_ctxt;
@@ -42,6 +36,11 @@ enum mhi_ch_state_type { · 15 unmodified lines
42 MHI_CH_STATE_TYPE_MAX,36 MHI_CH_STATE_TYPE_MAX,
43};37};
44 38
39#define MHI_CH_STATE_TYPE_LIST \
40 ch_state_type(RESET, "RESET") \
41 ch_state_type(STOP, "STOP") \
42 ch_state_type_end(START, "START")
43
45extern const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX];44extern const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX];
46#define TO_CH_STATE_TYPE_STR(state) (((state) >= MHI_CH_STATE_TYPE_MAX) ? \45#define TO_CH_STATE_TYPE_STR(state) (((state) >= MHI_CH_STATE_TYPE_MAX) ? \
47 "INVALID_STATE" : \46 "INVALID_STATE" : \
@@ -50,6 +49,18 @@ extern const char * const mhi_ch_state_type_str[MHI_CH_STATE_TYPE_MAX]; · 2 unmodified lines
50#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_DB_BRST_DISABLE && \49#define MHI_INVALID_BRSTMODE(mode) (mode != MHI_DB_BRST_DISABLE && \
51 mode != MHI_DB_BRST_ENABLE)50 mode != MHI_DB_BRST_ENABLE)
52 51
52#define MHI_EE_LIST \
53 mhi_ee(PBL, "PRIMARY BOOTLOADER") \
54 mhi_ee(SBL, "SECONDARY BOOTLOADER") \
55 mhi_ee(AMSS, "MISSION MODE") \
56 mhi_ee(RDDM, "RAMDUMP DOWNLOAD MODE")\
57 mhi_ee(WFW, "WLAN FIRMWARE") \
58 mhi_ee(PTHRU, "PASS THROUGH") \
59 mhi_ee(EDL, "EMERGENCY DOWNLOAD") \
60 mhi_ee(FP, "FLASH PROGRAMMER") \
61 mhi_ee(DISABLE_TRANSITION, "DISABLE") \
62 mhi_ee_end(NOT_SUPPORTED, "NOT SUPPORTED")
63
53extern const char * const mhi_ee_str[MHI_EE_MAX];64extern const char * const mhi_ee_str[MHI_EE_MAX];
54#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \65#define TO_MHI_EXEC_STR(ee) (((ee) >= MHI_EE_MAX) ? \
55 "INVALID_EE" : mhi_ee_str[ee])66 "INVALID_EE" : mhi_ee_str[ee])
@@ -72,6 +83,15 @@ enum dev_st_transition { · 16 unmodified lines
72 DEV_ST_TRANSITION_MAX,83 DEV_ST_TRANSITION_MAX,
73};84};
74 85
86#define DEV_ST_TRANSITION_LIST \
87 dev_st_trans(PBL, "PBL") \
88 dev_st_trans(READY, "READY") \
89 dev_st_trans(SBL, "SBL") \
90 dev_st_trans(MISSION_MODE, "MISSION MODE") \
91 dev_st_trans(FP, "FLASH PROGRAMMER") \
92 dev_st_trans(SYS_ERR, "SYS ERROR") \
93 dev_st_trans_end(DISABLE, "DISABLE")
94
75extern const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX];95extern const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX];
76#define TO_DEV_STATE_TRANS_STR(state) (((state) >= DEV_ST_TRANSITION_MAX) ? \96#define TO_DEV_STATE_TRANS_STR(state) (((state) >= DEV_ST_TRANSITION_MAX) ? \
77 "INVALID_STATE" : dev_state_tran_str[state])97 "INVALID_STATE" : dev_state_tran_str[state])
@@ -88,11 +108,27 @@ enum mhi_pm_state { · 10 unmodified lines
88 MHI_PM_STATE_FW_DL_ERR,108 MHI_PM_STATE_FW_DL_ERR,
89 MHI_PM_STATE_SYS_ERR_DETECT,109 MHI_PM_STATE_SYS_ERR_DETECT,
90 MHI_PM_STATE_SYS_ERR_PROCESS,110 MHI_PM_STATE_SYS_ERR_PROCESS,
111 MHI_PM_STATE_SYS_ERR_FAIL,
91 MHI_PM_STATE_SHUTDOWN_PROCESS,112 MHI_PM_STATE_SHUTDOWN_PROCESS,
92 MHI_PM_STATE_LD_ERR_FATAL_DETECT,113 MHI_PM_STATE_LD_ERR_FATAL_DETECT,
93 MHI_PM_STATE_MAX114 MHI_PM_STATE_MAX
94};115};
95 116
117#define MHI_PM_STATE_LIST \
118 mhi_pm_state(DISABLE, "DISABLE") \
119 mhi_pm_state(POR, "POWER ON RESET") \
120 mhi_pm_state(M0, "M0") \
121 mhi_pm_state(M2, "M2") \
122 mhi_pm_state(M3_ENTER, "M?->M3") \
123 mhi_pm_state(M3, "M3") \
124 mhi_pm_state(M3_EXIT, "M3->M0") \
125 mhi_pm_state(FW_DL_ERR, "Firmware Download Error") \
126 mhi_pm_state(SYS_ERR_DETECT, "SYS ERROR Detect") \
127 mhi_pm_state(SYS_ERR_PROCESS, "SYS ERROR Process") \
128 mhi_pm_state(SYS_ERR_FAIL, "SYS ERROR Failure") \
129 mhi_pm_state(SHUTDOWN_PROCESS, "SHUTDOWN Process") \
130 mhi_pm_state_end(LD_ERR_FATAL_DETECT, "Linkdown or Error Fatal Detect")
131
96#define MHI_PM_DISABLE BIT(0)132#define MHI_PM_DISABLE BIT(0)
97#define MHI_PM_POR BIT(1)133#define MHI_PM_POR BIT(1)
98#define MHI_PM_M0 BIT(2)134#define MHI_PM_M0 BIT(2)
@@ -104,14 +140,16 @@ enum mhi_pm_state { · 5 unmodified lines
104#define MHI_PM_FW_DL_ERR BIT(7)140#define MHI_PM_FW_DL_ERR BIT(7)
105#define MHI_PM_SYS_ERR_DETECT BIT(8)141#define MHI_PM_SYS_ERR_DETECT BIT(8)
106#define MHI_PM_SYS_ERR_PROCESS BIT(9)142#define MHI_PM_SYS_ERR_PROCESS BIT(9)
107#define MHI_PM_SHUTDOWN_PROCESS BIT(10)143#define MHI_PM_SYS_ERR_FAIL BIT(10)
144#define MHI_PM_SHUTDOWN_PROCESS BIT(11)
108/* link not accessible */145/* link not accessible */
109#define MHI_PM_LD_ERR_FATAL_DETECT BIT(11)146#define MHI_PM_LD_ERR_FATAL_DETECT BIT(12)
110 147
111#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \148#define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \
112 MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \149 MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
113 MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \150 MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \
114 MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR)))151 MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS | \
152 MHI_PM_FW_DL_ERR)))
115#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)153#define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)
116#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT)154#define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT)
117#define MHI_DB_ACCESS_VALID(mhi_cntrl) (mhi_cntrl->pm_state & mhi_cntrl->db_access)155#define MHI_DB_ACCESS_VALID(mhi_cntrl) (mhi_cntrl->pm_state & mhi_cntrl->db_access)
drivers/bus/mhi/host/main.c+9−10
@@ -15,6 +15,7 @@ · 14 unmodified lines
15#include <linux/skbuff.h>15#include <linux/skbuff.h>
16#include <linux/slab.h>16#include <linux/slab.h>
17#include "internal.h"17#include "internal.h"
18#include "trace.h"
18 19
19int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,20int __must_check mhi_read_reg(struct mhi_controller *mhi_cntrl,
20 void __iomem *base, u32 offset, u32 *out)21 void __iomem *base, u32 offset, u32 *out)
@@ -493,11 +494,8 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *priv) · 472 unmodified lines
493 494
494 state = mhi_get_mhi_state(mhi_cntrl);495 state = mhi_get_mhi_state(mhi_cntrl);
495 ee = mhi_get_exec_env(mhi_cntrl);496 ee = mhi_get_exec_env(mhi_cntrl);
496 dev_dbg(dev, "local ee: %s state: %s device ee: %s state: %s\n",
497 TO_MHI_EXEC_STR(mhi_cntrl->ee),
498 mhi_state_str(mhi_cntrl->dev_state),
499 TO_MHI_EXEC_STR(ee), mhi_state_str(state));
500 497
498 trace_mhi_intvec_states(mhi_cntrl, ee, state);
501 if (state == MHI_STATE_SYS_ERR) {499 if (state == MHI_STATE_SYS_ERR) {
502 dev_dbg(dev, "System error detected\n");500 dev_dbg(dev, "System error detected\n");
503 pm_state = mhi_tryset_pm_state(mhi_cntrl,501 pm_state = mhi_tryset_pm_state(mhi_cntrl,
@@ -838,6 +836,8 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, · 334 unmodified lines
838 while (dev_rp != local_rp) {836 while (dev_rp != local_rp) {
839 enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);837 enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);
840 838
839 trace_mhi_ctrl_event(mhi_cntrl, local_rp);
840
841 switch (type) {841 switch (type) {
842 case MHI_PKT_TYPE_BW_REQ_EVENT:842 case MHI_PKT_TYPE_BW_REQ_EVENT:
843 {843 {
@@ -1003,6 +1003,8 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl, · 159 unmodified lines
1003 while (dev_rp != local_rp && event_quota > 0) {1003 while (dev_rp != local_rp && event_quota > 0) {
1004 enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);1004 enum mhi_pkt_type type = MHI_TRE_GET_EV_TYPE(local_rp);
1005 1005
1006 trace_mhi_data_event(mhi_cntrl, local_rp);
1007
1006 chan = MHI_TRE_GET_EV_CHID(local_rp);1008 chan = MHI_TRE_GET_EV_CHID(local_rp);
1007 1009
1008 WARN_ON(chan >= mhi_cntrl->max_chan);1010 WARN_ON(chan >= mhi_cntrl->max_chan);
@@ -1243,6 +1245,7 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, · 234 unmodified lines
1243 mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);1245 mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
1244 mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain);1246 mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain);
1245 1247
1248 trace_mhi_gen_tre(mhi_cntrl, mhi_chan, mhi_tre);
1246 /* increment WP */1249 /* increment WP */
1247 mhi_add_ring_element(mhi_cntrl, tre_ring);1250 mhi_add_ring_element(mhi_cntrl, tre_ring);
1248 mhi_add_ring_element(mhi_cntrl, buf_ring);1251 mhi_add_ring_element(mhi_cntrl, buf_ring);
@@ -1337,9 +1340,7 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl, · 88 unmodified lines
1337 enum mhi_cmd_type cmd = MHI_CMD_NOP;1340 enum mhi_cmd_type cmd = MHI_CMD_NOP;
1338 int ret;1341 int ret;
1339 1342
1340 dev_dbg(dev, "%d: Updating channel state to: %s\n", mhi_chan->chan,1343 trace_mhi_channel_command_start(mhi_cntrl, mhi_chan, to_state, TPS("Updating"));
1341 TO_CH_STATE_TYPE_STR(to_state));
1342
1343 switch (to_state) {1344 switch (to_state) {
1344 case MHI_CH_STATE_TYPE_RESET:1345 case MHI_CH_STATE_TYPE_RESET:
1345 write_lock_irq(&mhi_chan->lock);1346 write_lock_irq(&mhi_chan->lock);
@@ -1406,9 +1407,7 @@ static int mhi_update_channel_state(struct mhi_controller *mhi_cntrl, · 60 unmodified lines
1406 write_unlock_irq(&mhi_chan->lock);1407 write_unlock_irq(&mhi_chan->lock);
1407 }1408 }
1408 1409
1409 dev_dbg(dev, "%d: Channel state change to %s successful\n",1410 trace_mhi_channel_command_end(mhi_cntrl, mhi_chan, to_state, TPS("Updated"));
1410 mhi_chan->chan, TO_CH_STATE_TYPE_STR(to_state));
1411
1412exit_channel_update:1411exit_channel_update:
1413 mhi_cntrl->runtime_put(mhi_cntrl);1412 mhi_cntrl->runtime_put(mhi_cntrl);
1414 mhi_device_put(mhi_cntrl->mhi_dev);1413 mhi_device_put(mhi_cntrl->mhi_dev);
drivers/bus/mhi/host/pci_generic.c+1−1
@@ -538,7 +538,7 @@ static struct mhi_event_config mhi_telit_fn980_hw_v1_events[] = { · 537 unmodified lines
538 MHI_EVENT_CONFIG_HW_DATA(2, 2048, 101)538 MHI_EVENT_CONFIG_HW_DATA(2, 2048, 101)
539};539};
540 540
541static struct mhi_controller_config modem_telit_fn980_hw_v1_config = {541static const struct mhi_controller_config modem_telit_fn980_hw_v1_config = {
542 .max_channels = 128,542 .max_channels = 128,
543 .timeout_ms = 20000,543 .timeout_ms = 20000,
544 .num_channels = ARRAY_SIZE(mhi_telit_fn980_hw_v1_channels),544 .num_channels = ARRAY_SIZE(mhi_telit_fn980_hw_v1_channels),
drivers/bus/mhi/host/pm.c+21−6
@@ -15,6 +15,7 @@ · 14 unmodified lines
15#include <linux/slab.h>15#include <linux/slab.h>
16#include <linux/wait.h>16#include <linux/wait.h>
17#include "internal.h"17#include "internal.h"
18#include "trace.h"
18 19
19/*20/*
20 * Not all MHI state transitions are synchronous. Transitions like Linkdown,21 * Not all MHI state transitions are synchronous. Transitions like Linkdown,
@@ -36,7 +37,10 @@ · 15 unmodified lines
36 * M0 <--> M037 * M0 <--> M0
37 * M0 -> FW_DL_ERR38 * M0 -> FW_DL_ERR
38 * M0 -> M3_ENTER -> M3 -> M3_EXIT --> M039 * M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0
39 * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR40 * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS
41 * SYS_ERR_PROCESS -> SYS_ERR_FAIL
42 * SYS_ERR_FAIL -> SYS_ERR_DETECT
43 * SYS_ERR_PROCESS --> POR
40 * L2: SHUTDOWN_PROCESS -> LD_ERR_FATAL_DETECT44 * L2: SHUTDOWN_PROCESS -> LD_ERR_FATAL_DETECT
41 * SHUTDOWN_PROCESS -> DISABLE45 * SHUTDOWN_PROCESS -> DISABLE
42 * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT46 * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT
@@ -93,7 +97,12 @@ static const struct mhi_pm_transitions dev_state_transitions[] = { · 50 unmodified lines
93 },97 },
94 {98 {
95 MHI_PM_SYS_ERR_PROCESS,99 MHI_PM_SYS_ERR_PROCESS,
96 MHI_PM_POR | MHI_PM_SHUTDOWN_PROCESS |100 MHI_PM_POR | MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS |
101 MHI_PM_LD_ERR_FATAL_DETECT
102 },
103 {
104 MHI_PM_SYS_ERR_FAIL,
105 MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS |
97 MHI_PM_LD_ERR_FATAL_DETECT106 MHI_PM_LD_ERR_FATAL_DETECT
98 },107 },
99 /* L2 States */108 /* L2 States */
@@ -123,6 +132,7 @@ enum mhi_pm_state __must_check mhi_tryset_pm_state(struct mhi_controller *mhi_cn · 23 unmodified lines
123 if (unlikely(!(dev_state_transitions[index].to_states & state)))132 if (unlikely(!(dev_state_transitions[index].to_states & state)))
124 return cur_state;133 return cur_state;
125 134
135 trace_mhi_tryset_pm_state(mhi_cntrl, state);
126 mhi_cntrl->pm_state = state;136 mhi_cntrl->pm_state = state;
127 return mhi_cntrl->pm_state;137 return mhi_cntrl->pm_state;
128}138}
@@ -629,7 +639,13 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl) · 500 unmodified lines
629 !in_reset, timeout);639 !in_reset, timeout);
630 if (!ret || in_reset) {640 if (!ret || in_reset) {
631 dev_err(dev, "Device failed to exit MHI Reset state\n");641 dev_err(dev, "Device failed to exit MHI Reset state\n");
632 goto exit_sys_error_transition;642 write_lock_irq(&mhi_cntrl->pm_lock);
643 cur_state = mhi_tryset_pm_state(mhi_cntrl,
644 MHI_PM_SYS_ERR_FAIL);
645 write_unlock_irq(&mhi_cntrl->pm_lock);
646 /* Shutdown may have occurred, otherwise cleanup now */
647 if (cur_state != MHI_PM_SYS_ERR_FAIL)
648 goto exit_sys_error_transition;
633 }649 }
634 650
635 /*651 /*
@@ -758,7 +774,6 @@ void mhi_pm_st_worker(struct work_struct *work) · 122 unmodified lines
758 struct mhi_controller *mhi_cntrl = container_of(work,774 struct mhi_controller *mhi_cntrl = container_of(work,
759 struct mhi_controller,775 struct mhi_controller,
760 st_worker);776 st_worker);
761 struct device *dev = &mhi_cntrl->mhi_dev->dev;
762 777
763 spin_lock_irq(&mhi_cntrl->transition_lock);778 spin_lock_irq(&mhi_cntrl->transition_lock);
764 list_splice_tail_init(&mhi_cntrl->transition_list, &head);779 list_splice_tail_init(&mhi_cntrl->transition_list, &head);
@@ -766,8 +781,8 @@ void mhi_pm_st_worker(struct work_struct *work) · 1 unmodified line
766 781
767 list_for_each_entry_safe(itr, tmp, &head, node) {782 list_for_each_entry_safe(itr, tmp, &head, node) {
768 list_del(&itr->node);783 list_del(&itr->node);
769 dev_dbg(dev, "Handling state transition: %s\n",784
770 TO_DEV_STATE_TRANS_STR(itr->state));785 trace_mhi_pm_st_transition(mhi_cntrl, itr->state);
771 786
772 switch (itr->state) {787 switch (itr->state) {
773 case DEV_ST_TRANSITION_PBL:788 case DEV_ST_TRANSITION_PBL:
drivers/bus/mhi/host/trace.h+282−0
@@ -0,0 +1,282 @@
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 */
5
6#undef TRACE_SYSTEM
7#define TRACE_SYSTEM mhi_host
8
9#if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ)
10#define _TRACE_EVENT_MHI_HOST_H
11
12#include <linux/tracepoint.h>
13#include <linux/trace_seq.h>
14#include "../common.h"
15#include "internal.h"
16
17#undef mhi_state
18#undef mhi_state_end
19
20#define mhi_state(a, b) TRACE_DEFINE_ENUM(MHI_STATE_##a);
21#define mhi_state_end(a, b) TRACE_DEFINE_ENUM(MHI_STATE_##a);
22
23MHI_STATE_LIST
24
25#undef mhi_state
26#undef mhi_state_end
27
28#define mhi_state(a, b) { MHI_STATE_##a, b },
29#define mhi_state_end(a, b) { MHI_STATE_##a, b }
30
31#undef mhi_pm_state
32#undef mhi_pm_state_end
33
34#define mhi_pm_state(a, b) TRACE_DEFINE_ENUM(MHI_PM_STATE_##a);
35#define mhi_pm_state_end(a, b) TRACE_DEFINE_ENUM(MHI_PM_STATE_##a);
36
37MHI_PM_STATE_LIST
38
39#undef mhi_pm_state
40#undef mhi_pm_state_end
41
42#define mhi_pm_state(a, b) { MHI_PM_STATE_##a, b },
43#define mhi_pm_state_end(a, b) { MHI_PM_STATE_##a, b }
44
45#undef mhi_ee
46#undef mhi_ee_end
47
48#define mhi_ee(a, b) TRACE_DEFINE_ENUM(MHI_EE_##a);
49#define mhi_ee_end(a, b) TRACE_DEFINE_ENUM(MHI_EE_##a);
50
51MHI_EE_LIST
52
53#undef mhi_ee
54#undef mhi_ee_end
55
56#define mhi_ee(a, b) { MHI_EE_##a, b },
57#define mhi_ee_end(a, b) { MHI_EE_##a, b }
58
59#undef ch_state_type
60#undef ch_state_type_end
61
62#define ch_state_type(a, b) TRACE_DEFINE_ENUM(MHI_CH_STATE_TYPE_##a);
63#define ch_state_type_end(a, b) TRACE_DEFINE_ENUM(MHI_CH_STATE_TYPE_##a);
64
65MHI_CH_STATE_TYPE_LIST
66
67#undef ch_state_type
68#undef ch_state_type_end
69
70#define ch_state_type(a, b) { MHI_CH_STATE_TYPE_##a, b },
71#define ch_state_type_end(a, b) { MHI_CH_STATE_TYPE_##a, b }
72
73#undef dev_st_trans
74#undef dev_st_trans_end
75
76#define dev_st_trans(a, b) TRACE_DEFINE_ENUM(DEV_ST_TRANSITION_##a);
77#define dev_st_trans_end(a, b) TRACE_DEFINE_ENUM(DEV_ST_TRANSITION_##a);
78
79DEV_ST_TRANSITION_LIST
80
81#undef dev_st_trans
82#undef dev_st_trans_end
83
84#define dev_st_trans(a, b) { DEV_ST_TRANSITION_##a, b },
85#define dev_st_trans_end(a, b) { DEV_ST_TRANSITION_##a, b }
86
87#define TPS(x) tracepoint_string(x)
88
89TRACE_EVENT(mhi_gen_tre,
90
91 TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
92 struct mhi_ring_element *mhi_tre),
93
94 TP_ARGS(mhi_cntrl, mhi_chan, mhi_tre),
95
96 TP_STRUCT__entry(
97 __string(name, mhi_cntrl->mhi_dev->name)
98 __field(int, ch_num)
99 __field(void *, wp)
100 __field(__le64, tre_ptr)
101 __field(__le32, dword0)
102 __field(__le32, dword1)
103 ),
104
105 TP_fast_assign(
106 __assign_str(name, mhi_cntrl->mhi_dev->name);
107 __entry->ch_num = mhi_chan->chan;
108 __entry->wp = mhi_tre;
109 __entry->tre_ptr = mhi_tre->ptr;
110 __entry->dword0 = mhi_tre->dword[0];
111 __entry->dword1 = mhi_tre->dword[1];
112 ),
113
114 TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n",
115 __get_str(name), __entry->ch_num, __entry->wp, __entry->tre_ptr,
116 __entry->dword0, __entry->dword1)
117);
118
119TRACE_EVENT(mhi_intvec_states,
120
121 TP_PROTO(struct mhi_controller *mhi_cntrl, int dev_ee, int dev_state),
122
123 TP_ARGS(mhi_cntrl, dev_ee, dev_state),
124
125 TP_STRUCT__entry(
126 __string(name, mhi_cntrl->mhi_dev->name)
127 __field(int, local_ee)
128 __field(int, state)
129 __field(int, dev_ee)
130 __field(int, dev_state)
131 ),
132
133 TP_fast_assign(
134 __assign_str(name, mhi_cntrl->mhi_dev->name);
135 __entry->local_ee = mhi_cntrl->ee;
136 __entry->state = mhi_cntrl->dev_state;
137 __entry->dev_ee = dev_ee;
138 __entry->dev_state = dev_state;
139 ),
140
141 TP_printk("%s: Local EE: %s State: %s Device EE: %s Dev State: %s\n",
142 __get_str(name),
143 __print_symbolic(__entry->local_ee, MHI_EE_LIST),
144 __print_symbolic(__entry->state, MHI_STATE_LIST),
145 __print_symbolic(__entry->dev_ee, MHI_EE_LIST),
146 __print_symbolic(__entry->dev_state, MHI_STATE_LIST))
147);
148
149TRACE_EVENT(mhi_tryset_pm_state,
150
151 TP_PROTO(struct mhi_controller *mhi_cntrl, int pm_state),
152
153 TP_ARGS(mhi_cntrl, pm_state),
154
155 TP_STRUCT__entry(
156 __string(name, mhi_cntrl->mhi_dev->name)
157 __field(int, pm_state)
158 ),
159
160 TP_fast_assign(
161 __assign_str(name, mhi_cntrl->mhi_dev->name);
162 if (pm_state)
163 pm_state = __fls(pm_state);
164 __entry->pm_state = pm_state;
165 ),
166
167 TP_printk("%s: PM state: %s\n", __get_str(name),
168 __print_symbolic(__entry->pm_state, MHI_PM_STATE_LIST))
169);
170
171DECLARE_EVENT_CLASS(mhi_process_event_ring,
172
173 TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
174
175 TP_ARGS(mhi_cntrl, rp),
176
177 TP_STRUCT__entry(
178 __string(name, mhi_cntrl->mhi_dev->name)
179 __field(__le32, dword0)
180 __field(__le32, dword1)
181 __field(int, state)
182 __field(__le64, ptr)
183 __field(void *, rp)
184 ),
185
186 TP_fast_assign(
187 __assign_str(name, mhi_cntrl->mhi_dev->name);
188 __entry->rp = rp;
189 __entry->ptr = rp->ptr;
190 __entry->dword0 = rp->dword[0];
191 __entry->dword1 = rp->dword[1];
192 __entry->state = MHI_TRE_GET_EV_STATE(rp);
193 ),
194
195 TP_printk("%s: TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x State: %s\n",
196 __get_str(name), __entry->rp, __entry->ptr, __entry->dword0,
197 __entry->dword1, __print_symbolic(__entry->state, MHI_STATE_LIST))
198);
199
200DEFINE_EVENT(mhi_process_event_ring, mhi_data_event,
201
202 TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
203
204 TP_ARGS(mhi_cntrl, rp)
205);
206
207DEFINE_EVENT(mhi_process_event_ring, mhi_ctrl_event,
208
209 TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_ring_element *rp),
210
211 TP_ARGS(mhi_cntrl, rp)
212);
213
214DECLARE_EVENT_CLASS(mhi_update_channel_state,
215
216 TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
217 const char *reason),
218
219 TP_ARGS(mhi_cntrl, mhi_chan, state, reason),
220
221 TP_STRUCT__entry(
222 __string(name, mhi_cntrl->mhi_dev->name)
223 __field(int, ch_num)
224 __field(int, state)
225 __field(const char *, reason)
226 ),
227
228 TP_fast_assign(
229 __assign_str(name, mhi_cntrl->mhi_dev->name);
230 __entry->ch_num = mhi_chan->chan;
231 __entry->state = state;
232 __entry->reason = reason;
233 ),
234
235 TP_printk("%s: chan%d: %s state to: %s\n",
236 __get_str(name), __entry->ch_num, __entry->reason,
237 __print_symbolic(__entry->state, MHI_CH_STATE_TYPE_LIST))
238);
239
240DEFINE_EVENT(mhi_update_channel_state, mhi_channel_command_start,
241
242 TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
243 const char *reason),
244
245 TP_ARGS(mhi_cntrl, mhi_chan, state, reason)
246);
247
248DEFINE_EVENT(mhi_update_channel_state, mhi_channel_command_end,
249
250 TP_PROTO(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan, int state,
251 const char *reason),
252
253 TP_ARGS(mhi_cntrl, mhi_chan, state, reason)
254);
255
256TRACE_EVENT(mhi_pm_st_transition,
257
258 TP_PROTO(struct mhi_controller *mhi_cntrl, int state),
259
260 TP_ARGS(mhi_cntrl, state),
261
262 TP_STRUCT__entry(
263 __string(name, mhi_cntrl->mhi_dev->name)
264 __field(int, state)
265 ),
266
267 TP_fast_assign(
268 __assign_str(name, mhi_cntrl->mhi_dev->name);
269 __entry->state = state;
270 ),
271
272 TP_printk("%s: Handling state transition: %s\n", __get_str(name),
273 __print_symbolic(__entry->state, DEV_ST_TRANSITION_LIST))
274);
275
276#endif
277#undef TRACE_INCLUDE_PATH
278#define TRACE_INCLUDE_PATH ../../drivers/bus/mhi/host
279#undef TRACE_INCLUDE_FILE
280#define TRACE_INCLUDE_FILE trace
281
282#include <trace/define_trace.h>
drivers/cdx/Makefile+4−0
@@ -8,3 +8,7 @@ · 7 unmodified lines
8ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=CDX_BUS8ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=CDX_BUS
9 9
10obj-$(CONFIG_CDX_BUS) += cdx.o controller/10obj-$(CONFIG_CDX_BUS) += cdx.o controller/
11
12ifdef CONFIG_GENERIC_MSI_IRQ
13obj-$(CONFIG_CDX_BUS) += cdx_msi.o
14endif
drivers/cdx/cdx.c+20−0
@@ -56,6 +56,7 @@ · 55 unmodified lines
56 */56 */
57 57
58#include <linux/init.h>58#include <linux/init.h>
59#include <linux/irqdomain.h>
59#include <linux/kernel.h>60#include <linux/kernel.h>
60#include <linux/of.h>61#include <linux/of.h>
61#include <linux/of_device.h>62#include <linux/of_device.h>
@@ -302,8 +303,19 @@ static int cdx_probe(struct device *dev) · 240 unmodified lines
302{303{
303 struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);304 struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
304 struct cdx_device *cdx_dev = to_cdx_device(dev);305 struct cdx_device *cdx_dev = to_cdx_device(dev);
306 struct cdx_controller *cdx = cdx_dev->cdx;
305 int error;307 int error;
306 308
309 /*
310 * Setup MSI device data so that generic MSI alloc/free can
311 * be used by the device driver.
312 */
313 if (cdx->msi_domain) {
314 error = msi_setup_device_data(&cdx_dev->dev);
315 if (error)
316 return error;
317 }
318
307 error = cdx_drv->probe(cdx_dev);319 error = cdx_drv->probe(cdx_dev);
308 if (error) {320 if (error) {
309 dev_err_probe(dev, error, "%s failed\n", __func__);321 dev_err_probe(dev, error, "%s failed\n", __func__);
@@ -787,6 +799,7 @@ int cdx_device_add(struct cdx_dev_params *dev_params) · 477 unmodified lines
787 799
788 /* Populate CDX dev params */800 /* Populate CDX dev params */
789 cdx_dev->req_id = dev_params->req_id;801 cdx_dev->req_id = dev_params->req_id;
802 cdx_dev->msi_dev_id = dev_params->msi_dev_id;
790 cdx_dev->vendor = dev_params->vendor;803 cdx_dev->vendor = dev_params->vendor;
791 cdx_dev->device = dev_params->device;804 cdx_dev->device = dev_params->device;
792 cdx_dev->subsystem_vendor = dev_params->subsys_vendor;805 cdx_dev->subsystem_vendor = dev_params->subsys_vendor;
@@ -804,12 +817,19 @@ int cdx_device_add(struct cdx_dev_params *dev_params) · 11 unmodified lines
804 cdx_dev->dev.bus = &cdx_bus_type;817 cdx_dev->dev.bus = &cdx_bus_type;
805 cdx_dev->dev.dma_mask = &cdx_dev->dma_mask;818 cdx_dev->dev.dma_mask = &cdx_dev->dma_mask;
806 cdx_dev->dev.release = cdx_device_release;819 cdx_dev->dev.release = cdx_device_release;
820 cdx_dev->msi_write_pending = false;
821 mutex_init(&cdx_dev->irqchip_lock);
807 822
808 /* Set Name */823 /* Set Name */
809 dev_set_name(&cdx_dev->dev, "cdx-%02x:%02x",824 dev_set_name(&cdx_dev->dev, "cdx-%02x:%02x",
810 ((cdx->id << CDX_CONTROLLER_ID_SHIFT) | (cdx_dev->bus_num & CDX_BUS_NUM_MASK)),825 ((cdx->id << CDX_CONTROLLER_ID_SHIFT) | (cdx_dev->bus_num & CDX_BUS_NUM_MASK)),
811 cdx_dev->dev_num);826 cdx_dev->dev_num);
812 827
828 if (cdx->msi_domain) {
829 cdx_dev->num_msi = dev_params->num_msi;
830 dev_set_msi_domain(&cdx_dev->dev, cdx->msi_domain);
831 }
832
813 ret = device_add(&cdx_dev->dev);833 ret = device_add(&cdx_dev->dev);
814 if (ret) {834 if (ret) {
815 dev_err(&cdx_dev->dev,835 dev_err(&cdx_dev->dev,
drivers/cdx/cdx.h+12−0
@@ -25,6 +25,8 @@ · 24 unmodified lines
25 * @req_id: Requestor ID associated with CDX device25 * @req_id: Requestor ID associated with CDX device
26 * @class: Class of the CDX Device26 * @class: Class of the CDX Device
27 * @revision: Revision of the CDX device27 * @revision: Revision of the CDX device
28 * @msi_dev_id: MSI device ID associated with CDX device
29 * @num_msi: Number of MSI's supported by the device
28 */30 */
29struct cdx_dev_params {31struct cdx_dev_params {
30 struct cdx_controller *cdx;32 struct cdx_controller *cdx;
@@ -40,6 +42,8 @@ struct cdx_dev_params { · 9 unmodified lines
40 u32 req_id;42 u32 req_id;
41 u32 class;43 u32 class;
42 u8 revision;44 u8 revision;
45 u32 msi_dev_id;
46 u32 num_msi;
43};47};
44 48
45/**49/**
@@ -79,4 +83,12 @@ int cdx_device_add(struct cdx_dev_params *dev_params); · 33 unmodified lines
79 */83 */
80struct device *cdx_bus_add(struct cdx_controller *cdx, u8 bus_num);84struct device *cdx_bus_add(struct cdx_controller *cdx, u8 bus_num);
81 85
86/**
87 * cdx_msi_domain_init - Init the CDX bus MSI domain.
88 * @dev: Device of the CDX bus controller
89 *
90 * Return: CDX MSI domain, NULL on failure
91 */
92struct irq_domain *cdx_msi_domain_init(struct device *dev);
93
82#endif /* _CDX_H_ */94#endif /* _CDX_H_ */
drivers/cdx/cdx_msi.c+192−0
@@ -0,0 +1,192 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * AMD CDX bus driver MSI support
4 *
5 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
6 */
7
8#include <linux/of.h>
9#include <linux/of_device.h>
10#include <linux/of_address.h>
11#include <linux/of_irq.h>
12#include <linux/irq.h>
13#include <linux/irqdomain.h>
14#include <linux/msi.h>
15#include <linux/cdx/cdx_bus.h>
16
17#include "cdx.h"
18
19static void cdx_msi_write_msg(struct irq_data *irq_data, struct msi_msg *msg)
20{
21 struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
22 struct cdx_device *cdx_dev = to_cdx_device(msi_desc->dev);
23
24 /* We would not operate on msg here rather we wait for irq_bus_sync_unlock()
25 * to be called from preemptible task context.
26 */
27 msi_desc->msg = *msg;
28 cdx_dev->msi_write_pending = true;
29}
30
31static void cdx_msi_write_irq_lock(struct irq_data *irq_data)
32{
33 struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
34 struct cdx_device *cdx_dev = to_cdx_device(msi_desc->dev);
35
36 mutex_lock(&cdx_dev->irqchip_lock);
37}
38
39static void cdx_msi_write_irq_unlock(struct irq_data *irq_data)
40{
41 struct msi_desc *msi_desc = irq_data_get_msi_desc(irq_data);
42 struct cdx_device *cdx_dev = to_cdx_device(msi_desc->dev);
43 struct cdx_controller *cdx = cdx_dev->cdx;
44 struct cdx_device_config dev_config;
45
46 if (!cdx_dev->msi_write_pending) {
47 mutex_unlock(&cdx_dev->irqchip_lock);
48 return;
49 }
50
51 cdx_dev->msi_write_pending = false;
52 mutex_unlock(&cdx_dev->irqchip_lock);
53
54 dev_config.msi.msi_index = msi_desc->msi_index;
55 dev_config.msi.data = msi_desc->msg.data;
56 dev_config.msi.addr = ((u64)(msi_desc->msg.address_hi) << 32) | msi_desc->msg.address_lo;
57
58 /*
59 * dev_configure() is a controller callback which can interact with
60 * Firmware or other entities, and can sleep, so invoke this function
61 * outside of the mutex held region.
62 */
63 dev_config.type = CDX_DEV_MSI_CONF;
64 if (cdx->ops->dev_configure)
65 cdx->ops->dev_configure(cdx, cdx_dev->bus_num, cdx_dev->dev_num, &dev_config);
66}
67
68int cdx_enable_msi(struct cdx_device *cdx_dev)
69{
70 struct cdx_controller *cdx = cdx_dev->cdx;
71 struct cdx_device_config dev_config;
72
73 dev_config.type = CDX_DEV_MSI_ENABLE;
74 dev_config.msi_enable = true;
75 if (cdx->ops->dev_configure) {
76 return cdx->ops->dev_configure(cdx, cdx_dev->bus_num, cdx_dev->dev_num,
77 &dev_config);
78 }
79
80 return -EOPNOTSUPP;
81}
82EXPORT_SYMBOL_GPL(cdx_enable_msi);
83
84void cdx_disable_msi(struct cdx_device *cdx_dev)
85{
86 struct cdx_controller *cdx = cdx_dev->cdx;
87 struct cdx_device_config dev_config;
88
89 dev_config.type = CDX_DEV_MSI_ENABLE;
90 dev_config.msi_enable = false;
91 if (cdx->ops->dev_configure)
92 cdx->ops->dev_configure(cdx, cdx_dev->bus_num, cdx_dev->dev_num, &dev_config);
93}
94EXPORT_SYMBOL_GPL(cdx_disable_msi);
95
96static struct irq_chip cdx_msi_irq_chip = {
97 .name = "CDX-MSI",
98 .irq_mask = irq_chip_mask_parent,
99 .irq_unmask = irq_chip_unmask_parent,
100 .irq_eoi = irq_chip_eoi_parent,
101 .irq_set_affinity = msi_domain_set_affinity,
102 .irq_write_msi_msg = cdx_msi_write_msg,
103 .irq_bus_lock = cdx_msi_write_irq_lock,
104 .irq_bus_sync_unlock = cdx_msi_write_irq_unlock
105};
106
107/* Convert an msi_desc to a unique identifier within the domain. */
108static irq_hw_number_t cdx_domain_calc_hwirq(struct cdx_device *dev,
109 struct msi_desc *desc)
110{
111 return ((irq_hw_number_t)dev->msi_dev_id << 10) | desc->msi_index;
112}
113
114static void cdx_msi_set_desc(msi_alloc_info_t *arg, struct msi_desc *desc)
115{
116 arg->desc = desc;
117 arg->hwirq = cdx_domain_calc_hwirq(to_cdx_device(desc->dev), desc);
118}
119
120static int cdx_msi_prepare(struct irq_domain *msi_domain,
121 struct device *dev,
122 int nvec, msi_alloc_info_t *info)
123{
124 struct cdx_device *cdx_dev = to_cdx_device(dev);
125 struct device *parent = cdx_dev->cdx->dev;
126 struct msi_domain_info *msi_info;
127 u32 dev_id;
128 int ret;
129
130 /* Retrieve device ID from requestor ID using parent device */
131 ret = of_map_id(parent->of_node, cdx_dev->msi_dev_id, "msi-map", "msi-map-mask",
132 NULL, &dev_id);
133 if (ret) {
134 dev_err(dev, "of_map_id failed for MSI: %d\n", ret);
135 return ret;
136 }
137
138#ifdef GENERIC_MSI_DOMAIN_OPS
139 /* Set the device Id to be passed to the GIC-ITS */
140 info->scratchpad[0].ul = dev_id;
141#endif
142
143 msi_info = msi_get_domain_info(msi_domain->parent);
144
145 return msi_info->ops->msi_prepare(msi_domain->parent, dev, nvec, info);
146}
147
148static struct msi_domain_ops cdx_msi_ops = {
149 .msi_prepare = cdx_msi_prepare,
150 .set_desc = cdx_msi_set_desc
151};
152
153static struct msi_domain_info cdx_msi_domain_info = {
154 .ops = &cdx_msi_ops,
155 .chip = &cdx_msi_irq_chip,
156 .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
157 MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS | MSI_FLAG_FREE_MSI_DESCS
158};
159
160struct irq_domain *cdx_msi_domain_init(struct device *dev)
161{
162 struct device_node *np = dev->of_node;
163 struct fwnode_handle *fwnode_handle;
164 struct irq_domain *cdx_msi_domain;
165 struct device_node *parent_node;
166 struct irq_domain *parent;
167
168 fwnode_handle = of_node_to_fwnode(np);
169
170 parent_node = of_parse_phandle(np, "msi-map", 1);
171 if (!parent_node) {
172 dev_err(dev, "msi-map not present on cdx controller\n");
173 return NULL;
174 }
175
176 parent = irq_find_matching_fwnode(of_node_to_fwnode(parent_node), DOMAIN_BUS_NEXUS);
177 if (!parent || !msi_get_domain_info(parent)) {
178 dev_err(dev, "unable to locate ITS domain\n");
179 return NULL;
180 }
181
182 cdx_msi_domain = msi_create_irq_domain(fwnode_handle, &cdx_msi_domain_info, parent);
183 if (!cdx_msi_domain) {
184 dev_err(dev, "unable to create CDX-MSI domain\n");
185 return NULL;
186 }
187
188 dev_dbg(dev, "CDX-MSI domain created\n");
189
190 return cdx_msi_domain;
191}
192EXPORT_SYMBOL_NS_GPL(cdx_msi_domain_init, CDX_BUS_CONTROLLER);
drivers/cdx/controller/Kconfig+1−0
@@ -9,6 +9,7 @@ if CDX_BUS · 8 unmodified lines
9 9
10config CDX_CONTROLLER10config CDX_CONTROLLER
11 tristate "CDX bus controller"11 tristate "CDX bus controller"
12 select GENERIC_MSI_IRQ
12 select REMOTEPROC13 select REMOTEPROC
13 select RPMSG14 select RPMSG
14 help15 help
drivers/cdx/controller/cdx_controller.c+25−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#include <linux/platform_device.h>9#include <linux/platform_device.h>
10#include <linux/slab.h>10#include <linux/slab.h>
11#include <linux/cdx/cdx_bus.h>11#include <linux/cdx/cdx_bus.h>
12#include <linux/irqdomain.h>
12 13
13#include "cdx_controller.h"14#include "cdx_controller.h"
14#include "../cdx.h"15#include "../cdx.h"
@@ -60,9 +61,19 @@ static int cdx_configure_device(struct cdx_controller *cdx, · 45 unmodified lines
60 u8 bus_num, u8 dev_num,61 u8 bus_num, u8 dev_num,
61 struct cdx_device_config *dev_config)62 struct cdx_device_config *dev_config)
62{63{
64 u16 msi_index;
63 int ret = 0;65 int ret = 0;
66 u32 data;
67 u64 addr;
64 68
65 switch (dev_config->type) {69 switch (dev_config->type) {
70 case CDX_DEV_MSI_CONF:
71 msi_index = dev_config->msi.msi_index;
72 data = dev_config->msi.data;
73 addr = dev_config->msi.addr;
74
75 ret = cdx_mcdi_write_msi(cdx->priv, bus_num, dev_num, msi_index, addr, data);
76 break;
66 case CDX_DEV_RESET_CONF:77 case CDX_DEV_RESET_CONF:
67 ret = cdx_mcdi_reset_device(cdx->priv, bus_num, dev_num);78 ret = cdx_mcdi_reset_device(cdx->priv, bus_num, dev_num);
68 break;79 break;
@@ -70,6 +81,9 @@ static int cdx_configure_device(struct cdx_controller *cdx, · 1 unmodified line
70 ret = cdx_mcdi_bus_master_enable(cdx->priv, bus_num, dev_num,81 ret = cdx_mcdi_bus_master_enable(cdx->priv, bus_num, dev_num,
71 dev_config->bus_master_enable);82 dev_config->bus_master_enable);
72 break;83 break;
84 case CDX_DEV_MSI_ENABLE:
85 ret = cdx_mcdi_msi_enable(cdx->priv, bus_num, dev_num, dev_config->msi_enable);
86 break;
73 default:87 default:
74 ret = -EINVAL;88 ret = -EINVAL;
75 }89 }
@@ -178,6 +192,14 @@ static int xlnx_cdx_probe(struct platform_device *pdev) · 102 unmodified lines
178 cdx->priv = cdx_mcdi;192 cdx->priv = cdx_mcdi;
179 cdx->ops = &cdx_ops;193 cdx->ops = &cdx_ops;
180 194
195 /* Create MSI domain */
196 cdx->msi_domain = cdx_msi_domain_init(&pdev->dev);
197 if (!cdx->msi_domain) {
198 dev_err(&pdev->dev, "cdx_msi_domain_init() failed");
199 ret = -ENODEV;
200 goto cdx_msi_fail;
201 }
202
181 ret = cdx_setup_rpmsg(pdev);203 ret = cdx_setup_rpmsg(pdev);
182 if (ret) {204 if (ret) {
183 if (ret != -EPROBE_DEFER)205 if (ret != -EPROBE_DEFER)
@@ -189,6 +211,8 @@ static int xlnx_cdx_probe(struct platform_device *pdev) · 5 unmodified lines
189 return 0;211 return 0;
190 212
191cdx_rpmsg_fail:213cdx_rpmsg_fail:
214 irq_domain_remove(cdx->msi_domain);
215cdx_msi_fail:
192 kfree(cdx);216 kfree(cdx);
193cdx_alloc_fail:217cdx_alloc_fail:
194 cdx_mcdi_finish(cdx_mcdi);218 cdx_mcdi_finish(cdx_mcdi);
@@ -205,6 +229,7 @@ static int xlnx_cdx_remove(struct platform_device *pdev) · 10 unmodified lines
205 229
206 cdx_destroy_rpmsg(pdev);230 cdx_destroy_rpmsg(pdev);
207 231
232 irq_domain_remove(cdx->msi_domain);
208 kfree(cdx);233 kfree(cdx);
209 234
210 cdx_mcdi_finish(cdx_mcdi);235 cdx_mcdi_finish(cdx_mcdi);
drivers/cdx/controller/mc_cdx_pcol.h+64−0
@@ -455,6 +455,12 @@ · 454 unmodified lines
455#define MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID_OFST 84455#define MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID_OFST 84
456#define MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID_LEN 4456#define MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID_LEN 4
457 457
458/* MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2 msgresponse */
459#define MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN 92
460/* Requester ID used by device for GIC ITS DeviceID */
461#define MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_REQUESTER_DEVICE_ID_OFST 88
462#define MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_REQUESTER_DEVICE_ID_LEN 4
463
458/***********************************/464/***********************************/
459/*465/*
460 * MC_CMD_CDX_BUS_DOWN466 * MC_CMD_CDX_BUS_DOWN
@@ -616,6 +622,64 @@ · 155 unmodified lines
616#define MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_MMIO_REGIONS_ENABLE_LBN 2622#define MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_MMIO_REGIONS_ENABLE_LBN 2
617#define MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_MMIO_REGIONS_ENABLE_WIDTH 1623#define MC_CMD_CDX_DEVICE_CONTROL_GET_OUT_MMIO_REGIONS_ENABLE_WIDTH 1
618 624
625/***********************************/
626/*
627 * MC_CMD_CDX_DEVICE_WRITE_MSI_MSG
628 * Populates the MSI message to be used by the hardware to raise the specified
629 * interrupt vector. Versal-net implementation specific limitations are that
630 * only 4 CDX devices with MSI interrupt capability are supported and all
631 * vectors within a device must use the same write address. The command will
632 * return EINVAL if any of these limitations is violated.
633 */
634#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG 0x9
635#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_MSGSET 0x9
636#undef MC_CMD_0x9_PRIVILEGE_CTG
637
638#define MC_CMD_0x9_PRIVILEGE_CTG SRIOV_CTG_ADMIN
639
640/* MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN msgrequest */
641#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_LEN 28
642/* Device bus number, in range 0 to BUS_COUNT-1 */
643#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_BUS_OFST 0
644#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_BUS_LEN 4
645/* Device number relative to the bus, in range 0 to DEVICE_COUNT-1 for that bus */
646#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_DEVICE_OFST 4
647#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_DEVICE_LEN 4
648/*
649 * Device-relative MSI vector number. Must be < MSI_COUNT reported for the
650 * device.
651 */
652#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_VECTOR_OFST 8
653#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_VECTOR_LEN 4
654/* Reserved (alignment) */
655#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_RESERVED_OFST 12
656#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_RESERVED_LEN 4
657/*
658 * MSI address to be used by the hardware. Typically, on ARM systems this
659 * address is translated by the IOMMU (if enabled) and it is the responsibility
660 * of the entity managing the IOMMU (APU kernel) to supply the correct IOVA
661 * here.
662 */
663#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_OFST 16
664#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_LEN 8
665#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_LO_OFST 16
666#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_LO_LEN 4
667#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_LO_LBN 128
668#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_LO_WIDTH 32
669#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_HI_OFST 20
670#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_HI_LEN 4
671#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_HI_LBN 160
672#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS_HI_WIDTH 32
673/*
674 * MSI data to be used by the hardware. On versal-net, only the lower 16-bits
675 * are used, the remaining bits are ignored and should be set to zero.
676 */
677#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_DATA_OFST 24
678#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_DATA_LEN 4
679
680/* MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_OUT msgresponse */
681#define MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_OUT_LEN 0
682
619/***********************************/683/***********************************/
620/* MC_CMD_V2_EXTN - Encapsulation for a v2 extended command */684/* MC_CMD_V2_EXTN - Encapsulation for a v2 extended command */
621#define MC_CMD_V2_EXTN 0x7f685#define MC_CMD_V2_EXTN 0x7f
drivers/cdx/controller/mcdi_functions.c+31−2
@@ -49,7 +49,7 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx, · 48 unmodified lines
49 u8 bus_num, u8 dev_num,49 u8 bus_num, u8 dev_num,
50 struct cdx_dev_params *dev_params)50 struct cdx_dev_params *dev_params)
51{51{
52 MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_LEN);52 MCDI_DECLARE_BUF(outbuf, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN);
53 MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_IN_LEN);53 MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_IN_LEN);
54 struct resource *res = &dev_params->res[0];54 struct resource *res = &dev_params->res[0];
55 size_t outlen;55 size_t outlen;
@@ -64,7 +64,7 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx, · 8 unmodified lines
64 if (ret)64 if (ret)
65 return ret;65 return ret;
66 66
67 if (outlen != MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_LEN)67 if (outlen != MC_CMD_CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_LEN)
68 return -EIO;68 return -EIO;
69 69
70 dev_params->bus_num = bus_num;70 dev_params->bus_num = bus_num;
@@ -73,6 +73,9 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx, · 2 unmodified lines
73 req_id = MCDI_DWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID);73 req_id = MCDI_DWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_REQUESTER_ID);
74 dev_params->req_id = req_id;74 dev_params->req_id = req_id;
75 75
76 dev_params->msi_dev_id = MCDI_DWORD(outbuf,
77 CDX_BUS_GET_DEVICE_CONFIG_OUT_V2_REQUESTER_DEVICE_ID);
78
76 dev_params->res_count = 0;79 dev_params->res_count = 0;
77 if (MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_SIZE) != 0) {80 if (MCDI_QWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MMIO_REGION0_SIZE) != 0) {
78 res[dev_params->res_count].start =81 res[dev_params->res_count].start =
@@ -127,6 +130,7 @@ int cdx_mcdi_get_dev_config(struct cdx_mcdi *cdx, · 48 unmodified lines
127 dev_params->class = MCDI_DWORD(outbuf,130 dev_params->class = MCDI_DWORD(outbuf,
128 CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_CLASS) & 0xFFFFFF;131 CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_CLASS) & 0xFFFFFF;
129 dev_params->revision = MCDI_BYTE(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_REVISION);132 dev_params->revision = MCDI_BYTE(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_DEVICE_REVISION);
133 dev_params->num_msi = MCDI_DWORD(outbuf, CDX_BUS_GET_DEVICE_CONFIG_OUT_MSI_COUNT);
130 134
131 return 0;135 return 0;
132}136}
@@ -155,6 +159,24 @@ int cdx_mcdi_bus_disable(struct cdx_mcdi *cdx, u8 bus_num) · 22 unmodified lines
155 return ret;159 return ret;
156}160}
157 161
162int cdx_mcdi_write_msi(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num,
163 u32 msi_vector, u64 msi_address, u32 msi_data)
164{
165 MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG_IN_LEN);
166 int ret;
167
168 MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_BUS, bus_num);
169 MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_DEVICE, dev_num);
170 MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_VECTOR, msi_vector);
171 MCDI_SET_QWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_ADDRESS, msi_address);
172 MCDI_SET_DWORD(inbuf, CDX_DEVICE_WRITE_MSI_MSG_IN_MSI_DATA, msi_data);
173
174 ret = cdx_mcdi_rpc(cdx, MC_CMD_CDX_DEVICE_WRITE_MSI_MSG, inbuf, sizeof(inbuf),
175 NULL, 0, NULL);
176
177 return ret;
178}
179
158int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num)180int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num)
159{181{
160 MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_RESET_IN_LEN);182 MCDI_DECLARE_BUF(inbuf, MC_CMD_CDX_DEVICE_RESET_IN_LEN);
@@ -226,3 +248,10 @@ int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num, · 65 unmodified lines
226 return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,248 return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,
227 MC_CMD_CDX_DEVICE_CONTROL_SET_IN_BUS_MASTER_ENABLE_LBN);249 MC_CMD_CDX_DEVICE_CONTROL_SET_IN_BUS_MASTER_ENABLE_LBN);
228}250}
251
252int cdx_mcdi_msi_enable(struct cdx_mcdi *cdx, u8 bus_num,
253 u8 dev_num, bool enable)
254{
255 return cdx_mcdi_ctrl_flag_set(cdx, bus_num, dev_num, enable,
256 MC_CMD_CDX_DEVICE_CONTROL_SET_IN_MSI_ENABLE_LBN);
257}
drivers/cdx/controller/mcdi_functions.h+33−0
@@ -65,6 +65,26 @@ int cdx_mcdi_bus_enable(struct cdx_mcdi *cdx, u8 bus_num); · 64 unmodified lines
65 */65 */
66int cdx_mcdi_bus_disable(struct cdx_mcdi *cdx, u8 bus_num);66int cdx_mcdi_bus_disable(struct cdx_mcdi *cdx, u8 bus_num);
67 67
68/**
69 * cdx_mcdi_write_msi - Write MSI configuration for CDX device
70 * @cdx: pointer to MCDI interface.
71 * @bus_num: Bus number.
72 * @dev_num: Device number.
73 * @msi_vector: Device-relative MSI vector number.
74 * Must be < MSI_COUNT reported for the device.
75 * @msi_address: MSI address to be used by the hardware. Typically, on ARM
76 * systems this address is translated by the IOMMU (if enabled) and
77 * it is the responsibility of the entity managing the IOMMU (APU kernel)
78 * to supply the correct IOVA here.
79 * @msi_data: MSI data to be used by the hardware. On versal-net, only the
80 * lower 16-bits are used, the remaining bits are ignored and should be
81 * set to zero.
82 *
83 * Return: 0 on success, <0 on failure
84 */
85int cdx_mcdi_write_msi(struct cdx_mcdi *cdx, u8 bus_num, u8 dev_num,
86 u32 msi_vector, u64 msi_address, u32 msi_data);
87
68/**88/**
69 * cdx_mcdi_reset_device - Reset cdx device represented by bus_num:dev_num89 * cdx_mcdi_reset_device - Reset cdx device represented by bus_num:dev_num
70 * @cdx: pointer to MCDI interface.90 * @cdx: pointer to MCDI interface.
@@ -89,4 +109,17 @@ int cdx_mcdi_reset_device(struct cdx_mcdi *cdx, · 18 unmodified lines
89int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,109int cdx_mcdi_bus_master_enable(struct cdx_mcdi *cdx, u8 bus_num,
90 u8 dev_num, bool enable);110 u8 dev_num, bool enable);
91 111
112/**
113 * cdx_mcdi_msi_enable - Enable/Disable MSIs for cdx device represented
114 * by bus_num:dev_num
115 * @cdx: pointer to MCDI interface.
116 * @bus_num: Bus number.
117 * @dev_num: Device number.
118 * @enable: Enable msi's if set, disable otherwise.
119 *
120 * Return: 0 on success, <0 on failure
121 */
122int cdx_mcdi_msi_enable(struct cdx_mcdi *cdx, u8 bus_num,
123 u8 dev_num, bool enable);
124
92#endif /* CDX_MCDI_FUNCTIONS_H */125#endif /* CDX_MCDI_FUNCTIONS_H */
drivers/char/hpet.c+0−1
@@ -87,7 +87,6 @@ struct hpets { · 86 unmodified lines
87 struct hpets *hp_next;87 struct hpets *hp_next;
88 struct hpet __iomem *hp_hpet;88 struct hpet __iomem *hp_hpet;
89 unsigned long hp_hpet_phys;89 unsigned long hp_hpet_phys;
90 struct clocksource *hp_clocksource;
91 unsigned long long hp_tick_freq;90 unsigned long long hp_tick_freq;
92 unsigned long hp_delta;91 unsigned long hp_delta;
93 unsigned int hp_ntimer;92 unsigned int hp_ntimer;
drivers/char/xilinx_hwicap/xilinx_hwicap.c+3−3
@@ -636,11 +636,11 @@ static int hwicap_setup(struct platform_device *pdev, int id, · 635 unmodified lines
636 retval = -ENOMEM;636 retval = -ENOMEM;
637 goto failed;637 goto failed;
638 }638 }
639 dev_set_drvdata(dev, (void *)drvdata);639 dev_set_drvdata(dev, drvdata);
640 640
641 drvdata->base_address = devm_platform_ioremap_resource(pdev, 0);641 drvdata->base_address = devm_platform_ioremap_resource(pdev, 0);
642 if (!drvdata->base_address) {642 if (IS_ERR(drvdata->base_address)) {
643 retval = -ENODEV;643 retval = PTR_ERR(drvdata->base_address);
644 goto failed;644 goto failed;
645 }645 }
646 646
drivers/char/xillybus/xillybus_of.c+2−4
@@ -64,19 +64,17 @@ static int xilly_drv_probe(struct platform_device *op) · 63 unmodified lines
64 return xillybus_endpoint_discovery(endpoint);64 return xillybus_endpoint_discovery(endpoint);
65}65}
66 66
67static int xilly_drv_remove(struct platform_device *op)67static void xilly_drv_remove(struct platform_device *op)
68{68{
69 struct device *dev = &op->dev;69 struct device *dev = &op->dev;
70 struct xilly_endpoint *endpoint = dev_get_drvdata(dev);70 struct xilly_endpoint *endpoint = dev_get_drvdata(dev);
71 71
72 xillybus_endpoint_remove(endpoint);72 xillybus_endpoint_remove(endpoint);
73
74 return 0;
75}73}
76 74
77static struct platform_driver xillybus_platform_driver = {75static struct platform_driver xillybus_platform_driver = {
78 .probe = xilly_drv_probe,76 .probe = xilly_drv_probe,
79 .remove = xilly_drv_remove,77 .remove_new = xilly_drv_remove,
80 .driver = {78 .driver = {
81 .name = xillyname,79 .name = xillyname,
82 .of_match_table = xillybus_of_match,80 .of_match_table = xillybus_of_match,
drivers/comedi/drivers/das08.c+0−1
@@ -177,7 +177,6 @@ static int das08_ai_insn_read(struct comedi_device *dev, · 176 unmodified lines
177 int ret;177 int ret;
178 178
179 chan = CR_CHAN(insn->chanspec);179 chan = CR_CHAN(insn->chanspec);
180 range = CR_RANGE(insn->chanspec);
181 180
182 /* clear crap */181 /* clear crap */
183 inb(dev->iobase + DAS08_AI_LSB_REG);182 inb(dev->iobase + DAS08_AI_LSB_REG);
drivers/dio/dio-driver.c+1−1
@@ -123,7 +123,7 @@ static int dio_bus_match(struct device *dev, struct device_driver *drv) · 122 unmodified lines
123}123}
124 124
125 125
126struct bus_type dio_bus_type = {126const struct bus_type dio_bus_type = {
127 .name = "dio",127 .name = "dio",
128 .match = dio_bus_match,128 .match = dio_bus_match,
129 .probe = dio_device_probe,129 .probe = dio_device_probe,
drivers/firmware/xilinx/zynqmp.c+25−0
@@ -3,6 +3,7 @@ · 2 unmodified lines
3 * Xilinx Zynq MPSoC Firmware layer3 * Xilinx Zynq MPSoC Firmware layer
4 *4 *
5 * Copyright (C) 2014-2022 Xilinx, Inc.5 * Copyright (C) 2014-2022 Xilinx, Inc.
6 * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
6 *7 *
7 * Michal Simek <michal.simek@amd.com>8 * Michal Simek <michal.simek@amd.com>
8 * Davorin Mista <davorin.mista@aggios.com>9 * Davorin Mista <davorin.mista@aggios.com>
@@ -1384,6 +1385,30 @@ int zynqmp_pm_aes_engine(const u64 address, u32 *out) · 1375 unmodified lines
1384}1385}
1385EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);1386EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
1386 1387
1388/**
1389 * zynqmp_pm_efuse_access - Provides access to efuse memory.
1390 * @address: Address of the efuse params structure
1391 * @out: Returned output value
1392 *
1393 * Return: Returns status, either success or error code.
1394 */
1395int zynqmp_pm_efuse_access(const u64 address, u32 *out)
1396{
1397 u32 ret_payload[PAYLOAD_ARG_CNT];
1398 int ret;
1399
1400 if (!out)
1401 return -EINVAL;
1402
1403 ret = zynqmp_pm_invoke_fn(PM_EFUSE_ACCESS, ret_payload, 2,
1404 upper_32_bits(address),
1405 lower_32_bits(address));
1406 *out = ret_payload[1];
1407
1408 return ret;
1409}
1410EXPORT_SYMBOL_GPL(zynqmp_pm_efuse_access);
1411
1387/**1412/**
1388 * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash1413 * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
1389 * @address: Address of the data/ Address of output buffer where1414 * @address: Address of the data/ Address of output buffer where
drivers/fpga/dfl.c+1−1
@@ -327,7 +327,7 @@ static struct attribute *dfl_dev_attrs[] = { · 326 unmodified lines
327};327};
328ATTRIBUTE_GROUPS(dfl_dev);328ATTRIBUTE_GROUPS(dfl_dev);
329 329
330static struct bus_type dfl_bus_type = {330static const struct bus_type dfl_bus_type = {
331 .name = "dfl",331 .name = "dfl",
332 .match = dfl_bus_match,332 .match = dfl_bus_match,
333 .probe = dfl_bus_probe,333 .probe = dfl_bus_probe,
drivers/fpga/fpga-bridge.c+4−4
@@ -30,7 +30,7 @@ int fpga_bridge_enable(struct fpga_bridge *bridge) · 29 unmodified lines
30{30{
31 dev_dbg(&bridge->dev, "enable\n");31 dev_dbg(&bridge->dev, "enable\n");
32 32
33 if (bridge->br_ops && bridge->br_ops->enable_set)33 if (bridge->br_ops->enable_set)
34 return bridge->br_ops->enable_set(bridge, 1);34 return bridge->br_ops->enable_set(bridge, 1);
35 35
36 return 0;36 return 0;
@@ -48,7 +48,7 @@ int fpga_bridge_disable(struct fpga_bridge *bridge) · 11 unmodified lines
48{48{
49 dev_dbg(&bridge->dev, "disable\n");49 dev_dbg(&bridge->dev, "disable\n");
50 50
51 if (bridge->br_ops && bridge->br_ops->enable_set)51 if (bridge->br_ops->enable_set)
52 return bridge->br_ops->enable_set(bridge, 0);52 return bridge->br_ops->enable_set(bridge, 0);
53 53
54 return 0;54 return 0;
@@ -296,7 +296,7 @@ static ssize_t state_show(struct device *dev, · 241 unmodified lines
296 struct fpga_bridge *bridge = to_fpga_bridge(dev);296 struct fpga_bridge *bridge = to_fpga_bridge(dev);
297 int state = 1;297 int state = 1;
298 298
299 if (bridge->br_ops && bridge->br_ops->enable_show) {299 if (bridge->br_ops->enable_show) {
300 state = bridge->br_ops->enable_show(bridge);300 state = bridge->br_ops->enable_show(bridge);
301 if (state < 0)301 if (state < 0)
302 return state;302 return state;
@@ -401,7 +401,7 @@ void fpga_bridge_unregister(struct fpga_bridge *bridge) · 98 unmodified lines
401 * If the low level driver provides a method for putting bridge into401 * If the low level driver provides a method for putting bridge into
402 * a desired state upon unregister, do it.402 * a desired state upon unregister, do it.
403 */403 */
404 if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove)404 if (bridge->br_ops->fpga_bridge_remove)
405 bridge->br_ops->fpga_bridge_remove(bridge);405 bridge->br_ops->fpga_bridge_remove(bridge);
406 406
407 device_unregister(&bridge->dev);407 device_unregister(&bridge->dev);
drivers/greybus/bundle.c+1−1
@@ -166,7 +166,7 @@ static const struct dev_pm_ops gb_bundle_pm_ops = { · 165 unmodified lines
166 SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle)166 SET_RUNTIME_PM_OPS(gb_bundle_suspend, gb_bundle_resume, gb_bundle_idle)
167};167};
168 168
169struct device_type greybus_bundle_type = {169const struct device_type greybus_bundle_type = {
170 .name = "greybus_bundle",170 .name = "greybus_bundle",
171 .release = gb_bundle_release,171 .release = gb_bundle_release,
172 .pm = &gb_bundle_pm_ops,172 .pm = &gb_bundle_pm_ops,
drivers/greybus/control.c+1−1
@@ -436,7 +436,7 @@ static void gb_control_release(struct device *dev) · 435 unmodified lines
436 kfree(control);436 kfree(control);
437}437}
438 438
439struct device_type greybus_control_type = {439const struct device_type greybus_control_type = {
440 .name = "greybus_control",440 .name = "greybus_control",
441 .release = gb_control_release,441 .release = gb_control_release,
442};442};
drivers/greybus/core.c+31−1
@@ -27,6 +27,36 @@ int greybus_disabled(void) · 26 unmodified lines
27}27}
28EXPORT_SYMBOL_GPL(greybus_disabled);28EXPORT_SYMBOL_GPL(greybus_disabled);
29 29
30static int is_gb_host_device(const struct device *dev)
31{
32 return dev->type == &greybus_hd_type;
33}
34
35static int is_gb_module(const struct device *dev)
36{
37 return dev->type == &greybus_module_type;
38}
39
40static int is_gb_interface(const struct device *dev)
41{
42 return dev->type == &greybus_interface_type;
43}
44
45static int is_gb_control(const struct device *dev)
46{
47 return dev->type == &greybus_control_type;
48}
49
50static int is_gb_bundle(const struct device *dev)
51{
52 return dev->type == &greybus_bundle_type;
53}
54
55static int is_gb_svc(const struct device *dev)
56{
57 return dev->type == &greybus_svc_type;
58}
59
30static bool greybus_match_one_id(struct gb_bundle *bundle,60static bool greybus_match_one_id(struct gb_bundle *bundle,
31 const struct greybus_bundle_id *id)61 const struct greybus_bundle_id *id)
32{62{
@@ -155,7 +185,7 @@ static void greybus_shutdown(struct device *dev) · 122 unmodified lines
155 }185 }
156}186}
157 187
158struct bus_type greybus_bus_type = {188const struct bus_type greybus_bus_type = {
159 .name = "greybus",189 .name = "greybus",
160 .match = greybus_match_device,190 .match = greybus_match_device,
161 .uevent = greybus_uevent,191 .uevent = greybus_uevent,
drivers/greybus/es2.c+4−4
@@ -513,16 +513,16 @@ static int es2_cport_allocate(struct gb_host_device *hd, int cport_id, · 512 unmodified lines
513 513
514 if (cport_id < 0) {514 if (cport_id < 0) {
515 ida_start = 0;515 ida_start = 0;
516 ida_end = hd->num_cports;516 ida_end = hd->num_cports - 1;
517 } else if (cport_id < hd->num_cports) {517 } else if (cport_id < hd->num_cports) {
518 ida_start = cport_id;518 ida_start = cport_id;
519 ida_end = cport_id + 1;519 ida_end = cport_id;
520 } else {520 } else {
521 dev_err(&hd->dev, "cport %d not available\n", cport_id);521 dev_err(&hd->dev, "cport %d not available\n", cport_id);
522 return -EINVAL;522 return -EINVAL;
523 }523 }
524 524
525 return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);525 return ida_alloc_range(id_map, ida_start, ida_end, GFP_KERNEL);
526}526}
527 527
528static void es2_cport_release(struct gb_host_device *hd, u16 cport_id)528static void es2_cport_release(struct gb_host_device *hd, u16 cport_id)
@@ -535,7 +535,7 @@ static void es2_cport_release(struct gb_host_device *hd, u16 cport_id) · 6 unmodified lines
535 return;535 return;
536 }536 }
537 537
538 ida_simple_remove(&hd->cport_id_map, cport_id);538 ida_free(&hd->cport_id_map, cport_id);
539}539}
540 540
541static int cport_enable(struct gb_host_device *hd, u16 cport_id,541static int cport_enable(struct gb_host_device *hd, u16 cport_id,
drivers/greybus/hd.c+9−9
@@ -50,7 +50,7 @@ int gb_hd_cport_reserve(struct gb_host_device *hd, u16 cport_id) · 49 unmodified lines
50 struct ida *id_map = &hd->cport_id_map;50 struct ida *id_map = &hd->cport_id_map;
51 int ret;51 int ret;
52 52
53 ret = ida_simple_get(id_map, cport_id, cport_id + 1, GFP_KERNEL);53 ret = ida_alloc_range(id_map, cport_id, cport_id, GFP_KERNEL);
54 if (ret < 0) {54 if (ret < 0) {
55 dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id);55 dev_err(&hd->dev, "failed to reserve cport %u\n", cport_id);
56 return ret;56 return ret;
@@ -64,7 +64,7 @@ void gb_hd_cport_release_reserved(struct gb_host_device *hd, u16 cport_id) · 7 unmodified lines
64{64{
65 struct ida *id_map = &hd->cport_id_map;65 struct ida *id_map = &hd->cport_id_map;
66 66
67 ida_simple_remove(id_map, cport_id);67 ida_free(id_map, cport_id);
68}68}
69EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved);69EXPORT_SYMBOL_GPL(gb_hd_cport_release_reserved);
70 70
@@ -80,16 +80,16 @@ int gb_hd_cport_allocate(struct gb_host_device *hd, int cport_id, · 9 unmodified lines
80 80
81 if (cport_id < 0) {81 if (cport_id < 0) {
82 ida_start = 0;82 ida_start = 0;
83 ida_end = hd->num_cports;83 ida_end = hd->num_cports - 1;
84 } else if (cport_id < hd->num_cports) {84 } else if (cport_id < hd->num_cports) {
85 ida_start = cport_id;85 ida_start = cport_id;
86 ida_end = cport_id + 1;86 ida_end = cport_id;
87 } else {87 } else {
88 dev_err(&hd->dev, "cport %d not available\n", cport_id);88 dev_err(&hd->dev, "cport %d not available\n", cport_id);
89 return -EINVAL;89 return -EINVAL;
90 }90 }
91 91
92 return ida_simple_get(id_map, ida_start, ida_end, GFP_KERNEL);92 return ida_alloc_range(id_map, ida_start, ida_end, GFP_KERNEL);
93}93}
94 94
95/* Locking: Caller guarantees serialisation */95/* Locking: Caller guarantees serialisation */
@@ -100,7 +100,7 @@ void gb_hd_cport_release(struct gb_host_device *hd, u16 cport_id) · 4 unmodified lines
100 return;100 return;
101 }101 }
102 102
103 ida_simple_remove(&hd->cport_id_map, cport_id);103 ida_free(&hd->cport_id_map, cport_id);
104}104}
105 105
106static void gb_hd_release(struct device *dev)106static void gb_hd_release(struct device *dev)
@@ -111,12 +111,12 @@ static void gb_hd_release(struct device *dev) · 4 unmodified lines
111 111
112 if (hd->svc)112 if (hd->svc)
113 gb_svc_put(hd->svc);113 gb_svc_put(hd->svc);
114 ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id);114 ida_free(&gb_hd_bus_id_map, hd->bus_id);
115 ida_destroy(&hd->cport_id_map);115 ida_destroy(&hd->cport_id_map);
116 kfree(hd);116 kfree(hd);
117}117}
118 118
119struct device_type greybus_hd_type = {119const struct device_type greybus_hd_type = {
120 .name = "greybus_host_device",120 .name = "greybus_host_device",
121 .release = gb_hd_release,121 .release = gb_hd_release,
122};122};
@@ -162,7 +162,7 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver, · 39 unmodified lines
162 if (!hd)162 if (!hd)
163 return ERR_PTR(-ENOMEM);163 return ERR_PTR(-ENOMEM);
164 164
165 ret = ida_simple_get(&gb_hd_bus_id_map, 1, 0, GFP_KERNEL);165 ret = ida_alloc_min(&gb_hd_bus_id_map, 1, GFP_KERNEL);
166 if (ret < 0) {166 if (ret < 0) {
167 kfree(hd);167 kfree(hd);
168 return ERR_PTR(ret);168 return ERR_PTR(ret);
drivers/greybus/interface.c+5−6
@@ -131,9 +131,8 @@ static int gb_interface_route_create(struct gb_interface *intf) · 130 unmodified lines
131 int ret;131 int ret;
132 132
133 /* Allocate an interface device id. */133 /* Allocate an interface device id. */
134 ret = ida_simple_get(&svc->device_id_map,134 ret = ida_alloc_range(&svc->device_id_map, GB_SVC_DEVICE_ID_MIN,
135 GB_SVC_DEVICE_ID_MIN, GB_SVC_DEVICE_ID_MAX + 1,135 GB_SVC_DEVICE_ID_MAX, GFP_KERNEL);
136 GFP_KERNEL);
137 if (ret < 0) {136 if (ret < 0) {
138 dev_err(&intf->dev, "failed to allocate device id: %d\n", ret);137 dev_err(&intf->dev, "failed to allocate device id: %d\n", ret);
139 return ret;138 return ret;
@@ -165,7 +164,7 @@ err_svc_id_free: · 25 unmodified lines
165 * XXX anymore.164 * XXX anymore.
166 */165 */
167err_ida_remove:166err_ida_remove:
168 ida_simple_remove(&svc->device_id_map, device_id);167 ida_free(&svc->device_id_map, device_id);
169 168
170 return ret;169 return ret;
171}170}
@@ -178,7 +177,7 @@ static void gb_interface_route_destroy(struct gb_interface *intf) · 6 unmodified lines
178 return;177 return;
179 178
180 gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id);179 gb_svc_route_destroy(svc, svc->ap_intf_id, intf->interface_id);
181 ida_simple_remove(&svc->device_id_map, intf->device_id);180 ida_free(&svc->device_id_map, intf->device_id);
182 intf->device_id = GB_INTERFACE_DEVICE_ID_BAD;181 intf->device_id = GB_INTERFACE_DEVICE_ID_BAD;
183}182}
184 183
@@ -765,7 +764,7 @@ static const struct dev_pm_ops gb_interface_pm_ops = { · 580 unmodified lines
765 gb_interface_runtime_idle)764 gb_interface_runtime_idle)
766};765};
767 766
768struct device_type greybus_interface_type = {767const struct device_type greybus_interface_type = {
769 .name = "greybus_interface",768 .name = "greybus_interface",
770 .release = gb_interface_release,769 .release = gb_interface_release,
771 .pm = &gb_interface_pm_ops,770 .pm = &gb_interface_pm_ops,
drivers/greybus/module.c+1−1
@@ -81,7 +81,7 @@ static void gb_module_release(struct device *dev) · 80 unmodified lines
81 kfree(module);81 kfree(module);
82}82}
83 83
84struct device_type greybus_module_type = {84const struct device_type greybus_module_type = {
85 .name = "greybus_module",85 .name = "greybus_module",
86 .release = gb_module_release,86 .release = gb_module_release,
87};87};
drivers/greybus/svc.c+1−1
@@ -1305,7 +1305,7 @@ static void gb_svc_release(struct device *dev) · 1304 unmodified lines
1305 kfree(svc);1305 kfree(svc);
1306}1306}
1307 1307
1308struct device_type greybus_svc_type = {1308const struct device_type greybus_svc_type = {
1309 .name = "greybus_svc",1309 .name = "greybus_svc",
1310 .release = gb_svc_release,1310 .release = gb_svc_release,
1311};1311};
drivers/hwtracing/coresight/Makefile+20−0
@@ -2,6 +2,26 @@ · 1 unmodified line
2#2#
3# Makefile for CoreSight drivers.3# Makefile for CoreSight drivers.
4#4#
5
6# Current W=1 warnings
7subdir-ccflags-y += -Wextra -Wunused -Wno-unused-parameter
8subdir-ccflags-y += -Wmissing-declarations
9subdir-ccflags-y += -Wmissing-format-attribute
10subdir-ccflags-y += -Wmissing-prototypes
11subdir-ccflags-y += -Wold-style-definition
12subdir-ccflags-y += -Wmissing-include-dirs
13subdir-ccflags-y += -Wno-sign-compare
14condflags := \
15 $(call cc-option, -Wrestrict) \
16 $(call cc-option, -Wunused-but-set-variable) \
17 $(call cc-option, -Wunused-const-variable) \
18 $(call cc-option, -Wpacked-not-aligned) \
19 $(call cc-option, -Wformat-overflow) \
20 $(call cc-option, -Wformat-truncation) \
21 $(call cc-option, -Wstringop-overflow) \
22 $(call cc-option, -Wstringop-truncation)
23subdir-ccflags-y += $(condflags)
24
5obj-$(CONFIG_CORESIGHT) += coresight.o25obj-$(CONFIG_CORESIGHT) += coresight.o
6coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \26coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
7 coresight-sysfs.o coresight-syscfg.o coresight-config.o \27 coresight-sysfs.o coresight-syscfg.o coresight-config.o \
drivers/hwtracing/coresight/coresight-cfg-afdo.c+1−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
9/* ETMv4 includes and features */9/* ETMv4 includes and features */
10#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)10#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
11#include "coresight-etm4x-cfg.h"11#include "coresight-etm4x-cfg.h"
12#include "coresight-cfg-preload.h"
12 13
13/* preload configurations and features */14/* preload configurations and features */
14 15
drivers/hwtracing/coresight/coresight-core.c+29−467
@@ -9,7 +9,6 @@ · 8 unmodified lines
9#include <linux/types.h>9#include <linux/types.h>
10#include <linux/device.h>10#include <linux/device.h>
11#include <linux/io.h>11#include <linux/io.h>
12#include <linux/idr.h>
13#include <linux/err.h>12#include <linux/err.h>
14#include <linux/export.h>13#include <linux/export.h>
15#include <linux/slab.h>14#include <linux/slab.h>
@@ -25,15 +24,12 @@ · 9 unmodified lines
25#include "coresight-priv.h"24#include "coresight-priv.h"
26#include "coresight-syscfg.h"25#include "coresight-syscfg.h"
27 26
28static DEFINE_MUTEX(coresight_mutex);
29static DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
30
31/*27/*
32 * Use IDR to map the hash of the source's device name28 * Mutex used to lock all sysfs enable and disable actions and loading and
33 * to the pointer of path for the source. The idr is for29 * unloading devices by the Coresight core.
34 * the sources which aren't associated with CPU.
35 */30 */
36static DEFINE_IDR(path_idr);31DEFINE_MUTEX(coresight_mutex);
32static DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
37 33
38/**34/**
39 * struct coresight_node - elements of a path, from source to sink35 * struct coresight_node - elements of a path, from source to sink
@@ -45,12 +41,6 @@ struct coresight_node { · 5 unmodified lines
45 struct list_head link;41 struct list_head link;
46};42};
47 43
48/*
49 * When operating Coresight drivers from the sysFS interface, only a single
50 * path can exist from a tracer (associated to a CPU) to a sink.
51 */
52static DEFINE_PER_CPU(struct list_head *, tracer_path);
53
54/*44/*
55 * When losing synchronisation a new barrier packet needs to be inserted at the45 * When losing synchronisation a new barrier packet needs to be inserted at the
56 * beginning of the data collected in a buffer. That way the decoder knows that46 * beginning of the data collected in a buffer. That way the decoder knows that
@@ -61,34 +51,6 @@ EXPORT_SYMBOL_GPL(coresight_barrier_pkt); · 4 unmodified lines
61 51
62static const struct cti_assoc_op *cti_assoc_ops;52static const struct cti_assoc_op *cti_assoc_ops;
63 53
64ssize_t coresight_simple_show_pair(struct device *_dev,
65 struct device_attribute *attr, char *buf)
66{
67 struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev);
68 struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr);
69 u64 val;
70
71 pm_runtime_get_sync(_dev->parent);
72 val = csdev_access_relaxed_read_pair(&csdev->access, cs_attr->lo_off, cs_attr->hi_off);
73 pm_runtime_put_sync(_dev->parent);
74 return sysfs_emit(buf, "0x%llx\n", val);
75}
76EXPORT_SYMBOL_GPL(coresight_simple_show_pair);
77
78ssize_t coresight_simple_show32(struct device *_dev,
79 struct device_attribute *attr, char *buf)
80{
81 struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev);
82 struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr);
83 u64 val;
84
85 pm_runtime_get_sync(_dev->parent);
86 val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off);
87 pm_runtime_put_sync(_dev->parent);
88 return sysfs_emit(buf, "0x%llx\n", val);
89}
90EXPORT_SYMBOL_GPL(coresight_simple_show32);
91
92void coresight_set_cti_ops(const struct cti_assoc_op *cti_op)54void coresight_set_cti_ops(const struct cti_assoc_op *cti_op)
93{55{
94 cti_assoc_ops = cti_op;56 cti_assoc_ops = cti_op;
@@ -279,42 +241,18 @@ EXPORT_SYMBOL_GPL(coresight_add_helper); · 184 unmodified lines
279static int coresight_enable_sink(struct coresight_device *csdev,241static int coresight_enable_sink(struct coresight_device *csdev,
280 enum cs_mode mode, void *data)242 enum cs_mode mode, void *data)
281{243{
282 int ret;244 return sink_ops(csdev)->enable(csdev, mode, data);
283
284 /*
285 * We need to make sure the "new" session is compatible with the
286 * existing "mode" of operation.
287 */
288 if (!sink_ops(csdev)->enable)
289 return -EINVAL;
290
291 ret = sink_ops(csdev)->enable(csdev, mode, data);
292 if (ret)
293 return ret;
294
295 csdev->enable = true;
296
297 return 0;
298}245}
299 246
300static void coresight_disable_sink(struct coresight_device *csdev)247static void coresight_disable_sink(struct coresight_device *csdev)
301{248{
302 int ret;249 sink_ops(csdev)->disable(csdev);
303
304 if (!sink_ops(csdev)->disable)
305 return;
306
307 ret = sink_ops(csdev)->disable(csdev);
308 if (ret)
309 return;
310 csdev->enable = false;
311}250}
312 251
313static int coresight_enable_link(struct coresight_device *csdev,252static int coresight_enable_link(struct coresight_device *csdev,
314 struct coresight_device *parent,253 struct coresight_device *parent,
315 struct coresight_device *child)254 struct coresight_device *child)
316{255{
317 int ret = 0;
318 int link_subtype;256 int link_subtype;
319 struct coresight_connection *inconn, *outconn;257 struct coresight_connection *inconn, *outconn;
320 258
@@ -330,21 +268,13 @@ static int coresight_enable_link(struct coresight_device *csdev, · 9 unmodified lines
330 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn))268 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn))
331 return PTR_ERR(outconn);269 return PTR_ERR(outconn);
332 270
333 if (link_ops(csdev)->enable) {271 return link_ops(csdev)->enable(csdev, inconn, outconn);
334 ret = link_ops(csdev)->enable(csdev, inconn, outconn);
335 if (!ret)
336 csdev->enable = true;
337 }
338
339 return ret;
340}272}
341 273
342static void coresight_disable_link(struct coresight_device *csdev,274static void coresight_disable_link(struct coresight_device *csdev,
343 struct coresight_device *parent,275 struct coresight_device *parent,
344 struct coresight_device *child)276 struct coresight_device *child)
345{277{
346 int i;
347 int link_subtype;
348 struct coresight_connection *inconn, *outconn;278 struct coresight_connection *inconn, *outconn;
349 279
350 if (!parent || !child)280 if (!parent || !child)
@@ -352,49 +282,9 @@ static void coresight_disable_link(struct coresight_device *csdev, · 1 unmodified line
352 282
353 inconn = coresight_find_out_connection(parent, csdev);283 inconn = coresight_find_out_connection(parent, csdev);
354 outconn = coresight_find_out_connection(csdev, child);284 outconn = coresight_find_out_connection(csdev, child);
355 link_subtype = csdev->subtype.link_subtype;
356 285
357 if (link_ops(csdev)->disable) {286 link_ops(csdev)->disable(csdev, inconn, outconn);
358 link_ops(csdev)->disable(csdev, inconn, outconn);
359 }
360
361 if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
362 for (i = 0; i < csdev->pdata->nr_inconns; i++)
363 if (atomic_read(&csdev->pdata->in_conns[i]->dest_refcnt) !=
364 0)
365 return;
366 } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
367 for (i = 0; i < csdev->pdata->nr_outconns; i++)
368 if (atomic_read(&csdev->pdata->out_conns[i]->src_refcnt) !=
369 0)
370 return;
371 } else {
372 if (atomic_read(&csdev->refcnt) != 0)
373 return;
374 }
375
376 csdev->enable = false;
377}
378
379int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,
380 void *data)
381{
382 int ret;
383
384 if (!csdev->enable) {
385 if (source_ops(csdev)->enable) {
386 ret = source_ops(csdev)->enable(csdev, data, mode);
387 if (ret)
388 return ret;
389 }
390 csdev->enable = true;
391 }
392
393 atomic_inc(&csdev->refcnt);
394
395 return 0;
396}287}
397EXPORT_SYMBOL_GPL(coresight_enable_source);
398 288
399static bool coresight_is_helper(struct coresight_device *csdev)289static bool coresight_is_helper(struct coresight_device *csdev)
400{290{
@@ -404,29 +294,12 @@ static bool coresight_is_helper(struct coresight_device *csdev) · 3 unmodified lines
404static int coresight_enable_helper(struct coresight_device *csdev,294static int coresight_enable_helper(struct coresight_device *csdev,
405 enum cs_mode mode, void *data)295 enum cs_mode mode, void *data)
406{296{
407 int ret;297 return helper_ops(csdev)->enable(csdev, mode, data);
408
409 if (!helper_ops(csdev)->enable)
410 return 0;
411 ret = helper_ops(csdev)->enable(csdev, mode, data);
412 if (ret)
413 return ret;
414
415 csdev->enable = true;
416 return 0;
417}298}
418 299
419static void coresight_disable_helper(struct coresight_device *csdev)300static void coresight_disable_helper(struct coresight_device *csdev)
420{301{
421 int ret;302 helper_ops(csdev)->disable(csdev, NULL);
422
423 if (!helper_ops(csdev)->disable)
424 return;
425
426 ret = helper_ops(csdev)->disable(csdev, NULL);
427 if (ret)
428 return;
429 csdev->enable = false;
430}303}
431 304
432static void coresight_disable_helpers(struct coresight_device *csdev)305static void coresight_disable_helpers(struct coresight_device *csdev)
@@ -441,25 +314,20 @@ static void coresight_disable_helpers(struct coresight_device *csdev) · 8 unmodified lines
441 }314 }
442}315}
443 316
444/**317/*
445 * coresight_disable_source - Drop the reference count by 1 and disable318 * Helper function to call source_ops(csdev)->disable and also disable the
446 * the device if there are no users left.319 * helpers.
447 *
448 * @csdev: The coresight device to disable
449 * @data: Opaque data to pass on to the disable function of the source device.
450 * For example in perf mode this is a pointer to the struct perf_event.
451 *320 *
452 * Returns true if the device has been disabled.321 * There is an imbalance between coresight_enable_path() and
322 * coresight_disable_path(). Enabling also enables the source's helpers as part
323 * of the path, but disabling always skips the first item in the path (which is
324 * the source), so sources and their helpers don't get disabled as part of that
325 * function and we need the extra step here.
453 */326 */
454bool coresight_disable_source(struct coresight_device *csdev, void *data)327void coresight_disable_source(struct coresight_device *csdev, void *data)
455{328{
456 if (atomic_dec_return(&csdev->refcnt) == 0) {329 source_ops(csdev)->disable(csdev, data);
457 if (source_ops(csdev)->disable)330 coresight_disable_helpers(csdev);
458 source_ops(csdev)->disable(csdev, data);
459 coresight_disable_helpers(csdev);
460 csdev->enable = false;
461 }
462 return !csdev->enable;
463}331}
464EXPORT_SYMBOL_GPL(coresight_disable_source);332EXPORT_SYMBOL_GPL(coresight_disable_source);
465 333
@@ -484,7 +352,7 @@ static void coresight_disable_path_from(struct list_head *path, · 18 unmodified lines
484 /*352 /*
485 * ETF devices are tricky... They can be a link or a sink,353 * ETF devices are tricky... They can be a link or a sink,
486 * depending on how they are configured. If an ETF has been354 * depending on how they are configured. If an ETF has been
487 * "activated" it will be configured as a sink, otherwise355 * selected as a sink it will be configured as a sink, otherwise
488 * go ahead with the link configuration.356 * go ahead with the link configuration.
489 */357 */
490 if (type == CORESIGHT_DEV_TYPE_LINKSINK)358 if (type == CORESIGHT_DEV_TYPE_LINKSINK)
@@ -562,7 +430,7 @@ int coresight_enable_path(struct list_head *path, enum cs_mode mode, · 71 unmodified lines
562 /*430 /*
563 * ETF devices are tricky... They can be a link or a sink,431 * ETF devices are tricky... They can be a link or a sink,
564 * depending on how they are configured. If an ETF has been432 * depending on how they are configured. If an ETF has been
565 * "activated" it will be configured as a sink, otherwise433 * selected as a sink it will be configured as a sink, otherwise
566 * go ahead with the link configuration.434 * go ahead with the link configuration.
567 */435 */
568 if (type == CORESIGHT_DEV_TYPE_LINKSINK)436 if (type == CORESIGHT_DEV_TYPE_LINKSINK)
@@ -619,48 +487,6 @@ struct coresight_device *coresight_get_sink(struct list_head *path) · 50 unmodified lines
619 return csdev;487 return csdev;
620}488}
621 489
622static struct coresight_device *
623coresight_find_enabled_sink(struct coresight_device *csdev)
624{
625 int i;
626 struct coresight_device *sink = NULL;
627
628 if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
629 csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
630 csdev->activated)
631 return csdev;
632
633 /*
634 * Recursively explore each port found on this element.
635 */
636 for (i = 0; i < csdev->pdata->nr_outconns; i++) {
637 struct coresight_device *child_dev;
638
639 child_dev = csdev->pdata->out_conns[i]->dest_dev;
640 if (child_dev)
641 sink = coresight_find_enabled_sink(child_dev);
642 if (sink)
643 return sink;
644 }
645
646 return NULL;
647}
648
649/**
650 * coresight_get_enabled_sink - returns the first enabled sink using
651 * connection based search starting from the source reference
652 *
653 * @source: Coresight source device reference
654 */
655struct coresight_device *
656coresight_get_enabled_sink(struct coresight_device *source)
657{
658 if (!source)
659 return NULL;
660
661 return coresight_find_enabled_sink(source);
662}
663
664static int coresight_sink_by_id(struct device *dev, const void *data)490static int coresight_sink_by_id(struct device *dev, const void *data)
665{491{
666 struct coresight_device *csdev = to_coresight_device(dev);492 struct coresight_device *csdev = to_coresight_device(dev);
@@ -794,11 +620,10 @@ static void coresight_drop_device(struct coresight_device *csdev) · 127 unmodified lines
794 * @sink: The final sink we want in this path.620 * @sink: The final sink we want in this path.
795 * @path: The list to add devices to.621 * @path: The list to add devices to.
796 *622 *
797 * The tree of Coresight device is traversed until an activated sink is623 * The tree of Coresight device is traversed until @sink is found.
798 * found. From there the sink is added to the list along with all the624 * From there the sink is added to the list along with all the devices that led
799 * devices that led to that point - the end result is a list from source625 * to that point - the end result is a list from source to sink. In that list
800 * to sink. In that list the source is the first device and the sink the626 * the source is the first device and the sink the last one.
801 * last one.
802 */627 */
803static int _coresight_build_path(struct coresight_device *csdev,628static int _coresight_build_path(struct coresight_device *csdev,
804 struct coresight_device *sink,629 struct coresight_device *sink,
@@ -808,7 +633,7 @@ static int _coresight_build_path(struct coresight_device *csdev, · 3 unmodified lines
808 bool found = false;633 bool found = false;
809 struct coresight_node *node;634 struct coresight_node *node;
810 635
811 /* An activated sink has been found. Enqueue the element */636 /* The sink has been found. Enqueue the element */
812 if (csdev == sink)637 if (csdev == sink)
813 goto out;638 goto out;
814 639
@@ -1072,269 +897,6 @@ static void coresight_clear_default_sink(struct coresight_device *csdev) · 257 unmodified lines
1072 }897 }
1073}898}
1074 899
1075/** coresight_validate_source - make sure a source has the right credentials
1076 * @csdev: the device structure for a source.
1077 * @function: the function this was called from.
1078 *
1079 * Assumes the coresight_mutex is held.
1080 */
1081static int coresight_validate_source(struct coresight_device *csdev,
1082 const char *function)
1083{
1084 u32 type, subtype;
1085
1086 type = csdev->type;
1087 subtype = csdev->subtype.source_subtype;
1088
1089 if (type != CORESIGHT_DEV_TYPE_SOURCE) {
1090 dev_err(&csdev->dev, "wrong device type in %s\n", function);
1091 return -EINVAL;
1092 }
1093
1094 if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC &&
1095 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE &&
1096 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM &&
1097 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) {
1098 dev_err(&csdev->dev, "wrong device subtype in %s\n", function);
1099 return -EINVAL;
1100 }
1101
1102 return 0;
1103}
1104
1105int coresight_enable(struct coresight_device *csdev)
1106{
1107 int cpu, ret = 0;
1108 struct coresight_device *sink;
1109 struct list_head *path;
1110 enum coresight_dev_subtype_source subtype;
1111 u32 hash;
1112
1113 subtype = csdev->subtype.source_subtype;
1114
1115 mutex_lock(&coresight_mutex);
1116
1117 ret = coresight_validate_source(csdev, __func__);
1118 if (ret)
1119 goto out;
1120
1121 if (csdev->enable) {
1122 /*
1123 * There could be multiple applications driving the software
1124 * source. So keep the refcount for each such user when the
1125 * source is already enabled.
1126 */
1127 if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE)
1128 atomic_inc(&csdev->refcnt);
1129 goto out;
1130 }
1131
1132 sink = coresight_get_enabled_sink(csdev);
1133 if (!sink) {
1134 ret = -EINVAL;
1135 goto out;
1136 }
1137
1138 path = coresight_build_path(csdev, sink);
1139 if (IS_ERR(path)) {
1140 pr_err("building path(s) failed\n");
1141 ret = PTR_ERR(path);
1142 goto out;
1143 }
1144
1145 ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL);
1146 if (ret)
1147 goto err_path;
1148
1149 ret = coresight_enable_source(csdev, CS_MODE_SYSFS, NULL);
1150 if (ret)
1151 goto err_source;
1152
1153 switch (subtype) {
1154 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
1155 /*
1156 * When working from sysFS it is important to keep track
1157 * of the paths that were created so that they can be
1158 * undone in 'coresight_disable()'. Since there can only
1159 * be a single session per tracer (when working from sysFS)
1160 * a per-cpu variable will do just fine.
1161 */
1162 cpu = source_ops(csdev)->cpu_id(csdev);
1163 per_cpu(tracer_path, cpu) = path;
1164 break;
1165 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
1166 case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM:
1167 case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS:
1168 /*
1169 * Use the hash of source's device name as ID
1170 * and map the ID to the pointer of the path.
1171 */
1172 hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev)));
1173 ret = idr_alloc_u32(&path_idr, path, &hash, hash, GFP_KERNEL);
1174 if (ret)
1175 goto err_source;
1176 break;
1177 default:
1178 /* We can't be here */
1179 break;
1180 }
1181
1182out:
1183 mutex_unlock(&coresight_mutex);
1184 return ret;
1185
1186err_source:
1187 coresight_disable_path(path);
1188
1189err_path:
1190 coresight_release_path(path);
1191 goto out;
1192}
1193EXPORT_SYMBOL_GPL(coresight_enable);
1194
1195void coresight_disable(struct coresight_device *csdev)
1196{
1197 int cpu, ret;
1198 struct list_head *path = NULL;
1199 u32 hash;
1200
1201 mutex_lock(&coresight_mutex);
1202
1203 ret = coresight_validate_source(csdev, __func__);
1204 if (ret)
1205 goto out;
1206
1207 if (!csdev->enable || !coresight_disable_source(csdev, NULL))
1208 goto out;
1209
1210 switch (csdev->subtype.source_subtype) {
1211 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
1212 cpu = source_ops(csdev)->cpu_id(csdev);
1213 path = per_cpu(tracer_path, cpu);
1214 per_cpu(tracer_path, cpu) = NULL;
1215 break;
1216 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
1217 case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM:
1218 case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS:
1219 hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev)));
1220 /* Find the path by the hash. */
1221 path = idr_find(&path_idr, hash);
1222 if (path == NULL) {
1223 pr_err("Path is not found for %s\n", dev_name(&csdev->dev));
1224 goto out;
1225 }
1226 idr_remove(&path_idr, hash);
1227 break;
1228 default:
1229 /* We can't be here */
1230 break;
1231 }
1232
1233 coresight_disable_path(path);
1234 coresight_release_path(path);
1235
1236out:
1237 mutex_unlock(&coresight_mutex);
1238}
1239EXPORT_SYMBOL_GPL(coresight_disable);
1240
1241static ssize_t enable_sink_show(struct device *dev,
1242 struct device_attribute *attr, char *buf)
1243{
1244 struct coresight_device *csdev = to_coresight_device(dev);
1245
1246 return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->activated);
1247}
1248
1249static ssize_t enable_sink_store(struct device *dev,
1250 struct device_attribute *attr,
1251 const char *buf, size_t size)
1252{
1253 int ret;
1254 unsigned long val;
1255 struct coresight_device *csdev = to_coresight_device(dev);
1256
1257 ret = kstrtoul(buf, 10, &val);
1258 if (ret)
1259 return ret;
1260
1261 if (val)
1262 csdev->activated = true;
1263 else
1264 csdev->activated = false;
1265
1266 return size;
1267
1268}
1269static DEVICE_ATTR_RW(enable_sink);
1270
1271static ssize_t enable_source_show(struct device *dev,
1272 struct device_attribute *attr, char *buf)
1273{
1274 struct coresight_device *csdev = to_coresight_device(dev);
1275
1276 return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->enable);
1277}
1278
1279static ssize_t enable_source_store(struct device *dev,
1280 struct device_attribute *attr,
1281 const char *buf, size_t size)
1282{
1283 int ret = 0;
1284 unsigned long val;
1285 struct coresight_device *csdev = to_coresight_device(dev);
1286
1287 ret = kstrtoul(buf, 10, &val);
1288 if (ret)
1289 return ret;
1290
1291 if (val) {
1292 ret = coresight_enable(csdev);
1293 if (ret)
1294 return ret;
1295 } else {
1296 coresight_disable(csdev);
1297 }
1298
1299 return size;
1300}
1301static DEVICE_ATTR_RW(enable_source);
1302
1303static struct attribute *coresight_sink_attrs[] = {
1304 &dev_attr_enable_sink.attr,
1305 NULL,
1306};
1307ATTRIBUTE_GROUPS(coresight_sink);
1308
1309static struct attribute *coresight_source_attrs[] = {
1310 &dev_attr_enable_source.attr,
1311 NULL,
1312};
1313ATTRIBUTE_GROUPS(coresight_source);
1314
1315static struct device_type coresight_dev_type[] = {
1316 {
1317 .name = "sink",
1318 .groups = coresight_sink_groups,
1319 },
1320 {
1321 .name = "link",
1322 },
1323 {
1324 .name = "linksink",
1325 .groups = coresight_sink_groups,
1326 },
1327 {
1328 .name = "source",
1329 .groups = coresight_source_groups,
1330 },
1331 {
1332 .name = "helper",
1333 }
1334};
1335/* Ensure the enum matches the names and groups */
1336static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX);
1337
1338static void coresight_device_release(struct device *dev)900static void coresight_device_release(struct device *dev)
1339{901{
1340 struct coresight_device *csdev = to_coresight_device(dev);902 struct coresight_device *csdev = to_coresight_device(dev);
@@ -1799,7 +1361,7 @@ done: · 458 unmodified lines
1799}1361}
1800EXPORT_SYMBOL_GPL(coresight_alloc_device_name);1362EXPORT_SYMBOL_GPL(coresight_alloc_device_name);
1801 1363
1802struct bus_type coresight_bustype = {1364const struct bus_type coresight_bustype = {
1803 .name = "coresight",1365 .name = "coresight",
1804};1366};
1805 1367
drivers/hwtracing/coresight/coresight-cti-core.c+1−1
@@ -974,7 +974,7 @@ static const struct amba_id cti_ids[] = { · 973 unmodified lines
974 CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */974 CS_AMBA_ID(0x000bb9aa), /* CTI - C-A73 */
975 CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */975 CS_AMBA_UCI_ID(0x000bb9da, uci_id_cti), /* CTI - C-A35 */
976 CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */976 CS_AMBA_UCI_ID(0x000bb9ed, uci_id_cti), /* Coresight CTI (SoC 600) */
977 { 0, 0},977 { 0, 0, NULL },
978};978};
979 979
980MODULE_DEVICE_TABLE(amba, cti_ids);980MODULE_DEVICE_TABLE(amba, cti_ids);
drivers/hwtracing/coresight/coresight-etb10.c+15−16
@@ -76,7 +76,6 @@ DEFINE_CORESIGHT_DEVLIST(etb_devs, "etb"); · 75 unmodified lines
76 * @pid: Process ID of the process being monitored by the session76 * @pid: Process ID of the process being monitored by the session
77 * that is using this component.77 * that is using this component.
78 * @buf: area of memory where ETB buffer content gets sent.78 * @buf: area of memory where ETB buffer content gets sent.
79 * @mode: this ETB is being used.
80 * @buffer_depth: size of @buf.79 * @buffer_depth: size of @buf.
81 * @trigger_cntr: amount of words to store after a trigger.80 * @trigger_cntr: amount of words to store after a trigger.
82 */81 */
@@ -89,7 +88,6 @@ struct etb_drvdata { · 6 unmodified lines
89 local_t reading;88 local_t reading;
90 pid_t pid;89 pid_t pid;
91 u8 *buf;90 u8 *buf;
92 u32 mode;
93 u32 buffer_depth;91 u32 buffer_depth;
94 u32 trigger_cntr;92 u32 trigger_cntr;
95};93};
@@ -150,20 +148,20 @@ static int etb_enable_sysfs(struct coresight_device *csdev) · 54 unmodified lines
150 spin_lock_irqsave(&drvdata->spinlock, flags);148 spin_lock_irqsave(&drvdata->spinlock, flags);
151 149
152 /* Don't messup with perf sessions. */150 /* Don't messup with perf sessions. */
153 if (drvdata->mode == CS_MODE_PERF) {151 if (coresight_get_mode(csdev) == CS_MODE_PERF) {
154 ret = -EBUSY;152 ret = -EBUSY;
155 goto out;153 goto out;
156 }154 }
157 155
158 if (drvdata->mode == CS_MODE_DISABLED) {156 if (coresight_get_mode(csdev) == CS_MODE_DISABLED) {
159 ret = etb_enable_hw(drvdata);157 ret = etb_enable_hw(drvdata);
160 if (ret)158 if (ret)
161 goto out;159 goto out;
162 160
163 drvdata->mode = CS_MODE_SYSFS;161 coresight_set_mode(csdev, CS_MODE_SYSFS);
164 }162 }
165 163
166 atomic_inc(&csdev->refcnt);164 csdev->refcnt++;
167out:165out:
168 spin_unlock_irqrestore(&drvdata->spinlock, flags);166 spin_unlock_irqrestore(&drvdata->spinlock, flags);
169 return ret;167 return ret;
@@ -181,7 +179,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) · 11 unmodified lines
181 spin_lock_irqsave(&drvdata->spinlock, flags);179 spin_lock_irqsave(&drvdata->spinlock, flags);
182 180
183 /* No need to continue if the component is already in used by sysFS. */181 /* No need to continue if the component is already in used by sysFS. */
184 if (drvdata->mode == CS_MODE_SYSFS) {182 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
185 ret = -EBUSY;183 ret = -EBUSY;
186 goto out;184 goto out;
187 }185 }
@@ -199,7 +197,7 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) · 11 unmodified lines
199 * use for this session.197 * use for this session.
200 */198 */
201 if (drvdata->pid == pid) {199 if (drvdata->pid == pid) {
202 atomic_inc(&csdev->refcnt);200 csdev->refcnt++;
203 goto out;201 goto out;
204 }202 }
205 203
@@ -216,8 +214,8 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data) · 10 unmodified lines
216 if (!ret) {214 if (!ret) {
217 /* Associate with monitored process. */215 /* Associate with monitored process. */
218 drvdata->pid = pid;216 drvdata->pid = pid;
219 drvdata->mode = CS_MODE_PERF;217 coresight_set_mode(drvdata->csdev, CS_MODE_PERF);
220 atomic_inc(&csdev->refcnt);218 csdev->refcnt++;
221 }219 }
222 220
223out:221out:
@@ -356,17 +354,18 @@ static int etb_disable(struct coresight_device *csdev) · 132 unmodified lines
356 354
357 spin_lock_irqsave(&drvdata->spinlock, flags);355 spin_lock_irqsave(&drvdata->spinlock, flags);
358 356
359 if (atomic_dec_return(&csdev->refcnt)) {357 csdev->refcnt--;
358 if (csdev->refcnt) {
360 spin_unlock_irqrestore(&drvdata->spinlock, flags);359 spin_unlock_irqrestore(&drvdata->spinlock, flags);
361 return -EBUSY;360 return -EBUSY;
362 }361 }
363 362
364 /* Complain if we (somehow) got out of sync */363 /* Complain if we (somehow) got out of sync */
365 WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);364 WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
366 etb_disable_hw(drvdata);365 etb_disable_hw(drvdata);
367 /* Dissociate from monitored process. */366 /* Dissociate from monitored process. */
368 drvdata->pid = -1;367 drvdata->pid = -1;
369 drvdata->mode = CS_MODE_DISABLED;368 coresight_set_mode(csdev, CS_MODE_DISABLED);
370 spin_unlock_irqrestore(&drvdata->spinlock, flags);369 spin_unlock_irqrestore(&drvdata->spinlock, flags);
371 370
372 dev_dbg(&csdev->dev, "ETB disabled\n");371 dev_dbg(&csdev->dev, "ETB disabled\n");
@@ -447,7 +446,7 @@ static unsigned long etb_update_buffer(struct coresight_device *csdev, · 74 unmodified lines
447 spin_lock_irqsave(&drvdata->spinlock, flags);446 spin_lock_irqsave(&drvdata->spinlock, flags);
448 447
449 /* Don't do anything if another tracer is using this sink */448 /* Don't do anything if another tracer is using this sink */
450 if (atomic_read(&csdev->refcnt) != 1)449 if (csdev->refcnt != 1)
451 goto out;450 goto out;
452 451
453 __etb_disable_hw(drvdata);452 __etb_disable_hw(drvdata);
@@ -589,7 +588,7 @@ static void etb_dump(struct etb_drvdata *drvdata) · 135 unmodified lines
589 unsigned long flags;588 unsigned long flags;
590 589
591 spin_lock_irqsave(&drvdata->spinlock, flags);590 spin_lock_irqsave(&drvdata->spinlock, flags);
592 if (drvdata->mode == CS_MODE_SYSFS) {591 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
593 __etb_disable_hw(drvdata);592 __etb_disable_hw(drvdata);
594 etb_dump_hw(drvdata);593 etb_dump_hw(drvdata);
595 __etb_enable_hw(drvdata);594 __etb_enable_hw(drvdata);
@@ -837,7 +836,7 @@ static const struct amba_id etb_ids[] = { · 241 unmodified lines
837 .id = 0x000bb907,836 .id = 0x000bb907,
838 .mask = 0x000fffff,837 .mask = 0x000fffff,
839 },838 },
840 { 0, 0},839 { 0, 0, NULL },
841};840};
842 841
843MODULE_DEVICE_TABLE(amba, etb_ids);842MODULE_DEVICE_TABLE(amba, etb_ids);
drivers/hwtracing/coresight/coresight-etm-perf.c+1−1
@@ -589,7 +589,7 @@ static void etm_event_stop(struct perf_event *event, int mode) · 588 unmodified lines
589 return;589 return;
590 590
591 /* stop tracer */591 /* stop tracer */
592 source_ops(csdev)->disable(csdev, event);592 coresight_disable_source(csdev, event);
593 593
594 /* tell the core */594 /* tell the core */
595 event->hw.state = PERF_HES_STOPPED;595 event->hw.state = PERF_HES_STOPPED;
drivers/hwtracing/coresight/coresight-etm.h+0−2
@@ -215,7 +215,6 @@ struct etm_config { · 214 unmodified lines
215 * @port_size: port size as reported by ETMCR bit 4-6 and 21.215 * @port_size: port size as reported by ETMCR bit 4-6 and 21.
216 * @arch: ETM/PTM version number.216 * @arch: ETM/PTM version number.
217 * @use_cpu14: true if management registers need to be accessed via CP14.217 * @use_cpu14: true if management registers need to be accessed via CP14.
218 * @mode: this tracer's mode, i.e sysFS, Perf or disabled.
219 * @sticky_enable: true if ETM base configuration has been done.218 * @sticky_enable: true if ETM base configuration has been done.
220 * @boot_enable:true if we should start tracing at boot time.219 * @boot_enable:true if we should start tracing at boot time.
221 * @os_unlock: true if access to management registers is allowed.220 * @os_unlock: true if access to management registers is allowed.
@@ -238,7 +237,6 @@ struct etm_drvdata { · 16 unmodified lines
238 int port_size;237 int port_size;
239 u8 arch;238 u8 arch;
240 bool use_cp14;239 bool use_cp14;
241 local_t mode;
242 bool sticky_enable;240 bool sticky_enable;
243 bool boot_enable;241 bool boot_enable;
244 bool os_unlock;242 bool os_unlock;
drivers/hwtracing/coresight/coresight-etm3x-core.c+12−15
@@ -115,7 +115,7 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata) · 114 unmodified lines
115 *115 *
116 * Basically the same as @coresight_timeout except for the register access116 * Basically the same as @coresight_timeout except for the register access
117 * method where we have to account for CP14 configurations.117 * method where we have to account for CP14 configurations.
118 118 *
119 * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if119 * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
120 * TIMEOUT_US has elapsed, which ever happens first.120 * TIMEOUT_US has elapsed, which ever happens first.
121 */121 */
@@ -556,14 +556,12 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event, · 434 unmodified lines
556 enum cs_mode mode)556 enum cs_mode mode)
557{557{
558 int ret;558 int ret;
559 u32 val;
560 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);559 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
561 560
562 val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);561 if (!coresight_take_mode(csdev, mode)) {
563 562 /* Someone is already using the tracer */
564 /* Someone is already using the tracer */
565 if (val)
566 return -EBUSY;563 return -EBUSY;
564 }
567 565
568 switch (mode) {566 switch (mode) {
569 case CS_MODE_SYSFS:567 case CS_MODE_SYSFS:
@@ -578,7 +576,7 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event, · 8 unmodified lines
578 576
579 /* The tracer didn't start */577 /* The tracer didn't start */
580 if (ret)578 if (ret)
581 local_set(&drvdata->mode, CS_MODE_DISABLED);579 coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
582 580
583 return ret;581 return ret;
584}582}
@@ -672,14 +670,13 @@ static void etm_disable(struct coresight_device *csdev, · 87 unmodified lines
672 struct perf_event *event)670 struct perf_event *event)
673{671{
674 enum cs_mode mode;672 enum cs_mode mode;
675 struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
676 673
677 /*674 /*
678 * For as long as the tracer isn't disabled another entity can't675 * For as long as the tracer isn't disabled another entity can't
679 * change its status. As such we can read the status here without676 * change its status. As such we can read the status here without
680 * fearing it will change under us.677 * fearing it will change under us.
681 */678 */
682 mode = local_read(&drvdata->mode);679 mode = coresight_get_mode(csdev);
683 680
684 switch (mode) {681 switch (mode) {
685 case CS_MODE_DISABLED:682 case CS_MODE_DISABLED:
@@ -696,7 +693,7 @@ static void etm_disable(struct coresight_device *csdev, · 10 unmodified lines
696 }693 }
697 694
698 if (mode)695 if (mode)
699 local_set(&drvdata->mode, CS_MODE_DISABLED);696 coresight_set_mode(csdev, CS_MODE_DISABLED);
700}697}
701 698
702static const struct coresight_ops_source etm_source_ops = {699static const struct coresight_ops_source etm_source_ops = {
@@ -715,7 +712,7 @@ static int etm_online_cpu(unsigned int cpu) · 12 unmodified lines
715 return 0;712 return 0;
716 713
717 if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable)714 if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable)
718 coresight_enable(etmdrvdata[cpu]->csdev);715 coresight_enable_sysfs(etmdrvdata[cpu]->csdev);
719 return 0;716 return 0;
720}717}
721 718
@@ -730,7 +727,7 @@ static int etm_starting_cpu(unsigned int cpu) · 8 unmodified lines
730 etmdrvdata[cpu]->os_unlock = true;727 etmdrvdata[cpu]->os_unlock = true;
731 }728 }
732 729
733 if (local_read(&etmdrvdata[cpu]->mode))730 if (coresight_get_mode(etmdrvdata[cpu]->csdev))
734 etm_enable_hw(etmdrvdata[cpu]);731 etm_enable_hw(etmdrvdata[cpu]);
735 spin_unlock(&etmdrvdata[cpu]->spinlock);732 spin_unlock(&etmdrvdata[cpu]->spinlock);
736 return 0;733 return 0;
@@ -742,7 +739,7 @@ static int etm_dying_cpu(unsigned int cpu) · 5 unmodified lines
742 return 0;739 return 0;
743 740
744 spin_lock(&etmdrvdata[cpu]->spinlock);741 spin_lock(&etmdrvdata[cpu]->spinlock);
745 if (local_read(&etmdrvdata[cpu]->mode))742 if (coresight_get_mode(etmdrvdata[cpu]->csdev))
746 etm_disable_hw(etmdrvdata[cpu]);743 etm_disable_hw(etmdrvdata[cpu]);
747 spin_unlock(&etmdrvdata[cpu]->spinlock);744 spin_unlock(&etmdrvdata[cpu]->spinlock);
748 return 0;745 return 0;
@@ -925,7 +922,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) · 176 unmodified lines
925 dev_info(&drvdata->csdev->dev,922 dev_info(&drvdata->csdev->dev,
926 "%s initialized\n", (char *)coresight_get_uci_data(id));923 "%s initialized\n", (char *)coresight_get_uci_data(id));
927 if (boot_enable) {924 if (boot_enable) {
928 coresight_enable(drvdata->csdev);925 coresight_enable_sysfs(drvdata->csdev);
929 drvdata->boot_enable = true;926 drvdata->boot_enable = true;
930 }927 }
931 928
@@ -1003,7 +1000,7 @@ static const struct amba_id etm_ids[] = { · 71 unmodified lines
1003 CS_AMBA_ID_DATA(0x000bb95f, "PTM 1.1"),1000 CS_AMBA_ID_DATA(0x000bb95f, "PTM 1.1"),
1004 /* PTM 1.1 Qualcomm */1001 /* PTM 1.1 Qualcomm */
1005 CS_AMBA_ID_DATA(0x000b006f, "PTM 1.1"),1002 CS_AMBA_ID_DATA(0x000b006f, "PTM 1.1"),
1006 { 0, 0},1003 { 0, 0, NULL},
1007};1004};
1008 1005
1009MODULE_DEVICE_TABLE(amba, etm_ids);1006MODULE_DEVICE_TABLE(amba, etm_ids);
drivers/hwtracing/coresight/coresight-etm3x-sysfs.c+2−2
@@ -722,7 +722,7 @@ static ssize_t cntr_val_show(struct device *dev, · 721 unmodified lines
722 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);722 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
723 struct etm_config *config = &drvdata->config;723 struct etm_config *config = &drvdata->config;
724 724
725 if (!local_read(&drvdata->mode)) {725 if (!coresight_get_mode(drvdata->csdev)) {
726 spin_lock(&drvdata->spinlock);726 spin_lock(&drvdata->spinlock);
727 for (i = 0; i < drvdata->nr_cntr; i++)727 for (i = 0; i < drvdata->nr_cntr; i++)
728 ret += sprintf(buf, "counter %d: %x\n",728 ret += sprintf(buf, "counter %d: %x\n",
@@ -941,7 +941,7 @@ static ssize_t seq_curr_state_show(struct device *dev, · 212 unmodified lines
941 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);941 struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
942 struct etm_config *config = &drvdata->config;942 struct etm_config *config = &drvdata->config;
943 943
944 if (!local_read(&drvdata->mode)) {944 if (!coresight_get_mode(drvdata->csdev)) {
945 val = config->seq_curr_state;945 val = config->seq_curr_state;
946 goto out;946 goto out;
947 }947 }
drivers/hwtracing/coresight/coresight-etm4x-core.c+17−21
@@ -840,14 +840,11 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event, · 839 unmodified lines
840 enum cs_mode mode)840 enum cs_mode mode)
841{841{
842 int ret;842 int ret;
843 u32 val;
844 struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
845
846 val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);
847 843
848 /* Someone is already using the tracer */844 if (!coresight_take_mode(csdev, mode)) {
849 if (val)845 /* Someone is already using the tracer */
850 return -EBUSY;846 return -EBUSY;
847 }
851 848
852 switch (mode) {849 switch (mode) {
853 case CS_MODE_SYSFS:850 case CS_MODE_SYSFS:
@@ -862,7 +859,7 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event, · 8 unmodified lines
862 859
863 /* The tracer didn't start */860 /* The tracer didn't start */
864 if (ret)861 if (ret)
865 local_set(&drvdata->mode, CS_MODE_DISABLED);862 coresight_set_mode(csdev, CS_MODE_DISABLED);
866 863
867 return ret;864 return ret;
868}865}
@@ -1004,14 +1001,13 @@ static void etm4_disable(struct coresight_device *csdev, · 135 unmodified lines
1004 struct perf_event *event)1001 struct perf_event *event)
1005{1002{
1006 enum cs_mode mode;1003 enum cs_mode mode;
1007 struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
1008 1004
1009 /*1005 /*
1010 * For as long as the tracer isn't disabled another entity can't1006 * For as long as the tracer isn't disabled another entity can't
1011 * change its status. As such we can read the status here without1007 * change its status. As such we can read the status here without
1012 * fearing it will change under us.1008 * fearing it will change under us.
1013 */1009 */
1014 mode = local_read(&drvdata->mode);1010 mode = coresight_get_mode(csdev);
1015 1011
1016 switch (mode) {1012 switch (mode) {
1017 case CS_MODE_DISABLED:1013 case CS_MODE_DISABLED:
@@ -1025,7 +1021,7 @@ static void etm4_disable(struct coresight_device *csdev, · 7 unmodified lines
1025 }1021 }
1026 1022
1027 if (mode)1023 if (mode)
1028 local_set(&drvdata->mode, CS_MODE_DISABLED);1024 coresight_set_mode(csdev, CS_MODE_DISABLED);
1029}1025}
1030 1026
1031static const struct coresight_ops_source etm4_source_ops = {1027static const struct coresight_ops_source etm4_source_ops = {
@@ -1200,6 +1196,7 @@ static void etm4_init_arch_data(void *info) · 168 unmodified lines
1200 struct etm4_init_arg *init_arg = info;1196 struct etm4_init_arg *init_arg = info;
1201 struct etmv4_drvdata *drvdata;1197 struct etmv4_drvdata *drvdata;
1202 struct csdev_access *csa;1198 struct csdev_access *csa;
1199 struct device *dev = init_arg->dev;
1203 int i;1200 int i;
1204 1201
1205 drvdata = dev_get_drvdata(init_arg->dev);1202 drvdata = dev_get_drvdata(init_arg->dev);
@@ -1213,6 +1210,10 @@ static void etm4_init_arch_data(void *info) · 7 unmodified lines
1213 if (!etm4_init_csdev_access(drvdata, csa))1210 if (!etm4_init_csdev_access(drvdata, csa))
1214 return;1211 return;
1215 1212
1213 if (!csa->io_mem ||
1214 fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
1215 drvdata->skip_power_up = true;
1216
1216 /* Detect the support for OS Lock before we actually use it */1217 /* Detect the support for OS Lock before we actually use it */
1217 etm_detect_os_lock(drvdata, csa);1218 etm_detect_os_lock(drvdata, csa);
1218 1219
@@ -1650,7 +1651,7 @@ static int etm4_online_cpu(unsigned int cpu) · 431 unmodified lines
1650 return etm4_probe_cpu(cpu);1651 return etm4_probe_cpu(cpu);
1651 1652
1652 if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable)1653 if (etmdrvdata[cpu]->boot_enable && !etmdrvdata[cpu]->sticky_enable)
1653 coresight_enable(etmdrvdata[cpu]->csdev);1654 coresight_enable_sysfs(etmdrvdata[cpu]->csdev);
1654 return 0;1655 return 0;
1655}1656}
1656 1657
@@ -1663,7 +1664,7 @@ static int etm4_starting_cpu(unsigned int cpu) · 6 unmodified lines
1663 if (!etmdrvdata[cpu]->os_unlock)1664 if (!etmdrvdata[cpu]->os_unlock)
1664 etm4_os_unlock(etmdrvdata[cpu]);1665 etm4_os_unlock(etmdrvdata[cpu]);
1665 1666
1666 if (local_read(&etmdrvdata[cpu]->mode))1667 if (coresight_get_mode(etmdrvdata[cpu]->csdev))
1667 etm4_enable_hw(etmdrvdata[cpu]);1668 etm4_enable_hw(etmdrvdata[cpu]);
1668 spin_unlock(&etmdrvdata[cpu]->spinlock);1669 spin_unlock(&etmdrvdata[cpu]->spinlock);
1669 return 0;1670 return 0;
@@ -1675,7 +1676,7 @@ static int etm4_dying_cpu(unsigned int cpu) · 5 unmodified lines
1675 return 0;1676 return 0;
1676 1677
1677 spin_lock(&etmdrvdata[cpu]->spinlock);1678 spin_lock(&etmdrvdata[cpu]->spinlock);
1678 if (local_read(&etmdrvdata[cpu]->mode))1679 if (coresight_get_mode(etmdrvdata[cpu]->csdev))
1679 etm4_disable_hw(etmdrvdata[cpu]);1680 etm4_disable_hw(etmdrvdata[cpu]);
1680 spin_unlock(&etmdrvdata[cpu]->spinlock);1681 spin_unlock(&etmdrvdata[cpu]->spinlock);
1681 return 0;1682 return 0;
@@ -1833,7 +1834,7 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata) · 151 unmodified lines
1833 * Save and restore the ETM Trace registers only if1834 * Save and restore the ETM Trace registers only if
1834 * the ETM is active.1835 * the ETM is active.
1835 */1836 */
1836 if (local_read(&drvdata->mode) && drvdata->save_state)1837 if (coresight_get_mode(drvdata->csdev) && drvdata->save_state)
1837 ret = __etm4_cpu_save(drvdata);1838 ret = __etm4_cpu_save(drvdata);
1838 return ret;1839 return ret;
1839}1840}
@@ -2040,11 +2041,6 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) · 200 unmodified lines
2040 if (!drvdata->arch)2041 if (!drvdata->arch)
2041 return -EINVAL;2042 return -EINVAL;
2042 2043
2043 /* TRCPDCR is not accessible with system instructions. */
2044 if (!desc.access.io_mem ||
2045 fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
2046 drvdata->skip_power_up = true;
2047
2048 major = ETM_ARCH_MAJOR_VERSION(drvdata->arch);2044 major = ETM_ARCH_MAJOR_VERSION(drvdata->arch);
2049 minor = ETM_ARCH_MINOR_VERSION(drvdata->arch);2045 minor = ETM_ARCH_MINOR_VERSION(drvdata->arch);
2050 2046
@@ -2098,7 +2094,7 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg) · 47 unmodified lines
2098 drvdata->cpu, type_name, major, minor);2094 drvdata->cpu, type_name, major, minor);
2099 2095
2100 if (boot_enable) {2096 if (boot_enable) {
2101 coresight_enable(drvdata->csdev);2097 coresight_enable_sysfs(drvdata->csdev);
2102 drvdata->boot_enable = true;2098 drvdata->boot_enable = true;
2103 }2099 }
2104 2100
@@ -2390,7 +2386,7 @@ static const struct of_device_id etm4_sysreg_match[] = { · 285 unmodified lines
2390 2386
2391#ifdef CONFIG_ACPI2387#ifdef CONFIG_ACPI
2392static const struct acpi_device_id etm4x_acpi_ids[] = {2388static const struct acpi_device_id etm4x_acpi_ids[] = {
2393 {"ARMHC500", 0}, /* ARM CoreSight ETM4x */2389 {"ARMHC500", 0, 0, 0}, /* ARM CoreSight ETM4x */
2394 {}2390 {}
2395};2391};
2396MODULE_DEVICE_TABLE(acpi, etm4x_acpi_ids);2392MODULE_DEVICE_TABLE(acpi, etm4x_acpi_ids);
drivers/hwtracing/coresight/coresight-etm4x.h+0−1
@@ -1016,7 +1016,6 @@ struct etmv4_drvdata { · 1015 unmodified lines
1016 void __iomem *base;1016 void __iomem *base;
1017 struct coresight_device *csdev;1017 struct coresight_device *csdev;
1018 spinlock_t spinlock;1018 spinlock_t spinlock;
1019 local_t mode;
1020 int cpu;1019 int cpu;
1021 u8 arch;1020 u8 arch;
1022 u8 nr_pe;1021 u8 nr_pe;
drivers/hwtracing/coresight/coresight-funnel.c+2−2
@@ -350,7 +350,7 @@ MODULE_DEVICE_TABLE(of, static_funnel_match); · 349 unmodified lines
350 350
351#ifdef CONFIG_ACPI351#ifdef CONFIG_ACPI
352static const struct acpi_device_id static_funnel_ids[] = {352static const struct acpi_device_id static_funnel_ids[] = {
353 {"ARMHC9FE", 0},353 {"ARMHC9FE", 0, 0, 0},
354 {},354 {},
355};355};
356 356
@@ -391,7 +391,7 @@ static const struct amba_id dynamic_funnel_ids[] = { · 34 unmodified lines
391 .id = 0x000bb9eb,391 .id = 0x000bb9eb,
392 .mask = 0x000fffff,392 .mask = 0x000fffff,
393 },393 },
394 { 0, 0},394 { 0, 0, NULL },
395};395};
396 396
397MODULE_DEVICE_TABLE(amba, dynamic_funnel_ids);397MODULE_DEVICE_TABLE(amba, dynamic_funnel_ids);
drivers/hwtracing/coresight/coresight-priv.h+4−5
@@ -12,6 +12,9 @@ · 11 unmodified lines
12#include <linux/coresight.h>12#include <linux/coresight.h>
13#include <linux/pm_runtime.h>13#include <linux/pm_runtime.h>
14 14
15extern struct mutex coresight_mutex;
16extern struct device_type coresight_dev_type[];
17
15/*18/*
16 * Coresight management registers (0xf00-0xfcc)19 * Coresight management registers (0xf00-0xfcc)
17 * 0xfa0 - 0xfa4: Management registers in PFTv1.020 * 0xfa0 - 0xfa4: Management registers in PFTv1.0
@@ -130,8 +133,6 @@ void coresight_disable_path(struct list_head *path); · 112 unmodified lines
130int coresight_enable_path(struct list_head *path, enum cs_mode mode,133int coresight_enable_path(struct list_head *path, enum cs_mode mode,
131 void *sink_data);134 void *sink_data);
132struct coresight_device *coresight_get_sink(struct list_head *path);135struct coresight_device *coresight_get_sink(struct list_head *path);
133struct coresight_device *
134coresight_get_enabled_sink(struct coresight_device *source);
135struct coresight_device *coresight_get_sink_by_id(u32 id);136struct coresight_device *coresight_get_sink_by_id(u32 id);
136struct coresight_device *137struct coresight_device *
137coresight_find_default_sink(struct coresight_device *csdev);138coresight_find_default_sink(struct coresight_device *csdev);
@@ -231,8 +232,6 @@ void coresight_add_helper(struct coresight_device *csdev, · 93 unmodified lines
231 232
232void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);233void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
233struct coresight_device *coresight_get_percpu_sink(int cpu);234struct coresight_device *coresight_get_percpu_sink(int cpu);
234int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,235void coresight_disable_source(struct coresight_device *csdev, void *data);
235 void *data);
236bool coresight_disable_source(struct coresight_device *csdev, void *data);
237 236
238#endif237#endif
drivers/hwtracing/coresight/coresight-replicator.c+1−1
@@ -363,7 +363,7 @@ MODULE_DEVICE_TABLE(of, static_replicator_match); · 362 unmodified lines
363 363
364#ifdef CONFIG_ACPI364#ifdef CONFIG_ACPI
365static const struct acpi_device_id static_replicator_acpi_ids[] = {365static const struct acpi_device_id static_replicator_acpi_ids[] = {
366 {"ARMHC985", 0}, /* ARM CoreSight Static Replicator */366 {"ARMHC985", 0, 0, 0}, /* ARM CoreSight Static Replicator */
367 {}367 {}
368};368};
369 369
drivers/hwtracing/coresight/coresight-stm.c+14−18
@@ -119,7 +119,6 @@ DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm"); · 118 unmodified lines
119 * @spinlock: only one at a time pls.119 * @spinlock: only one at a time pls.
120 * @chs: the channels accociated to this STM.120 * @chs: the channels accociated to this STM.
121 * @stm: structure associated to the generic STM interface.121 * @stm: structure associated to the generic STM interface.
122 * @mode: this tracer's mode (enum cs_mode), i.e sysFS, or disabled.
123 * @traceid: value of the current ID for this component.122 * @traceid: value of the current ID for this component.
124 * @write_bytes: Maximus bytes this STM can write at a time.123 * @write_bytes: Maximus bytes this STM can write at a time.
125 * @stmsper: settings for register STMSPER.124 * @stmsper: settings for register STMSPER.
@@ -136,7 +135,6 @@ struct stm_drvdata { · 10 unmodified lines
136 spinlock_t spinlock;135 spinlock_t spinlock;
137 struct channel_space chs;136 struct channel_space chs;
138 struct stm_data stm;137 struct stm_data stm;
139 local_t mode;
140 u8 traceid;138 u8 traceid;
141 u32 write_bytes;139 u32 write_bytes;
142 u32 stmsper;140 u32 stmsper;
@@ -195,17 +193,15 @@ static void stm_enable_hw(struct stm_drvdata *drvdata) · 52 unmodified lines
195static int stm_enable(struct coresight_device *csdev, struct perf_event *event,193static int stm_enable(struct coresight_device *csdev, struct perf_event *event,
196 enum cs_mode mode)194 enum cs_mode mode)
197{195{
198 u32 val;
199 struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);196 struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
200 197
201 if (mode != CS_MODE_SYSFS)198 if (mode != CS_MODE_SYSFS)
202 return -EINVAL;199 return -EINVAL;
203 200
204 val = local_cmpxchg(&drvdata->mode, CS_MODE_DISABLED, mode);201 if (!coresight_take_mode(csdev, mode)) {
205 202 /* Someone is already using the tracer */
206 /* Someone is already using the tracer */
207 if (val)
208 return -EBUSY;203 return -EBUSY;
204 }
209 205
210 pm_runtime_get_sync(csdev->dev.parent);206 pm_runtime_get_sync(csdev->dev.parent);
211 207
@@ -266,7 +262,7 @@ static void stm_disable(struct coresight_device *csdev, · 54 unmodified lines
266 * change its status. As such we can read the status here without262 * change its status. As such we can read the status here without
267 * fearing it will change under us.263 * fearing it will change under us.
268 */264 */
269 if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {265 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
270 spin_lock(&drvdata->spinlock);266 spin_lock(&drvdata->spinlock);
271 stm_disable_hw(drvdata);267 stm_disable_hw(drvdata);
272 spin_unlock(&drvdata->spinlock);268 spin_unlock(&drvdata->spinlock);
@@ -276,7 +272,7 @@ static void stm_disable(struct coresight_device *csdev, · 3 unmodified lines
276 272
277 pm_runtime_put(csdev->dev.parent);273 pm_runtime_put(csdev->dev.parent);
278 274
279 local_set(&drvdata->mode, CS_MODE_DISABLED);275 coresight_set_mode(csdev, CS_MODE_DISABLED);
280 dev_dbg(&csdev->dev, "STM tracing disabled\n");276 dev_dbg(&csdev->dev, "STM tracing disabled\n");
281 }277 }
282}278}
@@ -334,7 +330,7 @@ static int stm_generic_link(struct stm_data *stm_data, · 51 unmodified lines
334 if (!drvdata || !drvdata->csdev)330 if (!drvdata || !drvdata->csdev)
335 return -EINVAL;331 return -EINVAL;
336 332
337 return coresight_enable(drvdata->csdev);333 return coresight_enable_sysfs(drvdata->csdev);
338}334}
339 335
340static void stm_generic_unlink(struct stm_data *stm_data,336static void stm_generic_unlink(struct stm_data *stm_data,
@@ -345,7 +341,7 @@ static void stm_generic_unlink(struct stm_data *stm_data, · 4 unmodified lines
345 if (!drvdata || !drvdata->csdev)341 if (!drvdata || !drvdata->csdev)
346 return;342 return;
347 343
348 coresight_disable(drvdata->csdev);344 coresight_disable_sysfs(drvdata->csdev);
349}345}
350 346
351static phys_addr_t347static phys_addr_t
@@ -373,7 +369,7 @@ static long stm_generic_set_options(struct stm_data *stm_data, · 21 unmodified lines
373{369{
374 struct stm_drvdata *drvdata = container_of(stm_data,370 struct stm_drvdata *drvdata = container_of(stm_data,
375 struct stm_drvdata, stm);371 struct stm_drvdata, stm);
376 if (!(drvdata && local_read(&drvdata->mode)))372 if (!(drvdata && coresight_get_mode(drvdata->csdev)))
377 return -EINVAL;373 return -EINVAL;
378 374
379 if (channel >= drvdata->numsp)375 if (channel >= drvdata->numsp)
@@ -408,7 +404,7 @@ static ssize_t notrace stm_generic_packet(struct stm_data *stm_data, · 28 unmodified lines
408 struct stm_drvdata, stm);404 struct stm_drvdata, stm);
409 unsigned int stm_flags;405 unsigned int stm_flags;
410 406
411 if (!(drvdata && local_read(&drvdata->mode)))407 if (!(drvdata && coresight_get_mode(drvdata->csdev)))
412 return -EACCES;408 return -EACCES;
413 409
414 if (channel >= drvdata->numsp)410 if (channel >= drvdata->numsp)
@@ -515,7 +511,7 @@ static ssize_t port_select_show(struct device *dev, · 100 unmodified lines
515 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);511 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
516 unsigned long val;512 unsigned long val;
517 513
518 if (!local_read(&drvdata->mode)) {514 if (!coresight_get_mode(drvdata->csdev)) {
519 val = drvdata->stmspscr;515 val = drvdata->stmspscr;
520 } else {516 } else {
521 spin_lock(&drvdata->spinlock);517 spin_lock(&drvdata->spinlock);
@@ -541,7 +537,7 @@ static ssize_t port_select_store(struct device *dev, · 19 unmodified lines
541 spin_lock(&drvdata->spinlock);537 spin_lock(&drvdata->spinlock);
542 drvdata->stmspscr = val;538 drvdata->stmspscr = val;
543 539
544 if (local_read(&drvdata->mode)) {540 if (coresight_get_mode(drvdata->csdev)) {
545 CS_UNLOCK(drvdata->base);541 CS_UNLOCK(drvdata->base);
546 /* Process as per ARM's TRM recommendation */542 /* Process as per ARM's TRM recommendation */
547 stmsper = readl_relaxed(drvdata->base + STMSPER);543 stmsper = readl_relaxed(drvdata->base + STMSPER);
@@ -562,7 +558,7 @@ static ssize_t port_enable_show(struct device *dev, · 14 unmodified lines
562 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);558 struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
563 unsigned long val;559 unsigned long val;
564 560
565 if (!local_read(&drvdata->mode)) {561 if (!coresight_get_mode(drvdata->csdev)) {
566 val = drvdata->stmsper;562 val = drvdata->stmsper;
567 } else {563 } else {
568 spin_lock(&drvdata->spinlock);564 spin_lock(&drvdata->spinlock);
@@ -588,7 +584,7 @@ static ssize_t port_enable_store(struct device *dev, · 19 unmodified lines
588 spin_lock(&drvdata->spinlock);584 spin_lock(&drvdata->spinlock);
589 drvdata->stmsper = val;585 drvdata->stmsper = val;
590 586
591 if (local_read(&drvdata->mode)) {587 if (coresight_get_mode(drvdata->csdev)) {
592 CS_UNLOCK(drvdata->base);588 CS_UNLOCK(drvdata->base);
593 writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);589 writel_relaxed(drvdata->stmsper, drvdata->base + STMSPER);
594 CS_LOCK(drvdata->base);590 CS_LOCK(drvdata->base);
@@ -950,7 +946,7 @@ static const struct dev_pm_ops stm_dev_pm_ops = { · 355 unmodified lines
950static const struct amba_id stm_ids[] = {946static const struct amba_id stm_ids[] = {
951 CS_AMBA_ID_DATA(0x000bb962, "STM32"),947 CS_AMBA_ID_DATA(0x000bb962, "STM32"),
952 CS_AMBA_ID_DATA(0x000bb963, "STM500"),948 CS_AMBA_ID_DATA(0x000bb963, "STM500"),
953 { 0, 0},949 { 0, 0, NULL },
954};950};
955 951
956MODULE_DEVICE_TABLE(amba, stm_ids);952MODULE_DEVICE_TABLE(amba, stm_ids);
drivers/hwtracing/coresight/coresight-sysfs.c+391−0
@@ -5,10 +5,401 @@ · 4 unmodified lines
5 */5 */
6 6
7#include <linux/device.h>7#include <linux/device.h>
8#include <linux/idr.h>
8#include <linux/kernel.h>9#include <linux/kernel.h>
9 10
10#include "coresight-priv.h"11#include "coresight-priv.h"
11 12
13/*
14 * Use IDR to map the hash of the source's device name
15 * to the pointer of path for the source. The idr is for
16 * the sources which aren't associated with CPU.
17 */
18static DEFINE_IDR(path_idr);
19
20/*
21 * When operating Coresight drivers from the sysFS interface, only a single
22 * path can exist from a tracer (associated to a CPU) to a sink.
23 */
24static DEFINE_PER_CPU(struct list_head *, tracer_path);
25
26ssize_t coresight_simple_show_pair(struct device *_dev,
27 struct device_attribute *attr, char *buf)
28{
29 struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev);
30 struct cs_pair_attribute *cs_attr = container_of(attr, struct cs_pair_attribute, attr);
31 u64 val;
32
33 pm_runtime_get_sync(_dev->parent);
34 val = csdev_access_relaxed_read_pair(&csdev->access, cs_attr->lo_off, cs_attr->hi_off);
35 pm_runtime_put_sync(_dev->parent);
36 return sysfs_emit(buf, "0x%llx\n", val);
37}
38EXPORT_SYMBOL_GPL(coresight_simple_show_pair);
39
40ssize_t coresight_simple_show32(struct device *_dev,
41 struct device_attribute *attr, char *buf)
42{
43 struct coresight_device *csdev = container_of(_dev, struct coresight_device, dev);
44 struct cs_off_attribute *cs_attr = container_of(attr, struct cs_off_attribute, attr);
45 u64 val;
46
47 pm_runtime_get_sync(_dev->parent);
48 val = csdev_access_relaxed_read32(&csdev->access, cs_attr->off);
49 pm_runtime_put_sync(_dev->parent);
50 return sysfs_emit(buf, "0x%llx\n", val);
51}
52EXPORT_SYMBOL_GPL(coresight_simple_show32);
53
54static int coresight_enable_source_sysfs(struct coresight_device *csdev,
55 enum cs_mode mode, void *data)
56{
57 int ret;
58
59 /*
60 * Comparison with CS_MODE_SYSFS works without taking any device
61 * specific spinlock because the truthyness of that comparison can only
62 * change with coresight_mutex held, which we already have here.
63 */
64 lockdep_assert_held(&coresight_mutex);
65 if (coresight_get_mode(csdev) != CS_MODE_SYSFS) {
66 ret = source_ops(csdev)->enable(csdev, data, mode);
67 if (ret)
68 return ret;
69 }
70
71 csdev->refcnt++;
72
73 return 0;
74}
75
76/**
77 * coresight_disable_source_sysfs - Drop the reference count by 1 and disable
78 * the device if there are no users left.
79 *
80 * @csdev: The coresight device to disable
81 * @data: Opaque data to pass on to the disable function of the source device.
82 * For example in perf mode this is a pointer to the struct perf_event.
83 *
84 * Returns true if the device has been disabled.
85 */
86static bool coresight_disable_source_sysfs(struct coresight_device *csdev,
87 void *data)
88{
89 lockdep_assert_held(&coresight_mutex);
90 if (coresight_get_mode(csdev) != CS_MODE_SYSFS)
91 return false;
92
93 csdev->refcnt--;
94 if (csdev->refcnt == 0) {
95 coresight_disable_source(csdev, data);
96 return true;
97 }
98 return false;
99}
100
101/**
102 * coresight_find_activated_sysfs_sink - returns the first sink activated via
103 * sysfs using connection based search starting from the source reference.
104 *
105 * @csdev: Coresight source device reference
106 */
107static struct coresight_device *
108coresight_find_activated_sysfs_sink(struct coresight_device *csdev)
109{
110 int i;
111 struct coresight_device *sink = NULL;
112
113 if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
114 csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
115 csdev->sysfs_sink_activated)
116 return csdev;
117
118 /*
119 * Recursively explore each port found on this element.
120 */
121 for (i = 0; i < csdev->pdata->nr_outconns; i++) {
122 struct coresight_device *child_dev;
123
124 child_dev = csdev->pdata->out_conns[i]->dest_dev;
125 if (child_dev)
126 sink = coresight_find_activated_sysfs_sink(child_dev);
127 if (sink)
128 return sink;
129 }
130
131 return NULL;
132}
133
134/** coresight_validate_source - make sure a source has the right credentials to
135 * be used via sysfs.
136 * @csdev: the device structure for a source.
137 * @function: the function this was called from.
138 *
139 * Assumes the coresight_mutex is held.
140 */
141static int coresight_validate_source_sysfs(struct coresight_device *csdev,
142 const char *function)
143{
144 u32 type, subtype;
145
146 type = csdev->type;
147 subtype = csdev->subtype.source_subtype;
148
149 if (type != CORESIGHT_DEV_TYPE_SOURCE) {
150 dev_err(&csdev->dev, "wrong device type in %s\n", function);
151 return -EINVAL;
152 }
153
154 if (subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_PROC &&
155 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE &&
156 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM &&
157 subtype != CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS) {
158 dev_err(&csdev->dev, "wrong device subtype in %s\n", function);
159 return -EINVAL;
160 }
161
162 return 0;
163}
164
165int coresight_enable_sysfs(struct coresight_device *csdev)
166{
167 int cpu, ret = 0;
168 struct coresight_device *sink;
169 struct list_head *path;
170 enum coresight_dev_subtype_source subtype;
171 u32 hash;
172
173 subtype = csdev->subtype.source_subtype;
174
175 mutex_lock(&coresight_mutex);
176
177 ret = coresight_validate_source_sysfs(csdev, __func__);
178 if (ret)
179 goto out;
180
181 /*
182 * mode == SYSFS implies that it's already enabled. Don't look at the
183 * refcount to determine this because we don't claim the source until
184 * coresight_enable_source() so can still race with Perf mode which
185 * doesn't hold coresight_mutex.
186 */
187 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
188 /*
189 * There could be multiple applications driving the software
190 * source. So keep the refcount for each such user when the
191 * source is already enabled.
192 */
193 if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE)
194 csdev->refcnt++;
195 goto out;
196 }
197
198 sink = coresight_find_activated_sysfs_sink(csdev);
199 if (!sink) {
200 ret = -EINVAL;
201 goto out;
202 }
203
204 path = coresight_build_path(csdev, sink);
205 if (IS_ERR(path)) {
206 pr_err("building path(s) failed\n");
207 ret = PTR_ERR(path);
208 goto out;
209 }
210
211 ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL);
212 if (ret)
213 goto err_path;
214
215 ret = coresight_enable_source_sysfs(csdev, CS_MODE_SYSFS, NULL);
216 if (ret)
217 goto err_source;
218
219 switch (subtype) {
220 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
221 /*
222 * When working from sysFS it is important to keep track
223 * of the paths that were created so that they can be
224 * undone in 'coresight_disable()'. Since there can only
225 * be a single session per tracer (when working from sysFS)
226 * a per-cpu variable will do just fine.
227 */
228 cpu = source_ops(csdev)->cpu_id(csdev);
229 per_cpu(tracer_path, cpu) = path;
230 break;
231 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
232 case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM:
233 case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS:
234 /*
235 * Use the hash of source's device name as ID
236 * and map the ID to the pointer of the path.
237 */
238 hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev)));
239 ret = idr_alloc_u32(&path_idr, path, &hash, hash, GFP_KERNEL);
240 if (ret)
241 goto err_source;
242 break;
243 default:
244 /* We can't be here */
245 break;
246 }
247
248out:
249 mutex_unlock(&coresight_mutex);
250 return ret;
251
252err_source:
253 coresight_disable_path(path);
254
255err_path:
256 coresight_release_path(path);
257 goto out;
258}
259EXPORT_SYMBOL_GPL(coresight_enable_sysfs);
260
261void coresight_disable_sysfs(struct coresight_device *csdev)
262{
263 int cpu, ret;
264 struct list_head *path = NULL;
265 u32 hash;
266
267 mutex_lock(&coresight_mutex);
268
269 ret = coresight_validate_source_sysfs(csdev, __func__);
270 if (ret)
271 goto out;
272
273 if (!coresight_disable_source_sysfs(csdev, NULL))
274 goto out;
275
276 switch (csdev->subtype.source_subtype) {
277 case CORESIGHT_DEV_SUBTYPE_SOURCE_PROC:
278 cpu = source_ops(csdev)->cpu_id(csdev);
279 path = per_cpu(tracer_path, cpu);
280 per_cpu(tracer_path, cpu) = NULL;
281 break;
282 case CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE:
283 case CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM:
284 case CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS:
285 hash = hashlen_hash(hashlen_string(NULL, dev_name(&csdev->dev)));
286 /* Find the path by the hash. */
287 path = idr_find(&path_idr, hash);
288 if (path == NULL) {
289 pr_err("Path is not found for %s\n", dev_name(&csdev->dev));
290 goto out;
291 }
292 idr_remove(&path_idr, hash);
293 break;
294 default:
295 /* We can't be here */
296 break;
297 }
298
299 coresight_disable_path(path);
300 coresight_release_path(path);
301
302out:
303 mutex_unlock(&coresight_mutex);
304}
305EXPORT_SYMBOL_GPL(coresight_disable_sysfs);
306
307static ssize_t enable_sink_show(struct device *dev,
308 struct device_attribute *attr, char *buf)
309{
310 struct coresight_device *csdev = to_coresight_device(dev);
311
312 return scnprintf(buf, PAGE_SIZE, "%u\n", csdev->sysfs_sink_activated);
313}
314
315static ssize_t enable_sink_store(struct device *dev,
316 struct device_attribute *attr,
317 const char *buf, size_t size)
318{
319 int ret;
320 unsigned long val;
321 struct coresight_device *csdev = to_coresight_device(dev);
322
323 ret = kstrtoul(buf, 10, &val);
324 if (ret)
325 return ret;
326
327 csdev->sysfs_sink_activated = !!val;
328
329 return size;
330
331}
332static DEVICE_ATTR_RW(enable_sink);
333
334static ssize_t enable_source_show(struct device *dev,
335 struct device_attribute *attr, char *buf)
336{
337 struct coresight_device *csdev = to_coresight_device(dev);
338
339 guard(mutex)(&coresight_mutex);
340 return scnprintf(buf, PAGE_SIZE, "%u\n",
341 coresight_get_mode(csdev) == CS_MODE_SYSFS);
342}
343
344static ssize_t enable_source_store(struct device *dev,
345 struct device_attribute *attr,
346 const char *buf, size_t size)
347{
348 int ret = 0;
349 unsigned long val;
350 struct coresight_device *csdev = to_coresight_device(dev);
351
352 ret = kstrtoul(buf, 10, &val);
353 if (ret)
354 return ret;
355
356 if (val) {
357 ret = coresight_enable_sysfs(csdev);
358 if (ret)
359 return ret;
360 } else {
361 coresight_disable_sysfs(csdev);
362 }
363
364 return size;
365}
366static DEVICE_ATTR_RW(enable_source);
367
368static struct attribute *coresight_sink_attrs[] = {
369 &dev_attr_enable_sink.attr,
370 NULL,
371};
372ATTRIBUTE_GROUPS(coresight_sink);
373
374static struct attribute *coresight_source_attrs[] = {
375 &dev_attr_enable_source.attr,
376 NULL,
377};
378ATTRIBUTE_GROUPS(coresight_source);
379
380struct device_type coresight_dev_type[] = {
381 [CORESIGHT_DEV_TYPE_SINK] = {
382 .name = "sink",
383 .groups = coresight_sink_groups,
384 },
385 [CORESIGHT_DEV_TYPE_LINK] = {
386 .name = "link",
387 },
388 [CORESIGHT_DEV_TYPE_LINKSINK] = {
389 .name = "linksink",
390 .groups = coresight_sink_groups,
391 },
392 [CORESIGHT_DEV_TYPE_SOURCE] = {
393 .name = "source",
394 .groups = coresight_source_groups,
395 },
396 [CORESIGHT_DEV_TYPE_HELPER] = {
397 .name = "helper",
398 }
399};
400/* Ensure the enum matches the names and groups */
401static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX);
402
12/*403/*
13 * Connections group - links attribute.404 * Connections group - links attribute.
14 * Count of created links between coresight components in the group.405 * Count of created links between coresight components in the group.
drivers/hwtracing/coresight/coresight-tmc-core.c+2−2
@@ -558,7 +558,7 @@ static void tmc_shutdown(struct amba_device *adev) · 557 unmodified lines
558 558
559 spin_lock_irqsave(&drvdata->spinlock, flags);559 spin_lock_irqsave(&drvdata->spinlock, flags);
560 560
561 if (drvdata->mode == CS_MODE_DISABLED)561 if (coresight_get_mode(drvdata->csdev) == CS_MODE_DISABLED)
562 goto out;562 goto out;
563 563
564 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)564 if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
@@ -594,7 +594,7 @@ static const struct amba_id tmc_ids[] = { · 29 unmodified lines
594 CS_AMBA_ID(0x000bb9e9),594 CS_AMBA_ID(0x000bb9e9),
595 /* Coresight SoC 600 TMC-ETF */595 /* Coresight SoC 600 TMC-ETF */
596 CS_AMBA_ID(0x000bb9ea),596 CS_AMBA_ID(0x000bb9ea),
597 { 0, 0},597 { 0, 0, NULL },
598};598};
599 599
600MODULE_DEVICE_TABLE(amba, tmc_ids);600MODULE_DEVICE_TABLE(amba, tmc_ids);
drivers/hwtracing/coresight/coresight-tmc-etf.c+24−22
@@ -89,7 +89,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata) · 88 unmodified lines
89 * When operating in sysFS mode the content of the buffer needs to be89 * When operating in sysFS mode the content of the buffer needs to be
90 * read before the TMC is disabled.90 * read before the TMC is disabled.
91 */91 */
92 if (drvdata->mode == CS_MODE_SYSFS)92 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS)
93 tmc_etb_dump_hw(drvdata);93 tmc_etb_dump_hw(drvdata);
94 tmc_disable_hw(drvdata);94 tmc_disable_hw(drvdata);
95 95
@@ -205,8 +205,8 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) · 109 unmodified lines
205 * sink is already enabled no memory is needed and the HW need not be205 * sink is already enabled no memory is needed and the HW need not be
206 * touched.206 * touched.
207 */207 */
208 if (drvdata->mode == CS_MODE_SYSFS) {208 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
209 atomic_inc(&csdev->refcnt);209 csdev->refcnt++;
210 goto out;210 goto out;
211 }211 }
212 212
@@ -228,8 +228,8 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev) · 15 unmodified lines
228 228
229 ret = tmc_etb_enable_hw(drvdata);229 ret = tmc_etb_enable_hw(drvdata);
230 if (!ret) {230 if (!ret) {
231 drvdata->mode = CS_MODE_SYSFS;231 coresight_set_mode(csdev, CS_MODE_SYSFS);
232 atomic_inc(&csdev->refcnt);232 csdev->refcnt++;
233 } else {233 } else {
234 /* Free up the buffer if we failed to enable */234 /* Free up the buffer if we failed to enable */
235 used = false;235 used = false;
@@ -262,7 +262,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) · 26 unmodified lines
262 * No need to continue if the ETB/ETF is already operated262 * No need to continue if the ETB/ETF is already operated
263 * from sysFS.263 * from sysFS.
264 */264 */
265 if (drvdata->mode == CS_MODE_SYSFS) {265 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
266 ret = -EBUSY;266 ret = -EBUSY;
267 break;267 break;
268 }268 }
@@ -284,7 +284,7 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) · 15 unmodified lines
284 * use for this session.284 * use for this session.
285 */285 */
286 if (drvdata->pid == pid) {286 if (drvdata->pid == pid) {
287 atomic_inc(&csdev->refcnt);287 csdev->refcnt++;
288 break;288 break;
289 }289 }
290 290
@@ -292,8 +292,8 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data) · 1 unmodified line
292 if (!ret) {292 if (!ret) {
293 /* Associate with monitored process. */293 /* Associate with monitored process. */
294 drvdata->pid = pid;294 drvdata->pid = pid;
295 drvdata->mode = CS_MODE_PERF;295 coresight_set_mode(csdev, CS_MODE_PERF);
296 atomic_inc(&csdev->refcnt);296 csdev->refcnt++;
297 }297 }
298 } while (0);298 } while (0);
299 spin_unlock_irqrestore(&drvdata->spinlock, flags);299 spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -338,17 +338,18 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev) · 38 unmodified lines
338 return -EBUSY;338 return -EBUSY;
339 }339 }
340 340
341 if (atomic_dec_return(&csdev->refcnt)) {341 csdev->refcnt--;
342 if (csdev->refcnt) {
342 spin_unlock_irqrestore(&drvdata->spinlock, flags);343 spin_unlock_irqrestore(&drvdata->spinlock, flags);
343 return -EBUSY;344 return -EBUSY;
344 }345 }
345 346
346 /* Complain if we (somehow) got out of sync */347 /* Complain if we (somehow) got out of sync */
347 WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);348 WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
348 tmc_etb_disable_hw(drvdata);349 tmc_etb_disable_hw(drvdata);
349 /* Dissociate from monitored process. */350 /* Dissociate from monitored process. */
350 drvdata->pid = -1;351 drvdata->pid = -1;
351 drvdata->mode = CS_MODE_DISABLED;352 coresight_set_mode(csdev, CS_MODE_DISABLED);
352 353
353 spin_unlock_irqrestore(&drvdata->spinlock, flags);354 spin_unlock_irqrestore(&drvdata->spinlock, flags);
354 355
@@ -371,15 +372,15 @@ static int tmc_enable_etf_link(struct coresight_device *csdev, · 16 unmodified lines
371 return -EBUSY;372 return -EBUSY;
372 }373 }
373 374
374 if (atomic_read(&csdev->refcnt) == 0) {375 if (csdev->refcnt == 0) {
375 ret = tmc_etf_enable_hw(drvdata);376 ret = tmc_etf_enable_hw(drvdata);
376 if (!ret) {377 if (!ret) {
377 drvdata->mode = CS_MODE_SYSFS;378 coresight_set_mode(csdev, CS_MODE_SYSFS);
378 first_enable = true;379 first_enable = true;
379 }380 }
380 }381 }
381 if (!ret)382 if (!ret)
382 atomic_inc(&csdev->refcnt);383 csdev->refcnt++;
383 spin_unlock_irqrestore(&drvdata->spinlock, flags);384 spin_unlock_irqrestore(&drvdata->spinlock, flags);
384 385
385 if (first_enable)386 if (first_enable)
@@ -401,9 +402,10 @@ static void tmc_disable_etf_link(struct coresight_device *csdev, · 15 unmodified lines
401 return;402 return;
402 }403 }
403 404
404 if (atomic_dec_return(&csdev->refcnt) == 0) {405 csdev->refcnt--;
406 if (csdev->refcnt == 0) {
405 tmc_etf_disable_hw(drvdata);407 tmc_etf_disable_hw(drvdata);
406 drvdata->mode = CS_MODE_DISABLED;408 coresight_set_mode(csdev, CS_MODE_DISABLED);
407 last_disable = true;409 last_disable = true;
408 }410 }
409 spin_unlock_irqrestore(&drvdata->spinlock, flags);411 spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -483,13 +485,13 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, · 73 unmodified lines
483 return 0;485 return 0;
484 486
485 /* This shouldn't happen */487 /* This shouldn't happen */
486 if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF))488 if (WARN_ON_ONCE(coresight_get_mode(csdev) != CS_MODE_PERF))
487 return 0;489 return 0;
488 490
489 spin_lock_irqsave(&drvdata->spinlock, flags);491 spin_lock_irqsave(&drvdata->spinlock, flags);
490 492
491 /* Don't do anything if another tracer is using this sink */493 /* Don't do anything if another tracer is using this sink */
492 if (atomic_read(&csdev->refcnt) != 1)494 if (csdev->refcnt != 1)
493 goto out;495 goto out;
494 496
495 CS_UNLOCK(drvdata->base);497 CS_UNLOCK(drvdata->base);
@@ -629,7 +631,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) · 133 unmodified lines
629 }631 }
630 632
631 /* Don't interfere if operated from Perf */633 /* Don't interfere if operated from Perf */
632 if (drvdata->mode == CS_MODE_PERF) {634 if (coresight_get_mode(drvdata->csdev) == CS_MODE_PERF) {
633 ret = -EINVAL;635 ret = -EINVAL;
634 goto out;636 goto out;
635 }637 }
@@ -641,7 +643,7 @@ int tmc_read_prepare_etb(struct tmc_drvdata *drvdata) · 5 unmodified lines
641 }643 }
642 644
643 /* Disable the TMC if need be */645 /* Disable the TMC if need be */
644 if (drvdata->mode == CS_MODE_SYSFS) {646 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
645 /* There is no point in reading a TMC in HW FIFO mode */647 /* There is no point in reading a TMC in HW FIFO mode */
646 mode = readl_relaxed(drvdata->base + TMC_MODE);648 mode = readl_relaxed(drvdata->base + TMC_MODE);
647 if (mode != TMC_MODE_CIRCULAR_BUFFER) {649 if (mode != TMC_MODE_CIRCULAR_BUFFER) {
@@ -673,7 +675,7 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) · 25 unmodified lines
673 spin_lock_irqsave(&drvdata->spinlock, flags);675 spin_lock_irqsave(&drvdata->spinlock, flags);
674 676
675 /* Re-enable the TMC if need be */677 /* Re-enable the TMC if need be */
676 if (drvdata->mode == CS_MODE_SYSFS) {678 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
677 /* There is no point in reading a TMC in HW FIFO mode */679 /* There is no point in reading a TMC in HW FIFO mode */
678 mode = readl_relaxed(drvdata->base + TMC_MODE);680 mode = readl_relaxed(drvdata->base + TMC_MODE);
679 if (mode != TMC_MODE_CIRCULAR_BUFFER) {681 if (mode != TMC_MODE_CIRCULAR_BUFFER) {
drivers/hwtracing/coresight/coresight-tmc-etr.c+17−16
@@ -1143,7 +1143,7 @@ static void __tmc_etr_disable_hw(struct tmc_drvdata *drvdata) · 1142 unmodified lines
1143 * When operating in sysFS mode the content of the buffer needs to be1143 * When operating in sysFS mode the content of the buffer needs to be
1144 * read before the TMC is disabled.1144 * read before the TMC is disabled.
1145 */1145 */
1146 if (drvdata->mode == CS_MODE_SYSFS)1146 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS)
1147 tmc_etr_sync_sysfs_buf(drvdata);1147 tmc_etr_sync_sysfs_buf(drvdata);
1148 1148
1149 tmc_disable_hw(drvdata);1149 tmc_disable_hw(drvdata);
@@ -1189,7 +1189,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) · 39 unmodified lines
1189 spin_lock_irqsave(&drvdata->spinlock, flags);1189 spin_lock_irqsave(&drvdata->spinlock, flags);
1190 }1190 }
1191 1191
1192 if (drvdata->reading || drvdata->mode == CS_MODE_PERF) {1192 if (drvdata->reading || coresight_get_mode(csdev) == CS_MODE_PERF) {
1193 ret = -EBUSY;1193 ret = -EBUSY;
1194 goto out;1194 goto out;
1195 }1195 }
@@ -1230,15 +1230,15 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) · 34 unmodified lines
1230 * sink is already enabled no memory is needed and the HW need not be1230 * sink is already enabled no memory is needed and the HW need not be
1231 * touched, even if the buffer size has changed.1231 * touched, even if the buffer size has changed.
1232 */1232 */
1233 if (drvdata->mode == CS_MODE_SYSFS) {1233 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
1234 atomic_inc(&csdev->refcnt);1234 csdev->refcnt++;
1235 goto out;1235 goto out;
1236 }1236 }
1237 1237
1238 ret = tmc_etr_enable_hw(drvdata, sysfs_buf);1238 ret = tmc_etr_enable_hw(drvdata, sysfs_buf);
1239 if (!ret) {1239 if (!ret) {
1240 drvdata->mode = CS_MODE_SYSFS;1240 coresight_set_mode(csdev, CS_MODE_SYSFS);
1241 atomic_inc(&csdev->refcnt);1241 csdev->refcnt++;
1242 }1242 }
1243 1243
1244out:1244out:
@@ -1564,7 +1564,7 @@ tmc_update_etr_buffer(struct coresight_device *csdev, · 319 unmodified lines
1564 spin_lock_irqsave(&drvdata->spinlock, flags);1564 spin_lock_irqsave(&drvdata->spinlock, flags);
1565 1565
1566 /* Don't do anything if another tracer is using this sink */1566 /* Don't do anything if another tracer is using this sink */
1567 if (atomic_read(&csdev->refcnt) != 1) {1567 if (csdev->refcnt != 1) {
1568 spin_unlock_irqrestore(&drvdata->spinlock, flags);1568 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1569 goto out;1569 goto out;
1570 }1570 }
@@ -1652,7 +1652,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) · 81 unmodified lines
1652 1652
1653 spin_lock_irqsave(&drvdata->spinlock, flags);1653 spin_lock_irqsave(&drvdata->spinlock, flags);
1654 /* Don't use this sink if it is already claimed by sysFS */1654 /* Don't use this sink if it is already claimed by sysFS */
1655 if (drvdata->mode == CS_MODE_SYSFS) {1655 if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
1656 rc = -EBUSY;1656 rc = -EBUSY;
1657 goto unlock_out;1657 goto unlock_out;
1658 }1658 }
@@ -1676,7 +1676,7 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) · 17 unmodified lines
1676 * use for this session.1676 * use for this session.
1677 */1677 */
1678 if (drvdata->pid == pid) {1678 if (drvdata->pid == pid) {
1679 atomic_inc(&csdev->refcnt);1679 csdev->refcnt++;
1680 goto unlock_out;1680 goto unlock_out;
1681 }1681 }
1682 1682
@@ -1684,9 +1684,9 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data) · 1 unmodified line
1684 if (!rc) {1684 if (!rc) {
1685 /* Associate with monitored process. */1685 /* Associate with monitored process. */
1686 drvdata->pid = pid;1686 drvdata->pid = pid;
1687 drvdata->mode = CS_MODE_PERF;1687 coresight_set_mode(csdev, CS_MODE_PERF);
1688 drvdata->perf_buf = etr_perf->etr_buf;1688 drvdata->perf_buf = etr_perf->etr_buf;
1689 atomic_inc(&csdev->refcnt);1689 csdev->refcnt++;
1690 }1690 }
1691 1691
1692unlock_out:1692unlock_out:
@@ -1719,17 +1719,18 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev) · 26 unmodified lines
1719 return -EBUSY;1719 return -EBUSY;
1720 }1720 }
1721 1721
1722 if (atomic_dec_return(&csdev->refcnt)) {1722 csdev->refcnt--;
1723 if (csdev->refcnt) {
1723 spin_unlock_irqrestore(&drvdata->spinlock, flags);1724 spin_unlock_irqrestore(&drvdata->spinlock, flags);
1724 return -EBUSY;1725 return -EBUSY;
1725 }1726 }
1726 1727
1727 /* Complain if we (somehow) got out of sync */1728 /* Complain if we (somehow) got out of sync */
1728 WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);1729 WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
1729 tmc_etr_disable_hw(drvdata);1730 tmc_etr_disable_hw(drvdata);
1730 /* Dissociate from monitored process. */1731 /* Dissociate from monitored process. */
1731 drvdata->pid = -1;1732 drvdata->pid = -1;
1732 drvdata->mode = CS_MODE_DISABLED;1733 coresight_set_mode(csdev, CS_MODE_DISABLED);
1733 /* Reset perf specific data */1734 /* Reset perf specific data */
1734 drvdata->perf_buf = NULL;1735 drvdata->perf_buf = NULL;
1735 1736
@@ -1777,7 +1778,7 @@ int tmc_read_prepare_etr(struct tmc_drvdata *drvdata) · 41 unmodified lines
1777 }1778 }
1778 1779
1779 /* Disable the TMC if we are trying to read from a running session. */1780 /* Disable the TMC if we are trying to read from a running session. */
1780 if (drvdata->mode == CS_MODE_SYSFS)1781 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS)
1781 __tmc_etr_disable_hw(drvdata);1782 __tmc_etr_disable_hw(drvdata);
1782 1783
1783 drvdata->reading = true;1784 drvdata->reading = true;
@@ -1799,7 +1800,7 @@ int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata) · 15 unmodified lines
1799 spin_lock_irqsave(&drvdata->spinlock, flags);1800 spin_lock_irqsave(&drvdata->spinlock, flags);
1800 1801
1801 /* RE-enable the TMC if need be */1802 /* RE-enable the TMC if need be */
1802 if (drvdata->mode == CS_MODE_SYSFS) {1803 if (coresight_get_mode(drvdata->csdev) == CS_MODE_SYSFS) {
1803 /*1804 /*
1804 * The trace run will continue with the same allocated trace1805 * The trace run will continue with the same allocated trace
1805 * buffer. Since the tracer is still enabled drvdata::buf can't1806 * buffer. Since the tracer is still enabled drvdata::buf can't
drivers/hwtracing/coresight/coresight-tmc.h+0−2
@@ -178,7 +178,6 @@ struct etr_buf { · 177 unmodified lines
178 * @size: trace buffer size for this TMC (common for all modes).178 * @size: trace buffer size for this TMC (common for all modes).
179 * @max_burst_size: The maximum burst size that can be initiated by179 * @max_burst_size: The maximum burst size that can be initiated by
180 * TMC-ETR on AXI bus.180 * TMC-ETR on AXI bus.
181 * @mode: how this TMC is being used.
182 * @config_type: TMC variant, must be of type @tmc_config_type.181 * @config_type: TMC variant, must be of type @tmc_config_type.
183 * @memwidth: width of the memory interface databus, in bytes.182 * @memwidth: width of the memory interface databus, in bytes.
184 * @trigger_cntr: amount of words to store after a trigger.183 * @trigger_cntr: amount of words to store after a trigger.
@@ -203,7 +202,6 @@ struct tmc_drvdata { · 18 unmodified lines
203 u32 len;202 u32 len;
204 u32 size;203 u32 size;
205 u32 max_burst_size;204 u32 max_burst_size;
206 u32 mode;
207 enum tmc_config_type config_type;205 enum tmc_config_type config_type;
208 enum tmc_mem_intf_width memwidth;206 enum tmc_mem_intf_width memwidth;
209 u32 trigger_cntr;207 u32 trigger_cntr;
drivers/hwtracing/coresight/coresight-tpda.c+86−59
@@ -18,6 +18,7 @@ · 17 unmodified lines
18#include "coresight-priv.h"18#include "coresight-priv.h"
19#include "coresight-tpda.h"19#include "coresight-tpda.h"
20#include "coresight-trace-id.h"20#include "coresight-trace-id.h"
21#include "coresight-tpdm.h"
21 22
22DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");23DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
23 24
@@ -28,24 +29,59 @@ static bool coresight_device_is_tpdm(struct coresight_device *csdev) · 4 unmodified lines
28 CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);29 CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
29}30}
30 31
32static void tpda_clear_element_size(struct coresight_device *csdev)
33{
34 struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
35
36 drvdata->dsb_esize = 0;
37 drvdata->cmb_esize = 0;
38}
39
40static void tpda_set_element_size(struct tpda_drvdata *drvdata, u32 *val)
41{
42 /* Clear all relevant fields */
43 *val &= ~(TPDA_Pn_CR_DSBSIZE | TPDA_Pn_CR_CMBSIZE);
44
45 if (drvdata->dsb_esize == 64)
46 *val |= TPDA_Pn_CR_DSBSIZE;
47 else if (drvdata->dsb_esize == 32)
48 *val &= ~TPDA_Pn_CR_DSBSIZE;
49
50 if (drvdata->cmb_esize == 64)
51 *val |= FIELD_PREP(TPDA_Pn_CR_CMBSIZE, 0x2);
52 else if (drvdata->cmb_esize == 32)
53 *val |= FIELD_PREP(TPDA_Pn_CR_CMBSIZE, 0x1);
54 else if (drvdata->cmb_esize == 8)
55 *val &= ~TPDA_Pn_CR_CMBSIZE;
56}
57
31/*58/*
32 * Read the DSB element size from the TPDM device59 * Read the element size from the TPDM device. One TPDM must have at least one of the
60 * element size property.
33 * Returns61 * Returns
34 * The dsb element size read from the devicetree if available.62 * 0 - The element size property is read
35 * 0 - Otherwise, with a warning once.63 * Others - Cannot read the property of the element size
36 */64 */
37static int tpdm_read_dsb_element_size(struct coresight_device *csdev)65static int tpdm_read_element_size(struct tpda_drvdata *drvdata,
66 struct coresight_device *csdev)
38{67{
39 int rc = 0;68 int rc = -EINVAL;
40 u8 size = 0;69 struct tpdm_drvdata *tpdm_data = dev_get_drvdata(csdev->dev.parent);
70
71 if (tpdm_has_dsb_dataset(tpdm_data)) {
72 rc = fwnode_property_read_u32(dev_fwnode(csdev->dev.parent),
73 "qcom,dsb-element-bits", &drvdata->dsb_esize);
74 }
75 if (tpdm_has_cmb_dataset(tpdm_data)) {
76 rc = fwnode_property_read_u32(dev_fwnode(csdev->dev.parent),
77 "qcom,cmb-element-bits", &drvdata->cmb_esize);
78 }
41 79
42 rc = fwnode_property_read_u8(dev_fwnode(csdev->dev.parent),
43 "qcom,dsb-element-size", &size);
44 if (rc)80 if (rc)
45 dev_warn_once(&csdev->dev,81 dev_warn_once(&csdev->dev,
46 "Failed to read TPDM DSB Element size: %d\n", rc);82 "Failed to read TPDM Element size: %d\n", rc);
47 83
48 return size;84 return rc;
49}85}
50 86
51/*87/*
@@ -56,11 +92,12 @@ static int tpdm_read_dsb_element_size(struct coresight_device *csdev) · 4 unmodified lines
56 * Parameter "inport" is used to pass in the input port number92 * Parameter "inport" is used to pass in the input port number
57 * of TPDA, and it is set to -1 in the recursize call.93 * of TPDA, and it is set to -1 in the recursize call.
58 */94 */
59static int tpda_get_element_size(struct coresight_device *csdev,95static int tpda_get_element_size(struct tpda_drvdata *drvdata,
96 struct coresight_device *csdev,
60 int inport)97 int inport)
61{98{
62 int dsb_size = -ENOENT;99 int rc = 0;
63 int i, size;100 int i;
64 struct coresight_device *in;101 struct coresight_device *in;
65 102
66 for (i = 0; i < csdev->pdata->nr_inconns; i++) {103 for (i = 0; i < csdev->pdata->nr_inconns; i++) {
@@ -69,30 +106,26 @@ static int tpda_get_element_size(struct coresight_device *csdev, · 2 unmodified lines
69 continue;106 continue;
70 107
71 /* Ignore the paths that do not match port */108 /* Ignore the paths that do not match port */
72 if (inport > 0 &&109 if (inport >= 0 &&
73 csdev->pdata->in_conns[i]->dest_port != inport)110 csdev->pdata->in_conns[i]->dest_port != inport)
74 continue;111 continue;
75 112
76 if (coresight_device_is_tpdm(in)) {113 if (coresight_device_is_tpdm(in)) {
77 size = tpdm_read_dsb_element_size(in);114 if (drvdata->dsb_esize || drvdata->cmb_esize)
115 return -EEXIST;
116 rc = tpdm_read_element_size(drvdata, in);
117 if (rc)
118 return rc;
78 } else {119 } else {
79 /* Recurse down the path */120 /* Recurse down the path */
80 size = tpda_get_element_size(in, -1);121 rc = tpda_get_element_size(drvdata, in, -1);
81 }122 if (rc)
82 123 return rc;
83 if (size < 0)
84 return size;
85
86 if (dsb_size < 0) {
87 /* Found a size, save it. */
88 dsb_size = size;
89 } else {
90 /* Found duplicate TPDMs */
91 return -EEXIST;
92 }124 }
93 }125 }
94 126
95 return dsb_size;127
128 return rc;
96}129}
97 130
98/* Settings pre enabling port control register */131/* Settings pre enabling port control register */
@@ -109,37 +142,24 @@ static void tpda_enable_pre_port(struct tpda_drvdata *drvdata) · 10 unmodified lines
109static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)142static int tpda_enable_port(struct tpda_drvdata *drvdata, int port)
110{143{
111 u32 val;144 u32 val;
112 int size;145 int rc;
113 146
114 val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));147 val = readl_relaxed(drvdata->base + TPDA_Pn_CR(port));
115 /*148 tpda_clear_element_size(drvdata->csdev);
116 * Configure aggregator port n DSB data set element size149 rc = tpda_get_element_size(drvdata, drvdata->csdev, port);
117 * Set the bit to 0 if the size is 32150 if (!rc && (drvdata->dsb_esize || drvdata->cmb_esize)) {
118 * Set the bit to 1 if the size is 64151 tpda_set_element_size(drvdata, &val);
119 */152 /* Enable the port */
120 size = tpda_get_element_size(drvdata->csdev, port);153 val |= TPDA_Pn_CR_ENA;
121 switch (size) {154 writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
122 case 32:155 } else if (rc == -EEXIST)
123 val &= ~TPDA_Pn_CR_DSBSIZE;
124 break;
125 case 64:
126 val |= TPDA_Pn_CR_DSBSIZE;
127 break;
128 case 0:
129 return -EEXIST;
130 case -EEXIST:
131 dev_warn_once(&drvdata->csdev->dev,156 dev_warn_once(&drvdata->csdev->dev,
132 "Detected multiple TPDMs on port %d", -EEXIST);157 "Detected multiple TPDMs on port %d", port);
133 return -EEXIST;158 else
134 default:159 dev_warn_once(&drvdata->csdev->dev,
135 return -EINVAL;160 "Didn't find TPDM element size");
136 }
137
138 /* Enable the port */
139 val |= TPDA_Pn_CR_ENA;
140 writel_relaxed(val, drvdata->base + TPDA_Pn_CR(port));
141 161
142 return 0;162 return rc;
143}163}
144 164
145static int __tpda_enable(struct tpda_drvdata *drvdata, int port)165static int __tpda_enable(struct tpda_drvdata *drvdata, int port)
@@ -148,7 +168,12 @@ static int __tpda_enable(struct tpda_drvdata *drvdata, int port) · 2 unmodified lines
148 168
149 CS_UNLOCK(drvdata->base);169 CS_UNLOCK(drvdata->base);
150 170
151 if (!drvdata->csdev->enable)171 /*
172 * Only do pre-port enable for first port that calls enable when the
173 * device's main refcount is still 0
174 */
175 lockdep_assert_held(&drvdata->spinlock);
176 if (!drvdata->csdev->refcnt)
152 tpda_enable_pre_port(drvdata);177 tpda_enable_pre_port(drvdata);
153 178
154 ret = tpda_enable_port(drvdata, port);179 ret = tpda_enable_port(drvdata, port);
@@ -169,6 +194,7 @@ static int tpda_enable(struct coresight_device *csdev, · 14 unmodified lines
169 ret = __tpda_enable(drvdata, in->dest_port);194 ret = __tpda_enable(drvdata, in->dest_port);
170 if (!ret) {195 if (!ret) {
171 atomic_inc(&in->dest_refcnt);196 atomic_inc(&in->dest_refcnt);
197 csdev->refcnt++;
172 dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);198 dev_dbg(drvdata->dev, "TPDA inport %d enabled.\n", in->dest_port);
173 }199 }
174 }200 }
@@ -197,9 +223,10 @@ static void tpda_disable(struct coresight_device *csdev, · 22 unmodified lines
197 struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);223 struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
198 224
199 spin_lock(&drvdata->spinlock);225 spin_lock(&drvdata->spinlock);
200 if (atomic_dec_return(&in->dest_refcnt) == 0)226 if (atomic_dec_return(&in->dest_refcnt) == 0) {
201 __tpda_disable(drvdata, in->dest_port);227 __tpda_disable(drvdata, in->dest_port);
202 228 csdev->refcnt--;
229 }
203 spin_unlock(&drvdata->spinlock);230 spin_unlock(&drvdata->spinlock);
204 231
205 dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);232 dev_dbg(drvdata->dev, "TPDA inport %d disabled\n", in->dest_port);
@@ -300,7 +327,7 @@ static struct amba_id tpda_ids[] = { · 94 unmodified lines
300 .id = 0x000f0f00,327 .id = 0x000f0f00,
301 .mask = 0x000fff00,328 .mask = 0x000fff00,
302 },329 },
303 { 0, 0},330 { 0, 0, NULL },
304};331};
305 332
306static struct amba_driver tpda_driver = {333static struct amba_driver tpda_driver = {
drivers/hwtracing/coresight/coresight-tpda.h+6−0
@@ -10,6 +10,8 @@ · 9 unmodified lines
10#define TPDA_Pn_CR(n) (0x004 + (n * 4))10#define TPDA_Pn_CR(n) (0x004 + (n * 4))
11/* Aggregator port enable bit */11/* Aggregator port enable bit */
12#define TPDA_Pn_CR_ENA BIT(0)12#define TPDA_Pn_CR_ENA BIT(0)
13/* Aggregator port CMB data set element size bit */
14#define TPDA_Pn_CR_CMBSIZE GENMASK(7, 6)
13/* Aggregator port DSB data set element size bit */15/* Aggregator port DSB data set element size bit */
14#define TPDA_Pn_CR_DSBSIZE BIT(8)16#define TPDA_Pn_CR_DSBSIZE BIT(8)
15 17
@@ -25,6 +27,8 @@ · 9 unmodified lines
25 * @csdev: component vitals needed by the framework.27 * @csdev: component vitals needed by the framework.
26 * @spinlock: lock for the drvdata value.28 * @spinlock: lock for the drvdata value.
27 * @enable: enable status of the component.29 * @enable: enable status of the component.
30 * @dsb_esize Record the DSB element size.
31 * @cmb_esize Record the CMB element size.
28 */32 */
29struct tpda_drvdata {33struct tpda_drvdata {
30 void __iomem *base;34 void __iomem *base;
@@ -32,6 +36,8 @@ struct tpda_drvdata { · 1 unmodified line
32 struct coresight_device *csdev;36 struct coresight_device *csdev;
33 spinlock_t spinlock;37 spinlock_t spinlock;
34 u8 atid;38 u8 atid;
39 u32 dsb_esize;
40 u32 cmb_esize;
35};41};
36 42
37#endif /* _CORESIGHT_CORESIGHT_TPDA_H */43#endif /* _CORESIGHT_CORESIGHT_TPDA_H */
drivers/hwtracing/coresight/coresight-tpdm.c+414−43
@@ -66,6 +66,31 @@ static ssize_t tpdm_simple_dataset_show(struct device *dev, · 65 unmodified lines
66 return -EINVAL;66 return -EINVAL;
67 return sysfs_emit(buf, "0x%x\n",67 return sysfs_emit(buf, "0x%x\n",
68 drvdata->dsb->msr[tpdm_attr->idx]);68 drvdata->dsb->msr[tpdm_attr->idx]);
69 case CMB_TRIG_PATT:
70 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT)
71 return -EINVAL;
72 return sysfs_emit(buf, "0x%x\n",
73 drvdata->cmb->trig_patt[tpdm_attr->idx]);
74 case CMB_TRIG_PATT_MASK:
75 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT)
76 return -EINVAL;
77 return sysfs_emit(buf, "0x%x\n",
78 drvdata->cmb->trig_patt_mask[tpdm_attr->idx]);
79 case CMB_PATT:
80 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT)
81 return -EINVAL;
82 return sysfs_emit(buf, "0x%x\n",
83 drvdata->cmb->patt_val[tpdm_attr->idx]);
84 case CMB_PATT_MASK:
85 if (tpdm_attr->idx >= TPDM_CMB_MAX_PATT)
86 return -EINVAL;
87 return sysfs_emit(buf, "0x%x\n",
88 drvdata->cmb->patt_mask[tpdm_attr->idx]);
89 case CMB_MSR:
90 if (tpdm_attr->idx >= drvdata->cmb_msr_num)
91 return -EINVAL;
92 return sysfs_emit(buf, "0x%x\n",
93 drvdata->cmb->msr[tpdm_attr->idx]);
69 }94 }
70 return -EINVAL;95 return -EINVAL;
71}96}
@@ -77,67 +102,103 @@ static ssize_t tpdm_simple_dataset_store(struct device *dev, · 5 unmodified lines
77 size_t size)102 size_t size)
78{103{
79 unsigned long val;104 unsigned long val;
80 ssize_t ret = size;105 ssize_t ret = -EINVAL;
81 106
82 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);107 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
83 struct tpdm_dataset_attribute *tpdm_attr =108 struct tpdm_dataset_attribute *tpdm_attr =
84 container_of(attr, struct tpdm_dataset_attribute, attr);109 container_of(attr, struct tpdm_dataset_attribute, attr);
85 110
86 if (kstrtoul(buf, 0, &val))111 if (kstrtoul(buf, 0, &val))
87 return -EINVAL;112 return ret;
88 113
89 spin_lock(&drvdata->spinlock);114 guard(spinlock)(&drvdata->spinlock);
90 switch (tpdm_attr->mem) {115 switch (tpdm_attr->mem) {
91 case DSB_TRIG_PATT:116 case DSB_TRIG_PATT:
92 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)117 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) {
93 drvdata->dsb->trig_patt[tpdm_attr->idx] = val;118 drvdata->dsb->trig_patt[tpdm_attr->idx] = val;
94 else119 ret = size;
95 ret = -EINVAL;120 }
96 break;121 break;
97 case DSB_TRIG_PATT_MASK:122 case DSB_TRIG_PATT_MASK:
98 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)123 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) {
99 drvdata->dsb->trig_patt_mask[tpdm_attr->idx] = val;124 drvdata->dsb->trig_patt_mask[tpdm_attr->idx] = val;
100 else125 ret = size;
101 ret = -EINVAL;126 }
102 break;127 break;
103 case DSB_PATT:128 case DSB_PATT:
104 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)129 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) {
105 drvdata->dsb->patt_val[tpdm_attr->idx] = val;130 drvdata->dsb->patt_val[tpdm_attr->idx] = val;
106 else131 ret = size;
107 ret = -EINVAL;132 }
108 break;133 break;
109 case DSB_PATT_MASK:134 case DSB_PATT_MASK:
110 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT)135 if (tpdm_attr->idx < TPDM_DSB_MAX_PATT) {
111 drvdata->dsb->patt_mask[tpdm_attr->idx] = val;136 drvdata->dsb->patt_mask[tpdm_attr->idx] = val;
112 else137 ret = size;
113 ret = -EINVAL;138 }
114 break;139 break;
115 case DSB_MSR:140 case DSB_MSR:
116 if (tpdm_attr->idx < drvdata->dsb_msr_num)141 if (tpdm_attr->idx < drvdata->dsb_msr_num) {
117 drvdata->dsb->msr[tpdm_attr->idx] = val;142 drvdata->dsb->msr[tpdm_attr->idx] = val;
118 else143 ret = size;
119 ret = -EINVAL;144 }
145 break;
146 case CMB_TRIG_PATT:
147 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) {
148 drvdata->cmb->trig_patt[tpdm_attr->idx] = val;
149 ret = size;
150 }
151 break;
152 case CMB_TRIG_PATT_MASK:
153 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) {
154 drvdata->cmb->trig_patt_mask[tpdm_attr->idx] = val;
155 ret = size;
156 }
157 break;
158 case CMB_PATT:
159 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) {
160 drvdata->cmb->patt_val[tpdm_attr->idx] = val;
161 ret = size;
162 }
163 break;
164 case CMB_PATT_MASK:
165 if (tpdm_attr->idx < TPDM_CMB_MAX_PATT) {
166 drvdata->cmb->patt_mask[tpdm_attr->idx] = val;
167 ret = size;
168 }
169 break;
170 case CMB_MSR:
171 if (tpdm_attr->idx < drvdata->cmb_msr_num) {
172 drvdata->cmb->msr[tpdm_attr->idx] = val;
173 ret = size;
174 }
120 break;175 break;
121 default:176 default:
122 ret = -EINVAL;177 break;
123 }178 }
124 spin_unlock(&drvdata->spinlock);
125 179
126 return ret;180 return ret;
127}181}
128 182
129static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata)183static umode_t tpdm_dsb_is_visible(struct kobject *kobj,
184 struct attribute *attr, int n)
130{185{
131 return (drvdata->datasets & TPDM_PIDR0_DS_DSB);186 struct device *dev = kobj_to_dev(kobj);
187 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
188
189 if (drvdata && tpdm_has_dsb_dataset(drvdata))
190 return attr->mode;
191
192 return 0;
132}193}
133 194
134static umode_t tpdm_dsb_is_visible(struct kobject *kobj,195static umode_t tpdm_cmb_is_visible(struct kobject *kobj,
135 struct attribute *attr, int n)196 struct attribute *attr, int n)
136{197{
137 struct device *dev = kobj_to_dev(kobj);198 struct device *dev = kobj_to_dev(kobj);
138 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);199 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
139 200
140 if (drvdata && tpdm_has_dsb_dataset(drvdata))201 if (drvdata && tpdm_has_cmb_dataset(drvdata))
141 return attr->mode;202 return attr->mode;
142 203
143 return 0;204 return 0;
@@ -159,6 +220,23 @@ static umode_t tpdm_dsb_msr_is_visible(struct kobject *kobj, · 15 unmodified lines
159 return 0;220 return 0;
160}221}
161 222
223static umode_t tpdm_cmb_msr_is_visible(struct kobject *kobj,
224 struct attribute *attr, int n)
225{
226 struct device *dev = kobj_to_dev(kobj);
227 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
228
229 struct device_attribute *dev_attr =
230 container_of(attr, struct device_attribute, attr);
231 struct tpdm_dataset_attribute *tpdm_attr =
232 container_of(dev_attr, struct tpdm_dataset_attribute, attr);
233
234 if (tpdm_attr->idx < drvdata->cmb_msr_num)
235 return attr->mode;
236
237 return 0;
238}
239
162static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata)240static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata)
163{241{
164 if (tpdm_has_dsb_dataset(drvdata)) {242 if (tpdm_has_dsb_dataset(drvdata)) {
@@ -167,6 +245,9 @@ static void tpdm_reset_datasets(struct tpdm_drvdata *drvdata) · 2 unmodified lines
167 drvdata->dsb->trig_ts = true;245 drvdata->dsb->trig_ts = true;
168 drvdata->dsb->trig_type = false;246 drvdata->dsb->trig_type = false;
169 }247 }
248
249 if (drvdata->cmb)
250 memset(drvdata->cmb, 0, sizeof(struct cmb_dataset));
170}251}
171 252
172static void set_dsb_mode(struct tpdm_drvdata *drvdata, u32 *val)253static void set_dsb_mode(struct tpdm_drvdata *drvdata, u32 *val)
@@ -233,25 +314,27 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) · 60 unmodified lines
233{314{
234 u32 val, i;315 u32 val, i;
235 316
317 if (!tpdm_has_dsb_dataset(drvdata))
318 return;
319
236 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)320 for (i = 0; i < TPDM_DSB_MAX_EDCR; i++)
237 writel_relaxed(drvdata->dsb->edge_ctrl[i],321 writel_relaxed(drvdata->dsb->edge_ctrl[i],
238 drvdata->base + TPDM_DSB_EDCR(i));322 drvdata->base + TPDM_DSB_EDCR(i));
239 for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)323 for (i = 0; i < TPDM_DSB_MAX_EDCMR; i++)
240 writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],324 writel_relaxed(drvdata->dsb->edge_ctrl_mask[i],
241 drvdata->base + TPDM_DSB_EDCMR(i));325 drvdata->base + TPDM_DSB_EDCMR(i));
242 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {326 for (i = 0; i < TPDM_DSB_MAX_PATT; i++) {
243 writel_relaxed(drvdata->dsb->patt_val[i],327 writel_relaxed(drvdata->dsb->patt_val[i],
244 drvdata->base + TPDM_DSB_TPR(i));328 drvdata->base + TPDM_DSB_TPR(i));
245 writel_relaxed(drvdata->dsb->patt_mask[i],329 writel_relaxed(drvdata->dsb->patt_mask[i],
246 drvdata->base + TPDM_DSB_TPMR(i));330 drvdata->base + TPDM_DSB_TPMR(i));
247 writel_relaxed(drvdata->dsb->trig_patt[i],331 writel_relaxed(drvdata->dsb->trig_patt[i],
248 drvdata->base + TPDM_DSB_XPR(i));332 drvdata->base + TPDM_DSB_XPR(i));
249 writel_relaxed(drvdata->dsb->trig_patt_mask[i],333 writel_relaxed(drvdata->dsb->trig_patt_mask[i],
250 drvdata->base + TPDM_DSB_XPMR(i));334 drvdata->base + TPDM_DSB_XPMR(i));
251 }335 }
252 336
253 set_dsb_tier(drvdata);337 set_dsb_tier(drvdata);
254
255 set_dsb_msr(drvdata);338 set_dsb_msr(drvdata);
256 339
257 val = readl_relaxed(drvdata->base + TPDM_DSB_CR);340 val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
@@ -267,6 +350,76 @@ static void tpdm_enable_dsb(struct tpdm_drvdata *drvdata) · 9 unmodified lines
267 writel_relaxed(val, drvdata->base + TPDM_DSB_CR);350 writel_relaxed(val, drvdata->base + TPDM_DSB_CR);
268}351}
269 352
353static void set_cmb_tier(struct tpdm_drvdata *drvdata)
354{
355 u32 val;
356
357 val = readl_relaxed(drvdata->base + TPDM_CMB_TIER);
358
359 /* Clear all relevant fields */
360 val &= ~(TPDM_CMB_TIER_PATT_TSENAB | TPDM_CMB_TIER_TS_ALL |
361 TPDM_CMB_TIER_XTRIG_TSENAB);
362
363 /* Set pattern timestamp type and enablement */
364 if (drvdata->cmb->patt_ts)
365 val |= TPDM_CMB_TIER_PATT_TSENAB;
366
367 /* Set trigger timestamp */
368 if (drvdata->cmb->trig_ts)
369 val |= TPDM_CMB_TIER_XTRIG_TSENAB;
370
371 /* Set all timestamp enablement*/
372 if (drvdata->cmb->ts_all)
373 val |= TPDM_CMB_TIER_TS_ALL;
374
375 writel_relaxed(val, drvdata->base + TPDM_CMB_TIER);
376}
377
378static void set_cmb_msr(struct tpdm_drvdata *drvdata)
379{
380 int i;
381
382 for (i = 0; i < drvdata->cmb_msr_num; i++)
383 writel_relaxed(drvdata->cmb->msr[i],
384 drvdata->base + TPDM_CMB_MSR(i));
385}
386
387static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
388{
389 u32 val, i;
390
391 if (!tpdm_has_cmb_dataset(drvdata))
392 return;
393
394 /* Configure pattern registers */
395 for (i = 0; i < TPDM_CMB_MAX_PATT; i++) {
396 writel_relaxed(drvdata->cmb->patt_val[i],
397 drvdata->base + TPDM_CMB_TPR(i));
398 writel_relaxed(drvdata->cmb->patt_mask[i],
399 drvdata->base + TPDM_CMB_TPMR(i));
400 writel_relaxed(drvdata->cmb->trig_patt[i],
401 drvdata->base + TPDM_CMB_XPR(i));
402 writel_relaxed(drvdata->cmb->trig_patt_mask[i],
403 drvdata->base + TPDM_CMB_XPMR(i));
404 }
405
406 set_cmb_tier(drvdata);
407 set_cmb_msr(drvdata);
408
409 val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
410 /*
411 * Set to 0 for continuous CMB collection mode,
412 * 1 for trace-on-change CMB collection mode.
413 */
414 if (drvdata->cmb->trace_mode)
415 val |= TPDM_CMB_CR_MODE;
416 else
417 val &= ~TPDM_CMB_CR_MODE;
418 /* Set the enable bit of CMB control register to 1 */
419 val |= TPDM_CMB_CR_ENA;
420 writel_relaxed(val, drvdata->base + TPDM_CMB_CR);
421}
422
270/*423/*
271 * TPDM enable operations424 * TPDM enable operations
272 * The TPDM or Monitor serves as data collection component for various425 * The TPDM or Monitor serves as data collection component for various
@@ -279,8 +432,8 @@ static void __tpdm_enable(struct tpdm_drvdata *drvdata) · 6 unmodified lines
279{432{
280 CS_UNLOCK(drvdata->base);433 CS_UNLOCK(drvdata->base);
281 434
282 if (tpdm_has_dsb_dataset(drvdata))435 tpdm_enable_dsb(drvdata);
283 tpdm_enable_dsb(drvdata);436 tpdm_enable_cmb(drvdata);
284 437
285 CS_LOCK(drvdata->base);438 CS_LOCK(drvdata->base);
286}439}
@@ -308,19 +461,35 @@ static void tpdm_disable_dsb(struct tpdm_drvdata *drvdata) · 21 unmodified lines
308{461{
309 u32 val;462 u32 val;
310 463
464 if (!tpdm_has_dsb_dataset(drvdata))
465 return;
466
311 /* Set the enable bit of DSB control register to 0 */467 /* Set the enable bit of DSB control register to 0 */
312 val = readl_relaxed(drvdata->base + TPDM_DSB_CR);468 val = readl_relaxed(drvdata->base + TPDM_DSB_CR);
313 val &= ~TPDM_DSB_CR_ENA;469 val &= ~TPDM_DSB_CR_ENA;
314 writel_relaxed(val, drvdata->base + TPDM_DSB_CR);470 writel_relaxed(val, drvdata->base + TPDM_DSB_CR);
315}471}
316 472
473static void tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
474{
475 u32 val;
476
477 if (!tpdm_has_cmb_dataset(drvdata))
478 return;
479
480 val = readl_relaxed(drvdata->base + TPDM_CMB_CR);
481 /* Set the enable bit of CMB control register to 0 */
482 val &= ~TPDM_CMB_CR_ENA;
483 writel_relaxed(val, drvdata->base + TPDM_CMB_CR);
484}
485
317/* TPDM disable operations */486/* TPDM disable operations */
318static void __tpdm_disable(struct tpdm_drvdata *drvdata)487static void __tpdm_disable(struct tpdm_drvdata *drvdata)
319{488{
320 CS_UNLOCK(drvdata->base);489 CS_UNLOCK(drvdata->base);
321 490
322 if (tpdm_has_dsb_dataset(drvdata))491 tpdm_disable_dsb(drvdata);
323 tpdm_disable_dsb(drvdata);492 tpdm_disable_cmb(drvdata);
324 493
325 CS_LOCK(drvdata->base);494 CS_LOCK(drvdata->base);
326}495}
@@ -366,6 +535,12 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata) · 39 unmodified lines
366 if (!drvdata->dsb)535 if (!drvdata->dsb)
367 return -ENOMEM;536 return -ENOMEM;
368 }537 }
538 if (tpdm_has_cmb_dataset(drvdata) && (!drvdata->cmb)) {
539 drvdata->cmb = devm_kzalloc(drvdata->dev,
540 sizeof(*drvdata->cmb), GFP_KERNEL);
541 if (!drvdata->cmb)
542 return -ENOMEM;
543 }
369 tpdm_reset_datasets(drvdata);544 tpdm_reset_datasets(drvdata);
370 545
371 return 0;546 return 0;
@@ -577,9 +752,18 @@ static ssize_t enable_ts_show(struct device *dev, · 205 unmodified lines
577 char *buf)752 char *buf)
578{753{
579 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);754 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
755 struct tpdm_dataset_attribute *tpdm_attr =
756 container_of(attr, struct tpdm_dataset_attribute, attr);
757 ssize_t size = -EINVAL;
580 758
581 return sysfs_emit(buf, "%u\n",759 if (tpdm_attr->mem == DSB_PATT)
582 (unsigned int)drvdata->dsb->patt_ts);760 size = sysfs_emit(buf, "%u\n",
761 (unsigned int)drvdata->dsb->patt_ts);
762 else if (tpdm_attr->mem == CMB_PATT)
763 size = sysfs_emit(buf, "%u\n",
764 (unsigned int)drvdata->cmb->patt_ts);
765
766 return size;
583}767}
584 768
585/*769/*
@@ -591,17 +775,23 @@ static ssize_t enable_ts_store(struct device *dev, · 5 unmodified lines
591 size_t size)775 size_t size)
592{776{
593 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);777 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
778 struct tpdm_dataset_attribute *tpdm_attr =
779 container_of(attr, struct tpdm_dataset_attribute, attr);
594 unsigned long val;780 unsigned long val;
595 781
596 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))782 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
597 return -EINVAL;783 return -EINVAL;
598 784
599 spin_lock(&drvdata->spinlock);785 guard(spinlock)(&drvdata->spinlock);
600 drvdata->dsb->patt_ts = !!val;786 if (tpdm_attr->mem == DSB_PATT)
601 spin_unlock(&drvdata->spinlock);787 drvdata->dsb->patt_ts = !!val;
788 else if (tpdm_attr->mem == CMB_PATT)
789 drvdata->cmb->patt_ts = !!val;
790 else
791 return -EINVAL;
792
602 return size;793 return size;
603}794}
604static DEVICE_ATTR_RW(enable_ts);
605 795
606static ssize_t set_type_show(struct device *dev,796static ssize_t set_type_show(struct device *dev,
607 struct device_attribute *attr,797 struct device_attribute *attr,
@@ -704,6 +894,96 @@ static ssize_t dsb_trig_ts_store(struct device *dev, · 96 unmodified lines
704}894}
705static DEVICE_ATTR_RW(dsb_trig_ts);895static DEVICE_ATTR_RW(dsb_trig_ts);
706 896
897static ssize_t cmb_mode_show(struct device *dev,
898 struct device_attribute *attr,
899 char *buf)
900{
901 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
902
903 return sysfs_emit(buf, "%x\n", drvdata->cmb->trace_mode);
904
905}
906
907static ssize_t cmb_mode_store(struct device *dev,
908 struct device_attribute *attr,
909 const char *buf,
910 size_t size)
911{
912 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
913 unsigned long trace_mode;
914
915 if (kstrtoul(buf, 0, &trace_mode) || (trace_mode & ~1UL))
916 return -EINVAL;
917
918 spin_lock(&drvdata->spinlock);
919 drvdata->cmb->trace_mode = trace_mode;
920 spin_unlock(&drvdata->spinlock);
921 return size;
922}
923static DEVICE_ATTR_RW(cmb_mode);
924
925static ssize_t cmb_ts_all_show(struct device *dev,
926 struct device_attribute *attr,
927 char *buf)
928{
929 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
930
931 return sysfs_emit(buf, "%u\n",
932 (unsigned int)drvdata->cmb->ts_all);
933}
934
935static ssize_t cmb_ts_all_store(struct device *dev,
936 struct device_attribute *attr,
937 const char *buf,
938 size_t size)
939{
940 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
941 unsigned long val;
942
943 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
944 return -EINVAL;
945
946 guard(spinlock)(&drvdata->spinlock);
947 if (val)
948 drvdata->cmb->ts_all = true;
949 else
950 drvdata->cmb->ts_all = false;
951
952 return size;
953}
954static DEVICE_ATTR_RW(cmb_ts_all);
955
956static ssize_t cmb_trig_ts_show(struct device *dev,
957 struct device_attribute *attr,
958 char *buf)
959{
960 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
961
962 return sysfs_emit(buf, "%u\n",
963 (unsigned int)drvdata->cmb->trig_ts);
964}
965
966static ssize_t cmb_trig_ts_store(struct device *dev,
967 struct device_attribute *attr,
968 const char *buf,
969 size_t size)
970{
971 struct tpdm_drvdata *drvdata = dev_get_drvdata(dev->parent);
972 unsigned long val;
973
974 if ((kstrtoul(buf, 0, &val)) || (val & ~1UL))
975 return -EINVAL;
976
977 guard(spinlock)(&drvdata->spinlock);
978 if (val)
979 drvdata->cmb->trig_ts = true;
980 else
981 drvdata->cmb->trig_ts = false;
982
983 return size;
984}
985static DEVICE_ATTR_RW(cmb_trig_ts);
986
707static struct attribute *tpdm_dsb_edge_attrs[] = {987static struct attribute *tpdm_dsb_edge_attrs[] = {
708 &dev_attr_ctrl_idx.attr,988 &dev_attr_ctrl_idx.attr,
709 &dev_attr_ctrl_val.attr,989 &dev_attr_ctrl_val.attr,
@@ -772,7 +1052,7 @@ static struct attribute *tpdm_dsb_patt_attrs[] = { · 62 unmodified lines
772 DSB_PATT_MASK_ATTR(5),1052 DSB_PATT_MASK_ATTR(5),
773 DSB_PATT_MASK_ATTR(6),1053 DSB_PATT_MASK_ATTR(6),
774 DSB_PATT_MASK_ATTR(7),1054 DSB_PATT_MASK_ATTR(7),
775 &dev_attr_enable_ts.attr,1055 DSB_PATT_ENABLE_TS,
776 &dev_attr_set_type.attr,1056 &dev_attr_set_type.attr,
777 NULL,1057 NULL,
778};1058};
@@ -813,6 +1093,59 @@ static struct attribute *tpdm_dsb_msr_attrs[] = { · 34 unmodified lines
813 NULL,1093 NULL,
814};1094};
815 1095
1096static struct attribute *tpdm_cmb_trig_patt_attrs[] = {
1097 CMB_TRIG_PATT_ATTR(0),
1098 CMB_TRIG_PATT_ATTR(1),
1099 CMB_TRIG_PATT_MASK_ATTR(0),
1100 CMB_TRIG_PATT_MASK_ATTR(1),
1101 NULL,
1102};
1103
1104static struct attribute *tpdm_cmb_patt_attrs[] = {
1105 CMB_PATT_ATTR(0),
1106 CMB_PATT_ATTR(1),
1107 CMB_PATT_MASK_ATTR(0),
1108 CMB_PATT_MASK_ATTR(1),
1109 CMB_PATT_ENABLE_TS,
1110 NULL,
1111};
1112
1113static struct attribute *tpdm_cmb_msr_attrs[] = {
1114 CMB_MSR_ATTR(0),
1115 CMB_MSR_ATTR(1),
1116 CMB_MSR_ATTR(2),
1117 CMB_MSR_ATTR(3),
1118 CMB_MSR_ATTR(4),
1119 CMB_MSR_ATTR(5),
1120 CMB_MSR_ATTR(6),
1121 CMB_MSR_ATTR(7),
1122 CMB_MSR_ATTR(8),
1123 CMB_MSR_ATTR(9),
1124 CMB_MSR_ATTR(10),
1125 CMB_MSR_ATTR(11),
1126 CMB_MSR_ATTR(12),
1127 CMB_MSR_ATTR(13),
1128 CMB_MSR_ATTR(14),
1129 CMB_MSR_ATTR(15),
1130 CMB_MSR_ATTR(16),
1131 CMB_MSR_ATTR(17),
1132 CMB_MSR_ATTR(18),
1133 CMB_MSR_ATTR(19),
1134 CMB_MSR_ATTR(20),
1135 CMB_MSR_ATTR(21),
1136 CMB_MSR_ATTR(22),
1137 CMB_MSR_ATTR(23),
1138 CMB_MSR_ATTR(24),
1139 CMB_MSR_ATTR(25),
1140 CMB_MSR_ATTR(26),
1141 CMB_MSR_ATTR(27),
1142 CMB_MSR_ATTR(28),
1143 CMB_MSR_ATTR(29),
1144 CMB_MSR_ATTR(30),
1145 CMB_MSR_ATTR(31),
1146 NULL,
1147};
1148
816static struct attribute *tpdm_dsb_attrs[] = {1149static struct attribute *tpdm_dsb_attrs[] = {
817 &dev_attr_dsb_mode.attr,1150 &dev_attr_dsb_mode.attr,
818 &dev_attr_dsb_trig_ts.attr,1151 &dev_attr_dsb_trig_ts.attr,
@@ -820,6 +1153,13 @@ static struct attribute *tpdm_dsb_attrs[] = { · 1 unmodified line
820 NULL,1153 NULL,
821};1154};
822 1155
1156static struct attribute *tpdm_cmb_attrs[] = {
1157 &dev_attr_cmb_mode.attr,
1158 &dev_attr_cmb_ts_all.attr,
1159 &dev_attr_cmb_trig_ts.attr,
1160 NULL,
1161};
1162
823static struct attribute_group tpdm_dsb_attr_grp = {1163static struct attribute_group tpdm_dsb_attr_grp = {
824 .attrs = tpdm_dsb_attrs,1164 .attrs = tpdm_dsb_attrs,
825 .is_visible = tpdm_dsb_is_visible,1165 .is_visible = tpdm_dsb_is_visible,
@@ -849,6 +1189,29 @@ static struct attribute_group tpdm_dsb_msr_grp = { · 23 unmodified lines
849 .name = "dsb_msr",1189 .name = "dsb_msr",
850};1190};
851 1191
1192static struct attribute_group tpdm_cmb_attr_grp = {
1193 .attrs = tpdm_cmb_attrs,
1194 .is_visible = tpdm_cmb_is_visible,
1195};
1196
1197static struct attribute_group tpdm_cmb_trig_patt_grp = {
1198 .attrs = tpdm_cmb_trig_patt_attrs,
1199 .is_visible = tpdm_cmb_is_visible,
1200 .name = "cmb_trig_patt",
1201};
1202
1203static struct attribute_group tpdm_cmb_patt_grp = {
1204 .attrs = tpdm_cmb_patt_attrs,
1205 .is_visible = tpdm_cmb_is_visible,
1206 .name = "cmb_patt",
1207};
1208
1209static struct attribute_group tpdm_cmb_msr_grp = {
1210 .attrs = tpdm_cmb_msr_attrs,
1211 .is_visible = tpdm_cmb_msr_is_visible,
1212 .name = "cmb_msr",
1213};
1214
852static const struct attribute_group *tpdm_attr_grps[] = {1215static const struct attribute_group *tpdm_attr_grps[] = {
853 &tpdm_attr_grp,1216 &tpdm_attr_grp,
854 &tpdm_dsb_attr_grp,1217 &tpdm_dsb_attr_grp,
@@ -856,6 +1219,10 @@ static const struct attribute_group *tpdm_attr_grps[] = { · 1 unmodified line
856 &tpdm_dsb_trig_patt_grp,1219 &tpdm_dsb_trig_patt_grp,
857 &tpdm_dsb_patt_grp,1220 &tpdm_dsb_patt_grp,
858 &tpdm_dsb_msr_grp,1221 &tpdm_dsb_msr_grp,
1222 &tpdm_cmb_attr_grp,
1223 &tpdm_cmb_trig_patt_grp,
1224 &tpdm_cmb_patt_grp,
1225 &tpdm_cmb_msr_grp,
859 NULL,1226 NULL,
860};1227};
861 1228
@@ -894,6 +1261,10 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id) · 32 unmodified lines
894 of_property_read_u32(drvdata->dev->of_node,1261 of_property_read_u32(drvdata->dev->of_node,
895 "qcom,dsb-msrs-num", &drvdata->dsb_msr_num);1262 "qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
896 1263
1264 if (drvdata && tpdm_has_cmb_dataset(drvdata))
1265 of_property_read_u32(drvdata->dev->of_node,
1266 "qcom,cmb-msrs-num", &drvdata->cmb_msr_num);
1267
897 /* Set up coresight component description */1268 /* Set up coresight component description */
898 desc.name = coresight_alloc_device_name(&tpdm_devs, dev);1269 desc.name = coresight_alloc_device_name(&tpdm_devs, dev);
899 if (!desc.name)1270 if (!desc.name)
@@ -933,7 +1304,7 @@ static struct amba_id tpdm_ids[] = { · 33 unmodified lines
933 .id = 0x000f0e00,1304 .id = 0x000f0e00,
934 .mask = 0x000fff00,1305 .mask = 0x000fff00,
935 },1306 },
936 { 0, 0},1307 { 0, 0, NULL },
937};1308};
938 1309
939static struct amba_driver tpdm_driver = {1310static struct amba_driver tpdm_driver = {
drivers/hwtracing/coresight/coresight-tpdm.h+114−0
@@ -9,6 +9,38 @@ · 8 unmodified lines
9/* The max number of the datasets that TPDM supports */9/* The max number of the datasets that TPDM supports */
10#define TPDM_DATASETS 710#define TPDM_DATASETS 7
11 11
12/* CMB Subunit Registers */
13#define TPDM_CMB_CR (0xA00)
14/* CMB subunit timestamp insertion enable register */
15#define TPDM_CMB_TIER (0xA04)
16/* CMB subunit timestamp pattern registers */
17#define TPDM_CMB_TPR(n) (0xA08 + (n * 4))
18/* CMB subunit timestamp pattern mask registers */
19#define TPDM_CMB_TPMR(n) (0xA10 + (n * 4))
20/* CMB subunit trigger pattern registers */
21#define TPDM_CMB_XPR(n) (0xA18 + (n * 4))
22/* CMB subunit trigger pattern mask registers */
23#define TPDM_CMB_XPMR(n) (0xA20 + (n * 4))
24/* CMB MSR register */
25#define TPDM_CMB_MSR(n) (0xA80 + (n * 4))
26
27/* Enable bit for CMB subunit */
28#define TPDM_CMB_CR_ENA BIT(0)
29/* Trace collection mode for CMB subunit */
30#define TPDM_CMB_CR_MODE BIT(1)
31/* Timestamp control for pattern match */
32#define TPDM_CMB_TIER_PATT_TSENAB BIT(0)
33/* CMB CTI timestamp request */
34#define TPDM_CMB_TIER_XTRIG_TSENAB BIT(1)
35/* For timestamp fo all trace */
36#define TPDM_CMB_TIER_TS_ALL BIT(2)
37
38/* Patten register number */
39#define TPDM_CMB_MAX_PATT 2
40
41/* MAX number of DSB MSR */
42#define TPDM_CMB_MAX_MSR 32
43
12/* DSB Subunit Registers */44/* DSB Subunit Registers */
13#define TPDM_DSB_CR (0x780)45#define TPDM_DSB_CR (0x780)
14#define TPDM_DSB_TIER (0x784)46#define TPDM_DSB_TIER (0x784)
@@ -79,10 +111,12 @@ · 64 unmodified lines
79 *111 *
80 * PERIPHIDR0[0] : Fix to 1 if ImplDef subunit present, else 0112 * PERIPHIDR0[0] : Fix to 1 if ImplDef subunit present, else 0
81 * PERIPHIDR0[1] : Fix to 1 if DSB subunit present, else 0113 * PERIPHIDR0[1] : Fix to 1 if DSB subunit present, else 0
114 * PERIPHIDR0[2] : Fix to 1 if CMB subunit present, else 0
82 */115 */
83 116
84#define TPDM_PIDR0_DS_IMPDEF BIT(0)117#define TPDM_PIDR0_DS_IMPDEF BIT(0)
85#define TPDM_PIDR0_DS_DSB BIT(1)118#define TPDM_PIDR0_DS_DSB BIT(1)
119#define TPDM_PIDR0_DS_CMB BIT(2)
86 120
87#define TPDM_DSB_MAX_LINES 256121#define TPDM_DSB_MAX_LINES 256
88/* MAX number of EDCR registers */122/* MAX number of EDCR registers */
@@ -113,6 +147,16 @@ · 24 unmodified lines
113 } \147 } \
114 })[0].attr.attr)148 })[0].attr.attr)
115 149
150#define tpdm_patt_enable_ts(name, mem) \
151 (&((struct tpdm_dataset_attribute[]) { \
152 { \
153 __ATTR(name, 0644, enable_ts_show, \
154 enable_ts_store), \
155 mem, \
156 0, \
157 } \
158 })[0].attr.attr)
159
116#define DSB_EDGE_CTRL_ATTR(nr) \160#define DSB_EDGE_CTRL_ATTR(nr) \
117 tpdm_simple_dataset_ro(edcr##nr, \161 tpdm_simple_dataset_ro(edcr##nr, \
118 DSB_EDGE_CTRL, nr)162 DSB_EDGE_CTRL, nr)
@@ -137,10 +181,38 @@ · 18 unmodified lines
137 tpdm_simple_dataset_rw(tpmr##nr, \181 tpdm_simple_dataset_rw(tpmr##nr, \
138 DSB_PATT_MASK, nr)182 DSB_PATT_MASK, nr)
139 183
184#define DSB_PATT_ENABLE_TS \
185 tpdm_patt_enable_ts(enable_ts, \
186 DSB_PATT)
187
140#define DSB_MSR_ATTR(nr) \188#define DSB_MSR_ATTR(nr) \
141 tpdm_simple_dataset_rw(msr##nr, \189 tpdm_simple_dataset_rw(msr##nr, \
142 DSB_MSR, nr)190 DSB_MSR, nr)
143 191
192#define CMB_TRIG_PATT_ATTR(nr) \
193 tpdm_simple_dataset_rw(xpr##nr, \
194 CMB_TRIG_PATT, nr)
195
196#define CMB_TRIG_PATT_MASK_ATTR(nr) \
197 tpdm_simple_dataset_rw(xpmr##nr, \
198 CMB_TRIG_PATT_MASK, nr)
199
200#define CMB_PATT_ATTR(nr) \
201 tpdm_simple_dataset_rw(tpr##nr, \
202 CMB_PATT, nr)
203
204#define CMB_PATT_MASK_ATTR(nr) \
205 tpdm_simple_dataset_rw(tpmr##nr, \
206 CMB_PATT_MASK, nr)
207
208#define CMB_PATT_ENABLE_TS \
209 tpdm_patt_enable_ts(enable_ts, \
210 CMB_PATT)
211
212#define CMB_MSR_ATTR(nr) \
213 tpdm_simple_dataset_rw(msr##nr, \
214 CMB_MSR, nr)
215
144/**216/**
145 * struct dsb_dataset - specifics associated to dsb dataset217 * struct dsb_dataset - specifics associated to dsb dataset
146 * @mode: DSB programming mode218 * @mode: DSB programming mode
@@ -173,6 +245,30 @@ struct dsb_dataset { · 26 unmodified lines
173 bool trig_type;245 bool trig_type;
174};246};
175 247
248/**
249 * struct cmb_dataset
250 * @trace_mode: Dataset collection mode
251 * @patt_val: Save value for pattern
252 * @patt_mask: Save value for pattern mask
253 * @trig_patt: Save value for trigger pattern
254 * @trig_patt_mask: Save value for trigger pattern mask
255 * @msr Save value for MSR
256 * @patt_ts: Indicates if pattern match for timestamp is enabled.
257 * @trig_ts: Indicates if CTI trigger for timestamp is enabled.
258 * @ts_all: Indicates if timestamp is enabled for all packets.
259 */
260struct cmb_dataset {
261 u32 trace_mode;
262 u32 patt_val[TPDM_CMB_MAX_PATT];
263 u32 patt_mask[TPDM_CMB_MAX_PATT];
264 u32 trig_patt[TPDM_CMB_MAX_PATT];
265 u32 trig_patt_mask[TPDM_CMB_MAX_PATT];
266 u32 msr[TPDM_CMB_MAX_MSR];
267 bool patt_ts;
268 bool trig_ts;
269 bool ts_all;
270};
271
176/**272/**
177 * struct tpdm_drvdata - specifics associated to an TPDM component273 * struct tpdm_drvdata - specifics associated to an TPDM component
178 * @base: memory mapped base address for this component.274 * @base: memory mapped base address for this component.
@@ -182,7 +278,9 @@ struct dsb_dataset { · 3 unmodified lines
182 * @enable: enable status of the component.278 * @enable: enable status of the component.
183 * @datasets: The datasets types present of the TPDM.279 * @datasets: The datasets types present of the TPDM.
184 * @dsb Specifics associated to TPDM DSB.280 * @dsb Specifics associated to TPDM DSB.
281 * @cmb Specifics associated to TPDM CMB.
185 * @dsb_msr_num Number of MSR supported by DSB TPDM282 * @dsb_msr_num Number of MSR supported by DSB TPDM
283 * @cmb_msr_num Number of MSR supported by CMB TPDM
186 */284 */
187 285
188struct tpdm_drvdata {286struct tpdm_drvdata {
@@ -193,7 +291,9 @@ struct tpdm_drvdata { · 4 unmodified lines
193 bool enable;291 bool enable;
194 unsigned long datasets;292 unsigned long datasets;
195 struct dsb_dataset *dsb;293 struct dsb_dataset *dsb;
294 struct cmb_dataset *cmb;
196 u32 dsb_msr_num;295 u32 dsb_msr_num;
296 u32 cmb_msr_num;
197};297};
198 298
199/* Enumerate members of various datasets */299/* Enumerate members of various datasets */
@@ -205,6 +305,11 @@ enum dataset_mem { · 5 unmodified lines
205 DSB_PATT,305 DSB_PATT,
206 DSB_PATT_MASK,306 DSB_PATT_MASK,
207 DSB_MSR,307 DSB_MSR,
308 CMB_TRIG_PATT,
309 CMB_TRIG_PATT_MASK,
310 CMB_PATT,
311 CMB_PATT_MASK,
312 CMB_MSR
208};313};
209 314
210/**315/**
@@ -220,4 +325,13 @@ struct tpdm_dataset_attribute { · 9 unmodified lines
220 u32 idx;325 u32 idx;
221};326};
222 327
328static bool tpdm_has_dsb_dataset(struct tpdm_drvdata *drvdata)
329{
330 return (drvdata->datasets & TPDM_PIDR0_DS_DSB);
331}
332
333static bool tpdm_has_cmb_dataset(struct tpdm_drvdata *drvdata)
334{
335 return (drvdata->datasets & TPDM_PIDR0_DS_CMB);
336}
223#endif /* _CORESIGHT_CORESIGHT_TPDM_H */337#endif /* _CORESIGHT_CORESIGHT_TPDM_H */
drivers/hwtracing/coresight/coresight-tpiu.c+13−3
@@ -58,6 +58,7 @@ struct tpiu_drvdata { · 57 unmodified lines
58 void __iomem *base;58 void __iomem *base;
59 struct clk *atclk;59 struct clk *atclk;
60 struct coresight_device *csdev;60 struct coresight_device *csdev;
61 spinlock_t spinlock;
61};62};
62 63
63static void tpiu_enable_hw(struct csdev_access *csa)64static void tpiu_enable_hw(struct csdev_access *csa)
@@ -72,8 +73,11 @@ static void tpiu_enable_hw(struct csdev_access *csa) · 8 unmodified lines
72static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode,73static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode,
73 void *__unused)74 void *__unused)
74{75{
76 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
77
78 guard(spinlock)(&drvdata->spinlock);
75 tpiu_enable_hw(&csdev->access);79 tpiu_enable_hw(&csdev->access);
76 atomic_inc(&csdev->refcnt);80 csdev->refcnt++;
77 dev_dbg(&csdev->dev, "TPIU enabled\n");81 dev_dbg(&csdev->dev, "TPIU enabled\n");
78 return 0;82 return 0;
79}83}
@@ -96,7 +100,11 @@ static void tpiu_disable_hw(struct csdev_access *csa) · 16 unmodified lines
96 100
97static int tpiu_disable(struct coresight_device *csdev)101static int tpiu_disable(struct coresight_device *csdev)
98{102{
99 if (atomic_dec_return(&csdev->refcnt))103 struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
104
105 guard(spinlock)(&drvdata->spinlock);
106 csdev->refcnt--;
107 if (csdev->refcnt)
100 return -EBUSY;108 return -EBUSY;
101 109
102 tpiu_disable_hw(&csdev->access);110 tpiu_disable_hw(&csdev->access);
@@ -132,6 +140,8 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) · 29 unmodified lines
132 if (!drvdata)140 if (!drvdata)
133 return -ENOMEM;141 return -ENOMEM;
134 142
143 spin_lock_init(&drvdata->spinlock);
144
135 drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */145 drvdata->atclk = devm_clk_get(&adev->dev, "atclk"); /* optional */
136 if (!IS_ERR(drvdata->atclk)) {146 if (!IS_ERR(drvdata->atclk)) {
137 ret = clk_prepare_enable(drvdata->atclk);147 ret = clk_prepare_enable(drvdata->atclk);
@@ -218,7 +228,7 @@ static const struct amba_id tpiu_ids[] = { · 80 unmodified lines
218 .id = 0x000bb9e7,228 .id = 0x000bb9e7,
219 .mask = 0x000fffff,229 .mask = 0x000fffff,
220 },230 },
221 { 0, 0},231 { 0, 0, NULL },
222};232};
223 233
224MODULE_DEVICE_TABLE(amba, tpiu_ids);234MODULE_DEVICE_TABLE(amba, tpiu_ids);
drivers/hwtracing/coresight/ultrasoc-smb.c+13−11
@@ -103,7 +103,7 @@ static int smb_open(struct inode *inode, struct file *file) · 102 unmodified lines
103 if (drvdata->reading)103 if (drvdata->reading)
104 return -EBUSY;104 return -EBUSY;
105 105
106 if (atomic_read(&drvdata->csdev->refcnt))106 if (drvdata->csdev->refcnt)
107 return -EBUSY;107 return -EBUSY;
108 108
109 smb_update_data_size(drvdata);109 smb_update_data_size(drvdata);
@@ -207,11 +207,11 @@ static void smb_enable_sysfs(struct coresight_device *csdev) · 97 unmodified lines
207{207{
208 struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);208 struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
209 209
210 if (drvdata->mode != CS_MODE_DISABLED)210 if (coresight_get_mode(csdev) != CS_MODE_DISABLED)
211 return;211 return;
212 212
213 smb_enable_hw(drvdata);213 smb_enable_hw(drvdata);
214 drvdata->mode = CS_MODE_SYSFS;214 coresight_set_mode(csdev, CS_MODE_SYSFS);
215}215}
216 216
217static int smb_enable_perf(struct coresight_device *csdev, void *data)217static int smb_enable_perf(struct coresight_device *csdev, void *data)
@@ -234,7 +234,7 @@ static int smb_enable_perf(struct coresight_device *csdev, void *data) · 16 unmodified lines
234 if (drvdata->pid == -1) {234 if (drvdata->pid == -1) {
235 smb_enable_hw(drvdata);235 smb_enable_hw(drvdata);
236 drvdata->pid = pid;236 drvdata->pid = pid;
237 drvdata->mode = CS_MODE_PERF;237 coresight_set_mode(csdev, CS_MODE_PERF);
238 }238 }
239 239
240 return 0;240 return 0;
@@ -253,7 +253,8 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode, · 12 unmodified lines
253 return -EBUSY;253 return -EBUSY;
254 254
255 /* Do nothing, the SMB is already enabled as other mode */255 /* Do nothing, the SMB is already enabled as other mode */
256 if (drvdata->mode != CS_MODE_DISABLED && drvdata->mode != mode)256 if (coresight_get_mode(csdev) != CS_MODE_DISABLED &&
257 coresight_get_mode(csdev) != mode)
257 return -EBUSY;258 return -EBUSY;
258 259
259 switch (mode) {260 switch (mode) {
@@ -270,7 +271,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode, · 10 unmodified lines
270 if (ret)271 if (ret)
271 return ret;272 return ret;
272 273
273 atomic_inc(&csdev->refcnt);274 csdev->refcnt++;
274 dev_dbg(&csdev->dev, "Ultrasoc SMB enabled\n");275 dev_dbg(&csdev->dev, "Ultrasoc SMB enabled\n");
275 276
276 return ret;277 return ret;
@@ -285,17 +286,18 @@ static int smb_disable(struct coresight_device *csdev) · 8 unmodified lines
285 if (drvdata->reading)286 if (drvdata->reading)
286 return -EBUSY;287 return -EBUSY;
287 288
288 if (atomic_dec_return(&csdev->refcnt))289 csdev->refcnt--;
290 if (csdev->refcnt)
289 return -EBUSY;291 return -EBUSY;
290 292
291 /* Complain if we (somehow) got out of sync */293 /* Complain if we (somehow) got out of sync */
292 WARN_ON_ONCE(drvdata->mode == CS_MODE_DISABLED);294 WARN_ON_ONCE(coresight_get_mode(csdev) == CS_MODE_DISABLED);
293 295
294 smb_disable_hw(drvdata);296 smb_disable_hw(drvdata);
295 297
296 /* Dissociate from the target process. */298 /* Dissociate from the target process. */
297 drvdata->pid = -1;299 drvdata->pid = -1;
298 drvdata->mode = CS_MODE_DISABLED;300 coresight_set_mode(csdev, CS_MODE_DISABLED);
299 dev_dbg(&csdev->dev, "Ultrasoc SMB disabled\n");301 dev_dbg(&csdev->dev, "Ultrasoc SMB disabled\n");
300 302
301 return 0;303 return 0;
@@ -380,7 +382,7 @@ static unsigned long smb_update_buffer(struct coresight_device *csdev, · 78 unmodified lines
380 guard(spinlock)(&drvdata->spinlock);382 guard(spinlock)(&drvdata->spinlock);
381 383
382 /* Don't do anything if another tracer is using this sink. */384 /* Don't do anything if another tracer is using this sink. */
383 if (atomic_read(&csdev->refcnt) != 1)385 if (csdev->refcnt != 1)
384 return 0;386 return 0;
385 387
386 smb_disable_hw(drvdata);388 smb_disable_hw(drvdata);
@@ -586,7 +588,7 @@ static void smb_remove(struct platform_device *pdev) · 199 unmodified lines
586 588
587#ifdef CONFIG_ACPI589#ifdef CONFIG_ACPI
588static const struct acpi_device_id ultrasoc_smb_acpi_match[] = {590static const struct acpi_device_id ultrasoc_smb_acpi_match[] = {
589 {"HISI03A1", 0},591 {"HISI03A1", 0, 0, 0},
590 {}592 {}
591};593};
592MODULE_DEVICE_TABLE(acpi, ultrasoc_smb_acpi_match);594MODULE_DEVICE_TABLE(acpi, ultrasoc_smb_acpi_match);
drivers/hwtracing/coresight/ultrasoc-smb.h+0−2
@@ -109,7 +109,6 @@ struct smb_data_buffer { · 108 unmodified lines
109 * @reading: Synchronise user space access to SMB buffer.109 * @reading: Synchronise user space access to SMB buffer.
110 * @pid: Process ID of the process being monitored by the110 * @pid: Process ID of the process being monitored by the
111 * session that is using this component.111 * session that is using this component.
112 * @mode: How this SMB is being used, perf mode or sysfs mode.
113 */112 */
114struct smb_drv_data {113struct smb_drv_data {
115 void __iomem *base;114 void __iomem *base;
@@ -119,7 +118,6 @@ struct smb_drv_data { · 3 unmodified lines
119 spinlock_t spinlock;118 spinlock_t spinlock;
120 bool reading;119 bool reading;
121 pid_t pid;120 pid_t pid;
122 enum cs_mode mode;
123};121};
124 122
125#endif123#endif
drivers/hwtracing/ptt/hisi_ptt.c+3−3
@@ -998,6 +998,9 @@ static int hisi_ptt_pmu_event_init(struct perf_event *event) · 997 unmodified lines
998 int ret;998 int ret;
999 u32 val;999 u32 val;
1000 1000
1001 if (event->attr.type != hisi_ptt->hisi_ptt_pmu.type)
1002 return -ENOENT;
1003
1001 if (event->cpu < 0) {1004 if (event->cpu < 0) {
1002 dev_dbg(event->pmu->dev, "Per-task mode not supported\n");1005 dev_dbg(event->pmu->dev, "Per-task mode not supported\n");
1003 return -EOPNOTSUPP;1006 return -EOPNOTSUPP;
@@ -1006,9 +1009,6 @@ static int hisi_ptt_pmu_event_init(struct perf_event *event) · 2 unmodified lines
1006 if (event->attach_state & PERF_ATTACH_TASK)1009 if (event->attach_state & PERF_ATTACH_TASK)
1007 return -EOPNOTSUPP;1010 return -EOPNOTSUPP;
1008 1011
1009 if (event->attr.type != hisi_ptt->hisi_ptt_pmu.type)
1010 return -ENOENT;
1011
1012 ret = hisi_ptt_trace_valid_filter(hisi_ptt, event->attr.config);1012 ret = hisi_ptt_trace_valid_filter(hisi_ptt, event->attr.config);
1013 if (ret < 0)1013 if (ret < 0)
1014 return ret;1014 return ret;
drivers/iio/Kconfig+9−0
@@ -71,6 +71,15 @@ config IIO_TRIGGERED_EVENT · 70 unmodified lines
71 help71 help
72 Provides helper functions for setting up triggered events.72 Provides helper functions for setting up triggered events.
73 73
74config IIO_BACKEND
75 tristate
76 help
77 Framework to handle complex IIO aggregate devices. The typical
78 architecture that can make use of this framework is to have one
79 device as the frontend device which can be "linked" against one or
80 multiple backend devices. The framework then makes it easy to get
81 and control such backend devices.
82
74source "drivers/iio/accel/Kconfig"83source "drivers/iio/accel/Kconfig"
75source "drivers/iio/adc/Kconfig"84source "drivers/iio/adc/Kconfig"
76source "drivers/iio/addac/Kconfig"85source "drivers/iio/addac/Kconfig"
drivers/iio/Makefile+1−0
@@ -13,6 +13,7 @@ obj-$(CONFIG_IIO_GTS_HELPER) += industrialio-gts-helper.o · 12 unmodified lines
13obj-$(CONFIG_IIO_SW_DEVICE) += industrialio-sw-device.o13obj-$(CONFIG_IIO_SW_DEVICE) += industrialio-sw-device.o
14obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o14obj-$(CONFIG_IIO_SW_TRIGGER) += industrialio-sw-trigger.o
15obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o15obj-$(CONFIG_IIO_TRIGGERED_EVENT) += industrialio-triggered-event.o
16obj-$(CONFIG_IIO_BACKEND) += industrialio-backend.o
16 17
17obj-y += accel/18obj-y += accel/
18obj-y += adc/19obj-y += adc/
drivers/iio/accel/Kconfig+6−2
@@ -256,11 +256,11 @@ config BMC150_ACCEL_SPI · 255 unmodified lines
256 256
257config BMI088_ACCEL257config BMI088_ACCEL
258 tristate "Bosch BMI088 Accelerometer Driver"258 tristate "Bosch BMI088 Accelerometer Driver"
259 depends on SPI
260 select IIO_BUFFER259 select IIO_BUFFER
261 select IIO_TRIGGERED_BUFFER260 select IIO_TRIGGERED_BUFFER
262 select REGMAP261 select REGMAP
263 select BMI088_ACCEL_SPI262 select BMI088_ACCEL_SPI if SPI
263 select BMI088_ACCEL_I2C if I2C
264 help264 help
265 Say yes here to build support for the following Bosch accelerometers:265 Say yes here to build support for the following Bosch accelerometers:
266 BMI088, BMI085, BMI090L. Note that all of these are combo module that266 BMI088, BMI085, BMI090L. Note that all of these are combo module that
@@ -269,6 +269,10 @@ config BMI088_ACCEL · 2 unmodified lines
269 This driver only implements the accelerometer part, which has its own269 This driver only implements the accelerometer part, which has its own
270 address and register map. BMG160 provides the gyroscope driver.270 address and register map. BMG160 provides the gyroscope driver.
271 271
272config BMI088_ACCEL_I2C
273 tristate
274 select REGMAP_I2C
275
272config BMI088_ACCEL_SPI276config BMI088_ACCEL_SPI
273 tristate277 tristate
274 select REGMAP_SPI278 select REGMAP_SPI
drivers/iio/accel/Makefile+1−0
@@ -30,6 +30,7 @@ obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o · 29 unmodified lines
30obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o30obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
31obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o31obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
32obj-$(CONFIG_BMI088_ACCEL) += bmi088-accel-core.o32obj-$(CONFIG_BMI088_ACCEL) += bmi088-accel-core.o
33obj-$(CONFIG_BMI088_ACCEL_I2C) += bmi088-accel-i2c.o
33obj-$(CONFIG_BMI088_ACCEL_SPI) += bmi088-accel-spi.o34obj-$(CONFIG_BMI088_ACCEL_SPI) += bmi088-accel-spi.o
34obj-$(CONFIG_DA280) += da280.o35obj-$(CONFIG_DA280) += da280.o
35obj-$(CONFIG_DA311) += da311.o36obj-$(CONFIG_DA311) += da311.o
drivers/iio/accel/adxl367.c+118−179
@@ -339,22 +339,17 @@ static int adxl367_set_act_threshold(struct adxl367_state *st, · 338 unmodified lines
339{339{
340 int ret;340 int ret;
341 341
342 mutex_lock(&st->lock);342 guard(mutex)(&st->lock);
343 343
344 ret = adxl367_set_measure_en(st, false);344 ret = adxl367_set_measure_en(st, false);
345 if (ret)345 if (ret)
346 goto out;346 return ret;
347 347
348 ret = _adxl367_set_act_threshold(st, act, threshold);348 ret = _adxl367_set_act_threshold(st, act, threshold);
349 if (ret)349 if (ret)
350 goto out;350 return ret;
351
352 ret = adxl367_set_measure_en(st, true);
353
354out:
355 mutex_unlock(&st->lock);
356 351
357 return ret;352 return adxl367_set_measure_en(st, true);
358}353}
359 354
360static int adxl367_set_act_proc_mode(struct adxl367_state *st,355static int adxl367_set_act_proc_mode(struct adxl367_state *st,
@@ -482,51 +477,45 @@ static int adxl367_set_fifo_watermark(struct adxl367_state *st, · 121 unmodified lines
482static int adxl367_set_range(struct iio_dev *indio_dev,477static int adxl367_set_range(struct iio_dev *indio_dev,
483 enum adxl367_range range)478 enum adxl367_range range)
484{479{
485 struct adxl367_state *st = iio_priv(indio_dev);480 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
486 int ret;481 struct adxl367_state *st = iio_priv(indio_dev);
482 int ret;
487 483
488 ret = iio_device_claim_direct_mode(indio_dev);484 guard(mutex)(&st->lock);
489 if (ret)
490 return ret;
491
492 mutex_lock(&st->lock);
493
494 ret = adxl367_set_measure_en(st, false);
495 if (ret)
496 goto out;
497 485
498 ret = regmap_update_bits(st->regmap, ADXL367_REG_FILTER_CTL,486 ret = adxl367_set_measure_en(st, false);
499 ADXL367_FILTER_CTL_RANGE_MASK,487 if (ret)
500 FIELD_PREP(ADXL367_FILTER_CTL_RANGE_MASK,488 return ret;
501 range));
502 if (ret)
503 goto out;
504 489
505 adxl367_scale_act_thresholds(st, st->range, range);490 ret = regmap_update_bits(st->regmap, ADXL367_REG_FILTER_CTL,
491 ADXL367_FILTER_CTL_RANGE_MASK,
492 FIELD_PREP(ADXL367_FILTER_CTL_RANGE_MASK,
493 range));
494 if (ret)
495 return ret;
506 496
507 /* Activity thresholds depend on range */497 adxl367_scale_act_thresholds(st, st->range, range);
508 ret = _adxl367_set_act_threshold(st, ADXL367_ACTIVITY,
509 st->act_threshold);
510 if (ret)
511 goto out;
512 498
513 ret = _adxl367_set_act_threshold(st, ADXL367_INACTIVITY,499 /* Activity thresholds depend on range */
514 st->inact_threshold);500 ret = _adxl367_set_act_threshold(st, ADXL367_ACTIVITY,
515 if (ret)501 st->act_threshold);
516 goto out;502 if (ret)
517 503 return ret;
518 ret = adxl367_set_measure_en(st, true);
519 if (ret)
520 goto out;
521 504
522 st->range = range;505 ret = _adxl367_set_act_threshold(st, ADXL367_INACTIVITY,
506 st->inact_threshold);
507 if (ret)
508 return ret;
523 509
524out:510 ret = adxl367_set_measure_en(st, true);
525 mutex_unlock(&st->lock);511 if (ret)
512 return ret;
526 513
527 iio_device_release_direct_mode(indio_dev);514 st->range = range;
528 515
529 return ret;516 return 0;
517 }
518 unreachable();
530}519}
531 520
532static int adxl367_time_ms_to_samples(struct adxl367_state *st, unsigned int ms)521static int adxl367_time_ms_to_samples(struct adxl367_state *st, unsigned int ms)
@@ -587,11 +576,11 @@ static int adxl367_set_act_time_ms(struct adxl367_state *st, · 54 unmodified lines
587{576{
588 int ret;577 int ret;
589 578
590 mutex_lock(&st->lock);579 guard(mutex)(&st->lock);
591 580
592 ret = adxl367_set_measure_en(st, false);581 ret = adxl367_set_measure_en(st, false);
593 if (ret)582 if (ret)
594 goto out;583 return ret;
595 584
596 if (act == ADXL367_ACTIVITY)585 if (act == ADXL367_ACTIVITY)
597 ret = _adxl367_set_act_time_ms(st, ms);586 ret = _adxl367_set_act_time_ms(st, ms);
@@ -599,14 +588,9 @@ static int adxl367_set_act_time_ms(struct adxl367_state *st, · 1 unmodified line
599 ret = _adxl367_set_inact_time_ms(st, ms);588 ret = _adxl367_set_inact_time_ms(st, ms);
600 589
601 if (ret)590 if (ret)
602 goto out;591 return ret;
603
604 ret = adxl367_set_measure_en(st, true);
605
606out:
607 mutex_unlock(&st->lock);
608 592
609 return ret;593 return adxl367_set_measure_en(st, true);
610}594}
611 595
612static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr)596static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr)
@@ -636,31 +620,23 @@ static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr) · 23 unmodified lines
636 620
637static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr)621static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr)
638{622{
639 struct adxl367_state *st = iio_priv(indio_dev);623 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
640 int ret;624 struct adxl367_state *st = iio_priv(indio_dev);;
625 int ret;
641 626
642 ret = iio_device_claim_direct_mode(indio_dev);627 guard(mutex)(&st->lock);
643 if (ret)
644 return ret;
645 628
646 mutex_lock(&st->lock);629 ret = adxl367_set_measure_en(st, false);
647 630 if (ret)
648 ret = adxl367_set_measure_en(st, false);631 return ret;
649 if (ret)
650 goto out;
651
652 ret = _adxl367_set_odr(st, odr);
653 if (ret)
654 goto out;
655
656 ret = adxl367_set_measure_en(st, true);
657
658out:
659 mutex_unlock(&st->lock);
660 632
661 iio_device_release_direct_mode(indio_dev);633 ret = _adxl367_set_odr(st, odr);
634 if (ret)
635 return ret;
662 636
663 return ret;637 return adxl367_set_measure_en(st, true);
638 }
639 unreachable();
664}640}
665 641
666static int adxl367_set_temp_adc_en(struct adxl367_state *st, unsigned int reg,642static int adxl367_set_temp_adc_en(struct adxl367_state *st, unsigned int reg,
@@ -749,36 +725,32 @@ static int adxl367_read_sample(struct iio_dev *indio_dev, · 82 unmodified lines
749 struct iio_chan_spec const *chan,725 struct iio_chan_spec const *chan,
750 int *val)726 int *val)
751{727{
752 struct adxl367_state *st = iio_priv(indio_dev);728 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
753 u16 sample;729 struct adxl367_state *st = iio_priv(indio_dev);
754 int ret;730 u16 sample;
731 int ret;
755 732
756 ret = iio_device_claim_direct_mode(indio_dev);733 guard(mutex)(&st->lock);
757 if (ret)
758 return ret;
759 734
760 mutex_lock(&st->lock);735 ret = adxl367_set_temp_adc_reg_en(st, chan->address, true);
761 736 if (ret)
762 ret = adxl367_set_temp_adc_reg_en(st, chan->address, true);737 return ret;
763 if (ret)
764 goto out;
765
766 ret = regmap_bulk_read(st->regmap, chan->address, &st->sample_buf,
767 sizeof(st->sample_buf));
768 if (ret)
769 goto out;
770
771 sample = FIELD_GET(ADXL367_DATA_MASK, be16_to_cpu(st->sample_buf));
772 *val = sign_extend32(sample, chan->scan_type.realbits - 1);
773 738
774 ret = adxl367_set_temp_adc_reg_en(st, chan->address, false);739 ret = regmap_bulk_read(st->regmap, chan->address, &st->sample_buf,
740 sizeof(st->sample_buf));
741 if (ret)
742 return ret;
775 743
776out:744 sample = FIELD_GET(ADXL367_DATA_MASK, be16_to_cpu(st->sample_buf));
777 mutex_unlock(&st->lock);745 *val = sign_extend32(sample, chan->scan_type.realbits - 1);
778 746
779 iio_device_release_direct_mode(indio_dev);747 ret = adxl367_set_temp_adc_reg_en(st, chan->address, false);
748 if (ret)
749 return ret;
780 750
781 return ret ?: IIO_VAL_INT;751 return IIO_VAL_INT;
752 }
753 unreachable();
782}754}
783 755
784static int adxl367_get_status(struct adxl367_state *st, u8 *status,756static int adxl367_get_status(struct adxl367_state *st, u8 *status,
@@ -886,12 +858,12 @@ static int adxl367_read_raw(struct iio_dev *indio_dev, · 101 unmodified lines
886 return adxl367_read_sample(indio_dev, chan, val);858 return adxl367_read_sample(indio_dev, chan, val);
887 case IIO_CHAN_INFO_SCALE:859 case IIO_CHAN_INFO_SCALE:
888 switch (chan->type) {860 switch (chan->type) {
889 case IIO_ACCEL:861 case IIO_ACCEL: {
890 mutex_lock(&st->lock);862 guard(mutex)(&st->lock);
891 *val = adxl367_range_scale_tbl[st->range][0];863 *val = adxl367_range_scale_tbl[st->range][0];
892 *val2 = adxl367_range_scale_tbl[st->range][1];864 *val2 = adxl367_range_scale_tbl[st->range][1];
893 mutex_unlock(&st->lock);
894 return IIO_VAL_INT_PLUS_NANO;865 return IIO_VAL_INT_PLUS_NANO;
866 }
895 case IIO_TEMP:867 case IIO_TEMP:
896 *val = 1000;868 *val = 1000;
897 *val2 = ADXL367_TEMP_PER_C;869 *val2 = ADXL367_TEMP_PER_C;
@@ -914,12 +886,12 @@ static int adxl367_read_raw(struct iio_dev *indio_dev, · 16 unmodified lines
914 default:886 default:
915 return -EINVAL;887 return -EINVAL;
916 }888 }
917 case IIO_CHAN_INFO_SAMP_FREQ:889 case IIO_CHAN_INFO_SAMP_FREQ: {
918 mutex_lock(&st->lock);890 guard(mutex)(&st->lock);
919 *val = adxl367_samp_freq_tbl[st->odr][0];891 *val = adxl367_samp_freq_tbl[st->odr][0];
920 *val2 = adxl367_samp_freq_tbl[st->odr][1];892 *val2 = adxl367_samp_freq_tbl[st->odr][1];
921 mutex_unlock(&st->lock);
922 return IIO_VAL_INT_PLUS_MICRO;893 return IIO_VAL_INT_PLUS_MICRO;
894 }
923 default:895 default:
924 return -EINVAL;896 return -EINVAL;
925 }897 }
@@ -1004,18 +976,15 @@ static int adxl367_read_event_value(struct iio_dev *indio_dev, · 78 unmodified lines
1004{976{
1005 struct adxl367_state *st = iio_priv(indio_dev);977 struct adxl367_state *st = iio_priv(indio_dev);
1006 978
979 guard(mutex)(&st->lock);
1007 switch (info) {980 switch (info) {
1008 case IIO_EV_INFO_VALUE: {981 case IIO_EV_INFO_VALUE: {
1009 switch (dir) {982 switch (dir) {
1010 case IIO_EV_DIR_RISING:983 case IIO_EV_DIR_RISING:
1011 mutex_lock(&st->lock);
1012 *val = st->act_threshold;984 *val = st->act_threshold;
1013 mutex_unlock(&st->lock);
1014 return IIO_VAL_INT;985 return IIO_VAL_INT;
1015 case IIO_EV_DIR_FALLING:986 case IIO_EV_DIR_FALLING:
1016 mutex_lock(&st->lock);
1017 *val = st->inact_threshold;987 *val = st->inact_threshold;
1018 mutex_unlock(&st->lock);
1019 return IIO_VAL_INT;988 return IIO_VAL_INT;
1020 default:989 default:
1021 return -EINVAL;990 return -EINVAL;
@@ -1024,15 +993,11 @@ static int adxl367_read_event_value(struct iio_dev *indio_dev, · 2 unmodified lines
1024 case IIO_EV_INFO_PERIOD:993 case IIO_EV_INFO_PERIOD:
1025 switch (dir) {994 switch (dir) {
1026 case IIO_EV_DIR_RISING:995 case IIO_EV_DIR_RISING:
1027 mutex_lock(&st->lock);
1028 *val = st->act_time_ms;996 *val = st->act_time_ms;
1029 mutex_unlock(&st->lock);
1030 *val2 = 1000;997 *val2 = 1000;
1031 return IIO_VAL_FRACTIONAL;998 return IIO_VAL_FRACTIONAL;
1032 case IIO_EV_DIR_FALLING:999 case IIO_EV_DIR_FALLING:
1033 mutex_lock(&st->lock);
1034 *val = st->inact_time_ms;1000 *val = st->inact_time_ms;
1035 mutex_unlock(&st->lock);
1036 *val2 = 1000;1001 *val2 = 1000;
1037 return IIO_VAL_FRACTIONAL;1002 return IIO_VAL_FRACTIONAL;
1038 default:1003 default:
@@ -1110,9 +1075,7 @@ static int adxl367_write_event_config(struct iio_dev *indio_dev, · 71 unmodified lines
1110 enum iio_event_direction dir,1075 enum iio_event_direction dir,
1111 int state)1076 int state)
1112{1077{
1113 struct adxl367_state *st = iio_priv(indio_dev);
1114 enum adxl367_activity_type act;1078 enum adxl367_activity_type act;
1115 int ret;
1116 1079
1117 switch (dir) {1080 switch (dir) {
1118 case IIO_EV_DIR_RISING:1081 case IIO_EV_DIR_RISING:
@@ -1125,33 +1088,28 @@ static int adxl367_write_event_config(struct iio_dev *indio_dev, · 6 unmodified lines
1125 return -EINVAL;1088 return -EINVAL;
1126 }1089 }
1127 1090
1128 ret = iio_device_claim_direct_mode(indio_dev);1091 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
1129 if (ret)1092 struct adxl367_state *st = iio_priv(indio_dev);
1130 return ret;1093 int ret;
1131
1132 mutex_lock(&st->lock);
1133 1094
1134 ret = adxl367_set_measure_en(st, false);1095 guard(mutex)(&st->lock);
1135 if (ret)
1136 goto out;
1137 1096
1138 ret = adxl367_set_act_interrupt_en(st, act, state);1097 ret = adxl367_set_measure_en(st, false);
1139 if (ret)1098 if (ret)
1140 goto out;1099 return ret;
1141
1142 ret = adxl367_set_act_en(st, act, state ? ADCL367_ACT_REF_ENABLED
1143 : ADXL367_ACT_DISABLED);
1144 if (ret)
1145 goto out;
1146
1147 ret = adxl367_set_measure_en(st, true);
1148 1100
1149out:1101 ret = adxl367_set_act_interrupt_en(st, act, state);
1150 mutex_unlock(&st->lock);1102 if (ret)
1103 return ret;
1151 1104
1152 iio_device_release_direct_mode(indio_dev);1105 ret = adxl367_set_act_en(st, act, state ? ADCL367_ACT_REF_ENABLED
1106 : ADXL367_ACT_DISABLED);
1107 if (ret)
1108 return ret;
1153 1109
1154 return ret;1110 return adxl367_set_measure_en(st, true);
1111 }
1112 unreachable();
1155}1113}
1156 1114
1157static ssize_t adxl367_get_fifo_enabled(struct device *dev,1115static ssize_t adxl367_get_fifo_enabled(struct device *dev,
@@ -1176,9 +1134,8 @@ static ssize_t adxl367_get_fifo_watermark(struct device *dev, · 18 unmodified lines
1176 struct adxl367_state *st = iio_priv(dev_to_iio_dev(dev));1134 struct adxl367_state *st = iio_priv(dev_to_iio_dev(dev));
1177 unsigned int fifo_watermark;1135 unsigned int fifo_watermark;
1178 1136
1179 mutex_lock(&st->lock);1137 guard(mutex)(&st->lock);
1180 fifo_watermark = st->fifo_watermark;1138 fifo_watermark = st->fifo_watermark;
1181 mutex_unlock(&st->lock);
1182 1139
1183 return sysfs_emit(buf, "%d\n", fifo_watermark);1140 return sysfs_emit(buf, "%d\n", fifo_watermark);
1184}1141}
@@ -1207,22 +1164,17 @@ static int adxl367_set_watermark(struct iio_dev *indio_dev, unsigned int val) · 22 unmodified lines
1207 if (val > ADXL367_FIFO_MAX_WATERMARK)1164 if (val > ADXL367_FIFO_MAX_WATERMARK)
1208 return -EINVAL;1165 return -EINVAL;
1209 1166
1210 mutex_lock(&st->lock);1167 guard(mutex)(&st->lock);
1211 1168
1212 ret = adxl367_set_measure_en(st, false);1169 ret = adxl367_set_measure_en(st, false);
1213 if (ret)1170 if (ret)
1214 goto out;1171 return ret;
1215 1172
1216 ret = adxl367_set_fifo_watermark(st, val);1173 ret = adxl367_set_fifo_watermark(st, val);
1217 if (ret)1174 if (ret)
1218 goto out;1175 return ret;
1219
1220 ret = adxl367_set_measure_en(st, true);
1221
1222out:
1223 mutex_unlock(&st->lock);
1224 1176
1225 return ret;1177 return adxl367_set_measure_en(st, true);
1226}1178}
1227 1179
1228static bool adxl367_find_mask_fifo_format(const unsigned long *scan_mask,1180static bool adxl367_find_mask_fifo_format(const unsigned long *scan_mask,
@@ -1253,27 +1205,24 @@ static int adxl367_update_scan_mode(struct iio_dev *indio_dev, · 24 unmodified lines
1253 if (!adxl367_find_mask_fifo_format(active_scan_mask, &fifo_format))1205 if (!adxl367_find_mask_fifo_format(active_scan_mask, &fifo_format))
1254 return -EINVAL;1206 return -EINVAL;
1255 1207
1256 mutex_lock(&st->lock);1208 guard(mutex)(&st->lock);
1257 1209
1258 ret = adxl367_set_measure_en(st, false);1210 ret = adxl367_set_measure_en(st, false);
1259 if (ret)1211 if (ret)
1260 goto out;1212 return ret;
1261 1213
1262 ret = adxl367_set_fifo_format(st, fifo_format);1214 ret = adxl367_set_fifo_format(st, fifo_format);
1263 if (ret)1215 if (ret)
1264 goto out;1216 return ret;
1265 1217
1266 ret = adxl367_set_measure_en(st, true);1218 ret = adxl367_set_measure_en(st, true);
1267 if (ret)1219 if (ret)
1268 goto out;1220 return ret;
1269 1221
1270 st->fifo_set_size = bitmap_weight(active_scan_mask,1222 st->fifo_set_size = bitmap_weight(active_scan_mask,
1271 indio_dev->masklength);1223 indio_dev->masklength);
1272 1224
1273out:1225 return 0;
1274 mutex_unlock(&st->lock);
1275
1276 return ret;
1277}1226}
1278 1227
1279static int adxl367_buffer_postenable(struct iio_dev *indio_dev)1228static int adxl367_buffer_postenable(struct iio_dev *indio_dev)
@@ -1281,31 +1230,26 @@ static int adxl367_buffer_postenable(struct iio_dev *indio_dev) · 1 unmodified line
1281 struct adxl367_state *st = iio_priv(indio_dev);1230 struct adxl367_state *st = iio_priv(indio_dev);
1282 int ret;1231 int ret;
1283 1232
1284 mutex_lock(&st->lock);1233 guard(mutex)(&st->lock);
1285 1234
1286 ret = adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask,1235 ret = adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask,
1287 true);1236 true);
1288 if (ret)1237 if (ret)
1289 goto out;1238 return ret;
1290 1239
1291 ret = adxl367_set_measure_en(st, false);1240 ret = adxl367_set_measure_en(st, false);
1292 if (ret)1241 if (ret)
1293 goto out;1242 return ret;
1294 1243
1295 ret = adxl367_set_fifo_watermark_interrupt_en(st, true);1244 ret = adxl367_set_fifo_watermark_interrupt_en(st, true);
1296 if (ret)1245 if (ret)
1297 goto out;1246 return ret;
1298 1247
1299 ret = adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_STREAM);1248 ret = adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_STREAM);
1300 if (ret)1249 if (ret)
1301 goto out;1250 return ret;
1302
1303 ret = adxl367_set_measure_en(st, true);
1304
1305out:
1306 mutex_unlock(&st->lock);
1307 1251
1308 return ret;1252 return adxl367_set_measure_en(st, true);
1309}1253}
1310 1254
1311static int adxl367_buffer_predisable(struct iio_dev *indio_dev)1255static int adxl367_buffer_predisable(struct iio_dev *indio_dev)
@@ -1313,31 +1257,26 @@ static int adxl367_buffer_predisable(struct iio_dev *indio_dev) · 1 unmodified line
1313 struct adxl367_state *st = iio_priv(indio_dev);1257 struct adxl367_state *st = iio_priv(indio_dev);
1314 int ret;1258 int ret;
1315 1259
1316 mutex_lock(&st->lock);1260 guard(mutex)(&st->lock);
1317 1261
1318 ret = adxl367_set_measure_en(st, false);1262 ret = adxl367_set_measure_en(st, false);
1319 if (ret)1263 if (ret)
1320 goto out;1264 return ret;
1321 1265
1322 ret = adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_DISABLED);1266 ret = adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_DISABLED);
1323 if (ret)1267 if (ret)
1324 goto out;1268 return ret;
1325 1269
1326 ret = adxl367_set_fifo_watermark_interrupt_en(st, false);1270 ret = adxl367_set_fifo_watermark_interrupt_en(st, false);
1327 if (ret)1271 if (ret)
1328 goto out;1272 return ret;
1329 1273
1330 ret = adxl367_set_measure_en(st, true);1274 ret = adxl367_set_measure_en(st, true);
1331 if (ret)1275 if (ret)
1332 goto out;1276 return ret;
1333
1334 ret = adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask,
1335 false);
1336
1337out:
1338 mutex_unlock(&st->lock);
1339 1277
1340 return ret;1278 return adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask,
1279 false);
1341}1280}
1342 1281
1343static const struct iio_buffer_setup_ops adxl367_buffer_ops = {1282static const struct iio_buffer_setup_ops adxl367_buffer_ops = {
drivers/iio/accel/adxl372_spi.c+1−1
@@ -6,8 +6,8 @@ · 5 unmodified lines
6 */6 */
7 7
8#include <linux/module.h>8#include <linux/module.h>
9#include <linux/mod_devicetable.h>
9#include <linux/regmap.h>10#include <linux/regmap.h>
10#include <linux/of.h>
11#include <linux/spi/spi.h>11#include <linux/spi/spi.h>
12 12
13#include "adxl372.h"13#include "adxl372.h"
drivers/iio/accel/bma180.c+1−1
@@ -13,10 +13,10 @@ · 12 unmodified lines
13 */13 */
14 14
15#include <linux/module.h>15#include <linux/module.h>
16#include <linux/mod_devicetable.h>
16#include <linux/i2c.h>17#include <linux/i2c.h>
17#include <linux/interrupt.h>18#include <linux/interrupt.h>
18#include <linux/delay.h>19#include <linux/delay.h>
19#include <linux/of.h>
20#include <linux/bitops.h>20#include <linux/bitops.h>
21#include <linux/regulator/consumer.h>21#include <linux/regulator/consumer.h>
22#include <linux/slab.h>22#include <linux/slab.h>
drivers/iio/accel/bmc150-accel-i2c.c+14−1
@@ -224,6 +224,19 @@ static const struct acpi_device_id bmc150_accel_acpi_match[] = { · 223 unmodified lines
224 {"BMA250E"},224 {"BMA250E"},
225 {"BMC150A"},225 {"BMC150A"},
226 {"BMI055A"},226 {"BMI055A"},
227 /*
228 * The "BOSC0200" identifier used here is not unique to devices using
229 * bmc150. The same "BOSC0200" identifier is found in the ACPI tables
230 * of the ASUS ROG ALLY and Ayaneo AIR Plus which both use a Bosch
231 * BMI323 chip. This creates a conflict with duplicate ACPI identifiers
232 * which multiple drivers want to use. Fortunately, when the bmc150
233 * driver starts to load on the ASUS ROG ALLY, the chip ID check
234 * portion fails (correctly) because the chip IDs received (via i2c)
235 * are unique between bmc150 and bmi323 and a dmesg output similar to
236 * this: "bmc150_accel_i2c i2c-BOSC0200:00: Invalid chip 0" can be
237 * seen. This allows the bmi323 driver to take over for ASUS ROG ALLY,
238 * and other devices using the bmi323 chip.
239 */
227 {"BOSC0200"},240 {"BOSC0200"},
228 {"BSBA0150"},241 {"BSBA0150"},
229 {"DUAL250E"},242 {"DUAL250E"},
@@ -266,7 +279,7 @@ static struct i2c_driver bmc150_accel_driver = { · 36 unmodified lines
266 .driver = {279 .driver = {
267 .name = "bmc150_accel_i2c",280 .name = "bmc150_accel_i2c",
268 .of_match_table = bmc150_accel_of_match,281 .of_match_table = bmc150_accel_of_match,
269 .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),282 .acpi_match_table = bmc150_accel_acpi_match,
270 .pm = &bmc150_accel_pm_ops,283 .pm = &bmc150_accel_pm_ops,
271 },284 },
272 .probe = bmc150_accel_probe,285 .probe = bmc150_accel_probe,
drivers/iio/accel/bmc150-accel-spi.c+1−2
@@ -7,7 +7,6 @@ · 6 unmodified lines
7#include <linux/device.h>7#include <linux/device.h>
8#include <linux/mod_devicetable.h>8#include <linux/mod_devicetable.h>
9#include <linux/module.h>9#include <linux/module.h>
10#include <linux/acpi.h>
11#include <linux/regmap.h>10#include <linux/regmap.h>
12#include <linux/spi/spi.h>11#include <linux/spi/spi.h>
13 12
@@ -70,7 +69,7 @@ MODULE_DEVICE_TABLE(spi, bmc150_accel_id); · 56 unmodified lines
70static struct spi_driver bmc150_accel_driver = {69static struct spi_driver bmc150_accel_driver = {
71 .driver = {70 .driver = {
72 .name = "bmc150_accel_spi",71 .name = "bmc150_accel_spi",
73 .acpi_match_table = ACPI_PTR(bmc150_accel_acpi_match),72 .acpi_match_table = bmc150_accel_acpi_match,
74 .pm = &bmc150_accel_pm_ops,73 .pm = &bmc150_accel_pm_ops,
75 },74 },
76 .probe = bmc150_accel_probe,75 .probe = bmc150_accel_probe,
drivers/iio/accel/bmi088-accel-i2c.c+70−0
@@ -0,0 +1,70 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * 3-axis accelerometer driver supporting following Bosch-Sensortec chips:
4 * - BMI088
5 * - BMI085
6 * - BMI090L
7 *
8 * Copyright 2023 Jun Yan <jerrysteve1101@gmail.com>
9 */
10
11#include <linux/i2c.h>
12#include <linux/mod_devicetable.h>
13#include <linux/module.h>
14#include <linux/regmap.h>
15#include <linux/slab.h>
16
17#include "bmi088-accel.h"
18
19static int bmi088_accel_probe(struct i2c_client *i2c)
20{
21 struct regmap *regmap;
22 const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
23
24 regmap = devm_regmap_init_i2c(i2c, &bmi088_regmap_conf);
25 if (IS_ERR(regmap)) {
26 dev_err(&i2c->dev, "Failed to initialize i2c regmap\n");
27 return PTR_ERR(regmap);
28 }
29
30 return bmi088_accel_core_probe(&i2c->dev, regmap, i2c->irq,
31 id->driver_data);
32}
33
34static void bmi088_accel_remove(struct i2c_client *i2c)
35{
36 bmi088_accel_core_remove(&i2c->dev);
37}
38
39static const struct of_device_id bmi088_of_match[] = {
40 { .compatible = "bosch,bmi085-accel" },
41 { .compatible = "bosch,bmi088-accel" },
42 { .compatible = "bosch,bmi090l-accel" },
43 {}
44};
45MODULE_DEVICE_TABLE(of, bmi088_of_match);
46
47static const struct i2c_device_id bmi088_accel_id[] = {
48 { "bmi085-accel", BOSCH_BMI085 },
49 { "bmi088-accel", BOSCH_BMI088 },
50 { "bmi090l-accel", BOSCH_BMI090L },
51 {}
52};
53MODULE_DEVICE_TABLE(i2c, bmi088_accel_id);
54
55static struct i2c_driver bmi088_accel_driver = {
56 .driver = {
57 .name = "bmi088_accel_i2c",
58 .pm = pm_ptr(&bmi088_accel_pm_ops),
59 .of_match_table = bmi088_of_match,
60 },
61 .probe = bmi088_accel_probe,
62 .remove = bmi088_accel_remove,
63 .id_table = bmi088_accel_id,
64};
65module_i2c_driver(bmi088_accel_driver);
66
67MODULE_AUTHOR("Jun Yan <jerrysteve1101@gmail.com>");
68MODULE_LICENSE("GPL");
69MODULE_DESCRIPTION("BMI088 accelerometer driver (I2C)");
70MODULE_IMPORT_NS(IIO_BMI088);
drivers/iio/accel/da280.c+26−40
@@ -23,8 +23,6 @@ · 22 unmodified lines
23#define DA280_MODE_ENABLE 0x1e23#define DA280_MODE_ENABLE 0x1e
24#define DA280_MODE_DISABLE 0x9e24#define DA280_MODE_DISABLE 0x9e
25 25
26enum da280_chipset { da217, da226, da280 };
27
28/*26/*
29 * a value of + or -4096 corresponds to + or - 1G27 * a value of + or -4096 corresponds to + or - 1G
30 * scale = 9.81 / 4096 = 0.00239501928 * scale = 9.81 / 4096 = 0.002395019
@@ -47,6 +45,11 @@ static const struct iio_chan_spec da280_channels[] = { · 16 unmodified lines
47 DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),45 DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),
48};46};
49 47
48struct da280_match_data {
49 const char *name;
50 int num_channels;
51};
52
50struct da280_data {53struct da280_data {
51 struct i2c_client *client;54 struct i2c_client *client;
52};55};
@@ -89,17 +92,6 @@ static const struct iio_info da280_info = { · 36 unmodified lines
89 .read_raw = da280_read_raw,92 .read_raw = da280_read_raw,
90};93};
91 94
92static enum da280_chipset da280_match_acpi_device(struct device *dev)
93{
94 const struct acpi_device_id *id;
95
96 id = acpi_match_device(dev->driver->acpi_match_table, dev);
97 if (!id)
98 return -EINVAL;
99
100 return (enum da280_chipset) id->driver_data;
101}
102
103static void da280_disable(void *client)95static void da280_disable(void *client)
104{96{
105 da280_enable(client, false);97 da280_enable(client, false);
@@ -107,16 +99,21 @@ static void da280_disable(void *client) · 1 unmodified line
107 99
108static int da280_probe(struct i2c_client *client)100static int da280_probe(struct i2c_client *client)
109{101{
110 const struct i2c_device_id *id = i2c_client_get_device_id(client);102 const struct da280_match_data *match_data;
111 int ret;
112 struct iio_dev *indio_dev;103 struct iio_dev *indio_dev;
113 struct da280_data *data;104 struct da280_data *data;
114 enum da280_chipset chip;105 int ret;
115 106
116 ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);107 ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
117 if (ret != DA280_CHIP_ID)108 if (ret != DA280_CHIP_ID)
118 return (ret < 0) ? ret : -ENODEV;109 return (ret < 0) ? ret : -ENODEV;
119 110
111 match_data = i2c_get_match_data(client);
112 if (!match_data) {
113 dev_err(&client->dev, "Error match-data not set\n");
114 return -EINVAL;
115 }
116
120 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));117 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
121 if (!indio_dev)118 if (!indio_dev)
122 return -ENOMEM;119 return -ENOMEM;
@@ -127,23 +124,8 @@ static int da280_probe(struct i2c_client *client) · 4 unmodified lines
127 indio_dev->info = &da280_info;124 indio_dev->info = &da280_info;
128 indio_dev->modes = INDIO_DIRECT_MODE;125 indio_dev->modes = INDIO_DIRECT_MODE;
129 indio_dev->channels = da280_channels;126 indio_dev->channels = da280_channels;
130 127 indio_dev->num_channels = match_data->num_channels;
131 if (ACPI_HANDLE(&client->dev)) {128 indio_dev->name = match_data->name;
132 chip = da280_match_acpi_device(&client->dev);
133 } else {
134 chip = id->driver_data;
135 }
136
137 if (chip == da217) {
138 indio_dev->name = "da217";
139 indio_dev->num_channels = 3;
140 } else if (chip == da226) {
141 indio_dev->name = "da226";
142 indio_dev->num_channels = 2;
143 } else {
144 indio_dev->name = "da280";
145 indio_dev->num_channels = 3;
146 }
147 129
148 ret = da280_enable(client, true);130 ret = da280_enable(client, true);
149 if (ret < 0)131 if (ret < 0)
@@ -168,17 +150,21 @@ static int da280_resume(struct device *dev) · 18 unmodified lines
168 150
169static DEFINE_SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);151static DEFINE_SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);
170 152
153static const struct da280_match_data da217_match_data = { "da217", 3 };
154static const struct da280_match_data da226_match_data = { "da226", 2 };
155static const struct da280_match_data da280_match_data = { "da280", 3 };
156
171static const struct acpi_device_id da280_acpi_match[] = {157static const struct acpi_device_id da280_acpi_match[] = {
172 {"NSA2513", da217},158 { "NSA2513", (kernel_ulong_t)&da217_match_data },
173 {"MIRAACC", da280},159 { "MIRAACC", (kernel_ulong_t)&da280_match_data },
174 {},160 {}
175};161};
176MODULE_DEVICE_TABLE(acpi, da280_acpi_match);162MODULE_DEVICE_TABLE(acpi, da280_acpi_match);
177 163
178static const struct i2c_device_id da280_i2c_id[] = {164static const struct i2c_device_id da280_i2c_id[] = {
179 { "da217", da217 },165 { "da217", (kernel_ulong_t)&da217_match_data },
180 { "da226", da226 },166 { "da226", (kernel_ulong_t)&da226_match_data },
181 { "da280", da280 },167 { "da280", (kernel_ulong_t)&da280_match_data },
182 {}168 {}
183};169};
184MODULE_DEVICE_TABLE(i2c, da280_i2c_id);170MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
@@ -186,7 +172,7 @@ MODULE_DEVICE_TABLE(i2c, da280_i2c_id); · 1 unmodified line
186static struct i2c_driver da280_driver = {172static struct i2c_driver da280_driver = {
187 .driver = {173 .driver = {
188 .name = "da280",174 .name = "da280",
189 .acpi_match_table = ACPI_PTR(da280_acpi_match),175 .acpi_match_table = da280_acpi_match,
190 .pm = pm_sleep_ptr(&da280_pm_ops),176 .pm = pm_sleep_ptr(&da280_pm_ops),
191 },177 },
192 .probe = da280_probe,178 .probe = da280_probe,
drivers/iio/accel/kxcjk-1013.c+101−19
@@ -422,6 +422,23 @@ static int kiox010a_dsm(struct device *dev, int fn_index) · 421 unmodified lines
422 ACPI_FREE(obj);422 ACPI_FREE(obj);
423 return 0;423 return 0;
424}424}
425
426static const struct acpi_device_id kx_acpi_match[] = {
427 {"KXCJ1013", KXCJK1013},
428 {"KXCJ1008", KXCJ91008},
429 {"KXCJ9000", KXCJ91008},
430 {"KIOX0008", KXCJ91008},
431 {"KIOX0009", KXTJ21009},
432 {"KIOX000A", KXCJ91008},
433 {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */
434 {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */
435 {"KXTJ1009", KXTJ21009},
436 {"KXJ2109", KXTJ21009},
437 {"SMO8500", KXCJ91008},
438 { }
439};
440MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
441
425#endif442#endif
426 443
427static int kxcjk1013_set_mode(struct kxcjk1013_data *data,444static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
@@ -619,6 +636,84 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on) · 191 unmodified lines
619 return 0;636 return 0;
620}637}
621 638
639#ifdef CONFIG_ACPI
640static bool kxj_acpi_orientation(struct device *dev,
641 struct iio_mount_matrix *orientation)
642{
643 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
644 struct acpi_device *adev = ACPI_COMPANION(dev);
645 char *str;
646 union acpi_object *obj, *elements;
647 acpi_status status;
648 int i, j, val[3];
649 bool ret = false;
650
651 if (!acpi_has_method(adev->handle, "ROTM"))
652 return false;
653
654 status = acpi_evaluate_object(adev->handle, "ROTM", NULL, &buffer);
655 if (ACPI_FAILURE(status)) {
656 dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status);
657 return false;
658 }
659
660 obj = buffer.pointer;
661 if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 3) {
662 dev_err(dev, "Unknown ACPI mount matrix package format\n");
663 goto out_free_buffer;
664 }
665
666 elements = obj->package.elements;
667 for (i = 0; i < 3; i++) {
668 if (elements[i].type != ACPI_TYPE_STRING) {
669 dev_err(dev, "Unknown ACPI mount matrix element format\n");
670 goto out_free_buffer;
671 }
672
673 str = elements[i].string.pointer;
674 if (sscanf(str, "%d %d %d", &val[0], &val[1], &val[2]) != 3) {
675 dev_err(dev, "Incorrect ACPI mount matrix string format\n");
676 goto out_free_buffer;
677 }
678
679 for (j = 0; j < 3; j++) {
680 switch (val[j]) {
681 case -1: str = "-1"; break;
682 case 0: str = "0"; break;
683 case 1: str = "1"; break;
684 default:
685 dev_err(dev, "Invalid value in ACPI mount matrix: %d\n", val[j]);
686 goto out_free_buffer;
687 }
688 orientation->rotation[i * 3 + j] = str;
689 }
690 }
691
692 ret = true;
693
694out_free_buffer:
695 kfree(buffer.pointer);
696 return ret;
697}
698
699static bool kxj1009_apply_acpi_orientation(struct device *dev,
700 struct iio_mount_matrix *orientation)
701{
702 struct acpi_device *adev = ACPI_COMPANION(dev);
703
704 if (adev && acpi_dev_hid_uid_match(adev, "KIOX000A", NULL))
705 return kxj_acpi_orientation(dev, orientation);
706
707 return false;
708}
709#else
710static bool kxj1009_apply_acpi_orientation(struct device *dev,
711 struct iio_mount_matrix *orientation)
712{
713 return false;
714}
715#endif
716
622static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)717static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
623{718{
624 int ret;719 int ret;
@@ -1449,9 +1544,12 @@ static int kxcjk1013_probe(struct i2c_client *client) · 824 unmodified lines
1449 } else {1544 } else {
1450 data->active_high_intr = true; /* default polarity */1545 data->active_high_intr = true; /* default polarity */
1451 1546
1452 ret = iio_read_mount_matrix(&client->dev, &data->orientation);1547 if (!kxj1009_apply_acpi_orientation(&client->dev, &data->orientation)) {
1453 if (ret)1548 ret = iio_read_mount_matrix(&client->dev, &data->orientation);
1454 return ret;1549 if (ret)
1550 return ret;
1551 }
1552
1455 }1553 }
1456 1554
1457 ret = devm_regulator_bulk_get_enable(&client->dev,1555 ret = devm_regulator_bulk_get_enable(&client->dev,
@@ -1687,22 +1785,6 @@ static const struct dev_pm_ops kxcjk1013_pm_ops = { · 229 unmodified lines
1687 kxcjk1013_runtime_resume, NULL)1785 kxcjk1013_runtime_resume, NULL)
1688};1786};
1689 1787
1690static const struct acpi_device_id kx_acpi_match[] = {
1691 {"KXCJ1013", KXCJK1013},
1692 {"KXCJ1008", KXCJ91008},
1693 {"KXCJ9000", KXCJ91008},
1694 {"KIOX0008", KXCJ91008},
1695 {"KIOX0009", KXTJ21009},
1696 {"KIOX000A", KXCJ91008},
1697 {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */
1698 {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */
1699 {"KXTJ1009", KXTJ21009},
1700 {"KXJ2109", KXTJ21009},
1701 {"SMO8500", KXCJ91008},
1702 { },
1703};
1704MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
1705
1706static const struct i2c_device_id kxcjk1013_id[] = {1788static const struct i2c_device_id kxcjk1013_id[] = {
1707 {"kxcjk1013", KXCJK1013},1789 {"kxcjk1013", KXCJK1013},
1708 {"kxcj91008", KXCJ91008},1790 {"kxcj91008", KXCJ91008},
drivers/iio/accel/kxsd9-spi.c+1−1
@@ -1,9 +1,9 @@
1// SPDX-License-Identifier: GPL-2.0-only1// SPDX-License-Identifier: GPL-2.0-only
2#include <linux/device.h>2#include <linux/device.h>
3#include <linux/kernel.h>3#include <linux/kernel.h>
4#include <linux/of.h>
5#include <linux/spi/spi.h>4#include <linux/spi/spi.h>
6#include <linux/module.h>5#include <linux/module.h>
6#include <linux/mod_devicetable.h>
7#include <linux/slab.h>7#include <linux/slab.h>
8#include <linux/regmap.h>8#include <linux/regmap.h>
9 9
drivers/iio/accel/mma9551.c+2−2
@@ -604,9 +604,9 @@ MODULE_DEVICE_TABLE(i2c, mma9551_id); · 603 unmodified lines
604static struct i2c_driver mma9551_driver = {604static struct i2c_driver mma9551_driver = {
605 .driver = {605 .driver = {
606 .name = MMA9551_DRV_NAME,606 .name = MMA9551_DRV_NAME,
607 .acpi_match_table = ACPI_PTR(mma9551_acpi_match),607 .acpi_match_table = mma9551_acpi_match,
608 .pm = pm_ptr(&mma9551_pm_ops),608 .pm = pm_ptr(&mma9551_pm_ops),
609 },609 },
610 .probe = mma9551_probe,610 .probe = mma9551_probe,
611 .remove = mma9551_remove,611 .remove = mma9551_remove,
612 .id_table = mma9551_id,612 .id_table = mma9551_id,
drivers/iio/accel/mma9553.c+2−2
@@ -1243,9 +1243,9 @@ MODULE_DEVICE_TABLE(i2c, mma9553_id); · 1242 unmodified lines
1243static struct i2c_driver mma9553_driver = {1243static struct i2c_driver mma9553_driver = {
1244 .driver = {1244 .driver = {
1245 .name = MMA9553_DRV_NAME,1245 .name = MMA9553_DRV_NAME,
1246 .acpi_match_table = ACPI_PTR(mma9553_acpi_match),1246 .acpi_match_table = mma9553_acpi_match,
1247 .pm = pm_ptr(&mma9553_pm_ops),1247 .pm = pm_ptr(&mma9553_pm_ops),
1248 },1248 },
1249 .probe = mma9553_probe,1249 .probe = mma9553_probe,
1250 .remove = mma9553_remove,1250 .remove = mma9553_remove,
1251 .id_table = mma9553_id,1251 .id_table = mma9553_id,
drivers/iio/accel/mxc4005.c+3−2
@@ -8,7 +8,7 @@ · 7 unmodified lines
8#include <linux/module.h>8#include <linux/module.h>
9#include <linux/i2c.h>9#include <linux/i2c.h>
10#include <linux/iio/iio.h>10#include <linux/iio/iio.h>
11#include <linux/acpi.h>11#include <linux/mod_devicetable.h>
12#include <linux/regmap.h>12#include <linux/regmap.h>
13#include <linux/iio/sysfs.h>13#include <linux/iio/sysfs.h>
14#include <linux/iio/trigger.h>14#include <linux/iio/trigger.h>
@@ -472,6 +472,7 @@ static int mxc4005_probe(struct i2c_client *client) · 457 unmodified lines
472static const struct acpi_device_id mxc4005_acpi_match[] = {472static const struct acpi_device_id mxc4005_acpi_match[] = {
473 {"MXC4005", 0},473 {"MXC4005", 0},
474 {"MXC6655", 0},474 {"MXC6655", 0},
475 {"MDA6655", 0},
475 { },476 { },
476};477};
477MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);478MODULE_DEVICE_TABLE(acpi, mxc4005_acpi_match);
@@ -493,7 +494,7 @@ MODULE_DEVICE_TABLE(i2c, mxc4005_id); · 15 unmodified lines
493static struct i2c_driver mxc4005_driver = {494static struct i2c_driver mxc4005_driver = {
494 .driver = {495 .driver = {
495 .name = MXC4005_DRV_NAME,496 .name = MXC4005_DRV_NAME,
496 .acpi_match_table = ACPI_PTR(mxc4005_acpi_match),497 .acpi_match_table = mxc4005_acpi_match,
497 .of_match_table = mxc4005_of_match,498 .of_match_table = mxc4005_of_match,
498 },499 },
499 .probe = mxc4005_probe,500 .probe = mxc4005_probe,
drivers/iio/accel/mxc6255.c+2−2
@@ -12,7 +12,7 @@ · 11 unmodified lines
12#include <linux/init.h>12#include <linux/init.h>
13#include <linux/iio/iio.h>13#include <linux/iio/iio.h>
14#include <linux/delay.h>14#include <linux/delay.h>
15#include <linux/acpi.h>15#include <linux/mod_devicetable.h>
16#include <linux/regmap.h>16#include <linux/regmap.h>
17#include <linux/iio/sysfs.h>17#include <linux/iio/sysfs.h>
18 18
@@ -181,7 +181,7 @@ MODULE_DEVICE_TABLE(i2c, mxc6255_id); · 162 unmodified lines
181static struct i2c_driver mxc6255_driver = {181static struct i2c_driver mxc6255_driver = {
182 .driver = {182 .driver = {
183 .name = MXC6255_DRV_NAME,183 .name = MXC6255_DRV_NAME,
184 .acpi_match_table = ACPI_PTR(mxc6255_acpi_match),184 .acpi_match_table = mxc6255_acpi_match,
185 },185 },
186 .probe = mxc6255_probe,186 .probe = mxc6255_probe,
187 .id_table = mxc6255_id,187 .id_table = mxc6255_id,
drivers/iio/accel/st_accel_i2c.c+1−4
@@ -10,7 +10,6 @@ · 9 unmodified lines
10#include <linux/kernel.h>10#include <linux/kernel.h>
11#include <linux/module.h>11#include <linux/module.h>
12#include <linux/mod_devicetable.h>12#include <linux/mod_devicetable.h>
13#include <linux/acpi.h>
14#include <linux/i2c.h>13#include <linux/i2c.h>
15#include <linux/iio/iio.h>14#include <linux/iio/iio.h>
16 15
@@ -127,14 +126,12 @@ static const struct of_device_id st_accel_of_match[] = { · 110 unmodified lines
127};126};
128MODULE_DEVICE_TABLE(of, st_accel_of_match);127MODULE_DEVICE_TABLE(of, st_accel_of_match);
129 128
130#ifdef CONFIG_ACPI
131static const struct acpi_device_id st_accel_acpi_match[] = {129static const struct acpi_device_id st_accel_acpi_match[] = {
132 {"SMO8840", (kernel_ulong_t)LIS2DH12_ACCEL_DEV_NAME},130 {"SMO8840", (kernel_ulong_t)LIS2DH12_ACCEL_DEV_NAME},
133 {"SMO8A90", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME},131 {"SMO8A90", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME},
134 { },132 { },
135};133};
136MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match);134MODULE_DEVICE_TABLE(acpi, st_accel_acpi_match);
137#endif
138 135
139static const struct i2c_device_id st_accel_id_table[] = {136static const struct i2c_device_id st_accel_id_table[] = {
140 { LSM303DLH_ACCEL_DEV_NAME },137 { LSM303DLH_ACCEL_DEV_NAME },
@@ -204,7 +201,7 @@ static struct i2c_driver st_accel_driver = { · 63 unmodified lines
204 .driver = {201 .driver = {
205 .name = "st-accel-i2c",202 .name = "st-accel-i2c",
206 .of_match_table = st_accel_of_match,203 .of_match_table = st_accel_of_match,
207 .acpi_match_table = ACPI_PTR(st_accel_acpi_match),204 .acpi_match_table = st_accel_acpi_match,
208 },205 },
209 .probe = st_accel_i2c_probe,206 .probe = st_accel_i2c_probe,
210 .id_table = st_accel_id_table,207 .id_table = st_accel_id_table,
drivers/iio/accel/stk8ba50.c+2−2
@@ -7,11 +7,11 @@ · 6 unmodified lines
7 * STK8BA50 7-bit I2C address: 0x18.7 * STK8BA50 7-bit I2C address: 0x18.
8 */8 */
9 9
10#include <linux/acpi.h>
11#include <linux/i2c.h>10#include <linux/i2c.h>
12#include <linux/interrupt.h>11#include <linux/interrupt.h>
13#include <linux/kernel.h>12#include <linux/kernel.h>
14#include <linux/module.h>13#include <linux/module.h>
14#include <linux/mod_devicetable.h>
15#include <linux/iio/buffer.h>15#include <linux/iio/buffer.h>
16#include <linux/iio/iio.h>16#include <linux/iio/iio.h>
17#include <linux/iio/sysfs.h>17#include <linux/iio/sysfs.h>
@@ -541,7 +541,7 @@ static struct i2c_driver stk8ba50_driver = { · 523 unmodified lines
541 .driver = {541 .driver = {
542 .name = "stk8ba50",542 .name = "stk8ba50",
543 .pm = pm_sleep_ptr(&stk8ba50_pm_ops),543 .pm = pm_sleep_ptr(&stk8ba50_pm_ops),
544 .acpi_match_table = ACPI_PTR(stk8ba50_acpi_id),544 .acpi_match_table = stk8ba50_acpi_id,
545 },545 },
546 .probe = stk8ba50_probe,546 .probe = stk8ba50_probe,
547 .remove = stk8ba50_remove,547 .remove = stk8ba50_remove,
drivers/iio/adc/Kconfig+24−2
@@ -291,7 +291,7 @@ config AD799X · 290 unmodified lines
291config AD9467291config AD9467
292 tristate "Analog Devices AD9467 High Speed ADC driver"292 tristate "Analog Devices AD9467 High Speed ADC driver"
293 depends on SPI293 depends on SPI
294 depends on ADI_AXI_ADC294 select IIO_BACKEND
295 help295 help
296 Say yes here to build support for Analog Devices:296 Say yes here to build support for Analog Devices:
297 * AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter297 * AD9467 16-Bit, 200 MSPS/250 MSPS Analog-to-Digital Converter
@@ -309,7 +309,7 @@ config ADI_AXI_ADC · 11 unmodified lines
309 select IIO_BUFFER_HW_CONSUMER309 select IIO_BUFFER_HW_CONSUMER
310 select IIO_BUFFER_DMAENGINE310 select IIO_BUFFER_DMAENGINE
311 select REGMAP_MMIO311 select REGMAP_MMIO
312 depends on OF312 select IIO_BACKEND
313 help313 help
314 Say yes here to build support for Analog Devices Generic314 Say yes here to build support for Analog Devices Generic
315 AXI ADC IP core. The IP core is used for interfacing with315 AXI ADC IP core. The IP core is used for interfacing with
@@ -930,6 +930,17 @@ config NPCM_ADC · 614 unmodified lines
930 This driver can also be built as a module. If so, the module930 This driver can also be built as a module. If so, the module
931 will be called npcm_adc.931 will be called npcm_adc.
932 932
933config PAC1934
934 tristate "Microchip Technology PAC1934 driver"
935 depends on I2C
936 help
937 Say yes here to build support for Microchip Technology's PAC1931,
938 PAC1932, PAC1933, PAC1934 Single/Multi-Channel Power Monitor with
939 Accumulator.
940
941 This driver can also be built as a module. If so, the module
942 will be called pac1934.
943
933config PALMAS_GPADC944config PALMAS_GPADC
934 tristate "TI Palmas General Purpose ADC"945 tristate "TI Palmas General Purpose ADC"
935 depends on MFD_PALMAS946 depends on MFD_PALMAS
@@ -1312,6 +1323,17 @@ config TI_ADS1100 · 376 unmodified lines
1312 This driver can also be built as a module. If so, the module will be1323 This driver can also be built as a module. If so, the module will be
1313 called ti-ads1100.1324 called ti-ads1100.
1314 1325
1326config TI_ADS1298
1327 tristate "Texas Instruments ADS1298"
1328 depends on SPI
1329 select IIO_BUFFER
1330 help
1331 If you say yes here you get support for Texas Instruments ADS1298
1332 medical ADC chips
1333
1334 This driver can also be built as a module. If so, the module will be
1335 called ti-ads1298.
1336
1315config TI_ADS79501337config TI_ADS7950
1316 tristate "Texas Instruments ADS7950 ADC driver"1338 tristate "Texas Instruments ADS7950 ADC driver"
1317 depends on SPI && GPIOLIB1339 depends on SPI && GPIOLIB
drivers/iio/adc/Makefile+2−0
@@ -86,6 +86,7 @@ obj-$(CONFIG_MP2629_ADC) += mp2629_adc.o · 85 unmodified lines
86obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o86obj-$(CONFIG_MXS_LRADC_ADC) += mxs-lradc-adc.o
87obj-$(CONFIG_NAU7802) += nau7802.o87obj-$(CONFIG_NAU7802) += nau7802.o
88obj-$(CONFIG_NPCM_ADC) += npcm_adc.o88obj-$(CONFIG_NPCM_ADC) += npcm_adc.o
89obj-$(CONFIG_PAC1934) += pac1934.o
89obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o90obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
90obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o91obj-$(CONFIG_QCOM_SPMI_ADC5) += qcom-spmi-adc5.o
91obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o92obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spmi-iadc.o
@@ -116,6 +117,7 @@ obj-$(CONFIG_TI_ADC128S052) += ti-adc128s052.o · 24 unmodified lines
116obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o117obj-$(CONFIG_TI_ADC161S626) += ti-adc161s626.o
117obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o118obj-$(CONFIG_TI_ADS1015) += ti-ads1015.o
118obj-$(CONFIG_TI_ADS1100) += ti-ads1100.o119obj-$(CONFIG_TI_ADS1100) += ti-ads1100.o
120obj-$(CONFIG_TI_ADS1298) += ti-ads1298.o
119obj-$(CONFIG_TI_ADS7924) += ti-ads7924.o121obj-$(CONFIG_TI_ADS7924) += ti-ads7924.o
120obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o122obj-$(CONFIG_TI_ADS7950) += ti-ads7950.o
121obj-$(CONFIG_TI_ADS8344) += ti-ads8344.o123obj-$(CONFIG_TI_ADS8344) += ti-ads8344.o
drivers/iio/adc/ad4130.c+52−79
@@ -887,9 +887,9 @@ static int ad4130_set_filter_mode(struct iio_dev *indio_dev, · 886 unmodified lines
887 unsigned int old_fs;887 unsigned int old_fs;
888 int ret = 0;888 int ret = 0;
889 889
890 mutex_lock(&st->lock);890 guard(mutex)(&st->lock);
891 if (setup_info->filter_mode == val)891 if (setup_info->filter_mode == val)
892 goto out;892 return 0;
893 893
894 old_fs = setup_info->fs;894 old_fs = setup_info->fs;
895 old_filter_mode = setup_info->filter_mode;895 old_filter_mode = setup_info->filter_mode;
@@ -911,12 +911,10 @@ static int ad4130_set_filter_mode(struct iio_dev *indio_dev, · 15 unmodified lines
911 if (ret) {911 if (ret) {
912 setup_info->fs = old_fs;912 setup_info->fs = old_fs;
913 setup_info->filter_mode = old_filter_mode;913 setup_info->filter_mode = old_filter_mode;
914 return ret;
914 }915 }
915 916
916 out:917 return 0;
917 mutex_unlock(&st->lock);
918
919 return ret;
920}918}
921 919
922static int ad4130_get_filter_mode(struct iio_dev *indio_dev,920static int ad4130_get_filter_mode(struct iio_dev *indio_dev,
@@ -927,9 +925,8 @@ static int ad4130_get_filter_mode(struct iio_dev *indio_dev, · 4 unmodified lines
927 struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;925 struct ad4130_setup_info *setup_info = &st->chans_info[channel].setup;
928 enum ad4130_filter_mode filter_mode;926 enum ad4130_filter_mode filter_mode;
929 927
930 mutex_lock(&st->lock);928 guard(mutex)(&st->lock);
931 filter_mode = setup_info->filter_mode;929 filter_mode = setup_info->filter_mode;
932 mutex_unlock(&st->lock);
933 930
934 return filter_mode;931 return filter_mode;
935}932}
@@ -971,7 +968,7 @@ static int ad4130_set_channel_pga(struct ad4130_state *st, unsigned int channel, · 35 unmodified lines
971 struct ad4130_chan_info *chan_info = &st->chans_info[channel];968 struct ad4130_chan_info *chan_info = &st->chans_info[channel];
972 struct ad4130_setup_info *setup_info = &chan_info->setup;969 struct ad4130_setup_info *setup_info = &chan_info->setup;
973 unsigned int pga, old_pga;970 unsigned int pga, old_pga;
974 int ret = 0;971 int ret;
975 972
976 for (pga = 0; pga < AD4130_MAX_PGA; pga++)973 for (pga = 0; pga < AD4130_MAX_PGA; pga++)
977 if (val == st->scale_tbls[setup_info->ref_sel][pga][0] &&974 if (val == st->scale_tbls[setup_info->ref_sel][pga][0] &&
@@ -981,21 +978,20 @@ static int ad4130_set_channel_pga(struct ad4130_state *st, unsigned int channel, · 3 unmodified lines
981 if (pga == AD4130_MAX_PGA)978 if (pga == AD4130_MAX_PGA)
982 return -EINVAL;979 return -EINVAL;
983 980
984 mutex_lock(&st->lock);981 guard(mutex)(&st->lock);
985 if (pga == setup_info->pga)982 if (pga == setup_info->pga)
986 goto out;983 return 0;
987 984
988 old_pga = setup_info->pga;985 old_pga = setup_info->pga;
989 setup_info->pga = pga;986 setup_info->pga = pga;
990 987
991 ret = ad4130_write_channel_setup(st, channel, false);988 ret = ad4130_write_channel_setup(st, channel, false);
992 if (ret)989 if (ret) {
993 setup_info->pga = old_pga;990 setup_info->pga = old_pga;
991 return ret;
992 }
994 993
995out:994 return 0;
996 mutex_unlock(&st->lock);
997
998 return ret;
999}995}
1000 996
1001static int ad4130_set_channel_freq(struct ad4130_state *st,997static int ad4130_set_channel_freq(struct ad4130_state *st,
@@ -1004,26 +1000,25 @@ static int ad4130_set_channel_freq(struct ad4130_state *st, · 2 unmodified lines
1004 struct ad4130_chan_info *chan_info = &st->chans_info[channel];1000 struct ad4130_chan_info *chan_info = &st->chans_info[channel];
1005 struct ad4130_setup_info *setup_info = &chan_info->setup;1001 struct ad4130_setup_info *setup_info = &chan_info->setup;
1006 unsigned int fs, old_fs;1002 unsigned int fs, old_fs;
1007 int ret = 0;1003 int ret;
1008 1004
1009 mutex_lock(&st->lock);1005 guard(mutex)(&st->lock);
1010 old_fs = setup_info->fs;1006 old_fs = setup_info->fs;
1011 1007
1012 ad4130_freq_to_fs(setup_info->filter_mode, val, val2, &fs);1008 ad4130_freq_to_fs(setup_info->filter_mode, val, val2, &fs);
1013 1009
1014 if (fs == setup_info->fs)1010 if (fs == setup_info->fs)
1015 goto out;1011 return 0;
1016 1012
1017 setup_info->fs = fs;1013 setup_info->fs = fs;
1018 1014
1019 ret = ad4130_write_channel_setup(st, channel, false);1015 ret = ad4130_write_channel_setup(st, channel, false);
1020 if (ret)1016 if (ret) {
1021 setup_info->fs = old_fs;1017 setup_info->fs = old_fs;
1018 return ret;
1019 }
1022 1020
1023out:1021 return 0;
1024 mutex_unlock(&st->lock);
1025
1026 return ret;
1027}1022}
1028 1023
1029static int _ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,1024static int _ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
@@ -1065,20 +1060,13 @@ static int _ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel, · 35 unmodified lines
1065static int ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,1060static int ad4130_read_sample(struct iio_dev *indio_dev, unsigned int channel,
1066 int *val)1061 int *val)
1067{1062{
1068 struct ad4130_state *st = iio_priv(indio_dev);1063 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
1069 int ret;1064 struct ad4130_state *st = iio_priv(indio_dev);
1070
1071 ret = iio_device_claim_direct_mode(indio_dev);
1072 if (ret)
1073 return ret;
1074 1065
1075 mutex_lock(&st->lock);1066 guard(mutex)(&st->lock);
1076 ret = _ad4130_read_sample(indio_dev, channel, val);1067 return _ad4130_read_sample(indio_dev, channel, val);
1077 mutex_unlock(&st->lock);1068 }
1078 1069 unreachable();
1079 iio_device_release_direct_mode(indio_dev);
1080
1081 return ret;
1082}1070}
1083 1071
1084static int ad4130_read_raw(struct iio_dev *indio_dev,1072static int ad4130_read_raw(struct iio_dev *indio_dev,
@@ -1092,24 +1080,24 @@ static int ad4130_read_raw(struct iio_dev *indio_dev, · 7 unmodified lines
1092 switch (info) {1080 switch (info) {
1093 case IIO_CHAN_INFO_RAW:1081 case IIO_CHAN_INFO_RAW:
1094 return ad4130_read_sample(indio_dev, channel, val);1082 return ad4130_read_sample(indio_dev, channel, val);
1095 case IIO_CHAN_INFO_SCALE:1083 case IIO_CHAN_INFO_SCALE: {
1096 mutex_lock(&st->lock);1084 guard(mutex)(&st->lock);
1097 *val = st->scale_tbls[setup_info->ref_sel][setup_info->pga][0];1085 *val = st->scale_tbls[setup_info->ref_sel][setup_info->pga][0];
1098 *val2 = st->scale_tbls[setup_info->ref_sel][setup_info->pga][1];1086 *val2 = st->scale_tbls[setup_info->ref_sel][setup_info->pga][1];
1099 mutex_unlock(&st->lock);
1100 1087
1101 return IIO_VAL_INT_PLUS_NANO;1088 return IIO_VAL_INT_PLUS_NANO;
1089 }
1102 case IIO_CHAN_INFO_OFFSET:1090 case IIO_CHAN_INFO_OFFSET:
1103 *val = st->bipolar ? -BIT(chan->scan_type.realbits - 1) : 0;1091 *val = st->bipolar ? -BIT(chan->scan_type.realbits - 1) : 0;
1104 1092
1105 return IIO_VAL_INT;1093 return IIO_VAL_INT;
1106 case IIO_CHAN_INFO_SAMP_FREQ:1094 case IIO_CHAN_INFO_SAMP_FREQ: {
1107 mutex_lock(&st->lock);1095 guard(mutex)(&st->lock);
1108 ad4130_fs_to_freq(setup_info->filter_mode, setup_info->fs,1096 ad4130_fs_to_freq(setup_info->filter_mode, setup_info->fs,
1109 val, val2);1097 val, val2);
1110 mutex_unlock(&st->lock);
1111 1098
1112 return IIO_VAL_INT_PLUS_NANO;1099 return IIO_VAL_INT_PLUS_NANO;
1100 }
1113 default:1101 default:
1114 return -EINVAL;1102 return -EINVAL;
1115 }1103 }
@@ -1134,9 +1122,9 @@ static int ad4130_read_avail(struct iio_dev *indio_dev, · 18 unmodified lines
1134 1122
1135 return IIO_AVAIL_LIST;1123 return IIO_AVAIL_LIST;
1136 case IIO_CHAN_INFO_SAMP_FREQ:1124 case IIO_CHAN_INFO_SAMP_FREQ:
1137 mutex_lock(&st->lock);1125 scoped_guard(mutex, &st->lock) {
1138 filter_config = &ad4130_filter_configs[setup_info->filter_mode];1126 filter_config = &ad4130_filter_configs[setup_info->filter_mode];
1139 mutex_unlock(&st->lock);1127 }
1140 1128
1141 *vals = (int *)filter_config->samp_freq_avail;1129 *vals = (int *)filter_config->samp_freq_avail;
1142 *length = filter_config->samp_freq_avail_len * 2;1130 *length = filter_config->samp_freq_avail_len * 2;
@@ -1197,21 +1185,18 @@ static int ad4130_update_scan_mode(struct iio_dev *indio_dev, · 54 unmodified lines
1197 unsigned int val = 0;1185 unsigned int val = 0;
1198 int ret;1186 int ret;
1199 1187
1200 mutex_lock(&st->lock);1188 guard(mutex)(&st->lock);
1201 1189
1202 for_each_set_bit(channel, scan_mask, indio_dev->num_channels) {1190 for_each_set_bit(channel, scan_mask, indio_dev->num_channels) {
1203 ret = ad4130_set_channel_enable(st, channel, true);1191 ret = ad4130_set_channel_enable(st, channel, true);
1204 if (ret)1192 if (ret)
1205 goto out;1193 return ret;
1206 1194
1207 val++;1195 val++;
1208 }1196 }
1209 1197
1210 st->num_enabled_channels = val;1198 st->num_enabled_channels = val;
1211 1199
1212out:
1213 mutex_unlock(&st->lock);
1214
1215 return 0;1200 return 0;
1216}1201}
1217 1202
@@ -1232,22 +1217,19 @@ static int ad4130_set_fifo_watermark(struct iio_dev *indio_dev, unsigned int val · 14 unmodified lines
1232 */1217 */
1233 eff = rounddown(AD4130_FIFO_SIZE, st->num_enabled_channels);1218 eff = rounddown(AD4130_FIFO_SIZE, st->num_enabled_channels);
1234 1219
1235 mutex_lock(&st->lock);1220 guard(mutex)(&st->lock);
1236 1221
1237 ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,1222 ret = regmap_update_bits(st->regmap, AD4130_FIFO_CONTROL_REG,
1238 AD4130_FIFO_CONTROL_WM_MASK,1223 AD4130_FIFO_CONTROL_WM_MASK,
1239 FIELD_PREP(AD4130_FIFO_CONTROL_WM_MASK,1224 FIELD_PREP(AD4130_FIFO_CONTROL_WM_MASK,
1240 ad4130_watermark_reg_val(eff)));1225 ad4130_watermark_reg_val(eff)));
1241 if (ret)1226 if (ret)
1242 goto out;1227 return ret;
1243 1228
1244 st->effective_watermark = eff;1229 st->effective_watermark = eff;
1245 st->watermark = val;1230 st->watermark = val;
1246 1231
1247out:1232 return 0;
1248 mutex_unlock(&st->lock);
1249
1250 return ret;
1251}1233}
1252 1234
1253static const struct iio_info ad4130_info = {1235static const struct iio_info ad4130_info = {
@@ -1265,26 +1247,21 @@ static int ad4130_buffer_postenable(struct iio_dev *indio_dev) · 11 unmodified lines
1265 struct ad4130_state *st = iio_priv(indio_dev);1247 struct ad4130_state *st = iio_priv(indio_dev);
1266 int ret;1248 int ret;
1267 1249
1268 mutex_lock(&st->lock);1250 guard(mutex)(&st->lock);
1269 1251
1270 ret = ad4130_set_watermark_interrupt_en(st, true);1252 ret = ad4130_set_watermark_interrupt_en(st, true);
1271 if (ret)1253 if (ret)
1272 goto out;1254 return ret;
1273 1255
1274 ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);1256 ret = irq_set_irq_type(st->spi->irq, st->inv_irq_trigger);
1275 if (ret)1257 if (ret)
1276 goto out;1258 return ret;
1277 1259
1278 ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);1260 ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_WM);
1279 if (ret)1261 if (ret)
1280 goto out;1262 return ret;
1281
1282 ret = ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
1283
1284out:
1285 mutex_unlock(&st->lock);
1286 1263
1287 return ret;1264 return ad4130_set_mode(st, AD4130_MODE_CONTINUOUS);
1288}1265}
1289 1266
1290static int ad4130_buffer_predisable(struct iio_dev *indio_dev)1267static int ad4130_buffer_predisable(struct iio_dev *indio_dev)
@@ -1293,23 +1270,23 @@ static int ad4130_buffer_predisable(struct iio_dev *indio_dev) · 2 unmodified lines
1293 unsigned int i;1270 unsigned int i;
1294 int ret;1271 int ret;
1295 1272
1296 mutex_lock(&st->lock);1273 guard(mutex)(&st->lock);
1297 1274
1298 ret = ad4130_set_mode(st, AD4130_MODE_IDLE);1275 ret = ad4130_set_mode(st, AD4130_MODE_IDLE);
1299 if (ret)1276 if (ret)
1300 goto out;1277 return ret;
1301 1278
1302 ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);1279 ret = irq_set_irq_type(st->spi->irq, st->irq_trigger);
1303 if (ret)1280 if (ret)
1304 goto out;1281 return ret;
1305 1282
1306 ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);1283 ret = ad4130_set_fifo_mode(st, AD4130_FIFO_MODE_DISABLED);
1307 if (ret)1284 if (ret)
1308 goto out;1285 return ret;
1309 1286
1310 ret = ad4130_set_watermark_interrupt_en(st, false);1287 ret = ad4130_set_watermark_interrupt_en(st, false);
1311 if (ret)1288 if (ret)
1312 goto out;1289 return ret;
1313 1290
1314 /*1291 /*
1315 * update_scan_mode() is not called in the disable path, disable all1292 * update_scan_mode() is not called in the disable path, disable all
@@ -1318,13 +1295,10 @@ static int ad4130_buffer_predisable(struct iio_dev *indio_dev) · 2 unmodified lines
1318 for (i = 0; i < indio_dev->num_channels; i++) {1295 for (i = 0; i < indio_dev->num_channels; i++) {
1319 ret = ad4130_set_channel_enable(st, i, false);1296 ret = ad4130_set_channel_enable(st, i, false);
1320 if (ret)1297 if (ret)
1321 goto out;1298 return ret;
1322 }1299 }
1323 1300
1324out:1301 return 0;
1325 mutex_unlock(&st->lock);
1326
1327 return ret;
1328}1302}
1329 1303
1330static const struct iio_buffer_setup_ops ad4130_buffer_ops = {1304static const struct iio_buffer_setup_ops ad4130_buffer_ops = {
@@ -1338,9 +1312,8 @@ static ssize_t hwfifo_watermark_show(struct device *dev, · 7 unmodified lines
1338 struct ad4130_state *st = iio_priv(dev_to_iio_dev(dev));1312 struct ad4130_state *st = iio_priv(dev_to_iio_dev(dev));
1339 unsigned int val;1313 unsigned int val;
1340 1314
1341 mutex_lock(&st->lock);1315 guard(mutex)(&st->lock);
1342 val = st->watermark;1316 val = st->watermark;
1343 mutex_unlock(&st->lock);
1344 1317
1345 return sysfs_emit(buf, "%d\n", val);1318 return sysfs_emit(buf, "%d\n", val);
1346}1319}
drivers/iio/adc/ad7091r-base.c+8−17
@@ -86,28 +86,25 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev, · 85 unmodified lines
86 unsigned int read_val;86 unsigned int read_val;
87 int ret;87 int ret;
88 88
89 mutex_lock(&st->lock);89 guard(mutex)(&st->lock);
90 90
91 switch (m) {91 switch (m) {
92 case IIO_CHAN_INFO_RAW:92 case IIO_CHAN_INFO_RAW:
93 if (st->mode != AD7091R_MODE_COMMAND) {93 if (st->mode != AD7091R_MODE_COMMAND)
94 ret = -EBUSY;94 return -EBUSY;
95 goto unlock;
96 }
97 95
98 ret = ad7091r_read_one(iio_dev, chan->channel, &read_val);96 ret = ad7091r_read_one(iio_dev, chan->channel, &read_val);
99 if (ret)97 if (ret)
100 goto unlock;98 return ret;
101 99
102 *val = read_val;100 *val = read_val;
103 ret = IIO_VAL_INT;101 return IIO_VAL_INT;
104 break;
105 102
106 case IIO_CHAN_INFO_SCALE:103 case IIO_CHAN_INFO_SCALE:
107 if (st->vref) {104 if (st->vref) {
108 ret = regulator_get_voltage(st->vref);105 ret = regulator_get_voltage(st->vref);
109 if (ret < 0)106 if (ret < 0)
110 goto unlock;107 return ret;
111 108
112 *val = ret / 1000;109 *val = ret / 1000;
113 } else {110 } else {
@@ -115,17 +112,11 @@ static int ad7091r_read_raw(struct iio_dev *iio_dev, · 1 unmodified line
115 }112 }
116 113
117 *val2 = chan->scan_type.realbits;114 *val2 = chan->scan_type.realbits;
118 ret = IIO_VAL_FRACTIONAL_LOG2;115 return IIO_VAL_FRACTIONAL_LOG2;
119 break;
120 116
121 default:117 default:
122 ret = -EINVAL;118 return -EINVAL;
123 break;
124 }119 }
125
126unlock:
127 mutex_unlock(&st->lock);
128 return ret;
129}120}
130 121
131static int ad7091r_read_event_config(struct iio_dev *indio_dev,122static int ad7091r_read_event_config(struct iio_dev *indio_dev,
drivers/iio/adc/ad9467.c+177−90
@@ -17,13 +17,12 @@ · 16 unmodified lines
17#include <linux/of.h>17#include <linux/of.h>
18 18
19 19
20#include <linux/iio/backend.h>
20#include <linux/iio/iio.h>21#include <linux/iio/iio.h>
21#include <linux/iio/sysfs.h>22#include <linux/iio/sysfs.h>
22 23
23#include <linux/clk.h>24#include <linux/clk.h>
24 25
25#include <linux/iio/adc/adi-axi-adc.h>
26
27/*26/*
28 * ADI High-Speed ADC common spi interface registers27 * ADI High-Speed ADC common spi interface registers
29 * See Application-Note AN-877:28 * See Application-Note AN-877:
@@ -102,15 +101,20 @@ · 72 unmodified lines
102#define AD9467_REG_VREF_MASK 0x0F101#define AD9467_REG_VREF_MASK 0x0F
103 102
104struct ad9467_chip_info {103struct ad9467_chip_info {
105 struct adi_axi_adc_chip_info axi_adc_info;104 const char *name;
106 unsigned int default_output_mode;105 unsigned int id;
107 unsigned int vref_mask;106 const struct iio_chan_spec *channels;
107 unsigned int num_channels;
108 const unsigned int (*scale_table)[2];
109 int num_scales;
110 unsigned long max_rate;
111 unsigned int default_output_mode;
112 unsigned int vref_mask;
108};113};
109 114
110#define to_ad9467_chip_info(_info) \
111 container_of(_info, struct ad9467_chip_info, axi_adc_info)
112
113struct ad9467_state {115struct ad9467_state {
116 const struct ad9467_chip_info *info;
117 struct iio_backend *back;
114 struct spi_device *spi;118 struct spi_device *spi;
115 struct clk *clk;119 struct clk *clk;
116 unsigned int output_mode;120 unsigned int output_mode;
@@ -151,10 +155,10 @@ static int ad9467_spi_write(struct spi_device *spi, unsigned int reg, · 34 unmodified lines
151 return spi_write(spi, buf, ARRAY_SIZE(buf));155 return spi_write(spi, buf, ARRAY_SIZE(buf));
152}156}
153 157
154static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg,158static int ad9467_reg_access(struct iio_dev *indio_dev, unsigned int reg,
155 unsigned int writeval, unsigned int *readval)159 unsigned int writeval, unsigned int *readval)
156{160{
157 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);161 struct ad9467_state *st = iio_priv(indio_dev);
158 struct spi_device *spi = st->spi;162 struct spi_device *spi = st->spi;
159 int ret;163 int ret;
160 164
@@ -191,10 +195,10 @@ static const unsigned int ad9467_scale_table[][2] = { · 30 unmodified lines
191 {2300, 8}, {2400, 9}, {2500, 10},195 {2300, 8}, {2400, 9}, {2500, 10},
192};196};
193 197
194static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index,198static void __ad9467_get_scale(struct ad9467_state *st, int index,
195 unsigned int *val, unsigned int *val2)199 unsigned int *val, unsigned int *val2)
196{200{
197 const struct adi_axi_adc_chip_info *info = conv->chip_info;201 const struct ad9467_chip_info *info = st->info;
198 const struct iio_chan_spec *chan = &info->channels[0];202 const struct iio_chan_spec *chan = &info->channels[0];
199 unsigned int tmp;203 unsigned int tmp;
200 204
@@ -229,52 +233,44 @@ static const struct iio_chan_spec ad9467_channels[] = { · 28 unmodified lines
229};233};
230 234
231static const struct ad9467_chip_info ad9467_chip_tbl = {235static const struct ad9467_chip_info ad9467_chip_tbl = {
232 .axi_adc_info = {236 .name = "ad9467",
233 .name = "ad9467",237 .id = CHIPID_AD9467,
234 .id = CHIPID_AD9467,238 .max_rate = 250000000UL,
235 .max_rate = 250000000UL,239 .scale_table = ad9467_scale_table,
236 .scale_table = ad9467_scale_table,240 .num_scales = ARRAY_SIZE(ad9467_scale_table),
237 .num_scales = ARRAY_SIZE(ad9467_scale_table),241 .channels = ad9467_channels,
238 .channels = ad9467_channels,242 .num_channels = ARRAY_SIZE(ad9467_channels),
239 .num_channels = ARRAY_SIZE(ad9467_channels),
240 },
241 .default_output_mode = AD9467_DEF_OUTPUT_MODE,243 .default_output_mode = AD9467_DEF_OUTPUT_MODE,
242 .vref_mask = AD9467_REG_VREF_MASK,244 .vref_mask = AD9467_REG_VREF_MASK,
243};245};
244 246
245static const struct ad9467_chip_info ad9434_chip_tbl = {247static const struct ad9467_chip_info ad9434_chip_tbl = {
246 .axi_adc_info = {248 .name = "ad9434",
247 .name = "ad9434",249 .id = CHIPID_AD9434,
248 .id = CHIPID_AD9434,250 .max_rate = 500000000UL,
249 .max_rate = 500000000UL,251 .scale_table = ad9434_scale_table,
250 .scale_table = ad9434_scale_table,252 .num_scales = ARRAY_SIZE(ad9434_scale_table),
251 .num_scales = ARRAY_SIZE(ad9434_scale_table),253 .channels = ad9434_channels,
252 .channels = ad9434_channels,254 .num_channels = ARRAY_SIZE(ad9434_channels),
253 .num_channels = ARRAY_SIZE(ad9434_channels),
254 },
255 .default_output_mode = AD9434_DEF_OUTPUT_MODE,255 .default_output_mode = AD9434_DEF_OUTPUT_MODE,
256 .vref_mask = AD9434_REG_VREF_MASK,256 .vref_mask = AD9434_REG_VREF_MASK,
257};257};
258 258
259static const struct ad9467_chip_info ad9265_chip_tbl = {259static const struct ad9467_chip_info ad9265_chip_tbl = {
260 .axi_adc_info = {260 .name = "ad9265",
261 .name = "ad9265",261 .id = CHIPID_AD9265,
262 .id = CHIPID_AD9265,262 .max_rate = 125000000UL,
263 .max_rate = 125000000UL,263 .scale_table = ad9265_scale_table,
264 .scale_table = ad9265_scale_table,264 .num_scales = ARRAY_SIZE(ad9265_scale_table),
265 .num_scales = ARRAY_SIZE(ad9265_scale_table),265 .channels = ad9467_channels,
266 .channels = ad9467_channels,266 .num_channels = ARRAY_SIZE(ad9467_channels),
267 .num_channels = ARRAY_SIZE(ad9467_channels),
268 },
269 .default_output_mode = AD9265_DEF_OUTPUT_MODE,267 .default_output_mode = AD9265_DEF_OUTPUT_MODE,
270 .vref_mask = AD9265_REG_VREF_MASK,268 .vref_mask = AD9265_REG_VREF_MASK,
271};269};
272 270
273static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2)271static int ad9467_get_scale(struct ad9467_state *st, int *val, int *val2)
274{272{
275 const struct adi_axi_adc_chip_info *info = conv->chip_info;273 const struct ad9467_chip_info *info = st->info;
276 const struct ad9467_chip_info *info1 = to_ad9467_chip_info(info);
277 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
278 unsigned int i, vref_val;274 unsigned int i, vref_val;
279 int ret;275 int ret;
280 276
@@ -282,7 +278,7 @@ static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2) · 1 unmodified line
282 if (ret < 0)278 if (ret < 0)
283 return ret;279 return ret;
284 280
285 vref_val = ret & info1->vref_mask;281 vref_val = ret & info->vref_mask;
286 282
287 for (i = 0; i < info->num_scales; i++) {283 for (i = 0; i < info->num_scales; i++) {
288 if (vref_val == info->scale_table[i][1])284 if (vref_val == info->scale_table[i][1])
@@ -292,15 +288,14 @@ static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2) · 3 unmodified lines
292 if (i == info->num_scales)288 if (i == info->num_scales)
293 return -ERANGE;289 return -ERANGE;
294 290
295 __ad9467_get_scale(conv, i, val, val2);291 __ad9467_get_scale(st, i, val, val2);
296 292
297 return IIO_VAL_INT_PLUS_MICRO;293 return IIO_VAL_INT_PLUS_MICRO;
298}294}
299 295
300static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2)296static int ad9467_set_scale(struct ad9467_state *st, int val, int val2)
301{297{
302 const struct adi_axi_adc_chip_info *info = conv->chip_info;298 const struct ad9467_chip_info *info = st->info;
303 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
304 unsigned int scale_val[2];299 unsigned int scale_val[2];
305 unsigned int i;300 unsigned int i;
306 int ret;301 int ret;
@@ -309,7 +304,7 @@ static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2) · 2 unmodified lines
309 return -EINVAL;304 return -EINVAL;
310 305
311 for (i = 0; i < info->num_scales; i++) {306 for (i = 0; i < info->num_scales; i++) {
312 __ad9467_get_scale(conv, i, &scale_val[0], &scale_val[1]);307 __ad9467_get_scale(st, i, &scale_val[0], &scale_val[1]);
313 if (scale_val[0] != val || scale_val[1] != val2)308 if (scale_val[0] != val || scale_val[1] != val2)
314 continue;309 continue;
315 310
@@ -326,15 +321,15 @@ static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2) · 10 unmodified lines
326 return -EINVAL;321 return -EINVAL;
327}322}
328 323
329static int ad9467_read_raw(struct adi_axi_adc_conv *conv,324static int ad9467_read_raw(struct iio_dev *indio_dev,
330 struct iio_chan_spec const *chan,325 struct iio_chan_spec const *chan,
331 int *val, int *val2, long m)326 int *val, int *val2, long m)
332{327{
333 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);328 struct ad9467_state *st = iio_priv(indio_dev);
334 329
335 switch (m) {330 switch (m) {
336 case IIO_CHAN_INFO_SCALE:331 case IIO_CHAN_INFO_SCALE:
337 return ad9467_get_scale(conv, val, val2);332 return ad9467_get_scale(st, val, val2);
338 case IIO_CHAN_INFO_SAMP_FREQ:333 case IIO_CHAN_INFO_SAMP_FREQ:
339 *val = clk_get_rate(st->clk);334 *val = clk_get_rate(st->clk);
340 335
@@ -344,17 +339,17 @@ static int ad9467_read_raw(struct adi_axi_adc_conv *conv, · 3 unmodified lines
344 }339 }
345}340}
346 341
347static int ad9467_write_raw(struct adi_axi_adc_conv *conv,342static int ad9467_write_raw(struct iio_dev *indio_dev,
348 struct iio_chan_spec const *chan,343 struct iio_chan_spec const *chan,
349 int val, int val2, long mask)344 int val, int val2, long mask)
350{345{
351 const struct adi_axi_adc_chip_info *info = conv->chip_info;346 struct ad9467_state *st = iio_priv(indio_dev);
352 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);347 const struct ad9467_chip_info *info = st->info;
353 long r_clk;348 long r_clk;
354 349
355 switch (mask) {350 switch (mask) {
356 case IIO_CHAN_INFO_SCALE:351 case IIO_CHAN_INFO_SCALE:
357 return ad9467_set_scale(conv, val, val2);352 return ad9467_set_scale(st, val, val2);
358 case IIO_CHAN_INFO_SAMP_FREQ:353 case IIO_CHAN_INFO_SAMP_FREQ:
359 r_clk = clk_round_rate(st->clk, val);354 r_clk = clk_round_rate(st->clk, val);
360 if (r_clk < 0 || r_clk > info->max_rate) {355 if (r_clk < 0 || r_clk > info->max_rate) {
@@ -369,13 +364,13 @@ static int ad9467_write_raw(struct adi_axi_adc_conv *conv, · 8 unmodified lines
369 }364 }
370}365}
371 366
372static int ad9467_read_avail(struct adi_axi_adc_conv *conv,367static int ad9467_read_avail(struct iio_dev *indio_dev,
373 struct iio_chan_spec const *chan,368 struct iio_chan_spec const *chan,
374 const int **vals, int *type, int *length,369 const int **vals, int *type, int *length,
375 long mask)370 long mask)
376{371{
377 const struct adi_axi_adc_chip_info *info = conv->chip_info;372 struct ad9467_state *st = iio_priv(indio_dev);
378 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);373 const struct ad9467_chip_info *info = st->info;
379 374
380 switch (mask) {375 switch (mask) {
381 case IIO_CHAN_INFO_SCALE:376 case IIO_CHAN_INFO_SCALE:
@@ -389,6 +384,33 @@ static int ad9467_read_avail(struct adi_axi_adc_conv *conv, · 7 unmodified lines
389 }384 }
390}385}
391 386
387static int ad9467_update_scan_mode(struct iio_dev *indio_dev,
388 const unsigned long *scan_mask)
389{
390 struct ad9467_state *st = iio_priv(indio_dev);
391 unsigned int c;
392 int ret;
393
394 for (c = 0; c < st->info->num_channels; c++) {
395 if (test_bit(c, scan_mask))
396 ret = iio_backend_chan_enable(st->back, c);
397 else
398 ret = iio_backend_chan_disable(st->back, c);
399 if (ret)
400 return ret;
401 }
402
403 return 0;
404}
405
406static const struct iio_info ad9467_info = {
407 .read_raw = ad9467_read_raw,
408 .write_raw = ad9467_write_raw,
409 .update_scan_mode = ad9467_update_scan_mode,
410 .debugfs_reg_access = ad9467_reg_access,
411 .read_avail = ad9467_read_avail,
412};
413
392static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)414static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode)
393{415{
394 int ret;416 int ret;
@@ -401,10 +423,9 @@ static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode) · 6 unmodified lines
401 AN877_ADC_TRANSFER_SYNC);423 AN877_ADC_TRANSFER_SYNC);
402}424}
403 425
404static int ad9467_scale_fill(struct adi_axi_adc_conv *conv)426static int ad9467_scale_fill(struct ad9467_state *st)
405{427{
406 const struct adi_axi_adc_chip_info *info = conv->chip_info;428 const struct ad9467_chip_info *info = st->info;
407 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);
408 unsigned int i, val1, val2;429 unsigned int i, val1, val2;
409 430
410 st->scales = devm_kmalloc_array(&st->spi->dev, info->num_scales,431 st->scales = devm_kmalloc_array(&st->spi->dev, info->num_scales,
@@ -413,7 +434,7 @@ static int ad9467_scale_fill(struct adi_axi_adc_conv *conv) · 2 unmodified lines
413 return -ENOMEM;434 return -ENOMEM;
414 435
415 for (i = 0; i < info->num_scales; i++) {436 for (i = 0; i < info->num_scales; i++) {
416 __ad9467_get_scale(conv, i, &val1, &val2);437 __ad9467_get_scale(st, i, &val1, &val2);
417 st->scales[i][0] = val1;438 st->scales[i][0] = val1;
418 st->scales[i][1] = val2;439 st->scales[i][1] = val2;
419 }440 }
@@ -421,11 +442,27 @@ static int ad9467_scale_fill(struct adi_axi_adc_conv *conv) · 1 unmodified line
421 return 0;442 return 0;
422}443}
423 444
424static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv)445static int ad9467_setup(struct ad9467_state *st)
425{446{
426 struct ad9467_state *st = adi_axi_adc_conv_priv(conv);447 struct iio_backend_data_fmt data = {
448 .sign_extend = true,
449 .enable = true,
450 };
451 unsigned int c, mode;
452 int ret;
453
454 mode = st->info->default_output_mode | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;
455 ret = ad9467_outputmode_set(st->spi, mode);
456 if (ret)
457 return ret;
427 458
428 return ad9467_outputmode_set(st->spi, st->output_mode);459 for (c = 0; c < st->info->num_channels; c++) {
460 ret = iio_backend_data_format_set(st->back, c, &data);
461 if (ret)
462 return ret;
463 }
464
465 return 0;
429}466}
430 467
431static int ad9467_reset(struct device *dev)468static int ad9467_reset(struct device *dev)
@@ -443,25 +480,65 @@ static int ad9467_reset(struct device *dev) · 11 unmodified lines
443 return 0;480 return 0;
444}481}
445 482
483static int ad9467_iio_backend_get(struct ad9467_state *st)
484{
485 struct device *dev = &st->spi->dev;
486 struct device_node *__back;
487
488 st->back = devm_iio_backend_get(dev, NULL);
489 if (!IS_ERR(st->back))
490 return 0;
491 /* If not found, don't error out as we might have legacy DT property */
492 if (PTR_ERR(st->back) != -ENOENT)
493 return PTR_ERR(st->back);
494
495 /*
496 * if we don't get the backend using the normal API's, use the legacy
497 * 'adi,adc-dev' property. So we get all nodes with that property, and
498 * look for the one pointing at us. Then we directly lookup that fwnode
499 * on the backend list of registered devices. This is done so we don't
500 * make io-backends mandatory which would break DT ABI.
501 */
502 for_each_node_with_property(__back, "adi,adc-dev") {
503 struct device_node *__me;
504
505 __me = of_parse_phandle(__back, "adi,adc-dev", 0);
506 if (!__me)
507 continue;
508
509 if (!device_match_of_node(dev, __me)) {
510 of_node_put(__me);
511 continue;
512 }
513
514 of_node_put(__me);
515 st->back = __devm_iio_backend_get_from_fwnode_lookup(dev,
516 of_fwnode_handle(__back));
517 of_node_put(__back);
518 return PTR_ERR_OR_ZERO(st->back);
519 }
520
521 return -ENODEV;
522}
523
446static int ad9467_probe(struct spi_device *spi)524static int ad9467_probe(struct spi_device *spi)
447{525{
448 const struct ad9467_chip_info *info;526 struct iio_dev *indio_dev;
449 struct adi_axi_adc_conv *conv;
450 struct ad9467_state *st;527 struct ad9467_state *st;
451 unsigned int id;528 unsigned int id;
452 int ret;529 int ret;
453 530
454 info = spi_get_device_match_data(spi);531 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
455 if (!info)532 if (!indio_dev)
456 return -ENODEV;533 return -ENOMEM;
457
458 conv = devm_adi_axi_adc_conv_register(&spi->dev, sizeof(*st));
459 if (IS_ERR(conv))
460 return PTR_ERR(conv);
461 534
462 st = adi_axi_adc_conv_priv(conv);535 st = iio_priv(indio_dev);
463 st->spi = spi;536 st->spi = spi;
464 537
538 st->info = spi_get_device_match_data(spi);
539 if (!st->info)
540 return -ENODEV;
541
465 st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk");542 st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk");
466 if (IS_ERR(st->clk))543 if (IS_ERR(st->clk))
467 return PTR_ERR(st->clk);544 return PTR_ERR(st->clk);
@@ -475,29 +552,39 @@ static int ad9467_probe(struct spi_device *spi) · 7 unmodified lines
475 if (ret)552 if (ret)
476 return ret;553 return ret;
477 554
478 conv->chip_info = &info->axi_adc_info;555 ret = ad9467_scale_fill(st);
479
480 ret = ad9467_scale_fill(conv);
481 if (ret)556 if (ret)
482 return ret;557 return ret;
483 558
484 id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID);559 id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID);
485 if (id != conv->chip_info->id) {560 if (id != st->info->id) {
486 dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",561 dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n",
487 id, conv->chip_info->id);562 id, st->info->id);
488 return -ENODEV;563 return -ENODEV;
489 }564 }
490 565
491 conv->reg_access = ad9467_reg_access;566 indio_dev->name = st->info->name;
492 conv->write_raw = ad9467_write_raw;567 indio_dev->channels = st->info->channels;
493 conv->read_raw = ad9467_read_raw;568 indio_dev->num_channels = st->info->num_channels;
494 conv->read_avail = ad9467_read_avail;569 indio_dev->info = &ad9467_info;
495 conv->preenable_setup = ad9467_preenable_setup;
496 570
497 st->output_mode = info->default_output_mode |571 ret = ad9467_iio_backend_get(st);
498 AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT;572 if (ret)
573 return ret;
499 574
500 return 0;575 ret = devm_iio_backend_request_buffer(&spi->dev, st->back, indio_dev);
576 if (ret)
577 return ret;
578
579 ret = devm_iio_backend_enable(&spi->dev, st->back);
580 if (ret)
581 return ret;
582
583 ret = ad9467_setup(st);
584 if (ret)
585 return ret;
586
587 return devm_iio_device_register(&spi->dev, indio_dev);
501}588}
502 589
503static const struct of_device_id ad9467_of_match[] = {590static const struct of_device_id ad9467_of_match[] = {
@@ -529,4 +616,4 @@ module_spi_driver(ad9467_driver); · 25 unmodified lines
529MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");616MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
530MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");617MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
531MODULE_LICENSE("GPL v2");618MODULE_LICENSE("GPL v2");
532MODULE_IMPORT_NS(IIO_ADI_AXI);619MODULE_IMPORT_NS(IIO_BACKEND);
drivers/iio/adc/ad_sigma_delta.c+6−1
@@ -568,6 +568,7 @@ EXPORT_SYMBOL_NS_GPL(ad_sd_validate_trigger, IIO_AD_SIGMA_DELTA); · 567 unmodified lines
568static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev)568static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev)
569{569{
570 struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);570 struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
571 unsigned long irq_flags = irq_get_trigger_type(sigma_delta->spi->irq);
571 int ret;572 int ret;
572 573
573 if (dev != &sigma_delta->spi->dev) {574 if (dev != &sigma_delta->spi->dev) {
@@ -588,9 +589,13 @@ static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_de · 14 unmodified lines
588 /* the IRQ core clears IRQ_DISABLE_UNLAZY flag when freeing an IRQ */589 /* the IRQ core clears IRQ_DISABLE_UNLAZY flag when freeing an IRQ */
589 irq_set_status_flags(sigma_delta->spi->irq, IRQ_DISABLE_UNLAZY);590 irq_set_status_flags(sigma_delta->spi->irq, IRQ_DISABLE_UNLAZY);
590 591
592 /* Allow overwriting the flags from firmware */
593 if (!irq_flags)
594 irq_flags = sigma_delta->info->irq_flags;
595
591 ret = devm_request_irq(dev, sigma_delta->spi->irq,596 ret = devm_request_irq(dev, sigma_delta->spi->irq,
592 ad_sd_data_rdy_trig_poll,597 ad_sd_data_rdy_trig_poll,
593 sigma_delta->info->irq_flags | IRQF_NO_AUTOEN,598 irq_flags | IRQF_NO_AUTOEN,
594 indio_dev->name,599 indio_dev->name,
595 sigma_delta);600 sigma_delta);
596 if (ret)601 if (ret)
drivers/iio/adc/adi-axi-adc.c+96−289
@@ -8,6 +8,7 @@ · 7 unmodified lines
8 8
9#include <linux/bitfield.h>9#include <linux/bitfield.h>
10#include <linux/clk.h>10#include <linux/clk.h>
11#include <linux/err.h>
11#include <linux/io.h>12#include <linux/io.h>
12#include <linux/delay.h>13#include <linux/delay.h>
13#include <linux/module.h>14#include <linux/module.h>
@@ -17,13 +18,12 @@ · 3 unmodified lines
17#include <linux/regmap.h>18#include <linux/regmap.h>
18#include <linux/slab.h>19#include <linux/slab.h>
19 20
20#include <linux/iio/iio.h>
21#include <linux/iio/sysfs.h>
22#include <linux/iio/buffer.h>
23#include <linux/iio/buffer-dmaengine.h>
24
25#include <linux/fpga/adi-axi-common.h>21#include <linux/fpga/adi-axi-common.h>
26#include <linux/iio/adc/adi-axi-adc.h>22
23#include <linux/iio/backend.h>
24#include <linux/iio/buffer-dmaengine.h>
25#include <linux/iio/buffer.h>
26#include <linux/iio/iio.h>
27 27
28/*28/*
29 * Register definitions:29 * Register definitions:
@@ -44,6 +44,7 @@ · 14 unmodified lines
44#define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)44#define ADI_AXI_REG_CHAN_CTRL_PN_SEL_OWR BIT(10)
45#define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)45#define ADI_AXI_REG_CHAN_CTRL_IQCOR_EN BIT(9)
46#define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)46#define ADI_AXI_REG_CHAN_CTRL_DCFILT_EN BIT(8)
47#define ADI_AXI_REG_CHAN_CTRL_FMT_MASK GENMASK(6, 4)
47#define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)48#define ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT BIT(6)
48#define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)49#define ADI_AXI_REG_CHAN_CTRL_FMT_TYPE BIT(5)
49#define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)50#define ADI_AXI_REG_CHAN_CTRL_FMT_EN BIT(4)
@@ -55,286 +56,100 @@ · 5 unmodified lines
55 ADI_AXI_REG_CHAN_CTRL_FMT_EN | \56 ADI_AXI_REG_CHAN_CTRL_FMT_EN | \
56 ADI_AXI_REG_CHAN_CTRL_ENABLE)57 ADI_AXI_REG_CHAN_CTRL_ENABLE)
57 58
58struct adi_axi_adc_core_info {
59 unsigned int version;
60};
61
62struct adi_axi_adc_state {59struct adi_axi_adc_state {
63 struct mutex lock;
64
65 struct adi_axi_adc_client *client;
66 struct regmap *regmap;60 struct regmap *regmap;
67};
68
69struct adi_axi_adc_client {
70 struct list_head entry;
71 struct adi_axi_adc_conv conv;
72 struct adi_axi_adc_state *state;
73 struct device *dev;61 struct device *dev;
74 const struct adi_axi_adc_core_info *info;
75};62};
76 63
77static LIST_HEAD(registered_clients);64static int axi_adc_enable(struct iio_backend *back)
78static DEFINE_MUTEX(registered_clients_lock);
79
80static struct adi_axi_adc_client *conv_to_client(struct adi_axi_adc_conv *conv)
81{
82 return container_of(conv, struct adi_axi_adc_client, conv);
83}
84
85void *adi_axi_adc_conv_priv(struct adi_axi_adc_conv *conv)
86{
87 struct adi_axi_adc_client *cl = conv_to_client(conv);
88
89 return (char *)cl + ALIGN(sizeof(struct adi_axi_adc_client),
90 IIO_DMA_MINALIGN);
91}
92EXPORT_SYMBOL_NS_GPL(adi_axi_adc_conv_priv, IIO_ADI_AXI);
93
94static int adi_axi_adc_config_dma_buffer(struct device *dev,
95 struct iio_dev *indio_dev)
96{
97 const char *dma_name;
98
99 if (!device_property_present(dev, "dmas"))
100 return 0;
101
102 if (device_property_read_string(dev, "dma-names", &dma_name))
103 dma_name = "rx";
104
105 return devm_iio_dmaengine_buffer_setup(indio_dev->dev.parent,
106 indio_dev, dma_name);
107}
108
109static int adi_axi_adc_read_raw(struct iio_dev *indio_dev,
110 struct iio_chan_spec const *chan,
111 int *val, int *val2, long mask)
112{
113 struct adi_axi_adc_state *st = iio_priv(indio_dev);
114 struct adi_axi_adc_conv *conv = &st->client->conv;
115
116 if (!conv->read_raw)
117 return -EOPNOTSUPP;
118
119 return conv->read_raw(conv, chan, val, val2, mask);
120}
121
122static int adi_axi_adc_write_raw(struct iio_dev *indio_dev,
123 struct iio_chan_spec const *chan,
124 int val, int val2, long mask)
125{
126 struct adi_axi_adc_state *st = iio_priv(indio_dev);
127 struct adi_axi_adc_conv *conv = &st->client->conv;
128
129 if (!conv->write_raw)
130 return -EOPNOTSUPP;
131
132 return conv->write_raw(conv, chan, val, val2, mask);
133}
134
135static int adi_axi_adc_read_avail(struct iio_dev *indio_dev,
136 struct iio_chan_spec const *chan,
137 const int **vals, int *type, int *length,
138 long mask)
139{
140 struct adi_axi_adc_state *st = iio_priv(indio_dev);
141 struct adi_axi_adc_conv *conv = &st->client->conv;
142
143 if (!conv->read_avail)
144 return -EOPNOTSUPP;
145
146 return conv->read_avail(conv, chan, vals, type, length, mask);
147}
148
149static int adi_axi_adc_update_scan_mode(struct iio_dev *indio_dev,
150 const unsigned long *scan_mask)
151{65{
152 struct adi_axi_adc_state *st = iio_priv(indio_dev);66 struct adi_axi_adc_state *st = iio_backend_get_priv(back);
153 struct adi_axi_adc_conv *conv = &st->client->conv;
154 unsigned int i;
155 int ret;67 int ret;
156 68
157 for (i = 0; i < conv->chip_info->num_channels; i++) {69 ret = regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
158 if (test_bit(i, scan_mask))70 ADI_AXI_REG_RSTN_MMCM_RSTN);
159 ret = regmap_set_bits(st->regmap,71 if (ret)
160 ADI_AXI_REG_CHAN_CTRL(i),72 return ret;
161 ADI_AXI_REG_CHAN_CTRL_ENABLE);
162 else
163 ret = regmap_clear_bits(st->regmap,
164 ADI_AXI_REG_CHAN_CTRL(i),
165 ADI_AXI_REG_CHAN_CTRL_ENABLE);
166 if (ret)
167 return ret;
168 }
169
170 return 0;
171}
172
173static struct adi_axi_adc_conv *adi_axi_adc_conv_register(struct device *dev,
174 size_t sizeof_priv)
175{
176 struct adi_axi_adc_client *cl;
177 size_t alloc_size;
178
179 alloc_size = ALIGN(sizeof(struct adi_axi_adc_client), IIO_DMA_MINALIGN);
180 if (sizeof_priv)
181 alloc_size += ALIGN(sizeof_priv, IIO_DMA_MINALIGN);
182
183 cl = kzalloc(alloc_size, GFP_KERNEL);
184 if (!cl)
185 return ERR_PTR(-ENOMEM);
186
187 mutex_lock(&registered_clients_lock);
188
189 cl->dev = get_device(dev);
190
191 list_add_tail(&cl->entry, &registered_clients);
192
193 mutex_unlock(&registered_clients_lock);
194 73
195 return &cl->conv;74 fsleep(10000);
75 return regmap_set_bits(st->regmap, ADI_AXI_REG_RSTN,
76 ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
196}77}
197 78
198static void adi_axi_adc_conv_unregister(struct adi_axi_adc_conv *conv)79static void axi_adc_disable(struct iio_backend *back)
199{80{
200 struct adi_axi_adc_client *cl = conv_to_client(conv);81 struct adi_axi_adc_state *st = iio_backend_get_priv(back);
201
202 mutex_lock(&registered_clients_lock);
203
204 list_del(&cl->entry);
205 put_device(cl->dev);
206 82
207 mutex_unlock(&registered_clients_lock);83 regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
208
209 kfree(cl);
210}84}
211 85
212static void devm_adi_axi_adc_conv_release(void *conv)86static int axi_adc_data_format_set(struct iio_backend *back, unsigned int chan,
87 const struct iio_backend_data_fmt *data)
213{88{
214 adi_axi_adc_conv_unregister(conv);89 struct adi_axi_adc_state *st = iio_backend_get_priv(back);
90 u32 val;
91
92 if (!data->enable)
93 return regmap_clear_bits(st->regmap,
94 ADI_AXI_REG_CHAN_CTRL(chan),
95 ADI_AXI_REG_CHAN_CTRL_FMT_EN);
96
97 val = FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_EN, true);
98 if (data->sign_extend)
99 val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_SIGNEXT, true);
100 if (data->type == IIO_BACKEND_OFFSET_BINARY)
101 val |= FIELD_PREP(ADI_AXI_REG_CHAN_CTRL_FMT_TYPE, true);
102
103 return regmap_update_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
104 ADI_AXI_REG_CHAN_CTRL_FMT_MASK, val);
215}105}
216 106
217struct adi_axi_adc_conv *devm_adi_axi_adc_conv_register(struct device *dev,107static int axi_adc_chan_enable(struct iio_backend *back, unsigned int chan)
218 size_t sizeof_priv)
219{108{
220 struct adi_axi_adc_conv *conv;109 struct adi_axi_adc_state *st = iio_backend_get_priv(back);
221 int ret;
222
223 conv = adi_axi_adc_conv_register(dev, sizeof_priv);
224 if (IS_ERR(conv))
225 return conv;
226 110
227 ret = devm_add_action_or_reset(dev, devm_adi_axi_adc_conv_release,111 return regmap_set_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
228 conv);112 ADI_AXI_REG_CHAN_CTRL_ENABLE);
229 if (ret)
230 return ERR_PTR(ret);
231
232 return conv;
233}113}
234EXPORT_SYMBOL_NS_GPL(devm_adi_axi_adc_conv_register, IIO_ADI_AXI);
235
236static const struct iio_info adi_axi_adc_info = {
237 .read_raw = &adi_axi_adc_read_raw,
238 .write_raw = &adi_axi_adc_write_raw,
239 .update_scan_mode = &adi_axi_adc_update_scan_mode,
240 .read_avail = &adi_axi_adc_read_avail,
241};
242
243static const struct adi_axi_adc_core_info adi_axi_adc_10_0_a_info = {
244 .version = ADI_AXI_PCORE_VER(10, 0, 'a'),
245};
246 114
247static struct adi_axi_adc_client *adi_axi_adc_attach_client(struct device *dev)115static int axi_adc_chan_disable(struct iio_backend *back, unsigned int chan)
248{116{
249 const struct adi_axi_adc_core_info *info;117 struct adi_axi_adc_state *st = iio_backend_get_priv(back);
250 struct adi_axi_adc_client *cl;
251 struct device_node *cln;
252
253 info = of_device_get_match_data(dev);
254 if (!info)
255 return ERR_PTR(-ENODEV);
256
257 cln = of_parse_phandle(dev->of_node, "adi,adc-dev", 0);
258 if (!cln) {
259 dev_err(dev, "No 'adi,adc-dev' node defined\n");
260 return ERR_PTR(-ENODEV);
261 }
262
263 mutex_lock(&registered_clients_lock);
264
265 list_for_each_entry(cl, &registered_clients, entry) {
266 if (!cl->dev)
267 continue;
268
269 if (cl->dev->of_node != cln)
270 continue;
271
272 if (!try_module_get(cl->dev->driver->owner)) {
273 mutex_unlock(&registered_clients_lock);
274 of_node_put(cln);
275 return ERR_PTR(-ENODEV);
276 }
277
278 get_device(cl->dev);
279 cl->info = info;
280 mutex_unlock(&registered_clients_lock);
281 of_node_put(cln);
282 return cl;
283 }
284 118
285 mutex_unlock(&registered_clients_lock);119 return regmap_clear_bits(st->regmap, ADI_AXI_REG_CHAN_CTRL(chan),
286 of_node_put(cln);120 ADI_AXI_REG_CHAN_CTRL_ENABLE);
287
288 return ERR_PTR(-EPROBE_DEFER);
289}121}
290 122
291static int adi_axi_adc_setup_channels(struct device *dev,123static struct iio_buffer *axi_adc_request_buffer(struct iio_backend *back,
292 struct adi_axi_adc_state *st)124 struct iio_dev *indio_dev)
293{125{
294 struct adi_axi_adc_conv *conv = &st->client->conv;126 struct adi_axi_adc_state *st = iio_backend_get_priv(back);
295 int i, ret;127 struct iio_buffer *buffer;
128 const char *dma_name;
129 int ret;
296 130
297 if (conv->preenable_setup) {131 if (device_property_read_string(st->dev, "dma-names", &dma_name))
298 ret = conv->preenable_setup(conv);132 dma_name = "rx";
299 if (ret)
300 return ret;
301 }
302 133
303 for (i = 0; i < conv->chip_info->num_channels; i++) {134 buffer = iio_dmaengine_buffer_alloc(st->dev, dma_name);
304 ret = regmap_write(st->regmap, ADI_AXI_REG_CHAN_CTRL(i),135 if (IS_ERR(buffer)) {
305 ADI_AXI_REG_CHAN_CTRL_DEFAULTS);136 dev_err(st->dev, "Could not get DMA buffer, %ld\n",
306 if (ret)137 PTR_ERR(buffer));
307 return ret;138 return ERR_CAST(buffer);
308 }139 }
309 140
310 return 0;141 indio_dev->modes |= INDIO_BUFFER_HARDWARE;
311}142 ret = iio_device_attach_buffer(indio_dev, buffer);
312
313static int axi_adc_reset(struct adi_axi_adc_state *st)
314{
315 int ret;
316
317 ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
318 if (ret)
319 return ret;
320
321 mdelay(10);
322 ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN,
323 ADI_AXI_REG_RSTN_MMCM_RSTN);
324 if (ret)143 if (ret)
325 return ret;144 return ERR_PTR(ret);
326 145
327 mdelay(10);146 return buffer;
328 return regmap_write(st->regmap, ADI_AXI_REG_RSTN,
329 ADI_AXI_REG_RSTN_RSTN | ADI_AXI_REG_RSTN_MMCM_RSTN);
330}147}
331 148
332static void adi_axi_adc_cleanup(void *data)149static void axi_adc_free_buffer(struct iio_backend *back,
150 struct iio_buffer *buffer)
333{151{
334 struct adi_axi_adc_client *cl = data;152 iio_dmaengine_buffer_free(buffer);
335
336 put_device(cl->dev);
337 module_put(cl->dev->driver->owner);
338}153}
339 154
340static const struct regmap_config axi_adc_regmap_config = {155static const struct regmap_config axi_adc_regmap_config = {
@@ -344,45 +159,47 @@ static const struct regmap_config axi_adc_regmap_config = { · 3 unmodified lines
344 .max_register = 0x0800,159 .max_register = 0x0800,
345};160};
346 161
162static const struct iio_backend_ops adi_axi_adc_generic = {
163 .enable = axi_adc_enable,
164 .disable = axi_adc_disable,
165 .data_format_set = axi_adc_data_format_set,
166 .chan_enable = axi_adc_chan_enable,
167 .chan_disable = axi_adc_chan_disable,
168 .request_buffer = axi_adc_request_buffer,
169 .free_buffer = axi_adc_free_buffer,
170};
171
347static int adi_axi_adc_probe(struct platform_device *pdev)172static int adi_axi_adc_probe(struct platform_device *pdev)
348{173{
349 struct adi_axi_adc_conv *conv;174 const unsigned int *expected_ver;
350 struct iio_dev *indio_dev;
351 struct adi_axi_adc_client *cl;
352 struct adi_axi_adc_state *st;175 struct adi_axi_adc_state *st;
353 void __iomem *base;176 void __iomem *base;
354 unsigned int ver;177 unsigned int ver;
355 int ret;178 int ret;
356 179
357 cl = adi_axi_adc_attach_client(&pdev->dev);180 st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
358 if (IS_ERR(cl))181 if (!st)
359 return PTR_ERR(cl);
360
361 ret = devm_add_action_or_reset(&pdev->dev, adi_axi_adc_cleanup, cl);
362 if (ret)
363 return ret;
364
365 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
366 if (indio_dev == NULL)
367 return -ENOMEM;182 return -ENOMEM;
368 183
369 st = iio_priv(indio_dev);
370 st->client = cl;
371 cl->state = st;
372 mutex_init(&st->lock);
373
374 base = devm_platform_ioremap_resource(pdev, 0);184 base = devm_platform_ioremap_resource(pdev, 0);
375 if (IS_ERR(base))185 if (IS_ERR(base))
376 return PTR_ERR(base);186 return PTR_ERR(base);
377 187
188 st->dev = &pdev->dev;
378 st->regmap = devm_regmap_init_mmio(&pdev->dev, base,189 st->regmap = devm_regmap_init_mmio(&pdev->dev, base,
379 &axi_adc_regmap_config);190 &axi_adc_regmap_config);
380 if (IS_ERR(st->regmap))191 if (IS_ERR(st->regmap))
381 return PTR_ERR(st->regmap);192 return PTR_ERR(st->regmap);
382 193
383 conv = &st->client->conv;194 expected_ver = device_get_match_data(&pdev->dev);
195 if (!expected_ver)
196 return -ENODEV;
384 197
385 ret = axi_adc_reset(st);198 /*
199 * Force disable the core. Up to the frontend to enable us. And we can
200 * still read/write registers...
201 */
202 ret = regmap_write(st->regmap, ADI_AXI_REG_RSTN, 0);
386 if (ret)203 if (ret)
387 return ret;204 return ret;
388 205
@@ -390,33 +207,19 @@ static int adi_axi_adc_probe(struct platform_device *pdev) · 1 unmodified line
390 if (ret)207 if (ret)
391 return ret;208 return ret;
392 209
393 if (cl->info->version > ver) {210 if (*expected_ver > ver) {
394 dev_err(&pdev->dev,211 dev_err(&pdev->dev,
395 "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",212 "IP core version is too old. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
396 ADI_AXI_PCORE_VER_MAJOR(cl->info->version),213 ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
397 ADI_AXI_PCORE_VER_MINOR(cl->info->version),214 ADI_AXI_PCORE_VER_MINOR(*expected_ver),
398 ADI_AXI_PCORE_VER_PATCH(cl->info->version),215 ADI_AXI_PCORE_VER_PATCH(*expected_ver),
399 ADI_AXI_PCORE_VER_MAJOR(ver),216 ADI_AXI_PCORE_VER_MAJOR(ver),
400 ADI_AXI_PCORE_VER_MINOR(ver),217 ADI_AXI_PCORE_VER_MINOR(ver),
401 ADI_AXI_PCORE_VER_PATCH(ver));218 ADI_AXI_PCORE_VER_PATCH(ver));
402 return -ENODEV;219 return -ENODEV;
403 }220 }
404 221
405 indio_dev->info = &adi_axi_adc_info;222 ret = devm_iio_backend_register(&pdev->dev, &adi_axi_adc_generic, st);
406 indio_dev->name = "adi-axi-adc";
407 indio_dev->modes = INDIO_DIRECT_MODE;
408 indio_dev->num_channels = conv->chip_info->num_channels;
409 indio_dev->channels = conv->chip_info->channels;
410
411 ret = adi_axi_adc_config_dma_buffer(&pdev->dev, indio_dev);
412 if (ret)
413 return ret;
414
415 ret = adi_axi_adc_setup_channels(&pdev->dev, st);
416 if (ret)
417 return ret;
418
419 ret = devm_iio_device_register(&pdev->dev, indio_dev);
420 if (ret)223 if (ret)
421 return ret;224 return ret;
422 225
@@ -428,6 +231,8 @@ static int adi_axi_adc_probe(struct platform_device *pdev) · 5 unmodified lines
428 return 0;231 return 0;
429}232}
430 233
234static unsigned int adi_axi_adc_10_0_a_info = ADI_AXI_PCORE_VER(10, 0, 'a');
235
431/* Match table for of_platform binding */236/* Match table for of_platform binding */
432static const struct of_device_id adi_axi_adc_of_match[] = {237static const struct of_device_id adi_axi_adc_of_match[] = {
433 { .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },238 { .compatible = "adi,axi-adc-10.0.a", .data = &adi_axi_adc_10_0_a_info },
@@ -447,3 +252,5 @@ module_platform_driver(adi_axi_adc_driver); · 13 unmodified lines
447MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");252MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
448MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");253MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
449MODULE_LICENSE("GPL v2");254MODULE_LICENSE("GPL v2");
255MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
256MODULE_IMPORT_NS(IIO_BACKEND);
drivers/iio/adc/max1363.c+79−92
@@ -357,62 +357,55 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev, · 356 unmodified lines
357 int *val,357 int *val,
358 long m)358 long m)
359{359{
360 int ret = 0;360 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
361 s32 data;361 s32 data;
362 u8 rxbuf[2];362 u8 rxbuf[2];
363 struct max1363_state *st = iio_priv(indio_dev);363 struct max1363_state *st = iio_priv(indio_dev);
364 struct i2c_client *client = st->client;364 struct i2c_client *client = st->client;
365 365
366 ret = iio_device_claim_direct_mode(indio_dev);366 guard(mutex)(&st->lock);
367 if (ret)367
368 return ret;368 /*
369 mutex_lock(&st->lock);369 * If monitor mode is enabled, the method for reading a single
370 370 * channel will have to be rather different and has not yet
371 /*371 * been implemented.
372 * If monitor mode is enabled, the method for reading a single372 *
373 * channel will have to be rather different and has not yet373 * Also, cannot read directly if buffered capture enabled.
374 * been implemented.374 */
375 *375 if (st->monitor_on)
376 * Also, cannot read directly if buffered capture enabled.376 return -EBUSY;
377 */377
378 if (st->monitor_on) {378 /* Check to see if current scan mode is correct */
379 ret = -EBUSY;379 if (st->current_mode != &max1363_mode_table[chan->address]) {
380 goto error_ret;380 int ret;
381 }381
382 382 /* Update scan mode if needed */
383 /* Check to see if current scan mode is correct */383 st->current_mode = &max1363_mode_table[chan->address];
384 if (st->current_mode != &max1363_mode_table[chan->address]) {384 ret = max1363_set_scan_mode(st);
385 /* Update scan mode if needed */385 if (ret < 0)
386 st->current_mode = &max1363_mode_table[chan->address];386 return ret;
387 ret = max1363_set_scan_mode(st);
388 if (ret < 0)
389 goto error_ret;
390 }
391 if (st->chip_info->bits != 8) {
392 /* Get reading */
393 data = st->recv(client, rxbuf, 2);
394 if (data < 0) {
395 ret = data;
396 goto error_ret;
397 }387 }
398 data = (rxbuf[1] | rxbuf[0] << 8) &388 if (st->chip_info->bits != 8) {
399 ((1 << st->chip_info->bits) - 1);389 /* Get reading */
400 } else {390 data = st->recv(client, rxbuf, 2);
401 /* Get reading */391 if (data < 0)
402 data = st->recv(client, rxbuf, 1);392 return data;
403 if (data < 0) {393
404 ret = data;394 data = (rxbuf[1] | rxbuf[0] << 8) &
405 goto error_ret;395 ((1 << st->chip_info->bits) - 1);
396 } else {
397 /* Get reading */
398 data = st->recv(client, rxbuf, 1);
399 if (data < 0)
400 return data;
401
402 data = rxbuf[0];
406 }403 }
407 data = rxbuf[0];404 *val = data;
408 }
409 *val = data;
410
411error_ret:
412 mutex_unlock(&st->lock);
413 iio_device_release_direct_mode(indio_dev);
414 return ret;
415 405
406 return 0;
407 }
408 unreachable();
416}409}
417 410
418static int max1363_read_raw(struct iio_dev *indio_dev,411static int max1363_read_raw(struct iio_dev *indio_dev,
@@ -710,9 +703,8 @@ static ssize_t max1363_monitor_store_freq(struct device *dev, · 291 unmodified lines
710 if (!found)703 if (!found)
711 return -EINVAL;704 return -EINVAL;
712 705
713 mutex_lock(&st->lock);706 scoped_guard(mutex, &st->lock)
714 st->monitor_speed = i;707 st->monitor_speed = i;
715 mutex_unlock(&st->lock);
716 708
717 return 0;709 return 0;
718}710}
@@ -815,12 +807,11 @@ static int max1363_read_event_config(struct iio_dev *indio_dev, · 96 unmodified lines
815 int val;807 int val;
816 int number = chan->channel;808 int number = chan->channel;
817 809
818 mutex_lock(&st->lock);810 guard(mutex)(&st->lock);
819 if (dir == IIO_EV_DIR_FALLING)811 if (dir == IIO_EV_DIR_FALLING)
820 val = (1 << number) & st->mask_low;812 val = (1 << number) & st->mask_low;
821 else813 else
822 val = (1 << number) & st->mask_high;814 val = (1 << number) & st->mask_high;
823 mutex_unlock(&st->lock);
824 815
825 return val;816 return val;
826}817}
@@ -962,46 +953,42 @@ static int max1363_write_event_config(struct iio_dev *indio_dev, · 135 unmodified lines
962 const struct iio_chan_spec *chan, enum iio_event_type type,953 const struct iio_chan_spec *chan, enum iio_event_type type,
963 enum iio_event_direction dir, int state)954 enum iio_event_direction dir, int state)
964{955{
965 int ret = 0;
966 struct max1363_state *st = iio_priv(indio_dev);956 struct max1363_state *st = iio_priv(indio_dev);
967 u16 unifiedmask;
968 int number = chan->channel;
969 957
970 ret = iio_device_claim_direct_mode(indio_dev);958 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
971 if (ret)959 int number = chan->channel;
972 return ret;960 u16 unifiedmask;
973 mutex_lock(&st->lock);961 int ret;
974 962
975 unifiedmask = st->mask_low | st->mask_high;963 guard(mutex)(&st->lock);
976 if (dir == IIO_EV_DIR_FALLING) {964
977 965 unifiedmask = st->mask_low | st->mask_high;
978 if (state == 0)966 if (dir == IIO_EV_DIR_FALLING) {
979 st->mask_low &= ~(1 << number);967
980 else {968 if (state == 0)
981 ret = __max1363_check_event_mask((1 << number),969 st->mask_low &= ~(1 << number);
982 unifiedmask);970 else {
983 if (ret)971 ret = __max1363_check_event_mask((1 << number),
984 goto error_ret;972 unifiedmask);
985 st->mask_low |= (1 << number);973 if (ret)
986 }974 return ret;
987 } else {975 st->mask_low |= (1 << number);
988 if (state == 0)976 }
989 st->mask_high &= ~(1 << number);977 } else {
990 else {978 if (state == 0)
991 ret = __max1363_check_event_mask((1 << number),979 st->mask_high &= ~(1 << number);
992 unifiedmask);980 else {
993 if (ret)981 ret = __max1363_check_event_mask((1 << number),
994 goto error_ret;982 unifiedmask);
995 st->mask_high |= (1 << number);983 if (ret)
984 return ret;
985 st->mask_high |= (1 << number);
986 }
996 }987 }
997 }988 }
998
999 max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));989 max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low));
1000error_ret:
1001 mutex_unlock(&st->lock);
1002 iio_device_release_direct_mode(indio_dev);
1003 990
1004 return ret;991 return 0;
1005}992}
1006 993
1007/*994/*
drivers/iio/adc/mcp320x.c+9−20
@@ -371,6 +371,11 @@ static const struct mcp320x_chip_info mcp320x_chip_infos[] = { · 370 unmodified lines
371 },371 },
372};372};
373 373
374static void mcp320x_regulator_disable(void *reg)
375{
376 regulator_disable(reg);
377}
378
374static int mcp320x_probe(struct spi_device *spi)379static int mcp320x_probe(struct spi_device *spi)
375{380{
376 struct iio_dev *indio_dev;381 struct iio_dev *indio_dev;
@@ -388,7 +393,6 @@ static int mcp320x_probe(struct spi_device *spi) · 11 unmodified lines
388 indio_dev->name = spi_get_device_id(spi)->name;393 indio_dev->name = spi_get_device_id(spi)->name;
389 indio_dev->modes = INDIO_DIRECT_MODE;394 indio_dev->modes = INDIO_DIRECT_MODE;
390 indio_dev->info = &mcp320x_info;395 indio_dev->info = &mcp320x_info;
391 spi_set_drvdata(spi, indio_dev);
392 396
393 device_index = spi_get_device_id(spi)->driver_data;397 device_index = spi_get_device_id(spi)->driver_data;
394 chip_info = &mcp320x_chip_infos[device_index];398 chip_info = &mcp320x_chip_infos[device_index];
@@ -445,27 +449,13 @@ static int mcp320x_probe(struct spi_device *spi) · 50 unmodified lines
445 if (ret < 0)449 if (ret < 0)
446 return ret;450 return ret;
447 451
448 mutex_init(&adc->lock);452 ret = devm_add_action_or_reset(&spi->dev, mcp320x_regulator_disable, adc->reg);
449
450 ret = iio_device_register(indio_dev);
451 if (ret < 0)453 if (ret < 0)
452 goto reg_disable;454 return ret;
453
454 return 0;
455
456reg_disable:
457 regulator_disable(adc->reg);
458
459 return ret;
460}
461 455
462static void mcp320x_remove(struct spi_device *spi)456 mutex_init(&adc->lock);
463{
464 struct iio_dev *indio_dev = spi_get_drvdata(spi);
465 struct mcp320x *adc = iio_priv(indio_dev);
466 457
467 iio_device_unregister(indio_dev);458 return devm_iio_device_register(&spi->dev, indio_dev);
468 regulator_disable(adc->reg);
469}459}
470 460
471static const struct of_device_id mcp320x_dt_ids[] = {461static const struct of_device_id mcp320x_dt_ids[] = {
@@ -520,7 +510,6 @@ static struct spi_driver mcp320x_driver = { · 48 unmodified lines
520 .of_match_table = mcp320x_dt_ids,510 .of_match_table = mcp320x_dt_ids,
521 },511 },
522 .probe = mcp320x_probe,512 .probe = mcp320x_probe,
523 .remove = mcp320x_remove,
524 .id_table = mcp320x_id,513 .id_table = mcp320x_id,
525};514};
526module_spi_driver(mcp320x_driver);515module_spi_driver(mcp320x_driver);
drivers/iio/adc/pac1934.c+1636−0
@@ -0,0 +1,1636 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * IIO driver for PAC1934 Multi-Channel DC Power/Energy Monitor
4 *
5 * Copyright (C) 2017-2024 Microchip Technology Inc. and its subsidiaries
6 *
7 * Author: Bogdan Bolocan <bogdan.bolocan@microchip.com>
8 * Author: Victor Tudose
9 * Author: Marius Cristea <marius.cristea@microchip.com>
10 *
11 * Datasheet for PAC1931, PAC1932, PAC1933 and PAC1934 can be found here:
12 * https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/PAC1931-Family-Data-Sheet-DS20005850E.pdf
13 */
14
15#include <linux/acpi.h>
16#include <linux/bitfield.h>
17#include <linux/delay.h>
18#include <linux/device.h>
19#include <linux/i2c.h>
20#include <linux/iio/iio.h>
21#include <linux/iio/sysfs.h>
22#include <asm/unaligned.h>
23
24/*
25 * maximum accumulation time should be (17 * 60 * 1000) around 17 minutes@1024 sps
26 * till PAC1934 accumulation registers starts to saturate
27 */
28#define PAC1934_MAX_RFSH_LIMIT_MS 60000
29/* 50msec is the timeout for validity of the cached registers */
30#define PAC1934_MIN_POLLING_TIME_MS 50
31/*
32 * 1000usec is the minimum wait time for normal conversions when sample
33 * rate doesn't change
34 */
35#define PAC1934_MIN_UPDATE_WAIT_TIME_US 1000
36
37/* 32000mV */
38#define PAC1934_VOLTAGE_MILLIVOLTS_MAX 32000
39/* voltage bits resolution when set for unsigned values */
40#define PAC1934_VOLTAGE_U_RES 16
41/* voltage bits resolution when set for signed values */
42#define PAC1934_VOLTAGE_S_RES 15
43
44/*
45 * max signed value that can be stored on 32 bits and 8 digits fractional value
46 * (2^31 - 1) * 10^8 + 99999999
47 */
48#define PAC_193X_MAX_POWER_ACC 214748364799999999LL
49/*
50 * min signed value that can be stored on 32 bits and 8 digits fractional value
51 * -(2^31) * 10^8 - 99999999
52 */
53#define PAC_193X_MIN_POWER_ACC -214748364899999999LL
54
55#define PAC1934_MAX_NUM_CHANNELS 4
56
57#define PAC1934_MEAS_REG_LEN 76
58#define PAC1934_CTRL_REG_LEN 12
59
60#define PAC1934_DEFAULT_CHIP_SAMP_SPEED_HZ 1024
61
62/* I2C address map */
63#define PAC1934_REFRESH_REG_ADDR 0x00
64#define PAC1934_CTRL_REG_ADDR 0x01
65#define PAC1934_ACC_COUNT_REG_ADDR 0x02
66#define PAC1934_VPOWER_ACC_1_ADDR 0x03
67#define PAC1934_VPOWER_ACC_2_ADDR 0x04
68#define PAC1934_VPOWER_ACC_3_ADDR 0x05
69#define PAC1934_VPOWER_ACC_4_ADDR 0x06
70#define PAC1934_VBUS_1_ADDR 0x07
71#define PAC1934_VBUS_2_ADDR 0x08
72#define PAC1934_VBUS_3_ADDR 0x09
73#define PAC1934_VBUS_4_ADDR 0x0A
74#define PAC1934_VSENSE_1_ADDR 0x0B
75#define PAC1934_VSENSE_2_ADDR 0x0C
76#define PAC1934_VSENSE_3_ADDR 0x0D
77#define PAC1934_VSENSE_4_ADDR 0x0E
78#define PAC1934_VBUS_AVG_1_ADDR 0x0F
79#define PAC1934_VBUS_AVG_2_ADDR 0x10
80#define PAC1934_VBUS_AVG_3_ADDR 0x11
81#define PAC1934_VBUS_AVG_4_ADDR 0x12
82#define PAC1934_VSENSE_AVG_1_ADDR 0x13
83#define PAC1934_VSENSE_AVG_2_ADDR 0x14
84#define PAC1934_VSENSE_AVG_3_ADDR 0x15
85#define PAC1934_VSENSE_AVG_4_ADDR 0x16
86#define PAC1934_VPOWER_1_ADDR 0x17
87#define PAC1934_VPOWER_2_ADDR 0x18
88#define PAC1934_VPOWER_3_ADDR 0x19
89#define PAC1934_VPOWER_4_ADDR 0x1A
90#define PAC1934_REFRESH_V_REG_ADDR 0x1F
91#define PAC1934_CTRL_STAT_REGS_ADDR 0x1C
92#define PAC1934_PID_REG_ADDR 0xFD
93#define PAC1934_MID_REG_ADDR 0xFE
94#define PAC1934_RID_REG_ADDR 0xFF
95
96/* PRODUCT ID REGISTER + MANUFACTURER ID REGISTER + REVISION ID REGISTER */
97#define PAC1934_ID_REG_LEN 3
98#define PAC1934_PID_IDX 0
99#define PAC1934_MID_IDX 1
100#define PAC1934_RID_IDX 2
101
102#define PAC1934_ACPI_GET_NAMES_AND_MOHMS_VALS 1
103#define PAC1934_ACPI_GET_UOHMS_VALS 2
104#define PAC1934_ACPI_GET_BIPOLAR_SETTINGS 4
105#define PAC1934_ACPI_GET_SAMP 5
106
107#define PAC1934_SAMPLE_RATE_SHIFT 6
108
109#define PAC1934_VBUS_SENSE_REG_LEN 2
110#define PAC1934_ACC_REG_LEN 3
111#define PAC1934_VPOWER_REG_LEN 4
112#define PAC1934_VPOWER_ACC_REG_LEN 6
113#define PAC1934_MAX_REGISTER_LENGTH 6
114
115#define PAC1934_CUSTOM_ATTR_FOR_CHANNEL 1
116
117/*
118 * relative offsets when using multi-byte reads/writes even though these
119 * bytes are read one after the other, they are not at adjacent memory
120 * locations within the I2C memory map. The chip can skip some addresses
121 */
122#define PAC1934_CHANNEL_DIS_REG_OFF 0
123#define PAC1934_NEG_PWR_REG_OFF 1
124
125/*
126 * when reading/writing multiple bytes from offset PAC1934_CHANNEL_DIS_REG_OFF,
127 * the chip jumps over the 0x1E (REFRESH_G) and 0x1F (REFRESH_V) offsets
128 */
129#define PAC1934_SLOW_REG_OFF 2
130#define PAC1934_CTRL_ACT_REG_OFF 3
131#define PAC1934_CHANNEL_DIS_ACT_REG_OFF 4
132#define PAC1934_NEG_PWR_ACT_REG_OFF 5
133#define PAC1934_CTRL_LAT_REG_OFF 6
134#define PAC1934_CHANNEL_DIS_LAT_REG_OFF 7
135#define PAC1934_NEG_PWR_LAT_REG_OFF 8
136#define PAC1934_PID_REG_OFF 9
137#define PAC1934_MID_REG_OFF 10
138#define PAC1934_REV_REG_OFF 11
139#define PAC1934_CTRL_STATUS_INFO_LEN 12
140
141#define PAC1934_MID 0x5D
142#define PAC1931_PID 0x58
143#define PAC1932_PID 0x59
144#define PAC1933_PID 0x5A
145#define PAC1934_PID 0x5B
146
147/* Scale constant = (10^3 * 3.2 * 10^9 / 2^28) for mili Watt-second */
148#define PAC1934_SCALE_CONSTANT 11921
149
150#define PAC1934_MAX_VPOWER_RSHIFTED_BY_28B 11921
151#define PAC1934_MAX_VSENSE_RSHIFTED_BY_16B 1525
152
153#define PAC1934_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
154
155#define PAC1934_CRTL_SAMPLE_RATE_MASK GENMASK(7, 6)
156#define PAC1934_CHAN_SLEEP_MASK BIT(5)
157#define PAC1934_CHAN_SLEEP_SET BIT(5)
158#define PAC1934_CHAN_SINGLE_MASK BIT(4)
159#define PAC1934_CHAN_SINGLE_SHOT_SET BIT(4)
160#define PAC1934_CHAN_ALERT_MASK BIT(3)
161#define PAC1934_CHAN_ALERT_EN BIT(3)
162#define PAC1934_CHAN_ALERT_CC_MASK BIT(2)
163#define PAC1934_CHAN_ALERT_CC_EN BIT(2)
164#define PAC1934_CHAN_OVF_ALERT_MASK BIT(1)
165#define PAC1934_CHAN_OVF_ALERT_EN BIT(1)
166#define PAC1934_CHAN_OVF_MASK BIT(0)
167
168#define PAC1934_CHAN_DIS_CH1_OFF_MASK BIT(7)
169#define PAC1934_CHAN_DIS_CH2_OFF_MASK BIT(6)
170#define PAC1934_CHAN_DIS_CH3_OFF_MASK BIT(5)
171#define PAC1934_CHAN_DIS_CH4_OFF_MASK BIT(4)
172#define PAC1934_SMBUS_TIMEOUT_MASK BIT(3)
173#define PAC1934_SMBUS_BYTECOUNT_MASK BIT(2)
174#define PAC1934_SMBUS_NO_SKIP_MASK BIT(1)
175
176#define PAC1934_NEG_PWR_CH1_BIDI_MASK BIT(7)
177#define PAC1934_NEG_PWR_CH2_BIDI_MASK BIT(6)
178#define PAC1934_NEG_PWR_CH3_BIDI_MASK BIT(5)
179#define PAC1934_NEG_PWR_CH4_BIDI_MASK BIT(4)
180#define PAC1934_NEG_PWR_CH1_BIDV_MASK BIT(3)
181#define PAC1934_NEG_PWR_CH2_BIDV_MASK BIT(2)
182#define PAC1934_NEG_PWR_CH3_BIDV_MASK BIT(1)
183#define PAC1934_NEG_PWR_CH4_BIDV_MASK BIT(0)
184
185/*
186 * Universal Unique Identifier (UUID),
187 * 033771E0-1705-47B4-9535-D1BBE14D9A09,
188 * is reserved to Microchip for the PAC1934.
189 */
190#define PAC1934_DSM_UUID "033771E0-1705-47B4-9535-D1BBE14D9A09"
191
192enum pac1934_ids {
193 PAC1931,
194 PAC1932,
195 PAC1933,
196 PAC1934
197};
198
199enum pac1934_samps {
200 PAC1934_SAMP_1024SPS,
201 PAC1934_SAMP_256SPS,
202 PAC1934_SAMP_64SPS,
203 PAC1934_SAMP_8SPS
204};
205
206/*
207 * these indexes are exactly describing the element order within a single
208 * PAC1934 phys channel IIO channel descriptor; see the static const struct
209 * iio_chan_spec pac1934_single_channel[] declaration
210 */
211enum pac1934_ch_idx {
212 PAC1934_CH_ENERGY,
213 PAC1934_CH_POWER,
214 PAC1934_CH_VOLTAGE,
215 PAC1934_CH_CURRENT,
216 PAC1934_CH_VOLTAGE_AVERAGE,
217 PAC1934_CH_CURRENT_AVERAGE
218};
219
220/**
221 * struct pac1934_features - features of a pac1934 instance
222 * @phys_channels: number of physical channels supported by the chip
223 * @name: chip's name
224 */
225struct pac1934_features {
226 u8 phys_channels;
227 const char *name;
228};
229
230struct samp_rate_mapping {
231 u16 samp_rate;
232 u8 shift2value;
233};
234
235static const unsigned int samp_rate_map_tbl[] = {
236 [PAC1934_SAMP_1024SPS] = 1024,
237 [PAC1934_SAMP_256SPS] = 256,
238 [PAC1934_SAMP_64SPS] = 64,
239 [PAC1934_SAMP_8SPS] = 8,
240};
241
242static const struct pac1934_features pac1934_chip_config[] = {
243 [PAC1931] = {
244 .phys_channels = 1,
245 .name = "pac1931",
246 },
247 [PAC1932] = {
248 .phys_channels = 2,
249 .name = "pac1932",
250 },
251 [PAC1933] = {
252 .phys_channels = 3,
253 .name = "pac1933",
254 },
255 [PAC1934] = {
256 .phys_channels = 4,
257 .name = "pac1934",
258 },
259};
260
261/**
262 * struct reg_data - data from the registers
263 * @meas_regs: snapshot of raw measurements registers
264 * @ctrl_regs: snapshot of control registers
265 * @energy_sec_acc: snapshot of energy values
266 * @vpower_acc: accumulated vpower values
267 * @vpower: snapshot of vpower registers
268 * @vbus: snapshot of vbus registers
269 * @vbus_avg: averages of vbus registers
270 * @vsense: snapshot of vsense registers
271 * @vsense_avg: averages of vsense registers
272 * @num_enabled_channels: count of how many chip channels are currently enabled
273 */
274struct reg_data {
275 u8 meas_regs[PAC1934_MEAS_REG_LEN];
276 u8 ctrl_regs[PAC1934_CTRL_REG_LEN];
277 s64 energy_sec_acc[PAC1934_MAX_NUM_CHANNELS];
278 s64 vpower_acc[PAC1934_MAX_NUM_CHANNELS];
279 s32 vpower[PAC1934_MAX_NUM_CHANNELS];
280 s32 vbus[PAC1934_MAX_NUM_CHANNELS];
281 s32 vbus_avg[PAC1934_MAX_NUM_CHANNELS];
282 s32 vsense[PAC1934_MAX_NUM_CHANNELS];
283 s32 vsense_avg[PAC1934_MAX_NUM_CHANNELS];
284 u8 num_enabled_channels;
285};
286
287/**
288 * struct pac1934_chip_info - information about the chip
289 * @client: the i2c-client attached to the device
290 * @lock: synchronize access to driver's state members
291 * @work_chip_rfsh: work queue used for refresh commands
292 * @phys_channels: phys channels count
293 * @active_channels: array of values, true means that channel is active
294 * @enable_energy: array of values, true means that channel energy is measured
295 * @bi_dir: array of bools, true means that channel is bidirectional
296 * @chip_variant: chip variant
297 * @chip_revision: chip revision
298 * @shunts: shunts
299 * @chip_reg_data: chip reg data
300 * @sample_rate_value: sampling frequency
301 * @labels: table with channels labels
302 * @iio_info: iio_info
303 * @tstamp: chip's uptime
304 */
305struct pac1934_chip_info {
306 struct i2c_client *client;
307 struct mutex lock; /* synchronize access to driver's state members */
308 struct delayed_work work_chip_rfsh;
309 u8 phys_channels;
310 bool active_channels[PAC1934_MAX_NUM_CHANNELS];
311 bool enable_energy[PAC1934_MAX_NUM_CHANNELS];
312 bool bi_dir[PAC1934_MAX_NUM_CHANNELS];
313 u8 chip_variant;
314 u8 chip_revision;
315 u32 shunts[PAC1934_MAX_NUM_CHANNELS];
316 struct reg_data chip_reg_data;
317 s32 sample_rate_value;
318 char *labels[PAC1934_MAX_NUM_CHANNELS];
319 struct iio_info iio_info;
320 unsigned long tstamp;
321};
322
323#define TO_PAC1934_CHIP_INFO(d) container_of(d, struct pac1934_chip_info, work_chip_rfsh)
324
325#define PAC1934_VPOWER_ACC_CHANNEL(_index, _si, _address) { \
326 .type = IIO_ENERGY, \
327 .address = (_address), \
328 .indexed = 1, \
329 .channel = (_index), \
330 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
331 BIT(IIO_CHAN_INFO_SCALE) | \
332 BIT(IIO_CHAN_INFO_ENABLE), \
333 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
334 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
335 .scan_index = (_si), \
336 .scan_type = { \
337 .sign = 'u', \
338 .realbits = 48, \
339 .storagebits = 64, \
340 .endianness = IIO_CPU, \
341 } \
342}
343
344#define PAC1934_VBUS_CHANNEL(_index, _si, _address) { \
345 .type = IIO_VOLTAGE, \
346 .address = (_address), \
347 .indexed = 1, \
348 .channel = (_index), \
349 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
350 BIT(IIO_CHAN_INFO_SCALE), \
351 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
352 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
353 .scan_index = (_si), \
354 .scan_type = { \
355 .sign = 'u', \
356 .realbits = 16, \
357 .storagebits = 16, \
358 .endianness = IIO_CPU, \
359 } \
360}
361
362#define PAC1934_VBUS_AVG_CHANNEL(_index, _si, _address) { \
363 .type = IIO_VOLTAGE, \
364 .address = (_address), \
365 .indexed = 1, \
366 .channel = (_index), \
367 .info_mask_separate = BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \
368 BIT(IIO_CHAN_INFO_SCALE), \
369 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
370 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
371 .scan_index = (_si), \
372 .scan_type = { \
373 .sign = 'u', \
374 .realbits = 16, \
375 .storagebits = 16, \
376 .endianness = IIO_CPU, \
377 } \
378}
379
380#define PAC1934_VSENSE_CHANNEL(_index, _si, _address) { \
381 .type = IIO_CURRENT, \
382 .address = (_address), \
383 .indexed = 1, \
384 .channel = (_index), \
385 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
386 BIT(IIO_CHAN_INFO_SCALE), \
387 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
388 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
389 .scan_index = (_si), \
390 .scan_type = { \
391 .sign = 'u', \
392 .realbits = 16, \
393 .storagebits = 16, \
394 .endianness = IIO_CPU, \
395 } \
396}
397
398#define PAC1934_VSENSE_AVG_CHANNEL(_index, _si, _address) { \
399 .type = IIO_CURRENT, \
400 .address = (_address), \
401 .indexed = 1, \
402 .channel = (_index), \
403 .info_mask_separate = BIT(IIO_CHAN_INFO_AVERAGE_RAW) | \
404 BIT(IIO_CHAN_INFO_SCALE), \
405 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
406 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
407 .scan_index = (_si), \
408 .scan_type = { \
409 .sign = 'u', \
410 .realbits = 16, \
411 .storagebits = 16, \
412 .endianness = IIO_CPU, \
413 } \
414}
415
416#define PAC1934_VPOWER_CHANNEL(_index, _si, _address) { \
417 .type = IIO_POWER, \
418 .address = (_address), \
419 .indexed = 1, \
420 .channel = (_index), \
421 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
422 BIT(IIO_CHAN_INFO_SCALE), \
423 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
424 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
425 .scan_index = (_si), \
426 .scan_type = { \
427 .sign = 'u', \
428 .realbits = 28, \
429 .storagebits = 32, \
430 .shift = 4, \
431 .endianness = IIO_CPU, \
432 } \
433}
434
435static const struct iio_chan_spec pac1934_single_channel[] = {
436 PAC1934_VPOWER_ACC_CHANNEL(0, 0, PAC1934_VPOWER_ACC_1_ADDR),
437 PAC1934_VPOWER_CHANNEL(0, 0, PAC1934_VPOWER_1_ADDR),
438 PAC1934_VBUS_CHANNEL(0, 0, PAC1934_VBUS_1_ADDR),
439 PAC1934_VSENSE_CHANNEL(0, 0, PAC1934_VSENSE_1_ADDR),
440 PAC1934_VBUS_AVG_CHANNEL(0, 0, PAC1934_VBUS_AVG_1_ADDR),
441 PAC1934_VSENSE_AVG_CHANNEL(0, 0, PAC1934_VSENSE_AVG_1_ADDR),
442};
443
444/* Low-level I2c functions used to transfer up to 76 bytes at once */
445static int pac1934_i2c_read(struct i2c_client *client, u8 reg_addr,
446 void *databuf, u8 len)
447{
448 int ret;
449 struct i2c_msg msgs[2] = {
450 {
451 .addr = client->addr,
452 .len = 1,
453 .buf = (u8 *)&reg_addr,
454 },
455 {
456 .addr = client->addr,
457 .len = len,
458 .buf = databuf,
459 .flags = I2C_M_RD
460 }
461 };
462
463 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
464 if (ret < 0)
465 return ret;
466
467 return 0;
468}
469
470static int pac1934_get_samp_rate_idx(struct pac1934_chip_info *info,
471 u32 new_samp_rate)
472{
473 int cnt;
474
475 for (cnt = 0; cnt < ARRAY_SIZE(samp_rate_map_tbl); cnt++)
476 if (new_samp_rate == samp_rate_map_tbl[cnt])
477 return cnt;
478
479 /* not a valid sample rate value */
480 return -EINVAL;
481}
482
483static ssize_t pac1934_shunt_value_show(struct device *dev,
484 struct device_attribute *attr,
485 char *buf)
486{
487 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
488 struct pac1934_chip_info *info = iio_priv(indio_dev);
489 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
490
491 return sysfs_emit(buf, "%u\n", info->shunts[this_attr->address]);
492}
493
494static ssize_t pac1934_shunt_value_store(struct device *dev,
495 struct device_attribute *attr,
496 const char *buf, size_t count)
497{
498 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
499 struct pac1934_chip_info *info = iio_priv(indio_dev);
500 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
501 int sh_val;
502
503 if (kstrtouint(buf, 10, &sh_val)) {
504 dev_err(dev, "Shunt value is not valid\n");
505 return -EINVAL;
506 }
507
508 scoped_guard(mutex, &info->lock)
509 info->shunts[this_attr->address] = sh_val;
510
511 return count;
512}
513
514static int pac1934_read_avail(struct iio_dev *indio_dev,
515 struct iio_chan_spec const *channel,
516 const int **vals, int *type, int *length, long mask)
517{
518 switch (mask) {
519 case IIO_CHAN_INFO_SAMP_FREQ:
520 *type = IIO_VAL_INT;
521 *vals = samp_rate_map_tbl;
522 *length = ARRAY_SIZE(samp_rate_map_tbl);
523 return IIO_AVAIL_LIST;
524 }
525
526 return -EINVAL;
527}
528
529static int pac1934_send_refresh(struct pac1934_chip_info *info,
530 u8 refresh_cmd, u32 wait_time)
531{
532 /* this function only sends REFRESH or REFRESH_V */
533 struct i2c_client *client = info->client;
534 int ret;
535 u8 bidir_reg;
536 bool revision_bug = false;
537
538 if (info->chip_revision == 2 || info->chip_revision == 3) {
539 /*
540 * chip rev 2 and 3 bug workaround
541 * see: PAC1934 Family Data Sheet Errata DS80000836A.pdf
542 */
543 revision_bug = true;
544
545 bidir_reg =
546 FIELD_PREP(PAC1934_NEG_PWR_CH1_BIDI_MASK, info->bi_dir[0]) |
547 FIELD_PREP(PAC1934_NEG_PWR_CH2_BIDI_MASK, info->bi_dir[1]) |
548 FIELD_PREP(PAC1934_NEG_PWR_CH3_BIDI_MASK, info->bi_dir[2]) |
549 FIELD_PREP(PAC1934_NEG_PWR_CH4_BIDI_MASK, info->bi_dir[3]) |
550 FIELD_PREP(PAC1934_NEG_PWR_CH1_BIDV_MASK, info->bi_dir[0]) |
551 FIELD_PREP(PAC1934_NEG_PWR_CH2_BIDV_MASK, info->bi_dir[1]) |
552 FIELD_PREP(PAC1934_NEG_PWR_CH3_BIDV_MASK, info->bi_dir[2]) |
553 FIELD_PREP(PAC1934_NEG_PWR_CH4_BIDV_MASK, info->bi_dir[3]);
554
555 ret = i2c_smbus_write_byte_data(client,
556 PAC1934_CTRL_STAT_REGS_ADDR +
557 PAC1934_NEG_PWR_REG_OFF,
558 bidir_reg);
559 if (ret)
560 return ret;
561 }
562
563 ret = i2c_smbus_write_byte(client, refresh_cmd);
564 if (ret) {
565 dev_err(&client->dev, "%s - cannot send 0x%02X\n",
566 __func__, refresh_cmd);
567 return ret;
568 }
569
570 if (revision_bug) {
571 /*
572 * chip rev 2 and 3 bug workaround - write again the same
573 * register write the updated registers back
574 */
575 ret = i2c_smbus_write_byte_data(client,
576 PAC1934_CTRL_STAT_REGS_ADDR +
577 PAC1934_NEG_PWR_REG_OFF, bidir_reg);
578 if (ret)
579 return ret;
580 }
581
582 /* register data retrieval timestamp */
583 info->tstamp = jiffies;
584
585 /* wait till the data is available */
586 usleep_range(wait_time, wait_time + 100);
587
588 return ret;
589}
590
591static int pac1934_reg_snapshot(struct pac1934_chip_info *info,
592 bool do_refresh, u8 refresh_cmd, u32 wait_time)
593{
594 int ret;
595 struct i2c_client *client = info->client;
596 u8 samp_shift, ctrl_regs_tmp;
597 u8 *offset_reg_data_p;
598 u16 tmp_value;
599 u32 samp_rate, cnt, tmp;
600 s64 curr_energy, inc;
601 u64 tmp_energy;
602 struct reg_data *reg_data;
603
604 guard(mutex)(&info->lock);
605
606 if (do_refresh) {
607 ret = pac1934_send_refresh(info, refresh_cmd, wait_time);
608 if (ret < 0) {
609 dev_err(&client->dev,
610 "%s - cannot send refresh\n",
611 __func__);
612 return ret;
613 }
614 }
615
616 ret = i2c_smbus_read_i2c_block_data(client, PAC1934_CTRL_STAT_REGS_ADDR,
617 PAC1934_CTRL_REG_LEN,
618 (u8 *)info->chip_reg_data.ctrl_regs);
619 if (ret < 0) {
620 dev_err(&client->dev,
621 "%s - cannot read ctrl/status registers\n",
622 __func__);
623 return ret;
624 }
625
626 reg_data = &info->chip_reg_data;
627
628 /* read the data registers */
629 ret = pac1934_i2c_read(client, PAC1934_ACC_COUNT_REG_ADDR,
630 (u8 *)reg_data->meas_regs, PAC1934_MEAS_REG_LEN);
631 if (ret) {
632 dev_err(&client->dev,
633 "%s - cannot read ACC_COUNT register: %d:%d\n",
634 __func__, ret, PAC1934_MEAS_REG_LEN);
635 return ret;
636 }
637
638 /* see how much shift is required by the sample rate */
639 samp_rate = samp_rate_map_tbl[((reg_data->ctrl_regs[PAC1934_CTRL_LAT_REG_OFF]) >> 6)];
640 samp_shift = get_count_order(samp_rate);
641
642 ctrl_regs_tmp = reg_data->ctrl_regs[PAC1934_CHANNEL_DIS_LAT_REG_OFF];
643 offset_reg_data_p = &reg_data->meas_regs[PAC1934_ACC_REG_LEN];
644
645 /* start with VPOWER_ACC */
646 for (cnt = 0; cnt < info->phys_channels; cnt++) {
647 /* check if the channel is active, skip all fields if disabled */
648 if ((ctrl_regs_tmp << cnt) & 0x80)
649 continue;
650
651 /* skip if the energy accumulation is disabled */
652 if (info->enable_energy[cnt]) {
653 curr_energy = info->chip_reg_data.energy_sec_acc[cnt];
654
655 tmp_energy = get_unaligned_be48(offset_reg_data_p);
656
657 if (info->bi_dir[cnt])
658 reg_data->vpower_acc[cnt] = sign_extend64(tmp_energy, 47);
659 else
660 reg_data->vpower_acc[cnt] = tmp_energy;
661
662 /*
663 * compute the scaled to 1 second accumulated energy value;
664 * energy accumulator scaled to 1sec = VPOWER_ACC/2^samp_shift
665 * the chip's sampling rate is 2^samp_shift samples/sec
666 */
667 inc = (reg_data->vpower_acc[cnt] >> samp_shift);
668
669 /* add the power_acc field */
670 curr_energy += inc;
671
672 clamp(curr_energy, PAC_193X_MIN_POWER_ACC, PAC_193X_MAX_POWER_ACC);
673
674 reg_data->energy_sec_acc[cnt] = curr_energy;
675 }
676
677 offset_reg_data_p += PAC1934_VPOWER_ACC_REG_LEN;
678 }
679
680 /* continue with VBUS */
681 for (cnt = 0; cnt < info->phys_channels; cnt++) {
682 if ((ctrl_regs_tmp << cnt) & 0x80)
683 continue;
684
685 tmp_value = get_unaligned_be16(offset_reg_data_p);
686
687 if (info->bi_dir[cnt])
688 reg_data->vbus[cnt] = sign_extend32((u32)(tmp_value), 15);
689 else
690 reg_data->vbus[cnt] = tmp_value;
691
692 offset_reg_data_p += PAC1934_VBUS_SENSE_REG_LEN;
693 }
694
695 /* VSENSE */
696 for (cnt = 0; cnt < info->phys_channels; cnt++) {
697 if ((ctrl_regs_tmp << cnt) & 0x80)
698 continue;
699
700 tmp_value = get_unaligned_be16(offset_reg_data_p);
701
702 if (info->bi_dir[cnt])
703 reg_data->vsense[cnt] = sign_extend32((u32)(tmp_value), 15);
704 else
705 reg_data->vsense[cnt] = tmp_value;
706
707 offset_reg_data_p += PAC1934_VBUS_SENSE_REG_LEN;
708 }
709
710 /* VBUS_AVG */
711 for (cnt = 0; cnt < info->phys_channels; cnt++) {
712 if ((ctrl_regs_tmp << cnt) & 0x80)
713 continue;
714
715 tmp_value = get_unaligned_be16(offset_reg_data_p);
716
717 if (info->bi_dir[cnt])
718 reg_data->vbus_avg[cnt] = sign_extend32((u32)(tmp_value), 15);
719 else
720 reg_data->vbus_avg[cnt] = tmp_value;
721
722 offset_reg_data_p += PAC1934_VBUS_SENSE_REG_LEN;
723 }
724
725 /* VSENSE_AVG */
726 for (cnt = 0; cnt < info->phys_channels; cnt++) {
727 if ((ctrl_regs_tmp << cnt) & 0x80)
728 continue;
729
730 tmp_value = get_unaligned_be16(offset_reg_data_p);
731
732 if (info->bi_dir[cnt])
733 reg_data->vsense_avg[cnt] = sign_extend32((u32)(tmp_value), 15);
734 else
735 reg_data->vsense_avg[cnt] = tmp_value;
736
737 offset_reg_data_p += PAC1934_VBUS_SENSE_REG_LEN;
738 }
739
740 /* VPOWER */
741 for (cnt = 0; cnt < info->phys_channels; cnt++) {
742 if ((ctrl_regs_tmp << cnt) & 0x80)
743 continue;
744
745 tmp = get_unaligned_be32(offset_reg_data_p) >> 4;
746
747 if (info->bi_dir[cnt])
748 reg_data->vpower[cnt] = sign_extend32(tmp, 27);
749 else
750 reg_data->vpower[cnt] = tmp;
751
752 offset_reg_data_p += PAC1934_VPOWER_REG_LEN;
753 }
754
755 return 0;
756}
757
758static int pac1934_retrieve_data(struct pac1934_chip_info *info,
759 u32 wait_time)
760{
761 int ret = 0;
762
763 /*
764 * check if the minimal elapsed time has passed and if so,
765 * re-read the chip, otherwise the cached info is just fine
766 */
767 if (time_after(jiffies, info->tstamp + msecs_to_jiffies(PAC1934_MIN_POLLING_TIME_MS))) {
768 ret = pac1934_reg_snapshot(info, true, PAC1934_REFRESH_REG_ADDR,
769 wait_time);
770
771 /*
772 * Re-schedule the work for the read registers on timeout
773 * (to prevent chip registers saturation)
774 */
775 mod_delayed_work(system_wq, &info->work_chip_rfsh,
776 msecs_to_jiffies(PAC1934_MAX_RFSH_LIMIT_MS));
777 }
778
779 return ret;
780}
781
782static int pac1934_read_raw(struct iio_dev *indio_dev,
783 struct iio_chan_spec const *chan, int *val,
784 int *val2, long mask)
785{
786 struct pac1934_chip_info *info = iio_priv(indio_dev);
787 s64 curr_energy;
788 int ret, channel = chan->channel - 1;
789
790 ret = pac1934_retrieve_data(info, PAC1934_MIN_UPDATE_WAIT_TIME_US);
791 if (ret < 0)
792 return ret;
793
794 switch (mask) {
795 case IIO_CHAN_INFO_RAW:
796 switch (chan->type) {
797 case IIO_VOLTAGE:
798 *val = info->chip_reg_data.vbus[channel];
799 return IIO_VAL_INT;
800 case IIO_CURRENT:
801 *val = info->chip_reg_data.vsense[channel];
802 return IIO_VAL_INT;
803 case IIO_POWER:
804 *val = info->chip_reg_data.vpower[channel];
805 return IIO_VAL_INT;
806 case IIO_ENERGY:
807 curr_energy = info->chip_reg_data.energy_sec_acc[channel];
808 *val = (u32)curr_energy;
809 *val2 = (u32)(curr_energy >> 32);
810 return IIO_VAL_INT_64;
811 default:
812 return -EINVAL;
813 }
814 case IIO_CHAN_INFO_AVERAGE_RAW:
815 switch (chan->type) {
816 case IIO_VOLTAGE:
817 *val = info->chip_reg_data.vbus_avg[channel];
818 return IIO_VAL_INT;
819 case IIO_CURRENT:
820 *val = info->chip_reg_data.vsense_avg[channel];
821 return IIO_VAL_INT;
822 default:
823 return -EINVAL;
824 }
825 case IIO_CHAN_INFO_SCALE:
826 switch (chan->address) {
827 /* Voltages - scale for millivolts */
828 case PAC1934_VBUS_1_ADDR:
829 case PAC1934_VBUS_2_ADDR:
830 case PAC1934_VBUS_3_ADDR:
831 case PAC1934_VBUS_4_ADDR:
832 case PAC1934_VBUS_AVG_1_ADDR:
833 case PAC1934_VBUS_AVG_2_ADDR:
834 case PAC1934_VBUS_AVG_3_ADDR:
835 case PAC1934_VBUS_AVG_4_ADDR:
836 *val = PAC1934_VOLTAGE_MILLIVOLTS_MAX;
837 if (chan->scan_type.sign == 'u')
838 *val2 = PAC1934_VOLTAGE_U_RES;
839 else
840 *val2 = PAC1934_VOLTAGE_S_RES;
841 return IIO_VAL_FRACTIONAL_LOG2;
842 /*
843 * Currents - scale for mA - depends on the
844 * channel's shunt value
845 * (100mV * 1000000) / (2^16 * shunt(uohm))
846 */
847 case PAC1934_VSENSE_1_ADDR:
848 case PAC1934_VSENSE_2_ADDR:
849 case PAC1934_VSENSE_3_ADDR:
850 case PAC1934_VSENSE_4_ADDR:
851 case PAC1934_VSENSE_AVG_1_ADDR:
852 case PAC1934_VSENSE_AVG_2_ADDR:
853 case PAC1934_VSENSE_AVG_3_ADDR:
854 case PAC1934_VSENSE_AVG_4_ADDR:
855 *val = PAC1934_MAX_VSENSE_RSHIFTED_BY_16B;
856 if (chan->scan_type.sign == 'u')
857 *val2 = info->shunts[channel];
858 else
859 *val2 = info->shunts[channel] >> 1;
860 return IIO_VAL_FRACTIONAL;
861 /*
862 * Power - uW - it will use the combined scale
863 * for current and voltage
864 * current(mA) * voltage(mV) = power (uW)
865 */
866 case PAC1934_VPOWER_1_ADDR:
867 case PAC1934_VPOWER_2_ADDR:
868 case PAC1934_VPOWER_3_ADDR:
869 case PAC1934_VPOWER_4_ADDR:
870 *val = PAC1934_MAX_VPOWER_RSHIFTED_BY_28B;
871 if (chan->scan_type.sign == 'u')
872 *val2 = info->shunts[channel];
873 else
874 *val2 = info->shunts[channel] >> 1;
875 return IIO_VAL_FRACTIONAL;
876 case PAC1934_VPOWER_ACC_1_ADDR:
877 case PAC1934_VPOWER_ACC_2_ADDR:
878 case PAC1934_VPOWER_ACC_3_ADDR:
879 case PAC1934_VPOWER_ACC_4_ADDR:
880 /*
881 * expresses the 32 bit scale value here compute
882 * the scale for energy (miliWatt-second or miliJoule)
883 */
884 *val = PAC1934_SCALE_CONSTANT;
885
886 if (chan->scan_type.sign == 'u')
887 *val2 = info->shunts[channel];
888 else
889 *val2 = info->shunts[channel] >> 1;
890 return IIO_VAL_FRACTIONAL;
891 default:
892 return -EINVAL;
893 }
894 case IIO_CHAN_INFO_SAMP_FREQ:
895 *val = info->sample_rate_value;
896 return IIO_VAL_INT;
897 case IIO_CHAN_INFO_ENABLE:
898 *val = info->enable_energy[channel];
899 return IIO_VAL_INT;
900 default:
901 return -EINVAL;
902 }
903}
904
905static int pac1934_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
906 int val, int val2, long mask)
907{
908 struct pac1934_chip_info *info = iio_priv(indio_dev);
909 struct i2c_client *client = info->client;
910 int ret = -EINVAL;
911 s32 old_samp_rate;
912 u8 ctrl_reg;
913
914 switch (mask) {
915 case IIO_CHAN_INFO_SAMP_FREQ:
916 ret = pac1934_get_samp_rate_idx(info, val);
917 if (ret < 0)
918 return ret;
919
920 /* write the new sampling value and trigger a snapshot(incl refresh) */
921 scoped_guard(mutex, &info->lock) {
922 ctrl_reg = FIELD_PREP(PAC1934_CRTL_SAMPLE_RATE_MASK, ret);
923 ret = i2c_smbus_write_byte_data(client, PAC1934_CTRL_REG_ADDR, ctrl_reg);
924 if (ret) {
925 dev_err(&client->dev,
926 "%s - can't update sample rate\n",
927 __func__);
928 return ret;
929 }
930 }
931
932 old_samp_rate = info->sample_rate_value;
933 info->sample_rate_value = val;
934
935 /*
936 * now, force a snapshot with refresh - call retrieve
937 * data in order to update the refresh timer
938 * alter the timestamp in order to force trigger a
939 * register snapshot and a timestamp update
940 */
941 info->tstamp -= msecs_to_jiffies(PAC1934_MIN_POLLING_TIME_MS);
942 ret = pac1934_retrieve_data(info, (1024 / old_samp_rate) * 1000);
943 if (ret < 0) {
944 dev_err(&client->dev,
945 "%s - cannot snapshot ctrl and measurement regs\n",
946 __func__);
947 return ret;
948 }
949
950 return 0;
951 case IIO_CHAN_INFO_ENABLE:
952 scoped_guard(mutex, &info->lock) {
953 info->enable_energy[chan->channel - 1] = val ? true : false;
954 if (!val)
955 info->chip_reg_data.energy_sec_acc[chan->channel - 1] = 0;
956 }
957
958 return 0;
959 default:
960 return -EINVAL;
961 }
962}
963
964static int pac1934_read_label(struct iio_dev *indio_dev,
965 struct iio_chan_spec const *chan, char *label)
966{
967 struct pac1934_chip_info *info = iio_priv(indio_dev);
968
969 switch (chan->address) {
970 case PAC1934_VBUS_1_ADDR:
971 case PAC1934_VBUS_2_ADDR:
972 case PAC1934_VBUS_3_ADDR:
973 case PAC1934_VBUS_4_ADDR:
974 return sysfs_emit(label, "%s_VBUS_%d\n",
975 info->labels[chan->scan_index],
976 chan->scan_index + 1);
977 case PAC1934_VBUS_AVG_1_ADDR:
978 case PAC1934_VBUS_AVG_2_ADDR:
979 case PAC1934_VBUS_AVG_3_ADDR:
980 case PAC1934_VBUS_AVG_4_ADDR:
981 return sysfs_emit(label, "%s_VBUS_AVG_%d\n",
982 info->labels[chan->scan_index],
983 chan->scan_index + 1);
984 case PAC1934_VSENSE_1_ADDR:
985 case PAC1934_VSENSE_2_ADDR:
986 case PAC1934_VSENSE_3_ADDR:
987 case PAC1934_VSENSE_4_ADDR:
988 return sysfs_emit(label, "%s_IBUS_%d\n",
989 info->labels[chan->scan_index],
990 chan->scan_index + 1);
991 case PAC1934_VSENSE_AVG_1_ADDR:
992 case PAC1934_VSENSE_AVG_2_ADDR:
993 case PAC1934_VSENSE_AVG_3_ADDR:
994 case PAC1934_VSENSE_AVG_4_ADDR:
995 return sysfs_emit(label, "%s_IBUS_AVG_%d\n",
996 info->labels[chan->scan_index],
997 chan->scan_index + 1);
998 case PAC1934_VPOWER_1_ADDR:
999 case PAC1934_VPOWER_2_ADDR:
1000 case PAC1934_VPOWER_3_ADDR:
1001 case PAC1934_VPOWER_4_ADDR:
1002 return sysfs_emit(label, "%s_POWER_%d\n",
1003 info->labels[chan->scan_index],
1004 chan->scan_index + 1);
1005 case PAC1934_VPOWER_ACC_1_ADDR:
1006 case PAC1934_VPOWER_ACC_2_ADDR:
1007 case PAC1934_VPOWER_ACC_3_ADDR:
1008 case PAC1934_VPOWER_ACC_4_ADDR:
1009 return sysfs_emit(label, "%s_ENERGY_%d\n",
1010 info->labels[chan->scan_index],
1011 chan->scan_index + 1);
1012 }
1013
1014 return 0;
1015}
1016
1017static void pac1934_work_periodic_rfsh(struct work_struct *work)
1018{
1019 struct pac1934_chip_info *info = TO_PAC1934_CHIP_INFO((struct delayed_work *)work);
1020 struct device *dev = &info->client->dev;
1021
1022 dev_dbg(dev, "%s - Periodic refresh\n", __func__);
1023
1024 /* do a REFRESH, then read */
1025 pac1934_reg_snapshot(info, true, PAC1934_REFRESH_REG_ADDR,
1026 PAC1934_MIN_UPDATE_WAIT_TIME_US);
1027
1028 schedule_delayed_work(&info->work_chip_rfsh,
1029 msecs_to_jiffies(PAC1934_MAX_RFSH_LIMIT_MS));
1030}
1031
1032static int pac1934_read_revision(struct pac1934_chip_info *info, u8 *buf)
1033{
1034 int ret;
1035 struct i2c_client *client = info->client;
1036
1037 ret = i2c_smbus_read_i2c_block_data(client, PAC1934_PID_REG_ADDR,
1038 PAC1934_ID_REG_LEN,
1039 buf);
1040 if (ret < 0) {
1041 dev_err(&client->dev, "cannot read revision\n");
1042 return ret;
1043 }
1044
1045 return 0;
1046}
1047
1048static int pac1934_chip_identify(struct pac1934_chip_info *info)
1049{
1050 u8 rev_info[PAC1934_ID_REG_LEN];
1051 struct device *dev = &info->client->dev;
1052 int ret = 0;
1053
1054 ret = pac1934_read_revision(info, (u8 *)rev_info);
1055 if (ret)
1056 return ret;
1057
1058 info->chip_variant = rev_info[PAC1934_PID_IDX];
1059 info->chip_revision = rev_info[PAC1934_RID_IDX];
1060
1061 dev_dbg(dev, "Chip variant: 0x%02X\n", info->chip_variant);
1062 dev_dbg(dev, "Chip revision: 0x%02X\n", info->chip_revision);
1063
1064 switch (info->chip_variant) {
1065 case PAC1934_PID:
1066 return PAC1934;
1067 case PAC1933_PID:
1068 return PAC1933;
1069 case PAC1932_PID:
1070 return PAC1932;
1071 case PAC1931_PID:
1072 return PAC1931;
1073 default:
1074 return -EINVAL;
1075 }
1076}
1077
1078/*
1079 * documentation related to the ACPI device definition
1080 * https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ApplicationNotes/ApplicationNotes/PAC1934-Integration-Notes-for-Microsoft-Windows-10-and-Windows-11-Driver-Support-DS00002534.pdf
1081 */
1082static bool pac1934_acpi_parse_channel_config(struct i2c_client *client,
1083 struct pac1934_chip_info *info)
1084{
1085 acpi_handle handle;
1086 union acpi_object *rez;
1087 struct device *dev = &client->dev;
1088 unsigned short bi_dir_mask;
1089 int idx, i;
1090 guid_t guid;
1091
1092 handle = ACPI_HANDLE(dev);
1093
1094 guid_parse(PAC1934_DSM_UUID, &guid);
1095
1096 rez = acpi_evaluate_dsm(handle, &guid, 0, PAC1934_ACPI_GET_NAMES_AND_MOHMS_VALS, NULL);
1097 if (!rez)
1098 return false;
1099
1100 for (i = 0; i < rez->package.count; i += 2) {
1101 idx = i / 2;
1102 info->labels[idx] =
1103 devm_kmemdup(dev, rez->package.elements[i].string.pointer,
1104 (size_t)rez->package.elements[i].string.length + 1,
1105 GFP_KERNEL);
1106 info->labels[idx][rez->package.elements[i].string.length] = '\0';
1107 info->shunts[idx] = rez->package.elements[i + 1].integer.value * 1000;
1108 info->active_channels[idx] = (info->shunts[idx] != 0);
1109 }
1110
1111 ACPI_FREE(rez);
1112
1113 rez = acpi_evaluate_dsm(handle, &guid, 1, PAC1934_ACPI_GET_UOHMS_VALS, NULL);
1114 if (!rez) {
1115 /*
1116 * initializing with default values
1117 * we assume all channels are unidirectional(the mask is zero)
1118 * and assign the default sampling rate
1119 */
1120 info->sample_rate_value = PAC1934_DEFAULT_CHIP_SAMP_SPEED_HZ;
1121 return true;
1122 }
1123
1124 for (i = 0; i < rez->package.count; i++) {
1125 idx = i;
1126 info->shunts[idx] = rez->package.elements[i].integer.value;
1127 info->active_channels[idx] = (info->shunts[idx] != 0);
1128 }
1129
1130 ACPI_FREE(rez);
1131
1132 rez = acpi_evaluate_dsm(handle, &guid, 1, PAC1934_ACPI_GET_BIPOLAR_SETTINGS, NULL);
1133 if (!rez)
1134 return false;
1135
1136 bi_dir_mask = rez->package.elements[0].integer.value;
1137 info->bi_dir[0] = ((bi_dir_mask & (1 << 3)) | (bi_dir_mask & (1 << 7))) != 0;
1138 info->bi_dir[1] = ((bi_dir_mask & (1 << 2)) | (bi_dir_mask & (1 << 6))) != 0;
1139 info->bi_dir[2] = ((bi_dir_mask & (1 << 1)) | (bi_dir_mask & (1 << 5))) != 0;
1140 info->bi_dir[3] = ((bi_dir_mask & (1 << 0)) | (bi_dir_mask & (1 << 4))) != 0;
1141
1142 ACPI_FREE(rez);
1143
1144 rez = acpi_evaluate_dsm(handle, &guid, 1, PAC1934_ACPI_GET_SAMP, NULL);
1145 if (!rez)
1146 return false;
1147
1148 info->sample_rate_value = rez->package.elements[0].integer.value;
1149
1150 ACPI_FREE(rez);
1151
1152 return true;
1153}
1154
1155static bool pac1934_of_parse_channel_config(struct i2c_client *client,
1156 struct pac1934_chip_info *info)
1157{
1158 struct fwnode_handle *node, *fwnode;
1159 struct device *dev = &client->dev;
1160 unsigned int current_channel;
1161 int idx, ret;
1162
1163 info->sample_rate_value = 1024;
1164 current_channel = 1;
1165
1166 fwnode = dev_fwnode(dev);
1167 fwnode_for_each_available_child_node(fwnode, node) {
1168 ret = fwnode_property_read_u32(node, "reg", &idx);
1169 if (ret) {
1170 dev_err_probe(dev, ret,
1171 "reading invalid channel index\n");
1172 goto err_fwnode;
1173 }
1174 /* adjust idx to match channel index (1 to 4) from the datasheet */
1175 idx--;
1176
1177 if (current_channel >= (info->phys_channels + 1) ||
1178 idx >= info->phys_channels || idx < 0) {
1179 dev_err_probe(dev, -EINVAL,
1180 "%s: invalid channel_index %d value\n",
1181 fwnode_get_name(node), idx);
1182 goto err_fwnode;
1183 }
1184
1185 /* enable channel */
1186 info->active_channels[idx] = true;
1187
1188 ret = fwnode_property_read_u32(node, "shunt-resistor-micro-ohms",
1189 &info->shunts[idx]);
1190 if (ret) {
1191 dev_err_probe(dev, ret,
1192 "%s: invalid shunt-resistor value: %d\n",
1193 fwnode_get_name(node), info->shunts[idx]);
1194 goto err_fwnode;
1195 }
1196
1197 if (fwnode_property_present(node, "label")) {
1198 ret = fwnode_property_read_string(node, "label",
1199 (const char **)&info->labels[idx]);
1200 if (ret) {
1201 dev_err_probe(dev, ret,
1202 "%s: invalid rail-name value\n",
1203 fwnode_get_name(node));
1204 goto err_fwnode;
1205 }
1206 }
1207
1208 info->bi_dir[idx] = fwnode_property_read_bool(node, "bipolar");
1209
1210 current_channel++;
1211 }
1212
1213 return true;
1214
1215err_fwnode:
1216 fwnode_handle_put(node);
1217
1218 return false;
1219}
1220
1221static void pac1934_cancel_delayed_work(void *dwork)
1222{
1223 cancel_delayed_work_sync(dwork);
1224}
1225
1226static int pac1934_chip_configure(struct pac1934_chip_info *info)
1227{
1228 int cnt, ret;
1229 struct i2c_client *client = info->client;
1230 u8 regs[PAC1934_CTRL_STATUS_INFO_LEN], idx, ctrl_reg;
1231 u32 wait_time;
1232
1233 info->chip_reg_data.num_enabled_channels = 0;
1234 for (cnt = 0; cnt < info->phys_channels; cnt++) {
1235 if (info->active_channels[cnt])
1236 info->chip_reg_data.num_enabled_channels++;
1237 }
1238
1239 /*
1240 * read whatever information was gathered before the driver was loaded
1241 * establish which channels are enabled/disabled and then establish the
1242 * information retrieval mode (using SKIP or no).
1243 * Read the chip ID values
1244 */
1245 ret = i2c_smbus_read_i2c_block_data(client, PAC1934_CTRL_STAT_REGS_ADDR,
1246 ARRAY_SIZE(regs),
1247 (u8 *)regs);
1248 if (ret < 0) {
1249 dev_err_probe(&client->dev, ret,
1250 "%s - cannot read regs from 0x%02X\n",
1251 __func__, PAC1934_CTRL_STAT_REGS_ADDR);
1252 return ret;
1253 }
1254
1255 /* write the CHANNEL_DIS and the NEG_PWR registers */
1256 regs[PAC1934_CHANNEL_DIS_REG_OFF] =
1257 FIELD_PREP(PAC1934_CHAN_DIS_CH1_OFF_MASK, info->active_channels[0] ? 0 : 1) |
1258 FIELD_PREP(PAC1934_CHAN_DIS_CH2_OFF_MASK, info->active_channels[1] ? 0 : 1) |
1259 FIELD_PREP(PAC1934_CHAN_DIS_CH3_OFF_MASK, info->active_channels[2] ? 0 : 1) |
1260 FIELD_PREP(PAC1934_CHAN_DIS_CH4_OFF_MASK, info->active_channels[3] ? 0 : 1) |
1261 FIELD_PREP(PAC1934_SMBUS_TIMEOUT_MASK, 0) |
1262 FIELD_PREP(PAC1934_SMBUS_BYTECOUNT_MASK, 0) |
1263 FIELD_PREP(PAC1934_SMBUS_NO_SKIP_MASK, 0);
1264
1265 regs[PAC1934_NEG_PWR_REG_OFF] =
1266 FIELD_PREP(PAC1934_NEG_PWR_CH1_BIDI_MASK, info->bi_dir[0]) |
1267 FIELD_PREP(PAC1934_NEG_PWR_CH2_BIDI_MASK, info->bi_dir[1]) |
1268 FIELD_PREP(PAC1934_NEG_PWR_CH3_BIDI_MASK, info->bi_dir[2]) |
1269 FIELD_PREP(PAC1934_NEG_PWR_CH4_BIDI_MASK, info->bi_dir[3]) |
1270 FIELD_PREP(PAC1934_NEG_PWR_CH1_BIDV_MASK, info->bi_dir[0]) |
1271 FIELD_PREP(PAC1934_NEG_PWR_CH2_BIDV_MASK, info->bi_dir[1]) |
1272 FIELD_PREP(PAC1934_NEG_PWR_CH3_BIDV_MASK, info->bi_dir[2]) |
1273 FIELD_PREP(PAC1934_NEG_PWR_CH4_BIDV_MASK, info->bi_dir[3]);
1274
1275 /* no SLOW triggered REFRESH, clear POR */
1276 regs[PAC1934_SLOW_REG_OFF] = 0;
1277
1278 ret = i2c_smbus_write_block_data(client, PAC1934_CTRL_STAT_REGS_ADDR,
1279 ARRAY_SIZE(regs), (u8 *)regs);
1280 if (ret)
1281 return ret;
1282
1283 /* Default sampling rate */
1284 ctrl_reg = FIELD_PREP(PAC1934_CRTL_SAMPLE_RATE_MASK, PAC1934_SAMP_1024SPS);
1285
1286 ret = i2c_smbus_write_byte_data(client, PAC1934_CTRL_REG_ADDR, ctrl_reg);
1287 if (ret)
1288 return ret;
1289
1290 /*
1291 * send a REFRESH to the chip, so the new settings take place
1292 * as well as resetting the accumulators
1293 */
1294 ret = i2c_smbus_write_byte(client, PAC1934_REFRESH_REG_ADDR);
1295 if (ret) {
1296 dev_err(&client->dev,
1297 "%s - cannot send 0x%02X\n",
1298 __func__, PAC1934_REFRESH_REG_ADDR);
1299 return ret;
1300 }
1301
1302 /*
1303 * get the current(in the chip) sampling speed and compute the
1304 * required timeout based on its value
1305 * the timeout is 1/sampling_speed
1306 */
1307 idx = regs[PAC1934_CTRL_ACT_REG_OFF] >> PAC1934_SAMPLE_RATE_SHIFT;
1308 wait_time = (1024 / samp_rate_map_tbl[idx]) * 1000;
1309
1310 /*
1311 * wait the maximum amount of time to be on the safe side
1312 * the maximum wait time is for 8sps
1313 */
1314 usleep_range(wait_time, wait_time + 100);
1315
1316 INIT_DELAYED_WORK(&info->work_chip_rfsh, pac1934_work_periodic_rfsh);
1317 /* Setup the latest moment for reading the regs before saturation */
1318 schedule_delayed_work(&info->work_chip_rfsh,
1319 msecs_to_jiffies(PAC1934_MAX_RFSH_LIMIT_MS));
1320
1321 return devm_add_action_or_reset(&client->dev, pac1934_cancel_delayed_work,
1322 &info->work_chip_rfsh);
1323}
1324
1325static int pac1934_prep_iio_channels(struct pac1934_chip_info *info, struct iio_dev *indio_dev)
1326{
1327 struct iio_chan_spec *ch_sp;
1328 int channel_size, attribute_count, cnt;
1329 void *dyn_ch_struct, *tmp_data;
1330 struct device *dev = &info->client->dev;
1331
1332 /* find out dynamically how many IIO channels we need */
1333 attribute_count = 0;
1334 channel_size = 0;
1335 for (cnt = 0; cnt < info->phys_channels; cnt++) {
1336 if (!info->active_channels[cnt])
1337 continue;
1338
1339 /* add the size of the properties of one chip physical channel */
1340 channel_size += sizeof(pac1934_single_channel);
1341 /* count how many enabled channels we have */
1342 attribute_count += ARRAY_SIZE(pac1934_single_channel);
1343 dev_dbg(dev, ":%s: Channel %d active\n", __func__, cnt + 1);
1344 }
1345
1346 dyn_ch_struct = devm_kzalloc(dev, channel_size, GFP_KERNEL);
1347 if (!dyn_ch_struct)
1348 return -EINVAL;
1349
1350 tmp_data = dyn_ch_struct;
1351
1352 /* populate the dynamic channels and make all the adjustments */
1353 for (cnt = 0; cnt < info->phys_channels; cnt++) {
1354 if (!info->active_channels[cnt])
1355 continue;
1356
1357 memcpy(tmp_data, pac1934_single_channel, sizeof(pac1934_single_channel));
1358 ch_sp = (struct iio_chan_spec *)tmp_data;
1359 ch_sp[PAC1934_CH_ENERGY].channel = cnt + 1;
1360 ch_sp[PAC1934_CH_ENERGY].scan_index = cnt;
1361 ch_sp[PAC1934_CH_ENERGY].address = cnt + PAC1934_VPOWER_ACC_1_ADDR;
1362 ch_sp[PAC1934_CH_POWER].channel = cnt + 1;
1363 ch_sp[PAC1934_CH_POWER].scan_index = cnt;
1364 ch_sp[PAC1934_CH_POWER].address = cnt + PAC1934_VPOWER_1_ADDR;
1365 ch_sp[PAC1934_CH_VOLTAGE].channel = cnt + 1;
1366 ch_sp[PAC1934_CH_VOLTAGE].scan_index = cnt;
1367 ch_sp[PAC1934_CH_VOLTAGE].address = cnt + PAC1934_VBUS_1_ADDR;
1368 ch_sp[PAC1934_CH_CURRENT].channel = cnt + 1;
1369 ch_sp[PAC1934_CH_CURRENT].scan_index = cnt;
1370 ch_sp[PAC1934_CH_CURRENT].address = cnt + PAC1934_VSENSE_1_ADDR;
1371
1372 /*
1373 * In order to be able to use labels for PAC1934_CH_VOLTAGE, and
1374 * PAC1934_CH_VOLTAGE_AVERAGE,respectively PAC1934_CH_CURRENT
1375 * and PAC1934_CH_CURRENT_AVERAGE we need to use different
1376 * channel numbers. We will add +5 (+1 to maximum PAC channels).
1377 */
1378 ch_sp[PAC1934_CH_VOLTAGE_AVERAGE].channel = cnt + 5;
1379 ch_sp[PAC1934_CH_VOLTAGE_AVERAGE].scan_index = cnt;
1380 ch_sp[PAC1934_CH_VOLTAGE_AVERAGE].address = cnt + PAC1934_VBUS_AVG_1_ADDR;
1381 ch_sp[PAC1934_CH_CURRENT_AVERAGE].channel = cnt + 5;
1382 ch_sp[PAC1934_CH_CURRENT_AVERAGE].scan_index = cnt;
1383 ch_sp[PAC1934_CH_CURRENT_AVERAGE].address = cnt + PAC1934_VSENSE_AVG_1_ADDR;
1384
1385 /*
1386 * now modify the parameters in all channels if the
1387 * whole chip rail(channel) is bi-directional
1388 */
1389 if (info->bi_dir[cnt]) {
1390 ch_sp[PAC1934_CH_ENERGY].scan_type.sign = 's';
1391 ch_sp[PAC1934_CH_ENERGY].scan_type.realbits = 47;
1392 ch_sp[PAC1934_CH_POWER].scan_type.sign = 's';
1393 ch_sp[PAC1934_CH_POWER].scan_type.realbits = 27;
1394 ch_sp[PAC1934_CH_VOLTAGE].scan_type.sign = 's';
1395 ch_sp[PAC1934_CH_VOLTAGE].scan_type.realbits = 15;
1396 ch_sp[PAC1934_CH_CURRENT].scan_type.sign = 's';
1397 ch_sp[PAC1934_CH_CURRENT].scan_type.realbits = 15;
1398 ch_sp[PAC1934_CH_VOLTAGE_AVERAGE].scan_type.sign = 's';
1399 ch_sp[PAC1934_CH_VOLTAGE_AVERAGE].scan_type.realbits = 15;
1400 ch_sp[PAC1934_CH_CURRENT_AVERAGE].scan_type.sign = 's';
1401 ch_sp[PAC1934_CH_CURRENT_AVERAGE].scan_type.realbits = 15;
1402 }
1403 tmp_data += sizeof(pac1934_single_channel);
1404 }
1405
1406 /*
1407 * send the updated dynamic channel structure information towards IIO
1408 * prepare the required field for IIO class registration
1409 */
1410 indio_dev->num_channels = attribute_count;
1411 indio_dev->channels = (const struct iio_chan_spec *)dyn_ch_struct;
1412
1413 return 0;
1414}
1415
1416static IIO_DEVICE_ATTR(in_shunt_resistor1, 0644,
1417 pac1934_shunt_value_show, pac1934_shunt_value_store, 0);
1418static IIO_DEVICE_ATTR(in_shunt_resistor2, 0644,
1419 pac1934_shunt_value_show, pac1934_shunt_value_store, 1);
1420static IIO_DEVICE_ATTR(in_shunt_resistor3, 0644,
1421 pac1934_shunt_value_show, pac1934_shunt_value_store, 2);
1422static IIO_DEVICE_ATTR(in_shunt_resistor4, 0644,
1423 pac1934_shunt_value_show, pac1934_shunt_value_store, 3);
1424
1425static int pac1934_prep_custom_attributes(struct pac1934_chip_info *info,
1426 struct iio_dev *indio_dev)
1427{
1428 int i, active_channels_count = 0;
1429 struct attribute **pac1934_custom_attr;
1430 struct attribute_group *pac1934_group;
1431 struct device *dev = &info->client->dev;
1432
1433 for (i = 0 ; i < info->phys_channels; i++)
1434 if (info->active_channels[i])
1435 active_channels_count++;
1436
1437 pac1934_group = devm_kzalloc(dev, sizeof(*pac1934_group), GFP_KERNEL);
1438 if (!pac1934_group)
1439 return -ENOMEM;
1440
1441 pac1934_custom_attr = devm_kzalloc(dev,
1442 (PAC1934_CUSTOM_ATTR_FOR_CHANNEL *
1443 active_channels_count)
1444 * sizeof(*pac1934_group) + 1,
1445 GFP_KERNEL);
1446 if (!pac1934_custom_attr)
1447 return -ENOMEM;
1448
1449 i = 0;
1450 if (info->active_channels[0])
1451 pac1934_custom_attr[i++] = PAC1934_DEV_ATTR(in_shunt_resistor1);
1452
1453 if (info->active_channels[1])
1454 pac1934_custom_attr[i++] = PAC1934_DEV_ATTR(in_shunt_resistor2);
1455
1456 if (info->active_channels[2])
1457 pac1934_custom_attr[i++] = PAC1934_DEV_ATTR(in_shunt_resistor3);
1458
1459 if (info->active_channels[3])
1460 pac1934_custom_attr[i] = PAC1934_DEV_ATTR(in_shunt_resistor4);
1461
1462 pac1934_group->attrs = pac1934_custom_attr;
1463 info->iio_info.attrs = pac1934_group;
1464
1465 return 0;
1466}
1467
1468static void pac1934_mutex_destroy(void *data)
1469{
1470 struct mutex *lock = data;
1471
1472 mutex_destroy(lock);
1473}
1474
1475static const struct iio_info pac1934_info = {
1476 .read_raw = pac1934_read_raw,
1477 .write_raw = pac1934_write_raw,
1478 .read_avail = pac1934_read_avail,
1479 .read_label = pac1934_read_label,
1480};
1481
1482static int pac1934_probe(struct i2c_client *client)
1483{
1484 struct pac1934_chip_info *info;
1485 const struct pac1934_features *chip;
1486 struct iio_dev *indio_dev;
1487 int cnt, ret;
1488 bool match = false;
1489 struct device *dev = &client->dev;
1490
1491 indio_dev = devm_iio_device_alloc(dev, sizeof(*info));
1492 if (!indio_dev)
1493 return -ENOMEM;
1494
1495 info = iio_priv(indio_dev);
1496
1497 info->client = client;
1498
1499 /* always start with energy accumulation enabled */
1500 for (cnt = 0; cnt < PAC1934_MAX_NUM_CHANNELS; cnt++)
1501 info->enable_energy[cnt] = true;
1502
1503 ret = pac1934_chip_identify(info);
1504 if (ret < 0) {
1505 /*
1506 * If failed to identify the hardware based on internal
1507 * registers, try using fallback compatible in device tree
1508 * to deal with some newer part number.
1509 */
1510 chip = i2c_get_match_data(client);
1511 if (!chip)
1512 return -EINVAL;
1513
1514 info->phys_channels = chip->phys_channels;
1515 indio_dev->name = chip->name;
1516 } else {
1517 info->phys_channels = pac1934_chip_config[ret].phys_channels;
1518 indio_dev->name = pac1934_chip_config[ret].name;
1519 }
1520
1521 if (acpi_match_device(dev->driver->acpi_match_table, dev))
1522 match = pac1934_acpi_parse_channel_config(client, info);
1523 else
1524 /*
1525 * This makes it possible to use also ACPI PRP0001 for
1526 * registering the device using device tree properties.
1527 */
1528 match = pac1934_of_parse_channel_config(client, info);
1529
1530 if (!match)
1531 return dev_err_probe(dev, -EINVAL,
1532 "parameter parsing returned an error\n");
1533
1534 mutex_init(&info->lock);
1535 ret = devm_add_action_or_reset(dev, pac1934_mutex_destroy,
1536 &info->lock);
1537 if (ret < 0)
1538 return ret;
1539
1540 /*
1541 * do now any chip specific initialization (e.g. read/write
1542 * some registers), enable/disable certain channels, change the sampling
1543 * rate to the requested value
1544 */
1545 ret = pac1934_chip_configure(info);
1546 if (ret < 0)
1547 return ret;
1548
1549 /* prepare the channel information */
1550 ret = pac1934_prep_iio_channels(info, indio_dev);
1551 if (ret < 0)
1552 return ret;
1553
1554 info->iio_info = pac1934_info;
1555 indio_dev->info = &info->iio_info;
1556 indio_dev->modes = INDIO_DIRECT_MODE;
1557
1558 ret = pac1934_prep_custom_attributes(info, indio_dev);
1559 if (ret < 0)
1560 return dev_err_probe(dev, ret,
1561 "Can't configure custom attributes for PAC1934 device\n");
1562
1563 /*
1564 * read whatever has been accumulated in the chip so far
1565 * and reset the accumulators
1566 */
1567 ret = pac1934_reg_snapshot(info, true, PAC1934_REFRESH_REG_ADDR,
1568 PAC1934_MIN_UPDATE_WAIT_TIME_US);
1569 if (ret < 0)
1570 return ret;
1571
1572 ret = devm_iio_device_register(dev, indio_dev);
1573 if (ret < 0)
1574 return dev_err_probe(dev, ret,
1575 "Can't register IIO device\n");
1576
1577 return 0;
1578}
1579
1580static const struct i2c_device_id pac1934_id[] = {
1581 { .name = "pac1931", .driver_data = (kernel_ulong_t)&pac1934_chip_config[PAC1931] },
1582 { .name = "pac1932", .driver_data = (kernel_ulong_t)&pac1934_chip_config[PAC1932] },
1583 { .name = "pac1933", .driver_data = (kernel_ulong_t)&pac1934_chip_config[PAC1933] },
1584 { .name = "pac1934", .driver_data = (kernel_ulong_t)&pac1934_chip_config[PAC1934] },
1585 {}
1586};
1587MODULE_DEVICE_TABLE(i2c, pac1934_id);
1588
1589static const struct of_device_id pac1934_of_match[] = {
1590 {
1591 .compatible = "microchip,pac1931",
1592 .data = &pac1934_chip_config[PAC1931]
1593 },
1594 {
1595 .compatible = "microchip,pac1932",
1596 .data = &pac1934_chip_config[PAC1932]
1597 },
1598 {
1599 .compatible = "microchip,pac1933",
1600 .data = &pac1934_chip_config[PAC1933]
1601 },
1602 {
1603 .compatible = "microchip,pac1934",
1604 .data = &pac1934_chip_config[PAC1934]
1605 },
1606 {}
1607};
1608MODULE_DEVICE_TABLE(of, pac1934_of_match);
1609
1610/*
1611 * using MCHP1930 to be compatible with BIOS ACPI. See example:
1612 * https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ApplicationNotes/ApplicationNotes/PAC1934-Integration-Notes-for-Microsoft-Windows-10-and-Windows-11-Driver-Support-DS00002534.pdf
1613 */
1614static const struct acpi_device_id pac1934_acpi_match[] = {
1615 { "MCHP1930", .driver_data = (kernel_ulong_t)&pac1934_chip_config[PAC1934] },
1616 {}
1617};
1618MODULE_DEVICE_TABLE(acpi, pac1934_acpi_match);
1619
1620static struct i2c_driver pac1934_driver = {
1621 .driver = {
1622 .name = "pac1934",
1623 .of_match_table = pac1934_of_match,
1624 .acpi_match_table = pac1934_acpi_match
1625 },
1626 .probe = pac1934_probe,
1627 .id_table = pac1934_id,
1628};
1629
1630module_i2c_driver(pac1934_driver);
1631
1632MODULE_AUTHOR("Bogdan Bolocan <bogdan.bolocan@microchip.com>");
1633MODULE_AUTHOR("Victor Tudose");
1634MODULE_AUTHOR("Marius Cristea <marius.cristea@microchip.com>");
1635MODULE_DESCRIPTION("IIO driver for PAC1934 Multi-Channel DC Power/Energy Monitor");
1636MODULE_LICENSE("GPL");
drivers/iio/adc/qcom-pm8xxx-xoadc.c+0−1
@@ -372,7 +372,6 @@ static const struct xoadc_channel pm8921_xoadc_channels[] = { · 371 unmodified lines
372 * @name: name of this channel372 * @name: name of this channel
373 * @hwchan: pointer to hardware channel information (muxing & scaling settings)373 * @hwchan: pointer to hardware channel information (muxing & scaling settings)
374 * @calibration: whether to use absolute or ratiometric calibration374 * @calibration: whether to use absolute or ratiometric calibration
375 * @scale_fn_type: scaling function type
376 * @decimation: 0,1,2,3375 * @decimation: 0,1,2,3
377 * @amux_ip_rsv: ratiometric scale value if using ratiometric376 * @amux_ip_rsv: ratiometric scale value if using ratiometric
378 * calibration: 0, 1, 2, 4, 5.377 * calibration: 0, 1, 2, 4, 5.
drivers/iio/adc/rockchip_saradc.c+6−11
@@ -52,7 +52,7 @@ · 51 unmodified lines
52#define SARADC2_START BIT(4)52#define SARADC2_START BIT(4)
53#define SARADC2_SINGLE_MODE BIT(5)53#define SARADC2_SINGLE_MODE BIT(5)
54 54
55#define SARADC2_CONV_CHANNELS GENMASK(15, 0)55#define SARADC2_CONV_CHANNELS GENMASK(3, 0)
56 56
57struct rockchip_saradc;57struct rockchip_saradc;
58 58
@@ -102,12 +102,12 @@ static void rockchip_saradc_start_v2(struct rockchip_saradc *info, int chn) · 43 unmodified lines
102 writel_relaxed(0xc, info->regs + SARADC_T_DAS_SOC);102 writel_relaxed(0xc, info->regs + SARADC_T_DAS_SOC);
103 writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC);103 writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC);
104 val = FIELD_PREP(SARADC2_EN_END_INT, 1);104 val = FIELD_PREP(SARADC2_EN_END_INT, 1);
105 val |= val << 16;105 val |= SARADC2_EN_END_INT << 16;
106 writel_relaxed(val, info->regs + SARADC2_END_INT_EN);106 writel_relaxed(val, info->regs + SARADC2_END_INT_EN);
107 val = FIELD_PREP(SARADC2_START, 1) |107 val = FIELD_PREP(SARADC2_START, 1) |
108 FIELD_PREP(SARADC2_SINGLE_MODE, 1) |108 FIELD_PREP(SARADC2_SINGLE_MODE, 1) |
109 FIELD_PREP(SARADC2_CONV_CHANNELS, chn);109 FIELD_PREP(SARADC2_CONV_CHANNELS, chn);
110 val |= val << 16;110 val |= (SARADC2_START | SARADC2_SINGLE_MODE | SARADC2_CONV_CHANNELS) << 16;
111 writel(val, info->regs + SARADC2_CONV_CON);111 writel(val, info->regs + SARADC2_CONV_CON);
112}112}
113 113
@@ -450,16 +450,11 @@ static int rockchip_saradc_probe(struct platform_device *pdev) · 336 unmodified lines
450 * The reset should be an optional property, as it should work450 * The reset should be an optional property, as it should work
451 * with old devicetrees as well451 * with old devicetrees as well
452 */452 */
453 info->reset = devm_reset_control_get_exclusive(&pdev->dev,453 info->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
454 "saradc-apb");454 "saradc-apb");
455 if (IS_ERR(info->reset)) {455 if (IS_ERR(info->reset)) {
456 ret = PTR_ERR(info->reset);456 ret = PTR_ERR(info->reset);
457 if (ret != -ENOENT)457 return dev_err_probe(&pdev->dev, ret, "failed to get saradc-apb\n");
458 return dev_err_probe(&pdev->dev, ret,
459 "failed to get saradc-apb\n");
460
461 dev_dbg(&pdev->dev, "no reset control found\n");
462 info->reset = NULL;
463 }458 }
464 459
465 init_completion(&info->completion);460 init_completion(&info->completion);
drivers/iio/adc/rtq6056.c+255−20
@@ -39,6 +39,10 @@ · 38 unmodified lines
39#define RTQ6056_DEFAULT_CONFIG 0x412739#define RTQ6056_DEFAULT_CONFIG 0x4127
40#define RTQ6056_CONT_ALLON 740#define RTQ6056_CONT_ALLON 7
41 41
42#define RTQ6059_DEFAULT_CONFIG 0x3C47
43#define RTQ6059_VBUS_LSB_OFFSET 3
44#define RTQ6059_AVG_BASE 8
45
42enum {46enum {
43 RTQ6056_CH_VSHUNT = 0,47 RTQ6056_CH_VSHUNT = 0,
44 RTQ6056_CH_VBUS,48 RTQ6056_CH_VBUS,
@@ -47,19 +51,46 @@ enum { · 2 unmodified lines
47 RTQ6056_MAX_CHANNEL51 RTQ6056_MAX_CHANNEL
48};52};
49 53
54/*
55 * The enum is to present the 0x00 CONFIG RG bitfield for the 16bit RG value
56 * field value order from LSB to MSB
57 * RTQ6053/6 is OPMODE->VSHUNTCT->VBUSCT->AVG->RESET
58 * RTQ6059 is OPMODE->SADC->BADC->PGA->RESET
59 */
50enum {60enum {
51 F_OPMODE = 0,61 F_OPMODE = 0,
52 F_VSHUNTCT,62 F_VSHUNTCT,
63 F_RTQ6059_SADC = F_VSHUNTCT,
53 F_VBUSCT,64 F_VBUSCT,
65 F_RTQ6059_BADC = F_VBUSCT,
54 F_AVG,66 F_AVG,
67 F_RTQ6059_PGA = F_AVG,
55 F_RESET,68 F_RESET,
56 F_MAX_FIELDS69 F_MAX_FIELDS
57};70};
58 71
72struct rtq6056_priv;
73
74struct richtek_dev_data {
75 bool fixed_samp_freq;
76 u8 vbus_offset;
77 int default_conv_time_us;
78 unsigned int default_config;
79 unsigned int calib_coefficient;
80 const int *avg_sample_list;
81 int avg_sample_list_length;
82 const struct reg_field *reg_fields;
83 const struct iio_chan_spec *channels;
84 int num_channels;
85 int (*read_scale)(struct iio_chan_spec const *ch, int *val, int *val2);
86 int (*set_average)(struct rtq6056_priv *priv, int val);
87};
88
59struct rtq6056_priv {89struct rtq6056_priv {
60 struct device *dev;90 struct device *dev;
61 struct regmap *regmap;91 struct regmap *regmap;
62 struct regmap_field *rm_fields[F_MAX_FIELDS];92 struct regmap_field *rm_fields[F_MAX_FIELDS];
93 const struct richtek_dev_data *devdata;
63 u32 shunt_resistor_uohm;94 u32 shunt_resistor_uohm;
64 int vshuntct_us;95 int vshuntct_us;
65 int vbusct_us;96 int vbusct_us;
@@ -74,6 +105,14 @@ static const struct reg_field rtq6056_reg_fields[F_MAX_FIELDS] = { · 8 unmodified lines
74 [F_RESET] = REG_FIELD(RTQ6056_REG_CONFIG, 15, 15),105 [F_RESET] = REG_FIELD(RTQ6056_REG_CONFIG, 15, 15),
75};106};
76 107
108static const struct reg_field rtq6059_reg_fields[F_MAX_FIELDS] = {
109 [F_OPMODE] = REG_FIELD(RTQ6056_REG_CONFIG, 0, 2),
110 [F_RTQ6059_SADC] = REG_FIELD(RTQ6056_REG_CONFIG, 3, 6),
111 [F_RTQ6059_BADC] = REG_FIELD(RTQ6056_REG_CONFIG, 7, 10),
112 [F_RTQ6059_PGA] = REG_FIELD(RTQ6056_REG_CONFIG, 11, 12),
113 [F_RESET] = REG_FIELD(RTQ6056_REG_CONFIG, 15, 15),
114};
115
77static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1] = {116static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1] = {
78 {117 {
79 .type = IIO_VOLTAGE,118 .type = IIO_VOLTAGE,
@@ -151,10 +190,93 @@ static const struct iio_chan_spec rtq6056_channels[RTQ6056_MAX_CHANNEL + 1] = { · 71 unmodified lines
151 IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL),190 IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL),
152};191};
153 192
193/*
194 * Difference between RTQ6056 and RTQ6059
195 * - Fixed sampling conversion time
196 * - Average sample numbers
197 * - Channel scale
198 * - calibration coefficient
199 */
200static const struct iio_chan_spec rtq6059_channels[RTQ6056_MAX_CHANNEL + 1] = {
201 {
202 .type = IIO_VOLTAGE,
203 .indexed = 1,
204 .channel = 0,
205 .address = RTQ6056_REG_SHUNTVOLT,
206 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
207 BIT(IIO_CHAN_INFO_SCALE) |
208 BIT(IIO_CHAN_INFO_SAMP_FREQ),
209 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
210 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
211 .scan_index = 0,
212 .scan_type = {
213 .sign = 's',
214 .realbits = 16,
215 .storagebits = 16,
216 .endianness = IIO_CPU,
217 },
218 },
219 {
220 .type = IIO_VOLTAGE,
221 .indexed = 1,
222 .channel = 1,
223 .address = RTQ6056_REG_BUSVOLT,
224 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
225 BIT(IIO_CHAN_INFO_SCALE) |
226 BIT(IIO_CHAN_INFO_SAMP_FREQ),
227 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
228 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
229 .scan_index = 1,
230 .scan_type = {
231 .sign = 'u',
232 .realbits = 16,
233 .storagebits = 16,
234 .endianness = IIO_CPU,
235 },
236 },
237 {
238 .type = IIO_POWER,
239 .indexed = 1,
240 .channel = 2,
241 .address = RTQ6056_REG_POWER,
242 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
243 BIT(IIO_CHAN_INFO_SCALE) |
244 BIT(IIO_CHAN_INFO_SAMP_FREQ),
245 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
246 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
247 .scan_index = 2,
248 .scan_type = {
249 .sign = 'u',
250 .realbits = 16,
251 .storagebits = 16,
252 .endianness = IIO_CPU,
253 },
254 },
255 {
256 .type = IIO_CURRENT,
257 .indexed = 1,
258 .channel = 3,
259 .address = RTQ6056_REG_CURRENT,
260 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
261 BIT(IIO_CHAN_INFO_SAMP_FREQ),
262 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
263 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
264 .scan_index = 3,
265 .scan_type = {
266 .sign = 's',
267 .realbits = 16,
268 .storagebits = 16,
269 .endianness = IIO_CPU,
270 },
271 },
272 IIO_CHAN_SOFT_TIMESTAMP(RTQ6056_MAX_CHANNEL),
273};
274
154static int rtq6056_adc_read_channel(struct rtq6056_priv *priv,275static int rtq6056_adc_read_channel(struct rtq6056_priv *priv,
155 struct iio_chan_spec const *ch,276 struct iio_chan_spec const *ch,
156 int *val)277 int *val)
157{278{
279 const struct richtek_dev_data *devdata = priv->devdata;
158 struct device *dev = priv->dev;280 struct device *dev = priv->dev;
159 unsigned int addr = ch->address;281 unsigned int addr = ch->address;
160 unsigned int regval;282 unsigned int regval;
@@ -168,12 +290,21 @@ static int rtq6056_adc_read_channel(struct rtq6056_priv *priv, · 7 unmodified lines
168 return ret;290 return ret;
169 291
170 /* Power and VBUS is unsigned 16-bit, others are signed 16-bit */292 /* Power and VBUS is unsigned 16-bit, others are signed 16-bit */
171 if (addr == RTQ6056_REG_BUSVOLT || addr == RTQ6056_REG_POWER)293 switch (addr) {
294 case RTQ6056_REG_BUSVOLT:
295 regval >>= devdata->vbus_offset;
172 *val = regval;296 *val = regval;
173 else297 return IIO_VAL_INT;
298 case RTQ6056_REG_POWER:
299 *val = regval;
300 return IIO_VAL_INT;
301 case RTQ6056_REG_SHUNTVOLT:
302 case RTQ6056_REG_CURRENT:
174 *val = sign_extend32(regval, 16);303 *val = sign_extend32(regval, 16);
175 304 return IIO_VAL_INT;
176 return IIO_VAL_INT;305 default:
306 return -EINVAL;
307 }
177}308}
178 309
179static int rtq6056_adc_read_scale(struct iio_chan_spec const *ch, int *val,310static int rtq6056_adc_read_scale(struct iio_chan_spec const *ch, int *val,
@@ -199,6 +330,28 @@ static int rtq6056_adc_read_scale(struct iio_chan_spec const *ch, int *val, · 19 unmodified lines
199 }330 }
200}331}
201 332
333static int rtq6059_adc_read_scale(struct iio_chan_spec const *ch, int *val,
334 int *val2)
335{
336 switch (ch->address) {
337 case RTQ6056_REG_SHUNTVOLT:
338 /* VSHUNT lsb 10uV */
339 *val = 10000;
340 *val2 = 1000000;
341 return IIO_VAL_FRACTIONAL;
342 case RTQ6056_REG_BUSVOLT:
343 /* VBUS lsb 4mV */
344 *val = 4;
345 return IIO_VAL_INT;
346 case RTQ6056_REG_POWER:
347 /* Power lsb 20mW */
348 *val = 20;
349 return IIO_VAL_INT;
350 default:
351 return -EINVAL;
352 }
353}
354
202/*355/*
203 * Sample frequency for channel VSHUNT and VBUS. The indices correspond356 * Sample frequency for channel VSHUNT and VBUS. The indices correspond
204 * with the bit value expected by the chip. And it can be found at357 * with the bit value expected by the chip. And it can be found at
@@ -248,6 +401,10 @@ static const int rtq6056_avg_sample_list[] = { · 43 unmodified lines
248 1, 4, 16, 64, 128, 256, 512, 1024,401 1, 4, 16, 64, 128, 256, 512, 1024,
249};402};
250 403
404static const int rtq6059_avg_sample_list[] = {
405 1, 2, 4, 8, 16, 32, 64, 128,
406};
407
251static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val)408static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val)
252{409{
253 unsigned int selector;410 unsigned int selector;
@@ -268,6 +425,30 @@ static int rtq6056_adc_set_average(struct rtq6056_priv *priv, int val) · 14 unmodified lines
268 return 0;425 return 0;
269}426}
270 427
428static int rtq6059_adc_set_average(struct rtq6056_priv *priv, int val)
429{
430 unsigned int selector;
431 int ret;
432
433 if (val > 128 || val < 1)
434 return -EINVAL;
435
436 /* The supported average sample is 2^x (x from 0 to 7) */
437 selector = fls(val) - 1;
438
439 ret = regmap_field_write(priv->rm_fields[F_RTQ6059_BADC],
440 RTQ6059_AVG_BASE + selector);
441 if (ret)
442 return ret;
443
444 ret = regmap_field_write(priv->rm_fields[F_RTQ6059_SADC],
445 RTQ6059_AVG_BASE + selector);
446
447 priv->avg_sample = BIT(selector);
448
449 return 0;
450}
451
271static int rtq6056_adc_get_sample_freq(struct rtq6056_priv *priv,452static int rtq6056_adc_get_sample_freq(struct rtq6056_priv *priv,
272 struct iio_chan_spec const *ch, int *val)453 struct iio_chan_spec const *ch, int *val)
273{454{
@@ -292,12 +473,13 @@ static int rtq6056_adc_read_raw(struct iio_dev *indio_dev, · 18 unmodified lines
292 int *val2, long mask)473 int *val2, long mask)
293{474{
294 struct rtq6056_priv *priv = iio_priv(indio_dev);475 struct rtq6056_priv *priv = iio_priv(indio_dev);
476 const struct richtek_dev_data *devdata = priv->devdata;
295 477
296 switch (mask) {478 switch (mask) {
297 case IIO_CHAN_INFO_RAW:479 case IIO_CHAN_INFO_RAW:
298 return rtq6056_adc_read_channel(priv, chan, val);480 return rtq6056_adc_read_channel(priv, chan, val);
299 case IIO_CHAN_INFO_SCALE:481 case IIO_CHAN_INFO_SCALE:
300 return rtq6056_adc_read_scale(chan, val, val2);482 return devdata->read_scale(chan, val, val2);
301 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:483 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
302 *val = priv->avg_sample;484 *val = priv->avg_sample;
303 return IIO_VAL_INT;485 return IIO_VAL_INT;
@@ -313,6 +495,9 @@ static int rtq6056_adc_read_avail(struct iio_dev *indio_dev, · 9 unmodified lines
313 const int **vals, int *type, int *length,495 const int **vals, int *type, int *length,
314 long mask)496 long mask)
315{497{
498 struct rtq6056_priv *priv = iio_priv(indio_dev);
499 const struct richtek_dev_data *devdata = priv->devdata;
500
316 switch (mask) {501 switch (mask) {
317 case IIO_CHAN_INFO_SAMP_FREQ:502 case IIO_CHAN_INFO_SAMP_FREQ:
318 *vals = rtq6056_samp_freq_list;503 *vals = rtq6056_samp_freq_list;
@@ -320,9 +505,9 @@ static int rtq6056_adc_read_avail(struct iio_dev *indio_dev, · 1 unmodified line
320 *length = ARRAY_SIZE(rtq6056_samp_freq_list);505 *length = ARRAY_SIZE(rtq6056_samp_freq_list);
321 return IIO_AVAIL_LIST;506 return IIO_AVAIL_LIST;
322 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:507 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
323 *vals = rtq6056_avg_sample_list;508 *vals = devdata->avg_sample_list;
509 *length = devdata->avg_sample_list_length;
324 *type = IIO_VAL_INT;510 *type = IIO_VAL_INT;
325 *length = ARRAY_SIZE(rtq6056_avg_sample_list);
326 return IIO_AVAIL_LIST;511 return IIO_AVAIL_LIST;
327 default:512 default:
328 return -EINVAL;513 return -EINVAL;
@@ -334,6 +519,7 @@ static int rtq6056_adc_write_raw(struct iio_dev *indio_dev, · 5 unmodified lines
334 int val2, long mask)519 int val2, long mask)
335{520{
336 struct rtq6056_priv *priv = iio_priv(indio_dev);521 struct rtq6056_priv *priv = iio_priv(indio_dev);
522 const struct richtek_dev_data *devdata = priv->devdata;
337 int ret;523 int ret;
338 524
339 ret = iio_device_claim_direct_mode(indio_dev);525 ret = iio_device_claim_direct_mode(indio_dev);
@@ -342,10 +528,15 @@ static int rtq6056_adc_write_raw(struct iio_dev *indio_dev, · 2 unmodified lines
342 528
343 switch (mask) {529 switch (mask) {
344 case IIO_CHAN_INFO_SAMP_FREQ:530 case IIO_CHAN_INFO_SAMP_FREQ:
531 if (devdata->fixed_samp_freq) {
532 ret = -EINVAL;
533 break;
534 }
535
345 ret = rtq6056_adc_set_samp_freq(priv, chan, val);536 ret = rtq6056_adc_set_samp_freq(priv, chan, val);
346 break;537 break;
347 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:538 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
348 ret = rtq6056_adc_set_average(priv, val);539 ret = devdata->set_average(priv, val);
349 break;540 break;
350 default:541 default:
351 ret = -EINVAL;542 ret = -EINVAL;
@@ -374,6 +565,7 @@ static int rtq6056_adc_read_label(struct iio_dev *indio_dev, · 22 unmodified lines
374static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv,565static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv,
375 int resistor_uohm)566 int resistor_uohm)
376{567{
568 const struct richtek_dev_data *devdata = priv->devdata;
377 unsigned int calib_val;569 unsigned int calib_val;
378 int ret;570 int ret;
379 571
@@ -382,8 +574,8 @@ static int rtq6056_set_shunt_resistor(struct rtq6056_priv *priv, · 2 unmodified lines
382 return -EINVAL;574 return -EINVAL;
383 }575 }
384 576
385 /* calibration = 5120000 / (Rshunt (uOhm) * current lsb (1mA)) */577 /* calibration = coefficient / (Rshunt (uOhm) * current lsb (1mA)) */
386 calib_val = 5120000 / resistor_uohm;578 calib_val = devdata->calib_coefficient / resistor_uohm;
387 ret = regmap_write(priv->regmap, RTQ6056_REG_CALIBRATION, calib_val);579 ret = regmap_write(priv->regmap, RTQ6056_REG_CALIBRATION, calib_val);
388 if (ret)580 if (ret)
389 return ret;581 return ret;
@@ -450,6 +642,7 @@ static irqreturn_t rtq6056_buffer_trigger_handler(int irq, void *p) · 60 unmodified lines
450 struct iio_poll_func *pf = p;642 struct iio_poll_func *pf = p;
451 struct iio_dev *indio_dev = pf->indio_dev;643 struct iio_dev *indio_dev = pf->indio_dev;
452 struct rtq6056_priv *priv = iio_priv(indio_dev);644 struct rtq6056_priv *priv = iio_priv(indio_dev);
645 const struct richtek_dev_data *devdata = priv->devdata;
453 struct device *dev = priv->dev;646 struct device *dev = priv->dev;
454 struct {647 struct {
455 u16 vals[RTQ6056_MAX_CHANNEL];648 u16 vals[RTQ6056_MAX_CHANNEL];
@@ -469,6 +662,9 @@ static irqreturn_t rtq6056_buffer_trigger_handler(int irq, void *p) · 13 unmodified lines
469 if (ret)662 if (ret)
470 goto out;663 goto out;
471 664
665 if (addr == RTQ6056_REG_BUSVOLT)
666 raw >>= devdata->vbus_offset;
667
472 data.vals[i++] = raw;668 data.vals[i++] = raw;
473 }669 }
474 670
@@ -528,20 +724,26 @@ static int rtq6056_probe(struct i2c_client *i2c) · 53 unmodified lines
528 struct rtq6056_priv *priv;724 struct rtq6056_priv *priv;
529 struct device *dev = &i2c->dev;725 struct device *dev = &i2c->dev;
530 struct regmap *regmap;726 struct regmap *regmap;
727 const struct richtek_dev_data *devdata;
531 unsigned int vendor_id, shunt_resistor_uohm;728 unsigned int vendor_id, shunt_resistor_uohm;
532 int ret;729 int ret;
533 730
534 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA))731 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_WORD_DATA))
535 return -EOPNOTSUPP;732 return -EOPNOTSUPP;
536 733
734 devdata = device_get_match_data(dev);
735 if (!devdata)
736 return dev_err_probe(dev, -EINVAL, "Invalid dev data\n");
737
537 indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));738 indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
538 if (!indio_dev)739 if (!indio_dev)
539 return -ENOMEM;740 return -ENOMEM;
540 741
541 priv = iio_priv(indio_dev);742 priv = iio_priv(indio_dev);
542 priv->dev = dev;743 priv->dev = dev;
543 priv->vshuntct_us = priv->vbusct_us = 1037;744 priv->vshuntct_us = priv->vbusct_us = devdata->default_conv_time_us;
544 priv->avg_sample = 1;745 priv->avg_sample = 1;
746 priv->devdata = devdata;
545 i2c_set_clientdata(i2c, priv);747 i2c_set_clientdata(i2c, priv);
546 748
547 regmap = devm_regmap_init_i2c(i2c, &rtq6056_regmap_config);749 regmap = devm_regmap_init_i2c(i2c, &rtq6056_regmap_config);
@@ -561,15 +763,11 @@ static int rtq6056_probe(struct i2c_client *i2c) · 13 unmodified lines
561 "Invalid vendor id 0x%04x\n", vendor_id);763 "Invalid vendor id 0x%04x\n", vendor_id);
562 764
563 ret = devm_regmap_field_bulk_alloc(dev, regmap, priv->rm_fields,765 ret = devm_regmap_field_bulk_alloc(dev, regmap, priv->rm_fields,
564 rtq6056_reg_fields, F_MAX_FIELDS);766 devdata->reg_fields, F_MAX_FIELDS);
565 if (ret)767 if (ret)
566 return dev_err_probe(dev, ret, "Failed to init regmap field\n");768 return dev_err_probe(dev, ret, "Failed to init regmap field\n");
567 769
568 /*770 ret = regmap_write(regmap, RTQ6056_REG_CONFIG, devdata->default_config);
569 * By default, configure average sample as 1, bus and shunt conversion
570 * time as 1037 microsecond, and operating mode to all on.
571 */
572 ret = regmap_write(regmap, RTQ6056_REG_CONFIG, RTQ6056_DEFAULT_CONFIG);
573 if (ret)771 if (ret)
574 return dev_err_probe(dev, ret,772 return dev_err_probe(dev, ret,
575 "Failed to enable continuous sensing\n");773 "Failed to enable continuous sensing\n");
@@ -598,8 +796,8 @@ static int rtq6056_probe(struct i2c_client *i2c) · 22 unmodified lines
598 796
599 indio_dev->name = "rtq6056";797 indio_dev->name = "rtq6056";
600 indio_dev->modes = INDIO_DIRECT_MODE;798 indio_dev->modes = INDIO_DIRECT_MODE;
601 indio_dev->channels = rtq6056_channels;799 indio_dev->channels = devdata->channels;
602 indio_dev->num_channels = ARRAY_SIZE(rtq6056_channels);800 indio_dev->num_channels = devdata->num_channels;
603 indio_dev->info = &rtq6056_info;801 indio_dev->info = &rtq6056_info;
604 802
605 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,803 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
@@ -640,8 +838,45 @@ static int rtq6056_runtime_resume(struct device *dev) · 34 unmodified lines
640static DEFINE_RUNTIME_DEV_PM_OPS(rtq6056_pm_ops, rtq6056_runtime_suspend,838static DEFINE_RUNTIME_DEV_PM_OPS(rtq6056_pm_ops, rtq6056_runtime_suspend,
641 rtq6056_runtime_resume, NULL);839 rtq6056_runtime_resume, NULL);
642 840
841static const struct richtek_dev_data rtq6056_devdata = {
842 .default_conv_time_us = 1037,
843 .calib_coefficient = 5120000,
844 /*
845 * By default, configure average sample as 1, bus and shunt conversion
846 * time as 1037 microsecond, and operating mode to all on.
847 */
848 .default_config = RTQ6056_DEFAULT_CONFIG,
849 .avg_sample_list = rtq6056_avg_sample_list,
850 .avg_sample_list_length = ARRAY_SIZE(rtq6056_avg_sample_list),
851 .reg_fields = rtq6056_reg_fields,
852 .channels = rtq6056_channels,
853 .num_channels = ARRAY_SIZE(rtq6056_channels),
854 .read_scale = rtq6056_adc_read_scale,
855 .set_average = rtq6056_adc_set_average,
856};
857
858static const struct richtek_dev_data rtq6059_devdata = {
859 .fixed_samp_freq = true,
860 .vbus_offset = RTQ6059_VBUS_LSB_OFFSET,
861 .default_conv_time_us = 532,
862 .calib_coefficient = 40960000,
863 /*
864 * By default, configure average sample as 1, bus and shunt conversion
865 * time as 532 microsecond, and operating mode to all on.
866 */
867 .default_config = RTQ6059_DEFAULT_CONFIG,
868 .avg_sample_list = rtq6059_avg_sample_list,
869 .avg_sample_list_length = ARRAY_SIZE(rtq6059_avg_sample_list),
870 .reg_fields = rtq6059_reg_fields,
871 .channels = rtq6059_channels,
872 .num_channels = ARRAY_SIZE(rtq6059_channels),
873 .read_scale = rtq6059_adc_read_scale,
874 .set_average = rtq6059_adc_set_average,
875};
876
643static const struct of_device_id rtq6056_device_match[] = {877static const struct of_device_id rtq6056_device_match[] = {
644 { .compatible = "richtek,rtq6056" },878 { .compatible = "richtek,rtq6056", .data = &rtq6056_devdata },
879 { .compatible = "richtek,rtq6059", .data = &rtq6059_devdata },
645 {}880 {}
646};881};
647MODULE_DEVICE_TABLE(of, rtq6056_device_match);882MODULE_DEVICE_TABLE(of, rtq6056_device_match);
drivers/iio/adc/ti-adc108s102.c+1−3
@@ -293,13 +293,11 @@ static const struct of_device_id adc108s102_of_match[] = { · 292 unmodified lines
293};293};
294MODULE_DEVICE_TABLE(of, adc108s102_of_match);294MODULE_DEVICE_TABLE(of, adc108s102_of_match);
295 295
296#ifdef CONFIG_ACPI
297static const struct acpi_device_id adc108s102_acpi_ids[] = {296static const struct acpi_device_id adc108s102_acpi_ids[] = {
298 { "INT3495", 0 },297 { "INT3495", 0 },
299 { }298 { }
300};299};
301MODULE_DEVICE_TABLE(acpi, adc108s102_acpi_ids);300MODULE_DEVICE_TABLE(acpi, adc108s102_acpi_ids);
302#endif
303 301
304static const struct spi_device_id adc108s102_id[] = {302static const struct spi_device_id adc108s102_id[] = {
305 { "adc108s102", 0 },303 { "adc108s102", 0 },
@@ -311,7 +309,7 @@ static struct spi_driver adc108s102_driver = { · 5 unmodified lines
311 .driver = {309 .driver = {
312 .name = "adc108s102",310 .name = "adc108s102",
313 .of_match_table = adc108s102_of_match,311 .of_match_table = adc108s102_of_match,
314 .acpi_match_table = ACPI_PTR(adc108s102_acpi_ids),312 .acpi_match_table = adc108s102_acpi_ids,
315 },313 },
316 .probe = adc108s102_probe,314 .probe = adc108s102_probe,
317 .id_table = adc108s102_id,315 .id_table = adc108s102_id,
drivers/iio/adc/ti-ads1015.c+1−1
@@ -925,7 +925,7 @@ static int ads1015_client_get_channels_config(struct i2c_client *client) · 924 unmodified lines
925 925
926 if (!fwnode_property_read_u32(node, "ti,gain", &pval)) {926 if (!fwnode_property_read_u32(node, "ti,gain", &pval)) {
927 pga = pval;927 pga = pval;
928 if (pga > 6) {928 if (pga > 5) {
929 dev_err(dev, "invalid gain on %pfw\n", node);929 dev_err(dev, "invalid gain on %pfw\n", node);
930 fwnode_handle_put(node);930 fwnode_handle_put(node);
931 return -EINVAL;931 return -EINVAL;
drivers/iio/adc/ti-ads1298.c+771−0
@@ -0,0 +1,771 @@
1// SPDX-License-Identifier: GPL-2.0
2/* TI ADS1298 chip family driver
3 * Copyright (C) 2023 - 2024 Topic Embedded Products
4 */
5
6#include <linux/bitfield.h>
7#include <linux/cleanup.h>
8#include <linux/clk.h>
9#include <linux/err.h>
10#include <linux/delay.h>
11#include <linux/device.h>
12#include <linux/gpio/consumer.h>
13#include <linux/log2.h>
14#include <linux/math.h>
15#include <linux/module.h>
16#include <linux/regmap.h>
17#include <linux/regulator/consumer.h>
18#include <linux/slab.h>
19#include <linux/spi/spi.h>
20#include <linux/units.h>
21
22#include <linux/iio/iio.h>
23#include <linux/iio/buffer.h>
24#include <linux/iio/kfifo_buf.h>
25
26#include <asm/unaligned.h>
27
28/* Commands */
29#define ADS1298_CMD_WAKEUP 0x02
30#define ADS1298_CMD_STANDBY 0x04
31#define ADS1298_CMD_RESET 0x06
32#define ADS1298_CMD_START 0x08
33#define ADS1298_CMD_STOP 0x0a
34#define ADS1298_CMD_RDATAC 0x10
35#define ADS1298_CMD_SDATAC 0x11
36#define ADS1298_CMD_RDATA 0x12
37#define ADS1298_CMD_RREG 0x20
38#define ADS1298_CMD_WREG 0x40
39
40/* Registers */
41#define ADS1298_REG_ID 0x00
42#define ADS1298_MASK_ID_FAMILY GENMASK(7, 3)
43#define ADS1298_MASK_ID_CHANNELS GENMASK(2, 0)
44#define ADS1298_ID_FAMILY_ADS129X 0x90
45#define ADS1298_ID_FAMILY_ADS129XR 0xd0
46
47#define ADS1298_REG_CONFIG1 0x01
48#define ADS1298_MASK_CONFIG1_HR BIT(7)
49#define ADS1298_MASK_CONFIG1_DR GENMASK(2, 0)
50#define ADS1298_SHIFT_DR_HR 6
51#define ADS1298_SHIFT_DR_LP 7
52#define ADS1298_LOWEST_DR 0x06
53
54#define ADS1298_REG_CONFIG2 0x02
55#define ADS1298_MASK_CONFIG2_RESERVED BIT(6)
56#define ADS1298_MASK_CONFIG2_WCT_CHOP BIT(5)
57#define ADS1298_MASK_CONFIG2_INT_TEST BIT(4)
58#define ADS1298_MASK_CONFIG2_TEST_AMP BIT(2)
59#define ADS1298_MASK_CONFIG2_TEST_FREQ_DC GENMASK(1, 0)
60#define ADS1298_MASK_CONFIG2_TEST_FREQ_SLOW 0
61#define ADS1298_MASK_CONFIG2_TEST_FREQ_FAST BIT(0)
62
63#define ADS1298_REG_CONFIG3 0x03
64#define ADS1298_MASK_CONFIG3_PWR_REFBUF BIT(7)
65#define ADS1298_MASK_CONFIG3_RESERVED BIT(6)
66#define ADS1298_MASK_CONFIG3_VREF_4V BIT(5)
67
68#define ADS1298_REG_LOFF 0x04
69#define ADS1298_REG_CHnSET(n) (0x05 + n)
70#define ADS1298_MASK_CH_PD BIT(7)
71#define ADS1298_MASK_CH_PGA GENMASK(6, 4)
72#define ADS1298_MASK_CH_MUX GENMASK(2, 0)
73
74#define ADS1298_REG_LOFF_STATP 0x12
75#define ADS1298_REG_LOFF_STATN 0x13
76#define ADS1298_REG_CONFIG4 0x17
77#define ADS1298_MASK_CONFIG4_SINGLE_SHOT BIT(3)
78
79#define ADS1298_REG_WCT1 0x18
80#define ADS1298_REG_WCT2 0x19
81
82#define ADS1298_MAX_CHANNELS 8
83#define ADS1298_BITS_PER_SAMPLE 24
84#define ADS1298_CLK_RATE_HZ 2048000
85#define ADS1298_CLOCKS_TO_USECS(x) \
86 (DIV_ROUND_UP((x) * MICROHZ_PER_HZ, ADS1298_CLK_RATE_HZ))
87/*
88 * Read/write register commands require 4 clocks to decode, for speeds above
89 * 2x the clock rate, this would require extra time between the command byte and
90 * the data. Much simpler is to just limit the SPI transfer speed while doing
91 * register access.
92 */
93#define ADS1298_SPI_BUS_SPEED_SLOW ADS1298_CLK_RATE_HZ
94/* For reading and writing registers, we need a 3-byte buffer */
95#define ADS1298_SPI_CMD_BUFFER_SIZE 3
96/* Outputs status word and 'n' 24-bit samples, plus the command byte */
97#define ADS1298_SPI_RDATA_BUFFER_SIZE(n) (((n) + 1) * 3 + 1)
98#define ADS1298_SPI_RDATA_BUFFER_SIZE_MAX \
99 ADS1298_SPI_RDATA_BUFFER_SIZE(ADS1298_MAX_CHANNELS)
100
101struct ads1298_private {
102 const struct ads1298_chip_info *chip_info;
103 struct spi_device *spi;
104 struct regulator *reg_avdd;
105 struct regulator *reg_vref;
106 struct clk *clk;
107 struct regmap *regmap;
108 struct completion completion;
109 struct iio_trigger *trig;
110 struct spi_transfer rdata_xfer;
111 struct spi_message rdata_msg;
112 spinlock_t irq_busy_lock; /* Handshake between SPI and DRDY irqs */
113 /*
114 * rdata_xfer_busy increments when a DRDY occurs and decrements when SPI
115 * completion is reported. Hence its meaning is:
116 * 0 = Waiting for DRDY interrupt
117 * 1 = SPI transfer in progress
118 * 2 = DRDY during SPI transfer, start another transfer on completion
119 * >2 = Multiple DRDY during transfer, lost rdata_xfer_busy - 2 samples
120 */
121 unsigned int rdata_xfer_busy;
122
123 /* Temporary storage for demuxing data after SPI transfer */
124 u32 bounce_buffer[ADS1298_MAX_CHANNELS];
125
126 /* For synchronous SPI exchanges (read/write registers) */
127 u8 cmd_buffer[ADS1298_SPI_CMD_BUFFER_SIZE] __aligned(IIO_DMA_MINALIGN);
128
129 /* Buffer used for incoming SPI data */
130 u8 rx_buffer[ADS1298_SPI_RDATA_BUFFER_SIZE_MAX];
131 /* Contains the RDATA command and zeroes to clock out */
132 u8 tx_buffer[ADS1298_SPI_RDATA_BUFFER_SIZE_MAX];
133};
134
135/* Three bytes per sample in RX buffer, starting at offset 4 */
136#define ADS1298_OFFSET_IN_RX_BUFFER(index) (3 * (index) + 4)
137
138#define ADS1298_CHAN(index) \
139{ \
140 .type = IIO_VOLTAGE, \
141 .indexed = 1, \
142 .channel = index, \
143 .address = ADS1298_OFFSET_IN_RX_BUFFER(index), \
144 .info_mask_separate = \
145 BIT(IIO_CHAN_INFO_RAW) | \
146 BIT(IIO_CHAN_INFO_SCALE), \
147 .info_mask_shared_by_all = \
148 BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
149 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
150 .scan_index = index, \
151 .scan_type = { \
152 .sign = 's', \
153 .realbits = ADS1298_BITS_PER_SAMPLE, \
154 .storagebits = 32, \
155 .endianness = IIO_CPU, \
156 }, \
157}
158
159static const struct iio_chan_spec ads1298_channels[] = {
160 ADS1298_CHAN(0),
161 ADS1298_CHAN(1),
162 ADS1298_CHAN(2),
163 ADS1298_CHAN(3),
164 ADS1298_CHAN(4),
165 ADS1298_CHAN(5),
166 ADS1298_CHAN(6),
167 ADS1298_CHAN(7),
168};
169
170static int ads1298_write_cmd(struct ads1298_private *priv, u8 command)
171{
172 struct spi_transfer xfer = {
173 .tx_buf = priv->cmd_buffer,
174 .rx_buf = priv->cmd_buffer,
175 .len = 1,
176 .speed_hz = ADS1298_SPI_BUS_SPEED_SLOW,
177 .delay = {
178 .value = 2,
179 .unit = SPI_DELAY_UNIT_USECS,
180 },
181 };
182
183 priv->cmd_buffer[0] = command;
184
185 return spi_sync_transfer(priv->spi, &xfer, 1);
186}
187
188static int ads1298_read_one(struct ads1298_private *priv, int chan_index)
189{
190 int ret;
191
192 /* Enable the channel */
193 ret = regmap_update_bits(priv->regmap, ADS1298_REG_CHnSET(chan_index),
194 ADS1298_MASK_CH_PD, 0);
195 if (ret)
196 return ret;
197
198 /* Enable single-shot mode, so we don't need to send a STOP */
199 ret = regmap_update_bits(priv->regmap, ADS1298_REG_CONFIG4,
200 ADS1298_MASK_CONFIG4_SINGLE_SHOT,
201 ADS1298_MASK_CONFIG4_SINGLE_SHOT);
202 if (ret)
203 return ret;
204
205 reinit_completion(&priv->completion);
206
207 ret = ads1298_write_cmd(priv, ADS1298_CMD_START);
208 if (ret < 0) {
209 dev_err(&priv->spi->dev, "CMD_START error: %d\n", ret);
210 return ret;
211 }
212
213 /* Cannot take longer than 40ms (250Hz) */
214 ret = wait_for_completion_timeout(&priv->completion, msecs_to_jiffies(50));
215 if (!ret)
216 return -ETIMEDOUT;
217
218 return 0;
219}
220
221static int ads1298_get_samp_freq(struct ads1298_private *priv, int *val)
222{
223 unsigned long rate;
224 unsigned int cfg;
225 int ret;
226
227 ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG1, &cfg);
228 if (ret)
229 return ret;
230
231 if (priv->clk)
232 rate = clk_get_rate(priv->clk);
233 else
234 rate = ADS1298_CLK_RATE_HZ;
235 if (!rate)
236 return -EINVAL;
237
238 /* Data rate shift depends on HR/LP mode */
239 if (cfg & ADS1298_MASK_CONFIG1_HR)
240 rate >>= ADS1298_SHIFT_DR_HR;
241 else
242 rate >>= ADS1298_SHIFT_DR_LP;
243
244 *val = rate >> (cfg & ADS1298_MASK_CONFIG1_DR);
245
246 return IIO_VAL_INT;
247}
248
249static int ads1298_set_samp_freq(struct ads1298_private *priv, int val)
250{
251 unsigned long rate;
252 unsigned int factor;
253 unsigned int cfg;
254
255 if (priv->clk)
256 rate = clk_get_rate(priv->clk);
257 else
258 rate = ADS1298_CLK_RATE_HZ;
259 if (!rate)
260 return -EINVAL;
261 if (val <= 0)
262 return -EINVAL;
263
264 factor = (rate >> ADS1298_SHIFT_DR_HR) / val;
265 if (factor >= BIT(ADS1298_SHIFT_DR_LP))
266 cfg = ADS1298_LOWEST_DR;
267 else if (factor)
268 cfg = ADS1298_MASK_CONFIG1_HR | ilog2(factor); /* Use HR mode */
269 else
270 cfg = ADS1298_MASK_CONFIG1_HR; /* Fastest possible */
271
272 return regmap_update_bits(priv->regmap, ADS1298_REG_CONFIG1,
273 ADS1298_MASK_CONFIG1_HR | ADS1298_MASK_CONFIG1_DR,
274 cfg);
275}
276
277static const u8 ads1298_pga_settings[] = { 6, 1, 2, 3, 4, 8, 12 };
278
279static int ads1298_get_scale(struct ads1298_private *priv,
280 int channel, int *val, int *val2)
281{
282 int ret;
283 unsigned int regval;
284 u8 gain;
285
286 if (priv->reg_vref) {
287 ret = regulator_get_voltage(priv->reg_vref);
288 if (ret < 0)
289 return ret;
290
291 *val = ret / MILLI; /* Convert to millivolts */
292 } else {
293 ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG3, &regval);
294 if (ret)
295 return ret;
296
297 /* Refererence in millivolts */
298 *val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400;
299 }
300
301 ret = regmap_read(priv->regmap, ADS1298_REG_CHnSET(channel), &regval);
302 if (ret)
303 return ret;
304
305 gain = ads1298_pga_settings[FIELD_GET(ADS1298_MASK_CH_PGA, regval)];
306 *val /= gain; /* Full scale is VREF / gain */
307
308 *val2 = ADS1298_BITS_PER_SAMPLE - 1; /* Signed, hence the -1 */
309
310 return IIO_VAL_FRACTIONAL_LOG2;
311}
312
313static int ads1298_read_raw(struct iio_dev *indio_dev,
314 struct iio_chan_spec const *chan,
315 int *val, int *val2, long mask)
316{
317 struct ads1298_private *priv = iio_priv(indio_dev);
318 int ret;
319
320 switch (mask) {
321 case IIO_CHAN_INFO_RAW:
322 ret = iio_device_claim_direct_mode(indio_dev);
323 if (ret)
324 return ret;
325
326 ret = ads1298_read_one(priv, chan->scan_index);
327
328 iio_device_release_direct_mode(indio_dev);
329
330 if (ret)
331 return ret;
332
333 *val = sign_extend32(get_unaligned_be24(priv->rx_buffer + chan->address),
334 ADS1298_BITS_PER_SAMPLE - 1);
335 return IIO_VAL_INT;
336 case IIO_CHAN_INFO_SCALE:
337 return ads1298_get_scale(priv, chan->channel, val, val2);
338 case IIO_CHAN_INFO_SAMP_FREQ:
339 return ads1298_get_samp_freq(priv, val);
340 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
341 ret = regmap_read(priv->regmap, ADS1298_REG_CONFIG1, val);
342 if (ret)
343 return ret;
344
345 *val = 16 << (*val & ADS1298_MASK_CONFIG1_DR);
346 return IIO_VAL_INT;
347 default:
348 return -EINVAL;
349 }
350}
351
352static int ads1298_write_raw(struct iio_dev *indio_dev,
353 struct iio_chan_spec const *chan, int val,
354 int val2, long mask)
355{
356 struct ads1298_private *priv = iio_priv(indio_dev);
357
358 switch (mask) {
359 case IIO_CHAN_INFO_SAMP_FREQ:
360 return ads1298_set_samp_freq(priv, val);
361 default:
362 return -EINVAL;
363 }
364}
365
366static int ads1298_reg_write(void *context, unsigned int reg, unsigned int val)
367{
368 struct ads1298_private *priv = context;
369 struct spi_transfer reg_write_xfer = {
370 .tx_buf = priv->cmd_buffer,
371 .rx_buf = priv->cmd_buffer,
372 .len = 3,
373 .speed_hz = ADS1298_SPI_BUS_SPEED_SLOW,
374 .delay = {
375 .value = 2,
376 .unit = SPI_DELAY_UNIT_USECS,
377 },
378 };
379
380 priv->cmd_buffer[0] = ADS1298_CMD_WREG | reg;
381 priv->cmd_buffer[1] = 0; /* Number of registers to be written - 1 */
382 priv->cmd_buffer[2] = val;
383
384 return spi_sync_transfer(priv->spi, &reg_write_xfer, 1);
385}
386
387static int ads1298_reg_read(void *context, unsigned int reg, unsigned int *val)
388{
389 struct ads1298_private *priv = context;
390 struct spi_transfer reg_read_xfer = {
391 .tx_buf = priv->cmd_buffer,
392 .rx_buf = priv->cmd_buffer,
393 .len = 3,
394 .speed_hz = ADS1298_SPI_BUS_SPEED_SLOW,
395 .delay = {
396 .value = 2,
397 .unit = SPI_DELAY_UNIT_USECS,
398 },
399 };
400 int ret;
401
402 priv->cmd_buffer[0] = ADS1298_CMD_RREG | reg;
403 priv->cmd_buffer[1] = 0; /* Number of registers to be read - 1 */
404 priv->cmd_buffer[2] = 0;
405
406 ret = spi_sync_transfer(priv->spi, &reg_read_xfer, 1);
407 if (ret)
408 return ret;
409
410 *val = priv->cmd_buffer[2];
411
412 return 0;
413}
414
415static int ads1298_reg_access(struct iio_dev *indio_dev, unsigned int reg,
416 unsigned int writeval, unsigned int *readval)
417{
418 struct ads1298_private *priv = iio_priv(indio_dev);
419
420 if (readval)
421 return regmap_read(priv->regmap, reg, readval);
422
423 return regmap_write(priv->regmap, reg, writeval);
424}
425
426static void ads1298_rdata_unmark_busy(struct ads1298_private *priv)
427{
428 /* Notify we're no longer waiting for the SPI transfer to complete */
429 guard(spinlock_irqsave)(&priv->irq_busy_lock);
430 priv->rdata_xfer_busy = 0;
431}
432
433static int ads1298_update_scan_mode(struct iio_dev *indio_dev,
434 const unsigned long *scan_mask)
435{
436 struct ads1298_private *priv = iio_priv(indio_dev);
437 unsigned int val;
438 int ret;
439 int i;
440
441 /* Make the interrupt routines start with a clean slate */
442 ads1298_rdata_unmark_busy(priv);
443
444 /* Configure power-down bits to match scan mask */
445 for (i = 0; i < indio_dev->num_channels; i++) {
446 val = test_bit(i, scan_mask) ? 0 : ADS1298_MASK_CH_PD;
447 ret = regmap_update_bits(priv->regmap, ADS1298_REG_CHnSET(i),
448 ADS1298_MASK_CH_PD, val);
449 if (ret)
450 return ret;
451 }
452
453 return 0;
454}
455
456static const struct iio_info ads1298_info = {
457 .read_raw = &ads1298_read_raw,
458 .write_raw = &ads1298_write_raw,
459 .update_scan_mode = &ads1298_update_scan_mode,
460 .debugfs_reg_access = &ads1298_reg_access,
461};
462
463static void ads1298_rdata_release_busy_or_restart(struct ads1298_private *priv)
464{
465 guard(spinlock_irqsave)(&priv->irq_busy_lock);
466
467 if (priv->rdata_xfer_busy > 1) {
468 /*
469 * DRDY interrupt occurred before SPI completion. Start a new
470 * SPI transaction now to retrieve the data that wasn't latched
471 * into the ADS1298 chip's transfer buffer yet.
472 */
473 spi_async(priv->spi, &priv->rdata_msg);
474 /*
475 * If more than one DRDY took place, there was an overrun. Since
476 * the sample is already lost, reset the counter to 1 so that
477 * we will wait for a DRDY interrupt after this SPI transaction.
478 */
479 priv->rdata_xfer_busy = 1;
480 } else {
481 /* No pending data, wait for DRDY */
482 priv->rdata_xfer_busy = 0;
483 }
484}
485
486/* Called from SPI completion interrupt handler */
487static void ads1298_rdata_complete(void *context)
488{
489 struct iio_dev *indio_dev = context;
490 struct ads1298_private *priv = iio_priv(indio_dev);
491 int scan_index;
492 u32 *bounce = priv->bounce_buffer;
493
494 if (!iio_buffer_enabled(indio_dev)) {
495 /*
496 * for a single transfer mode we're kept in direct_mode until
497 * completion, avoiding a race with buffered IO.
498 */
499 ads1298_rdata_unmark_busy(priv);
500 complete(&priv->completion);
501 return;
502 }
503
504 /* Demux the channel data into our bounce buffer */
505 for_each_set_bit(scan_index, indio_dev->active_scan_mask,
506 indio_dev->masklength) {
507 const struct iio_chan_spec *scan_chan =
508 &indio_dev->channels[scan_index];
509 const u8 *data = priv->rx_buffer + scan_chan->address;
510
511 *bounce++ = get_unaligned_be24(data);
512 }
513
514 /* rx_buffer can be overwritten from this point on */
515 ads1298_rdata_release_busy_or_restart(priv);
516
517 iio_push_to_buffers(indio_dev, priv->bounce_buffer);
518}
519
520static irqreturn_t ads1298_interrupt(int irq, void *dev_id)
521{
522 struct iio_dev *indio_dev = dev_id;
523 struct ads1298_private *priv = iio_priv(indio_dev);
524 unsigned int wasbusy;
525
526 guard(spinlock_irqsave)(&priv->irq_busy_lock);
527
528 wasbusy = priv->rdata_xfer_busy++;
529 /* When no SPI transfer in transit, start one now */
530 if (!wasbusy)
531 spi_async(priv->spi, &priv->rdata_msg);
532
533 return IRQ_HANDLED;
534};
535
536static int ads1298_buffer_postenable(struct iio_dev *indio_dev)
537{
538 struct ads1298_private *priv = iio_priv(indio_dev);
539 int ret;
540
541 /* Disable single-shot mode */
542 ret = regmap_update_bits(priv->regmap, ADS1298_REG_CONFIG4,
543 ADS1298_MASK_CONFIG4_SINGLE_SHOT, 0);
544 if (ret)
545 return ret;
546
547 return ads1298_write_cmd(priv, ADS1298_CMD_START);
548}
549
550static int ads1298_buffer_predisable(struct iio_dev *indio_dev)
551{
552 struct ads1298_private *priv = iio_priv(indio_dev);
553
554 return ads1298_write_cmd(priv, ADS1298_CMD_STOP);
555}
556
557static const struct iio_buffer_setup_ops ads1298_setup_ops = {
558 .postenable = &ads1298_buffer_postenable,
559 .predisable = &ads1298_buffer_predisable,
560};
561
562static void ads1298_reg_disable(void *reg)
563{
564 regulator_disable(reg);
565}
566
567static const struct regmap_range ads1298_regmap_volatile_range[] = {
568 regmap_reg_range(ADS1298_REG_LOFF_STATP, ADS1298_REG_LOFF_STATN),
569};
570
571static const struct regmap_access_table ads1298_regmap_volatile = {
572 .yes_ranges = ads1298_regmap_volatile_range,
573 .n_yes_ranges = ARRAY_SIZE(ads1298_regmap_volatile_range),
574};
575
576static const struct regmap_config ads1298_regmap_config = {
577 .reg_bits = 8,
578 .val_bits = 8,
579 .reg_read = ads1298_reg_read,
580 .reg_write = ads1298_reg_write,
581 .max_register = ADS1298_REG_WCT2,
582 .volatile_table = &ads1298_regmap_volatile,
583 .cache_type = REGCACHE_MAPLE,
584};
585
586static int ads1298_init(struct iio_dev *indio_dev)
587{
588 struct ads1298_private *priv = iio_priv(indio_dev);
589 struct device *dev = &priv->spi->dev;
590 const char *suffix;
591 unsigned int val;
592 int ret;
593
594 /* Device initializes into RDATAC mode, which we don't want */
595 ret = ads1298_write_cmd(priv, ADS1298_CMD_SDATAC);
596 if (ret)
597 return ret;
598
599 ret = regmap_read(priv->regmap, ADS1298_REG_ID, &val);
600 if (ret)
601 return ret;
602
603 /* Fill in name and channel count based on what the chip told us */
604 indio_dev->num_channels = 4 + 2 * (val & ADS1298_MASK_ID_CHANNELS);
605 switch (val & ADS1298_MASK_ID_FAMILY) {
606 case ADS1298_ID_FAMILY_ADS129X:
607 suffix = "";
608 break;
609 case ADS1298_ID_FAMILY_ADS129XR:
610 suffix = "r";
611 break;
612 default:
613 return dev_err_probe(dev, -ENODEV, "Unknown ID: 0x%x\n", val);
614 }
615 indio_dev->name = devm_kasprintf(dev, GFP_KERNEL, "ads129%u%s",
616 indio_dev->num_channels, suffix);
617
618 /* Enable internal test signal, double amplitude, double frequency */
619 ret = regmap_write(priv->regmap, ADS1298_REG_CONFIG2,
620 ADS1298_MASK_CONFIG2_RESERVED |
621 ADS1298_MASK_CONFIG2_INT_TEST |
622 ADS1298_MASK_CONFIG2_TEST_AMP |
623 ADS1298_MASK_CONFIG2_TEST_FREQ_FAST);
624 if (ret)
625 return ret;
626
627 val = ADS1298_MASK_CONFIG3_RESERVED; /* Must write 1 always */
628 if (!priv->reg_vref) {
629 /* Enable internal reference */
630 val |= ADS1298_MASK_CONFIG3_PWR_REFBUF;
631 /* Use 4V VREF when power supply is at least 4.4V */
632 if (regulator_get_voltage(priv->reg_avdd) >= 4400000)
633 val |= ADS1298_MASK_CONFIG3_VREF_4V;
634 }
635 return regmap_write(priv->regmap, ADS1298_REG_CONFIG3, val);
636}
637
638static int ads1298_probe(struct spi_device *spi)
639{
640 struct ads1298_private *priv;
641 struct iio_dev *indio_dev;
642 struct device *dev = &spi->dev;
643 struct gpio_desc *reset_gpio;
644 int ret;
645
646 indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
647 if (!indio_dev)
648 return -ENOMEM;
649
650 priv = iio_priv(indio_dev);
651
652 /* Reset to be asserted before enabling clock and power */
653 reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
654 if (IS_ERR(reset_gpio))
655 return dev_err_probe(dev, PTR_ERR(reset_gpio),
656 "Cannot get reset GPIO\n");
657
658 /* VREF can be supplied externally, otherwise use internal reference */
659 priv->reg_vref = devm_regulator_get_optional(dev, "vref");
660 if (IS_ERR(priv->reg_vref)) {
661 if (PTR_ERR(priv->reg_vref) != -ENODEV)
662 return dev_err_probe(dev, PTR_ERR(priv->reg_vref),
663 "Failed to get vref regulator\n");
664
665 priv->reg_vref = NULL;
666 } else {
667 ret = regulator_enable(priv->reg_vref);
668 if (ret)
669 return ret;
670
671 ret = devm_add_action_or_reset(dev, ads1298_reg_disable, priv->reg_vref);
672 if (ret)
673 return ret;
674 }
675
676 priv->clk = devm_clk_get_optional_enabled(dev, "clk");
677 if (IS_ERR(priv->clk))
678 return dev_err_probe(dev, PTR_ERR(priv->clk), "Failed to get clk\n");
679
680 priv->reg_avdd = devm_regulator_get(dev, "avdd");
681 if (IS_ERR(priv->reg_avdd))
682 return dev_err_probe(dev, PTR_ERR(priv->reg_avdd),
683 "Failed to get avdd regulator\n");
684
685 ret = regulator_enable(priv->reg_avdd);
686 if (ret)
687 return dev_err_probe(dev, ret, "Failed to enable avdd regulator\n");
688
689 ret = devm_add_action_or_reset(dev, ads1298_reg_disable, priv->reg_avdd);
690 if (ret)
691 return ret;
692
693 priv->spi = spi;
694 init_completion(&priv->completion);
695 spin_lock_init(&priv->irq_busy_lock);
696 priv->regmap = devm_regmap_init(dev, NULL, priv, &ads1298_regmap_config);
697 if (IS_ERR(priv->regmap))
698 return PTR_ERR(priv->regmap);
699
700 indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
701 indio_dev->channels = ads1298_channels;
702 indio_dev->info = &ads1298_info;
703
704 if (reset_gpio) {
705 /*
706 * Deassert reset now that clock and power are active.
707 * Minimum reset pulsewidth is 2 clock cycles.
708 */
709 fsleep(ADS1298_CLOCKS_TO_USECS(2));
710 gpiod_set_value_cansleep(reset_gpio, 0);
711 } else {
712 ret = ads1298_write_cmd(priv, ADS1298_CMD_RESET);
713 if (ret)
714 return dev_err_probe(dev, ret, "RESET failed\n");
715 }
716 /* Wait 18 clock cycles for reset command to complete */
717 fsleep(ADS1298_CLOCKS_TO_USECS(18));
718
719 ret = ads1298_init(indio_dev);
720 if (ret)
721 return dev_err_probe(dev, ret, "Init failed\n");
722
723 priv->tx_buffer[0] = ADS1298_CMD_RDATA;
724 priv->rdata_xfer.tx_buf = priv->tx_buffer;
725 priv->rdata_xfer.rx_buf = priv->rx_buffer;
726 priv->rdata_xfer.len = ADS1298_SPI_RDATA_BUFFER_SIZE(indio_dev->num_channels);
727 /* Must keep CS low for 4 clocks */
728 priv->rdata_xfer.delay.value = 2;
729 priv->rdata_xfer.delay.unit = SPI_DELAY_UNIT_USECS;
730 spi_message_init_with_transfers(&priv->rdata_msg, &priv->rdata_xfer, 1);
731 priv->rdata_msg.complete = &ads1298_rdata_complete;
732 priv->rdata_msg.context = indio_dev;
733
734 ret = devm_request_irq(dev, spi->irq, &ads1298_interrupt,
735 IRQF_TRIGGER_FALLING, indio_dev->name,
736 indio_dev);
737 if (ret)
738 return ret;
739
740 ret = devm_iio_kfifo_buffer_setup(dev, indio_dev, &ads1298_setup_ops);
741 if (ret)
742 return ret;
743
744 return devm_iio_device_register(dev, indio_dev);
745}
746
747static const struct spi_device_id ads1298_id[] = {
748 { "ads1298" },
749 { }
750};
751MODULE_DEVICE_TABLE(spi, ads1298_id);
752
753static const struct of_device_id ads1298_of_table[] = {
754 { .compatible = "ti,ads1298" },
755 { }
756};
757MODULE_DEVICE_TABLE(of, ads1298_of_table);
758
759static struct spi_driver ads1298_driver = {
760 .driver = {
761 .name = "ads1298",
762 .of_match_table = ads1298_of_table,
763 },
764 .probe = ads1298_probe,
765 .id_table = ads1298_id,
766};
767module_spi_driver(ads1298_driver);
768
769MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
770MODULE_DESCRIPTION("TI ADS1298 ADC");
771MODULE_LICENSE("GPL");
drivers/iio/adc/ti-ads8688.c+1−1
@@ -11,7 +11,7 @@ · 10 unmodified lines
11#include <linux/regulator/consumer.h>11#include <linux/regulator/consumer.h>
12#include <linux/err.h>12#include <linux/err.h>
13#include <linux/module.h>13#include <linux/module.h>
14#include <linux/of.h>14#include <linux/mod_devicetable.h>
15 15
16#include <linux/iio/iio.h>16#include <linux/iio/iio.h>
17#include <linux/iio/buffer.h>17#include <linux/iio/buffer.h>
drivers/iio/amplifiers/hmc425a.c+216−58
@@ -2,9 +2,10 @@ · 1 unmodified line
2/*2/*
3 * HMC425A and similar Gain Amplifiers3 * HMC425A and similar Gain Amplifiers
4 *4 *
5 * Copyright 2020 Analog Devices Inc.5 * Copyright 2020, 2024 Analog Devices Inc.
6 */6 */
7 7
8#include <linux/bits.h>
8#include <linux/bitops.h>9#include <linux/bitops.h>
9#include <linux/device.h>10#include <linux/device.h>
10#include <linux/err.h>11#include <linux/err.h>
@@ -12,6 +13,7 @@ · 1 unmodified line
12#include <linux/iio/iio.h>13#include <linux/iio/iio.h>
13#include <linux/iio/sysfs.h>14#include <linux/iio/sysfs.h>
14#include <linux/kernel.h>15#include <linux/kernel.h>
16#include <linux/math.h>
15#include <linux/mod_devicetable.h>17#include <linux/mod_devicetable.h>
16#include <linux/module.h>18#include <linux/module.h>
17#include <linux/platform_device.h>19#include <linux/platform_device.h>
@@ -20,10 +22,24 @@ · 2 unmodified lines
20#include <linux/regulator/consumer.h>22#include <linux/regulator/consumer.h>
21#include <linux/sysfs.h>23#include <linux/sysfs.h>
22 24
25/*
26 * The LTC6373 amplifier supports configuring gain using GPIO's with the following
27 * values (OUTPUT_V / INPUT_V): 0(shutdown), 0.25, 0.5, 1, 2, 4, 8, 16
28 *
29 * Except for the shutdown value, all can be converted to dB using 20 * log10(x)
30 * From here, it is observed that all values are multiples of the '2' gain setting,
31 * with the correspondent of 6.020dB.
32 */
33#define LTC6373_CONVERSION_CONSTANT 6020
34#define LTC6373_MIN_GAIN_CODE 0x6
35#define LTC6373_CONVERSION_MASK GENMASK(2, 0)
36#define LTC6373_SHUTDOWN GENMASK(2, 0)
37
23enum hmc425a_type {38enum hmc425a_type {
24 ID_HMC425A,39 ID_HMC425A,
25 ID_HMC540S,40 ID_HMC540S,
26 ID_ADRF574041 ID_ADRF5740,
42 ID_LTC6373,
27};43};
28 44
29struct hmc425a_chip_info {45struct hmc425a_chip_info {
@@ -34,16 +50,110 @@ struct hmc425a_chip_info { · 4 unmodified lines
34 int gain_min;50 int gain_min;
35 int gain_max;51 int gain_max;
36 int default_gain;52 int default_gain;
53 int powerdown_val;
54 bool has_powerdown;
55
56 int (*gain_dB_to_code)(int gain, int *code);
57 int (*code_to_gain_dB)(int code, int *val, int *val2);
37};58};
38 59
39struct hmc425a_state {60struct hmc425a_state {
40 struct mutex lock; /* protect sensor state */61 struct mutex lock; /* protect sensor state */
41 struct hmc425a_chip_info *chip_info;62 const struct hmc425a_chip_info *chip_info;
42 struct gpio_descs *gpios;63 struct gpio_descs *gpios;
43 enum hmc425a_type type;
44 u32 gain;64 u32 gain;
65 bool powerdown;
45};66};
46 67
68static int gain_dB_to_code(struct hmc425a_state *st, int val, int val2, int *code)
69{
70 const struct hmc425a_chip_info *inf = st->chip_info;
71 int gain;
72
73 if (val < 0)
74 gain = (val * 1000) - (val2 / 1000);
75 else
76 gain = (val * 1000) + (val2 / 1000);
77
78 if (gain > inf->gain_max || gain < inf->gain_min)
79 return -EINVAL;
80 if (st->powerdown)
81 return -EPERM;
82
83 return st->chip_info->gain_dB_to_code(gain, code);
84}
85
86static int hmc425a_gain_dB_to_code(int gain, int *code)
87{
88 *code = ~((abs(gain) / 500) & 0x3F);
89 return 0;
90}
91
92static int hmc540s_gain_dB_to_code(int gain, int *code)
93{
94 *code = ~((abs(gain) / 1000) & 0xF);
95 return 0;
96}
97
98static int adrf5740_gain_dB_to_code(int gain, int *code)
99{
100 int temp = (abs(gain) / 2000) & 0xF;
101
102 /* Bit [0-3]: 2dB 4dB 8dB 8dB */
103 *code = temp & BIT(3) ? temp | BIT(2) : temp;
104 return 0;
105}
106
107static int ltc6373_gain_dB_to_code(int gain, int *code)
108{
109 *code = ~(DIV_ROUND_CLOSEST(gain, LTC6373_CONVERSION_CONSTANT) + 3)
110 & LTC6373_CONVERSION_MASK;
111 return 0;
112}
113
114static int code_to_gain_dB(struct hmc425a_state *st, int *val, int *val2)
115{
116 if (st->powerdown)
117 return -EPERM;
118 return st->chip_info->code_to_gain_dB(st->gain, val, val2);
119}
120
121static int hmc425a_code_to_gain_dB(int code, int *val, int *val2)
122{
123 *val = (~code * -500) / 1000;
124 *val2 = ((~code * -500) % 1000) * 1000;
125 return 0;
126}
127
128static int hmc540s_code_to_gain_dB(int code, int *val, int *val2)
129{
130 *val = (~code * -1000) / 1000;
131 *val2 = ((~code * -1000) % 1000) * 1000;
132 return 0;
133}
134
135static int adrf5740_code_to_gain_dB(int code, int *val, int *val2)
136{
137 /*
138 * Bit [0-3]: 2dB 4dB 8dB 8dB
139 * When BIT(3) is set, unset BIT(2) and use 3 as double the place value
140 */
141 code = code & BIT(3) ? code & ~BIT(2) : code;
142 *val = (code * -2000) / 1000;
143 *val2 = ((code * -2000) % 1000) * 1000;
144 return 0;
145}
146
147static int ltc6373_code_to_gain_dB(int code, int *val, int *val2)
148{
149 int gain = ((~code & LTC6373_CONVERSION_MASK) - 3) *
150 LTC6373_CONVERSION_CONSTANT;
151
152 *val = gain / 1000;
153 *val2 = (gain % 1000) * 1000;
154 return 0;
155}
156
47static int hmc425a_write(struct iio_dev *indio_dev, u32 value)157static int hmc425a_write(struct iio_dev *indio_dev, u32 value)
48{158{
49 struct hmc425a_state *st = iio_priv(indio_dev);159 struct hmc425a_state *st = iio_priv(indio_dev);
@@ -61,30 +171,14 @@ static int hmc425a_read_raw(struct iio_dev *indio_dev, · 11 unmodified lines
61 int *val2, long m)171 int *val2, long m)
62{172{
63 struct hmc425a_state *st = iio_priv(indio_dev);173 struct hmc425a_state *st = iio_priv(indio_dev);
64 int code, gain = 0;
65 int ret;174 int ret;
66 175
67 mutex_lock(&st->lock);176 mutex_lock(&st->lock);
68 switch (m) {177 switch (m) {
69 case IIO_CHAN_INFO_HARDWAREGAIN:178 case IIO_CHAN_INFO_HARDWAREGAIN:
70 code = st->gain;179 ret = code_to_gain_dB(st, val, val2);
71 180 if (ret)
72 switch (st->type) {
73 case ID_HMC425A:
74 gain = ~code * -500;
75 break;181 break;
76 case ID_HMC540S:
77 gain = ~code * -1000;
78 break;
79 case ID_ADRF5740:
80 code = code & BIT(3) ? code & ~BIT(2) : code;
81 gain = code * -2000;
82 break;
83 }
84
85 *val = gain / 1000;
86 *val2 = (gain % 1000) * 1000;
87
88 ret = IIO_VAL_INT_PLUS_MICRO_DB;182 ret = IIO_VAL_INT_PLUS_MICRO_DB;
89 break;183 break;
90 default:184 default:
@@ -100,34 +194,14 @@ static int hmc425a_write_raw(struct iio_dev *indio_dev, · 9 unmodified lines
100 int val2, long mask)194 int val2, long mask)
101{195{
102 struct hmc425a_state *st = iio_priv(indio_dev);196 struct hmc425a_state *st = iio_priv(indio_dev);
103 struct hmc425a_chip_info *inf = st->chip_info;197 int code = 0, ret;
104 int code = 0, gain;
105 int ret;
106
107 if (val < 0)
108 gain = (val * 1000) - (val2 / 1000);
109 else
110 gain = (val * 1000) + (val2 / 1000);
111
112 if (gain > inf->gain_max || gain < inf->gain_min)
113 return -EINVAL;
114
115 switch (st->type) {
116 case ID_HMC425A:
117 code = ~((abs(gain) / 500) & 0x3F);
118 break;
119 case ID_HMC540S:
120 code = ~((abs(gain) / 1000) & 0xF);
121 break;
122 case ID_ADRF5740:
123 code = (abs(gain) / 2000) & 0xF;
124 code = code & BIT(3) ? code | BIT(2) : code;
125 break;
126 }
127 198
128 mutex_lock(&st->lock);199 mutex_lock(&st->lock);
129 switch (mask) {200 switch (mask) {
130 case IIO_CHAN_INFO_HARDWAREGAIN:201 case IIO_CHAN_INFO_HARDWAREGAIN:
202 ret = gain_dB_to_code(st, val, val2, &code);
203 if (ret)
204 break;
131 st->gain = code;205 st->gain = code;
132 206
133 ret = hmc425a_write(indio_dev, st->gain);207 ret = hmc425a_write(indio_dev, st->gain);
@@ -158,6 +232,48 @@ static const struct iio_info hmc425a_info = { · 24 unmodified lines
158 .write_raw_get_fmt = &hmc425a_write_raw_get_fmt,232 .write_raw_get_fmt = &hmc425a_write_raw_get_fmt,
159};233};
160 234
235static ssize_t ltc6373_read_powerdown(struct iio_dev *indio_dev,
236 uintptr_t private,
237 const struct iio_chan_spec *chan,
238 char *buf)
239{
240 struct hmc425a_state *st = iio_priv(indio_dev);
241
242 return sysfs_emit(buf, "%d\n", st->powerdown);
243}
244
245static ssize_t ltc6373_write_powerdown(struct iio_dev *indio_dev,
246 uintptr_t private,
247 const struct iio_chan_spec *chan,
248 const char *buf,
249 size_t len)
250{
251 struct hmc425a_state *st = iio_priv(indio_dev);
252 bool powerdown;
253 int code, ret;
254
255 ret = kstrtobool(buf, &powerdown);
256 if (ret)
257 return ret;
258
259 mutex_lock(&st->lock);
260 st->powerdown = powerdown;
261 code = (powerdown) ? LTC6373_SHUTDOWN : st->gain;
262 hmc425a_write(indio_dev, code);
263 mutex_unlock(&st->lock);
264 return len;
265}
266
267static const struct iio_chan_spec_ext_info ltc6373_ext_info[] = {
268 {
269 .name = "powerdown",
270 .read = ltc6373_read_powerdown,
271 .write = ltc6373_write_powerdown,
272 .shared = IIO_SEPARATE,
273 },
274 {}
275};
276
161#define HMC425A_CHAN(_channel) \277#define HMC425A_CHAN(_channel) \
162{ \278{ \
163 .type = IIO_VOLTAGE, \279 .type = IIO_VOLTAGE, \
@@ -167,20 +283,25 @@ static const struct iio_info hmc425a_info = { · 3 unmodified lines
167 .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN), \283 .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
168}284}
169 285
286#define LTC6373_CHAN(_channel) \
287{ \
288 .type = IIO_VOLTAGE, \
289 .output = 1, \
290 .indexed = 1, \
291 .channel = _channel, \
292 .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
293 .ext_info = ltc6373_ext_info, \
294}
295
170static const struct iio_chan_spec hmc425a_channels[] = {296static const struct iio_chan_spec hmc425a_channels[] = {
171 HMC425A_CHAN(0),297 HMC425A_CHAN(0),
172};298};
173 299
174/* Match table for of_platform binding */300static const struct iio_chan_spec ltc6373_channels[] = {
175static const struct of_device_id hmc425a_of_match[] = {301 LTC6373_CHAN(0),
176 { .compatible = "adi,hmc425a", .data = (void *)ID_HMC425A },
177 { .compatible = "adi,hmc540s", .data = (void *)ID_HMC540S },
178 { .compatible = "adi,adrf5740", .data = (void *)ID_ADRF5740 },
179 {},
180};302};
181MODULE_DEVICE_TABLE(of, hmc425a_of_match);
182 303
183static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = {304static const struct hmc425a_chip_info hmc425a_chip_info_tbl[] = {
184 [ID_HMC425A] = {305 [ID_HMC425A] = {
185 .name = "hmc425a",306 .name = "hmc425a",
186 .channels = hmc425a_channels,307 .channels = hmc425a_channels,
@@ -189,6 +310,8 @@ static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = { · 2 unmodified lines
189 .gain_min = -31500,310 .gain_min = -31500,
190 .gain_max = 0,311 .gain_max = 0,
191 .default_gain = -0x40, /* set default gain -31.5db*/312 .default_gain = -0x40, /* set default gain -31.5db*/
313 .gain_dB_to_code = hmc425a_gain_dB_to_code,
314 .code_to_gain_dB = hmc425a_code_to_gain_dB,
192 },315 },
193 [ID_HMC540S] = {316 [ID_HMC540S] = {
194 .name = "hmc540s",317 .name = "hmc540s",
@@ -198,6 +321,8 @@ static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = { · 3 unmodified lines
198 .gain_min = -15000,321 .gain_min = -15000,
199 .gain_max = 0,322 .gain_max = 0,
200 .default_gain = -0x10, /* set default gain -15.0db*/323 .default_gain = -0x10, /* set default gain -15.0db*/
324 .gain_dB_to_code = hmc540s_gain_dB_to_code,
325 .code_to_gain_dB = hmc540s_code_to_gain_dB,
201 },326 },
202 [ID_ADRF5740] = {327 [ID_ADRF5740] = {
203 .name = "adrf5740",328 .name = "adrf5740",
@@ -207,6 +332,21 @@ static struct hmc425a_chip_info hmc425a_chip_info_tbl[] = { · 3 unmodified lines
207 .gain_min = -22000,332 .gain_min = -22000,
208 .gain_max = 0,333 .gain_max = 0,
209 .default_gain = 0xF, /* set default gain -22.0db*/334 .default_gain = 0xF, /* set default gain -22.0db*/
335 .gain_dB_to_code = adrf5740_gain_dB_to_code,
336 .code_to_gain_dB = adrf5740_code_to_gain_dB,
337 },
338 [ID_LTC6373] = {
339 .name = "ltc6373",
340 .channels = ltc6373_channels,
341 .num_channels = ARRAY_SIZE(ltc6373_channels),
342 .num_gpios = 3,
343 .gain_min = -12041, /* gain setting x0.25*/
344 .gain_max = 24082, /* gain setting x16 */
345 .default_gain = LTC6373_MIN_GAIN_CODE,
346 .powerdown_val = LTC6373_SHUTDOWN,
347 .has_powerdown = true,
348 .gain_dB_to_code = ltc6373_gain_dB_to_code,
349 .code_to_gain_dB = ltc6373_code_to_gain_dB,
210 },350 },
211};351};
212 352
@@ -221,9 +361,8 @@ static int hmc425a_probe(struct platform_device *pdev) · 8 unmodified lines
221 return -ENOMEM;361 return -ENOMEM;
222 362
223 st = iio_priv(indio_dev);363 st = iio_priv(indio_dev);
224 st->type = (uintptr_t)device_get_match_data(&pdev->dev);
225 364
226 st->chip_info = &hmc425a_chip_info_tbl[st->type];365 st->chip_info = device_get_match_data(&pdev->dev);
227 indio_dev->num_channels = st->chip_info->num_channels;366 indio_dev->num_channels = st->chip_info->num_channels;
228 indio_dev->channels = st->chip_info->channels;367 indio_dev->channels = st->chip_info->channels;
229 indio_dev->name = st->chip_info->name;368 indio_dev->name = st->chip_info->name;
@@ -249,12 +388,31 @@ static int hmc425a_probe(struct platform_device *pdev) · 19 unmodified lines
249 indio_dev->info = &hmc425a_info;388 indio_dev->info = &hmc425a_info;
250 indio_dev->modes = INDIO_DIRECT_MODE;389 indio_dev->modes = INDIO_DIRECT_MODE;
251 390
252 /* Set default gain */391 if (st->chip_info->has_powerdown) {
253 hmc425a_write(indio_dev, st->gain);392 st->powerdown = true;
393 hmc425a_write(indio_dev, st->chip_info->powerdown_val);
394 } else {
395 /* Set default gain */
396 hmc425a_write(indio_dev, st->gain);
397 }
254 398
255 return devm_iio_device_register(&pdev->dev, indio_dev);399 return devm_iio_device_register(&pdev->dev, indio_dev);
256}400}
257 401
402/* Match table for of_platform binding */
403static const struct of_device_id hmc425a_of_match[] = {
404 { .compatible = "adi,hmc425a",
405 .data = &hmc425a_chip_info_tbl[ID_HMC425A]},
406 { .compatible = "adi,hmc540s",
407 .data = &hmc425a_chip_info_tbl[ID_HMC540S]},
408 { .compatible = "adi,adrf5740",
409 .data = &hmc425a_chip_info_tbl[ID_ADRF5740]},
410 { .compatible = "adi,ltc6373",
411 .data = &hmc425a_chip_info_tbl[ID_LTC6373]},
412 {}
413};
414MODULE_DEVICE_TABLE(of, hmc425a_of_match);
415
258static struct platform_driver hmc425a_driver = {416static struct platform_driver hmc425a_driver = {
259 .driver = {417 .driver = {
260 .name = KBUILD_MODNAME,418 .name = KBUILD_MODNAME,
drivers/iio/buffer/industrialio-buffer-dmaengine.c+6−5
@@ -159,7 +159,7 @@ static const struct iio_dev_attr *iio_dmaengine_buffer_attrs[] = { · 158 unmodified lines
159 * Once done using the buffer iio_dmaengine_buffer_free() should be used to159 * Once done using the buffer iio_dmaengine_buffer_free() should be used to
160 * release it.160 * release it.
161 */161 */
162static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,162struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
163 const char *channel)163 const char *channel)
164{164{
165 struct dmaengine_buffer *dmaengine_buffer;165 struct dmaengine_buffer *dmaengine_buffer;
@@ -210,6 +210,7 @@ err_free: · 44 unmodified lines
210 kfree(dmaengine_buffer);210 kfree(dmaengine_buffer);
211 return ERR_PTR(ret);211 return ERR_PTR(ret);
212}212}
213EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_alloc, IIO_DMAENGINE_BUFFER);
213 214
214/**215/**
215 * iio_dmaengine_buffer_free() - Free dmaengine buffer216 * iio_dmaengine_buffer_free() - Free dmaengine buffer
@@ -217,7 +218,7 @@ err_free: · 1 unmodified line
217 *218 *
218 * Frees a buffer previously allocated with iio_dmaengine_buffer_alloc().219 * Frees a buffer previously allocated with iio_dmaengine_buffer_alloc().
219 */220 */
220static void iio_dmaengine_buffer_free(struct iio_buffer *buffer)221void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
221{222{
222 struct dmaengine_buffer *dmaengine_buffer =223 struct dmaengine_buffer *dmaengine_buffer =
223 iio_buffer_to_dmaengine_buffer(buffer);224 iio_buffer_to_dmaengine_buffer(buffer);
@@ -227,6 +228,7 @@ static void iio_dmaengine_buffer_free(struct iio_buffer *buffer) · 3 unmodified lines
227 228
228 iio_buffer_put(buffer);229 iio_buffer_put(buffer);
229}230}
231EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, IIO_DMAENGINE_BUFFER);
230 232
231static void __devm_iio_dmaengine_buffer_free(void *buffer)233static void __devm_iio_dmaengine_buffer_free(void *buffer)
232{234{
@@ -279,8 +281,7 @@ int devm_iio_dmaengine_buffer_setup(struct device *dev, · 46 unmodified lines
279{281{
280 struct iio_buffer *buffer;282 struct iio_buffer *buffer;
281 283
282 buffer = devm_iio_dmaengine_buffer_alloc(indio_dev->dev.parent,284 buffer = devm_iio_dmaengine_buffer_alloc(dev, channel);
283 channel);
284 if (IS_ERR(buffer))285 if (IS_ERR(buffer))
285 return PTR_ERR(buffer);286 return PTR_ERR(buffer);
286 287
@@ -288,7 +289,7 @@ int devm_iio_dmaengine_buffer_setup(struct device *dev, · 1 unmodified line
288 289
289 return iio_device_attach_buffer(indio_dev, buffer);290 return iio_device_attach_buffer(indio_dev, buffer);
290}291}
291EXPORT_SYMBOL_GPL(devm_iio_dmaengine_buffer_setup);292EXPORT_SYMBOL_NS_GPL(devm_iio_dmaengine_buffer_setup, IIO_DMAENGINE_BUFFER);
292 293
293MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");294MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
294MODULE_DESCRIPTION("DMA buffer for the IIO framework");295MODULE_DESCRIPTION("DMA buffer for the IIO framework");
drivers/iio/common/inv_sensors/inv_sensors_timestamp.c+1−1
@@ -126,7 +126,7 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, · 125 unmodified lines
126 struct inv_sensors_timestamp_interval *it;126 struct inv_sensors_timestamp_interval *it;
127 int64_t delta, interval;127 int64_t delta, interval;
128 const uint32_t fifo_mult = fifo_period / ts->chip.clock_period;128 const uint32_t fifo_mult = fifo_period / ts->chip.clock_period;
129 uint32_t period = ts->period;129 uint32_t period;
130 bool valid = false;130 bool valid = false;
131 131
132 if (fifo_nb == 0)132 if (fifo_nb == 0)
drivers/iio/dac/mcp4821.c+1−1
@@ -17,7 +17,7 @@ · 16 unmodified lines
17 */17 */
18 18
19#include <linux/module.h>19#include <linux/module.h>
20#include <linux/of.h>20#include <linux/mod_devicetable.h>
21#include <linux/spi/spi.h>21#include <linux/spi/spi.h>
22 22
23#include <linux/iio/iio.h>23#include <linux/iio/iio.h>
drivers/iio/dummy/iio_dummy_evgen.c+0−2
@@ -31,8 +31,6 @@ · 30 unmodified lines
31 * @regs: irq regs we are faking31 * @regs: irq regs we are faking
32 * @lock: protect the evgen state32 * @lock: protect the evgen state
33 * @inuse: mask of which irqs are connected33 * @inuse: mask of which irqs are connected
34 * @irq_sim: interrupt simulator
35 * @base: base of irq range
36 * @irq_sim_domain: irq simulator domain34 * @irq_sim_domain: irq simulator domain
37 */35 */
38struct iio_dummy_eventgen {36struct iio_dummy_eventgen {
drivers/iio/dummy/iio_simple_dummy.c+89−96
@@ -283,65 +283,63 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, · 282 unmodified lines
283 long mask)283 long mask)
284{284{
285 struct iio_dummy_state *st = iio_priv(indio_dev);285 struct iio_dummy_state *st = iio_priv(indio_dev);
286 int ret = -EINVAL;
287 286
288 mutex_lock(&st->lock);
289 switch (mask) {287 switch (mask) {
290 case IIO_CHAN_INFO_RAW: /* magic value - channel value read */288 case IIO_CHAN_INFO_RAW: /* magic value - channel value read */
291 switch (chan->type) {289 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
292 case IIO_VOLTAGE:290 guard(mutex)(&st->lock);
293 if (chan->output) {291 switch (chan->type) {
294 /* Set integer part to cached value */292 case IIO_VOLTAGE:
295 *val = st->dac_val;293 if (chan->output) {
296 ret = IIO_VAL_INT;294 /* Set integer part to cached value */
297 } else if (chan->differential) {295 *val = st->dac_val;
298 if (chan->channel == 1)296 return IIO_VAL_INT;
299 *val = st->differential_adc_val[0];297 } else if (chan->differential) {
300 else298 if (chan->channel == 1)
301 *val = st->differential_adc_val[1];299 *val = st->differential_adc_val[0];
302 ret = IIO_VAL_INT;300 else
303 } else {301 *val = st->differential_adc_val[1];
304 *val = st->single_ended_adc_val;302 return IIO_VAL_INT;
305 ret = IIO_VAL_INT;303 } else {
304 *val = st->single_ended_adc_val;
305 return IIO_VAL_INT;
306 }
307
308 case IIO_ACCEL:
309 *val = st->accel_val;
310 return IIO_VAL_INT;
311 default:
312 return -EINVAL;
306 }313 }
307 break;
308 case IIO_ACCEL:
309 *val = st->accel_val;
310 ret = IIO_VAL_INT;
311 break;
312 default:
313 break;
314 }314 }
315 break;315 unreachable();
316 case IIO_CHAN_INFO_PROCESSED:316 case IIO_CHAN_INFO_PROCESSED:
317 switch (chan->type) {317 iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
318 case IIO_STEPS:318 guard(mutex)(&st->lock);
319 *val = st->steps;319 switch (chan->type) {
320 ret = IIO_VAL_INT;320 case IIO_STEPS:
321 break;321 *val = st->steps;
322 case IIO_ACTIVITY:322 return IIO_VAL_INT;
323 switch (chan->channel2) {323 case IIO_ACTIVITY:
324 case IIO_MOD_RUNNING:324 switch (chan->channel2) {
325 *val = st->activity_running;325 case IIO_MOD_RUNNING:
326 ret = IIO_VAL_INT;326 *val = st->activity_running;
327 break;327 return IIO_VAL_INT;
328 case IIO_MOD_WALKING:328 case IIO_MOD_WALKING:
329 *val = st->activity_walking;329 *val = st->activity_walking;
330 ret = IIO_VAL_INT;330 return IIO_VAL_INT;
331 break;331 default:
332 return -EINVAL;
333 }
332 default:334 default:
333 break;335 return -EINVAL;
334 }336 }
335 break;
336 default:
337 break;
338 }337 }
339 break;338 unreachable();
340 case IIO_CHAN_INFO_OFFSET:339 case IIO_CHAN_INFO_OFFSET:
341 /* only single ended adc -> 7 */340 /* only single ended adc -> 7 */
342 *val = 7;341 *val = 7;
343 ret = IIO_VAL_INT;342 return IIO_VAL_INT;
344 break;
345 case IIO_CHAN_INFO_SCALE:343 case IIO_CHAN_INFO_SCALE:
346 switch (chan->type) {344 switch (chan->type) {
347 case IIO_VOLTAGE:345 case IIO_VOLTAGE:
@@ -350,60 +348,57 @@ static int iio_dummy_read_raw(struct iio_dev *indio_dev, · 2 unmodified lines
350 /* only single ended adc -> 0.001333 */348 /* only single ended adc -> 0.001333 */
351 *val = 0;349 *val = 0;
352 *val2 = 1333;350 *val2 = 1333;
353 ret = IIO_VAL_INT_PLUS_MICRO;351 return IIO_VAL_INT_PLUS_MICRO;
354 break;
355 case 1:352 case 1:
356 /* all differential adc -> 0.000001344 */353 /* all differential adc -> 0.000001344 */
357 *val = 0;354 *val = 0;
358 *val2 = 1344;355 *val2 = 1344;
359 ret = IIO_VAL_INT_PLUS_NANO;356 return IIO_VAL_INT_PLUS_NANO;
357 default:
358 return -EINVAL;
360 }359 }
361 break;
362 default:360 default:
363 break;361 return -EINVAL;
364 }362 }
365 break;363 case IIO_CHAN_INFO_CALIBBIAS: {
366 case IIO_CHAN_INFO_CALIBBIAS:364 guard(mutex)(&st->lock);
367 /* only the acceleration axis - read from cache */365 /* only the acceleration axis - read from cache */
368 *val = st->accel_calibbias;366 *val = st->accel_calibbias;
369 ret = IIO_VAL_INT;367 return IIO_VAL_INT;
370 break;368 }
371 case IIO_CHAN_INFO_CALIBSCALE:369 case IIO_CHAN_INFO_CALIBSCALE: {
370 guard(mutex)(&st->lock);
372 *val = st->accel_calibscale->val;371 *val = st->accel_calibscale->val;
373 *val2 = st->accel_calibscale->val2;372 *val2 = st->accel_calibscale->val2;
374 ret = IIO_VAL_INT_PLUS_MICRO;373 return IIO_VAL_INT_PLUS_MICRO;
375 break;374 }
376 case IIO_CHAN_INFO_SAMP_FREQ:375 case IIO_CHAN_INFO_SAMP_FREQ:
377 *val = 3;376 *val = 3;
378 *val2 = 33;377 *val2 = 33;
379 ret = IIO_VAL_INT_PLUS_NANO;378 return IIO_VAL_INT_PLUS_NANO;
380 break;379 case IIO_CHAN_INFO_ENABLE: {
381 case IIO_CHAN_INFO_ENABLE:380 guard(mutex)(&st->lock);
382 switch (chan->type) {381 switch (chan->type) {
383 case IIO_STEPS:382 case IIO_STEPS:
384 *val = st->steps_enabled;383 *val = st->steps_enabled;
385 ret = IIO_VAL_INT;384 return IIO_VAL_INT;
386 break;
387 default:385 default:
388 break;386 return -EINVAL;
389 }387 }
390 break;388 }
391 case IIO_CHAN_INFO_CALIBHEIGHT:389 case IIO_CHAN_INFO_CALIBHEIGHT: {
390 guard(mutex)(&st->lock);
392 switch (chan->type) {391 switch (chan->type) {
393 case IIO_STEPS:392 case IIO_STEPS:
394 *val = st->height;393 *val = st->height;
395 ret = IIO_VAL_INT;394 return IIO_VAL_INT;
396 break;
397 default:395 default:
398 break;396 return -EINVAL;
399 }397 }
400 break;398 }
401
402 default:399 default:
403 break;400 return -EINVAL;
404 }401 }
405 mutex_unlock(&st->lock);
406 return ret;
407}402}
408 403
409/**404/**
@@ -426,7 +421,6 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, · 16 unmodified lines
426 long mask)421 long mask)
427{422{
428 int i;423 int i;
429 int ret = 0;
430 struct iio_dummy_state *st = iio_priv(indio_dev);424 struct iio_dummy_state *st = iio_priv(indio_dev);
431 425
432 switch (mask) {426 switch (mask) {
@@ -436,10 +430,10 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, · 3 unmodified lines
436 if (chan->output == 0)430 if (chan->output == 0)
437 return -EINVAL;431 return -EINVAL;
438 432
439 /* Locking not required as writing single value */433 scoped_guard(mutex, &st->lock) {
440 mutex_lock(&st->lock);434 /* Locking not required as writing single value */
441 st->dac_val = val;435 st->dac_val = val;
442 mutex_unlock(&st->lock);436 }
443 return 0;437 return 0;
444 default:438 default:
445 return -EINVAL;439 return -EINVAL;
@@ -447,9 +441,9 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, · 1 unmodified line
447 case IIO_CHAN_INFO_PROCESSED:441 case IIO_CHAN_INFO_PROCESSED:
448 switch (chan->type) {442 switch (chan->type) {
449 case IIO_STEPS:443 case IIO_STEPS:
450 mutex_lock(&st->lock);444 scoped_guard(mutex, &st->lock) {
451 st->steps = val;445 st->steps = val;
452 mutex_unlock(&st->lock);446 }
453 return 0;447 return 0;
454 case IIO_ACTIVITY:448 case IIO_ACTIVITY:
455 if (val < 0)449 if (val < 0)
@@ -470,30 +464,29 @@ static int iio_dummy_write_raw(struct iio_dev *indio_dev, · 14 unmodified lines
470 default:464 default:
471 return -EINVAL;465 return -EINVAL;
472 }466 }
473 case IIO_CHAN_INFO_CALIBSCALE:467 case IIO_CHAN_INFO_CALIBSCALE: {
474 mutex_lock(&st->lock);468 guard(mutex)(&st->lock);
475 /* Compare against table - hard matching here */469 /* Compare against table - hard matching here */
476 for (i = 0; i < ARRAY_SIZE(dummy_scales); i++)470 for (i = 0; i < ARRAY_SIZE(dummy_scales); i++)
477 if (val == dummy_scales[i].val &&471 if (val == dummy_scales[i].val &&
478 val2 == dummy_scales[i].val2)472 val2 == dummy_scales[i].val2)
479 break;473 break;
480 if (i == ARRAY_SIZE(dummy_scales))474 if (i == ARRAY_SIZE(dummy_scales))
481 ret = -EINVAL;475 return -EINVAL;
482 else476 st->accel_calibscale = &dummy_scales[i];
483 st->accel_calibscale = &dummy_scales[i];477 return 0;
484 mutex_unlock(&st->lock);478 }
485 return ret;
486 case IIO_CHAN_INFO_CALIBBIAS:479 case IIO_CHAN_INFO_CALIBBIAS:
487 mutex_lock(&st->lock);480 scoped_guard(mutex, &st->lock) {
488 st->accel_calibbias = val;481 st->accel_calibbias = val;
489 mutex_unlock(&st->lock);482 }
490 return 0;483 return 0;
491 case IIO_CHAN_INFO_ENABLE:484 case IIO_CHAN_INFO_ENABLE:
492 switch (chan->type) {485 switch (chan->type) {
493 case IIO_STEPS:486 case IIO_STEPS:
494 mutex_lock(&st->lock);487 scoped_guard(mutex, &st->lock) {
495 st->steps_enabled = val;488 st->steps_enabled = val;
496 mutex_unlock(&st->lock);489 }
497 return 0;490 return 0;
498 default:491 default:
499 return -EINVAL;492 return -EINVAL;
drivers/iio/frequency/Kconfig+10−0
@@ -60,6 +60,16 @@ config ADF4377 · 59 unmodified lines
60 To compile this driver as a module, choose M here: the60 To compile this driver as a module, choose M here: the
61 module will be called adf4377.61 module will be called adf4377.
62 62
63config ADMFM2000
64 tristate "Analog Devices ADMFM2000 Dual Microwave Down Converter"
65 depends on GPIOLIB
66 help
67 Say yes here to build support for Analog Devices ADMFM2000 Dual
68 Microwave Down Converter.
69
70 To compile this driver as a module, choose M here: the
71 module will be called admfm2000.
72
63config ADMV101373config ADMV1013
64 tristate "Analog Devices ADMV1013 Microwave Upconverter"74 tristate "Analog Devices ADMV1013 Microwave Upconverter"
65 depends on SPI && COMMON_CLK75 depends on SPI && COMMON_CLK
drivers/iio/frequency/Makefile+1−0
@@ -8,6 +8,7 @@ obj-$(CONFIG_AD9523) += ad9523.o · 7 unmodified lines
8obj-$(CONFIG_ADF4350) += adf4350.o8obj-$(CONFIG_ADF4350) += adf4350.o
9obj-$(CONFIG_ADF4371) += adf4371.o9obj-$(CONFIG_ADF4371) += adf4371.o
10obj-$(CONFIG_ADF4377) += adf4377.o10obj-$(CONFIG_ADF4377) += adf4377.o
11obj-$(CONFIG_ADMFM2000) += admfm2000.o
11obj-$(CONFIG_ADMV1013) += admv1013.o12obj-$(CONFIG_ADMV1013) += admv1013.o
12obj-$(CONFIG_ADMV1014) += admv1014.o13obj-$(CONFIG_ADMV1014) += admv1014.o
13obj-$(CONFIG_ADMV4420) += admv4420.o14obj-$(CONFIG_ADMV4420) += admv4420.o
drivers/iio/frequency/admfm2000.c+282−0
@@ -0,0 +1,282 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * ADMFM2000 Dual Microwave Down Converter
4 *
5 * Copyright 2024 Analog Devices Inc.
6 */
7
8#include <linux/device.h>
9#include <linux/err.h>
10#include <linux/gpio/consumer.h>
11#include <linux/iio/iio.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/mod_devicetable.h>
15#include <linux/platform_device.h>
16#include <linux/property.h>
17
18#define ADMFM2000_MIXER_MODE 0
19#define ADMFM2000_DIRECT_IF_MODE 1
20#define ADMFM2000_DSA_GPIOS 5
21#define ADMFM2000_MODE_GPIOS 2
22#define ADMFM2000_MAX_GAIN 0
23#define ADMFM2000_MIN_GAIN -31000
24#define ADMFM2000_DEFAULT_GAIN -0x20
25
26struct admfm2000_state {
27 struct mutex lock; /* protect sensor state */
28 struct gpio_desc *sw1_ch[2];
29 struct gpio_desc *sw2_ch[2];
30 struct gpio_desc *dsa1_gpios[5];
31 struct gpio_desc *dsa2_gpios[5];
32 u32 gain[2];
33};
34
35static int admfm2000_mode(struct iio_dev *indio_dev, u32 chan, u32 mode)
36{
37 struct admfm2000_state *st = iio_priv(indio_dev);
38 int i;
39
40 switch (mode) {
41 case ADMFM2000_MIXER_MODE:
42 for (i = 0; i < ADMFM2000_MODE_GPIOS; i++) {
43 gpiod_set_value_cansleep(st->sw1_ch[i], (chan == 0) ? 1 : 0);
44 gpiod_set_value_cansleep(st->sw2_ch[i], (chan == 0) ? 0 : 1);
45 }
46 return 0;
47 case ADMFM2000_DIRECT_IF_MODE:
48 for (i = 0; i < ADMFM2000_MODE_GPIOS; i++) {
49 gpiod_set_value_cansleep(st->sw1_ch[i], (chan == 0) ? 0 : 1);
50 gpiod_set_value_cansleep(st->sw2_ch[i], (chan == 0) ? 1 : 0);
51 }
52 return 0;
53 default:
54 return -EINVAL;
55 }
56}
57
58static int admfm2000_attenuation(struct iio_dev *indio_dev, u32 chan, u32 value)
59{
60 struct admfm2000_state *st = iio_priv(indio_dev);
61 int i;
62
63 switch (chan) {
64 case 0:
65 for (i = 0; i < ADMFM2000_DSA_GPIOS; i++)
66 gpiod_set_value_cansleep(st->dsa1_gpios[i], value & (1 << i));
67 return 0;
68 case 1:
69 for (i = 0; i < ADMFM2000_DSA_GPIOS; i++)
70 gpiod_set_value_cansleep(st->dsa2_gpios[i], value & (1 << i));
71 return 0;
72 default:
73 return -EINVAL;
74 }
75}
76
77static int admfm2000_read_raw(struct iio_dev *indio_dev,
78 struct iio_chan_spec const *chan, int *val,
79 int *val2, long mask)
80{
81 struct admfm2000_state *st = iio_priv(indio_dev);
82 int gain;
83
84 switch (mask) {
85 case IIO_CHAN_INFO_HARDWAREGAIN:
86 mutex_lock(&st->lock);
87 gain = ~(st->gain[chan->channel]) * -1000;
88 *val = gain / 1000;
89 *val2 = (gain % 1000) * 1000;
90 mutex_unlock(&st->lock);
91
92 return IIO_VAL_INT_PLUS_MICRO_DB;
93 default:
94 return -EINVAL;
95 }
96}
97
98static int admfm2000_write_raw(struct iio_dev *indio_dev,
99 struct iio_chan_spec const *chan, int val,
100 int val2, long mask)
101{
102 struct admfm2000_state *st = iio_priv(indio_dev);
103 int gain, ret;
104
105 if (val < 0)
106 gain = (val * 1000) - (val2 / 1000);
107 else
108 gain = (val * 1000) + (val2 / 1000);
109
110 if (gain > ADMFM2000_MAX_GAIN || gain < ADMFM2000_MIN_GAIN)
111 return -EINVAL;
112
113 switch (mask) {
114 case IIO_CHAN_INFO_HARDWAREGAIN:
115 mutex_lock(&st->lock);
116 st->gain[chan->channel] = ~((abs(gain) / 1000) & 0x1F);
117
118 ret = admfm2000_attenuation(indio_dev, chan->channel,
119 st->gain[chan->channel]);
120 mutex_unlock(&st->lock);
121 return ret;
122 default:
123 return -EINVAL;
124 }
125}
126
127static int admfm2000_write_raw_get_fmt(struct iio_dev *indio_dev,
128 struct iio_chan_spec const *chan,
129 long mask)
130{
131 switch (mask) {
132 case IIO_CHAN_INFO_HARDWAREGAIN:
133 return IIO_VAL_INT_PLUS_MICRO_DB;
134 default:
135 return -EINVAL;
136 }
137}
138
139static const struct iio_info admfm2000_info = {
140 .read_raw = &admfm2000_read_raw,
141 .write_raw = &admfm2000_write_raw,
142 .write_raw_get_fmt = &admfm2000_write_raw_get_fmt,
143};
144
145#define ADMFM2000_CHAN(_channel) { \
146 .type = IIO_VOLTAGE, \
147 .output = 1, \
148 .indexed = 1, \
149 .channel = _channel, \
150 .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN), \
151}
152
153static const struct iio_chan_spec admfm2000_channels[] = {
154 ADMFM2000_CHAN(0),
155 ADMFM2000_CHAN(1),
156};
157
158static int admfm2000_channel_config(struct admfm2000_state *st,
159 struct iio_dev *indio_dev)
160{
161 struct platform_device *pdev = to_platform_device(indio_dev->dev.parent);
162 struct device *dev = &pdev->dev;
163 struct fwnode_handle *child;
164 struct gpio_desc **dsa;
165 struct gpio_desc **sw;
166 int ret, i;
167 bool mode;
168 u32 reg;
169
170 device_for_each_child_node(dev, child) {
171 ret = fwnode_property_read_u32(child, "reg", &reg);
172 if (ret) {
173 fwnode_handle_put(child);
174 return dev_err_probe(dev, ret,
175 "Failed to get reg property\n");
176 }
177
178 if (reg >= indio_dev->num_channels) {
179 fwnode_handle_put(child);
180 return dev_err_probe(dev, -EINVAL, "reg bigger than: %d\n",
181 indio_dev->num_channels);
182 }
183
184 if (fwnode_property_present(child, "adi,mixer-mode"))
185 mode = ADMFM2000_MIXER_MODE;
186 else
187 mode = ADMFM2000_DIRECT_IF_MODE;
188
189 switch (reg) {
190 case 0:
191 sw = st->sw1_ch;
192 dsa = st->dsa1_gpios;
193 break;
194 case 1:
195 sw = st->sw2_ch;
196 dsa = st->dsa2_gpios;
197 break;
198 default:
199 fwnode_handle_put(child);
200 return -EINVAL;
201 }
202
203 for (i = 0; i < ADMFM2000_MODE_GPIOS; i++) {
204 sw[i] = devm_fwnode_gpiod_get_index(dev, child, "switch",
205 i, GPIOD_OUT_LOW, NULL);
206 if (IS_ERR(sw[i])) {
207 fwnode_handle_put(child);
208 return dev_err_probe(dev, PTR_ERR(sw[i]),
209 "Failed to get gpios\n");
210 }
211 }
212
213 for (i = 0; i < ADMFM2000_DSA_GPIOS; i++) {
214 dsa[i] = devm_fwnode_gpiod_get_index(dev, child,
215 "attenuation", i,
216 GPIOD_OUT_LOW, NULL);
217 if (IS_ERR(dsa[i])) {
218 fwnode_handle_put(child);
219 return dev_err_probe(dev, PTR_ERR(dsa[i]),
220 "Failed to get gpios\n");
221 }
222 }
223
224 ret = admfm2000_mode(indio_dev, reg, mode);
225 if (ret) {
226 fwnode_handle_put(child);
227 return ret;
228 }
229 }
230
231 return 0;
232}
233
234static int admfm2000_probe(struct platform_device *pdev)
235{
236 struct device *dev = &pdev->dev;
237 struct admfm2000_state *st;
238 struct iio_dev *indio_dev;
239 int ret;
240
241 indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
242 if (!indio_dev)
243 return -ENOMEM;
244
245 st = iio_priv(indio_dev);
246
247 indio_dev->name = "admfm2000";
248 indio_dev->num_channels = ARRAY_SIZE(admfm2000_channels);
249 indio_dev->channels = admfm2000_channels;
250 indio_dev->info = &admfm2000_info;
251 indio_dev->modes = INDIO_DIRECT_MODE;
252
253 st->gain[0] = ADMFM2000_DEFAULT_GAIN;
254 st->gain[1] = ADMFM2000_DEFAULT_GAIN;
255
256 mutex_init(&st->lock);
257
258 ret = admfm2000_channel_config(st, indio_dev);
259 if (ret)
260 return ret;
261
262 return devm_iio_device_register(dev, indio_dev);
263}
264
265static const struct of_device_id admfm2000_of_match[] = {
266 { .compatible = "adi,admfm2000" },
267 { }
268};
269MODULE_DEVICE_TABLE(of, admfm2000_of_match);
270
271static struct platform_driver admfm2000_driver = {
272 .driver = {
273 .name = "admfm2000",
274 .of_match_table = admfm2000_of_match,
275 },
276 .probe = admfm2000_probe,
277};
278module_platform_driver(admfm2000_driver);
279
280MODULE_AUTHOR("Kim Seer Paller <kimseer.paller@analog.com>");
281MODULE_DESCRIPTION("ADMFM2000 Dual Microwave Down Converter");
282MODULE_LICENSE("GPL");
drivers/iio/gyro/bmg160_i2c.c+2−2
@@ -3,7 +3,7 @@ · 2 unmodified lines
3#include <linux/regmap.h>3#include <linux/regmap.h>
4#include <linux/iio/iio.h>4#include <linux/iio/iio.h>
5#include <linux/module.h>5#include <linux/module.h>
6#include <linux/acpi.h>6#include <linux/mod_devicetable.h>
7 7
8#include "bmg160.h"8#include "bmg160.h"
9 9
@@ -66,7 +66,7 @@ MODULE_DEVICE_TABLE(of, bmg160_of_match); · 56 unmodified lines
66static struct i2c_driver bmg160_i2c_driver = {66static struct i2c_driver bmg160_i2c_driver = {
67 .driver = {67 .driver = {
68 .name = "bmg160_i2c",68 .name = "bmg160_i2c",
69 .acpi_match_table = ACPI_PTR(bmg160_acpi_match),69 .acpi_match_table = bmg160_acpi_match,
70 .of_match_table = bmg160_of_match,70 .of_match_table = bmg160_of_match,
71 .pm = &bmg160_pm_ops,71 .pm = &bmg160_pm_ops,
72 },72 },
drivers/iio/health/afe4403.c+24−41
@@ -346,6 +346,13 @@ err: · 345 unmodified lines
346 return IRQ_HANDLED;346 return IRQ_HANDLED;
347}347}
348 348
349static void afe4403_regulator_disable(void *data)
350{
351 struct regulator *regulator = data;
352
353 regulator_disable(regulator);
354}
355
349#define AFE4403_TIMING_PAIRS \356#define AFE4403_TIMING_PAIRS \
350 { AFE440X_LED2STC, 0x000050 }, \357 { AFE440X_LED2STC, 0x000050 }, \
351 { AFE440X_LED2ENDC, 0x0003e7 }, \358 { AFE440X_LED2ENDC, 0x0003e7 }, \
@@ -495,19 +502,24 @@ static int afe4403_probe(struct spi_device *spi) · 143 unmodified lines
495 dev_err(afe->dev, "Unable to enable regulator\n");502 dev_err(afe->dev, "Unable to enable regulator\n");
496 return ret;503 return ret;
497 }504 }
505 ret = devm_add_action_or_reset(afe->dev, afe4403_regulator_disable, afe->regulator);
506 if (ret) {
507 dev_err(afe->dev, "Unable to add regulator disable action\n");
508 return ret;
509 }
498 510
499 ret = regmap_write(afe->regmap, AFE440X_CONTROL0,511 ret = regmap_write(afe->regmap, AFE440X_CONTROL0,
500 AFE440X_CONTROL0_SW_RESET);512 AFE440X_CONTROL0_SW_RESET);
501 if (ret) {513 if (ret) {
502 dev_err(afe->dev, "Unable to reset device\n");514 dev_err(afe->dev, "Unable to reset device\n");
503 goto err_disable_reg;515 return ret;
504 }516 }
505 517
506 ret = regmap_multi_reg_write(afe->regmap, afe4403_reg_sequences,518 ret = regmap_multi_reg_write(afe->regmap, afe4403_reg_sequences,
507 ARRAY_SIZE(afe4403_reg_sequences));519 ARRAY_SIZE(afe4403_reg_sequences));
508 if (ret) {520 if (ret) {
509 dev_err(afe->dev, "Unable to set register defaults\n");521 dev_err(afe->dev, "Unable to set register defaults\n");
510 goto err_disable_reg;522 return ret;
511 }523 }
512 524
513 indio_dev->modes = INDIO_DIRECT_MODE;525 indio_dev->modes = INDIO_DIRECT_MODE;
@@ -523,16 +535,15 @@ static int afe4403_probe(struct spi_device *spi) · 9 unmodified lines
523 iio_device_id(indio_dev));535 iio_device_id(indio_dev));
524 if (!afe->trig) {536 if (!afe->trig) {
525 dev_err(afe->dev, "Unable to allocate IIO trigger\n");537 dev_err(afe->dev, "Unable to allocate IIO trigger\n");
526 ret = -ENOMEM;538 return -ENOMEM;
527 goto err_disable_reg;
528 }539 }
529 540
530 iio_trigger_set_drvdata(afe->trig, indio_dev);541 iio_trigger_set_drvdata(afe->trig, indio_dev);
531 542
532 ret = iio_trigger_register(afe->trig);543 ret = devm_iio_trigger_register(afe->dev, afe->trig);
533 if (ret) {544 if (ret) {
534 dev_err(afe->dev, "Unable to register IIO trigger\n");545 dev_err(afe->dev, "Unable to register IIO trigger\n");
535 goto err_disable_reg;546 return ret;
536 }547 }
537 548
538 ret = devm_request_threaded_irq(afe->dev, afe->irq,549 ret = devm_request_threaded_irq(afe->dev, afe->irq,
@@ -542,52 +553,25 @@ static int afe4403_probe(struct spi_device *spi) · 3 unmodified lines
542 afe->trig);553 afe->trig);
543 if (ret) {554 if (ret) {
544 dev_err(afe->dev, "Unable to request IRQ\n");555 dev_err(afe->dev, "Unable to request IRQ\n");
545 goto err_trig;556 return ret;
546 }557 }
547 }558 }
548 559
549 ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,560 ret = devm_iio_triggered_buffer_setup(afe->dev, indio_dev,
550 afe4403_trigger_handler, NULL);561 &iio_pollfunc_store_time,
562 afe4403_trigger_handler, NULL);
551 if (ret) {563 if (ret) {
552 dev_err(afe->dev, "Unable to setup buffer\n");564 dev_err(afe->dev, "Unable to setup buffer\n");
553 goto err_trig;565 return ret;
554 }566 }
555 567
556 ret = iio_device_register(indio_dev);568 ret = devm_iio_device_register(afe->dev, indio_dev);
557 if (ret) {569 if (ret) {
558 dev_err(afe->dev, "Unable to register IIO device\n");570 dev_err(afe->dev, "Unable to register IIO device\n");
559 goto err_buff;571 return ret;
560 }572 }
561 573
562 return 0;574 return 0;
563
564err_buff:
565 iio_triggered_buffer_cleanup(indio_dev);
566err_trig:
567 if (afe->irq > 0)
568 iio_trigger_unregister(afe->trig);
569err_disable_reg:
570 regulator_disable(afe->regulator);
571
572 return ret;
573}
574
575static void afe4403_remove(struct spi_device *spi)
576{
577 struct iio_dev *indio_dev = spi_get_drvdata(spi);
578 struct afe4403_data *afe = iio_priv(indio_dev);
579 int ret;
580
581 iio_device_unregister(indio_dev);
582
583 iio_triggered_buffer_cleanup(indio_dev);
584
585 if (afe->irq > 0)
586 iio_trigger_unregister(afe->trig);
587
588 ret = regulator_disable(afe->regulator);
589 if (ret)
590 dev_warn(afe->dev, "Unable to disable regulator\n");
591}575}
592 576
593static const struct spi_device_id afe4403_ids[] = {577static const struct spi_device_id afe4403_ids[] = {
@@ -603,7 +587,6 @@ static struct spi_driver afe4403_spi_driver = { · 9 unmodified lines
603 .pm = pm_sleep_ptr(&afe4403_pm_ops),587 .pm = pm_sleep_ptr(&afe4403_pm_ops),
604 },588 },
605 .probe = afe4403_probe,589 .probe = afe4403_probe,
606 .remove = afe4403_remove,
607 .id_table = afe4403_ids,590 .id_table = afe4403_ids,
608};591};
609module_spi_driver(afe4403_spi_driver);592module_spi_driver(afe4403_spi_driver);
drivers/iio/health/afe4404.c+24−41
@@ -349,6 +349,13 @@ err: · 348 unmodified lines
349 return IRQ_HANDLED;349 return IRQ_HANDLED;
350}350}
351 351
352static void afe4404_regulator_disable(void *data)
353{
354 struct regulator *regulator = data;
355
356 regulator_disable(regulator);
357}
358
352/* Default timings from data-sheet */359/* Default timings from data-sheet */
353#define AFE4404_TIMING_PAIRS \360#define AFE4404_TIMING_PAIRS \
354 { AFE440X_PRPCOUNT, 39999 }, \361 { AFE440X_PRPCOUNT, 39999 }, \
@@ -502,19 +509,24 @@ static int afe4404_probe(struct i2c_client *client) · 147 unmodified lines
502 dev_err(afe->dev, "Unable to enable regulator\n");509 dev_err(afe->dev, "Unable to enable regulator\n");
503 return ret;510 return ret;
504 }511 }
512 ret = devm_add_action_or_reset(afe->dev, afe4404_regulator_disable, afe->regulator);
513 if (ret) {
514 dev_err(afe->dev, "Unable to enable regulator\n");
515 return ret;
516 }
505 517
506 ret = regmap_write(afe->regmap, AFE440X_CONTROL0,518 ret = regmap_write(afe->regmap, AFE440X_CONTROL0,
507 AFE440X_CONTROL0_SW_RESET);519 AFE440X_CONTROL0_SW_RESET);
508 if (ret) {520 if (ret) {
509 dev_err(afe->dev, "Unable to reset device\n");521 dev_err(afe->dev, "Unable to reset device\n");
510 goto disable_reg;522 return ret;
511 }523 }
512 524
513 ret = regmap_multi_reg_write(afe->regmap, afe4404_reg_sequences,525 ret = regmap_multi_reg_write(afe->regmap, afe4404_reg_sequences,
514 ARRAY_SIZE(afe4404_reg_sequences));526 ARRAY_SIZE(afe4404_reg_sequences));
515 if (ret) {527 if (ret) {
516 dev_err(afe->dev, "Unable to set register defaults\n");528 dev_err(afe->dev, "Unable to set register defaults\n");
517 goto disable_reg;529 return ret;
518 }530 }
519 531
520 indio_dev->modes = INDIO_DIRECT_MODE;532 indio_dev->modes = INDIO_DIRECT_MODE;
@@ -530,16 +542,15 @@ static int afe4404_probe(struct i2c_client *client) · 9 unmodified lines
530 iio_device_id(indio_dev));542 iio_device_id(indio_dev));
531 if (!afe->trig) {543 if (!afe->trig) {
532 dev_err(afe->dev, "Unable to allocate IIO trigger\n");544 dev_err(afe->dev, "Unable to allocate IIO trigger\n");
533 ret = -ENOMEM;545 return -ENOMEM;
534 goto disable_reg;
535 }546 }
536 547
537 iio_trigger_set_drvdata(afe->trig, indio_dev);548 iio_trigger_set_drvdata(afe->trig, indio_dev);
538 549
539 ret = iio_trigger_register(afe->trig);550 ret = devm_iio_trigger_register(afe->dev, afe->trig);
540 if (ret) {551 if (ret) {
541 dev_err(afe->dev, "Unable to register IIO trigger\n");552 dev_err(afe->dev, "Unable to register IIO trigger\n");
542 goto disable_reg;553 return ret;
543 }554 }
544 555
545 ret = devm_request_threaded_irq(afe->dev, afe->irq,556 ret = devm_request_threaded_irq(afe->dev, afe->irq,
@@ -549,52 +560,25 @@ static int afe4404_probe(struct i2c_client *client) · 3 unmodified lines
549 afe->trig);560 afe->trig);
550 if (ret) {561 if (ret) {
551 dev_err(afe->dev, "Unable to request IRQ\n");562 dev_err(afe->dev, "Unable to request IRQ\n");
552 goto disable_reg;563 return ret;
553 }564 }
554 }565 }
555 566
556 ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,567 ret = devm_iio_triggered_buffer_setup(afe->dev, indio_dev,
557 afe4404_trigger_handler, NULL);568 &iio_pollfunc_store_time,
569 afe4404_trigger_handler, NULL);
558 if (ret) {570 if (ret) {
559 dev_err(afe->dev, "Unable to setup buffer\n");571 dev_err(afe->dev, "Unable to setup buffer\n");
560 goto unregister_trigger;572 return ret;
561 }573 }
562 574
563 ret = iio_device_register(indio_dev);575 ret = devm_iio_device_register(afe->dev, indio_dev);
564 if (ret) {576 if (ret) {
565 dev_err(afe->dev, "Unable to register IIO device\n");577 dev_err(afe->dev, "Unable to register IIO device\n");
566 goto unregister_triggered_buffer;578 return ret;
567 }579 }
568 580
569 return 0;581 return 0;
570
571unregister_triggered_buffer:
572 iio_triggered_buffer_cleanup(indio_dev);
573unregister_trigger:
574 if (afe->irq > 0)
575 iio_trigger_unregister(afe->trig);
576disable_reg:
577 regulator_disable(afe->regulator);
578
579 return ret;
580}
581
582static void afe4404_remove(struct i2c_client *client)
583{
584 struct iio_dev *indio_dev = i2c_get_clientdata(client);
585 struct afe4404_data *afe = iio_priv(indio_dev);
586 int ret;
587
588 iio_device_unregister(indio_dev);
589
590 iio_triggered_buffer_cleanup(indio_dev);
591
592 if (afe->irq > 0)
593 iio_trigger_unregister(afe->trig);
594
595 ret = regulator_disable(afe->regulator);
596 if (ret)
597 dev_err(afe->dev, "Unable to disable regulator\n");
598}582}
599 583
600static const struct i2c_device_id afe4404_ids[] = {584static const struct i2c_device_id afe4404_ids[] = {
@@ -610,7 +594,6 @@ static struct i2c_driver afe4404_i2c_driver = { · 9 unmodified lines
610 .pm = pm_sleep_ptr(&afe4404_pm_ops),594 .pm = pm_sleep_ptr(&afe4404_pm_ops),
611 },595 },
612 .probe = afe4404_probe,596 .probe = afe4404_probe,
613 .remove = afe4404_remove,
614 .id_table = afe4404_ids,597 .id_table = afe4404_ids,
615};598};
616module_i2c_driver(afe4404_i2c_driver);599module_i2c_driver(afe4404_i2c_driver);
drivers/iio/humidity/hdc3020.c+309−136
@@ -5,41 +5,66 @@ · 4 unmodified lines
5 *5 *
6 * Copyright (C) 20236 * Copyright (C) 2023
7 *7 *
8 * Copyright (C) 2024 Liebherr-Electronics and Drives GmbH
9 *
8 * Datasheet: https://www.ti.com/lit/ds/symlink/hdc3020.pdf10 * Datasheet: https://www.ti.com/lit/ds/symlink/hdc3020.pdf
9 */11 */
10 12
13#include <linux/bitfield.h>
11#include <linux/bitops.h>14#include <linux/bitops.h>
12#include <linux/cleanup.h>15#include <linux/cleanup.h>
13#include <linux/crc8.h>16#include <linux/crc8.h>
14#include <linux/delay.h>17#include <linux/delay.h>
15#include <linux/i2c.h>18#include <linux/i2c.h>
16#include <linux/init.h>19#include <linux/init.h>
20#include <linux/interrupt.h>
17#include <linux/module.h>21#include <linux/module.h>
18#include <linux/mutex.h>22#include <linux/mutex.h>
23#include <linux/units.h>
19 24
20#include <asm/unaligned.h>25#include <asm/unaligned.h>
21 26
27#include <linux/iio/events.h>
22#include <linux/iio/iio.h>28#include <linux/iio/iio.h>
23 29
24#define HDC3020_HEATER_CMD_MSB 0x30 /* shared by all heater commands */30#define HDC3020_S_AUTO_10HZ_MOD0 0x2737
25#define HDC3020_HEATER_ENABLE 0x6D31#define HDC3020_S_STATUS 0x3041
26#define HDC3020_HEATER_DISABLE 0x6632#define HDC3020_HEATER_DISABLE 0x3066
27#define HDC3020_HEATER_CONFIG 0x6E33#define HDC3020_HEATER_ENABLE 0x306D
34#define HDC3020_HEATER_CONFIG 0x306E
35#define HDC3020_EXIT_AUTO 0x3093
36#define HDC3020_S_T_RH_THRESH_LOW 0x6100
37#define HDC3020_S_T_RH_THRESH_LOW_CLR 0x610B
38#define HDC3020_S_T_RH_THRESH_HIGH_CLR 0x6116
39#define HDC3020_S_T_RH_THRESH_HIGH 0x611D
40#define HDC3020_R_T_RH_AUTO 0xE000
41#define HDC3020_R_T_LOW_AUTO 0xE002
42#define HDC3020_R_T_HIGH_AUTO 0xE003
43#define HDC3020_R_RH_LOW_AUTO 0xE004
44#define HDC3020_R_RH_HIGH_AUTO 0xE005
45#define HDC3020_R_T_RH_THRESH_LOW 0xE102
46#define HDC3020_R_T_RH_THRESH_LOW_CLR 0xE109
47#define HDC3020_R_T_RH_THRESH_HIGH_CLR 0xE114
48#define HDC3020_R_T_RH_THRESH_HIGH 0xE11F
49#define HDC3020_R_STATUS 0xF32D
50
51#define HDC3020_THRESH_TEMP_MASK GENMASK(8, 0)
52#define HDC3020_THRESH_TEMP_TRUNC_SHIFT 7
53#define HDC3020_THRESH_HUM_MASK GENMASK(15, 9)
54#define HDC3020_THRESH_HUM_TRUNC_SHIFT 9
55
56#define HDC3020_STATUS_T_LOW_ALERT BIT(6)
57#define HDC3020_STATUS_T_HIGH_ALERT BIT(7)
58#define HDC3020_STATUS_RH_LOW_ALERT BIT(8)
59#define HDC3020_STATUS_RH_HIGH_ALERT BIT(9)
28 60
29#define HDC3020_READ_RETRY_TIMES 1061#define HDC3020_READ_RETRY_TIMES 10
30#define HDC3020_BUSY_DELAY_MS 1062#define HDC3020_BUSY_DELAY_MS 10
31 63
32#define HDC3020_CRC8_POLYNOMIAL 0x3164#define HDC3020_CRC8_POLYNOMIAL 0x31
33 65
34static const u8 HDC3020_S_AUTO_10HZ_MOD0[2] = { 0x27, 0x37 };66#define HDC3020_MIN_TEMP -40
35 67#define HDC3020_MAX_TEMP 125
36static const u8 HDC3020_EXIT_AUTO[2] = { 0x30, 0x93 };
37
38static const u8 HDC3020_R_T_RH_AUTO[2] = { 0xE0, 0x00 };
39static const u8 HDC3020_R_T_LOW_AUTO[2] = { 0xE0, 0x02 };
40static const u8 HDC3020_R_T_HIGH_AUTO[2] = { 0xE0, 0x03 };
41static const u8 HDC3020_R_RH_LOW_AUTO[2] = { 0xE0, 0x04 };
42static const u8 HDC3020_R_RH_HIGH_AUTO[2] = { 0xE0, 0x05 };
43 68
44struct hdc3020_data {69struct hdc3020_data {
45 struct i2c_client *client;70 struct i2c_client *client;
@@ -54,18 +79,37 @@ struct hdc3020_data { · 8 unmodified lines
54 79
55static const int hdc3020_heater_vals[] = {0, 1, 0x3FFF};80static const int hdc3020_heater_vals[] = {0, 1, 0x3FFF};
56 81
82static const struct iio_event_spec hdc3020_t_rh_event[] = {
83 {
84 .type = IIO_EV_TYPE_THRESH,
85 .dir = IIO_EV_DIR_RISING,
86 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
87 BIT(IIO_EV_INFO_HYSTERESIS),
88 },
89 {
90 .type = IIO_EV_TYPE_THRESH,
91 .dir = IIO_EV_DIR_FALLING,
92 .mask_separate = BIT(IIO_EV_INFO_VALUE) |
93 BIT(IIO_EV_INFO_HYSTERESIS),
94 },
95};
96
57static const struct iio_chan_spec hdc3020_channels[] = {97static const struct iio_chan_spec hdc3020_channels[] = {
58 {98 {
59 .type = IIO_TEMP,99 .type = IIO_TEMP,
60 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |100 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
61 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |101 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |
62 BIT(IIO_CHAN_INFO_TROUGH) | BIT(IIO_CHAN_INFO_OFFSET),102 BIT(IIO_CHAN_INFO_TROUGH) | BIT(IIO_CHAN_INFO_OFFSET),
103 .event_spec = hdc3020_t_rh_event,
104 .num_event_specs = ARRAY_SIZE(hdc3020_t_rh_event),
63 },105 },
64 {106 {
65 .type = IIO_HUMIDITYRELATIVE,107 .type = IIO_HUMIDITYRELATIVE,
66 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |108 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
67 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |109 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_PEAK) |
68 BIT(IIO_CHAN_INFO_TROUGH),110 BIT(IIO_CHAN_INFO_TROUGH),
111 .event_spec = hdc3020_t_rh_event,
112 .num_event_specs = ARRAY_SIZE(hdc3020_t_rh_event),
69 },113 },
70 {114 {
71 /*115 /*
@@ -82,7 +126,7 @@ static const struct iio_chan_spec hdc3020_channels[] = { · 10 unmodified lines
82 126
83DECLARE_CRC8_TABLE(hdc3020_crc8_table);127DECLARE_CRC8_TABLE(hdc3020_crc8_table);
84 128
85static int hdc3020_write_bytes(struct hdc3020_data *data, const u8 *buf, u8 len)129static int hdc3020_write_bytes(struct hdc3020_data *data, u8 *buf, u8 len)
86{130{
87 struct i2c_client *client = data->client;131 struct i2c_client *client = data->client;
88 struct i2c_msg msg;132 struct i2c_msg msg;
@@ -90,7 +134,7 @@ static int hdc3020_write_bytes(struct hdc3020_data *data, const u8 *buf, u8 len) · 1 unmodified line
90 134
91 msg.addr = client->addr;135 msg.addr = client->addr;
92 msg.flags = 0;136 msg.flags = 0;
93 msg.buf = (char *)buf;137 msg.buf = buf;
94 msg.len = len;138 msg.len = len;
95 139
96 /*140 /*
@@ -109,26 +153,28 @@ static int hdc3020_write_bytes(struct hdc3020_data *data, const u8 *buf, u8 len) · 12 unmodified lines
109 return -ETIMEDOUT;153 return -ETIMEDOUT;
110}154}
111 155
112static int hdc3020_read_bytes(struct hdc3020_data *data, const u8 *buf,156static
113 void *val, int len)157int hdc3020_read_bytes(struct hdc3020_data *data, u16 reg, u8 *buf, int len)
114{158{
159 u8 reg_buf[2];
115 int ret, cnt;160 int ret, cnt;
116 struct i2c_client *client = data->client;161 struct i2c_client *client = data->client;
117 struct i2c_msg msg[2] = {162 struct i2c_msg msg[2] = {
118 [0] = {163 [0] = {
119 .addr = client->addr,164 .addr = client->addr,
120 .flags = 0,165 .flags = 0,
121 .buf = (char *)buf,166 .buf = reg_buf,
122 .len = 2,167 .len = 2,
123 },168 },
124 [1] = {169 [1] = {
125 .addr = client->addr,170 .addr = client->addr,
126 .flags = I2C_M_RD,171 .flags = I2C_M_RD,
127 .buf = val,172 .buf = buf,
128 .len = len,173 .len = len,
129 },174 },
130 };175 };
131 176
177 put_unaligned_be16(reg, reg_buf);
132 /*178 /*
133 * During the measurement process, HDC3020 will not return data.179 * During the measurement process, HDC3020 will not return data.
134 * So wait for a while and try again180 * So wait for a while and try again
@@ -145,48 +191,12 @@ static int hdc3020_read_bytes(struct hdc3020_data *data, const u8 *buf, · 10 unmodified lines
145 return -ETIMEDOUT;191 return -ETIMEDOUT;
146}192}
147 193
148static int hdc3020_read_measurement(struct hdc3020_data *data,194static int hdc3020_read_be16(struct hdc3020_data *data, u16 reg)
149 enum iio_chan_type type, int *val)
150{
151 u8 crc, buf[6];
152 int ret;
153
154 ret = hdc3020_read_bytes(data, HDC3020_R_T_RH_AUTO, buf, 6);
155 if (ret < 0)
156 return ret;
157
158 /* CRC check of the temperature measurement */
159 crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
160 if (crc != buf[2])
161 return -EINVAL;
162
163 /* CRC check of the relative humidity measurement */
164 crc = crc8(hdc3020_crc8_table, buf + 3, 2, CRC8_INIT_VALUE);
165 if (crc != buf[5])
166 return -EINVAL;
167
168 if (type == IIO_TEMP)
169 *val = get_unaligned_be16(buf);
170 else if (type == IIO_HUMIDITYRELATIVE)
171 *val = get_unaligned_be16(&buf[3]);
172 else
173 return -EINVAL;
174
175 return 0;
176}
177
178/*
179 * After exiting the automatic measurement mode or resetting, the peak
180 * value will be reset to the default value
181 * This method is used to get the highest temp measured during automatic
182 * measurement
183 */
184static int hdc3020_read_high_peak_t(struct hdc3020_data *data, int *val)
185{195{
186 u8 crc, buf[3];196 u8 crc, buf[3];
187 int ret;197 int ret;
188 198
189 ret = hdc3020_read_bytes(data, HDC3020_R_T_HIGH_AUTO, buf, 3);199 ret = hdc3020_read_bytes(data, reg, buf, 3);
190 if (ret < 0)200 if (ret < 0)
191 return ret;201 return ret;
192 202
@@ -194,73 +204,43 @@ static int hdc3020_read_high_peak_t(struct hdc3020_data *data, int *val) · 1 unmodified line
194 if (crc != buf[2])204 if (crc != buf[2])
195 return -EINVAL;205 return -EINVAL;
196 206
197 *val = get_unaligned_be16(buf);207 return get_unaligned_be16(buf);
198
199 return 0;
200}208}
201 209
202/*210static int hdc3020_exec_cmd(struct hdc3020_data *data, u16 reg)
203 * This method is used to get the lowest temp measured during automatic
204 * measurement
205 */
206static int hdc3020_read_low_peak_t(struct hdc3020_data *data, int *val)
207{211{
208 u8 crc, buf[3];212 u8 reg_buf[2];
209 int ret;
210 213
211 ret = hdc3020_read_bytes(data, HDC3020_R_T_LOW_AUTO, buf, 3);214 put_unaligned_be16(reg, reg_buf);
212 if (ret < 0)215 return hdc3020_write_bytes(data, reg_buf, 2);
213 return ret;
214
215 crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
216 if (crc != buf[2])
217 return -EINVAL;
218
219 *val = get_unaligned_be16(buf);
220
221 return 0;
222}216}
223 217
224/*218static int hdc3020_read_measurement(struct hdc3020_data *data,
225 * This method is used to get the highest humidity measured during automatic219 enum iio_chan_type type, int *val)
226 * measurement
227 */
228static int hdc3020_read_high_peak_rh(struct hdc3020_data *data, int *val)
229{220{
230 u8 crc, buf[3];221 u8 crc, buf[6];
231 int ret;222 int ret;
232 223
233 ret = hdc3020_read_bytes(data, HDC3020_R_RH_HIGH_AUTO, buf, 3);224 ret = hdc3020_read_bytes(data, HDC3020_R_T_RH_AUTO, buf, 6);
234 if (ret < 0)225 if (ret < 0)
235 return ret;226 return ret;
236 227
228 /* CRC check of the temperature measurement */
237 crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);229 crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
238 if (crc != buf[2])230 if (crc != buf[2])
239 return -EINVAL;231 return -EINVAL;
240 232
241 *val = get_unaligned_be16(buf);233 /* CRC check of the relative humidity measurement */
242 234 crc = crc8(hdc3020_crc8_table, buf + 3, 2, CRC8_INIT_VALUE);
243 return 0;235 if (crc != buf[5])
244}
245
246/*
247 * This method is used to get the lowest humidity measured during automatic
248 * measurement
249 */
250static int hdc3020_read_low_peak_rh(struct hdc3020_data *data, int *val)
251{
252 u8 crc, buf[3];
253 int ret;
254
255 ret = hdc3020_read_bytes(data, HDC3020_R_RH_LOW_AUTO, buf, 3);
256 if (ret < 0)
257 return ret;
258
259 crc = crc8(hdc3020_crc8_table, buf, 2, CRC8_INIT_VALUE);
260 if (crc != buf[2])
261 return -EINVAL;236 return -EINVAL;
262 237
263 *val = get_unaligned_be16(buf);238 if (type == IIO_TEMP)
239 *val = get_unaligned_be16(buf);
240 else if (type == IIO_HUMIDITYRELATIVE)
241 *val = get_unaligned_be16(&buf[3]);
242 else
243 return -EINVAL;
264 244
265 return 0;245 return 0;
266}246}
@@ -286,28 +266,28 @@ static int hdc3020_read_raw(struct iio_dev *indio_dev, · 19 unmodified lines
286 }266 }
287 case IIO_CHAN_INFO_PEAK: {267 case IIO_CHAN_INFO_PEAK: {
288 guard(mutex)(&data->lock);268 guard(mutex)(&data->lock);
289 if (chan->type == IIO_TEMP) {269 if (chan->type == IIO_TEMP)
290 ret = hdc3020_read_high_peak_t(data, val);270 ret = hdc3020_read_be16(data, HDC3020_R_T_HIGH_AUTO);
291 if (ret < 0)271 else
292 return ret;272 ret = hdc3020_read_be16(data, HDC3020_R_RH_HIGH_AUTO);
293 } else {273
294 ret = hdc3020_read_high_peak_rh(data, val);274 if (ret < 0)
295 if (ret < 0)275 return ret;
296 return ret;276
297 }277 *val = ret;
298 return IIO_VAL_INT;278 return IIO_VAL_INT;
299 }279 }
300 case IIO_CHAN_INFO_TROUGH: {280 case IIO_CHAN_INFO_TROUGH: {
301 guard(mutex)(&data->lock);281 guard(mutex)(&data->lock);
302 if (chan->type == IIO_TEMP) {282 if (chan->type == IIO_TEMP)
303 ret = hdc3020_read_low_peak_t(data, val);283 ret = hdc3020_read_be16(data, HDC3020_R_T_LOW_AUTO);
304 if (ret < 0)284 else
305 return ret;285 ret = hdc3020_read_be16(data, HDC3020_R_RH_LOW_AUTO);
306 } else {286
307 ret = hdc3020_read_low_peak_rh(data, val);287 if (ret < 0)
308 if (ret < 0)288 return ret;
309 return ret;289
310 }290 *val = ret;
311 return IIO_VAL_INT;291 return IIO_VAL_INT;
312 }292 }
313 case IIO_CHAN_INFO_SCALE:293 case IIO_CHAN_INFO_SCALE:
@@ -352,23 +332,17 @@ static int hdc3020_update_heater(struct hdc3020_data *data, int val) · 38 unmodified lines
352 if (val < hdc3020_heater_vals[0] || val > hdc3020_heater_vals[2])332 if (val < hdc3020_heater_vals[0] || val > hdc3020_heater_vals[2])
353 return -EINVAL;333 return -EINVAL;
354 334
355 buf[0] = HDC3020_HEATER_CMD_MSB;335 if (!val)
336 hdc3020_exec_cmd(data, HDC3020_HEATER_DISABLE);
356 337
357 if (!val) {338 put_unaligned_be16(HDC3020_HEATER_CONFIG, buf);
358 buf[1] = HDC3020_HEATER_DISABLE;
359 return hdc3020_write_bytes(data, buf, 2);
360 }
361
362 buf[1] = HDC3020_HEATER_CONFIG;
363 put_unaligned_be16(val & GENMASK(13, 0), &buf[2]);339 put_unaligned_be16(val & GENMASK(13, 0), &buf[2]);
364 buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);340 buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
365 ret = hdc3020_write_bytes(data, buf, 5);341 ret = hdc3020_write_bytes(data, buf, 5);
366 if (ret < 0)342 if (ret < 0)
367 return ret;343 return ret;
368 344
369 buf[1] = HDC3020_HEATER_ENABLE;345 return hdc3020_exec_cmd(data, HDC3020_HEATER_ENABLE);
370
371 return hdc3020_write_bytes(data, buf, 2);
372}346}
373 347
374static int hdc3020_write_raw(struct iio_dev *indio_dev,348static int hdc3020_write_raw(struct iio_dev *indio_dev,
@@ -389,15 +363,197 @@ static int hdc3020_write_raw(struct iio_dev *indio_dev, · 14 unmodified lines
389 return -EINVAL;363 return -EINVAL;
390}364}
391 365
366static int hdc3020_write_thresh(struct iio_dev *indio_dev,
367 const struct iio_chan_spec *chan,
368 enum iio_event_type type,
369 enum iio_event_direction dir,
370 enum iio_event_info info,
371 int val, int val2)
372{
373 struct hdc3020_data *data = iio_priv(indio_dev);
374 u8 buf[5];
375 u64 tmp;
376 u16 reg;
377 int ret;
378
379 /* Supported temperature range is from –40 to 125 degree celsius */
380 if (val < HDC3020_MIN_TEMP || val > HDC3020_MAX_TEMP)
381 return -EINVAL;
382
383 /* Select threshold register */
384 if (info == IIO_EV_INFO_VALUE) {
385 if (dir == IIO_EV_DIR_RISING)
386 reg = HDC3020_S_T_RH_THRESH_HIGH;
387 else
388 reg = HDC3020_S_T_RH_THRESH_LOW;
389 } else {
390 if (dir == IIO_EV_DIR_RISING)
391 reg = HDC3020_S_T_RH_THRESH_HIGH_CLR;
392 else
393 reg = HDC3020_S_T_RH_THRESH_LOW_CLR;
394 }
395
396 guard(mutex)(&data->lock);
397 ret = hdc3020_read_be16(data, reg);
398 if (ret < 0)
399 return ret;
400
401 switch (chan->type) {
402 case IIO_TEMP:
403 /*
404 * Calculate temperature threshold, shift it down to get the
405 * truncated threshold representation in the 9LSBs while keeping
406 * the current humidity threshold in the 7 MSBs.
407 */
408 tmp = ((u64)(((val + 45) * MICRO) + val2)) * 65535ULL;
409 tmp = div_u64(tmp, MICRO * 175);
410 val = tmp >> HDC3020_THRESH_TEMP_TRUNC_SHIFT;
411 val = FIELD_PREP(HDC3020_THRESH_TEMP_MASK, val);
412 val |= (FIELD_GET(HDC3020_THRESH_HUM_MASK, ret) <<
413 HDC3020_THRESH_HUM_TRUNC_SHIFT);
414 break;
415 case IIO_HUMIDITYRELATIVE:
416 /*
417 * Calculate humidity threshold, shift it down and up to get the
418 * truncated threshold representation in the 7MSBs while keeping
419 * the current temperature threshold in the 9 LSBs.
420 */
421 tmp = ((u64)((val * MICRO) + val2)) * 65535ULL;
422 tmp = div_u64(tmp, MICRO * 100);
423 val = tmp >> HDC3020_THRESH_HUM_TRUNC_SHIFT;
424 val = FIELD_PREP(HDC3020_THRESH_HUM_MASK, val);
425 val |= FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
426 break;
427 default:
428 return -EOPNOTSUPP;
429 }
430
431 put_unaligned_be16(reg, buf);
432 put_unaligned_be16(val, buf + 2);
433 buf[4] = crc8(hdc3020_crc8_table, buf + 2, 2, CRC8_INIT_VALUE);
434 return hdc3020_write_bytes(data, buf, 5);
435}
436
437static int hdc3020_read_thresh(struct iio_dev *indio_dev,
438 const struct iio_chan_spec *chan,
439 enum iio_event_type type,
440 enum iio_event_direction dir,
441 enum iio_event_info info,
442 int *val, int *val2)
443{
444 struct hdc3020_data *data = iio_priv(indio_dev);
445 u16 reg;
446 int ret;
447
448 /* Select threshold register */
449 if (info == IIO_EV_INFO_VALUE) {
450 if (dir == IIO_EV_DIR_RISING)
451 reg = HDC3020_R_T_RH_THRESH_HIGH;
452 else
453 reg = HDC3020_R_T_RH_THRESH_LOW;
454 } else {
455 if (dir == IIO_EV_DIR_RISING)
456 reg = HDC3020_R_T_RH_THRESH_HIGH_CLR;
457 else
458 reg = HDC3020_R_T_RH_THRESH_LOW_CLR;
459 }
460
461 guard(mutex)(&data->lock);
462 ret = hdc3020_read_be16(data, reg);
463 if (ret < 0)
464 return ret;
465
466 switch (chan->type) {
467 case IIO_TEMP:
468 /*
469 * Get the temperature threshold from 9 LSBs, shift them to get
470 * the truncated temperature threshold representation and
471 * calculate the threshold according to the formula in the
472 * datasheet.
473 */
474 *val = FIELD_GET(HDC3020_THRESH_TEMP_MASK, ret);
475 *val = *val << HDC3020_THRESH_TEMP_TRUNC_SHIFT;
476 *val = -2949075 + (175 * (*val));
477 *val2 = 65535;
478 return IIO_VAL_FRACTIONAL;
479 case IIO_HUMIDITYRELATIVE:
480 /*
481 * Get the humidity threshold from 7 MSBs, shift them to get the
482 * truncated humidity threshold representation and calculate the
483 * threshold according to the formula in the datasheet.
484 */
485 *val = FIELD_GET(HDC3020_THRESH_HUM_MASK, ret);
486 *val = (*val << HDC3020_THRESH_HUM_TRUNC_SHIFT) * 100;
487 *val2 = 65535;
488 return IIO_VAL_FRACTIONAL;
489 default:
490 return -EOPNOTSUPP;
491 }
492}
493
494static irqreturn_t hdc3020_interrupt_handler(int irq, void *private)
495{
496 struct iio_dev *indio_dev = private;
497 struct hdc3020_data *data;
498 s64 time;
499 int ret;
500
501 data = iio_priv(indio_dev);
502 ret = hdc3020_read_be16(data, HDC3020_R_STATUS);
503 if (ret < 0)
504 return IRQ_HANDLED;
505
506 if (!(ret & (HDC3020_STATUS_T_HIGH_ALERT | HDC3020_STATUS_T_LOW_ALERT |
507 HDC3020_STATUS_RH_HIGH_ALERT | HDC3020_STATUS_RH_LOW_ALERT)))
508 return IRQ_NONE;
509
510 time = iio_get_time_ns(indio_dev);
511 if (ret & HDC3020_STATUS_T_HIGH_ALERT)
512 iio_push_event(indio_dev,
513 IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
514 IIO_NO_MOD,
515 IIO_EV_TYPE_THRESH,
516 IIO_EV_DIR_RISING),
517 time);
518
519 if (ret & HDC3020_STATUS_T_LOW_ALERT)
520 iio_push_event(indio_dev,
521 IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
522 IIO_NO_MOD,
523 IIO_EV_TYPE_THRESH,
524 IIO_EV_DIR_FALLING),
525 time);
526
527 if (ret & HDC3020_STATUS_RH_HIGH_ALERT)
528 iio_push_event(indio_dev,
529 IIO_MOD_EVENT_CODE(IIO_HUMIDITYRELATIVE, 0,
530 IIO_NO_MOD,
531 IIO_EV_TYPE_THRESH,
532 IIO_EV_DIR_RISING),
533 time);
534
535 if (ret & HDC3020_STATUS_RH_LOW_ALERT)
536 iio_push_event(indio_dev,
537 IIO_MOD_EVENT_CODE(IIO_HUMIDITYRELATIVE, 0,
538 IIO_NO_MOD,
539 IIO_EV_TYPE_THRESH,
540 IIO_EV_DIR_FALLING),
541 time);
542
543 return IRQ_HANDLED;
544}
545
392static const struct iio_info hdc3020_info = {546static const struct iio_info hdc3020_info = {
393 .read_raw = hdc3020_read_raw,547 .read_raw = hdc3020_read_raw,
394 .write_raw = hdc3020_write_raw,548 .write_raw = hdc3020_write_raw,
395 .read_avail = hdc3020_read_available,549 .read_avail = hdc3020_read_available,
550 .read_event_value = hdc3020_read_thresh,
551 .write_event_value = hdc3020_write_thresh,
396};552};
397 553
398static void hdc3020_stop(void *data)554static void hdc3020_stop(void *data)
399{555{
400 hdc3020_write_bytes((struct hdc3020_data *)data, HDC3020_EXIT_AUTO, 2);556 hdc3020_exec_cmd((struct hdc3020_data *)data, HDC3020_EXIT_AUTO);
401}557}
402 558
403static int hdc3020_probe(struct i2c_client *client)559static int hdc3020_probe(struct i2c_client *client)
@@ -424,8 +580,25 @@ static int hdc3020_probe(struct i2c_client *client) · 20 unmodified lines
424 indio_dev->info = &hdc3020_info;580 indio_dev->info = &hdc3020_info;
425 indio_dev->channels = hdc3020_channels;581 indio_dev->channels = hdc3020_channels;
426 indio_dev->num_channels = ARRAY_SIZE(hdc3020_channels);582 indio_dev->num_channels = ARRAY_SIZE(hdc3020_channels);
583 if (client->irq) {
584 ret = devm_request_threaded_irq(&client->dev, client->irq,
585 NULL, hdc3020_interrupt_handler,
586 IRQF_ONESHOT, "hdc3020",
587 indio_dev);
588 if (ret)
589 return dev_err_probe(&client->dev, ret,
590 "Failed to request IRQ\n");
591
592 /*
593 * The alert output is activated by default upon power up,
594 * hardware reset, and soft reset. Clear the status register.
595 */
596 ret = hdc3020_exec_cmd(data, HDC3020_S_STATUS);
597 if (ret)
598 return ret;
599 }
427 600
428 ret = hdc3020_write_bytes(data, HDC3020_S_AUTO_10HZ_MOD0, 2);601 ret = hdc3020_exec_cmd(data, HDC3020_S_AUTO_10HZ_MOD0);
429 if (ret)602 if (ret)
430 return dev_err_probe(&client->dev, ret,603 return dev_err_probe(&client->dev, ret,
431 "Unable to set up measurement\n");604 "Unable to set up measurement\n");
drivers/iio/humidity/hts221_i2c.c+2−2
@@ -9,7 +9,7 @@ · 8 unmodified lines
9 9
10#include <linux/kernel.h>10#include <linux/kernel.h>
11#include <linux/module.h>11#include <linux/module.h>
12#include <linux/acpi.h>12#include <linux/mod_devicetable.h>
13#include <linux/i2c.h>13#include <linux/i2c.h>
14#include <linux/slab.h>14#include <linux/slab.h>
15#include <linux/regmap.h>15#include <linux/regmap.h>
@@ -63,7 +63,7 @@ static struct i2c_driver hts221_driver = { · 47 unmodified lines
63 .name = "hts221_i2c",63 .name = "hts221_i2c",
64 .pm = pm_sleep_ptr(&hts221_pm_ops),64 .pm = pm_sleep_ptr(&hts221_pm_ops),
65 .of_match_table = hts221_i2c_of_match,65 .of_match_table = hts221_i2c_of_match,
66 .acpi_match_table = ACPI_PTR(hts221_acpi_match),66 .acpi_match_table = hts221_acpi_match,
67 },67 },
68 .probe = hts221_i2c_probe,68 .probe = hts221_i2c_probe,
69 .id_table = hts221_i2c_id_table,69 .id_table = hts221_i2c_id_table,
drivers/iio/imu/adis16475.c+1−7
@@ -1363,22 +1363,16 @@ static int adis16475_config_sync_mode(struct adis16475 *st) · 1362 unmodified lines
1363static int adis16475_config_irq_pin(struct adis16475 *st)1363static int adis16475_config_irq_pin(struct adis16475 *st)
1364{1364{
1365 int ret;1365 int ret;
1366 struct irq_data *desc;
1367 u32 irq_type;1366 u32 irq_type;
1368 u16 val = 0;1367 u16 val = 0;
1369 u8 polarity;1368 u8 polarity;
1370 struct spi_device *spi = st->adis.spi;1369 struct spi_device *spi = st->adis.spi;
1371 1370
1372 desc = irq_get_irq_data(spi->irq);
1373 if (!desc) {
1374 dev_err(&spi->dev, "Could not find IRQ %d\n", spi->irq);
1375 return -EINVAL;
1376 }
1377 /*1371 /*
1378 * It is possible to configure the data ready polarity. Furthermore, we1372 * It is possible to configure the data ready polarity. Furthermore, we
1379 * need to update the adis struct if we want data ready as active low.1373 * need to update the adis struct if we want data ready as active low.
1380 */1374 */
1381 irq_type = irqd_get_trigger_type(desc);1375 irq_type = irq_get_trigger_type(spi->irq);
1382 if (irq_type == IRQ_TYPE_EDGE_RISING) {1376 if (irq_type == IRQ_TYPE_EDGE_RISING) {
1383 polarity = 1;1377 polarity = 1;
1384 st->adis.irq_flag = IRQF_TRIGGER_RISING;1378 st->adis.irq_flag = IRQF_TRIGGER_RISING;
drivers/iio/imu/adis16480.c+1−8
@@ -1246,18 +1246,11 @@ static int adis16480_config_irq_pin(struct adis16480 *st) · 1245 unmodified lines
1246{1246{
1247 struct device *dev = &st->adis.spi->dev;1247 struct device *dev = &st->adis.spi->dev;
1248 struct fwnode_handle *fwnode = dev_fwnode(dev);1248 struct fwnode_handle *fwnode = dev_fwnode(dev);
1249 struct irq_data *desc;
1250 enum adis16480_int_pin pin;1249 enum adis16480_int_pin pin;
1251 unsigned int irq_type;1250 unsigned int irq_type;
1252 uint16_t val;1251 uint16_t val;
1253 int i, irq = 0;1252 int i, irq = 0;
1254 1253
1255 desc = irq_get_irq_data(st->adis.spi->irq);
1256 if (!desc) {
1257 dev_err(dev, "Could not find IRQ %d\n", irq);
1258 return -EINVAL;
1259 }
1260
1261 /* Disable data ready since the default after reset is on */1254 /* Disable data ready since the default after reset is on */
1262 val = ADIS16480_DRDY_EN(0);1255 val = ADIS16480_DRDY_EN(0);
1263 1256
@@ -1285,7 +1278,7 @@ static int adis16480_config_irq_pin(struct adis16480 *st) · 21 unmodified lines
1285 * configured as positive or negative, corresponding to1278 * configured as positive or negative, corresponding to
1286 * IRQ_TYPE_EDGE_RISING or IRQ_TYPE_EDGE_FALLING respectively.1279 * IRQ_TYPE_EDGE_RISING or IRQ_TYPE_EDGE_FALLING respectively.
1287 */1280 */
1288 irq_type = irqd_get_trigger_type(desc);1281 irq_type = irq_get_trigger_type(st->adis.spi->irq);
1289 if (irq_type == IRQ_TYPE_EDGE_RISING) { /* Default */1282 if (irq_type == IRQ_TYPE_EDGE_RISING) { /* Default */
1290 val |= ADIS16480_DRDY_POL(1);1283 val |= ADIS16480_DRDY_POL(1);
1291 } else if (irq_type == IRQ_TYPE_EDGE_FALLING) {1284 } else if (irq_type == IRQ_TYPE_EDGE_FALLING) {
drivers/iio/imu/bmi160/bmi160_i2c.c+9−0
@@ -43,6 +43,15 @@ static const struct i2c_device_id bmi160_i2c_id[] = { · 42 unmodified lines
43MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id);43MODULE_DEVICE_TABLE(i2c, bmi160_i2c_id);
44 44
45static const struct acpi_device_id bmi160_acpi_match[] = {45static const struct acpi_device_id bmi160_acpi_match[] = {
46 /*
47 * FIRMWARE BUG WORKAROUND
48 * Some manufacturers like GPD, Lenovo or Aya used the incorrect
49 * ID "10EC5280" for bmi160 in their DSDT. A fixed firmware is not
50 * available as of Feb 2024 after trying to work with OEMs, and
51 * this is not expected to change anymore since at least some of
52 * the affected devices are from 2021/2022.
53 */
54 {"10EC5280", 0},
46 {"BMI0160", 0},55 {"BMI0160", 0},
47 { },56 { },
48};57};
drivers/iio/imu/bmi323/bmi323_core.c+31−47
@@ -1668,52 +1668,41 @@ static int bmi323_write_raw(struct iio_dev *indio_dev, · 1667 unmodified lines
1668 int val2, long mask)1668 int val2, long mask)
1669{1669{
1670 struct bmi323_data *data = iio_priv(indio_dev);1670 struct bmi323_data *data = iio_priv(indio_dev);
1671 int ret;
1672 1671
1673 switch (mask) {1672 switch (mask) {
1674 case IIO_CHAN_INFO_SAMP_FREQ:1673 case IIO_CHAN_INFO_SAMP_FREQ:
1675 ret = iio_device_claim_direct_mode(indio_dev);1674 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
1676 if (ret)1675 return bmi323_set_odr(data,
1677 return ret;1676 bmi323_iio_to_sensor(chan->type),
1678 1677 val, val2);
1679 ret = bmi323_set_odr(data, bmi323_iio_to_sensor(chan->type),1678 unreachable();
1680 val, val2);
1681 iio_device_release_direct_mode(indio_dev);
1682 return ret;
1683 case IIO_CHAN_INFO_SCALE:1679 case IIO_CHAN_INFO_SCALE:
1684 ret = iio_device_claim_direct_mode(indio_dev);1680 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
1685 if (ret)1681 return bmi323_set_scale(data,
1686 return ret;1682 bmi323_iio_to_sensor(chan->type),
1687 1683 val, val2);
1688 ret = bmi323_set_scale(data, bmi323_iio_to_sensor(chan->type),1684 unreachable();
1689 val, val2);
1690 iio_device_release_direct_mode(indio_dev);
1691 return ret;
1692 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:1685 case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
1693 ret = iio_device_claim_direct_mode(indio_dev);1686 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
1694 if (ret)1687 return bmi323_set_average(data,
1695 return ret;1688 bmi323_iio_to_sensor(chan->type),
1696 1689 val);
1697 ret = bmi323_set_average(data, bmi323_iio_to_sensor(chan->type),1690 unreachable();
1698 val);
1699
1700 iio_device_release_direct_mode(indio_dev);
1701 return ret;
1702 case IIO_CHAN_INFO_ENABLE:1691 case IIO_CHAN_INFO_ENABLE:
1703 return bmi323_enable_steps(data, val);1692 return bmi323_enable_steps(data, val);
1704 case IIO_CHAN_INFO_PROCESSED:1693 case IIO_CHAN_INFO_PROCESSED: {
1705 scoped_guard(mutex, &data->mutex) {1694 guard(mutex)(&data->mutex);
1706 if (val || !FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK,
1707 data->feature_events))
1708 return -EINVAL;
1709 1695
1710 /* Clear step counter value */1696 if (val || !FIELD_GET(BMI323_FEAT_IO0_STP_CNT_MSK,
1711 ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,1697 data->feature_events))
1712 BMI323_STEP_SC1_RST_CNT_MSK,1698 return -EINVAL;
1713 FIELD_PREP(BMI323_STEP_SC1_RST_CNT_MSK,1699
1714 1));1700 /* Clear step counter value */
1715 }1701 return bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,
1716 return ret;1702 BMI323_STEP_SC1_RST_CNT_MSK,
1703 FIELD_PREP(BMI323_STEP_SC1_RST_CNT_MSK,
1704 1));
1705 }
1717 default:1706 default:
1718 return -EINVAL;1707 return -EINVAL;
1719 }1708 }
@@ -1724,7 +1713,6 @@ static int bmi323_read_raw(struct iio_dev *indio_dev, · 4 unmodified lines
1724 int *val2, long mask)1713 int *val2, long mask)
1725{1714{
1726 struct bmi323_data *data = iio_priv(indio_dev);1715 struct bmi323_data *data = iio_priv(indio_dev);
1727 int ret;
1728 1716
1729 switch (mask) {1717 switch (mask) {
1730 case IIO_CHAN_INFO_PROCESSED:1718 case IIO_CHAN_INFO_PROCESSED:
@@ -1733,14 +1721,10 @@ static int bmi323_read_raw(struct iio_dev *indio_dev, · 2 unmodified lines
1733 switch (chan->type) {1721 switch (chan->type) {
1734 case IIO_ACCEL:1722 case IIO_ACCEL:
1735 case IIO_ANGL_VEL:1723 case IIO_ANGL_VEL:
1736 ret = iio_device_claim_direct_mode(indio_dev);1724 iio_device_claim_direct_scoped(return -EBUSY,
1737 if (ret)1725 indio_dev)
1738 return ret;1726 return bmi323_read_axis(data, chan, val);
1739 1727 unreachable();
1740 ret = bmi323_read_axis(data, chan, val);
1741
1742 iio_device_release_direct_mode(indio_dev);
1743 return ret;
1744 case IIO_TEMP:1728 case IIO_TEMP:
1745 return bmi323_get_temp_data(data, val);1729 return bmi323_get_temp_data(data, val);
1746 default:1730 default:
drivers/iio/imu/bmi323/bmi323_i2c.c+21−0
@@ -93,6 +93,26 @@ static int bmi323_i2c_probe(struct i2c_client *i2c) · 92 unmodified lines
93 return bmi323_core_probe(dev);93 return bmi323_core_probe(dev);
94}94}
95 95
96static const struct acpi_device_id bmi323_acpi_match[] = {
97 /*
98 * The "BOSC0200" identifier used here is not unique to bmi323 devices.
99 * The same "BOSC0200" identifier is found in the ACPI tables of devices
100 * using the bmc150 chip. This creates a conflict with duplicate ACPI
101 * identifiers which multiple drivers want to use. If a non-bmi323
102 * device starts to load with this "BOSC0200" ACPI match here, then the
103 * chip ID check portion should fail because the chip IDs received (via
104 * i2c) are unique between bmc150 and bmi323 and the driver should
105 * relinquish the device. If and when a different driver (such as
106 * bmc150) starts to load with the "BOSC0200" ACPI match, a short reset
107 * should ensure that the device is not in a bad state during that
108 * driver initialization. This device reset does occur in both the
109 * bmi323 and bmc150 init sequences.
110 */
111 { "BOSC0200" },
112 { }
113};
114MODULE_DEVICE_TABLE(acpi, bmi323_acpi_match);
115
96static const struct i2c_device_id bmi323_i2c_ids[] = {116static const struct i2c_device_id bmi323_i2c_ids[] = {
97 { "bmi323" },117 { "bmi323" },
98 { }118 { }
@@ -109,6 +129,7 @@ static struct i2c_driver bmi323_i2c_driver = { · 10 unmodified lines
109 .driver = {129 .driver = {
110 .name = "bmi323",130 .name = "bmi323",
111 .of_match_table = bmi323_of_i2c_match,131 .of_match_table = bmi323_of_i2c_match,
132 .acpi_match_table = bmi323_acpi_match,
112 },133 },
113 .probe = bmi323_i2c_probe,134 .probe = bmi323_i2c_probe,
114 .id_table = bmi323_i2c_ids,135 .id_table = bmi323_i2c_ids,
drivers/iio/imu/fxos8700_i2c.c+1−2
@@ -10,7 +10,6 @@ · 9 unmodified lines
10 * 1 | 0 | 0x1C10 * 1 | 0 | 0x1C
11 * 1 | 1 | 0x1F11 * 1 | 1 | 0x1F
12 */12 */
13#include <linux/acpi.h>
14#include <linux/i2c.h>13#include <linux/i2c.h>
15#include <linux/module.h>14#include <linux/module.h>
16#include <linux/mod_devicetable.h>15#include <linux/mod_devicetable.h>
@@ -57,7 +56,7 @@ MODULE_DEVICE_TABLE(of, fxos8700_of_match); · 40 unmodified lines
57static struct i2c_driver fxos8700_i2c_driver = {56static struct i2c_driver fxos8700_i2c_driver = {
58 .driver = {57 .driver = {
59 .name = "fxos8700_i2c",58 .name = "fxos8700_i2c",
60 .acpi_match_table = ACPI_PTR(fxos8700_acpi_match),59 .acpi_match_table = fxos8700_acpi_match,
61 .of_match_table = fxos8700_of_match,60 .of_match_table = fxos8700_of_match,
62 },61 },
63 .probe = fxos8700_i2c_probe,62 .probe = fxos8700_i2c_probe,
drivers/iio/imu/fxos8700_spi.c+1−2
@@ -2,7 +2,6 @@ · 1 unmodified line
2/*2/*
3 * FXOS8700 - NXP IMU, SPI bits3 * FXOS8700 - NXP IMU, SPI bits
4 */4 */
5#include <linux/acpi.h>
6#include <linux/module.h>5#include <linux/module.h>
7#include <linux/mod_devicetable.h>6#include <linux/mod_devicetable.h>
8#include <linux/regmap.h>7#include <linux/regmap.h>
@@ -46,7 +45,7 @@ static struct spi_driver fxos8700_spi_driver = { · 37 unmodified lines
46 .probe = fxos8700_spi_probe,45 .probe = fxos8700_spi_probe,
47 .id_table = fxos8700_spi_id,46 .id_table = fxos8700_spi_id,
48 .driver = {47 .driver = {
49 .acpi_match_table = ACPI_PTR(fxos8700_acpi_match),48 .acpi_match_table = fxos8700_acpi_match,
50 .of_match_table = fxos8700_of_match,49 .of_match_table = fxos8700_of_match,
51 .name = "fxos8700_spi",50 .name = "fxos8700_spi",
52 },51 },
drivers/iio/imu/kmx61.c+1−1
@@ -1514,7 +1514,7 @@ MODULE_DEVICE_TABLE(i2c, kmx61_id); · 1513 unmodified lines
1514static struct i2c_driver kmx61_driver = {1514static struct i2c_driver kmx61_driver = {
1515 .driver = {1515 .driver = {
1516 .name = KMX61_DRV_NAME,1516 .name = KMX61_DRV_NAME,
1517 .acpi_match_table = ACPI_PTR(kmx61_acpi_match),1517 .acpi_match_table = kmx61_acpi_match,
1518 .pm = pm_ptr(&kmx61_pm_ops),1518 .pm = pm_ptr(&kmx61_pm_ops),
1519 },1519 },
1520 .probe = kmx61_probe,1520 .probe = kmx61_probe,
drivers/iio/imu/st_lsm6dsx/Kconfig+26−5
@@ -11,11 +11,32 @@ config IIO_ST_LSM6DSX · 10 unmodified lines
11 select IIO_ST_LSM6DSX_I3C if (I3C)11 select IIO_ST_LSM6DSX_I3C if (I3C)
12 help12 help
13 Say yes here to build support for STMicroelectronics LSM6DSx imu13 Say yes here to build support for STMicroelectronics LSM6DSx imu
14 sensor. Supported devices: lsm6ds3, lsm6ds3h, lsm6dsl, lsm6dsm,14 sensor.
15 ism330dlc, lsm6dso, lsm6dsox, asm330lhh, asm330lhhx, lsm6dsr,15 Supported devices:
16 lsm6ds3tr-c, ism330dhcx, lsm6dsrx, lsm6ds0, lsm6dsop, lsm6dstx,16 - asm330lhb
17 lsm6dsv, lsm6dsv16x, lsm6dso16is, ism330is, asm330lhb, lsm6dst17 - asm330lhh
18 and the accelerometer/gyroscope of lsm9ds1.18 - asm330lhhx
19 - asm330lhhxg1
20 - ism330dhcx
21 - ism330dlc
22 - ism330is
23 - lsm6ds0
24 - lsm6ds3
25 - lsm6ds3h
26 - lsm6ds3tr-c
27 - lsm6dsl
28 - lsm6dsm
29 - lsm6dso
30 - lsm6dso16is
31 - lsm6dsop
32 - lsm6dsox
33 - lsm6dsr
34 - lsm6dsrx
35 - lsm6dst
36 - lsm6dstx
37 - lsm6dsv
38 - lsm6dsv16x
39 - lsm9ds1
19 40
20 To compile this driver as a module, choose M here: the module41 To compile this driver as a module, choose M here: the module
21 will be called st_lsm6dsx.42 will be called st_lsm6dsx.
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h+2−0
@@ -38,6 +38,7 @@ · 37 unmodified lines
38#define ST_LSM6DSO16IS_DEV_NAME "lsm6dso16is"38#define ST_LSM6DSO16IS_DEV_NAME "lsm6dso16is"
39#define ST_ISM330IS_DEV_NAME "ism330is"39#define ST_ISM330IS_DEV_NAME "ism330is"
40#define ST_ASM330LHB_DEV_NAME "asm330lhb"40#define ST_ASM330LHB_DEV_NAME "asm330lhb"
41#define ST_ASM330LHHXG1_DEV_NAME "asm330lhhxg1"
41 42
42enum st_lsm6dsx_hw_id {43enum st_lsm6dsx_hw_id {
43 ST_LSM6DS3_ID = 1,44 ST_LSM6DS3_ID = 1,
@@ -63,6 +64,7 @@ enum st_lsm6dsx_hw_id { · 19 unmodified lines
63 ST_LSM6DSO16IS_ID,64 ST_LSM6DSO16IS_ID,
64 ST_ISM330IS_ID,65 ST_ISM330IS_ID,
65 ST_ASM330LHB_ID,66 ST_ASM330LHB_ID,
67 ST_ASM330LHHXG1_ID,
66 ST_LSM6DSX_MAX_ID,68 ST_LSM6DSX_MAX_ID,
67};69};
68 70
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c+25−3
@@ -2,7 +2,7 @@ · 1 unmodified line
2/*2/*
3 * STMicroelectronics st_lsm6dsx FIFO buffer library driver3 * STMicroelectronics st_lsm6dsx FIFO buffer library driver
4 *4 *
5 * LSM6DS3/LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C:5 * Pattern FIFO:
6 * The FIFO buffer can be configured to store data from gyroscope and6 * The FIFO buffer can be configured to store data from gyroscope and
7 * accelerometer. Samples are queued without any tag according to a7 * accelerometer. Samples are queued without any tag according to a
8 * specific pattern based on 'FIFO data sets' (6 bytes each):8 * specific pattern based on 'FIFO data sets' (6 bytes each):
@@ -14,12 +14,34 @@ · 5 unmodified lines
14 * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the14 * (e.g. Gx, Gy, Gz, Ax, Ay, Az), then data are repeated depending on the
15 * value of the decimation factor and ODR set for each FIFO data set.15 * value of the decimation factor and ODR set for each FIFO data set.
16 *16 *
17 * LSM6DSO/LSM6DSOX/ASM330LHH/ASM330LHHX/LSM6DSR/LSM6DSRX/ISM330DHCX/17 * Supported devices:
18 * LSM6DST/LSM6DSOP/LSM6DSTX/LSM6DSV/ASM330LHB:18 * - ISM330DLC
19 * - LSM6DS3
20 * - LSM6DS3H
21 * - LSM6DS3TR-C
22 * - LSM6DSL
23 * - LSM6DSM
24 *
25 * Tagged FIFO:
19 * The FIFO buffer can be configured to store data from gyroscope and26 * The FIFO buffer can be configured to store data from gyroscope and
20 * accelerometer. Each sample is queued with a tag (1B) indicating data27 * accelerometer. Each sample is queued with a tag (1B) indicating data
21 * source (gyroscope, accelerometer, hw timer).28 * source (gyroscope, accelerometer, hw timer).
22 *29 *
30 * Supported devices:
31 * - ASM330LHB
32 * - ASM330LHH
33 * - ASM330LHHX
34 * - ASM330LHHXG1
35 * - ISM330DHCX
36 * - LSM6DSO
37 * - LSM6DSOP
38 * - LSM6DSOX
39 * - LSM6DSR
40 * - LSM6DSRX
41 * - LSM6DST
42 * - LSM6DSTX
43 * - LSM6DSV
44 *
23 * FIFO supported modes:45 * FIFO supported modes:
24 * - BYPASS: FIFO disabled46 * - BYPASS: FIFO disabled
25 * - CONTINUOUS: FIFO enabled. When the buffer is full, the FIFO index47 * - CONTINUOUS: FIFO enabled. When the buffer is full, the FIFO index
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c+27−6
@@ -14,34 +14,51 @@ · 13 unmodified lines
14 * by a different driver.14 * by a different driver.
15 *15 *
16 * Supported sensors:16 * Supported sensors:
17 * - LSM6DS3:17 *
18 * - LSM6DS3
18 * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 41619 * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416
19 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-1620 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
20 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-200021 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
21 * - FIFO size: 8KB22 * - FIFO size: 8KB
22 *23 *
23 * - LSM6DS3H/LSM6DSL/LSM6DSM/ISM330DLC/LSM6DS3TR-C:24 * - ISM330DLC
25 * - LSM6DS3H
26 * - LSM6DS3TR-C
27 * - LSM6DSL
28 * - LSM6DSM
24 * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 41629 * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416
25 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-1630 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
26 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-200031 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
27 * - FIFO size: 4KB32 * - FIFO size: 4KB
28 *33 *
29 * - LSM6DSO/LSM6DSOX/ASM330LHH/ASM330LHHX/LSM6DSR/ISM330DHCX/LSM6DST/LSM6DSOP/34 * - ASM330LHH
30 * LSM6DSTX/LSM6DSO16IS/ISM330IS:35 * - ASM330LHHX
36 * - ASM330LHHXG1
37 * - ISM330DHCX
38 * - ISM330IS
39 * - LSM6DSO
40 * - LSM6DSO16IS
41 * - LSM6DSOP
42 * - LSM6DSOX
43 * - LSM6DSR
44 * - LSM6DST
45 * - LSM6DSTX
31 * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416,46 * - Accelerometer/Gyroscope supported ODR [Hz]: 12.5, 26, 52, 104, 208, 416,
32 * 83347 * 833
33 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-1648 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
34 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-200049 * - Gyroscope supported full-scale [dps]: +-125/+-245/+-500/+-1000/+-2000
35 * - FIFO size: 3KB50 * - FIFO size: 3KB
36 *51 *
37 * - LSM6DSV/LSM6DSV16X:52 * - LSM6DSV
53 * - LSM6DSV16X
38 * - Accelerometer/Gyroscope supported ODR [Hz]: 7.5, 15, 30, 60, 120, 240,54 * - Accelerometer/Gyroscope supported ODR [Hz]: 7.5, 15, 30, 60, 120, 240,
39 * 480, 96055 * 480, 960
40 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-1656 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
41 * - Gyroscope supported full-scale [dps]: +-125/+-250/+-500/+-1000/+-200057 * - Gyroscope supported full-scale [dps]: +-125/+-250/+-500/+-1000/+-2000
42 * - FIFO size: 3KB58 * - FIFO size: 3KB
43 *59 *
44 * - LSM9DS1/LSM6DS0:60 * - LSM6DS0
61 * - LSM9DS1
45 * - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 95262 * - Accelerometer supported ODR [Hz]: 10, 50, 119, 238, 476, 952
46 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-1663 * - Accelerometer supported full-scale [g]: +-2/+-4/+-8/+-16
47 * - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 95264 * - Gyroscope supported ODR [Hz]: 15, 60, 119, 238, 476, 952
@@ -820,6 +837,10 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { · 772 unmodified lines
820 .hw_id = ST_ASM330LHHX_ID,837 .hw_id = ST_ASM330LHHX_ID,
821 .name = ST_ASM330LHHX_DEV_NAME,838 .name = ST_ASM330LHHX_DEV_NAME,
822 .wai = 0x6b,839 .wai = 0x6b,
840 }, {
841 .hw_id = ST_ASM330LHHXG1_ID,
842 .name = ST_ASM330LHHXG1_DEV_NAME,
843 .wai = 0x6b,
823 }, {844 }, {
824 .hw_id = ST_LSM6DSTX_ID,845 .hw_id = ST_LSM6DSTX_ID,
825 .name = ST_LSM6DSTX_DEV_NAME,846 .name = ST_LSM6DSTX_DEV_NAME,
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c+5−0
@@ -134,6 +134,10 @@ static const struct of_device_id st_lsm6dsx_i2c_of_match[] = { · 133 unmodified lines
134 .compatible = "st,asm330lhb",134 .compatible = "st,asm330lhb",
135 .data = (void *)ST_ASM330LHB_ID,135 .data = (void *)ST_ASM330LHB_ID,
136 },136 },
137 {
138 .compatible = "st,asm330lhhxg1",
139 .data = (void *)ST_ASM330LHHXG1_ID,
140 },
137 {},141 {},
138};142};
139MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);143MODULE_DEVICE_TABLE(of, st_lsm6dsx_i2c_of_match);
@@ -168,6 +172,7 @@ static const struct i2c_device_id st_lsm6dsx_i2c_id_table[] = { · 28 unmodified lines
168 { ST_LSM6DSO16IS_DEV_NAME, ST_LSM6DSO16IS_ID },172 { ST_LSM6DSO16IS_DEV_NAME, ST_LSM6DSO16IS_ID },
169 { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID },173 { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID },
170 { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID },174 { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID },
175 { ST_ASM330LHHXG1_DEV_NAME, ST_ASM330LHHXG1_ID },
171 {},176 {},
172};177};
173MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);178MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c+5−0
@@ -129,6 +129,10 @@ static const struct of_device_id st_lsm6dsx_spi_of_match[] = { · 128 unmodified lines
129 .compatible = "st,asm330lhb",129 .compatible = "st,asm330lhb",
130 .data = (void *)ST_ASM330LHB_ID,130 .data = (void *)ST_ASM330LHB_ID,
131 },131 },
132 {
133 .compatible = "st,asm330lhhxg1",
134 .data = (void *)ST_ASM330LHHXG1_ID,
135 },
132 {},136 {},
133};137};
134MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);138MODULE_DEVICE_TABLE(of, st_lsm6dsx_spi_of_match);
@@ -157,6 +161,7 @@ static const struct spi_device_id st_lsm6dsx_spi_id_table[] = { · 22 unmodified lines
157 { ST_LSM6DSO16IS_DEV_NAME, ST_LSM6DSO16IS_ID },161 { ST_LSM6DSO16IS_DEV_NAME, ST_LSM6DSO16IS_ID },
158 { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID },162 { ST_ISM330IS_DEV_NAME, ST_ISM330IS_ID },
159 { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID },163 { ST_ASM330LHB_DEV_NAME, ST_ASM330LHB_ID },
164 { ST_ASM330LHHXG1_DEV_NAME, ST_ASM330LHHXG1_ID },
160 {},165 {},
161};166};
162MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);167MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
drivers/iio/imu/st_lsm9ds0/st_lsm9ds0.h+4−1
@@ -4,9 +4,12 @@ · 3 unmodified lines
4#ifndef ST_LSM9DS0_H4#ifndef ST_LSM9DS0_H
5#define ST_LSM9DS0_H5#define ST_LSM9DS0_H
6 6
7struct iio_dev;7struct device;
8struct regmap;
8struct regulator;9struct regulator;
9 10
11struct iio_dev;
12
10struct st_lsm9ds0 {13struct st_lsm9ds0 {
11 struct device *dev;14 struct device *dev;
12 const char *name;15 const char *name;
drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c+9−12
@@ -7,10 +7,10 @@ · 6 unmodified lines
7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
8 */8 */
9 9
10#include <linux/device.h>10#include <linux/array_size.h>
11#include <linux/dev_printk.h>
11#include <linux/err.h>12#include <linux/err.h>
12#include <linux/module.h>13#include <linux/module.h>
13#include <linux/regmap.h>
14#include <linux/regulator/consumer.h>14#include <linux/regulator/consumer.h>
15 15
16#include <linux/iio/common/st_sensors.h>16#include <linux/iio/common/st_sensors.h>
@@ -25,10 +25,9 @@ static int st_lsm9ds0_probe_accel(struct st_lsm9ds0 *lsm9ds0, struct regmap *reg · 8 unmodified lines
25 struct st_sensor_data *data;25 struct st_sensor_data *data;
26 26
27 settings = st_accel_get_settings(lsm9ds0->name);27 settings = st_accel_get_settings(lsm9ds0->name);
28 if (!settings) {28 if (!settings)
29 dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name);29 return dev_err_probe(dev, -ENODEV, "device name %s not recognized.\n",
30 return -ENODEV;30 lsm9ds0->name);
31 }
32 31
33 lsm9ds0->accel = devm_iio_device_alloc(dev, sizeof(*data));32 lsm9ds0->accel = devm_iio_device_alloc(dev, sizeof(*data));
34 if (!lsm9ds0->accel)33 if (!lsm9ds0->accel)
@@ -51,10 +50,9 @@ static int st_lsm9ds0_probe_magn(struct st_lsm9ds0 *lsm9ds0, struct regmap *regm · 16 unmodified lines
51 struct st_sensor_data *data;50 struct st_sensor_data *data;
52 51
53 settings = st_magn_get_settings(lsm9ds0->name);52 settings = st_magn_get_settings(lsm9ds0->name);
54 if (!settings) {53 if (!settings)
55 dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name);54 return dev_err_probe(dev, -ENODEV, "device name %s not recognized.\n",
56 return -ENODEV;55 lsm9ds0->name);
57 }
58 56
59 lsm9ds0->magn = devm_iio_device_alloc(dev, sizeof(*data));57 lsm9ds0->magn = devm_iio_device_alloc(dev, sizeof(*data));
60 if (!lsm9ds0->magn)58 if (!lsm9ds0->magn)
@@ -80,8 +78,7 @@ int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) · 19 unmodified lines
80 ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),78 ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
81 regulator_names);79 regulator_names);
82 if (ret)80 if (ret)
83 return dev_err_probe(dev, ret,81 return dev_err_probe(dev, ret, "unable to enable Vdd supply\n");
84 "unable to enable Vdd supply\n");
85 82
86 /* Setup accelerometer device */83 /* Setup accelerometer device */
87 ret = st_lsm9ds0_probe_accel(lsm9ds0, regmap);84 ret = st_lsm9ds0_probe_accel(lsm9ds0, regmap);
drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c+4−2
@@ -7,8 +7,10 @@ · 6 unmodified lines
7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
8 */8 */
9 9
10#include <linux/device.h>
11#include <linux/err.h>
12#include <linux/gfp_types.h>
10#include <linux/i2c.h>13#include <linux/i2c.h>
11#include <linux/kernel.h>
12#include <linux/module.h>14#include <linux/module.h>
13#include <linux/mod_devicetable.h>15#include <linux/mod_devicetable.h>
14#include <linux/regmap.h>16#include <linux/regmap.h>
@@ -39,7 +41,7 @@ MODULE_DEVICE_TABLE(i2c, st_lsm9ds0_id_table); · 24 unmodified lines
39 41
40static const struct acpi_device_id st_lsm9ds0_acpi_match[] = {42static const struct acpi_device_id st_lsm9ds0_acpi_match[] = {
41 {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME},43 {"ACCL0001", (kernel_ulong_t)LSM303D_IMU_DEV_NAME},
42 { },44 {}
43};45};
44MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match);46MODULE_DEVICE_TABLE(acpi, st_lsm9ds0_acpi_match);
45 47
drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c+3−1
@@ -7,7 +7,9 @@ · 6 unmodified lines
7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
8 */8 */
9 9
10#include <linux/kernel.h>10#include <linux/device.h>
11#include <linux/err.h>
12#include <linux/gfp_types.h>
11#include <linux/module.h>13#include <linux/module.h>
12#include <linux/mod_devicetable.h>14#include <linux/mod_devicetable.h>
13#include <linux/regmap.h>15#include <linux/regmap.h>
drivers/iio/industrialio-backend.c+418−0
@@ -0,0 +1,418 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Framework to handle complex IIO aggregate devices.
4 *
5 * The typical architecture is to have one device as the frontend device which
6 * can be "linked" against one or multiple backend devices. All the IIO and
7 * userspace interface is expected to be registers/managed by the frontend
8 * device which will callback into the backends when needed (to get/set some
9 * configuration that it does not directly control).
10 *
11 * -------------------------------------------------------
12 * ------------------ | ------------ ------------ ------- FPGA|
13 * | ADC |------------------------| | ADC CORE |---------| DMA CORE |------| RAM | |
14 * | (Frontend/IIO) | Serial Data (eg: LVDS) | |(backend) |---------| |------| | |
15 * | |------------------------| ------------ ------------ ------- |
16 * ------------------ -------------------------------------------------------
17 *
18 * The framework interface is pretty simple:
19 * - Backends should register themselves with devm_iio_backend_register()
20 * - Frontend devices should get backends with devm_iio_backend_get()
21 *
22 * Also to note that the primary target for this framework are converters like
23 * ADC/DACs so iio_backend_ops will have some operations typical of converter
24 * devices. On top of that, this is "generic" for all IIO which means any kind
25 * of device can make use of the framework. That said, If the iio_backend_ops
26 * struct begins to grow out of control, we can always refactor things so that
27 * the industrialio-backend.c is only left with the really generic stuff. Then,
28 * we can build on top of it depending on the needs.
29 *
30 * Copyright (C) 2023-2024 Analog Devices Inc.
31 */
32#define dev_fmt(fmt) "iio-backend: " fmt
33
34#include <linux/cleanup.h>
35#include <linux/device.h>
36#include <linux/err.h>
37#include <linux/errno.h>
38#include <linux/list.h>
39#include <linux/module.h>
40#include <linux/mutex.h>
41#include <linux/property.h>
42#include <linux/slab.h>
43#include <linux/types.h>
44
45#include <linux/iio/backend.h>
46
47struct iio_backend {
48 struct list_head entry;
49 const struct iio_backend_ops *ops;
50 struct device *dev;
51 struct module *owner;
52 void *priv;
53};
54
55/*
56 * Helper struct for requesting buffers. This ensures that we have all data
57 * that we need to free the buffer in a device managed action.
58 */
59struct iio_backend_buffer_pair {
60 struct iio_backend *back;
61 struct iio_buffer *buffer;
62};
63
64static LIST_HEAD(iio_back_list);
65static DEFINE_MUTEX(iio_back_lock);
66
67/*
68 * Helper macros to call backend ops. Makes sure the option is supported.
69 */
70#define iio_backend_check_op(back, op) ({ \
71 struct iio_backend *____back = back; \
72 int ____ret = 0; \
73 \
74 if (!____back->ops->op) \
75 ____ret = -EOPNOTSUPP; \
76 \
77 ____ret; \
78})
79
80#define iio_backend_op_call(back, op, args...) ({ \
81 struct iio_backend *__back = back; \
82 int __ret; \
83 \
84 __ret = iio_backend_check_op(__back, op); \
85 if (!__ret) \
86 __ret = __back->ops->op(__back, ##args); \
87 \
88 __ret; \
89})
90
91#define iio_backend_ptr_op_call(back, op, args...) ({ \
92 struct iio_backend *__back = back; \
93 void *ptr_err; \
94 int __ret; \
95 \
96 __ret = iio_backend_check_op(__back, op); \
97 if (__ret) \
98 ptr_err = ERR_PTR(__ret); \
99 else \
100 ptr_err = __back->ops->op(__back, ##args); \
101 \
102 ptr_err; \
103})
104
105#define iio_backend_void_op_call(back, op, args...) { \
106 struct iio_backend *__back = back; \
107 int __ret; \
108 \
109 __ret = iio_backend_check_op(__back, op); \
110 if (!__ret) \
111 __back->ops->op(__back, ##args); \
112}
113
114/**
115 * iio_backend_chan_enable - Enable a backend channel
116 * @back: Backend device
117 * @chan: Channel number
118 *
119 * RETURNS:
120 * 0 on success, negative error number on failure.
121 */
122int iio_backend_chan_enable(struct iio_backend *back, unsigned int chan)
123{
124 return iio_backend_op_call(back, chan_enable, chan);
125}
126EXPORT_SYMBOL_NS_GPL(iio_backend_chan_enable, IIO_BACKEND);
127
128/**
129 * iio_backend_chan_disable - Disable a backend channel
130 * @back: Backend device
131 * @chan: Channel number
132 *
133 * RETURNS:
134 * 0 on success, negative error number on failure.
135 */
136int iio_backend_chan_disable(struct iio_backend *back, unsigned int chan)
137{
138 return iio_backend_op_call(back, chan_disable, chan);
139}
140EXPORT_SYMBOL_NS_GPL(iio_backend_chan_disable, IIO_BACKEND);
141
142static void __iio_backend_disable(void *back)
143{
144 iio_backend_void_op_call(back, disable);
145}
146
147/**
148 * devm_iio_backend_enable - Device managed backend enable
149 * @dev: Consumer device for the backend
150 * @back: Backend device
151 *
152 * RETURNS:
153 * 0 on success, negative error number on failure.
154 */
155int devm_iio_backend_enable(struct device *dev, struct iio_backend *back)
156{
157 int ret;
158
159 ret = iio_backend_op_call(back, enable);
160 if (ret)
161 return ret;
162
163 return devm_add_action_or_reset(dev, __iio_backend_disable, back);
164}
165EXPORT_SYMBOL_NS_GPL(devm_iio_backend_enable, IIO_BACKEND);
166
167/**
168 * iio_backend_data_format_set - Configure the channel data format
169 * @back: Backend device
170 * @chan: Channel number
171 * @data: Data format
172 *
173 * Properly configure a channel with respect to the expected data format. A
174 * @struct iio_backend_data_fmt must be passed with the settings.
175 *
176 * RETURNS:
177 * 0 on success, negative error number on failure.
178 */
179int iio_backend_data_format_set(struct iio_backend *back, unsigned int chan,
180 const struct iio_backend_data_fmt *data)
181{
182 if (!data || data->type >= IIO_BACKEND_DATA_TYPE_MAX)
183 return -EINVAL;
184
185 return iio_backend_op_call(back, data_format_set, chan, data);
186}
187EXPORT_SYMBOL_NS_GPL(iio_backend_data_format_set, IIO_BACKEND);
188
189static void iio_backend_free_buffer(void *arg)
190{
191 struct iio_backend_buffer_pair *pair = arg;
192
193 iio_backend_void_op_call(pair->back, free_buffer, pair->buffer);
194}
195
196/**
197 * devm_iio_backend_request_buffer - Device managed buffer request
198 * @dev: Consumer device for the backend
199 * @back: Backend device
200 * @indio_dev: IIO device
201 *
202 * Request an IIO buffer from the backend. The type of the buffer (typically
203 * INDIO_BUFFER_HARDWARE) is up to the backend to decide. This is because,
204 * normally, the backend dictates what kind of buffering we can get.
205 *
206 * The backend .free_buffer() hooks is automatically called on @dev detach.
207 *
208 * RETURNS:
209 * 0 on success, negative error number on failure.
210 */
211int devm_iio_backend_request_buffer(struct device *dev,
212 struct iio_backend *back,
213 struct iio_dev *indio_dev)
214{
215 struct iio_backend_buffer_pair *pair;
216 struct iio_buffer *buffer;
217
218 pair = devm_kzalloc(dev, sizeof(*pair), GFP_KERNEL);
219 if (!pair)
220 return -ENOMEM;
221
222 buffer = iio_backend_ptr_op_call(back, request_buffer, indio_dev);
223 if (IS_ERR(buffer))
224 return PTR_ERR(buffer);
225
226 /* weak reference should be all what we need */
227 pair->back = back;
228 pair->buffer = buffer;
229
230 return devm_add_action_or_reset(dev, iio_backend_free_buffer, pair);
231}
232EXPORT_SYMBOL_NS_GPL(devm_iio_backend_request_buffer, IIO_BACKEND);
233
234static void iio_backend_release(void *arg)
235{
236 struct iio_backend *back = arg;
237
238 module_put(back->owner);
239}
240
241static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
242{
243 struct device_link *link;
244 int ret;
245
246 /*
247 * Make sure the provider cannot be unloaded before the consumer module.
248 * Note that device_links would still guarantee that nothing is
249 * accessible (and breaks) but this makes it explicit that the consumer
250 * module must be also unloaded.
251 */
252 if (!try_module_get(back->owner))
253 return dev_err_probe(dev, -ENODEV,
254 "Cannot get module reference\n");
255
256 ret = devm_add_action_or_reset(dev, iio_backend_release, back);
257 if (ret)
258 return ret;
259
260 link = device_link_add(dev, back->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
261 if (!link)
262 return dev_err_probe(dev, -EINVAL,
263 "Could not link to supplier(%s)\n",
264 dev_name(back->dev));
265
266 dev_dbg(dev, "Found backend(%s) device\n", dev_name(back->dev));
267
268 return 0;
269}
270
271/**
272 * devm_iio_backend_get - Device managed backend device get
273 * @dev: Consumer device for the backend
274 * @name: Backend name
275 *
276 * Get's the backend associated with @dev.
277 *
278 * RETURNS:
279 * A backend pointer, negative error pointer otherwise.
280 */
281struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name)
282{
283 struct fwnode_handle *fwnode;
284 struct iio_backend *back;
285 unsigned int index;
286 int ret;
287
288 if (name) {
289 ret = device_property_match_string(dev, "io-backend-names",
290 name);
291 if (ret < 0)
292 return ERR_PTR(ret);
293 index = ret;
294 } else {
295 index = 0;
296 }
297
298 fwnode = fwnode_find_reference(dev_fwnode(dev), "io-backends", index);
299 if (IS_ERR(fwnode)) {
300 dev_err_probe(dev, PTR_ERR(fwnode),
301 "Cannot get Firmware reference\n");
302 return ERR_CAST(fwnode);
303 }
304
305 guard(mutex)(&iio_back_lock);
306 list_for_each_entry(back, &iio_back_list, entry) {
307 if (!device_match_fwnode(back->dev, fwnode))
308 continue;
309
310 fwnode_handle_put(fwnode);
311 ret = __devm_iio_backend_get(dev, back);
312 if (ret)
313 return ERR_PTR(ret);
314
315 return back;
316 }
317
318 fwnode_handle_put(fwnode);
319 return ERR_PTR(-EPROBE_DEFER);
320}
321EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, IIO_BACKEND);
322
323/**
324 * __devm_iio_backend_get_from_fwnode_lookup - Device managed fwnode backend device get
325 * @dev: Consumer device for the backend
326 * @fwnode: Firmware node of the backend device
327 *
328 * Search the backend list for a device matching @fwnode.
329 * This API should not be used and it's only present for preventing the first
330 * user of this framework to break it's DT ABI.
331 *
332 * RETURNS:
333 * A backend pointer, negative error pointer otherwise.
334 */
335struct iio_backend *
336__devm_iio_backend_get_from_fwnode_lookup(struct device *dev,
337 struct fwnode_handle *fwnode)
338{
339 struct iio_backend *back;
340 int ret;
341
342 guard(mutex)(&iio_back_lock);
343 list_for_each_entry(back, &iio_back_list, entry) {
344 if (!device_match_fwnode(back->dev, fwnode))
345 continue;
346
347 ret = __devm_iio_backend_get(dev, back);
348 if (ret)
349 return ERR_PTR(ret);
350
351 return back;
352 }
353
354 return ERR_PTR(-EPROBE_DEFER);
355}
356EXPORT_SYMBOL_NS_GPL(__devm_iio_backend_get_from_fwnode_lookup, IIO_BACKEND);
357
358/**
359 * iio_backend_get_priv - Get driver private data
360 * @back: Backend device
361 */
362void *iio_backend_get_priv(const struct iio_backend *back)
363{
364 return back->priv;
365}
366EXPORT_SYMBOL_NS_GPL(iio_backend_get_priv, IIO_BACKEND);
367
368static void iio_backend_unregister(void *arg)
369{
370 struct iio_backend *back = arg;
371
372 guard(mutex)(&iio_back_lock);
373 list_del(&back->entry);
374}
375
376/**
377 * devm_iio_backend_register - Device managed backend device register
378 * @dev: Backend device being registered
379 * @ops: Backend ops
380 * @priv: Device private data
381 *
382 * @ops is mandatory. Not providing it results in -EINVAL.
383 *
384 * RETURNS:
385 * 0 on success, negative error number on failure.
386 */
387int devm_iio_backend_register(struct device *dev,
388 const struct iio_backend_ops *ops, void *priv)
389{
390 struct iio_backend *back;
391
392 if (!ops)
393 return dev_err_probe(dev, -EINVAL, "No backend ops given\n");
394
395 /*
396 * Through device_links, we guarantee that a frontend device cannot be
397 * bound/exist if the backend driver is not around. Hence, we can bind
398 * the backend object lifetime with the device being passed since
399 * removing it will tear the frontend/consumer down.
400 */
401 back = devm_kzalloc(dev, sizeof(*back), GFP_KERNEL);
402 if (!back)
403 return -ENOMEM;
404
405 back->ops = ops;
406 back->owner = dev->driver->owner;
407 back->dev = dev;
408 back->priv = priv;
409 scoped_guard(mutex, &iio_back_lock)
410 list_add(&back->entry, &iio_back_list);
411
412 return devm_add_action_or_reset(dev, iio_backend_unregister, back);
413}
414EXPORT_SYMBOL_NS_GPL(devm_iio_backend_register, IIO_BACKEND);
415
416MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
417MODULE_DESCRIPTION("Framework to handle complex IIO aggregate devices");
418MODULE_LICENSE("GPL");
drivers/iio/industrialio-core.c+2−4
@@ -42,7 +42,7 @@ static DEFINE_IDA(iio_ida); · 41 unmodified lines
42static dev_t iio_devt;42static dev_t iio_devt;
43 43
44#define IIO_DEV_MAX 25644#define IIO_DEV_MAX 256
45struct bus_type iio_bus_type = {45const struct bus_type iio_bus_type = {
46 .name = "iio",46 .name = "iio",
47};47};
48EXPORT_SYMBOL(iio_bus_type);48EXPORT_SYMBOL(iio_bus_type);
@@ -213,9 +213,7 @@ bool iio_buffer_enabled(struct iio_dev *indio_dev) · 164 unmodified lines
213{213{
214 struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);214 struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
215 215
216 return iio_dev_opaque->currentmode &216 return iio_dev_opaque->currentmode & INDIO_ALL_BUFFER_MODES;
217 (INDIO_BUFFER_HARDWARE | INDIO_BUFFER_SOFTWARE |
218 INDIO_BUFFER_TRIGGERED);
219}217}
220EXPORT_SYMBOL_GPL(iio_buffer_enabled);218EXPORT_SYMBOL_GPL(iio_buffer_enabled);
221 219
drivers/iio/industrialio-gts-helper.c+1−14
@@ -34,24 +34,11 @@ · 33 unmodified lines
34static int iio_gts_get_gain(const u64 max, const u64 scale)34static int iio_gts_get_gain(const u64 max, const u64 scale)
35{35{
36 u64 full = max;36 u64 full = max;
37 int tmp = 1;
38 37
39 if (scale > full || !scale)38 if (scale > full || !scale)
40 return -EINVAL;39 return -EINVAL;
41 40
42 if (U64_MAX - full < scale) {41 return div64_u64(full, scale);
43 /* Risk of overflow */
44 if (full - scale < scale)
45 return 1;
46
47 full -= scale;
48 tmp++;
49 }
50
51 while (full > scale * (u64)tmp)
52 tmp++;
53
54 return tmp;
55}42}
56 43
57/**44/**
drivers/iio/light/Kconfig+3−2
@@ -87,13 +87,14 @@ config APDS9960 · 86 unmodified lines
87 module will be called apds996087 module will be called apds9960
88 88
89config AS7321189config AS73211
90 tristate "AMS AS73211 XYZ color sensor"90 tristate "AMS AS73211 XYZ color sensor and AMS AS7331 UV sensor"
91 depends on I2C91 depends on I2C
92 select IIO_BUFFER92 select IIO_BUFFER
93 select IIO_TRIGGERED_BUFFER93 select IIO_TRIGGERED_BUFFER
94 help94 help
95 If you say yes here you get support for the AMS AS7321195 If you say yes here you get support for the AMS AS73211
96 JENCOLOR(R) Digital XYZ Sensor.96 JENCOLOR(R) Digital XYZ and the AMS AS7331 UVA, UVB and UVC
97 ultraviolet sensors.
97 98
98 For triggered measurements, you will need an additional trigger driver99 For triggered measurements, you will need an additional trigger driver
99 like IIO_HRTIMER_TRIGGER or IIO_SYSFS_TRIGGER.100 like IIO_HRTIMER_TRIGGER or IIO_SYSFS_TRIGGER.
drivers/iio/light/al3010.c+1−1
@@ -17,7 +17,7 @@ · 16 unmodified lines
17#include <linux/bitfield.h>17#include <linux/bitfield.h>
18#include <linux/i2c.h>18#include <linux/i2c.h>
19#include <linux/module.h>19#include <linux/module.h>
20#include <linux/of.h>20#include <linux/mod_devicetable.h>
21 21
22#include <linux/iio/iio.h>22#include <linux/iio/iio.h>
23#include <linux/iio/sysfs.h>23#include <linux/iio/sysfs.h>
drivers/iio/light/al3320a.c+0−1
@@ -15,7 +15,6 @@ · 14 unmodified lines
15#include <linux/bitfield.h>15#include <linux/bitfield.h>
16#include <linux/i2c.h>16#include <linux/i2c.h>
17#include <linux/module.h>17#include <linux/module.h>
18#include <linux/of.h>
19#include <linux/mod_devicetable.h>18#include <linux/mod_devicetable.h>
20 19
21#include <linux/iio/iio.h>20#include <linux/iio/iio.h>
drivers/iio/light/as73211.c+115−27
@@ -1,6 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0-only1// SPDX-License-Identifier: GPL-2.0-only
2/*2/*
3 * Support for AMS AS73211 JENCOLOR(R) Digital XYZ Sensor3 * Support for AMS AS73211 JENCOLOR(R) Digital XYZ Sensor and AMS AS7331
4 * UVA, UVB and UVC (DUV) Ultraviolet Sensor
4 *5 *
5 * Author: Christian Eggers <ceggers@arri.de>6 * Author: Christian Eggers <ceggers@arri.de>
6 *7 *
@@ -9,7 +10,9 @@ · 2 unmodified lines
9 * Color light sensor with 16-bit channels for x, y, z and temperature);10 * Color light sensor with 16-bit channels for x, y, z and temperature);
10 * 7-bit I2C slave address 0x74 .. 0x77.11 * 7-bit I2C slave address 0x74 .. 0x77.
11 *12 *
12 * Datasheet: https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf13 * Datasheets:
14 * AS73211: https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf
15 * AS7331: https://ams.com/documents/20143/9106314/AS7331_DS001047_4-00.pdf
13 */16 */
14 17
15#include <linux/bitfield.h>18#include <linux/bitfield.h>
@@ -84,6 +87,20 @@ static const int as73211_hardwaregain_avail[] = { · 68 unmodified lines
84 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,87 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
85};88};
86 89
90struct as73211_data;
91
92/**
93 * struct as73211_spec_dev_data - device-specific data
94 * @intensity_scale: Function to retrieve intensity scale values.
95 * @channels: Device channels.
96 * @num_channels: Number of channels of the device.
97 */
98struct as73211_spec_dev_data {
99 int (*intensity_scale)(struct as73211_data *data, int chan, int *val, int *val2);
100 struct iio_chan_spec const *channels;
101 int num_channels;
102};
103
87/**104/**
88 * struct as73211_data - Instance data for one AS73211105 * struct as73211_data - Instance data for one AS73211
89 * @client: I2C client.106 * @client: I2C client.
@@ -94,6 +111,7 @@ static const int as73211_hardwaregain_avail[] = { · 4 unmodified lines
94 * @mutex: Keeps cached registers in sync with the device.111 * @mutex: Keeps cached registers in sync with the device.
95 * @completion: Completion to wait for interrupt.112 * @completion: Completion to wait for interrupt.
96 * @int_time_avail: Available integration times (depend on sampling frequency).113 * @int_time_avail: Available integration times (depend on sampling frequency).
114 * @spec_dev: device-specific configuration.
97 */115 */
98struct as73211_data {116struct as73211_data {
99 struct i2c_client *client;117 struct i2c_client *client;
@@ -104,6 +122,7 @@ struct as73211_data { · 4 unmodified lines
104 struct mutex mutex;122 struct mutex mutex;
105 struct completion completion;123 struct completion completion;
106 int int_time_avail[AS73211_SAMPLE_TIME_NUM * 2];124 int int_time_avail[AS73211_SAMPLE_TIME_NUM * 2];
125 const struct as73211_spec_dev_data *spec_dev;
107};126};
108 127
109#define AS73211_COLOR_CHANNEL(_color, _si, _addr) { \128#define AS73211_COLOR_CHANNEL(_color, _si, _addr) { \
@@ -138,6 +157,10 @@ struct as73211_data { · 28 unmodified lines
138#define AS73211_SCALE_Y 298384270 /* nW/m^2 */157#define AS73211_SCALE_Y 298384270 /* nW/m^2 */
139#define AS73211_SCALE_Z 160241927 /* nW/m^2 */158#define AS73211_SCALE_Z 160241927 /* nW/m^2 */
140 159
160#define AS7331_SCALE_UVA 340000 /* nW/cm^2 */
161#define AS7331_SCALE_UVB 378000 /* nW/cm^2 */
162#define AS7331_SCALE_UVC 166000 /* nW/cm^2 */
163
141/* Channel order MUST match devices result register order */164/* Channel order MUST match devices result register order */
142#define AS73211_SCAN_INDEX_TEMP 0165#define AS73211_SCAN_INDEX_TEMP 0
143#define AS73211_SCAN_INDEX_X 1166#define AS73211_SCAN_INDEX_X 1
@@ -176,6 +199,28 @@ static const struct iio_chan_spec as73211_channels[] = { · 32 unmodified lines
176 IIO_CHAN_SOFT_TIMESTAMP(AS73211_SCAN_INDEX_TS),199 IIO_CHAN_SOFT_TIMESTAMP(AS73211_SCAN_INDEX_TS),
177};200};
178 201
202static const struct iio_chan_spec as7331_channels[] = {
203 {
204 .type = IIO_TEMP,
205 .info_mask_separate =
206 BIT(IIO_CHAN_INFO_RAW) |
207 BIT(IIO_CHAN_INFO_OFFSET) |
208 BIT(IIO_CHAN_INFO_SCALE),
209 .address = AS73211_OUT_TEMP,
210 .scan_index = AS73211_SCAN_INDEX_TEMP,
211 .scan_type = {
212 .sign = 'u',
213 .realbits = 16,
214 .storagebits = 16,
215 .endianness = IIO_LE,
216 }
217 },
218 AS73211_COLOR_CHANNEL(LIGHT_UVA, AS73211_SCAN_INDEX_X, AS73211_OUT_MRES1),
219 AS73211_COLOR_CHANNEL(LIGHT_UVB, AS73211_SCAN_INDEX_Y, AS73211_OUT_MRES2),
220 AS73211_COLOR_CHANNEL(LIGHT_DUV, AS73211_SCAN_INDEX_Z, AS73211_OUT_MRES3),
221 IIO_CHAN_SOFT_TIMESTAMP(AS73211_SCAN_INDEX_TS),
222};
223
179static unsigned int as73211_integration_time_1024cyc(struct as73211_data *data)224static unsigned int as73211_integration_time_1024cyc(struct as73211_data *data)
180{225{
181 /*226 /*
@@ -316,6 +361,48 @@ static int as73211_req_data(struct as73211_data *data) · 134 unmodified lines
316 return 0;361 return 0;
317}362}
318 363
364static int as73211_intensity_scale(struct as73211_data *data, int chan,
365 int *val, int *val2)
366{
367 switch (chan) {
368 case IIO_MOD_X:
369 *val = AS73211_SCALE_X;
370 break;
371 case IIO_MOD_Y:
372 *val = AS73211_SCALE_Y;
373 break;
374 case IIO_MOD_Z:
375 *val = AS73211_SCALE_Z;
376 break;
377 default:
378 return -EINVAL;
379 }
380 *val2 = as73211_integration_time_1024cyc(data) * as73211_gain(data);
381
382 return IIO_VAL_FRACTIONAL;
383}
384
385static int as7331_intensity_scale(struct as73211_data *data, int chan,
386 int *val, int *val2)
387{
388 switch (chan) {
389 case IIO_MOD_LIGHT_UVA:
390 *val = AS7331_SCALE_UVA;
391 break;
392 case IIO_MOD_LIGHT_UVB:
393 *val = AS7331_SCALE_UVB;
394 break;
395 case IIO_MOD_LIGHT_DUV:
396 *val = AS7331_SCALE_UVC;
397 break;
398 default:
399 return -EINVAL;
400 }
401 *val2 = as73211_integration_time_1024cyc(data) * as73211_gain(data);
402
403 return IIO_VAL_FRACTIONAL;
404}
405
319static int as73211_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,406static int as73211_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
320 int *val, int *val2, long mask)407 int *val, int *val2, long mask)
321{408{
@@ -355,30 +442,13 @@ static int as73211_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec cons · 33 unmodified lines
355 *val2 = AS73211_SCALE_TEMP_MICRO;442 *val2 = AS73211_SCALE_TEMP_MICRO;
356 return IIO_VAL_INT_PLUS_MICRO;443 return IIO_VAL_INT_PLUS_MICRO;
357 444
358 case IIO_INTENSITY: {445 case IIO_INTENSITY:
359 unsigned int scale;446 return data->spec_dev->intensity_scale(data, chan->channel2,
360 447 val, val2);
361 switch (chan->channel2) {
362 case IIO_MOD_X:
363 scale = AS73211_SCALE_X;
364 break;
365 case IIO_MOD_Y:
366 scale = AS73211_SCALE_Y;
367 break;
368 case IIO_MOD_Z:
369 scale = AS73211_SCALE_Z;
370 break;
371 default:
372 return -EINVAL;
373 }
374 scale /= as73211_gain(data);
375 scale /= as73211_integration_time_1024cyc(data);
376 *val = scale;
377 return IIO_VAL_INT;
378 448
379 default:449 default:
380 return -EINVAL;450 return -EINVAL;
381 }}451 }
382 452
383 case IIO_CHAN_INFO_SAMP_FREQ:453 case IIO_CHAN_INFO_SAMP_FREQ:
384 /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz) */454 /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz) */
@@ -676,13 +746,17 @@ static int as73211_probe(struct i2c_client *client) · 291 unmodified lines
676 i2c_set_clientdata(client, indio_dev);746 i2c_set_clientdata(client, indio_dev);
677 data->client = client;747 data->client = client;
678 748
749 data->spec_dev = i2c_get_match_data(client);
750 if (!data->spec_dev)
751 return -EINVAL;
752
679 mutex_init(&data->mutex);753 mutex_init(&data->mutex);
680 init_completion(&data->completion);754 init_completion(&data->completion);
681 755
682 indio_dev->info = &as73211_info;756 indio_dev->info = &as73211_info;
683 indio_dev->name = AS73211_DRV_NAME;757 indio_dev->name = AS73211_DRV_NAME;
684 indio_dev->channels = as73211_channels;758 indio_dev->channels = data->spec_dev->channels;
685 indio_dev->num_channels = ARRAY_SIZE(as73211_channels);759 indio_dev->num_channels = data->spec_dev->num_channels;
686 indio_dev->modes = INDIO_DIRECT_MODE;760 indio_dev->modes = INDIO_DIRECT_MODE;
687 761
688 ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_OSR);762 ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_OSR);
@@ -772,14 +846,28 @@ static int as73211_resume(struct device *dev) · 83 unmodified lines
772static DEFINE_SIMPLE_DEV_PM_OPS(as73211_pm_ops, as73211_suspend,846static DEFINE_SIMPLE_DEV_PM_OPS(as73211_pm_ops, as73211_suspend,
773 as73211_resume);847 as73211_resume);
774 848
849static const struct as73211_spec_dev_data as73211_spec = {
850 .intensity_scale = as73211_intensity_scale,
851 .channels = as73211_channels,
852 .num_channels = ARRAY_SIZE(as73211_channels),
853};
854
855static const struct as73211_spec_dev_data as7331_spec = {
856 .intensity_scale = as7331_intensity_scale,
857 .channels = as7331_channels,
858 .num_channels = ARRAY_SIZE(as7331_channels),
859};
860
775static const struct of_device_id as73211_of_match[] = {861static const struct of_device_id as73211_of_match[] = {
776 { .compatible = "ams,as73211" },862 { .compatible = "ams,as73211", &as73211_spec },
863 { .compatible = "ams,as7331", &as7331_spec },
777 { }864 { }
778};865};
779MODULE_DEVICE_TABLE(of, as73211_of_match);866MODULE_DEVICE_TABLE(of, as73211_of_match);
780 867
781static const struct i2c_device_id as73211_id[] = {868static const struct i2c_device_id as73211_id[] = {
782 { "as73211", 0 },869 { "as73211", (kernel_ulong_t)&as73211_spec },
870 { "as7331", (kernel_ulong_t)&as7331_spec },
783 { }871 { }
784};872};
785MODULE_DEVICE_TABLE(i2c, as73211_id);873MODULE_DEVICE_TABLE(i2c, as73211_id);
drivers/iio/light/hid-sensor-als.c+104−18
@@ -14,8 +14,11 @@ · 13 unmodified lines
14#include "../common/hid-sensors/hid-sensor-trigger.h"14#include "../common/hid-sensors/hid-sensor-trigger.h"
15 15
16enum {16enum {
17 CHANNEL_SCAN_INDEX_INTENSITY = 0,17 CHANNEL_SCAN_INDEX_INTENSITY,
18 CHANNEL_SCAN_INDEX_ILLUM = 1,18 CHANNEL_SCAN_INDEX_ILLUM,
19 CHANNEL_SCAN_INDEX_COLOR_TEMP,
20 CHANNEL_SCAN_INDEX_CHROMATICITY_X,
21 CHANNEL_SCAN_INDEX_CHROMATICITY_Y,
19 CHANNEL_SCAN_INDEX_MAX22 CHANNEL_SCAN_INDEX_MAX
20};23};
21 24
@@ -25,6 +28,7 @@ struct als_state { · 3 unmodified lines
25 struct hid_sensor_hub_callbacks callbacks;28 struct hid_sensor_hub_callbacks callbacks;
26 struct hid_sensor_common common_attributes;29 struct hid_sensor_common common_attributes;
27 struct hid_sensor_hub_attribute_info als[CHANNEL_SCAN_INDEX_MAX];30 struct hid_sensor_hub_attribute_info als[CHANNEL_SCAN_INDEX_MAX];
31 struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1];
28 struct {32 struct {
29 u32 illum[CHANNEL_SCAN_INDEX_MAX];33 u32 illum[CHANNEL_SCAN_INDEX_MAX];
30 u64 timestamp __aligned(8);34 u64 timestamp __aligned(8);
@@ -33,7 +37,18 @@ struct als_state { · 2 unmodified lines
33 int scale_post_decml;37 int scale_post_decml;
34 int scale_precision;38 int scale_precision;
35 int value_offset;39 int value_offset;
40 int num_channels;
36 s64 timestamp;41 s64 timestamp;
42 unsigned long als_scan_mask[2];
43};
44
45/* The order of usage ids must match scan index starting from CHANNEL_SCAN_INDEX_INTENSITY */
46static const u32 als_usage_ids[] = {
47 HID_USAGE_SENSOR_LIGHT_ILLUM,
48 HID_USAGE_SENSOR_LIGHT_ILLUM,
49 HID_USAGE_SENSOR_LIGHT_COLOR_TEMPERATURE,
50 HID_USAGE_SENSOR_LIGHT_CHROMATICITY_X,
51 HID_USAGE_SENSOR_LIGHT_CHROMATICITY_Y,
37};52};
38 53
39static const u32 als_sensitivity_addresses[] = {54static const u32 als_sensitivity_addresses[] = {
@@ -65,6 +80,40 @@ static const struct iio_chan_spec als_channels[] = { · 25 unmodified lines
65 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),80 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
66 .scan_index = CHANNEL_SCAN_INDEX_ILLUM,81 .scan_index = CHANNEL_SCAN_INDEX_ILLUM,
67 },82 },
83 {
84 .type = IIO_COLORTEMP,
85 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
86 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
87 BIT(IIO_CHAN_INFO_SCALE) |
88 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
89 BIT(IIO_CHAN_INFO_HYSTERESIS) |
90 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
91 .scan_index = CHANNEL_SCAN_INDEX_COLOR_TEMP,
92 },
93 {
94 .type = IIO_CHROMATICITY,
95 .modified = 1,
96 .channel2 = IIO_MOD_X,
97 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
98 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
99 BIT(IIO_CHAN_INFO_SCALE) |
100 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
101 BIT(IIO_CHAN_INFO_HYSTERESIS) |
102 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
103 .scan_index = CHANNEL_SCAN_INDEX_CHROMATICITY_X,
104 },
105 {
106 .type = IIO_CHROMATICITY,
107 .modified = 1,
108 .channel2 = IIO_MOD_Y,
109 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
110 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
111 BIT(IIO_CHAN_INFO_SCALE) |
112 BIT(IIO_CHAN_INFO_SAMP_FREQ) |
113 BIT(IIO_CHAN_INFO_HYSTERESIS) |
114 BIT(IIO_CHAN_INFO_HYSTERESIS_RELATIVE),
115 .scan_index = CHANNEL_SCAN_INDEX_CHROMATICITY_Y,
116 },
68 IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)117 IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
69};118};
70 119
@@ -103,6 +152,21 @@ static int als_read_raw(struct iio_dev *indio_dev, · 32 unmodified lines
103 min = als_state->als[chan->scan_index].logical_minimum;152 min = als_state->als[chan->scan_index].logical_minimum;
104 address = HID_USAGE_SENSOR_LIGHT_ILLUM;153 address = HID_USAGE_SENSOR_LIGHT_ILLUM;
105 break;154 break;
155 case CHANNEL_SCAN_INDEX_COLOR_TEMP:
156 report_id = als_state->als[chan->scan_index].report_id;
157 min = als_state->als[chan->scan_index].logical_minimum;
158 address = HID_USAGE_SENSOR_LIGHT_COLOR_TEMPERATURE;
159 break;
160 case CHANNEL_SCAN_INDEX_CHROMATICITY_X:
161 report_id = als_state->als[chan->scan_index].report_id;
162 min = als_state->als[chan->scan_index].logical_minimum;
163 address = HID_USAGE_SENSOR_LIGHT_CHROMATICITY_X;
164 break;
165 case CHANNEL_SCAN_INDEX_CHROMATICITY_Y:
166 report_id = als_state->als[chan->scan_index].report_id;
167 min = als_state->als[chan->scan_index].logical_minimum;
168 address = HID_USAGE_SENSOR_LIGHT_CHROMATICITY_Y;
169 break;
106 default:170 default:
107 report_id = -1;171 report_id = -1;
108 break;172 break;
@@ -223,6 +287,18 @@ static int als_capture_sample(struct hid_sensor_hub_device *hsdev, · 114 unmodified lines
223 als_state->scan.illum[CHANNEL_SCAN_INDEX_ILLUM] = sample_data;287 als_state->scan.illum[CHANNEL_SCAN_INDEX_ILLUM] = sample_data;
224 ret = 0;288 ret = 0;
225 break;289 break;
290 case HID_USAGE_SENSOR_LIGHT_COLOR_TEMPERATURE:
291 als_state->scan.illum[CHANNEL_SCAN_INDEX_COLOR_TEMP] = sample_data;
292 ret = 0;
293 break;
294 case HID_USAGE_SENSOR_LIGHT_CHROMATICITY_X:
295 als_state->scan.illum[CHANNEL_SCAN_INDEX_CHROMATICITY_X] = sample_data;
296 ret = 0;
297 break;
298 case HID_USAGE_SENSOR_LIGHT_CHROMATICITY_Y:
299 als_state->scan.illum[CHANNEL_SCAN_INDEX_CHROMATICITY_Y] = sample_data;
300 ret = 0;
301 break;
226 case HID_USAGE_SENSOR_TIME_TIMESTAMP:302 case HID_USAGE_SENSOR_TIME_TIMESTAMP:
227 als_state->timestamp = hid_sensor_convert_timestamp(&als_state->common_attributes,303 als_state->timestamp = hid_sensor_convert_timestamp(&als_state->common_attributes,
228 *(s64 *)raw_data);304 *(s64 *)raw_data);
@@ -238,27 +314,38 @@ static int als_capture_sample(struct hid_sensor_hub_device *hsdev, · 9 unmodified lines
238/* Parse report which is specific to an usage id*/314/* Parse report which is specific to an usage id*/
239static int als_parse_report(struct platform_device *pdev,315static int als_parse_report(struct platform_device *pdev,
240 struct hid_sensor_hub_device *hsdev,316 struct hid_sensor_hub_device *hsdev,
241 struct iio_chan_spec *channels,
242 unsigned usage_id,317 unsigned usage_id,
243 struct als_state *st)318 struct als_state *st)
244{319{
245 int ret;320 struct iio_chan_spec *channels;
321 int ret, index = 0;
246 int i;322 int i;
247 323
248 for (i = 0; i <= CHANNEL_SCAN_INDEX_ILLUM; ++i) {324 channels = st->channels;
325
326 for (i = 0; i < CHANNEL_SCAN_INDEX_MAX; ++i) {
249 ret = sensor_hub_input_get_attribute_info(hsdev,327 ret = sensor_hub_input_get_attribute_info(hsdev,
250 HID_INPUT_REPORT,328 HID_INPUT_REPORT,
251 usage_id,329 usage_id,
252 HID_USAGE_SENSOR_LIGHT_ILLUM,330 als_usage_ids[i],
253 &st->als[i]);331 &st->als[i]);
254 if (ret < 0)332 if (ret < 0)
255 return ret;333 continue;
256 als_adjust_channel_bit_mask(channels, i, st->als[i].size);334
335 channels[index] = als_channels[i];
336 st->als_scan_mask[0] |= BIT(i);
337 als_adjust_channel_bit_mask(channels, index, st->als[i].size);
338 ++index;
257 339
258 dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index,340 dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index,
259 st->als[i].report_id);341 st->als[i].report_id);
260 }342 }
261 343
344 st->num_channels = index;
345 /* Return success even if one usage id is present */
346 if (index)
347 ret = 0;
348
262 st->scale_precision = hid_sensor_format_scale(usage_id,349 st->scale_precision = hid_sensor_format_scale(usage_id,
263 &st->als[CHANNEL_SCAN_INDEX_INTENSITY],350 &st->als[CHANNEL_SCAN_INDEX_INTENSITY],
264 &st->scale_pre_decml, &st->scale_post_decml);351 &st->scale_pre_decml, &st->scale_post_decml);
@@ -294,15 +381,7 @@ static int hid_als_probe(struct platform_device *pdev) · 29 unmodified lines
294 return ret;381 return ret;
295 }382 }
296 383
297 indio_dev->channels = devm_kmemdup(&pdev->dev, als_channels,
298 sizeof(als_channels), GFP_KERNEL);
299 if (!indio_dev->channels) {
300 dev_err(&pdev->dev, "failed to duplicate channels\n");
301 return -ENOMEM;
302 }
303
304 ret = als_parse_report(pdev, hsdev,384 ret = als_parse_report(pdev, hsdev,
305 (struct iio_chan_spec *)indio_dev->channels,
306 hsdev->usage,385 hsdev->usage,
307 als_state);386 als_state);
308 if (ret) {387 if (ret) {
@@ -310,8 +389,15 @@ static int hid_als_probe(struct platform_device *pdev) · 1 unmodified line
310 return ret;389 return ret;
311 }390 }
312 391
313 indio_dev->num_channels =392 /* Add timestamp channel */
314 ARRAY_SIZE(als_channels);393 als_state->channels[als_state->num_channels] = als_channels[CHANNEL_SCAN_INDEX_TIMESTAMP];
394
395 /* +1 for adding timestamp channel */
396 indio_dev->num_channels = als_state->num_channels + 1;
397
398 indio_dev->channels = als_state->channels;
399 indio_dev->available_scan_masks = als_state->als_scan_mask;
400
315 indio_dev->info = &als_info;401 indio_dev->info = &als_info;
316 indio_dev->name = name;402 indio_dev->name = name;
317 indio_dev->modes = INDIO_DIRECT_MODE;403 indio_dev->modes = INDIO_DIRECT_MODE;
drivers/iio/light/jsa1212.c+2−2
@@ -12,10 +12,10 @@ · 11 unmodified lines
12#include <linux/kernel.h>12#include <linux/kernel.h>
13#include <linux/slab.h>13#include <linux/slab.h>
14#include <linux/module.h>14#include <linux/module.h>
15#include <linux/mod_devicetable.h>
15#include <linux/delay.h>16#include <linux/delay.h>
16#include <linux/i2c.h>17#include <linux/i2c.h>
17#include <linux/mutex.h>18#include <linux/mutex.h>
18#include <linux/acpi.h>
19#include <linux/regmap.h>19#include <linux/regmap.h>
20#include <linux/iio/iio.h>20#include <linux/iio/iio.h>
21#include <linux/iio/sysfs.h>21#include <linux/iio/sysfs.h>
@@ -438,7 +438,7 @@ static struct i2c_driver jsa1212_driver = { · 416 unmodified lines
438 .driver = {438 .driver = {
439 .name = JSA1212_DRIVER_NAME,439 .name = JSA1212_DRIVER_NAME,
440 .pm = pm_sleep_ptr(&jsa1212_pm_ops),440 .pm = pm_sleep_ptr(&jsa1212_pm_ops),
441 .acpi_match_table = ACPI_PTR(jsa1212_acpi_match),441 .acpi_match_table = jsa1212_acpi_match,
442 },442 },
443 .probe = jsa1212_probe,443 .probe = jsa1212_probe,
444 .remove = jsa1212_remove,444 .remove = jsa1212_remove,
drivers/iio/light/ltr501.c+2−1
@@ -10,6 +10,7 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/module.h>12#include <linux/module.h>
13#include <linux/mod_devicetable.h>
13#include <linux/i2c.h>14#include <linux/i2c.h>
14#include <linux/err.h>15#include <linux/err.h>
15#include <linux/delay.h>16#include <linux/delay.h>
@@ -1639,7 +1640,7 @@ static struct i2c_driver ltr501_driver = { · 1623 unmodified lines
1639 .name = LTR501_DRV_NAME,1640 .name = LTR501_DRV_NAME,
1640 .of_match_table = ltr501_of_match,1641 .of_match_table = ltr501_of_match,
1641 .pm = pm_sleep_ptr(&ltr501_pm_ops),1642 .pm = pm_sleep_ptr(&ltr501_pm_ops),
1642 .acpi_match_table = ACPI_PTR(ltr_acpi_match),1643 .acpi_match_table = ltr_acpi_match,
1643 },1644 },
1644 .probe = ltr501_probe,1645 .probe = ltr501_probe,
1645 .remove = ltr501_remove,1646 .remove = ltr501_remove,
drivers/iio/light/max44000.c+2−4
@@ -10,6 +10,7 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/module.h>12#include <linux/module.h>
13#include <linux/mod_devicetable.h>
13#include <linux/init.h>14#include <linux/init.h>
14#include <linux/i2c.h>15#include <linux/i2c.h>
15#include <linux/regmap.h>16#include <linux/regmap.h>
@@ -19,7 +20,6 @@ · 3 unmodified lines
19#include <linux/iio/buffer.h>20#include <linux/iio/buffer.h>
20#include <linux/iio/trigger_consumer.h>21#include <linux/iio/trigger_consumer.h>
21#include <linux/iio/triggered_buffer.h>22#include <linux/iio/triggered_buffer.h>
22#include <linux/acpi.h>
23 23
24#define MAX44000_DRV_NAME "max44000"24#define MAX44000_DRV_NAME "max44000"
25 25
@@ -603,18 +603,16 @@ static const struct i2c_device_id max44000_id[] = { · 577 unmodified lines
603};603};
604MODULE_DEVICE_TABLE(i2c, max44000_id);604MODULE_DEVICE_TABLE(i2c, max44000_id);
605 605
606#ifdef CONFIG_ACPI
607static const struct acpi_device_id max44000_acpi_match[] = {606static const struct acpi_device_id max44000_acpi_match[] = {
608 {"MAX44000", 0},607 {"MAX44000", 0},
609 { }608 { }
610};609};
611MODULE_DEVICE_TABLE(acpi, max44000_acpi_match);610MODULE_DEVICE_TABLE(acpi, max44000_acpi_match);
612#endif
613 611
614static struct i2c_driver max44000_driver = {612static struct i2c_driver max44000_driver = {
615 .driver = {613 .driver = {
616 .name = MAX44000_DRV_NAME,614 .name = MAX44000_DRV_NAME,
617 .acpi_match_table = ACPI_PTR(max44000_acpi_match),615 .acpi_match_table = max44000_acpi_match,
618 },616 },
619 .probe = max44000_probe,617 .probe = max44000_probe,
620 .id_table = max44000_id,618 .id_table = max44000_id,
drivers/iio/light/rpr0521.c+2−2
@@ -10,11 +10,11 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/module.h>12#include <linux/module.h>
13#include <linux/mod_devicetable.h>
13#include <linux/init.h>14#include <linux/init.h>
14#include <linux/i2c.h>15#include <linux/i2c.h>
15#include <linux/regmap.h>16#include <linux/regmap.h>
16#include <linux/delay.h>17#include <linux/delay.h>
17#include <linux/acpi.h>
18 18
19#include <linux/iio/iio.h>19#include <linux/iio/iio.h>
20#include <linux/iio/buffer.h>20#include <linux/iio/buffer.h>
@@ -1119,7 +1119,7 @@ static struct i2c_driver rpr0521_driver = { · 1098 unmodified lines
1119 .driver = {1119 .driver = {
1120 .name = RPR0521_DRV_NAME,1120 .name = RPR0521_DRV_NAME,
1121 .pm = pm_ptr(&rpr0521_pm_ops),1121 .pm = pm_ptr(&rpr0521_pm_ops),
1122 .acpi_match_table = ACPI_PTR(rpr0521_acpi_match),1122 .acpi_match_table = rpr0521_acpi_match,
1123 },1123 },
1124 .probe = rpr0521_probe,1124 .probe = rpr0521_probe,
1125 .remove = rpr0521_remove,1125 .remove = rpr0521_remove,
drivers/iio/light/stk3310.c+2−2
@@ -7,11 +7,11 @@ · 6 unmodified lines
7 * IIO driver for STK3310/STK3311. 7-bit I2C address: 0x48.7 * IIO driver for STK3310/STK3311. 7-bit I2C address: 0x48.
8 */8 */
9 9
10#include <linux/acpi.h>
11#include <linux/i2c.h>10#include <linux/i2c.h>
12#include <linux/interrupt.h>11#include <linux/interrupt.h>
13#include <linux/kernel.h>12#include <linux/kernel.h>
14#include <linux/module.h>13#include <linux/module.h>
14#include <linux/mod_devicetable.h>
15#include <linux/regmap.h>15#include <linux/regmap.h>
16#include <linux/iio/events.h>16#include <linux/iio/events.h>
17#include <linux/iio/iio.h>17#include <linux/iio/iio.h>
@@ -712,7 +712,7 @@ static struct i2c_driver stk3310_driver = { · 694 unmodified lines
712 .name = "stk3310",712 .name = "stk3310",
713 .of_match_table = stk3310_of_match,713 .of_match_table = stk3310_of_match,
714 .pm = pm_sleep_ptr(&stk3310_pm_ops),714 .pm = pm_sleep_ptr(&stk3310_pm_ops),
715 .acpi_match_table = ACPI_PTR(stk3310_acpi_id),715 .acpi_match_table = stk3310_acpi_id,
716 },716 },
717 .probe = stk3310_probe,717 .probe = stk3310_probe,
718 .remove = stk3310_remove,718 .remove = stk3310_remove,
drivers/iio/light/us5182d.c+2−2
@@ -9,7 +9,7 @@ · 8 unmodified lines
9 9
10#include <linux/kernel.h>10#include <linux/kernel.h>
11#include <linux/module.h>11#include <linux/module.h>
12#include <linux/acpi.h>12#include <linux/mod_devicetable.h>
13#include <linux/delay.h>13#include <linux/delay.h>
14#include <linux/i2c.h>14#include <linux/i2c.h>
15#include <linux/iio/events.h>15#include <linux/iio/events.h>
@@ -972,7 +972,7 @@ static struct i2c_driver us5182d_driver = { · 956 unmodified lines
972 .name = US5182D_DRV_NAME,972 .name = US5182D_DRV_NAME,
973 .pm = pm_ptr(&us5182d_pm_ops),973 .pm = pm_ptr(&us5182d_pm_ops),
974 .of_match_table = us5182d_of_match,974 .of_match_table = us5182d_of_match,
975 .acpi_match_table = ACPI_PTR(us5182d_acpi_match),975 .acpi_match_table = us5182d_acpi_match,
976 },976 },
977 .probe = us5182d_probe,977 .probe = us5182d_probe,
978 .remove = us5182d_remove,978 .remove = us5182d_remove,
drivers/iio/light/vcnl4000.c+35−1
@@ -90,6 +90,7 @@ · 89 unmodified lines
90#define VCNL4040_PS_CONF1_PS_SHUTDOWN BIT(0)90#define VCNL4040_PS_CONF1_PS_SHUTDOWN BIT(0)
91#define VCNL4040_PS_CONF2_PS_IT GENMASK(3, 1) /* Proximity integration time */91#define VCNL4040_PS_CONF2_PS_IT GENMASK(3, 1) /* Proximity integration time */
92#define VCNL4040_CONF1_PS_PERS GENMASK(5, 4) /* Proximity interrupt persistence setting */92#define VCNL4040_CONF1_PS_PERS GENMASK(5, 4) /* Proximity interrupt persistence setting */
93#define VCNL4040_PS_CONF2_PS_HD BIT(11) /* Proximity high definition */
93#define VCNL4040_PS_CONF2_PS_INT GENMASK(9, 8) /* Proximity interrupt mode */94#define VCNL4040_PS_CONF2_PS_INT GENMASK(9, 8) /* Proximity interrupt mode */
94#define VCNL4040_PS_CONF3_MPS GENMASK(6, 5) /* Proximity multi pulse number */95#define VCNL4040_PS_CONF3_MPS GENMASK(6, 5) /* Proximity multi pulse number */
95#define VCNL4040_PS_MS_LED_I GENMASK(10, 8) /* Proximity current */96#define VCNL4040_PS_MS_LED_I GENMASK(10, 8) /* Proximity current */
@@ -114,6 +115,13 @@ · 18 unmodified lines
114#define VCNL4010_INT_DRDY \115#define VCNL4010_INT_DRDY \
115 (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))116 (BIT(VCNL4010_INT_PROXIMITY) | BIT(VCNL4010_INT_ALS))
116 117
118#define VCNL4040_CONF3_PS_MPS_16BITS 3 /* 8 multi pulses */
119#define VCNL4040_CONF3_PS_LED_I_16BITS 3 /* 120 mA */
120
121#define VCNL4040_CONF3_PS_SAMPLE_16BITS \
122 (FIELD_PREP(VCNL4040_PS_CONF3_MPS, VCNL4040_CONF3_PS_MPS_16BITS) | \
123 FIELD_PREP(VCNL4040_PS_MS_LED_I, VCNL4040_CONF3_PS_LED_I_16BITS))
124
117static const int vcnl4010_prox_sampling_frequency[][2] = {125static const int vcnl4010_prox_sampling_frequency[][2] = {
118 {1, 950000},126 {1, 950000},
119 {3, 906250},127 {3, 906250},
@@ -195,6 +203,7 @@ struct vcnl4000_data { · 75 unmodified lines
195 enum vcnl4000_device_ids id;203 enum vcnl4000_device_ids id;
196 int rev;204 int rev;
197 int al_scale;205 int al_scale;
206 int ps_scale;
198 u8 ps_int; /* proximity interrupt mode */207 u8 ps_int; /* proximity interrupt mode */
199 u8 als_int; /* ambient light interrupt mode*/208 u8 als_int; /* ambient light interrupt mode*/
200 const struct vcnl4000_chip_spec *chip_spec;209 const struct vcnl4000_chip_spec *chip_spec;
@@ -345,6 +354,7 @@ static int vcnl4200_set_power_state(struct vcnl4000_data *data, bool on) · 144 unmodified lines
345static int vcnl4200_init(struct vcnl4000_data *data)354static int vcnl4200_init(struct vcnl4000_data *data)
346{355{
347 int ret, id;356 int ret, id;
357 u16 regval;
348 358
349 ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);359 ret = i2c_smbus_read_word_data(data->client, VCNL4200_DEV_ID);
350 if (ret < 0)360 if (ret < 0)
@@ -386,9 +396,32 @@ static int vcnl4200_init(struct vcnl4000_data *data) · 35 unmodified lines
386 break;396 break;
387 }397 }
388 data->al_scale = data->chip_spec->ulux_step;398 data->al_scale = data->chip_spec->ulux_step;
399 data->ps_scale = 16;
389 mutex_init(&data->vcnl4200_al.lock);400 mutex_init(&data->vcnl4200_al.lock);
390 mutex_init(&data->vcnl4200_ps.lock);401 mutex_init(&data->vcnl4200_ps.lock);
391 402
403 /* Use 16 bits proximity sensor readings */
404 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF1);
405 if (ret < 0)
406 return ret;
407
408 regval = ret | VCNL4040_PS_CONF2_PS_HD;
409 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF1,
410 regval);
411 if (ret < 0)
412 return ret;
413
414 /* Align proximity sensor sample rate to 16 bits data width */
415 ret = i2c_smbus_read_word_data(data->client, VCNL4200_PS_CONF3);
416 if (ret < 0)
417 return ret;
418
419 regval = ret | VCNL4040_CONF3_PS_SAMPLE_16BITS;
420 ret = i2c_smbus_write_word_data(data->client, VCNL4200_PS_CONF3,
421 regval);
422 if (ret < 0)
423 return ret;
424
392 ret = data->chip_spec->set_power_state(data, true);425 ret = data->chip_spec->set_power_state(data, true);
393 if (ret < 0)426 if (ret < 0)
394 return ret;427 return ret;
@@ -901,8 +934,9 @@ static int vcnl4000_read_raw(struct iio_dev *indio_dev, · 506 unmodified lines
901 break;934 break;
902 case IIO_PROXIMITY:935 case IIO_PROXIMITY:
903 ret = data->chip_spec->measure_proximity(data, val);936 ret = data->chip_spec->measure_proximity(data, val);
937 *val2 = data->ps_scale;
904 if (!ret)938 if (!ret)
905 ret = IIO_VAL_INT;939 ret = IIO_VAL_FRACTIONAL;
906 break;940 break;
907 default:941 default:
908 ret = -EINVAL;942 ret = -EINVAL;
drivers/iio/light/vl6180.c+0−1
@@ -20,7 +20,6 @@ · 19 unmodified lines
20#include <linux/i2c.h>20#include <linux/i2c.h>
21#include <linux/mutex.h>21#include <linux/mutex.h>
22#include <linux/err.h>22#include <linux/err.h>
23#include <linux/of.h>
24#include <linux/delay.h>23#include <linux/delay.h>
25#include <linux/util_macros.h>24#include <linux/util_macros.h>
26 25
drivers/iio/magnetometer/Kconfig+12−0
@@ -6,6 +6,18 @@ · 5 unmodified lines
6 6
7menu "Magnetometer sensors"7menu "Magnetometer sensors"
8 8
9config AF8133J
10 tristate "Voltafield AF8133J 3-Axis Magnetometer"
11 depends on I2C
12 depends on OF
13 select REGMAP_I2C
14 help
15 Say yes here to build support for Voltafield AF8133J I2C-based
16 3-axis magnetometer chip.
17
18 To compile this driver as a module, choose M here: the module
19 will be called af8133j.
20
9config AK897421config AK8974
10 tristate "Asahi Kasei AK8974 3-Axis Magnetometer"22 tristate "Asahi Kasei AK8974 3-Axis Magnetometer"
11 depends on I2C23 depends on I2C
drivers/iio/magnetometer/Makefile+1−0
@@ -4,6 +4,7 @@ · 3 unmodified lines
4#4#
5 5
6# When adding new entries keep the list in alphabetical order6# When adding new entries keep the list in alphabetical order
7obj-$(CONFIG_AF8133J) += af8133j.o
7obj-$(CONFIG_AK8974) += ak8974.o8obj-$(CONFIG_AK8974) += ak8974.o
8obj-$(CONFIG_AK8975) += ak8975.o9obj-$(CONFIG_AK8975) += ak8975.o
9obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o10obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
drivers/iio/magnetometer/af8133j.c+528−0
@@ -0,0 +1,528 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * af8133j.c - Voltafield AF8133J magnetometer driver
4 *
5 * Copyright 2021 Icenowy Zheng <icenowy@aosc.io>
6 * Copyright 2024 Ondřej Jirman <megi@xff.cz>
7 */
8
9#include <linux/delay.h>
10#include <linux/gpio/consumer.h>
11#include <linux/i2c.h>
12#include <linux/module.h>
13#include <linux/pm_runtime.h>
14#include <linux/regmap.h>
15#include <linux/regulator/consumer.h>
16
17#include <linux/iio/iio.h>
18#include <linux/iio/trigger_consumer.h>
19#include <linux/iio/triggered_buffer.h>
20
21#define AF8133J_REG_OUT 0x03
22#define AF8133J_REG_PCODE 0x00
23#define AF8133J_REG_PCODE_VAL 0x5e
24#define AF8133J_REG_STATUS 0x02
25#define AF8133J_REG_STATUS_ACQ BIT(0)
26#define AF8133J_REG_STATE 0x0a
27#define AF8133J_REG_STATE_STBY 0x00
28#define AF8133J_REG_STATE_WORK 0x01
29#define AF8133J_REG_RANGE 0x0b
30#define AF8133J_REG_RANGE_22G 0x12
31#define AF8133J_REG_RANGE_12G 0x34
32#define AF8133J_REG_SWR 0x11
33#define AF8133J_REG_SWR_PERFORM 0x81
34
35static const char * const af8133j_supply_names[] = {
36 "avdd",
37 "dvdd",
38};
39
40struct af8133j_data {
41 struct i2c_client *client;
42 struct regmap *regmap;
43 /*
44 * Protect device internal state between starting a measurement
45 * and reading the result.
46 */
47 struct mutex mutex;
48 struct iio_mount_matrix orientation;
49
50 struct gpio_desc *reset_gpiod;
51 struct regulator_bulk_data supplies[ARRAY_SIZE(af8133j_supply_names)];
52
53 u8 range;
54};
55
56enum af8133j_axis {
57 AXIS_X = 0,
58 AXIS_Y,
59 AXIS_Z,
60};
61
62static struct iio_mount_matrix *
63af8133j_get_mount_matrix(struct iio_dev *indio_dev,
64 const struct iio_chan_spec *chan)
65{
66 struct af8133j_data *data = iio_priv(indio_dev);
67
68 return &data->orientation;
69}
70
71static const struct iio_chan_spec_ext_info af8133j_ext_info[] = {
72 IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, af8133j_get_mount_matrix),
73 { }
74};
75
76#define AF8133J_CHANNEL(_si, _axis) { \
77 .type = IIO_MAGN, \
78 .modified = 1, \
79 .channel2 = IIO_MOD_ ## _axis, \
80 .address = AXIS_ ## _axis, \
81 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
82 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
83 .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \
84 .ext_info = af8133j_ext_info, \
85 .scan_index = _si, \
86 .scan_type = { \
87 .sign = 's', \
88 .realbits = 16, \
89 .storagebits = 16, \
90 .endianness = IIO_LE, \
91 }, \
92}
93
94static const struct iio_chan_spec af8133j_channels[] = {
95 AF8133J_CHANNEL(0, X),
96 AF8133J_CHANNEL(1, Y),
97 AF8133J_CHANNEL(2, Z),
98 IIO_CHAN_SOFT_TIMESTAMP(3),
99};
100
101static int af8133j_product_check(struct af8133j_data *data)
102{
103 struct device *dev = &data->client->dev;
104 unsigned int val;
105 int ret;
106
107 ret = regmap_read(data->regmap, AF8133J_REG_PCODE, &val);
108 if (ret) {
109 dev_err(dev, "Error reading product code (%d)\n", ret);
110 return ret;
111 }
112
113 if (val != AF8133J_REG_PCODE_VAL) {
114 dev_warn(dev, "Invalid product code (0x%02x)\n", val);
115 return 0; /* Allow unknown ID so fallback compatibles work */
116 }
117
118 return 0;
119}
120
121static int af8133j_reset(struct af8133j_data *data)
122{
123 struct device *dev = &data->client->dev;
124 int ret;
125
126 if (data->reset_gpiod) {
127 /* If we have GPIO reset line, use it */
128 gpiod_set_value_cansleep(data->reset_gpiod, 1);
129 udelay(10);
130 gpiod_set_value_cansleep(data->reset_gpiod, 0);
131 } else {
132 /* Otherwise use software reset */
133 ret = regmap_write(data->regmap, AF8133J_REG_SWR,
134 AF8133J_REG_SWR_PERFORM);
135 if (ret) {
136 dev_err(dev, "Failed to reset the chip\n");
137 return ret;
138 }
139 }
140
141 /* Wait for reset to finish */
142 usleep_range(1000, 1100);
143
144 /* Restore range setting */
145 if (data->range == AF8133J_REG_RANGE_22G) {
146 ret = regmap_write(data->regmap, AF8133J_REG_RANGE, data->range);
147 if (ret)
148 return ret;
149 }
150
151 return 0;
152}
153
154static void af8133j_power_down(struct af8133j_data *data)
155{
156 gpiod_set_value_cansleep(data->reset_gpiod, 1);
157 regulator_bulk_disable(ARRAY_SIZE(data->supplies), data->supplies);
158}
159
160static int af8133j_power_up(struct af8133j_data *data)
161{
162 struct device *dev = &data->client->dev;
163 int ret;
164
165 ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), data->supplies);
166 if (ret) {
167 dev_err(dev, "Could not enable regulators\n");
168 return ret;
169 }
170
171 gpiod_set_value_cansleep(data->reset_gpiod, 0);
172
173 /* Wait for power on reset */
174 usleep_range(15000, 16000);
175
176 ret = af8133j_reset(data);
177 if (ret) {
178 af8133j_power_down(data);
179 return ret;
180 }
181
182 return 0;
183}
184
185static int af8133j_take_measurement(struct af8133j_data *data)
186{
187 unsigned int val;
188 int ret;
189
190 ret = regmap_write(data->regmap,
191 AF8133J_REG_STATE, AF8133J_REG_STATE_WORK);
192 if (ret)
193 return ret;
194
195 /* The datasheet says "Mesaure Time <1.5ms" */
196 ret = regmap_read_poll_timeout(data->regmap, AF8133J_REG_STATUS, val,
197 val & AF8133J_REG_STATUS_ACQ,
198 500, 1500);
199 if (ret)
200 return ret;
201
202 ret = regmap_write(data->regmap,
203 AF8133J_REG_STATE, AF8133J_REG_STATE_STBY);
204 if (ret)
205 return ret;
206
207 return 0;
208}
209
210static int af8133j_read_measurement(struct af8133j_data *data, __le16 buf[3])
211{
212 struct device *dev = &data->client->dev;
213 int ret;
214
215 ret = pm_runtime_resume_and_get(dev);
216 if (ret) {
217 /*
218 * Ignore EACCES because that happens when RPM is disabled
219 * during system sleep, while userspace leave eg. hrtimer
220 * trigger attached and IIO core keeps trying to do measurements.
221 */
222 if (ret != -EACCES)
223 dev_err(dev, "Failed to power on (%d)\n", ret);
224 return ret;
225 }
226
227 scoped_guard(mutex, &data->mutex) {
228 ret = af8133j_take_measurement(data);
229 if (ret)
230 goto out_rpm_put;
231
232 ret = regmap_bulk_read(data->regmap, AF8133J_REG_OUT,
233 buf, sizeof(__le16) * 3);
234 }
235
236out_rpm_put:
237 pm_runtime_mark_last_busy(dev);
238 pm_runtime_put_autosuspend(dev);
239
240 return ret;
241}
242
243static const int af8133j_scales[][2] = {
244 [0] = { 0, 366210 }, /* 12 gauss */
245 [1] = { 0, 671386 }, /* 22 gauss */
246};
247
248static int af8133j_read_raw(struct iio_dev *indio_dev,
249 struct iio_chan_spec const *chan, int *val,
250 int *val2, long mask)
251{
252 struct af8133j_data *data = iio_priv(indio_dev);
253 __le16 buf[3];
254 int ret;
255
256 switch (mask) {
257 case IIO_CHAN_INFO_RAW:
258 ret = af8133j_read_measurement(data, buf);
259 if (ret)
260 return ret;
261
262 *val = sign_extend32(le16_to_cpu(buf[chan->address]),
263 chan->scan_type.realbits - 1);
264 return IIO_VAL_INT;
265 case IIO_CHAN_INFO_SCALE:
266 *val = 0;
267
268 if (data->range == AF8133J_REG_RANGE_12G)
269 *val2 = af8133j_scales[0][1];
270 else
271 *val2 = af8133j_scales[1][1];
272
273 return IIO_VAL_INT_PLUS_NANO;
274 default:
275 return -EINVAL;
276 }
277}
278
279static int af8133j_read_avail(struct iio_dev *indio_dev,
280 struct iio_chan_spec const *chan,
281 const int **vals, int *type, int *length,
282 long mask)
283{
284 switch (mask) {
285 case IIO_CHAN_INFO_SCALE:
286 *vals = (const int *)af8133j_scales;
287 *length = ARRAY_SIZE(af8133j_scales) * 2;
288 *type = IIO_VAL_INT_PLUS_NANO;
289 return IIO_AVAIL_LIST;
290 default:
291 return -EINVAL;
292 }
293}
294
295static int af8133j_set_scale(struct af8133j_data *data,
296 unsigned int val, unsigned int val2)
297{
298 struct device *dev = &data->client->dev;
299 u8 range;
300 int ret = 0;
301
302 if (af8133j_scales[0][0] == val && af8133j_scales[0][1] == val2)
303 range = AF8133J_REG_RANGE_12G;
304 else if (af8133j_scales[1][0] == val && af8133j_scales[1][1] == val2)
305 range = AF8133J_REG_RANGE_22G;
306 else
307 return -EINVAL;
308
309 pm_runtime_disable(dev);
310
311 /*
312 * When suspended, just store the new range to data->range to be
313 * applied later during power up.
314 */
315 if (!pm_runtime_status_suspended(dev))
316 scoped_guard(mutex, &data->mutex)
317 ret = regmap_write(data->regmap,
318 AF8133J_REG_RANGE, range);
319
320 pm_runtime_enable(dev);
321
322 data->range = range;
323 return ret;
324}
325
326static int af8133j_write_raw(struct iio_dev *indio_dev,
327 struct iio_chan_spec const *chan,
328 int val, int val2, long mask)
329{
330 struct af8133j_data *data = iio_priv(indio_dev);
331
332 switch (mask) {
333 case IIO_CHAN_INFO_SCALE:
334 return af8133j_set_scale(data, val, val2);
335 default:
336 return -EINVAL;
337 }
338}
339
340static int af8133j_write_raw_get_fmt(struct iio_dev *indio_dev,
341 struct iio_chan_spec const *chan,
342 long mask)
343{
344 return IIO_VAL_INT_PLUS_NANO;
345}
346
347static const struct iio_info af8133j_info = {
348 .read_raw = af8133j_read_raw,
349 .read_avail = af8133j_read_avail,
350 .write_raw = af8133j_write_raw,
351 .write_raw_get_fmt = af8133j_write_raw_get_fmt,
352};
353
354static irqreturn_t af8133j_trigger_handler(int irq, void *p)
355{
356 struct iio_poll_func *pf = p;
357 struct iio_dev *indio_dev = pf->indio_dev;
358 struct af8133j_data *data = iio_priv(indio_dev);
359 s64 timestamp = iio_get_time_ns(indio_dev);
360 struct {
361 __le16 values[3];
362 s64 timestamp __aligned(8);
363 } sample;
364 int ret;
365
366 memset(&sample, 0, sizeof(sample));
367
368 ret = af8133j_read_measurement(data, sample.values);
369 if (ret)
370 goto out_done;
371
372 iio_push_to_buffers_with_timestamp(indio_dev, &sample, timestamp);
373
374out_done:
375 iio_trigger_notify_done(indio_dev->trig);
376
377 return IRQ_HANDLED;
378}
379
380static const struct regmap_config af8133j_regmap_config = {
381 .name = "af8133j_regmap",
382 .reg_bits = 8,
383 .val_bits = 8,
384 .max_register = AF8133J_REG_SWR,
385 .cache_type = REGCACHE_NONE,
386};
387
388static void af8133j_power_down_action(void *ptr)
389{
390 struct af8133j_data *data = ptr;
391
392 if (!pm_runtime_status_suspended(&data->client->dev))
393 af8133j_power_down(data);
394}
395
396static int af8133j_probe(struct i2c_client *client)
397{
398 struct device *dev = &client->dev;
399 struct af8133j_data *data;
400 struct iio_dev *indio_dev;
401 struct regmap *regmap;
402 int ret, i;
403
404 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
405 if (!indio_dev)
406 return -ENOMEM;
407
408 regmap = devm_regmap_init_i2c(client, &af8133j_regmap_config);
409 if (IS_ERR(regmap))
410 return dev_err_probe(dev, PTR_ERR(regmap),
411 "regmap initialization failed\n");
412
413 data = iio_priv(indio_dev);
414 i2c_set_clientdata(client, indio_dev);
415 data->client = client;
416 data->regmap = regmap;
417 data->range = AF8133J_REG_RANGE_12G;
418 mutex_init(&data->mutex);
419
420 data->reset_gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
421 if (IS_ERR(data->reset_gpiod))
422 return dev_err_probe(dev, PTR_ERR(data->reset_gpiod),
423 "Failed to get reset gpio\n");
424
425 for (i = 0; i < ARRAY_SIZE(af8133j_supply_names); i++)
426 data->supplies[i].supply = af8133j_supply_names[i];
427 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
428 data->supplies);
429 if (ret)
430 return ret;
431
432 ret = iio_read_mount_matrix(dev, &data->orientation);
433 if (ret)
434 return dev_err_probe(dev, ret, "Failed to read mount matrix\n");
435
436 ret = af8133j_power_up(data);
437 if (ret)
438 return ret;
439
440 pm_runtime_set_active(dev);
441
442 ret = devm_add_action_or_reset(dev, af8133j_power_down_action, data);
443 if (ret)
444 return ret;
445
446 ret = af8133j_product_check(data);
447 if (ret)
448 return ret;
449
450 pm_runtime_get_noresume(dev);
451 pm_runtime_use_autosuspend(dev);
452 pm_runtime_set_autosuspend_delay(dev, 500);
453 ret = devm_pm_runtime_enable(dev);
454 if (ret)
455 return ret;
456
457 pm_runtime_put_autosuspend(dev);
458
459 indio_dev->info = &af8133j_info;
460 indio_dev->name = "af8133j";
461 indio_dev->channels = af8133j_channels;
462 indio_dev->num_channels = ARRAY_SIZE(af8133j_channels);
463 indio_dev->modes = INDIO_DIRECT_MODE;
464
465 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
466 &af8133j_trigger_handler, NULL);
467 if (ret)
468 return dev_err_probe(&client->dev, ret,
469 "Failed to setup iio triggered buffer\n");
470
471 ret = devm_iio_device_register(dev, indio_dev);
472 if (ret)
473 return dev_err_probe(dev, ret, "Failed to register iio device");
474
475 return 0;
476}
477
478static int af8133j_runtime_suspend(struct device *dev)
479{
480 struct iio_dev *indio_dev = dev_get_drvdata(dev);
481 struct af8133j_data *data = iio_priv(indio_dev);
482
483 af8133j_power_down(data);
484
485 return 0;
486}
487
488static int af8133j_runtime_resume(struct device *dev)
489{
490 struct iio_dev *indio_dev = dev_get_drvdata(dev);
491 struct af8133j_data *data = iio_priv(indio_dev);
492
493 return af8133j_power_up(data);
494}
495
496static const struct dev_pm_ops af8133j_pm_ops = {
497 SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
498 RUNTIME_PM_OPS(af8133j_runtime_suspend, af8133j_runtime_resume, NULL)
499};
500
501static const struct of_device_id af8133j_of_match[] = {
502 { .compatible = "voltafield,af8133j", },
503 { }
504};
505MODULE_DEVICE_TABLE(of, af8133j_of_match);
506
507static const struct i2c_device_id af8133j_id[] = {
508 { "af8133j", 0 },
509 { }
510};
511MODULE_DEVICE_TABLE(i2c, af8133j_id);
512
513static struct i2c_driver af8133j_driver = {
514 .driver = {
515 .name = "af8133j",
516 .of_match_table = af8133j_of_match,
517 .pm = pm_ptr(&af8133j_pm_ops),
518 },
519 .probe = af8133j_probe,
520 .id_table = af8133j_id,
521};
522
523module_i2c_driver(af8133j_driver);
524
525MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
526MODULE_AUTHOR("Ondřej Jirman <megi@xff.cz>");
527MODULE_DESCRIPTION("Voltafield AF8133J magnetic sensor driver");
528MODULE_LICENSE("GPL");
drivers/iio/magnetometer/bmc150_magn_i2c.c+1−2
@@ -11,7 +11,6 @@ · 10 unmodified lines
11#include <linux/mod_devicetable.h>11#include <linux/mod_devicetable.h>
12#include <linux/i2c.h>12#include <linux/i2c.h>
13#include <linux/module.h>13#include <linux/module.h>
14#include <linux/acpi.h>
15#include <linux/regmap.h>14#include <linux/regmap.h>
16 15
17#include "bmc150_magn.h"16#include "bmc150_magn.h"
@@ -68,7 +67,7 @@ static struct i2c_driver bmc150_magn_driver = { · 50 unmodified lines
68 .driver = {67 .driver = {
69 .name = "bmc150_magn_i2c",68 .name = "bmc150_magn_i2c",
70 .of_match_table = bmc150_magn_of_match,69 .of_match_table = bmc150_magn_of_match,
71 .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match),70 .acpi_match_table = bmc150_magn_acpi_match,
72 .pm = &bmc150_magn_pm_ops,71 .pm = &bmc150_magn_pm_ops,
73 },72 },
74 .probe = bmc150_magn_i2c_probe,73 .probe = bmc150_magn_i2c_probe,
drivers/iio/magnetometer/bmc150_magn_spi.c+1−2
@@ -10,7 +10,6 @@ · 9 unmodified lines
10#include <linux/module.h>10#include <linux/module.h>
11#include <linux/mod_devicetable.h>11#include <linux/mod_devicetable.h>
12#include <linux/spi/spi.h>12#include <linux/spi/spi.h>
13#include <linux/acpi.h>
14#include <linux/regmap.h>13#include <linux/regmap.h>
15 14
16#include "bmc150_magn.h"15#include "bmc150_magn.h"
@@ -55,7 +54,7 @@ static struct spi_driver bmc150_magn_spi_driver = { · 38 unmodified lines
55 .remove = bmc150_magn_spi_remove,54 .remove = bmc150_magn_spi_remove,
56 .id_table = bmc150_magn_spi_id,55 .id_table = bmc150_magn_spi_id,
57 .driver = {56 .driver = {
58 .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match),57 .acpi_match_table = bmc150_magn_acpi_match,
59 .name = "bmc150_magn_spi",58 .name = "bmc150_magn_spi",
60 },59 },
61};60};
drivers/iio/magnetometer/mmc35240.c+2−2
@@ -10,11 +10,11 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/module.h>12#include <linux/module.h>
13#include <linux/mod_devicetable.h>
13#include <linux/init.h>14#include <linux/init.h>
14#include <linux/i2c.h>15#include <linux/i2c.h>
15#include <linux/delay.h>16#include <linux/delay.h>
16#include <linux/regmap.h>17#include <linux/regmap.h>
17#include <linux/acpi.h>
18#include <linux/pm.h>18#include <linux/pm.h>
19 19
20#include <linux/iio/iio.h>20#include <linux/iio/iio.h>
@@ -573,7 +573,7 @@ static struct i2c_driver mmc35240_driver = { · 552 unmodified lines
573 .name = MMC35240_DRV_NAME,573 .name = MMC35240_DRV_NAME,
574 .of_match_table = mmc35240_of_match,574 .of_match_table = mmc35240_of_match,
575 .pm = pm_sleep_ptr(&mmc35240_pm_ops),575 .pm = pm_sleep_ptr(&mmc35240_pm_ops),
576 .acpi_match_table = ACPI_PTR(mmc35240_acpi_match),576 .acpi_match_table = mmc35240_acpi_match,
577 },577 },
578 .probe = mmc35240_probe,578 .probe = mmc35240_probe,
579 .id_table = mmc35240_id,579 .id_table = mmc35240_id,
drivers/iio/potentiometer/max5487.c+2−2
@@ -5,8 +5,8 @@ · 4 unmodified lines
5 * Copyright (C) 2016 Cristina-Gabriela Moraru <cristina.moraru09@gmail.com>5 * Copyright (C) 2016 Cristina-Gabriela Moraru <cristina.moraru09@gmail.com>
6 */6 */
7#include <linux/module.h>7#include <linux/module.h>
8#include <linux/mod_devicetable.h>
8#include <linux/spi/spi.h>9#include <linux/spi/spi.h>
9#include <linux/acpi.h>
10 10
11#include <linux/iio/sysfs.h>11#include <linux/iio/sysfs.h>
12#include <linux/iio/iio.h>12#include <linux/iio/iio.h>
@@ -144,7 +144,7 @@ MODULE_DEVICE_TABLE(acpi, max5487_acpi_match); · 131 unmodified lines
144static struct spi_driver max5487_driver = {144static struct spi_driver max5487_driver = {
145 .driver = {145 .driver = {
146 .name = "max5487",146 .name = "max5487",
147 .acpi_match_table = ACPI_PTR(max5487_acpi_match),147 .acpi_match_table = max5487_acpi_match,
148 },148 },
149 .id_table = max5487_id,149 .id_table = max5487_id,
150 .probe = max5487_spi_probe,150 .probe = max5487_spi_probe,
drivers/iio/pressure/Kconfig+15−1
@@ -114,6 +114,8 @@ config HSC030PA · 113 unmodified lines
114 depends on (I2C || SPI_MASTER)114 depends on (I2C || SPI_MASTER)
115 select HSC030PA_I2C if I2C115 select HSC030PA_I2C if I2C
116 select HSC030PA_SPI if SPI_MASTER116 select HSC030PA_SPI if SPI_MASTER
117 select IIO_BUFFER
118 select IIO_TRIGGERED_BUFFER
117 help119 help
118 Say Y here to build support for the Honeywell TruStability120 Say Y here to build support for the Honeywell TruStability
119 HSC and SSC pressure and temperature sensor series.121 HSC and SSC pressure and temperature sensor series.
@@ -181,7 +183,9 @@ config MPL3115 · 61 unmodified lines
181 183
182config MPRLS0025PA184config MPRLS0025PA
183 tristate "Honeywell MPRLS0025PA (MicroPressure sensors series)"185 tristate "Honeywell MPRLS0025PA (MicroPressure sensors series)"
184 depends on I2C186 depends on (I2C || SPI_MASTER)
187 select MPRLS0025PA_I2C if I2C
188 select MPRLS0025PA_SPI if SPI_MASTER
185 select IIO_BUFFER189 select IIO_BUFFER
186 select IIO_TRIGGERED_BUFFER190 select IIO_TRIGGERED_BUFFER
187 help191 help
@@ -192,6 +196,16 @@ config MPRLS0025PA · 4 unmodified lines
192 To compile this driver as a module, choose M here: the module will be196 To compile this driver as a module, choose M here: the module will be
193 called mprls0025pa.197 called mprls0025pa.
194 198
199config MPRLS0025PA_I2C
200 tristate
201 depends on MPRLS0025PA
202 depends on I2C
203
204config MPRLS0025PA_SPI
205 tristate
206 depends on MPRLS0025PA
207 depends on SPI_MASTER
208
195config MS5611209config MS5611
196 tristate "Measurement Specialties MS5611 pressure sensor driver"210 tristate "Measurement Specialties MS5611 pressure sensor driver"
197 select IIO_BUFFER211 select IIO_BUFFER
drivers/iio/pressure/Makefile+2−0
@@ -24,6 +24,8 @@ obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o · 23 unmodified lines
24obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o24obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o
25obj-$(CONFIG_MPL3115) += mpl3115.o25obj-$(CONFIG_MPL3115) += mpl3115.o
26obj-$(CONFIG_MPRLS0025PA) += mprls0025pa.o26obj-$(CONFIG_MPRLS0025PA) += mprls0025pa.o
27obj-$(CONFIG_MPRLS0025PA_I2C) += mprls0025pa_i2c.o
28obj-$(CONFIG_MPRLS0025PA_SPI) += mprls0025pa_spi.o
27obj-$(CONFIG_MS5611) += ms5611_core.o29obj-$(CONFIG_MS5611) += ms5611_core.o
28obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o30obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o
29obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o31obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o
drivers/iio/pressure/hp206c.c+2−4
@@ -11,12 +11,12 @@ · 10 unmodified lines
11 */11 */
12 12
13#include <linux/module.h>13#include <linux/module.h>
14#include <linux/mod_devicetable.h>
14#include <linux/i2c.h>15#include <linux/i2c.h>
15#include <linux/iio/iio.h>16#include <linux/iio/iio.h>
16#include <linux/iio/sysfs.h>17#include <linux/iio/sysfs.h>
17#include <linux/delay.h>18#include <linux/delay.h>
18#include <linux/util_macros.h>19#include <linux/util_macros.h>
19#include <linux/acpi.h>
20 20
21#include <asm/unaligned.h>21#include <asm/unaligned.h>
22 22
@@ -400,20 +400,18 @@ static const struct i2c_device_id hp206c_id[] = { · 377 unmodified lines
400};400};
401MODULE_DEVICE_TABLE(i2c, hp206c_id);401MODULE_DEVICE_TABLE(i2c, hp206c_id);
402 402
403#ifdef CONFIG_ACPI
404static const struct acpi_device_id hp206c_acpi_match[] = {403static const struct acpi_device_id hp206c_acpi_match[] = {
405 {"HOP206C", 0},404 {"HOP206C", 0},
406 { },405 { },
407};406};
408MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);407MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
409#endif
410 408
411static struct i2c_driver hp206c_driver = {409static struct i2c_driver hp206c_driver = {
412 .probe = hp206c_probe,410 .probe = hp206c_probe,
413 .id_table = hp206c_id,411 .id_table = hp206c_id,
414 .driver = {412 .driver = {
415 .name = "hp206c",413 .name = "hp206c",
416 .acpi_match_table = ACPI_PTR(hp206c_acpi_match),414 .acpi_match_table = hp206c_acpi_match,
417 },415 },
418};416};
419 417
drivers/iio/pressure/hsc030pa.c+48−1
@@ -22,8 +22,11 @@ · 21 unmodified lines
22#include <linux/types.h>22#include <linux/types.h>
23#include <linux/units.h>23#include <linux/units.h>
24 24
25#include <linux/iio/buffer.h>
25#include <linux/iio/iio.h>26#include <linux/iio/iio.h>
26#include <linux/iio/sysfs.h>27#include <linux/iio/sysfs.h>
28#include <linux/iio/trigger_consumer.h>
29#include <linux/iio/triggered_buffer.h>
27 30
28#include <asm/unaligned.h>31#include <asm/unaligned.h>
29 32
@@ -297,6 +300,29 @@ static int hsc_get_measurement(struct hsc_data *data) · 267 unmodified lines
297 return 0;300 return 0;
298}301}
299 302
303static irqreturn_t hsc_trigger_handler(int irq, void *private)
304{
305 struct iio_poll_func *pf = private;
306 struct iio_dev *indio_dev = pf->indio_dev;
307 struct hsc_data *data = iio_priv(indio_dev);
308 int ret;
309
310 ret = hsc_get_measurement(data);
311 if (ret)
312 goto error;
313
314 memcpy(&data->scan.chan[0], &data->buffer[0], 2);
315 memcpy(&data->scan.chan[1], &data->buffer[2], 2);
316
317 iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
318 iio_get_time_ns(indio_dev));
319
320error:
321 iio_trigger_notify_done(indio_dev->trig);
322
323 return IRQ_HANDLED;
324}
325
300/*326/*
301 * IIO ABI expects327 * IIO ABI expects
302 * value = (conv + offset) * scale328 * value = (conv + offset) * scale
@@ -382,13 +408,29 @@ static const struct iio_chan_spec hsc_channels[] = { · 79 unmodified lines
382 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |408 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
383 BIT(IIO_CHAN_INFO_SCALE) |409 BIT(IIO_CHAN_INFO_SCALE) |
384 BIT(IIO_CHAN_INFO_OFFSET),410 BIT(IIO_CHAN_INFO_OFFSET),
411 .scan_index = 0,
412 .scan_type = {
413 .sign = 'u',
414 .realbits = 14,
415 .storagebits = 16,
416 .endianness = IIO_BE,
417 },
385 },418 },
386 {419 {
387 .type = IIO_TEMP,420 .type = IIO_TEMP,
388 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |421 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
389 BIT(IIO_CHAN_INFO_SCALE) |422 BIT(IIO_CHAN_INFO_SCALE) |
390 BIT(IIO_CHAN_INFO_OFFSET),423 BIT(IIO_CHAN_INFO_OFFSET),
424 .scan_index = 1,
425 .scan_type = {
426 .sign = 'u',
427 .realbits = 11,
428 .storagebits = 16,
429 .shift = 5,
430 .endianness = IIO_BE,
431 },
391 },432 },
433 IIO_CHAN_SOFT_TIMESTAMP(2),
392};434};
393 435
394static const struct iio_info hsc_info = {436static const struct iio_info hsc_info = {
@@ -406,7 +448,7 @@ int hsc_common_probe(struct device *dev, hsc_recv_fn recv) · 11 unmodified lines
406 struct hsc_data *hsc;448 struct hsc_data *hsc;
407 struct iio_dev *indio_dev;449 struct iio_dev *indio_dev;
408 const char *triplet;450 const char *triplet;
409 u64 tmp;451 s64 tmp;
410 int ret;452 int ret;
411 453
412 indio_dev = devm_iio_device_alloc(dev, sizeof(*hsc));454 indio_dev = devm_iio_device_alloc(dev, sizeof(*hsc));
@@ -485,6 +527,11 @@ int hsc_common_probe(struct device *dev, hsc_recv_fn recv) · 72 unmodified lines
485 indio_dev->channels = hsc->chip->channels;527 indio_dev->channels = hsc->chip->channels;
486 indio_dev->num_channels = hsc->chip->num_channels;528 indio_dev->num_channels = hsc->chip->num_channels;
487 529
530 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
531 hsc_trigger_handler, NULL);
532 if (ret)
533 return ret;
534
488 return devm_iio_device_register(dev, indio_dev);535 return devm_iio_device_register(dev, indio_dev);
489}536}
490EXPORT_SYMBOL_NS(hsc_common_probe, IIO_HONEYWELL_HSC030PA);537EXPORT_SYMBOL_NS(hsc_common_probe, IIO_HONEYWELL_HSC030PA);
drivers/iio/pressure/hsc030pa.h+7−0
@@ -10,7 +10,10 @@ · 9 unmodified lines
10 10
11#include <linux/types.h>11#include <linux/types.h>
12 12
13#include <linux/iio/iio.h>
14
13#define HSC_REG_MEASUREMENT_RD_SIZE 415#define HSC_REG_MEASUREMENT_RD_SIZE 4
16#define HSC_RESP_TIME_MS 2
14 17
15struct device;18struct device;
16 19
@@ -53,6 +56,10 @@ struct hsc_data { · 36 unmodified lines
53 s32 p_scale_dec;56 s32 p_scale_dec;
54 s64 p_offset;57 s64 p_offset;
55 s32 p_offset_dec;58 s32 p_offset_dec;
59 struct {
60 __be16 chan[2];
61 s64 timestamp __aligned(8);
62 } scan;
56 u8 buffer[HSC_REG_MEASUREMENT_RD_SIZE] __aligned(IIO_DMA_MINALIGN);63 u8 buffer[HSC_REG_MEASUREMENT_RD_SIZE] __aligned(IIO_DMA_MINALIGN);
57};64};
58 65
drivers/iio/pressure/hsc030pa_i2c.c+7−2
@@ -4,14 +4,17 @@ · 3 unmodified lines
4 *4 *
5 * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro>5 * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro>
6 *6 *
7 * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/trustability-hsc-series/documents/sps-siot-trustability-hsc-series-high-accuracy-board-mount-pressure-sensors-50099148-a-en-ciid-151133.pdf [hsc]7 * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/common/documents/sps-siot-i2c-comms-digital-output-pressure-sensors-tn-008201-3-en-ciid-45841.pdf
8 * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/common/documents/sps-siot-i2c-comms-digital-output-pressure-sensors-tn-008201-3-en-ciid-45841.pdf [i2c related]8 * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/common/documents/sps-siot-sleep-mode-technical-note-008286-1-en-ciid-155793.pdf
9 */9 */
10 10
11#include <linux/delay.h>
12#include <linux/device.h>
11#include <linux/errno.h>13#include <linux/errno.h>
12#include <linux/i2c.h>14#include <linux/i2c.h>
13#include <linux/mod_devicetable.h>15#include <linux/mod_devicetable.h>
14#include <linux/module.h>16#include <linux/module.h>
17#include <linux/types.h>
15 18
16#include <linux/iio/iio.h>19#include <linux/iio/iio.h>
17 20
@@ -23,6 +26,8 @@ static int hsc_i2c_recv(struct hsc_data *data) · 5 unmodified lines
23 struct i2c_msg msg;26 struct i2c_msg msg;
24 int ret;27 int ret;
25 28
29 msleep_interruptible(HSC_RESP_TIME_MS);
30
26 msg.addr = client->addr;31 msg.addr = client->addr;
27 msg.flags = client->flags | I2C_M_RD;32 msg.flags = client->flags | I2C_M_RD;
28 msg.len = HSC_REG_MEASUREMENT_RD_SIZE;33 msg.len = HSC_REG_MEASUREMENT_RD_SIZE;
drivers/iio/pressure/hsc030pa_spi.c+6−1
@@ -4,13 +4,17 @@ · 3 unmodified lines
4 *4 *
5 * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro>5 * Copyright (c) 2023 Petre Rodan <petre.rodan@subdimension.ro>
6 *6 *
7 * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/trustability-hsc-series/documents/sps-siot-trustability-hsc-series-high-accuracy-board-mount-pressure-sensors-50099148-a-en-ciid-151133.pdf7 * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/common/documents/sps-siot-spi-comms-digital-ouptu-pressure-sensors-tn-008202-3-en-ciid-45843.pdf
8 * Datasheet: https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/common/documents/sps-siot-sleep-mode-technical-note-008286-1-en-ciid-155793.pdf
8 */9 */
9 10
11#include <linux/delay.h>
12#include <linux/device.h>
10#include <linux/mod_devicetable.h>13#include <linux/mod_devicetable.h>
11#include <linux/module.h>14#include <linux/module.h>
12#include <linux/spi/spi.h>15#include <linux/spi/spi.h>
13#include <linux/stddef.h>16#include <linux/stddef.h>
17#include <linux/types.h>
14 18
15#include <linux/iio/iio.h>19#include <linux/iio/iio.h>
16 20
@@ -25,6 +29,7 @@ static int hsc_spi_recv(struct hsc_data *data) · 8 unmodified lines
25 .len = HSC_REG_MEASUREMENT_RD_SIZE,29 .len = HSC_REG_MEASUREMENT_RD_SIZE,
26 };30 };
27 31
32 msleep_interruptible(HSC_RESP_TIME_MS);
28 return spi_sync_transfer(spi, &xfer, 1);33 return spi_sync_transfer(spi, &xfer, 1);
29}34}
30 35
drivers/iio/pressure/mprls0025pa.c+159−154
@@ -5,17 +5,13 @@ · 4 unmodified lines
5 * Copyright (c) Andreas Klinger <ak@it-klinger.de>5 * Copyright (c) Andreas Klinger <ak@it-klinger.de>
6 *6 *
7 * Data sheet:7 * Data sheet:
8 * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/8 * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/micropressure-mpr-series/documents/sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
9 * products/sensors/pressure-sensors/board-mount-pressure-sensors/
10 * micropressure-mpr-series/documents/
11 * sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
12 *9 *
13 * 7-bit I2C default slave address: 0x18
14 */10 */
15 11
16#include <linux/delay.h>12#include <linux/array_size.h>
17#include <linux/device.h>13#include <linux/bitfield.h>
18#include <linux/i2c.h>14#include <linux/bits.h>
19#include <linux/math64.h>15#include <linux/math64.h>
20#include <linux/mod_devicetable.h>16#include <linux/mod_devicetable.h>
21#include <linux/module.h>17#include <linux/module.h>
@@ -25,7 +21,6 @@ · 3 unmodified lines
25#include <linux/gpio/consumer.h>21#include <linux/gpio/consumer.h>
26 22
27#include <linux/iio/buffer.h>23#include <linux/iio/buffer.h>
28#include <linux/iio/iio.h>
29#include <linux/iio/trigger_consumer.h>24#include <linux/iio/trigger_consumer.h>
30#include <linux/iio/triggered_buffer.h>25#include <linux/iio/triggered_buffer.h>
31 26
@@ -33,11 +28,15 @@ · 1 unmodified line
33 28
34#include <asm/unaligned.h>29#include <asm/unaligned.h>
35 30
36/* bits in i2c status byte */31#include "mprls0025pa.h"
37#define MPR_I2C_POWER BIT(6) /* device is powered */32
38#define MPR_I2C_BUSY BIT(5) /* device is busy */33/* bits in status byte */
39#define MPR_I2C_MEMORY BIT(2) /* integrity test passed */34#define MPR_ST_POWER BIT(6) /* device is powered */
40#define MPR_I2C_MATH BIT(0) /* internal math saturation */35#define MPR_ST_BUSY BIT(5) /* device is busy */
36#define MPR_ST_MEMORY BIT(2) /* integrity test passed */
37#define MPR_ST_MATH BIT(0) /* internal math saturation */
38
39#define MPR_ST_ERR_FLAG (MPR_ST_BUSY | MPR_ST_MEMORY | MPR_ST_MATH)
41 40
42/*41/*
43 * support _RAW sysfs interface:42 * support _RAW sysfs interface:
@@ -70,60 +69,87 @@ · 26 unmodified lines
70 * transfer function B: 2.5% to 22.5% of 2^2469 * transfer function B: 2.5% to 22.5% of 2^24
71 * transfer function C: 20% to 80% of 2^2470 * transfer function C: 20% to 80% of 2^24
72 */71 */
73enum mpr_func_id {
74 MPR_FUNCTION_A,
75 MPR_FUNCTION_B,
76 MPR_FUNCTION_C,
77};
78
79struct mpr_func_spec {72struct mpr_func_spec {
80 u32 output_min;73 u32 output_min;
81 u32 output_max;74 u32 output_max;
82};75};
83 76
84static const struct mpr_func_spec mpr_func_spec[] = {77static const struct mpr_func_spec mpr_func_spec[] = {
85 [MPR_FUNCTION_A] = {.output_min = 1677722, .output_max = 15099494},78 [MPR_FUNCTION_A] = { .output_min = 1677722, .output_max = 15099494 },
86 [MPR_FUNCTION_B] = {.output_min = 419430, .output_max = 3774874},79 [MPR_FUNCTION_B] = { .output_min = 419430, .output_max = 3774874 },
87 [MPR_FUNCTION_C] = {.output_min = 3355443, .output_max = 13421773},80 [MPR_FUNCTION_C] = { .output_min = 3355443, .output_max = 13421773 },
88};81};
89 82
90struct mpr_chan {83enum mpr_variants {
91 s32 pres; /* pressure value */84 MPR0001BA = 0x00, MPR01_6BA = 0x01, MPR02_5BA = 0x02, MPR0060MG = 0x03,
92 s64 ts; /* timestamp */85 MPR0100MG = 0x04, MPR0160MG = 0x05, MPR0250MG = 0x06, MPR0400MG = 0x07,
86 MPR0600MG = 0x08, MPR0001BG = 0x09, MPR01_6BG = 0x0a, MPR02_5BG = 0x0b,
87 MPR0100KA = 0x0c, MPR0160KA = 0x0d, MPR0250KA = 0x0e, MPR0006KG = 0x0f,
88 MPR0010KG = 0x10, MPR0016KG = 0x11, MPR0025KG = 0x12, MPR0040KG = 0x13,
89 MPR0060KG = 0x14, MPR0100KG = 0x15, MPR0160KG = 0x16, MPR0250KG = 0x17,
90 MPR0015PA = 0x18, MPR0025PA = 0x19, MPR0030PA = 0x1a, MPR0001PG = 0x1b,
91 MPR0005PG = 0x1c, MPR0015PG = 0x1d, MPR0030PG = 0x1e, MPR0300YG = 0x1f,
92 MPR_VARIANTS_MAX
93};
94
95static const char * const mpr_triplet_variants[MPR_VARIANTS_MAX] = {
96 [MPR0001BA] = "0001BA", [MPR01_6BA] = "01.6BA", [MPR02_5BA] = "02.5BA",
97 [MPR0060MG] = "0060MG", [MPR0100MG] = "0100MG", [MPR0160MG] = "0160MG",
98 [MPR0250MG] = "0250MG", [MPR0400MG] = "0400MG", [MPR0600MG] = "0600MG",
99 [MPR0001BG] = "0001BG", [MPR01_6BG] = "01.6BG", [MPR02_5BG] = "02.5BG",
100 [MPR0100KA] = "0100KA", [MPR0160KA] = "0160KA", [MPR0250KA] = "0250KA",
101 [MPR0006KG] = "0006KG", [MPR0010KG] = "0010KG", [MPR0016KG] = "0016KG",
102 [MPR0025KG] = "0025KG", [MPR0040KG] = "0040KG", [MPR0060KG] = "0060KG",
103 [MPR0100KG] = "0100KG", [MPR0160KG] = "0160KG", [MPR0250KG] = "0250KG",
104 [MPR0015PA] = "0015PA", [MPR0025PA] = "0025PA", [MPR0030PA] = "0030PA",
105 [MPR0001PG] = "0001PG", [MPR0005PG] = "0005PG", [MPR0015PG] = "0015PG",
106 [MPR0030PG] = "0030PG", [MPR0300YG] = "0300YG"
107};
108
109/**
110 * struct mpr_range_config - list of pressure ranges based on nomenclature
111 * @pmin: lowest pressure that can be measured
112 * @pmax: highest pressure that can be measured
113 */
114struct mpr_range_config {
115 const s32 pmin;
116 const s32 pmax;
93};117};
94 118
95struct mpr_data {119/* All min max limits have been converted to pascals */
96 struct i2c_client *client;120static const struct mpr_range_config mpr_range_config[MPR_VARIANTS_MAX] = {
97 struct mutex lock; /*121 [MPR0001BA] = { .pmin = 0, .pmax = 100000 },
98 * access to device during read122 [MPR01_6BA] = { .pmin = 0, .pmax = 160000 },
99 */123 [MPR02_5BA] = { .pmin = 0, .pmax = 250000 },
100 u32 pmin; /* minimal pressure in pascal */124 [MPR0060MG] = { .pmin = 0, .pmax = 6000 },
101 u32 pmax; /* maximal pressure in pascal */125 [MPR0100MG] = { .pmin = 0, .pmax = 10000 },
102 enum mpr_func_id function; /* transfer function */126 [MPR0160MG] = { .pmin = 0, .pmax = 16000 },
103 u32 outmin; /*127 [MPR0250MG] = { .pmin = 0, .pmax = 25000 },
104 * minimal numerical range raw128 [MPR0400MG] = { .pmin = 0, .pmax = 40000 },
105 * value from sensor129 [MPR0600MG] = { .pmin = 0, .pmax = 60000 },
106 */130 [MPR0001BG] = { .pmin = 0, .pmax = 100000 },
107 u32 outmax; /*131 [MPR01_6BG] = { .pmin = 0, .pmax = 160000 },
108 * maximal numerical range raw132 [MPR02_5BG] = { .pmin = 0, .pmax = 250000 },
109 * value from sensor133 [MPR0100KA] = { .pmin = 0, .pmax = 100000 },
110 */134 [MPR0160KA] = { .pmin = 0, .pmax = 160000 },
111 int scale; /* int part of scale */135 [MPR0250KA] = { .pmin = 0, .pmax = 250000 },
112 int scale2; /* nano part of scale */136 [MPR0006KG] = { .pmin = 0, .pmax = 6000 },
113 int offset; /* int part of offset */137 [MPR0010KG] = { .pmin = 0, .pmax = 10000 },
114 int offset2; /* nano part of offset */138 [MPR0016KG] = { .pmin = 0, .pmax = 16000 },
115 struct gpio_desc *gpiod_reset; /* reset */139 [MPR0025KG] = { .pmin = 0, .pmax = 25000 },
116 int irq; /*140 [MPR0040KG] = { .pmin = 0, .pmax = 40000 },
117 * end of conversion irq;141 [MPR0060KG] = { .pmin = 0, .pmax = 60000 },
118 * used to distinguish between142 [MPR0100KG] = { .pmin = 0, .pmax = 100000 },
119 * irq mode and reading in a143 [MPR0160KG] = { .pmin = 0, .pmax = 160000 },
120 * loop until data is ready144 [MPR0250KG] = { .pmin = 0, .pmax = 250000 },
121 */145 [MPR0015PA] = { .pmin = 0, .pmax = 103421 },
122 struct completion completion; /* handshake from irq to read */146 [MPR0025PA] = { .pmin = 0, .pmax = 172369 },
123 struct mpr_chan chan; /*147 [MPR0030PA] = { .pmin = 0, .pmax = 206843 },
124 * channel values for buffered148 [MPR0001PG] = { .pmin = 0, .pmax = 6895 },
125 * mode149 [MPR0005PG] = { .pmin = 0, .pmax = 34474 },
126 */150 [MPR0015PG] = { .pmin = 0, .pmax = 103421 },
151 [MPR0030PG] = { .pmin = 0, .pmax = 206843 },
152 [MPR0300YG] = { .pmin = 0, .pmax = 39997 }
127};153};
128 154
129static const struct iio_chan_spec mpr_channels[] = {155static const struct iio_chan_spec mpr_channels[] = {
@@ -153,11 +179,11 @@ static void mpr_reset(struct mpr_data *data) · 23 unmodified lines
153}179}
154 180
155/**181/**
156 * mpr_read_pressure() - Read pressure value from sensor via I2C182 * mpr_read_pressure() - Read pressure value from sensor
157 * @data: Pointer to private data struct.183 * @data: Pointer to private data struct.
158 * @press: Output value read from sensor.184 * @press: Output value read from sensor.
159 *185 *
160 * Reading from the sensor by sending and receiving I2C telegrams.186 * Reading from the sensor by sending and receiving telegrams.
161 *187 *
162 * If there is an end of conversion (EOC) interrupt registered the function188 * If there is an end of conversion (EOC) interrupt registered the function
163 * waits for a maximum of one second for the interrupt.189 * waits for a maximum of one second for the interrupt.
@@ -170,25 +196,17 @@ static void mpr_reset(struct mpr_data *data) · 6 unmodified lines
170 */196 */
171static int mpr_read_pressure(struct mpr_data *data, s32 *press)197static int mpr_read_pressure(struct mpr_data *data, s32 *press)
172{198{
173 struct device *dev = &data->client->dev;199 struct device *dev = data->dev;
174 int ret, i;200 int ret, i;
175 u8 wdata[] = {0xAA, 0x00, 0x00};
176 s32 status;
177 int nloops = 10;201 int nloops = 10;
178 u8 buf[4];
179 202
180 reinit_completion(&data->completion);203 reinit_completion(&data->completion);
181 204
182 ret = i2c_master_send(data->client, wdata, sizeof(wdata));205 ret = data->ops->write(data, MPR_CMD_SYNC, MPR_PKT_SYNC_LEN);
183 if (ret < 0) {206 if (ret < 0) {
184 dev_err(dev, "error while writing ret: %d\n", ret);207 dev_err(dev, "error while writing ret: %d\n", ret);
185 return ret;208 return ret;
186 }209 }
187 if (ret != sizeof(wdata)) {
188 dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret,
189 (u32)sizeof(wdata));
190 return -EIO;
191 }
192 210
193 if (data->irq > 0) {211 if (data->irq > 0) {
194 ret = wait_for_completion_timeout(&data->completion, HZ);212 ret = wait_for_completion_timeout(&data->completion, HZ);
@@ -206,14 +224,14 @@ static int mpr_read_pressure(struct mpr_data *data, s32 *press) · 11 unmodified lines
206 * quite long224 * quite long
207 */225 */
208 usleep_range(5000, 10000);226 usleep_range(5000, 10000);
209 status = i2c_smbus_read_byte(data->client);227 ret = data->ops->read(data, MPR_CMD_NOP, 1);
210 if (status < 0) {228 if (ret < 0) {
211 dev_err(dev,229 dev_err(dev,
212 "error while reading, status: %d\n",230 "error while reading, status: %d\n",
213 status);231 ret);
214 return status;232 return ret;
215 }233 }
216 if (!(status & MPR_I2C_BUSY))234 if (!(data->buffer[0] & MPR_ST_ERR_FLAG))
217 break;235 break;
218 }236 }
219 if (i == nloops) {237 if (i == nloops) {
@@ -222,29 +240,19 @@ static int mpr_read_pressure(struct mpr_data *data, s32 *press) · 2 unmodified lines
222 }240 }
223 }241 }
224 242
225 ret = i2c_master_recv(data->client, buf, sizeof(buf));243 ret = data->ops->read(data, MPR_CMD_NOP, MPR_PKT_NOP_LEN);
226 if (ret < 0) {244 if (ret < 0)
227 dev_err(dev, "error in i2c_master_recv ret: %d\n", ret);
228 return ret;245 return ret;
229 }
230 if (ret != sizeof(buf)) {
231 dev_err(dev, "received size doesn't fit - ret: %d / %u\n", ret,
232 (u32)sizeof(buf));
233 return -EIO;
234 }
235 246
236 if (buf[0] & MPR_I2C_BUSY) {247 if (data->buffer[0] & MPR_ST_ERR_FLAG) {
237 /*248 dev_err(data->dev,
238 * it should never be the case that status still indicates249 "unexpected status byte %02x\n", data->buffer[0]);
239 * business
240 */
241 dev_err(dev, "data still not ready: %08x\n", buf[0]);
242 return -ETIMEDOUT;250 return -ETIMEDOUT;
243 }251 }
244 252
245 *press = get_unaligned_be24(&buf[1]);253 *press = get_unaligned_be24(&data->buffer[1]);
246 254
247 dev_dbg(dev, "received: %*ph cnt: %d\n", ret, buf, *press);255 dev_dbg(dev, "received: %*ph cnt: %d\n", ret, data->buffer, *press);
248 256
249 return 0;257 return 0;
250}258}
@@ -271,7 +279,7 @@ static irqreturn_t mpr_trigger_handler(int irq, void *p) · 20 unmodified lines
271 goto err;279 goto err;
272 280
273 iio_push_to_buffers_with_timestamp(indio_dev, &data->chan,281 iio_push_to_buffers_with_timestamp(indio_dev, &data->chan,
274 iio_get_time_ns(indio_dev));282 iio_get_time_ns(indio_dev));
275 283
276err:284err:
277 mutex_unlock(&data->lock);285 mutex_unlock(&data->lock);
@@ -316,25 +324,23 @@ static const struct iio_info mpr_info = { · 38 unmodified lines
316 .read_raw = &mpr_read_raw,324 .read_raw = &mpr_read_raw,
317};325};
318 326
319static int mpr_probe(struct i2c_client *client)327int mpr_common_probe(struct device *dev, const struct mpr_ops *ops, int irq)
320{328{
321 int ret;329 int ret;
322 struct mpr_data *data;330 struct mpr_data *data;
323 struct iio_dev *indio_dev;331 struct iio_dev *indio_dev;
324 struct device *dev = &client->dev;332 const char *triplet;
325 s64 scale, offset;333 s64 scale, offset;
326 334 u32 func;
327 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE))
328 return dev_err_probe(dev, -EOPNOTSUPP,
329 "I2C functionality not supported\n");
330 335
331 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));336 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
332 if (!indio_dev)337 if (!indio_dev)
333 return dev_err_probe(dev, -ENOMEM, "couldn't get iio_dev\n");338 return -ENOMEM;
334 339
335 data = iio_priv(indio_dev);340 data = iio_priv(indio_dev);
336 data->client = client;341 data->dev = dev;
337 data->irq = client->irq;342 data->ops = ops;
343 data->irq = irq;
338 344
339 mutex_init(&data->lock);345 mutex_init(&data->lock);
340 init_completion(&data->completion);346 init_completion(&data->completion);
@@ -348,103 +354,102 @@ static int mpr_probe(struct i2c_client *client) · 7 unmodified lines
348 ret = devm_regulator_get_enable(dev, "vdd");354 ret = devm_regulator_get_enable(dev, "vdd");
349 if (ret)355 if (ret)
350 return dev_err_probe(dev, ret,356 return dev_err_probe(dev, ret,
351 "can't get and enable vdd supply\n");357 "can't get and enable vdd supply\n");
352 358
353 if (dev_fwnode(dev)) {359 ret = data->ops->init(data->dev);
360 if (ret)
361 return ret;
362
363 ret = device_property_read_u32(dev,
364 "honeywell,transfer-function", &func);
365 if (ret)
366 return dev_err_probe(dev, ret,
367 "honeywell,transfer-function could not be read\n");
368 data->function = func - 1;
369 if (data->function > MPR_FUNCTION_C)
370 return dev_err_probe(dev, -EINVAL,
371 "honeywell,transfer-function %d invalid\n",
372 data->function);
373
374 ret = device_property_read_string(dev, "honeywell,pressure-triplet",
375 &triplet);
376 if (ret) {
354 ret = device_property_read_u32(dev, "honeywell,pmin-pascal",377 ret = device_property_read_u32(dev, "honeywell,pmin-pascal",
355 &data->pmin);378 &data->pmin);
356 if (ret)379 if (ret)
357 return dev_err_probe(dev, ret,380 return dev_err_probe(dev, ret,
358 "honeywell,pmin-pascal could not be read\n");381 "honeywell,pmin-pascal could not be read\n");
382
359 ret = device_property_read_u32(dev, "honeywell,pmax-pascal",383 ret = device_property_read_u32(dev, "honeywell,pmax-pascal",
360 &data->pmax);384 &data->pmax);
361 if (ret)385 if (ret)
362 return dev_err_probe(dev, ret,386 return dev_err_probe(dev, ret,
363 "honeywell,pmax-pascal could not be read\n");387 "honeywell,pmax-pascal could not be read\n");
364 ret = device_property_read_u32(dev,
365 "honeywell,transfer-function", &data->function);
366 if (ret)
367 return dev_err_probe(dev, ret,
368 "honeywell,transfer-function could not be read\n");
369 if (data->function > MPR_FUNCTION_C)
370 return dev_err_probe(dev, -EINVAL,
371 "honeywell,transfer-function %d invalid\n",
372 data->function);
373 } else {388 } else {
374 /* when loaded as i2c device we need to use default values */389 ret = device_property_match_property_string(dev,
375 dev_notice(dev, "firmware node not found; using defaults\n");390 "honeywell,pressure-triplet",
376 data->pmin = 0;391 mpr_triplet_variants,
377 data->pmax = 172369; /* 25 psi */392 MPR_VARIANTS_MAX);
378 data->function = MPR_FUNCTION_A;393 if (ret < 0)
394 return dev_err_probe(dev, -EINVAL,
395 "honeywell,pressure-triplet is invalid\n");
396
397 data->pmin = mpr_range_config[ret].pmin;
398 data->pmax = mpr_range_config[ret].pmax;
379 }399 }
380 400
401 if (data->pmin >= data->pmax)
402 return dev_err_probe(dev, -EINVAL,
403 "pressure limits are invalid\n");
404
381 data->outmin = mpr_func_spec[data->function].output_min;405 data->outmin = mpr_func_spec[data->function].output_min;
382 data->outmax = mpr_func_spec[data->function].output_max;406 data->outmax = mpr_func_spec[data->function].output_max;
383 407
384 /* use 64 bit calculation for preserving a reasonable precision */408 /* use 64 bit calculation for preserving a reasonable precision */
385 scale = div_s64(((s64)(data->pmax - data->pmin)) * NANO,409 scale = div_s64(((s64)(data->pmax - data->pmin)) * NANO,
386 data->outmax - data->outmin);410 data->outmax - data->outmin);
387 data->scale = div_s64_rem(scale, NANO, &data->scale2);411 data->scale = div_s64_rem(scale, NANO, &data->scale2);
388 /*412 /*
389 * multiply with NANO before dividing by scale and later divide by NANO413 * multiply with NANO before dividing by scale and later divide by NANO
390 * again.414 * again.
391 */415 */
392 offset = ((-1LL) * (s64)data->outmin) * NANO -416 offset = ((-1LL) * (s64)data->outmin) * NANO -
393 div_s64(div_s64((s64)data->pmin * NANO, scale), NANO);417 div_s64(div_s64((s64)data->pmin * NANO, scale), NANO);
394 data->offset = div_s64_rem(offset, NANO, &data->offset2);418 data->offset = div_s64_rem(offset, NANO, &data->offset2);
395 419
396 if (data->irq > 0) {420 if (data->irq > 0) {
397 ret = devm_request_irq(dev, data->irq, mpr_eoc_handler,421 ret = devm_request_irq(dev, data->irq, mpr_eoc_handler,
398 IRQF_TRIGGER_RISING, client->name, data);422 IRQF_TRIGGER_RISING,
423 dev_name(dev),
424 data);
399 if (ret)425 if (ret)
400 return dev_err_probe(dev, ret,426 return dev_err_probe(dev, ret,
401 "request irq %d failed\n", data->irq);427 "request irq %d failed\n", data->irq);
402 }428 }
403 429
404 data->gpiod_reset = devm_gpiod_get_optional(dev, "reset",430 data->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
405 GPIOD_OUT_HIGH);431 GPIOD_OUT_HIGH);
406 if (IS_ERR(data->gpiod_reset))432 if (IS_ERR(data->gpiod_reset))
407 return dev_err_probe(dev, PTR_ERR(data->gpiod_reset),433 return dev_err_probe(dev, PTR_ERR(data->gpiod_reset),
408 "request reset-gpio failed\n");434 "request reset-gpio failed\n");
409 435
410 mpr_reset(data);436 mpr_reset(data);
411 437
412 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,438 ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
413 mpr_trigger_handler, NULL);439 mpr_trigger_handler, NULL);
414 if (ret)440 if (ret)
415 return dev_err_probe(dev, ret,441 return dev_err_probe(dev, ret,
416 "iio triggered buffer setup failed\n");442 "iio triggered buffer setup failed\n");
417 443
418 ret = devm_iio_device_register(dev, indio_dev);444 ret = devm_iio_device_register(dev, indio_dev);
419 if (ret)445 if (ret)
420 return dev_err_probe(dev, ret,446 return dev_err_probe(dev, ret,
421 "unable to register iio device\n");447 "unable to register iio device\n");
422 448
423 return 0;449 return 0;
424}450}
425 451EXPORT_SYMBOL_NS(mpr_common_probe, IIO_HONEYWELL_MPRLS0025PA);
426static const struct of_device_id mpr_matches[] = {
427 { .compatible = "honeywell,mprls0025pa" },
428 { }
429};
430MODULE_DEVICE_TABLE(of, mpr_matches);
431
432static const struct i2c_device_id mpr_id[] = {
433 { "mprls0025pa" },
434 { }
435};
436MODULE_DEVICE_TABLE(i2c, mpr_id);
437
438static struct i2c_driver mpr_driver = {
439 .probe = mpr_probe,
440 .id_table = mpr_id,
441 .driver = {
442 .name = "mprls0025pa",
443 .of_match_table = mpr_matches,
444 },
445};
446module_i2c_driver(mpr_driver);
447 452
448MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");453MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
449MODULE_DESCRIPTION("Honeywell MPRLS0025PA I2C driver");454MODULE_DESCRIPTION("Honeywell MPR pressure sensor core driver");
450MODULE_LICENSE("GPL");455MODULE_LICENSE("GPL");
drivers/iio/pressure/mprls0025pa.h+102−0
@@ -0,0 +1,102 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * MPRLS0025PA - Honeywell MicroPressure pressure sensor series driver
4 *
5 * Copyright (c) Andreas Klinger <ak@it-klinger.de>
6 *
7 * Data sheet:
8 * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/micropressure-mpr-series/documents/sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
9 */
10
11#ifndef _MPRLS0025PA_H
12#define _MPRLS0025PA_H
13
14#include <linux/completion.h>
15#include <linux/delay.h>
16#include <linux/device.h>
17#include <linux/mutex.h>
18#include <linux/stddef.h>
19#include <linux/types.h>
20
21#include <linux/iio/iio.h>
22
23#define MPR_MEASUREMENT_RD_SIZE 4
24#define MPR_CMD_NOP 0xf0
25#define MPR_CMD_SYNC 0xaa
26#define MPR_PKT_NOP_LEN MPR_MEASUREMENT_RD_SIZE
27#define MPR_PKT_SYNC_LEN 3
28
29struct device;
30
31struct iio_chan_spec;
32struct iio_dev;
33
34struct mpr_data;
35struct mpr_ops;
36
37/**
38 * struct mpr_chan
39 * @pres: pressure value
40 * @ts: timestamp
41 */
42struct mpr_chan {
43 s32 pres;
44 s64 ts;
45};
46
47enum mpr_func_id {
48 MPR_FUNCTION_A,
49 MPR_FUNCTION_B,
50 MPR_FUNCTION_C,
51};
52
53/**
54 * struct mpr_data
55 * @dev: current device structure
56 * @ops: functions that implement the sensor reads/writes, bus init
57 * @lock: access to device during read
58 * @pmin: minimal pressure in pascal
59 * @pmax: maximal pressure in pascal
60 * @function: transfer function
61 * @outmin: minimum raw pressure in counts (based on transfer function)
62 * @outmax: maximum raw pressure in counts (based on transfer function)
63 * @scale: pressure scale
64 * @scale2: pressure scale, decimal number
65 * @offset: pressure offset
66 * @offset2: pressure offset, decimal number
67 * @gpiod_reset: reset
68 * @irq: end of conversion irq. used to distinguish between irq mode and
69 * reading in a loop until data is ready
70 * @completion: handshake from irq to read
71 * @chan: channel values for buffered mode
72 * @buffer: raw conversion data
73 */
74struct mpr_data {
75 struct device *dev;
76 const struct mpr_ops *ops;
77 struct mutex lock;
78 u32 pmin;
79 u32 pmax;
80 enum mpr_func_id function;
81 u32 outmin;
82 u32 outmax;
83 int scale;
84 int scale2;
85 int offset;
86 int offset2;
87 struct gpio_desc *gpiod_reset;
88 int irq;
89 struct completion completion;
90 struct mpr_chan chan;
91 u8 buffer[MPR_MEASUREMENT_RD_SIZE] __aligned(IIO_DMA_MINALIGN);
92};
93
94struct mpr_ops {
95 int (*init)(struct device *dev);
96 int (*read)(struct mpr_data *data, const u8 cmd, const u8 cnt);
97 int (*write)(struct mpr_data *data, const u8 cmd, const u8 cnt);
98};
99
100int mpr_common_probe(struct device *dev, const struct mpr_ops *ops, int irq);
101
102#endif
drivers/iio/pressure/mprls0025pa_i2c.c+100−0
@@ -0,0 +1,100 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * MPRLS0025PA - Honeywell MicroPressure pressure sensor series driver
4 *
5 * Copyright (c) Andreas Klinger <ak@it-klinger.de>
6 *
7 * Data sheet:
8 * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/micropressure-mpr-series/documents/sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
9 */
10
11#include <linux/device.h>
12#include <linux/errno.h>
13#include <linux/i2c.h>
14#include <linux/mod_devicetable.h>
15#include <linux/module.h>
16#include <linux/types.h>
17
18#include "mprls0025pa.h"
19
20static int mpr_i2c_init(struct device *unused)
21{
22 return 0;
23}
24
25static int mpr_i2c_read(struct mpr_data *data, const u8 unused, const u8 cnt)
26{
27 int ret;
28 struct i2c_client *client = to_i2c_client(data->dev);
29
30 if (cnt > MPR_MEASUREMENT_RD_SIZE)
31 return -EOVERFLOW;
32
33 memset(data->buffer, 0, MPR_MEASUREMENT_RD_SIZE);
34 ret = i2c_master_recv(client, data->buffer, cnt);
35 if (ret < 0)
36 return ret;
37 else if (ret != cnt)
38 return -EIO;
39
40 return 0;
41}
42
43static int mpr_i2c_write(struct mpr_data *data, const u8 cmd, const u8 unused)
44{
45 int ret;
46 struct i2c_client *client = to_i2c_client(data->dev);
47 u8 wdata[MPR_PKT_SYNC_LEN];
48
49 memset(wdata, 0, sizeof(wdata));
50 wdata[0] = cmd;
51
52 ret = i2c_master_send(client, wdata, MPR_PKT_SYNC_LEN);
53 if (ret < 0)
54 return ret;
55 else if (ret != MPR_PKT_SYNC_LEN)
56 return -EIO;
57
58 return 0;
59}
60
61static const struct mpr_ops mpr_i2c_ops = {
62 .init = mpr_i2c_init,
63 .read = mpr_i2c_read,
64 .write = mpr_i2c_write,
65};
66
67static int mpr_i2c_probe(struct i2c_client *client)
68{
69 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE))
70 return -EOPNOTSUPP;
71
72 return mpr_common_probe(&client->dev, &mpr_i2c_ops, client->irq);
73}
74
75static const struct of_device_id mpr_i2c_match[] = {
76 { .compatible = "honeywell,mprls0025pa" },
77 {}
78};
79MODULE_DEVICE_TABLE(of, mpr_i2c_match);
80
81static const struct i2c_device_id mpr_i2c_id[] = {
82 { "mprls0025pa" },
83 {}
84};
85MODULE_DEVICE_TABLE(i2c, mpr_i2c_id);
86
87static struct i2c_driver mpr_i2c_driver = {
88 .probe = mpr_i2c_probe,
89 .id_table = mpr_i2c_id,
90 .driver = {
91 .name = "mprls0025pa",
92 .of_match_table = mpr_i2c_match,
93 },
94};
95module_i2c_driver(mpr_i2c_driver);
96
97MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
98MODULE_DESCRIPTION("Honeywell MPR pressure sensor i2c driver");
99MODULE_LICENSE("GPL");
100MODULE_IMPORT_NS(IIO_HONEYWELL_MPRLS0025PA);
drivers/iio/pressure/mprls0025pa_spi.c+92−0
@@ -0,0 +1,92 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * MPRLS0025PA - Honeywell MicroPressure MPR series SPI sensor driver
4 *
5 * Copyright (c) 2024 Petre Rodan <petre.rodan@subdimension.ro>
6 *
7 * Data sheet:
8 * https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/products/sensors/pressure-sensors/board-mount-pressure-sensors/micropressure-mpr-series/documents/sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
9 */
10
11#include <linux/device.h>
12#include <linux/errno.h>
13#include <linux/mod_devicetable.h>
14#include <linux/module.h>
15#include <linux/spi/spi.h>
16#include <linux/stddef.h>
17#include <linux/types.h>
18
19#include "mprls0025pa.h"
20
21struct mpr_spi_buf {
22 u8 tx[MPR_MEASUREMENT_RD_SIZE] __aligned(IIO_DMA_MINALIGN);
23};
24
25static int mpr_spi_init(struct device *dev)
26{
27 struct spi_device *spi = to_spi_device(dev);
28 struct mpr_spi_buf *buf;
29
30 buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL);
31 if (!buf)
32 return -ENOMEM;
33
34 spi_set_drvdata(spi, buf);
35
36 return 0;
37}
38
39static int mpr_spi_xfer(struct mpr_data *data, const u8 cmd, const u8 pkt_len)
40{
41 struct spi_device *spi = to_spi_device(data->dev);
42 struct mpr_spi_buf *buf = spi_get_drvdata(spi);
43 struct spi_transfer xfer;
44
45 if (pkt_len > MPR_MEASUREMENT_RD_SIZE)
46 return -EOVERFLOW;
47
48 buf->tx[0] = cmd;
49 xfer.tx_buf = buf->tx;
50 xfer.rx_buf = data->buffer;
51 xfer.len = pkt_len;
52
53 return spi_sync_transfer(spi, &xfer, 1);
54}
55
56static const struct mpr_ops mpr_spi_ops = {
57 .init = mpr_spi_init,
58 .read = mpr_spi_xfer,
59 .write = mpr_spi_xfer,
60};
61
62static int mpr_spi_probe(struct spi_device *spi)
63{
64 return mpr_common_probe(&spi->dev, &mpr_spi_ops, spi->irq);
65}
66
67static const struct of_device_id mpr_spi_match[] = {
68 { .compatible = "honeywell,mprls0025pa" },
69 {}
70};
71MODULE_DEVICE_TABLE(of, mpr_spi_match);
72
73static const struct spi_device_id mpr_spi_id[] = {
74 { "mprls0025pa" },
75 {}
76};
77MODULE_DEVICE_TABLE(spi, mpr_spi_id);
78
79static struct spi_driver mpr_spi_driver = {
80 .driver = {
81 .name = "mprls0025pa",
82 .of_match_table = mpr_spi_match,
83 },
84 .probe = mpr_spi_probe,
85 .id_table = mpr_spi_id,
86};
87module_spi_driver(mpr_spi_driver);
88
89MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>");
90MODULE_DESCRIPTION("Honeywell MPR pressure sensor spi driver");
91MODULE_LICENSE("GPL");
92MODULE_IMPORT_NS(IIO_HONEYWELL_MPRLS0025PA);
drivers/iio/pressure/st_pressure_i2c.c+1−4
@@ -7,7 +7,6 @@ · 6 unmodified lines
7 * Denis Ciocca <denis.ciocca@st.com>7 * Denis Ciocca <denis.ciocca@st.com>
8 */8 */
9 9
10#include <linux/acpi.h>
11#include <linux/kernel.h>10#include <linux/kernel.h>
12#include <linux/module.h>11#include <linux/module.h>
13#include <linux/mod_devicetable.h>12#include <linux/mod_devicetable.h>
@@ -55,13 +54,11 @@ static const struct of_device_id st_press_of_match[] = { · 41 unmodified lines
55};54};
56MODULE_DEVICE_TABLE(of, st_press_of_match);55MODULE_DEVICE_TABLE(of, st_press_of_match);
57 56
58#ifdef CONFIG_ACPI
59static const struct acpi_device_id st_press_acpi_match[] = {57static const struct acpi_device_id st_press_acpi_match[] = {
60 {"SNO9210", LPS22HB},58 {"SNO9210", LPS22HB},
61 { },59 { },
62};60};
63MODULE_DEVICE_TABLE(acpi, st_press_acpi_match);61MODULE_DEVICE_TABLE(acpi, st_press_acpi_match);
64#endif
65 62
66static const struct i2c_device_id st_press_id_table[] = {63static const struct i2c_device_id st_press_id_table[] = {
67 { LPS001WP_PRESS_DEV_NAME, LPS001WP },64 { LPS001WP_PRESS_DEV_NAME, LPS001WP },
@@ -114,7 +111,7 @@ static struct i2c_driver st_press_driver = { · 46 unmodified lines
114 .driver = {111 .driver = {
115 .name = "st-press-i2c",112 .name = "st-press-i2c",
116 .of_match_table = st_press_of_match,113 .of_match_table = st_press_of_match,
117 .acpi_match_table = ACPI_PTR(st_press_acpi_match),114 .acpi_match_table = st_press_acpi_match,
118 },115 },
119 .probe = st_press_i2c_probe,116 .probe = st_press_i2c_probe,
120 .id_table = st_press_id_table,117 .id_table = st_press_id_table,
drivers/iio/proximity/isl29501.c+1−2
@@ -995,17 +995,16 @@ static const struct i2c_device_id isl29501_id[] = { · 994 unmodified lines
995 995
996MODULE_DEVICE_TABLE(i2c, isl29501_id);996MODULE_DEVICE_TABLE(i2c, isl29501_id);
997 997
998#if defined(CONFIG_OF)
999static const struct of_device_id isl29501_i2c_matches[] = {998static const struct of_device_id isl29501_i2c_matches[] = {
1000 { .compatible = "renesas,isl29501" },999 { .compatible = "renesas,isl29501" },
1001 { }1000 { }
1002};1001};
1003MODULE_DEVICE_TABLE(of, isl29501_i2c_matches);1002MODULE_DEVICE_TABLE(of, isl29501_i2c_matches);
1004#endif
1005 1003
1006static struct i2c_driver isl29501_driver = {1004static struct i2c_driver isl29501_driver = {
1007 .driver = {1005 .driver = {
1008 .name = "isl29501",1006 .name = "isl29501",
1007 .of_match_table = isl29501_i2c_matches,
1009 },1008 },
1010 .id_table = isl29501_id,1009 .id_table = isl29501_id,
1011 .probe = isl29501_probe,1010 .probe = isl29501_probe,
drivers/iio/proximity/sx9310.c+39−75
@@ -337,28 +337,19 @@ static int sx9310_read_raw(struct iio_dev *indio_dev, · 336 unmodified lines
337 int *val2, long mask)337 int *val2, long mask)
338{338{
339 struct sx_common_data *data = iio_priv(indio_dev);339 struct sx_common_data *data = iio_priv(indio_dev);
340 int ret;
341 340
342 if (chan->type != IIO_PROXIMITY)341 if (chan->type != IIO_PROXIMITY)
343 return -EINVAL;342 return -EINVAL;
344 343
345 switch (mask) {344 switch (mask) {
346 case IIO_CHAN_INFO_RAW:345 case IIO_CHAN_INFO_RAW:
347 ret = iio_device_claim_direct_mode(indio_dev);346 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
348 if (ret)347 return sx_common_read_proximity(data, chan, val);
349 return ret;348 unreachable();
350
351 ret = sx_common_read_proximity(data, chan, val);
352 iio_device_release_direct_mode(indio_dev);
353 return ret;
354 case IIO_CHAN_INFO_HARDWAREGAIN:349 case IIO_CHAN_INFO_HARDWAREGAIN:
355 ret = iio_device_claim_direct_mode(indio_dev);350 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
356 if (ret)351 return sx9310_read_gain(data, chan, val);
357 return ret;352 unreachable();
358
359 ret = sx9310_read_gain(data, chan, val);
360 iio_device_release_direct_mode(indio_dev);
361 return ret;
362 case IIO_CHAN_INFO_SAMP_FREQ:353 case IIO_CHAN_INFO_SAMP_FREQ:
363 return sx9310_read_samp_freq(data, val, val2);354 return sx9310_read_samp_freq(data, val, val2);
364 default:355 default:
@@ -546,12 +537,10 @@ static int sx9310_write_thresh(struct sx_common_data *data, · 181 unmodified lines
546 return -EINVAL;537 return -EINVAL;
547 538
548 regval = FIELD_PREP(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);539 regval = FIELD_PREP(SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
549 mutex_lock(&data->mutex);
550 ret = regmap_update_bits(data->regmap, reg,
551 SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
552 mutex_unlock(&data->mutex);
553 540
554 return ret;541 guard(mutex)(&data->mutex);
542 return regmap_update_bits(data->regmap, reg,
543 SX9310_REG_PROX_CTRL8_9_PTHRESH_MASK, regval);
555}544}
556 545
557static int sx9310_write_hysteresis(struct sx_common_data *data,546static int sx9310_write_hysteresis(struct sx_common_data *data,
@@ -576,17 +565,14 @@ static int sx9310_write_hysteresis(struct sx_common_data *data, · 18 unmodified lines
576 return -EINVAL;565 return -EINVAL;
577 566
578 hyst = FIELD_PREP(SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);567 hyst = FIELD_PREP(SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
579 mutex_lock(&data->mutex);
580 ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
581 SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
582 mutex_unlock(&data->mutex);
583 568
584 return ret;569 guard(mutex)(&data->mutex);
570 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
571 SX9310_REG_PROX_CTRL10_HYST_MASK, hyst);
585}572}
586 573
587static int sx9310_write_far_debounce(struct sx_common_data *data, int val)574static int sx9310_write_far_debounce(struct sx_common_data *data, int val)
588{575{
589 int ret;
590 unsigned int regval;576 unsigned int regval;
591 577
592 if (val > 0)578 if (val > 0)
@@ -596,18 +582,14 @@ static int sx9310_write_far_debounce(struct sx_common_data *data, int val) · 3 unmodified lines
596 582
597 regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val);583 regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK, val);
598 584
599 mutex_lock(&data->mutex);585 guard(mutex)(&data->mutex);
600 ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,586 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
601 SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK,587 SX9310_REG_PROX_CTRL10_FAR_DEBOUNCE_MASK,
602 regval);588 regval);
603 mutex_unlock(&data->mutex);
604
605 return ret;
606}589}
607 590
608static int sx9310_write_close_debounce(struct sx_common_data *data, int val)591static int sx9310_write_close_debounce(struct sx_common_data *data, int val)
609{592{
610 int ret;
611 unsigned int regval;593 unsigned int regval;
612 594
613 if (val > 0)595 if (val > 0)
@@ -617,13 +599,10 @@ static int sx9310_write_close_debounce(struct sx_common_data *data, int val) · 3 unmodified lines
617 599
618 regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val);600 regval = FIELD_PREP(SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK, val);
619 601
620 mutex_lock(&data->mutex);602 guard(mutex)(&data->mutex);
621 ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,603 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL10,
622 SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK,604 SX9310_REG_PROX_CTRL10_CLOSE_DEBOUNCE_MASK,
623 regval);605 regval);
624 mutex_unlock(&data->mutex);
625
626 return ret;
627}606}
628 607
629static int sx9310_write_event_val(struct iio_dev *indio_dev,608static int sx9310_write_event_val(struct iio_dev *indio_dev,
@@ -658,7 +637,7 @@ static int sx9310_write_event_val(struct iio_dev *indio_dev, · 28 unmodified lines
658 637
659static int sx9310_set_samp_freq(struct sx_common_data *data, int val, int val2)638static int sx9310_set_samp_freq(struct sx_common_data *data, int val, int val2)
660{639{
661 int i, ret;640 int i;
662 641
663 for (i = 0; i < ARRAY_SIZE(sx9310_samp_freq_table); i++)642 for (i = 0; i < ARRAY_SIZE(sx9310_samp_freq_table); i++)
664 if (val == sx9310_samp_freq_table[i].val &&643 if (val == sx9310_samp_freq_table[i].val &&
@@ -668,23 +647,17 @@ static int sx9310_set_samp_freq(struct sx_common_data *data, int val, int val2) · 3 unmodified lines
668 if (i == ARRAY_SIZE(sx9310_samp_freq_table))647 if (i == ARRAY_SIZE(sx9310_samp_freq_table))
669 return -EINVAL;648 return -EINVAL;
670 649
671 mutex_lock(&data->mutex);650 guard(mutex)(&data->mutex);
672 651 return regmap_update_bits(
673 ret = regmap_update_bits(
674 data->regmap, SX9310_REG_PROX_CTRL0,652 data->regmap, SX9310_REG_PROX_CTRL0,
675 SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK,653 SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK,
676 FIELD_PREP(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, i));654 FIELD_PREP(SX9310_REG_PROX_CTRL0_SCANPERIOD_MASK, i));
677
678 mutex_unlock(&data->mutex);
679
680 return ret;
681}655}
682 656
683static int sx9310_write_gain(struct sx_common_data *data,657static int sx9310_write_gain(struct sx_common_data *data,
684 const struct iio_chan_spec *chan, int val)658 const struct iio_chan_spec *chan, int val)
685{659{
686 unsigned int gain, mask;660 unsigned int gain, mask;
687 int ret;
688 661
689 gain = ilog2(val);662 gain = ilog2(val);
690 663
@@ -703,12 +676,9 @@ static int sx9310_write_gain(struct sx_common_data *data, · 12 unmodified lines
703 return -EINVAL;676 return -EINVAL;
704 }677 }
705 678
706 mutex_lock(&data->mutex);679 guard(mutex)(&data->mutex);
707 ret = regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL3, mask,680 return regmap_update_bits(data->regmap, SX9310_REG_PROX_CTRL3, mask,
708 gain);681 gain);
709 mutex_unlock(&data->mutex);
710
711 return ret;
712}682}
713 683
714static int sx9310_write_raw(struct iio_dev *indio_dev,684static int sx9310_write_raw(struct iio_dev *indio_dev,
@@ -969,22 +939,18 @@ static int sx9310_suspend(struct device *dev) · 254 unmodified lines
969 939
970 disable_irq_nosync(data->client->irq);940 disable_irq_nosync(data->client->irq);
971 941
972 mutex_lock(&data->mutex);942 guard(mutex)(&data->mutex);
973 ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0,943 ret = regmap_read(data->regmap, SX9310_REG_PROX_CTRL0,
974 &data->suspend_ctrl);944 &data->suspend_ctrl);
975 if (ret)945 if (ret)
976 goto out;946 return ret;
977 947
978 ctrl0 = data->suspend_ctrl & ~SX9310_REG_PROX_CTRL0_SENSOREN_MASK;948 ctrl0 = data->suspend_ctrl & ~SX9310_REG_PROX_CTRL0_SENSOREN_MASK;
979 ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);949 ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0, ctrl0);
980 if (ret)950 if (ret)
981 goto out;951 return ret;
982
983 ret = regmap_write(data->regmap, SX9310_REG_PAUSE, 0);
984 952
985out:953 return regmap_write(data->regmap, SX9310_REG_PAUSE, 0);
986 mutex_unlock(&data->mutex);
987 return ret;
988}954}
989 955
990static int sx9310_resume(struct device *dev)956static int sx9310_resume(struct device *dev)
@@ -992,18 +958,16 @@ static int sx9310_resume(struct device *dev) · 1 unmodified line
992 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));958 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
993 int ret;959 int ret;
994 960
995 mutex_lock(&data->mutex);961 scoped_guard(mutex, &data->mutex) {
996 ret = regmap_write(data->regmap, SX9310_REG_PAUSE, 1);962 ret = regmap_write(data->regmap, SX9310_REG_PAUSE, 1);
997 if (ret)963 if (ret)
998 goto out;964 return ret;
999
1000 ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
1001 data->suspend_ctrl);
1002 965
1003out:966 ret = regmap_write(data->regmap, SX9310_REG_PROX_CTRL0,
1004 mutex_unlock(&data->mutex);967 data->suspend_ctrl);
1005 if (ret)968 if (ret)
1006 return ret;969 return ret;
970 }
1007 971
1008 enable_irq(data->client->irq);972 enable_irq(data->client->irq);
1009 return 0;973 return 0;
drivers/iio/proximity/sx9324.c+79−99
@@ -429,25 +429,16 @@ static int sx9324_read_raw(struct iio_dev *indio_dev, · 428 unmodified lines
429 int *val, int *val2, long mask)429 int *val, int *val2, long mask)
430{430{
431 struct sx_common_data *data = iio_priv(indio_dev);431 struct sx_common_data *data = iio_priv(indio_dev);
432 int ret;
433 432
434 switch (mask) {433 switch (mask) {
435 case IIO_CHAN_INFO_RAW:434 case IIO_CHAN_INFO_RAW:
436 ret = iio_device_claim_direct_mode(indio_dev);435 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
437 if (ret)436 return sx_common_read_proximity(data, chan, val);
438 return ret;437 unreachable();
439
440 ret = sx_common_read_proximity(data, chan, val);
441 iio_device_release_direct_mode(indio_dev);
442 return ret;
443 case IIO_CHAN_INFO_HARDWAREGAIN:438 case IIO_CHAN_INFO_HARDWAREGAIN:
444 ret = iio_device_claim_direct_mode(indio_dev);439 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
445 if (ret)440 return sx9324_read_gain(data, chan, val);
446 return ret;441 unreachable();
447
448 ret = sx9324_read_gain(data, chan, val);
449 iio_device_release_direct_mode(indio_dev);
450 return ret;
451 case IIO_CHAN_INFO_SAMP_FREQ:442 case IIO_CHAN_INFO_SAMP_FREQ:
452 return sx9324_read_samp_freq(data, val, val2);443 return sx9324_read_samp_freq(data, val, val2);
453 default:444 default:
@@ -484,7 +475,7 @@ static int sx9324_read_avail(struct iio_dev *indio_dev, · 30 unmodified lines
484static int sx9324_set_samp_freq(struct sx_common_data *data,475static int sx9324_set_samp_freq(struct sx_common_data *data,
485 int val, int val2)476 int val, int val2)
486{477{
487 int i, ret;478 int i;
488 479
489 for (i = 0; i < ARRAY_SIZE(sx9324_samp_freq_table); i++)480 for (i = 0; i < ARRAY_SIZE(sx9324_samp_freq_table); i++)
490 if (val == sx9324_samp_freq_table[i].val &&481 if (val == sx9324_samp_freq_table[i].val &&
@@ -494,15 +485,11 @@ static int sx9324_set_samp_freq(struct sx_common_data *data, · 3 unmodified lines
494 if (i == ARRAY_SIZE(sx9324_samp_freq_table))485 if (i == ARRAY_SIZE(sx9324_samp_freq_table))
495 return -EINVAL;486 return -EINVAL;
496 487
497 mutex_lock(&data->mutex);488 guard(mutex)(&data->mutex);
498
499 ret = regmap_update_bits(data->regmap,
500 SX9324_REG_GNRL_CTRL0,
501 SX9324_REG_GNRL_CTRL0_SCANPERIOD_MASK, i);
502
503 mutex_unlock(&data->mutex);
504 489
505 return ret;490 return regmap_update_bits(data->regmap,
491 SX9324_REG_GNRL_CTRL0,
492 SX9324_REG_GNRL_CTRL0_SCANPERIOD_MASK, i);
506}493}
507 494
508static int sx9324_read_thresh(struct sx_common_data *data,495static int sx9324_read_thresh(struct sx_common_data *data,
@@ -623,7 +610,6 @@ static int sx9324_write_thresh(struct sx_common_data *data, · 114 unmodified lines
623 const struct iio_chan_spec *chan, int _val)610 const struct iio_chan_spec *chan, int _val)
624{611{
625 unsigned int reg, val = _val;612 unsigned int reg, val = _val;
626 int ret;
627 613
628 reg = SX9324_REG_PROX_CTRL6 + chan->channel / 2;614 reg = SX9324_REG_PROX_CTRL6 + chan->channel / 2;
629 615
@@ -633,11 +619,9 @@ static int sx9324_write_thresh(struct sx_common_data *data, · 3 unmodified lines
633 if (val > 0xff)619 if (val > 0xff)
634 return -EINVAL;620 return -EINVAL;
635 621
636 mutex_lock(&data->mutex);622 guard(mutex)(&data->mutex);
637 ret = regmap_write(data->regmap, reg, val);
638 mutex_unlock(&data->mutex);
639 623
640 return ret;624 return regmap_write(data->regmap, reg, val);
641}625}
642 626
643static int sx9324_write_hysteresis(struct sx_common_data *data,627static int sx9324_write_hysteresis(struct sx_common_data *data,
@@ -662,18 +646,15 @@ static int sx9324_write_hysteresis(struct sx_common_data *data, · 18 unmodified lines
662 return -EINVAL;646 return -EINVAL;
663 647
664 hyst = FIELD_PREP(SX9324_REG_PROX_CTRL5_HYST_MASK, hyst);648 hyst = FIELD_PREP(SX9324_REG_PROX_CTRL5_HYST_MASK, hyst);
665 mutex_lock(&data->mutex);649 guard(mutex)(&data->mutex);
666 ret = regmap_update_bits(data->regmap, SX9324_REG_PROX_CTRL5,
667 SX9324_REG_PROX_CTRL5_HYST_MASK, hyst);
668 mutex_unlock(&data->mutex);
669 650
670 return ret;651 return regmap_update_bits(data->regmap, SX9324_REG_PROX_CTRL5,
652 SX9324_REG_PROX_CTRL5_HYST_MASK, hyst);
671}653}
672 654
673static int sx9324_write_far_debounce(struct sx_common_data *data, int _val)655static int sx9324_write_far_debounce(struct sx_common_data *data, int _val)
674{656{
675 unsigned int regval, val = _val;657 unsigned int regval, val = _val;
676 int ret;
677 658
678 if (val > 0)659 if (val > 0)
679 val = ilog2(val);660 val = ilog2(val);
@@ -682,19 +663,16 @@ static int sx9324_write_far_debounce(struct sx_common_data *data, int _val) · 2 unmodified lines
682 663
683 regval = FIELD_PREP(SX9324_REG_PROX_CTRL5_FAR_DEBOUNCE_MASK, val);664 regval = FIELD_PREP(SX9324_REG_PROX_CTRL5_FAR_DEBOUNCE_MASK, val);
684 665
685 mutex_lock(&data->mutex);666 guard(mutex)(&data->mutex);
686 ret = regmap_update_bits(data->regmap, SX9324_REG_PROX_CTRL5,
687 SX9324_REG_PROX_CTRL5_FAR_DEBOUNCE_MASK,
688 regval);
689 mutex_unlock(&data->mutex);
690 667
691 return ret;668 return regmap_update_bits(data->regmap, SX9324_REG_PROX_CTRL5,
669 SX9324_REG_PROX_CTRL5_FAR_DEBOUNCE_MASK,
670 regval);
692}671}
693 672
694static int sx9324_write_close_debounce(struct sx_common_data *data, int _val)673static int sx9324_write_close_debounce(struct sx_common_data *data, int _val)
695{674{
696 unsigned int regval, val = _val;675 unsigned int regval, val = _val;
697 int ret;
698 676
699 if (val > 0)677 if (val > 0)
700 val = ilog2(val);678 val = ilog2(val);
@@ -703,13 +681,11 @@ static int sx9324_write_close_debounce(struct sx_common_data *data, int _val) · 2 unmodified lines
703 681
704 regval = FIELD_PREP(SX9324_REG_PROX_CTRL5_CLOSE_DEBOUNCE_MASK, val);682 regval = FIELD_PREP(SX9324_REG_PROX_CTRL5_CLOSE_DEBOUNCE_MASK, val);
705 683
706 mutex_lock(&data->mutex);684 guard(mutex)(&data->mutex);
707 ret = regmap_update_bits(data->regmap, SX9324_REG_PROX_CTRL5,
708 SX9324_REG_PROX_CTRL5_CLOSE_DEBOUNCE_MASK,
709 regval);
710 mutex_unlock(&data->mutex);
711 685
712 return ret;686 return regmap_update_bits(data->regmap, SX9324_REG_PROX_CTRL5,
687 SX9324_REG_PROX_CTRL5_CLOSE_DEBOUNCE_MASK,
688 regval);
713}689}
714 690
715static int sx9324_write_event_val(struct iio_dev *indio_dev,691static int sx9324_write_event_val(struct iio_dev *indio_dev,
@@ -746,7 +722,6 @@ static int sx9324_write_gain(struct sx_common_data *data, · 30 unmodified lines
746 const struct iio_chan_spec *chan, int val)722 const struct iio_chan_spec *chan, int val)
747{723{
748 unsigned int gain, reg;724 unsigned int gain, reg;
749 int ret;
750 725
751 reg = SX9324_REG_PROX_CTRL0 + chan->channel / 2;726 reg = SX9324_REG_PROX_CTRL0 + chan->channel / 2;
752 727
@@ -756,13 +731,11 @@ static int sx9324_write_gain(struct sx_common_data *data, · 3 unmodified lines
756 731
757 gain = FIELD_PREP(SX9324_REG_PROX_CTRL0_GAIN_MASK, gain);732 gain = FIELD_PREP(SX9324_REG_PROX_CTRL0_GAIN_MASK, gain);
758 733
759 mutex_lock(&data->mutex);734 guard(mutex)(&data->mutex);
760 ret = regmap_update_bits(data->regmap, reg,
761 SX9324_REG_PROX_CTRL0_GAIN_MASK,
762 gain);
763 mutex_unlock(&data->mutex);
764 735
765 return ret;736 return regmap_update_bits(data->regmap, reg,
737 SX9324_REG_PROX_CTRL0_GAIN_MASK,
738 gain);
766}739}
767 740
768static int sx9324_write_raw(struct iio_dev *indio_dev,741static int sx9324_write_raw(struct iio_dev *indio_dev,
@@ -873,6 +846,29 @@ static int sx9324_init_compensation(struct iio_dev *indio_dev) · 104 unmodified lines
873 20000, 2000000);846 20000, 2000000);
874}847}
875 848
849static u8 sx9324_parse_phase_prop(struct device *dev,
850 struct sx_common_reg_default *reg_def,
851 const char *prop)
852{
853 unsigned int pin_defs[SX9324_NUM_PINS];
854 int count, ret, pin;
855 u32 raw = 0;
856
857 count = device_property_count_u32(dev, prop);
858 if (count != ARRAY_SIZE(pin_defs))
859 return reg_def->def;
860 ret = device_property_read_u32_array(dev, prop, pin_defs,
861 ARRAY_SIZE(pin_defs));
862 if (ret)
863 return reg_def->def;
864
865 for (pin = 0; pin < SX9324_NUM_PINS; pin++)
866 raw |= (pin_defs[pin] << (2 * pin)) &
867 SX9324_REG_AFE_PH0_PIN_MASK(pin);
868
869 return raw;
870}
871
876static const struct sx_common_reg_default *872static const struct sx_common_reg_default *
877sx9324_get_default_reg(struct device *dev, int idx,873sx9324_get_default_reg(struct device *dev, int idx,
878 struct sx_common_reg_default *reg_def)874 struct sx_common_reg_default *reg_def)
@@ -881,37 +877,29 @@ sx9324_get_default_reg(struct device *dev, int idx, · 2 unmodified lines
881 "highest" };877 "highest" };
882 static const char * const sx9324_csidle[] = { "hi-z", "hi-z", "gnd",878 static const char * const sx9324_csidle[] = { "hi-z", "hi-z", "gnd",
883 "vdd" };879 "vdd" };
884#define SX9324_PIN_DEF "semtech,ph0-pin"
885#define SX9324_RESOLUTION_DEF "semtech,ph01-resolution"
886#define SX9324_PROXRAW_DEF "semtech,ph01-proxraw-strength"
887 unsigned int pin_defs[SX9324_NUM_PINS];
888 char prop[] = SX9324_PROXRAW_DEF;
889 u32 start = 0, raw = 0, pos = 0;880 u32 start = 0, raw = 0, pos = 0;
890 int ret, count, ph, pin;881 const char *prop;
882 int ret;
891 883
892 memcpy(reg_def, &sx9324_default_regs[idx], sizeof(*reg_def));884 memcpy(reg_def, &sx9324_default_regs[idx], sizeof(*reg_def));
893 885
894 sx_common_get_raw_register_config(dev, reg_def);886 sx_common_get_raw_register_config(dev, reg_def);
895 switch (reg_def->reg) {887 switch (reg_def->reg) {
896 case SX9324_REG_AFE_PH0:888 case SX9324_REG_AFE_PH0:
889 reg_def->def = sx9324_parse_phase_prop(dev, reg_def,
890 "semtech,ph0-pin");
891 break;
897 case SX9324_REG_AFE_PH1:892 case SX9324_REG_AFE_PH1:
893 reg_def->def = sx9324_parse_phase_prop(dev, reg_def,
894 "semtech,ph1-pin");
895 break;
898 case SX9324_REG_AFE_PH2:896 case SX9324_REG_AFE_PH2:
897 reg_def->def = sx9324_parse_phase_prop(dev, reg_def,
898 "semtech,ph2-pin");
899 break;
899 case SX9324_REG_AFE_PH3:900 case SX9324_REG_AFE_PH3:
900 ph = reg_def->reg - SX9324_REG_AFE_PH0;901 reg_def->def = sx9324_parse_phase_prop(dev, reg_def,
901 snprintf(prop, ARRAY_SIZE(prop), "semtech,ph%d-pin", ph);902 "semtech,ph3-pin");
902
903 count = device_property_count_u32(dev, prop);
904 if (count != ARRAY_SIZE(pin_defs))
905 break;
906 ret = device_property_read_u32_array(dev, prop, pin_defs,
907 ARRAY_SIZE(pin_defs));
908 if (ret)
909 break;
910
911 for (pin = 0; pin < SX9324_NUM_PINS; pin++)
912 raw |= (pin_defs[pin] << (2 * pin)) &
913 SX9324_REG_AFE_PH0_PIN_MASK(pin);
914 reg_def->def = raw;
915 break;903 break;
916 case SX9324_REG_AFE_CTRL0:904 case SX9324_REG_AFE_CTRL0:
917 ret = device_property_match_property_string(dev, "semtech,cs-idle-sleep",905 ret = device_property_match_property_string(dev, "semtech,cs-idle-sleep",
@@ -933,11 +921,9 @@ sx9324_get_default_reg(struct device *dev, int idx, · 15 unmodified lines
933 case SX9324_REG_AFE_CTRL4:921 case SX9324_REG_AFE_CTRL4:
934 case SX9324_REG_AFE_CTRL7:922 case SX9324_REG_AFE_CTRL7:
935 if (reg_def->reg == SX9324_REG_AFE_CTRL4)923 if (reg_def->reg == SX9324_REG_AFE_CTRL4)
936 strncpy(prop, "semtech,ph01-resolution",924 prop = "semtech,ph01-resolution";
937 ARRAY_SIZE(prop));
938 else925 else
939 strncpy(prop, "semtech,ph23-resolution",926 prop = "semtech,ph23-resolution";
940 ARRAY_SIZE(prop));
941 927
942 ret = device_property_read_u32(dev, prop, &raw);928 ret = device_property_read_u32(dev, prop, &raw);
943 if (ret)929 if (ret)
@@ -1008,11 +994,9 @@ sx9324_get_default_reg(struct device *dev, int idx, · 64 unmodified lines
1008 case SX9324_REG_PROX_CTRL0:994 case SX9324_REG_PROX_CTRL0:
1009 case SX9324_REG_PROX_CTRL1:995 case SX9324_REG_PROX_CTRL1:
1010 if (reg_def->reg == SX9324_REG_PROX_CTRL0)996 if (reg_def->reg == SX9324_REG_PROX_CTRL0)
1011 strncpy(prop, "semtech,ph01-proxraw-strength",997 prop = "semtech,ph01-proxraw-strength";
1012 ARRAY_SIZE(prop));
1013 else998 else
1014 strncpy(prop, "semtech,ph23-proxraw-strength",999 prop = "semtech,ph23-proxraw-strength";
1015 ARRAY_SIZE(prop));
1016 ret = device_property_read_u32(dev, prop, &raw);1000 ret = device_property_read_u32(dev, prop, &raw);
1017 if (ret)1001 if (ret)
1018 break;1002 break;
@@ -1081,34 +1065,30 @@ static int sx9324_suspend(struct device *dev) · 62 unmodified lines
1081 1065
1082 disable_irq_nosync(data->client->irq);1066 disable_irq_nosync(data->client->irq);
1083 1067
1084 mutex_lock(&data->mutex);1068 guard(mutex)(&data->mutex);
1085 ret = regmap_read(data->regmap, SX9324_REG_GNRL_CTRL1, &regval);1069 ret = regmap_read(data->regmap, SX9324_REG_GNRL_CTRL1, &regval);
1070 if (ret < 0)
1071 return ret;
1086 1072
1087 data->suspend_ctrl =1073 data->suspend_ctrl =
1088 FIELD_GET(SX9324_REG_GNRL_CTRL1_PHEN_MASK, regval);1074 FIELD_GET(SX9324_REG_GNRL_CTRL1_PHEN_MASK, regval);
1089 1075
1090 if (ret < 0)
1091 goto out;
1092 1076
1093 /* Disable all phases, send the device to sleep. */1077 /* Disable all phases, send the device to sleep. */
1094 ret = regmap_write(data->regmap, SX9324_REG_GNRL_CTRL1, 0);1078 return regmap_write(data->regmap, SX9324_REG_GNRL_CTRL1, 0);
1095
1096out:
1097 mutex_unlock(&data->mutex);
1098 return ret;
1099}1079}
1100 1080
1101static int sx9324_resume(struct device *dev)1081static int sx9324_resume(struct device *dev)
1102{1082{
1103 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));1083 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
1104 int ret;
1105 1084
1106 mutex_lock(&data->mutex);1085 scoped_guard(mutex, &data->mutex) {
1107 ret = regmap_write(data->regmap, SX9324_REG_GNRL_CTRL1,1086 int ret = regmap_write(data->regmap, SX9324_REG_GNRL_CTRL1,
1108 data->suspend_ctrl | SX9324_REG_GNRL_CTRL1_PAUSECTRL);1087 data->suspend_ctrl |
1109 mutex_unlock(&data->mutex);1088 SX9324_REG_GNRL_CTRL1_PAUSECTRL);
1110 if (ret)1089 if (ret)
1111 return ret;1090 return ret;
1091 }
1112 1092
1113 enable_irq(data->client->irq);1093 enable_irq(data->client->irq);
1114 return 0;1094 return 0;
drivers/iio/proximity/sx9360.c+39−76
@@ -322,25 +322,16 @@ static int sx9360_read_raw(struct iio_dev *indio_dev, · 321 unmodified lines
322 int *val, int *val2, long mask)322 int *val, int *val2, long mask)
323{323{
324 struct sx_common_data *data = iio_priv(indio_dev);324 struct sx_common_data *data = iio_priv(indio_dev);
325 int ret;
326 325
327 switch (mask) {326 switch (mask) {
328 case IIO_CHAN_INFO_RAW:327 case IIO_CHAN_INFO_RAW:
329 ret = iio_device_claim_direct_mode(indio_dev);328 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
330 if (ret)329 return sx_common_read_proximity(data, chan, val);
331 return ret;330 unreachable();
332
333 ret = sx_common_read_proximity(data, chan, val);
334 iio_device_release_direct_mode(indio_dev);
335 return ret;
336 case IIO_CHAN_INFO_HARDWAREGAIN:331 case IIO_CHAN_INFO_HARDWAREGAIN:
337 ret = iio_device_claim_direct_mode(indio_dev);332 iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
338 if (ret)333 return sx9360_read_gain(data, chan, val);
339 return ret;334 unreachable();
340
341 ret = sx9360_read_gain(data, chan, val);
342 iio_device_release_direct_mode(indio_dev);
343 return ret;
344 case IIO_CHAN_INFO_SAMP_FREQ:335 case IIO_CHAN_INFO_SAMP_FREQ:
345 return sx9360_read_samp_freq(data, val, val2);336 return sx9360_read_samp_freq(data, val, val2);
346 default:337 default:
@@ -387,19 +378,15 @@ static int sx9360_read_avail(struct iio_dev *indio_dev, · 40 unmodified lines
387static int sx9360_set_samp_freq(struct sx_common_data *data,378static int sx9360_set_samp_freq(struct sx_common_data *data,
388 int val, int val2)379 int val, int val2)
389{380{
390 int ret, reg;381 int reg;
391 __be16 buf;382 __be16 buf;
392 383
393 reg = val * 8192 / SX9360_FOSC_HZ + val2 * 8192 / (SX9360_FOSC_MHZ);384 reg = val * 8192 / SX9360_FOSC_HZ + val2 * 8192 / (SX9360_FOSC_MHZ);
394 buf = cpu_to_be16(reg);385 buf = cpu_to_be16(reg);
395 mutex_lock(&data->mutex);386 guard(mutex)(&data->mutex);
396
397 ret = regmap_bulk_write(data->regmap, SX9360_REG_GNRL_CTRL1, &buf,
398 sizeof(buf));
399 387
400 mutex_unlock(&data->mutex);388 return regmap_bulk_write(data->regmap, SX9360_REG_GNRL_CTRL1, &buf,
401 389 sizeof(buf));
402 return ret;
403}390}
404 391
405static int sx9360_read_thresh(struct sx_common_data *data, int *val)392static int sx9360_read_thresh(struct sx_common_data *data, int *val)
@@ -510,7 +497,6 @@ static int sx9360_read_event_val(struct iio_dev *indio_dev, · 104 unmodified lines
510static int sx9360_write_thresh(struct sx_common_data *data, int _val)497static int sx9360_write_thresh(struct sx_common_data *data, int _val)
511{498{
512 unsigned int val = _val;499 unsigned int val = _val;
513 int ret;
514 500
515 if (val >= 1)501 if (val >= 1)
516 val = int_sqrt(2 * val);502 val = int_sqrt(2 * val);
@@ -518,11 +504,8 @@ static int sx9360_write_thresh(struct sx_common_data *data, int _val) · 1 unmodified line
518 if (val > 0xff)504 if (val > 0xff)
519 return -EINVAL;505 return -EINVAL;
520 506
521 mutex_lock(&data->mutex);507 guard(mutex)(&data->mutex);
522 ret = regmap_write(data->regmap, SX9360_REG_PROX_CTRL5, val);508 return regmap_write(data->regmap, SX9360_REG_PROX_CTRL5, val);
523 mutex_unlock(&data->mutex);
524
525 return ret;
526}509}
527 510
528static int sx9360_write_hysteresis(struct sx_common_data *data, int _val)511static int sx9360_write_hysteresis(struct sx_common_data *data, int _val)
@@ -546,18 +529,14 @@ static int sx9360_write_hysteresis(struct sx_common_data *data, int _val) · 17 unmodified lines
546 return -EINVAL;529 return -EINVAL;
547 530
548 hyst = FIELD_PREP(SX9360_REG_PROX_CTRL4_HYST_MASK, hyst);531 hyst = FIELD_PREP(SX9360_REG_PROX_CTRL4_HYST_MASK, hyst);
549 mutex_lock(&data->mutex);532 guard(mutex)(&data->mutex);
550 ret = regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,533 return regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,
551 SX9360_REG_PROX_CTRL4_HYST_MASK, hyst);534 SX9360_REG_PROX_CTRL4_HYST_MASK, hyst);
552 mutex_unlock(&data->mutex);
553
554 return ret;
555}535}
556 536
557static int sx9360_write_far_debounce(struct sx_common_data *data, int _val)537static int sx9360_write_far_debounce(struct sx_common_data *data, int _val)
558{538{
559 unsigned int regval, val = _val;539 unsigned int regval, val = _val;
560 int ret;
561 540
562 if (val > 0)541 if (val > 0)
563 val = ilog2(val);542 val = ilog2(val);
@@ -566,19 +545,15 @@ static int sx9360_write_far_debounce(struct sx_common_data *data, int _val) · 2 unmodified lines
566 545
567 regval = FIELD_PREP(SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK, val);546 regval = FIELD_PREP(SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK, val);
568 547
569 mutex_lock(&data->mutex);548 guard(mutex)(&data->mutex);
570 ret = regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,549 return regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,
571 SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK,550 SX9360_REG_PROX_CTRL4_FAR_DEBOUNCE_MASK,
572 regval);551 regval);
573 mutex_unlock(&data->mutex);
574
575 return ret;
576}552}
577 553
578static int sx9360_write_close_debounce(struct sx_common_data *data, int _val)554static int sx9360_write_close_debounce(struct sx_common_data *data, int _val)
579{555{
580 unsigned int regval, val = _val;556 unsigned int regval, val = _val;
581 int ret;
582 557
583 if (val > 0)558 if (val > 0)
584 val = ilog2(val);559 val = ilog2(val);
@@ -587,13 +562,10 @@ static int sx9360_write_close_debounce(struct sx_common_data *data, int _val) · 2 unmodified lines
587 562
588 regval = FIELD_PREP(SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK, val);563 regval = FIELD_PREP(SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK, val);
589 564
590 mutex_lock(&data->mutex);565 guard(mutex)(&data->mutex);
591 ret = regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,566 return regmap_update_bits(data->regmap, SX9360_REG_PROX_CTRL4,
592 SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK,567 SX9360_REG_PROX_CTRL4_CLOSE_DEBOUNCE_MASK,
593 regval);568 regval);
594 mutex_unlock(&data->mutex);
595
596 return ret;
597}569}
598 570
599static int sx9360_write_event_val(struct iio_dev *indio_dev,571static int sx9360_write_event_val(struct iio_dev *indio_dev,
@@ -630,19 +602,15 @@ static int sx9360_write_gain(struct sx_common_data *data, · 30 unmodified lines
630 const struct iio_chan_spec *chan, int val)602 const struct iio_chan_spec *chan, int val)
631{603{
632 unsigned int gain, reg;604 unsigned int gain, reg;
633 int ret;
634 605
635 gain = ilog2(val);606 gain = ilog2(val);
636 reg = SX9360_REG_PROX_CTRL0_PHR + chan->channel;607 reg = SX9360_REG_PROX_CTRL0_PHR + chan->channel;
637 gain = FIELD_PREP(SX9360_REG_PROX_CTRL0_GAIN_MASK, gain);608 gain = FIELD_PREP(SX9360_REG_PROX_CTRL0_GAIN_MASK, gain);
638 609
639 mutex_lock(&data->mutex);610 guard(mutex)(&data->mutex);
640 ret = regmap_update_bits(data->regmap, reg,611 return regmap_update_bits(data->regmap, reg,
641 SX9360_REG_PROX_CTRL0_GAIN_MASK,612 SX9360_REG_PROX_CTRL0_GAIN_MASK,
642 gain);613 gain);
643 mutex_unlock(&data->mutex);
644
645 return ret;
646}614}
647 615
648static int sx9360_write_raw(struct iio_dev *indio_dev,616static int sx9360_write_raw(struct iio_dev *indio_dev,
@@ -827,36 +795,31 @@ static int sx9360_suspend(struct device *dev) · 178 unmodified lines
827 795
828 disable_irq_nosync(data->client->irq);796 disable_irq_nosync(data->client->irq);
829 797
830 mutex_lock(&data->mutex);798 guard(mutex)(&data->mutex);
831 ret = regmap_read(data->regmap, SX9360_REG_GNRL_CTRL0, &regval);799 ret = regmap_read(data->regmap, SX9360_REG_GNRL_CTRL0, &regval);
800 if (ret < 0)
801 return ret;
832 802
833 data->suspend_ctrl =803 data->suspend_ctrl =
834 FIELD_GET(SX9360_REG_GNRL_CTRL0_PHEN_MASK, regval);804 FIELD_GET(SX9360_REG_GNRL_CTRL0_PHEN_MASK, regval);
835 805
836 if (ret < 0)
837 goto out;
838 806
839 /* Disable all phases, send the device to sleep. */807 /* Disable all phases, send the device to sleep. */
840 ret = regmap_write(data->regmap, SX9360_REG_GNRL_CTRL0, 0);808 return regmap_write(data->regmap, SX9360_REG_GNRL_CTRL0, 0);
841
842out:
843 mutex_unlock(&data->mutex);
844 return ret;
845}809}
846 810
847static int sx9360_resume(struct device *dev)811static int sx9360_resume(struct device *dev)
848{812{
849 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));813 struct sx_common_data *data = iio_priv(dev_get_drvdata(dev));
850 int ret;
851
852 mutex_lock(&data->mutex);
853 ret = regmap_update_bits(data->regmap, SX9360_REG_GNRL_CTRL0,
854 SX9360_REG_GNRL_CTRL0_PHEN_MASK,
855 data->suspend_ctrl);
856 mutex_unlock(&data->mutex);
857 if (ret)
858 return ret;
859 814
815 scoped_guard(mutex, &data->mutex) {
816 int ret = regmap_update_bits(data->regmap,
817 SX9360_REG_GNRL_CTRL0,
818 SX9360_REG_GNRL_CTRL0_PHEN_MASK,
819 data->suspend_ctrl);
820 if (ret)
821 return ret;
822 }
860 enable_irq(data->client->irq);823 enable_irq(data->client->irq);
861 return 0;824 return 0;
862}825}
drivers/iio/temperature/ltc2983.c+18−10
@@ -207,6 +207,7 @@ enum { · 206 unmodified lines
207 container_of(_sensor, struct ltc2983_temp, sensor)207 container_of(_sensor, struct ltc2983_temp, sensor)
208 208
209struct ltc2983_chip_info {209struct ltc2983_chip_info {
210 const char *name;
210 unsigned int max_channels_nr;211 unsigned int max_channels_nr;
211 bool has_temp;212 bool has_temp;
212 bool has_eeprom;213 bool has_eeprom;
@@ -1346,7 +1347,7 @@ static irqreturn_t ltc2983_irq_handler(int irq, void *data) · 1133 unmodified lines
1346 __chan; \1347 __chan; \
1347})1348})
1348 1349
1349static int ltc2983_parse_dt(struct ltc2983_data *st)1350static int ltc2983_parse_fw(struct ltc2983_data *st)
1350{1351{
1351 struct device *dev = &st->spi->dev;1352 struct device *dev = &st->spi->dev;
1352 struct fwnode_handle *child;1353 struct fwnode_handle *child;
@@ -1605,7 +1606,6 @@ static int ltc2983_probe(struct spi_device *spi) · 252 unmodified lines
1605 struct ltc2983_data *st;1606 struct ltc2983_data *st;
1606 struct iio_dev *indio_dev;1607 struct iio_dev *indio_dev;
1607 struct gpio_desc *gpio;1608 struct gpio_desc *gpio;
1608 const char *name = spi_get_device_id(spi)->name;
1609 int ret;1609 int ret;
1610 1610
1611 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));1611 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
@@ -1614,9 +1614,7 @@ static int ltc2983_probe(struct spi_device *spi) · 2 unmodified lines
1614 1614
1615 st = iio_priv(indio_dev);1615 st = iio_priv(indio_dev);
1616 1616
1617 st->info = device_get_match_data(&spi->dev);1617 st->info = spi_get_device_match_data(spi);
1618 if (!st->info)
1619 st->info = (void *)spi_get_device_id(spi)->driver_data;
1620 if (!st->info)1618 if (!st->info)
1621 return -ENODEV;1619 return -ENODEV;
1622 1620
@@ -1632,7 +1630,7 @@ static int ltc2983_probe(struct spi_device *spi) · 9 unmodified lines
1632 st->eeprom_key = cpu_to_be32(LTC2983_EEPROM_KEY);1630 st->eeprom_key = cpu_to_be32(LTC2983_EEPROM_KEY);
1633 spi_set_drvdata(spi, st);1631 spi_set_drvdata(spi, st);
1634 1632
1635 ret = ltc2983_parse_dt(st);1633 ret = ltc2983_parse_fw(st);
1636 if (ret)1634 if (ret)
1637 return ret;1635 return ret;
1638 1636
@@ -1657,7 +1655,7 @@ static int ltc2983_probe(struct spi_device *spi) · 18 unmodified lines
1657 return ret;1655 return ret;
1658 1656
1659 ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler,1657 ret = devm_request_irq(&spi->dev, spi->irq, ltc2983_irq_handler,
1660 IRQF_TRIGGER_RISING, name, st);1658 IRQF_TRIGGER_RISING, st->info->name, st);
1661 if (ret) {1659 if (ret) {
1662 dev_err(&spi->dev, "failed to request an irq, %d", ret);1660 dev_err(&spi->dev, "failed to request an irq, %d", ret);
1663 return ret;1661 return ret;
@@ -1672,7 +1670,7 @@ static int ltc2983_probe(struct spi_device *spi) · 8 unmodified lines
1672 return ret;1670 return ret;
1673 }1671 }
1674 1672
1675 indio_dev->name = name;1673 indio_dev->name = st->info->name;
1676 indio_dev->num_channels = st->iio_channels;1674 indio_dev->num_channels = st->iio_channels;
1677 indio_dev->channels = st->iio_chan;1675 indio_dev->channels = st->iio_chan;
1678 indio_dev->modes = INDIO_DIRECT_MODE;1676 indio_dev->modes = INDIO_DIRECT_MODE;
@@ -1703,15 +1701,25 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ltc2983_pm_ops, ltc2983_suspend, · 24 unmodified lines
1703 ltc2983_resume);1701 ltc2983_resume);
1704 1702
1705static const struct ltc2983_chip_info ltc2983_chip_info_data = {1703static const struct ltc2983_chip_info ltc2983_chip_info_data = {
1704 .name = "ltc2983",
1706 .max_channels_nr = 20,1705 .max_channels_nr = 20,
1707};1706};
1708 1707
1709static const struct ltc2983_chip_info ltc2984_chip_info_data = {1708static const struct ltc2983_chip_info ltc2984_chip_info_data = {
1709 .name = "ltc2984",
1710 .max_channels_nr = 20,1710 .max_channels_nr = 20,
1711 .has_eeprom = true,1711 .has_eeprom = true,
1712};1712};
1713 1713
1714static const struct ltc2983_chip_info ltc2986_chip_info_data = {1714static const struct ltc2983_chip_info ltc2986_chip_info_data = {
1715 .name = "ltc2986",
1716 .max_channels_nr = 10,
1717 .has_temp = true,
1718 .has_eeprom = true,
1719};
1720
1721static const struct ltc2983_chip_info ltm2985_chip_info_data = {
1722 .name = "ltm2985",
1715 .max_channels_nr = 10,1723 .max_channels_nr = 10,
1716 .has_temp = true,1724 .has_temp = true,
1717 .has_eeprom = true,1725 .has_eeprom = true,
@@ -1721,7 +1729,7 @@ static const struct spi_device_id ltc2983_id_table[] = { · 3 unmodified lines
1721 { "ltc2983", (kernel_ulong_t)&ltc2983_chip_info_data },1729 { "ltc2983", (kernel_ulong_t)&ltc2983_chip_info_data },
1722 { "ltc2984", (kernel_ulong_t)&ltc2984_chip_info_data },1730 { "ltc2984", (kernel_ulong_t)&ltc2984_chip_info_data },
1723 { "ltc2986", (kernel_ulong_t)&ltc2986_chip_info_data },1731 { "ltc2986", (kernel_ulong_t)&ltc2986_chip_info_data },
1724 { "ltm2985", (kernel_ulong_t)&ltc2986_chip_info_data },1732 { "ltm2985", (kernel_ulong_t)&ltm2985_chip_info_data },
1725 {},1733 {},
1726};1734};
1727MODULE_DEVICE_TABLE(spi, ltc2983_id_table);1735MODULE_DEVICE_TABLE(spi, ltc2983_id_table);
@@ -1730,7 +1738,7 @@ static const struct of_device_id ltc2983_of_match[] = { · 2 unmodified lines
1730 { .compatible = "adi,ltc2983", .data = &ltc2983_chip_info_data },1738 { .compatible = "adi,ltc2983", .data = &ltc2983_chip_info_data },
1731 { .compatible = "adi,ltc2984", .data = &ltc2984_chip_info_data },1739 { .compatible = "adi,ltc2984", .data = &ltc2984_chip_info_data },
1732 { .compatible = "adi,ltc2986", .data = &ltc2986_chip_info_data },1740 { .compatible = "adi,ltc2986", .data = &ltc2986_chip_info_data },
1733 { .compatible = "adi,ltm2985", .data = &ltc2986_chip_info_data },1741 { .compatible = "adi,ltm2985", .data = &ltm2985_chip_info_data },
1734 {},1742 {},
1735};1743};
1736MODULE_DEVICE_TABLE(of, ltc2983_of_match);1744MODULE_DEVICE_TABLE(of, ltc2983_of_match);
drivers/iio/temperature/tmp117.c+9−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
9 * Note: This driver assumes that the sensor has been calibrated beforehand.9 * Note: This driver assumes that the sensor has been calibrated beforehand.
10 */10 */
11 11
12#include <linux/delay.h>
12#include <linux/err.h>13#include <linux/err.h>
13#include <linux/i2c.h>14#include <linux/i2c.h>
14#include <linux/module.h>15#include <linux/module.h>
@@ -17,6 +18,7 @@ · 2 unmodified lines
17#include <linux/kernel.h>18#include <linux/kernel.h>
18#include <linux/limits.h>19#include <linux/limits.h>
19#include <linux/property.h>20#include <linux/property.h>
21#include <linux/regulator/consumer.h>
20 22
21#include <linux/iio/iio.h>23#include <linux/iio/iio.h>
22 24
@@ -148,10 +150,17 @@ static int tmp117_probe(struct i2c_client *client) · 125 unmodified lines
148 struct tmp117_data *data;150 struct tmp117_data *data;
149 struct iio_dev *indio_dev;151 struct iio_dev *indio_dev;
150 int dev_id;152 int dev_id;
153 int ret;
151 154
152 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))155 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
153 return -EOPNOTSUPP;156 return -EOPNOTSUPP;
154 157
158 ret = devm_regulator_get_enable(&client->dev, "vcc");
159 if (ret)
160 return ret;
161
162 fsleep(1500);
163
155 dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID);164 dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID);
156 if (dev_id < 0)165 if (dev_id < 0)
157 return dev_id;166 return dev_id;
drivers/iio/test/Kconfig+14−0
@@ -4,6 +4,20 @@ · 3 unmodified lines
4#4#
5 5
6# Keep in alphabetical order6# Keep in alphabetical order
7config IIO_GTS_KUNIT_TEST
8 tristate "Test IIO formatting functions" if !KUNIT_ALL_TESTS
9 depends on KUNIT
10 select IIO_GTS_HELPER
11 select TEST_KUNIT_DEVICE_HELPERS
12 default KUNIT_ALL_TESTS
13 help
14 build unit tests for the IIO light sensor gain-time-scale helpers.
15
16 For more information on KUnit and unit tests in general, please refer
17 to the KUnit documentation in Documentation/dev-tools/kunit/.
18
19 If unsure, say N. Keep in alphabetical order
20
7config IIO_RESCALE_KUNIT_TEST21config IIO_RESCALE_KUNIT_TEST
8 tristate "Test IIO rescale conversion functions" if !KUNIT_ALL_TESTS22 tristate "Test IIO rescale conversion functions" if !KUNIT_ALL_TESTS
9 depends on KUNIT && IIO_RESCALE23 depends on KUNIT && IIO_RESCALE
drivers/iio/test/Makefile+1−0
@@ -6,4 +6,5 @@ · 5 unmodified lines
6# Keep in alphabetical order6# Keep in alphabetical order
7obj-$(CONFIG_IIO_RESCALE_KUNIT_TEST) += iio-test-rescale.o7obj-$(CONFIG_IIO_RESCALE_KUNIT_TEST) += iio-test-rescale.o
8obj-$(CONFIG_IIO_FORMAT_KUNIT_TEST) += iio-test-format.o8obj-$(CONFIG_IIO_FORMAT_KUNIT_TEST) += iio-test-format.o
9obj-$(CONFIG_IIO_GTS_KUNIT_TEST) += iio-test-gts.o
9CFLAGS_iio-test-format.o += $(DISABLE_STRUCTLEAK_PLUGIN)10CFLAGS_iio-test-format.o += $(DISABLE_STRUCTLEAK_PLUGIN)
drivers/iio/test/iio-test-gts.c+513−0
@@ -0,0 +1,513 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/* Unit tests for IIO light sensor gain-time-scale helpers
3 *
4 * Copyright (c) 2023 Matti Vaittinen <mazziesaccount@gmail.com>
5 */
6
7#include <kunit/device.h>
8#include <kunit/test.h>
9#include <linux/device.h>
10#include <linux/iio/iio-gts-helper.h>
11#include <linux/iio/types.h>
12
13/*
14 * Please, read the "rant" from the top of the lib/test_linear_ranges.c if
15 * you see a line of helper code which is not being tested.
16 *
17 * Then, please look at the line which is not being tested. Is this line
18 * somehow unusually complex? If answer is "no", then chances are that the
19 * "development inertia" caused by adding a test exceeds the benefits.
20 *
21 * If yes, then adding a test is probably a good idea but please stop for a
22 * moment and consider the effort of changing all the tests when code gets
23 * refactored. Eventually it neeeds to be.
24 */
25
26#define TEST_TSEL_50 1
27#define TEST_TSEL_X_MIN TEST_TSEL_50
28#define TEST_TSEL_100 0
29#define TEST_TSEL_200 2
30#define TEST_TSEL_400 4
31#define TEST_TSEL_X_MAX TEST_TSEL_400
32
33#define TEST_GSEL_1 0x00
34#define TEST_GSEL_X_MIN TEST_GSEL_1
35#define TEST_GSEL_4 0x08
36#define TEST_GSEL_16 0x0a
37#define TEST_GSEL_32 0x0b
38#define TEST_GSEL_64 0x0c
39#define TEST_GSEL_256 0x18
40#define TEST_GSEL_512 0x19
41#define TEST_GSEL_1024 0x1a
42#define TEST_GSEL_2048 0x1b
43#define TEST_GSEL_4096 0x1c
44#define TEST_GSEL_X_MAX TEST_GSEL_4096
45
46#define TEST_SCALE_1X 64
47#define TEST_SCALE_MIN_X TEST_SCALE_1X
48#define TEST_SCALE_2X 32
49#define TEST_SCALE_4X 16
50#define TEST_SCALE_8X 8
51#define TEST_SCALE_16X 4
52#define TEST_SCALE_32X 2
53#define TEST_SCALE_64X 1
54
55#define TEST_SCALE_NANO_128X 500000000
56#define TEST_SCALE_NANO_256X 250000000
57#define TEST_SCALE_NANO_512X 125000000
58#define TEST_SCALE_NANO_1024X 62500000
59#define TEST_SCALE_NANO_2048X 31250000
60#define TEST_SCALE_NANO_4096X 15625000
61#define TEST_SCALE_NANO_4096X2 7812500
62#define TEST_SCALE_NANO_4096X4 3906250
63#define TEST_SCALE_NANO_4096X8 1953125
64
65#define TEST_SCALE_NANO_MAX_X TEST_SCALE_NANO_4096X8
66
67/*
68 * Can't have this allocated from stack because the kunit clean-up will
69 * happen only after the test function has already gone
70 */
71static struct iio_gts gts;
72
73static const struct iio_gain_sel_pair gts_test_gains[] = {
74 GAIN_SCALE_GAIN(1, TEST_GSEL_1),
75 GAIN_SCALE_GAIN(4, TEST_GSEL_4),
76 GAIN_SCALE_GAIN(16, TEST_GSEL_16),
77 GAIN_SCALE_GAIN(32, TEST_GSEL_32),
78 GAIN_SCALE_GAIN(64, TEST_GSEL_64),
79 GAIN_SCALE_GAIN(256, TEST_GSEL_256),
80 GAIN_SCALE_GAIN(512, TEST_GSEL_512),
81 GAIN_SCALE_GAIN(1024, TEST_GSEL_1024),
82 GAIN_SCALE_GAIN(2048, TEST_GSEL_2048),
83 GAIN_SCALE_GAIN(4096, TEST_GSEL_4096),
84#define HWGAIN_MAX 4096
85};
86
87static const struct iio_itime_sel_mul gts_test_itimes[] = {
88 GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 8),
89 GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),
90 GAIN_SCALE_ITIME_US(100 * 1000, TEST_TSEL_100, 2),
91 GAIN_SCALE_ITIME_US(50 * 1000, TEST_TSEL_50, 1),
92#define TIMEGAIN_MAX 8
93};
94#define TOTAL_GAIN_MAX (HWGAIN_MAX * TIMEGAIN_MAX)
95#define IIO_GTS_TEST_DEV "iio-gts-test-dev"
96
97static struct device *__test_init_iio_gain_scale(struct kunit *test,
98 struct iio_gts *gts, const struct iio_gain_sel_pair *g_table,
99 int num_g, const struct iio_itime_sel_mul *i_table, int num_i)
100{
101 struct device *dev;
102 int ret;
103
104 dev = kunit_device_register(test, IIO_GTS_TEST_DEV);
105
106 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
107 if (IS_ERR_OR_NULL(dev))
108 return NULL;
109
110 ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, g_table, num_g,
111 i_table, num_i, gts);
112 KUNIT_EXPECT_EQ(test, 0, ret);
113 if (ret)
114 return NULL;
115
116 return dev;
117}
118
119#define test_init_iio_gain_scale(test, gts) \
120 __test_init_iio_gain_scale(test, gts, gts_test_gains, \
121 ARRAY_SIZE(gts_test_gains), gts_test_itimes, \
122 ARRAY_SIZE(gts_test_itimes))
123
124static void test_init_iio_gts_invalid(struct kunit *test)
125{
126 struct device *dev;
127 int ret;
128 const struct iio_itime_sel_mul itimes_neg[] = {
129 GAIN_SCALE_ITIME_US(-10, TEST_TSEL_400, 8),
130 GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),
131 };
132 const struct iio_gain_sel_pair gains_neg[] = {
133 GAIN_SCALE_GAIN(1, TEST_GSEL_1),
134 GAIN_SCALE_GAIN(2, TEST_GSEL_4),
135 GAIN_SCALE_GAIN(-2, TEST_GSEL_16),
136 };
137 /* 55555 * 38656 = 2147534080 => overflows 32bit int */
138 const struct iio_itime_sel_mul itimes_overflow[] = {
139 GAIN_SCALE_ITIME_US(400 * 1000, TEST_TSEL_400, 55555),
140 GAIN_SCALE_ITIME_US(200 * 1000, TEST_TSEL_200, 4),
141 };
142 const struct iio_gain_sel_pair gains_overflow[] = {
143 GAIN_SCALE_GAIN(1, TEST_GSEL_1),
144 GAIN_SCALE_GAIN(2, TEST_GSEL_4),
145 GAIN_SCALE_GAIN(38656, TEST_GSEL_16),
146 };
147
148 dev = kunit_device_register(test, IIO_GTS_TEST_DEV);
149 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev);
150 if (!dev)
151 return;
152
153 /* Ok gains, negative time */
154 ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gts_test_gains,
155 ARRAY_SIZE(gts_test_gains), itimes_neg,
156 ARRAY_SIZE(itimes_neg), &gts);
157 KUNIT_EXPECT_EQ(test, -EINVAL, ret);
158
159 /* Ok times, negative gain */
160 ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gains_neg,
161 ARRAY_SIZE(gains_neg), gts_test_itimes,
162 ARRAY_SIZE(gts_test_itimes), &gts);
163 KUNIT_EXPECT_EQ(test, -EINVAL, ret);
164
165 /* gain * time overflow int */
166 ret = devm_iio_init_iio_gts(dev, TEST_SCALE_1X, 0, gains_overflow,
167 ARRAY_SIZE(gains_overflow), itimes_overflow,
168 ARRAY_SIZE(itimes_overflow), &gts);
169 KUNIT_EXPECT_EQ(test, -EOVERFLOW, ret);
170}
171
172static void test_iio_gts_find_gain_for_scale_using_time(struct kunit *test)
173{
174 struct device *dev;
175 int ret, gain_sel;
176
177 dev = test_init_iio_gain_scale(test, &gts);
178 if (!dev)
179 return;
180
181 ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_100,
182 TEST_SCALE_8X, 0, &gain_sel);
183 /*
184 * Meas time 100 => gain by time 2x
185 * TEST_SCALE_8X matches total gain 8x
186 * => required HWGAIN 4x
187 */
188 KUNIT_EXPECT_EQ(test, 0, ret);
189 KUNIT_EXPECT_EQ(test, TEST_GSEL_4, gain_sel);
190
191 ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_200, 0,
192 TEST_SCALE_NANO_256X, &gain_sel);
193 /*
194 * Meas time 200 => gain by time 4x
195 * TEST_SCALE_256X matches total gain 256x
196 * => required HWGAIN 256/4 => 64x
197 */
198 KUNIT_EXPECT_EQ(test, 0, ret);
199 KUNIT_EXPECT_EQ(test, TEST_GSEL_64, gain_sel);
200
201 /* Min time, Min gain */
202 ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_X_MIN,
203 TEST_SCALE_MIN_X, 0, &gain_sel);
204 KUNIT_EXPECT_EQ(test, 0, ret);
205 KUNIT_EXPECT_EQ(test, TEST_GSEL_1, gain_sel);
206
207 /* Max time, Max gain */
208 ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_X_MAX,
209 0, TEST_SCALE_NANO_MAX_X, &gain_sel);
210 KUNIT_EXPECT_EQ(test, 0, ret);
211 KUNIT_EXPECT_EQ(test, TEST_GSEL_4096, gain_sel);
212
213 ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_100, 0,
214 TEST_SCALE_NANO_256X, &gain_sel);
215 /*
216 * Meas time 100 => gain by time 2x
217 * TEST_SCALE_256X matches total gain 256x
218 * => required HWGAIN 256/2 => 128x (not in gain-table - unsupported)
219 */
220 KUNIT_EXPECT_NE(test, 0, ret);
221
222 ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_200, 0,
223 TEST_SCALE_NANO_MAX_X, &gain_sel);
224 /* We can't reach the max gain with integration time smaller than MAX */
225 KUNIT_EXPECT_NE(test, 0, ret);
226
227 ret = iio_gts_find_gain_sel_for_scale_using_time(&gts, TEST_TSEL_50, 0,
228 TEST_SCALE_NANO_MAX_X, &gain_sel);
229 /* We can't reach the max gain with integration time smaller than MAX */
230 KUNIT_EXPECT_NE(test, 0, ret);
231}
232
233static void test_iio_gts_find_new_gain_sel_by_old_gain_time(struct kunit *test)
234{
235 struct device *dev;
236 int ret, old_gain, new_gain, old_time_sel, new_time_sel;
237
238 dev = test_init_iio_gain_scale(test, &gts);
239 if (!dev)
240 return;
241
242 old_gain = 32;
243 old_time_sel = TEST_TSEL_200;
244 new_time_sel = TEST_TSEL_400;
245
246 ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
247 old_time_sel, new_time_sel, &new_gain);
248 KUNIT_EXPECT_EQ(test, 0, ret);
249 /*
250 * Doubling the integration time doubles the total gain - so old
251 * (hw)gain must be divided by two to compensate. => 32 / 2 => 16
252 */
253 KUNIT_EXPECT_EQ(test, 16, new_gain);
254
255 old_gain = 4;
256 old_time_sel = TEST_TSEL_50;
257 new_time_sel = TEST_TSEL_200;
258 ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
259 old_time_sel, new_time_sel, &new_gain);
260 KUNIT_EXPECT_EQ(test, 0, ret);
261 /*
262 * gain by time 1x => 4x - (hw)gain 4x => 1x
263 */
264 KUNIT_EXPECT_EQ(test, 1, new_gain);
265
266 old_gain = 512;
267 old_time_sel = TEST_TSEL_400;
268 new_time_sel = TEST_TSEL_50;
269 ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
270 old_time_sel, new_time_sel, &new_gain);
271 KUNIT_EXPECT_EQ(test, 0, ret);
272 /*
273 * gain by time 8x => 1x - (hw)gain 512x => 4096x)
274 */
275 KUNIT_EXPECT_EQ(test, 4096, new_gain);
276
277 /* Unsupported gain 2x */
278 old_gain = 4;
279 old_time_sel = TEST_TSEL_200;
280 new_time_sel = TEST_TSEL_400;
281 ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
282 old_time_sel, new_time_sel, &new_gain);
283 KUNIT_EXPECT_NE(test, 0, ret);
284
285 /* Too small gain */
286 old_gain = 4;
287 old_time_sel = TEST_TSEL_50;
288 new_time_sel = TEST_TSEL_400;
289 ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
290 old_time_sel, new_time_sel, &new_gain);
291 KUNIT_EXPECT_NE(test, 0, ret);
292
293 /* Too big gain */
294 old_gain = 1024;
295 old_time_sel = TEST_TSEL_400;
296 new_time_sel = TEST_TSEL_50;
297 ret = iio_gts_find_new_gain_sel_by_old_gain_time(&gts, old_gain,
298 old_time_sel, new_time_sel, &new_gain);
299 KUNIT_EXPECT_NE(test, 0, ret);
300
301}
302
303static void test_iio_find_closest_gain_low(struct kunit *test)
304{
305 struct device *dev;
306 bool in_range;
307 int ret;
308
309 const struct iio_gain_sel_pair gts_test_gains_gain_low[] = {
310 GAIN_SCALE_GAIN(4, TEST_GSEL_4),
311 GAIN_SCALE_GAIN(16, TEST_GSEL_16),
312 GAIN_SCALE_GAIN(32, TEST_GSEL_32),
313 };
314
315 dev = test_init_iio_gain_scale(test, &gts);
316 if (!dev)
317 return;
318
319 ret = iio_find_closest_gain_low(&gts, 2, &in_range);
320 KUNIT_EXPECT_EQ(test, 1, ret);
321 KUNIT_EXPECT_EQ(test, true, in_range);
322
323 ret = iio_find_closest_gain_low(&gts, 1, &in_range);
324 KUNIT_EXPECT_EQ(test, 1, ret);
325 KUNIT_EXPECT_EQ(test, true, in_range);
326
327 ret = iio_find_closest_gain_low(&gts, 4095, &in_range);
328 KUNIT_EXPECT_EQ(test, 2048, ret);
329 KUNIT_EXPECT_EQ(test, true, in_range);
330
331 ret = iio_find_closest_gain_low(&gts, 4097, &in_range);
332 KUNIT_EXPECT_EQ(test, 4096, ret);
333 KUNIT_EXPECT_EQ(test, false, in_range);
334
335 kunit_device_unregister(test, dev);
336
337 dev = __test_init_iio_gain_scale(test, &gts, gts_test_gains_gain_low,
338 ARRAY_SIZE(gts_test_gains_gain_low),
339 gts_test_itimes, ARRAY_SIZE(gts_test_itimes));
340 if (!dev)
341 return;
342
343 ret = iio_find_closest_gain_low(&gts, 3, &in_range);
344 KUNIT_EXPECT_EQ(test, -EINVAL, ret);
345 KUNIT_EXPECT_EQ(test, false, in_range);
346}
347
348static void test_iio_gts_total_gain_to_scale(struct kunit *test)
349{
350 struct device *dev;
351 int ret, scale_int, scale_nano;
352
353 dev = test_init_iio_gain_scale(test, &gts);
354 if (!dev)
355 return;
356
357 ret = iio_gts_total_gain_to_scale(&gts, 1, &scale_int, &scale_nano);
358 KUNIT_EXPECT_EQ(test, 0, ret);
359 KUNIT_EXPECT_EQ(test, TEST_SCALE_1X, scale_int);
360 KUNIT_EXPECT_EQ(test, 0, scale_nano);
361
362 ret = iio_gts_total_gain_to_scale(&gts, 1, &scale_int, &scale_nano);
363 KUNIT_EXPECT_EQ(test, 0, ret);
364 KUNIT_EXPECT_EQ(test, TEST_SCALE_1X, scale_int);
365 KUNIT_EXPECT_EQ(test, 0, scale_nano);
366
367 ret = iio_gts_total_gain_to_scale(&gts, 4096 * 8, &scale_int,
368 &scale_nano);
369 KUNIT_EXPECT_EQ(test, 0, ret);
370 KUNIT_EXPECT_EQ(test, 0, scale_int);
371 KUNIT_EXPECT_EQ(test, TEST_SCALE_NANO_4096X8, scale_nano);
372}
373
374static void test_iio_gts_chk_times(struct kunit *test, const int *vals)
375{
376 static const int expected[] = {0, 50000, 0, 100000, 0, 200000, 0, 400000};
377 int i;
378
379 for (i = 0; i < ARRAY_SIZE(expected); i++)
380 KUNIT_EXPECT_EQ(test, expected[i], vals[i]);
381}
382
383static void test_iio_gts_chk_scales_all(struct kunit *test, struct iio_gts *gts,
384 const int *vals, int len)
385{
386 static const int gains[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
387 1024, 2048, 4096, 4096 * 2, 4096 * 4,
388 4096 * 8};
389 int expected[ARRAY_SIZE(gains) * 2];
390 int i, ret;
391 int exp_len = ARRAY_SIZE(gains) * 2;
392
393 KUNIT_EXPECT_EQ(test, exp_len, len);
394 if (len != exp_len)
395 return;
396
397 for (i = 0; i < ARRAY_SIZE(gains); i++) {
398 ret = iio_gts_total_gain_to_scale(gts, gains[i],
399 &expected[2 * i],
400 &expected[2 * i + 1]);
401 KUNIT_EXPECT_EQ(test, 0, ret);
402 if (ret)
403 return;
404 }
405
406 for (i = 0; i < ARRAY_SIZE(expected); i++)
407 KUNIT_EXPECT_EQ(test, expected[i], vals[i]);
408}
409
410static void test_iio_gts_chk_scales_t200(struct kunit *test, struct iio_gts *gts,
411 const int *vals, int len)
412{
413 /* The gain caused by time 200 is 4x */
414 static const int gains[] = {
415 1 * 4,
416 4 * 4,
417 16 * 4,
418 32 * 4,
419 64 * 4,
420 256 * 4,
421 512 * 4,
422 1024 * 4,
423 2048 * 4,
424 4096 * 4
425 };
426 int expected[ARRAY_SIZE(gains) * 2];
427 int i, ret;
428
429 KUNIT_EXPECT_EQ(test, 2 * ARRAY_SIZE(gains), len);
430 if (len < 2 * ARRAY_SIZE(gains))
431 return;
432
433 for (i = 0; i < ARRAY_SIZE(gains); i++) {
434 ret = iio_gts_total_gain_to_scale(gts, gains[i],
435 &expected[2 * i],
436 &expected[2 * i + 1]);
437 KUNIT_EXPECT_EQ(test, 0, ret);
438 if (ret)
439 return;
440 }
441
442 for (i = 0; i < ARRAY_SIZE(expected); i++)
443 KUNIT_EXPECT_EQ(test, expected[i], vals[i]);
444}
445
446static void test_iio_gts_avail_test(struct kunit *test)
447{
448 struct device *dev;
449 int ret;
450 int type, len;
451 const int *vals;
452
453 dev = test_init_iio_gain_scale(test, &gts);
454 if (!dev)
455 return;
456
457 /* test table building for times and iio_gts_avail_times() */
458 ret = iio_gts_avail_times(&gts, &vals, &type, &len);
459 KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);
460 if (ret)
461 return;
462
463 KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_MICRO, type);
464 KUNIT_EXPECT_EQ(test, 8, len);
465 if (len < 8)
466 return;
467
468 test_iio_gts_chk_times(test, vals);
469
470 /* Test table building for all scales and iio_gts_all_avail_scales() */
471 ret = iio_gts_all_avail_scales(&gts, &vals, &type, &len);
472 KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);
473 if (ret)
474 return;
475
476 KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_NANO, type);
477
478 test_iio_gts_chk_scales_all(test, &gts, vals, len);
479
480 /*
481 * Test table building for scales/time and
482 * iio_gts_avail_scales_for_time()
483 */
484 ret = iio_gts_avail_scales_for_time(&gts, 200000, &vals, &type, &len);
485 KUNIT_EXPECT_EQ(test, IIO_AVAIL_LIST, ret);
486 if (ret)
487 return;
488
489 KUNIT_EXPECT_EQ(test, IIO_VAL_INT_PLUS_NANO, type);
490 test_iio_gts_chk_scales_t200(test, &gts, vals, len);
491}
492
493static struct kunit_case iio_gts_test_cases[] = {
494 KUNIT_CASE(test_init_iio_gts_invalid),
495 KUNIT_CASE(test_iio_gts_find_gain_for_scale_using_time),
496 KUNIT_CASE(test_iio_gts_find_new_gain_sel_by_old_gain_time),
497 KUNIT_CASE(test_iio_find_closest_gain_low),
498 KUNIT_CASE(test_iio_gts_total_gain_to_scale),
499 KUNIT_CASE(test_iio_gts_avail_test),
500 {}
501};
502
503static struct kunit_suite iio_gts_test_suite = {
504 .name = "iio-gain-time-scale",
505 .test_cases = iio_gts_test_cases,
506};
507
508kunit_test_suite(iio_gts_test_suite);
509
510MODULE_LICENSE("GPL");
511MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
512MODULE_DESCRIPTION("Test IIO light sensor gain-time-scale helpers");
513MODULE_IMPORT_NS(IIO_GTS_HELPER);
drivers/interconnect/core.c+2−2
@@ -343,7 +343,7 @@ EXPORT_SYMBOL_GPL(icc_std_aggregate); · 342 unmodified lines
343 * an array of icc nodes specified in the icc_onecell_data struct when343 * an array of icc nodes specified in the icc_onecell_data struct when
344 * registering the provider.344 * registering the provider.
345 */345 */
346struct icc_node *of_icc_xlate_onecell(struct of_phandle_args *spec,346struct icc_node *of_icc_xlate_onecell(const struct of_phandle_args *spec,
347 void *data)347 void *data)
348{348{
349 struct icc_onecell_data *icc_data = data;349 struct icc_onecell_data *icc_data = data;
@@ -368,7 +368,7 @@ EXPORT_SYMBOL_GPL(of_icc_xlate_onecell); · 18 unmodified lines
368 * Returns a valid pointer to struct icc_node_data on success or ERR_PTR()368 * Returns a valid pointer to struct icc_node_data on success or ERR_PTR()
369 * on failure.369 * on failure.
370 */370 */
371struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec)371struct icc_node_data *of_icc_get_from_provider(const struct of_phandle_args *spec)
372{372{
373 struct icc_node *node = ERR_PTR(-EPROBE_DEFER);373 struct icc_node *node = ERR_PTR(-EPROBE_DEFER);
374 struct icc_node_data *data = NULL;374 struct icc_node_data *data = NULL;
drivers/interconnect/qcom/Kconfig+18−0
@@ -8,6 +8,15 @@ config INTERCONNECT_QCOM · 7 unmodified lines
8config INTERCONNECT_QCOM_BCM_VOTER8config INTERCONNECT_QCOM_BCM_VOTER
9 tristate9 tristate
10 10
11config INTERCONNECT_QCOM_MSM8909
12 tristate "Qualcomm MSM8909 interconnect driver"
13 depends on INTERCONNECT_QCOM
14 depends on QCOM_SMD_RPM
15 select INTERCONNECT_QCOM_SMD_RPM
16 help
17 This is a driver for the Qualcomm Network-on-Chip on msm8909-based
18 platforms.
19
11config INTERCONNECT_QCOM_MSM891620config INTERCONNECT_QCOM_MSM8916
12 tristate "Qualcomm MSM8916 interconnect driver"21 tristate "Qualcomm MSM8916 interconnect driver"
13 depends on INTERCONNECT_QCOM22 depends on INTERCONNECT_QCOM
@@ -209,6 +218,15 @@ config INTERCONNECT_QCOM_SM6350 · 195 unmodified lines
209 This is a driver for the Qualcomm Network-on-Chip on sm6350-based218 This is a driver for the Qualcomm Network-on-Chip on sm6350-based
210 platforms.219 platforms.
211 220
221config INTERCONNECT_QCOM_SM7150
222 tristate "Qualcomm SM7150 interconnect driver"
223 depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
224 select INTERCONNECT_QCOM_RPMH
225 select INTERCONNECT_QCOM_BCM_VOTER
226 help
227 This is a driver for the Qualcomm Network-on-Chip on sm7150-based
228 platforms.
229
212config INTERCONNECT_QCOM_SM8150230config INTERCONNECT_QCOM_SM8150
213 tristate "Qualcomm SM8150 interconnect driver"231 tristate "Qualcomm SM8150 interconnect driver"
214 depends on INTERCONNECT_QCOM_RPMH_POSSIBLE232 depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
drivers/interconnect/qcom/Makefile+4−0
@@ -4,6 +4,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM) += interconnect_qcom.o · 3 unmodified lines
4 4
5interconnect_qcom-y := icc-common.o5interconnect_qcom-y := icc-common.o
6icc-bcm-voter-objs := bcm-voter.o6icc-bcm-voter-objs := bcm-voter.o
7qnoc-msm8909-objs := msm8909.o
7qnoc-msm8916-objs := msm8916.o8qnoc-msm8916-objs := msm8916.o
8qnoc-msm8939-objs := msm8939.o9qnoc-msm8939-objs := msm8939.o
9qnoc-msm8974-objs := msm8974.o10qnoc-msm8974-objs := msm8974.o
@@ -26,6 +27,7 @@ qnoc-sdx65-objs := sdx65.o · 16 unmodified lines
26qnoc-sdx75-objs := sdx75.o27qnoc-sdx75-objs := sdx75.o
27qnoc-sm6115-objs := sm6115.o28qnoc-sm6115-objs := sm6115.o
28qnoc-sm6350-objs := sm6350.o29qnoc-sm6350-objs := sm6350.o
30qnoc-sm7150-objs := sm7150.o
29qnoc-sm8150-objs := sm8150.o31qnoc-sm8150-objs := sm8150.o
30qnoc-sm8250-objs := sm8250.o32qnoc-sm8250-objs := sm8250.o
31qnoc-sm8350-objs := sm8350.o33qnoc-sm8350-objs := sm8350.o
@@ -36,6 +38,7 @@ qnoc-x1e80100-objs := x1e80100.o · 4 unmodified lines
36icc-smd-rpm-objs := smd-rpm.o icc-rpm.o icc-rpm-clocks.o38icc-smd-rpm-objs := smd-rpm.o icc-rpm.o icc-rpm-clocks.o
37 39
38obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o40obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o
41obj-$(CONFIG_INTERCONNECT_QCOM_MSM8909) += qnoc-msm8909.o
39obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o42obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
40obj-$(CONFIG_INTERCONNECT_QCOM_MSM8939) += qnoc-msm8939.o43obj-$(CONFIG_INTERCONNECT_QCOM_MSM8939) += qnoc-msm8939.o
41obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o44obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o
@@ -58,6 +61,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_SDX65) += qnoc-sdx65.o · 16 unmodified lines
58obj-$(CONFIG_INTERCONNECT_QCOM_SDX75) += qnoc-sdx75.o61obj-$(CONFIG_INTERCONNECT_QCOM_SDX75) += qnoc-sdx75.o
59obj-$(CONFIG_INTERCONNECT_QCOM_SM6115) += qnoc-sm6115.o62obj-$(CONFIG_INTERCONNECT_QCOM_SM6115) += qnoc-sm6115.o
60obj-$(CONFIG_INTERCONNECT_QCOM_SM6350) += qnoc-sm6350.o63obj-$(CONFIG_INTERCONNECT_QCOM_SM6350) += qnoc-sm6350.o
64obj-$(CONFIG_INTERCONNECT_QCOM_SM7150) += qnoc-sm7150.o
61obj-$(CONFIG_INTERCONNECT_QCOM_SM8150) += qnoc-sm8150.o65obj-$(CONFIG_INTERCONNECT_QCOM_SM8150) += qnoc-sm8150.o
62obj-$(CONFIG_INTERCONNECT_QCOM_SM8250) += qnoc-sm8250.o66obj-$(CONFIG_INTERCONNECT_QCOM_SM8250) += qnoc-sm8250.o
63obj-$(CONFIG_INTERCONNECT_QCOM_SM8350) += qnoc-sm8350.o67obj-$(CONFIG_INTERCONNECT_QCOM_SM8350) += qnoc-sm8350.o
drivers/interconnect/qcom/icc-common.c+2−1
@@ -9,7 +9,8 @@ · 8 unmodified lines
9 9
10#include "icc-common.h"10#include "icc-common.h"
11 11
12struct icc_node_data *qcom_icc_xlate_extended(struct of_phandle_args *spec, void *data)12struct icc_node_data *qcom_icc_xlate_extended(const struct of_phandle_args *spec,
13 void *data)
13{14{
14 struct icc_node_data *ndata;15 struct icc_node_data *ndata;
15 struct icc_node *node;16 struct icc_node *node;
drivers/interconnect/qcom/icc-common.h+2−1
@@ -8,6 +8,7 @@ · 7 unmodified lines
8 8
9#include <linux/interconnect-provider.h>9#include <linux/interconnect-provider.h>
10 10
11struct icc_node_data *qcom_icc_xlate_extended(struct of_phandle_args *spec, void *data);11struct icc_node_data *qcom_icc_xlate_extended(const struct of_phandle_args *spec,
12 void *data);
12 13
13#endif14#endif
drivers/interconnect/qcom/msm8909.c+1329−0
@@ -0,0 +1,1329 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Based on data from msm8909-bus.dtsi in Qualcomm's msm-3.18 release:
4 * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
5 */
6
7#include <linux/device.h>
8#include <linux/interconnect-provider.h>
9#include <linux/mod_devicetable.h>
10#include <linux/module.h>
11#include <linux/platform_device.h>
12#include <linux/regmap.h>
13
14#include <dt-bindings/interconnect/qcom,msm8909.h>
15
16#include "icc-rpm.h"
17
18enum {
19 QNOC_MASTER_AMPSS_M0 = 1,
20 QNOC_MASTER_GRAPHICS_3D,
21 QNOC_SNOC_BIMC_0_MAS,
22 QNOC_SNOC_BIMC_1_MAS,
23 QNOC_MASTER_TCU_0,
24 QNOC_MASTER_TCU_1,
25 QNOC_MASTER_AUDIO,
26 QNOC_MASTER_SPDM,
27 QNOC_MASTER_DEHR,
28 QNOC_MASTER_QPIC,
29 QNOC_MASTER_BLSP_1,
30 QNOC_MASTER_USB_HS,
31 QNOC_MASTER_CRYPTO_CORE0,
32 QNOC_MASTER_SDCC_1,
33 QNOC_MASTER_SDCC_2,
34 QNOC_SNOC_PNOC_MAS,
35 QNOC_MASTER_QDSS_BAM,
36 QNOC_BIMC_SNOC_MAS,
37 QNOC_MASTER_MDP_PORT0,
38 QNOC_PNOC_SNOC_MAS,
39 QNOC_MASTER_VIDEO_P0,
40 QNOC_MASTER_VFE,
41 QNOC_MASTER_QDSS_ETR,
42 QNOC_PNOC_M_0,
43 QNOC_PNOC_M_1,
44 QNOC_PNOC_INT_0,
45 QNOC_PNOC_INT_1,
46 QNOC_PNOC_SLV_0,
47 QNOC_PNOC_SLV_1,
48 QNOC_PNOC_SLV_2,
49 QNOC_PNOC_SLV_3,
50 QNOC_PNOC_SLV_4,
51 QNOC_PNOC_SLV_5,
52 QNOC_PNOC_SLV_7,
53 QNOC_SNOC_MM_INT_0,
54 QNOC_SNOC_MM_INT_1,
55 QNOC_SNOC_MM_INT_2,
56 QNOC_SNOC_MM_INT_BIMC,
57 QNOC_SNOC_QDSS_INT,
58 QNOC_SNOC_INT_0,
59 QNOC_SNOC_INT_1,
60 QNOC_SNOC_INT_BIMC,
61 QNOC_SLAVE_EBI_CH0,
62 QNOC_BIMC_SNOC_SLV,
63 QNOC_SLAVE_TCSR,
64 QNOC_SLAVE_SDCC_1,
65 QNOC_SLAVE_BLSP_1,
66 QNOC_SLAVE_CRYPTO_0_CFG,
67 QNOC_SLAVE_MESSAGE_RAM,
68 QNOC_SLAVE_PDM,
69 QNOC_SLAVE_PRNG,
70 QNOC_SLAVE_USB_HS,
71 QNOC_SLAVE_QPIC,
72 QNOC_SLAVE_SPDM,
73 QNOC_SLAVE_SDCC_2,
74 QNOC_SLAVE_AUDIO,
75 QNOC_SLAVE_DEHR_CFG,
76 QNOC_SLAVE_SNOC_CFG,
77 QNOC_SLAVE_QDSS_CFG,
78 QNOC_SLAVE_USB_PHYS_CFG,
79 QNOC_SLAVE_CAMERA_CFG,

1250 more lines aren’t shown here.

drivers/interconnect/qcom/sa8775p.c+28−28

This diff is large: its 212 lines aren’t shown here.

drivers/interconnect/qcom/sm6115.c+6−6

This diff is large: its 54 lines aren’t shown here.

drivers/interconnect/qcom/sm7150.c+1754−0

This diff is large: its 1755 lines aren’t shown here.

drivers/interconnect/qcom/sm7150.h+140−0

This diff is large: its 141 lines aren’t shown here.

drivers/interconnect/qcom/sm8250.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/interconnect/qcom/sm8550.c+0−574

This diff is large: its 635 lines aren’t shown here.

drivers/interconnect/qcom/sm8550.h+122−162

This diff is large: its 290 lines aren’t shown here.

drivers/interconnect/qcom/x1e80100.c+6−321

This diff is large: its 450 lines aren’t shown here.

drivers/interconnect/samsung/exynos.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/ipack/ipack.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/mcb/mcb-core.c+2−2

This diff is large: its 18 lines aren’t shown here.

drivers/memory/tegra/mc.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/memory/tegra/tegra124-emc.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/memory/tegra/tegra124.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/memory/tegra/tegra186-emc.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/memory/tegra/tegra20-emc.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/memory/tegra/tegra20.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/memory/tegra/tegra30-emc.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/memory/tegra/tegra30.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/misc/atmel-ssc.c+2−4

This diff is large: its 27 lines aren’t shown here.

drivers/misc/cxl/of.c+2−3

This diff is large: its 25 lines aren’t shown here.

drivers/misc/eeprom/eeprom_93xx46.c+0−1

This diff is large: its 8 lines aren’t shown here.

drivers/misc/eeprom/idt_89hpesx.c+3−3

This diff is large: its 20 lines aren’t shown here.

drivers/misc/fastrpc.c+2−4

This diff is large: its 27 lines aren’t shown here.

drivers/misc/hi6421v600-irq.c+0−1

This diff is large: its 8 lines aren’t shown here.

drivers/misc/hisi_hikey_usb.c+2−5

This diff is large: its 35 lines aren’t shown here.

drivers/misc/hpilo.c+4−4

This diff is large: its 24 lines aren’t shown here.

drivers/misc/mei/gsc-me.c+5−17

This diff is large: its 77 lines aren’t shown here.

drivers/misc/mei/hdcp/Kconfig+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/misc/mei/hdcp/mei_hdcp.c+12−2

This diff is large: its 29 lines aren’t shown here.

drivers/misc/mei/pci-me.c+6−32

This diff is large: its 101 lines aren’t shown here.

drivers/misc/mei/pci-txe.c+6−34

This diff is large: its 102 lines aren’t shown here.

drivers/misc/mei/platform-vsc.c+2−4

This diff is large: its 27 lines aren’t shown here.

drivers/misc/mei/pxp/Kconfig+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/misc/mei/pxp/mei_pxp.c+12−2

This diff is large: its 32 lines aren’t shown here.

drivers/misc/mei/vsc-tp.c+18−15

This diff is large: its 82 lines aren’t shown here.

drivers/misc/open-dice.c+2−3

This diff is large: its 23 lines aren’t shown here.

drivers/misc/sram.c+2−4

This diff is large: its 27 lines aren’t shown here.

drivers/misc/ti-st/st_kim.c+2−3

This diff is large: its 26 lines aren’t shown here.

drivers/misc/tifm_core.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/misc/vcpu_stall_detector.c+2−4

This diff is large: its 27 lines aren’t shown here.

drivers/misc/xilinx_sdfec.c+2−3

This diff is large: its 26 lines aren’t shown here.

drivers/misc/xilinx_tmr_inject.c+2−3

This diff is large: its 22 lines aren’t shown here.

drivers/most/core.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/net/ethernet/broadcom/bnx2.c+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c+2−0

This diff is large: its 12 lines aren’t shown here.

drivers/net/ethernet/broadcom/cnic.c+17−8

This diff is large: its 63 lines aren’t shown here.

drivers/net/ethernet/broadcom/cnic.h+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/net/ethernet/broadcom/cnic_if.h+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/nvmem/core.c+5−0

This diff is large: its 12 lines aren’t shown here.

drivers/nvmem/layouts.c+1−1

This diff is large: its 9 lines aren’t shown here.

drivers/nvmem/meson-efuse.c+3−22

This diff is large: its 39 lines aren’t shown here.

drivers/nvmem/mtk-efuse.c+19−1

This diff is large: its 44 lines aren’t shown here.

drivers/nvmem/zynqmp_nvmem.c+184−31

This diff is large: its 252 lines aren’t shown here.

drivers/of/property.c+2−0

This diff is large: its 16 lines aren’t shown here.

drivers/parport/parport_amiga.c+2−3

This diff is large: its 22 lines aren’t shown here.

drivers/parport/parport_sunbpp.c+2−4

This diff is large: its 27 lines aren’t shown here.

drivers/platform/goldfish/Kconfig+1−0

This diff is large: its 8 lines aren’t shown here.

drivers/pps/generators/Makefile+1−3

This diff is large: its 8 lines aren’t shown here.

drivers/siox/siox-core.c+3−3

This diff is large: its 27 lines aren’t shown here.

drivers/slimbus/core.c+3−3

This diff is large: its 20 lines aren’t shown here.

drivers/slimbus/qcom-ngd-ctrl.c+4−4

This diff is large: its 36 lines aren’t shown here.

drivers/uio/uio.c+47−0

This diff is large: its 68 lines aren’t shown here.

drivers/uio/uio_dmem_genirq.c+8−14

This diff is large: its 66 lines aren’t shown here.

drivers/uio/uio_pruss.c+4−2

This diff is large: its 14 lines aren’t shown here.

include/dt-bindings/interconnect/qcom,msm8909.h+93−0

This diff is large: its 94 lines aren’t shown here.

include/dt-bindings/interconnect/qcom,sm7150-rpmh.h+150−0

This diff is large: its 151 lines aren’t shown here.

include/dt-bindings/interconnect/qcom,x1e80100-rpmh.h+0−24

This diff is large: its 64 lines aren’t shown here.

include/linux/cdx/cdx_bus.h+52−1

This diff is large: its 110 lines aren’t shown here.

include/linux/coresight.h+57−91

This diff is large: its 196 lines aren’t shown here.

include/linux/dio.h+1−1

This diff is large: its 9 lines aren’t shown here.

include/linux/firmware/xlnx-zynqmp.h+8−0

This diff is large: its 36 lines aren’t shown here.

include/linux/greybus.h+8−38

This diff is large: its 53 lines aren’t shown here.

include/linux/hid-sensor-ids.h+4−0

This diff is large: its 11 lines aren’t shown here.

include/linux/iio/adc/adi-axi-adc.h+0−68

This diff is large: its 69 lines aren’t shown here.

include/linux/iio/backend.h+72−0

This diff is large: its 73 lines aren’t shown here.

include/linux/iio/buffer-dmaengine.h+3−0

This diff is large: its 10 lines aren’t shown here.

include/linux/iio/iio.h+29−1

This diff is large: its 47 lines aren’t shown here.

include/linux/interconnect-provider.h+6−5

This diff is large: its 39 lines aren’t shown here.

include/linux/mhi.h+0−19

This diff is large: its 42 lines aren’t shown here.

include/linux/slimbus.h+1−1

This diff is large: its 9 lines aren’t shown here.

include/linux/uio_driver.h+13−0

This diff is large: its 40 lines aren’t shown here.

include/soc/tegra/mc.h+4−3

This diff is large: its 18 lines aren’t shown here.

tools/iio/iio_utils.c+1−1

This diff is large: its 9 lines aren’t shown here.