Pull staging driver updates from Greg KH: "Here's the big, really big, staging tree patches for 4.2-rc1. Loads of stuff in here, almost all just coding style fixes / churn, and a few new drivers as well, one of which I just disabled from the build a few minutes ago due to way too many build warnings. Other than the one "disable this driver" patch, all of these have been in linux-next for quite a while with no reported issues" * tag 'staging-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1163 commits) staging: wilc1000: disable driver due to build warnings Staging: rts5208: fix CHANGE_LINK_STATE value Staging: sm750fb: ddk750_swi2c.c: Insert spaces before parenthesis Staging: sm750fb: ddk750_swi2c.c: Place braces on correct lines Staging: sm750fb: ddk750_swi2c.c: Insert spaces around operators Staging: sm750fb: ddk750_swi2c.c: Replace spaces with tabs Staging: sm750fb: ddk750_swi2c.h: Shorten lines to under 80 characters Staging: sm750fb: ddk750_swi2c.h: Replace spaces with tabs Staging: sm750fb: modedb.h: Shorten lines to under 80 characters Staging: sm750fb: modedb.h: Replace spaces with tabs staging: comedi: addi_apci_3120: rename 'this_board' variables staging: comedi: addi_apci_1516: rename 'this_board' variables staging: comedi: ni_atmio: cleanup ni_getboardtype() staging: comedi: vmk80xx: sanity check context used to get the boardinfo staging: comedi: vmk80xx: rename 'boardinfo' variables staging: comedi: dt3000: rename 'this_board' variables staging: comedi: adv_pci_dio: rename 'this_board' variables staging: comedi: cb_pcidas64: rename 'thisboard' variables staging: comedi: cb_pcidas: rename 'thisboard' variables staging: comedi: me4000: rename 'thisboard' variables ...
Unified · Split
| @@ -71,6 +71,8 @@ Description: · 70 unmodified lines | ||
| 71 | 71 | |
| 72 | 72 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_raw |
| 73 | 73 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_raw |
| 74 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_raw | |
| 75 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_raw | |
| 74 | 76 | KernelVersion: 2.6.35 |
| 75 | 77 | Contact: linux-iio@vger.kernel.org |
| 76 | 78 | Description: |
| @@ -81,6 +83,11 @@ Description: · 4 unmodified lines | ||
| 81 | 83 | unique to allow association with event codes. Units after |
| 82 | 84 | application of scale and offset are millivolts. |
| 83 | 85 | |
| 86 | + Channels with 'i' and 'q' modifiers always exist in pairs and both | |
| 87 | + channels refer to the same signal. The 'i' channel contains the in-phase | |
| 88 | + component of the signal while the 'q' channel contains the quadrature | |
| 89 | + component. | |
| 90 | + | |
| 84 | 91 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw |
| 85 | 92 | KernelVersion: 2.6.35 |
| 86 | 93 | Contact: linux-iio@vger.kernel.org |
| @@ -246,8 +253,16 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset · 159 unmodified lines | ||
| 246 | 253 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset |
| 247 | 254 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset |
| 248 | 255 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset |
| 256 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_offset | |
| 257 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_offset | |
| 258 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_offset | |
| 259 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_offset | |
| 249 | 260 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset |
| 250 | 261 | What: /sys/bus/iio/devices/iio:deviceX/in_current_offset |
| 262 | +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_i_offset | |
| 263 | +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_q_offset | |
| 264 | +What: /sys/bus/iio/devices/iio:deviceX/in_current_q_offset | |
| 265 | +What: /sys/bus/iio/devices/iio:deviceX/in_current_i_offset | |
| 251 | 266 | What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset |
| 252 | 267 | What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset |
| 253 | 268 | What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset |
| @@ -273,14 +288,22 @@ Description: · 19 unmodified lines | ||
| 273 | 288 | to the _raw output. |
| 274 | 289 | |
| 275 | 290 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_scale |
| 291 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_scale | |
| 292 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_scale | |
| 276 | 293 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_scale |
| 277 | 294 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale |
| 295 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_i_scale | |
| 296 | +What: /sys/bus/iio/devices/iio:deviceX/in_voltage_q_scale | |
| 278 | 297 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale |
| 279 | 298 | What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale |
| 280 | 299 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale |
| 281 | 300 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale |
| 282 | 301 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale |
| 283 | 302 | What: /sys/bus/iio/devices/iio:deviceX/in_current_scale |
| 303 | +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_i_scale | |
| 304 | +What: /sys/bus/iio/devices/iio:deviceX/in_currentY_q_scale | |
| 305 | +What: /sys/bus/iio/devices/iio:deviceX/in_current_i_scale | |
| 306 | +What: /sys/bus/iio/devices/iio:deviceX/in_current_q_scale | |
| 284 | 307 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale |
| 285 | 308 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale |
| 286 | 309 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale |
| @@ -328,6 +351,10 @@ Description: · 41 unmodified lines | ||
| 328 | 351 | |
| 329 | 352 | What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale |
| 330 | 353 | What /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale |
| 354 | +What /sys/bus/iio/devices/iio:deviceX/in_voltageY_i_calibscale | |
| 355 | +What /sys/bus/iio/devices/iio:deviceX/in_voltageY_q_calibscale | |
| 356 | +What /sys/bus/iio/devices/iio:deviceX/in_voltage_i_calibscale | |
| 357 | +What /sys/bus/iio/devices/iio:deviceX/in_voltage_q_calibscale | |
| 331 | 358 | What /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale |
| 332 | 359 | What /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale |
| 333 | 360 | What /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale |
| @@ -420,6 +447,16 @@ Description: · 86 unmodified lines | ||
| 420 | 447 | to the underlying data channel, then this parameter |
| 421 | 448 | gives the 3dB frequency of the filter in Hz. |
| 422 | 449 | |
| 450 | +What: /sys/.../in_accel_filter_high_pass_3db_frequency | |
| 451 | +What: /sys/.../in_anglvel_filter_high_pass_3db_frequency | |
| 452 | +What: /sys/.../in_magn_filter_high_pass_3db_frequency | |
| 453 | +KernelVersion: 4.2 | |
| 454 | +Contact: linux-iio@vger.kernel.org | |
| 455 | +Description: | |
| 456 | + If a known or controllable high pass filter is applied | |
| 457 | + to the underlying data channel, then this parameter | |
| 458 | + gives the 3dB frequency of the filter in Hz. | |
| 459 | + | |
| 423 | 460 | What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw |
| 424 | 461 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_raw |
| 425 | 462 | KernelVersion: 2.6.37 |
| @@ -880,6 +917,26 @@ Description: · 454 unmodified lines | ||
| 880 | 917 | met before an event is generated. If direction is not |
| 881 | 918 | specified then this period applies to both directions. |
| 882 | 919 | |
| 920 | +What: /sys/.../events/in_accel_thresh_rising_low_pass_filter_3db | |
| 921 | +What: /sys/.../events/in_anglvel_thresh_rising_low_pass_filter_3db | |
| 922 | +What: /sys/.../events/in_magn_thresh_rising_low_pass_filter_3db | |
| 923 | +KernelVersion: 4.2 | |
| 924 | +Contact: linux-iio@vger.kernel.org | |
| 925 | +Description: | |
| 926 | + If a low pass filter can be applied to the event generation | |
| 927 | + this property gives its 3db frequency in Hz. | |
| 928 | + A value of zero disables the filter. | |
| 929 | + | |
| 930 | +What: /sys/.../events/in_accel_thresh_rising_high_pass_filter_3db | |
| 931 | +What: /sys/.../events/in_anglvel_thresh_rising_high_pass_filter_3db | |
| 932 | +What: /sys/.../events/in_magn_thresh_rising_high_pass_filter_3db | |
| 933 | +KernelVersion: 4.2 | |
| 934 | +Contact: linux-iio@vger.kernel.org | |
| 935 | +Description: | |
| 936 | + If a high pass filter can be applied to the event generation | |
| 937 | + this property gives its 3db frequency in Hz. | |
| 938 | + A value of zero disables the filter. | |
| 939 | + | |
| 883 | 940 | What: /sys/.../events/in_activity_still_thresh_rising_en |
| 884 | 941 | What: /sys/.../events/in_activity_still_thresh_falling_en |
| 885 | 942 | What: /sys/.../events/in_activity_walking_thresh_rising_en |
| @@ -1016,6 +1073,10 @@ What: /sys/.../iio:deviceX/scan_elements/in_timestamp_en · 130 unmodified lines | ||
| 1016 | 1073 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en |
| 1017 | 1074 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en |
| 1018 | 1075 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY-voltageZ_en |
| 1076 | +What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_en | |
| 1077 | +What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_en | |
| 1078 | +What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_en | |
| 1079 | +What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_en | |
| 1019 | 1080 | What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en |
| 1020 | 1081 | What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en |
| 1021 | 1082 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en |
| @@ -1034,6 +1095,10 @@ What: /sys/.../iio:deviceX/scan_elements/in_incli_type · 12 unmodified lines | ||
| 1034 | 1095 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type |
| 1035 | 1096 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_type |
| 1036 | 1097 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type |
| 1098 | +What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_type | |
| 1099 | +What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_type | |
| 1100 | +What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_type | |
| 1101 | +What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_type | |
| 1037 | 1102 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type |
| 1038 | 1103 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type |
| 1039 | 1104 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_type |
| @@ -1071,6 +1136,10 @@ Description: · 31 unmodified lines | ||
| 1071 | 1136 | |
| 1072 | 1137 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index |
| 1073 | 1138 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_index |
| 1139 | +What: /sys/.../iio:deviceX/scan_elements/in_voltageY_i_index | |
| 1140 | +What: /sys/.../iio:deviceX/scan_elements/in_voltageY_q_index | |
| 1141 | +What: /sys/.../iio:deviceX/scan_elements/in_voltage_i_index | |
| 1142 | +What: /sys/.../iio:deviceX/scan_elements/in_voltage_q_index | |
| 1074 | 1143 | What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index |
| 1075 | 1144 | What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index |
| 1076 | 1145 | What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index |
| @@ -1230,6 +1299,8 @@ Description: · 153 unmodified lines | ||
| 1230 | 1299 | or without compensation from tilt sensors. |
| 1231 | 1300 | |
| 1232 | 1301 | What: /sys/bus/iio/devices/iio:deviceX/in_currentX_raw |
| 1302 | +What: /sys/bus/iio/devices/iio:deviceX/in_currentX_i_raw | |
| 1303 | +What: /sys/bus/iio/devices/iio:deviceX/in_currentX_q_raw | |
| 1233 | 1304 | KernelVersion: 3.18 |
| 1234 | 1305 | Contact: linux-iio@vger.kernel.org |
| 1235 | 1306 | Description: |
| @@ -1238,6 +1309,11 @@ Description: · 2 unmodified lines | ||
| 1238 | 1309 | present, output should be considered as processed with the |
| 1239 | 1310 | unit in milliamps. |
| 1240 | 1311 | |
| 1312 | + Channels with 'i' and 'q' modifiers always exist in pairs and both | |
| 1313 | + channels refer to the same signal. The 'i' channel contains the in-phase | |
| 1314 | + component of the signal while the 'q' channel contains the quadrature | |
| 1315 | + component. | |
| 1316 | + | |
| 1241 | 1317 | What: /sys/.../iio:deviceX/in_energy_en |
| 1242 | 1318 | What: /sys/.../iio:deviceX/in_distance_en |
| 1243 | 1319 | What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en |
| @@ -1364,3 +1440,26 @@ Description: · 120 unmodified lines | ||
| 1364 | 1440 | hwfifo_watermak_min but not equal to any of the values in this |
| 1365 | 1441 | list, the driver will chose an appropriate value for the |
| 1366 | 1442 | hardware fifo watermark level. |
| 1443 | + | |
| 1444 | +What: /sys/bus/iio/devices/iio:deviceX/in_temp_calibemissivity | |
| 1445 | +What: /sys/bus/iio/devices/iio:deviceX/in_tempX_calibemissivity | |
| 1446 | +What: /sys/bus/iio/devices/iio:deviceX/in_temp_object_calibemissivity | |
| 1447 | +What: /sys/bus/iio/devices/iio:deviceX/in_tempX_object_calibemissivity | |
| 1448 | +KernelVersion: 4.1 | |
| 1449 | +Contact: linux-iio@vger.kernel.org | |
| 1450 | +Description: | |
| 1451 | + The emissivity ratio of the surface in the field of view of the | |
| 1452 | + contactless temperature sensor. Emissivity varies from 0 to 1, | |
| 1453 | + with 1 being the emissivity of a black body. | |
| 1454 | + | |
| 1455 | +What: /sys/bus/iio/devices/iio:deviceX/in_magn_x_oversampling_ratio | |
| 1456 | +What: /sys/bus/iio/devices/iio:deviceX/in_magn_y_oversampling_ratio | |
| 1457 | +What: /sys/bus/iio/devices/iio:deviceX/in_magn_z_oversampling_ratio | |
| 1458 | +KernelVersion: 4.2 | |
| 1459 | +Contact: linux-iio@vger.kernel.org | |
| 1460 | +Description: | |
| 1461 | + Hardware applied number of measurements for acquiring one | |
| 1462 | + data point. The HW will do <type>[_name]_oversampling_ratio | |
| 1463 | + measurements and return the average value as output data. Each | |
| 1464 | + value resulted from <type>[_name]_oversampling_ratio measurements | |
| 1465 | + is considered as one sample for <type>[_name]_sampling_frequency. | |
| @@ -0,0 +1,7 @@ | ||
| 1 | +What: /sys/bus/iio/devices/iio:deviceX/conversion_mode | |
| 2 | +KernelVersion: 4.2 | |
| 3 | +Contact: linux-iio@vger.kernel.org | |
| 4 | +Description: | |
| 5 | + Specifies the hardware conversion mode used. The three | |
| 6 | + available modes are "normal", "high-speed" and "low-power", | |
| 7 | + where the last is the default mode. | |
| @@ -0,0 +1,19 @@ | ||
| 1 | +* Berlin Analog to Digital Converter (ADC) | |
| 2 | + | |
| 3 | +The Berlin ADC has 8 channels, with one connected to a temperature sensor. | |
| 4 | +It is part of the system controller register set. The ADC node should be a | |
| 5 | +sub-node of the system controller node. | |
| 6 | + | |
| 7 | +Required properties: | |
| 8 | +- compatible: must be "marvell,berlin2-adc" | |
| 9 | +- interrupts: the interrupts for the ADC and the temperature sensor | |
| 10 | +- interrupt-names: should be "adc" and "tsen" | |
| 11 | + | |
| 12 | +Example: | |
| 13 | + | |
| 14 | +adc: adc { | |
| 15 | + compatible = "marvell,berlin2-adc"; | |
| 16 | + interrupt-parent = <&sic>; | |
| 17 | + interrupts = <12>, <14>; | |
| 18 | + interrupt-names = "adc", "tsen"; | |
| 19 | +}; | |
| @@ -1,7 +1,7 @@ | ||
| 1 | −* Texas Instruments' ADC128S052 ADC chip | |
| 1 | +* Texas Instruments' ADC128S052 and ADC122S021 ADC chip | |
| 2 | 2 | |
| 3 | 3 | Required properties: |
| 4 | − - compatible: Should be "ti,adc128s052" | |
| 4 | + - compatible: Should be "ti,adc128s052" or "ti,adc122s021" | |
| 5 | 5 | - reg: spi chip select number for the device |
| 6 | 6 | - vref-supply: The regulator supply for ADC reference voltage |
| 7 | 7 | |
| @@ -11,6 +11,13 @@ Required properties: · 10 unmodified lines | ||
| 11 | 11 | - clock-names: Must contain "adc", matching entry in the clocks property. |
| 12 | 12 | - vref-supply: The regulator supply ADC reference voltage. |
| 13 | 13 | |
| 14 | +Recommended properties: | |
| 15 | +- fsl,adck-max-frequency: Maximum frequencies according to datasheets operating | |
| 16 | + requirements. Three values are required, depending on conversion mode: | |
| 17 | + - Frequency in normal mode (ADLPC=0, ADHSC=0) | |
| 18 | + - Frequency in high-speed mode (ADLPC=0, ADHSC=1) | |
| 19 | + - Frequency in low-power mode (ADLPC=1, ADHSC=0) | |
| 20 | + | |
| 14 | 21 | Example: |
| 15 | 22 | adc0: adc@4003b000 { |
| 16 | 23 | compatible = "fsl,vf610-adc"; |
| @@ -18,5 +25,7 @@ adc0: adc@4003b000 { · 1 unmodified line | ||
| 18 | 25 | interrupts = <0 53 0x04>; |
| 19 | 26 | clocks = <&clks VF610_CLK_ADC0>; |
| 20 | 27 | clock-names = "adc"; |
| 28 | + fsl,adck-max-frequency = <30000000>, <40000000>, | |
| 29 | + <20000000>; | |
| 21 | 30 | vref-supply = <®_vcc_3v3_mcu>; |
| 22 | 31 | }; |
| @@ -0,0 +1,17 @@ | ||
| 1 | +InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device | |
| 2 | + | |
| 3 | +http://www.invensense.com/mems/gyro/mpu6050.html | |
| 4 | + | |
| 5 | +Required properties: | |
| 6 | + - compatible : should be "invensense,mpu6050" | |
| 7 | + - reg : the I2C address of the sensor | |
| 8 | + - interrupt-parent : should be the phandle for the interrupt controller | |
| 9 | + - interrupts : interrupt mapping for GPIO IRQ | |
| 10 | + | |
| 11 | +Example: | |
| 12 | + mpu6050@68 { | |
| 13 | + compatible = "invensense,mpu6050"; | |
| 14 | + reg = <0x68>; | |
| 15 | + interrupt-parent = <&gpio1>; | |
| 16 | + interrupts = <18 1>; | |
| 17 | + }; | |
| @@ -0,0 +1,22 @@ | ||
| 1 | +* Bosch BMC150 magnetometer sensor | |
| 2 | + | |
| 3 | +http://ae-bst.resource.bosch.com/media/products/dokumente/bmc150/BST-BMC150-DS000-04.pdf | |
| 4 | + | |
| 5 | +Required properties: | |
| 6 | + | |
| 7 | + - compatible : should be "bosch,bmc150_magn" | |
| 8 | + - reg : the I2C address of the magnetometer | |
| 9 | + | |
| 10 | +Optional properties: | |
| 11 | + | |
| 12 | + - interrupt-parent : phandle to the parent interrupt controller | |
| 13 | + - interrupts : interrupt mapping for GPIO IRQ | |
| 14 | + | |
| 15 | +Example: | |
| 16 | + | |
| 17 | +bmc150_magn@12 { | |
| 18 | + compatible = "bosch,bmc150_magn"; | |
| 19 | + reg = <0x12>; | |
| 20 | + interrupt-parent = <&gpio1>; | |
| 21 | + interrupts = <0 1>; | |
| 22 | +}; | |
| @@ -30,6 +30,7 @@ Accelerometers: · 29 unmodified lines | ||
| 30 | 30 | - st,lsm330d-accel |
| 31 | 31 | - st,lsm330dl-accel |
| 32 | 32 | - st,lsm330dlc-accel |
| 33 | +- st,lis331dl-accel | |
| 33 | 34 | - st,lis331dlh-accel |
| 34 | 35 | - st,lsm303dl-accel |
| 35 | 36 | - st,lsm303dlm-accel |
| @@ -45,6 +46,7 @@ Gyroscopes: · 9 unmodified lines | ||
| 45 | 46 | - st,lsm330-gyro |
| 46 | 47 | |
| 47 | 48 | Magnetometers: |
| 49 | +- st,lsm303dlh-magn | |
| 48 | 50 | - st,lsm303dlhc-magn |
| 49 | 51 | - st,lsm303dlm-magn |
| 50 | 52 | - st,lis3mdl-magn |
| @@ -0,0 +1,24 @@ | ||
| 1 | +* Melexis MLX90614 contactless IR temperature sensor | |
| 2 | + | |
| 3 | +http://melexis.com/Infrared-Thermometer-Sensors/Infrared-Thermometer-Sensors/MLX90614-615.aspx | |
| 4 | + | |
| 5 | +Required properties: | |
| 6 | + | |
| 7 | + - compatible: should be "melexis,mlx90614" | |
| 8 | + - reg: the I2C address of the sensor | |
| 9 | + | |
| 10 | +Optional properties: | |
| 11 | + | |
| 12 | + - wakeup-gpios: device tree identifier of the GPIO connected to the SDA line | |
| 13 | + to hold low in order to wake up the device. In normal operation, the | |
| 14 | + GPIO is set as input and will not interfere in I2C communication. There | |
| 15 | + is no need for a GPIO driving the SCL line. If no GPIO is given, power | |
| 16 | + management is disabled. | |
| 17 | + | |
| 18 | +Example: | |
| 19 | + | |
| 20 | +mlx90614@5a { | |
| 21 | + compatible = "melexis,mlx90614"; | |
| 22 | + reg = <0x5a>; | |
| 23 | + wakeup-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; | |
| 24 | +}; | |
| @@ -42,6 +42,27 @@ Optional properties: · 41 unmodified lines | ||
| 42 | 42 | hardware knob for adjusting the amount of "settling |
| 43 | 43 | time". |
| 44 | 44 | |
| 45 | +- child "adc" | |
| 46 | + ti,chan-step-opendelay: List of open delays for each channel of | |
| 47 | + ADC in the order of ti,adc-channels. The | |
| 48 | + value corresponds to the number of ADC | |
| 49 | + clock cycles to wait after applying the | |
| 50 | + step configuration registers and before | |
| 51 | + sending the start of ADC conversion. | |
| 52 | + Maximum value is 0x3FFFF. | |
| 53 | + ti,chan-step-sampledelay: List of sample delays for each channel | |
| 54 | + of ADC in the order of ti,adc-channels. | |
| 55 | + The value corresponds to the number of | |
| 56 | + ADC clock cycles to sample (to hold | |
| 57 | + start of conversion high). | |
| 58 | + Maximum value is 0xFF. | |
| 59 | + ti,chan-step-avg: Number of averages to be performed for each | |
| 60 | + channel of ADC. If average is 16 then input | |
| 61 | + is sampled 16 times and averaged to get more | |
| 62 | + accurate value. This increases the time taken | |
| 63 | + by ADC to generate a sample. Valid range is 0 | |
| 64 | + average to 16 averages. Maximum value is 16. | |
| 65 | + | |
| 45 | 66 | Example: |
| 46 | 67 | tscadc: tscadc@44e0d000 { |
| 47 | 68 | compatible = "ti,am3359-tscadc"; |
| @@ -55,5 +76,8 @@ Example: · 7 unmodified lines | ||
| 55 | 76 | |
| 56 | 77 | adc { |
| 57 | 78 | ti,adc-channels = <4 5 6 7>; |
| 79 | + ti,chan-step-opendelay = <0x098 0x3ffff 0x098 0x0>; | |
| 80 | + ti,chan-step-sampledelay = <0xff 0x0 0xf 0x0>; | |
| 81 | + ti,chan-step-avg = <16 2 4 8>; | |
| 58 | 82 | }; |
| 59 | 83 | } |
| @@ -123,6 +123,7 @@ lltc Linear Technology Corporation · 122 unmodified lines | ||
| 123 | 123 | marvell Marvell Technology Group Ltd. |
| 124 | 124 | maxim Maxim Integrated Products |
| 125 | 125 | mediatek MediaTek Inc. |
| 126 | +melexis Melexis N.V. | |
| 126 | 127 | merrii Merrii Technology Co., Ltd. |
| 127 | 128 | micrel Micrel Inc. |
| 128 | 129 | microchip Microchip Technology Inc. |
| @@ -171,6 +171,12 @@ This functions by reading the offset, applying the mask. If the bits selected in · 170 unmodified lines | ||
| 171 | 171 | the mask match with the values of the corresponding bits in the compare field, |
| 172 | 172 | the value of swap is written the specified offset. |
| 173 | 173 | |
| 174 | +Parts of a VME window can be mapped into user space memory using the following | |
| 175 | +function: | |
| 176 | + | |
| 177 | + int vme_master_mmap(struct vme_resource *resource, | |
| 178 | + struct vm_area_struct *vma) | |
| 179 | + | |
| 174 | 180 | |
| 175 | 181 | Slave windows |
| 176 | 182 | ============= |
| @@ -9696,6 +9696,15 @@ M: Forest Bond <forest@alittletooquiet.net> · 9695 unmodified lines | ||
| 9696 | 9696 | S: Odd Fixes |
| 9697 | 9697 | F: drivers/staging/vt665?/ |
| 9698 | 9698 | |
| 9699 | +STAGING - WILC1000 WIFI DRIVER | |
| 9700 | +M: Johnny Kim <johnny.kim@atmel.com> | |
| 9701 | +M: Rachel Kim <rachel.kim@atmel.com> | |
| 9702 | +M: Dean Lee <dean.lee@atmel.com> | |
| 9703 | +M: Chris Park <chris.park@atmel.com> | |
| 9704 | +L: linux-wireless@vger.kernel.org | |
| 9705 | +S: Supported | |
| 9706 | +F: drivers/staging/wilc1000/ | |
| 9707 | + | |
| 9699 | 9708 | STAGING - XGI Z7,Z9,Z11 PCI DISPLAY DRIVER |
| 9700 | 9709 | M: Arnaud Patard <arnaud.patard@rtp-net.org> |
| 9701 | 9710 | S: Odd Fixes |
| @@ -98,7 +98,6 @@ obj-$(CONFIG_USB_GADGET) += usb/ · 97 unmodified lines | ||
| 98 | 98 | obj-$(CONFIG_SERIO) += input/serio/ |
| 99 | 99 | obj-$(CONFIG_GAMEPORT) += input/gameport/ |
| 100 | 100 | obj-$(CONFIG_INPUT) += input/ |
| 101 | −obj-$(CONFIG_I2O) += message/ | |
| 102 | 101 | obj-$(CONFIG_RTC_LIB) += rtc/ |
| 103 | 102 | obj-y += i2c/ media/ |
| 104 | 103 | obj-$(CONFIG_PPS) += pps/ |
| @@ -136,4 +136,25 @@ config MMA9553 · 135 unmodified lines | ||
| 136 | 136 | |
| 137 | 137 | To compile this driver as a module, choose M here: the module |
| 138 | 138 | will be called mma9553. |
| 139 | + | |
| 140 | +config STK8312 | |
| 141 | + tristate "Sensortek STK8312 3-Axis Accelerometer Driver" | |
| 142 | + depends on I2C | |
| 143 | + help | |
| 144 | + Say yes here to get support for the Sensortek STK8312 3-axis | |
| 145 | + accelerometer. | |
| 146 | + | |
| 147 | + Choosing M will build the driver as a module. If so, the module | |
| 148 | + will be called stk8312. | |
| 149 | + | |
| 150 | +config STK8BA50 | |
| 151 | + tristate "Sensortek STK8BA50 3-Axis Accelerometer Driver" | |
| 152 | + depends on I2C | |
| 153 | + help | |
| 154 | + Say yes here to get support for the Sensortek STK8BA50 3-axis | |
| 155 | + accelerometer. | |
| 156 | + | |
| 157 | + Choosing M will build the driver as a module. If so, the module | |
| 158 | + will be called stk8ba50. | |
| 159 | + | |
| 139 | 160 | endmenu |
| @@ -14,6 +14,9 @@ obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o · 13 unmodified lines | ||
| 14 | 14 | obj-$(CONFIG_MMA9551) += mma9551.o |
| 15 | 15 | obj-$(CONFIG_MMA9553) += mma9553.o |
| 16 | 16 | |
| 17 | +obj-$(CONFIG_STK8312) += stk8312.o | |
| 18 | +obj-$(CONFIG_STK8BA50) += stk8ba50.o | |
| 19 | + | |
| 17 | 20 | obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o |
| 18 | 21 | |
| 19 | 22 | obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o |
| @@ -196,7 +196,7 @@ struct bmc150_accel_data { · 195 unmodified lines | ||
| 196 | 196 | u32 slope_thres; |
| 197 | 197 | u32 range; |
| 198 | 198 | int ev_enable_state; |
| 199 | − int64_t timestamp, old_timestamp; | |
| 199 | + int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ | |
| 200 | 200 | const struct bmc150_accel_chip_info *chip_info; |
| 201 | 201 | }; |
| 202 | 202 | |
| @@ -1183,7 +1183,6 @@ static const struct iio_info bmc150_accel_info = { · 980 unmodified lines | ||
| 1183 | 1183 | .write_event_value = bmc150_accel_write_event, |
| 1184 | 1184 | .write_event_config = bmc150_accel_write_event_config, |
| 1185 | 1185 | .read_event_config = bmc150_accel_read_event_config, |
| 1186 | − .validate_trigger = bmc150_accel_validate_trigger, | |
| 1187 | 1186 | .driver_module = THIS_MODULE, |
| 1188 | 1187 | }; |
| 1189 | 1188 | |
| @@ -1222,7 +1221,7 @@ static irqreturn_t bmc150_accel_trigger_handler(int irq, void *p) · 32 unmodified lines | ||
| 1222 | 1221 | mutex_unlock(&data->mutex); |
| 1223 | 1222 | |
| 1224 | 1223 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, |
| 1225 | − data->timestamp); | |
| 1224 | + pf->timestamp); | |
| 1226 | 1225 | err_read: |
| 1227 | 1226 | iio_trigger_notify_done(indio_dev->trig); |
| 1228 | 1227 | |
| @@ -1535,6 +1534,13 @@ static int bmc150_accel_fifo_set_mode(struct bmc150_accel_data *data) · 306 unmodified lines | ||
| 1535 | 1534 | return ret; |
| 1536 | 1535 | } |
| 1537 | 1536 | |
| 1537 | +static int bmc150_accel_buffer_preenable(struct iio_dev *indio_dev) | |
| 1538 | +{ | |
| 1539 | + struct bmc150_accel_data *data = iio_priv(indio_dev); | |
| 1540 | + | |
| 1541 | + return bmc150_accel_set_power_state(data, true); | |
| 1542 | +} | |
| 1543 | + | |
| 1538 | 1544 | static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev) |
| 1539 | 1545 | { |
| 1540 | 1546 | struct bmc150_accel_data *data = iio_priv(indio_dev); |
| @@ -1591,9 +1597,18 @@ out: · 50 unmodified lines | ||
| 1591 | 1597 | return 0; |
| 1592 | 1598 | } |
| 1593 | 1599 | |
| 1600 | +static int bmc150_accel_buffer_postdisable(struct iio_dev *indio_dev) | |
| 1601 | +{ | |
| 1602 | + struct bmc150_accel_data *data = iio_priv(indio_dev); | |
| 1603 | + | |
| 1604 | + return bmc150_accel_set_power_state(data, false); | |
| 1605 | +} | |
| 1606 | + | |
| 1594 | 1607 | static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = { |
| 1608 | + .preenable = bmc150_accel_buffer_preenable, | |
| 1595 | 1609 | .postenable = bmc150_accel_buffer_postenable, |
| 1596 | 1610 | .predisable = bmc150_accel_buffer_predisable, |
| 1611 | + .postdisable = bmc150_accel_buffer_postdisable, | |
| 1597 | 1612 | }; |
| 1598 | 1613 | |
| 1599 | 1614 | static int bmc150_accel_probe(struct i2c_client *client, |
| @@ -1636,6 +1651,15 @@ static int bmc150_accel_probe(struct i2c_client *client, · 36 unmodified lines | ||
| 1636 | 1651 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1637 | 1652 | indio_dev->info = &bmc150_accel_info; |
| 1638 | 1653 | |
| 1654 | + ret = iio_triggered_buffer_setup(indio_dev, | |
| 1655 | + &iio_pollfunc_store_time, | |
| 1656 | + bmc150_accel_trigger_handler, | |
| 1657 | + &bmc150_accel_buffer_ops); | |
| 1658 | + if (ret < 0) { | |
| 1659 | + dev_err(&client->dev, "Failed: iio triggered buffer setup\n"); | |
| 1660 | + return ret; | |
| 1661 | + } | |
| 1662 | + | |
| 1639 | 1663 | if (client->irq < 0) |
| 1640 | 1664 | client->irq = bmc150_accel_gpio_probe(client, data); |
| 1641 | 1665 | |
| @@ -1648,7 +1672,7 @@ static int bmc150_accel_probe(struct i2c_client *client, · 6 unmodified lines | ||
| 1648 | 1672 | BMC150_ACCEL_IRQ_NAME, |
| 1649 | 1673 | indio_dev); |
| 1650 | 1674 | if (ret) |
| 1651 | − return ret; | |
| 1675 | + goto err_buffer_cleanup; | |
| 1652 | 1676 | |
| 1653 | 1677 | /* |
| 1654 | 1678 | * Set latched mode interrupt. While certain interrupts are |
| @@ -1661,24 +1685,14 @@ static int bmc150_accel_probe(struct i2c_client *client, · 6 unmodified lines | ||
| 1661 | 1685 | BMC150_ACCEL_INT_MODE_LATCH_RESET); |
| 1662 | 1686 | if (ret < 0) { |
| 1663 | 1687 | dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n"); |
| 1664 | − return ret; | |
| 1688 | + goto err_buffer_cleanup; | |
| 1665 | 1689 | } |
| 1666 | 1690 | |
| 1667 | 1691 | bmc150_accel_interrupts_setup(indio_dev, data); |
| 1668 | 1692 | |
| 1669 | 1693 | ret = bmc150_accel_triggers_setup(indio_dev, data); |
| 1670 | 1694 | if (ret) |
| 1671 | − return ret; | |
| 1672 | − | |
| 1673 | − ret = iio_triggered_buffer_setup(indio_dev, | |
| 1674 | − &iio_pollfunc_store_time, | |
| 1675 | − bmc150_accel_trigger_handler, | |
| 1676 | − &bmc150_accel_buffer_ops); | |
| 1677 | − if (ret < 0) { | |
| 1678 | − dev_err(&client->dev, | |
| 1679 | − "Failed: iio triggered buffer setup\n"); | |
| 1680 | − goto err_trigger_unregister; | |
| 1681 | − } | |
| 1695 | + goto err_buffer_cleanup; | |
| 1682 | 1696 | |
| 1683 | 1697 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || |
| 1684 | 1698 | i2c_check_functionality(client->adapter, |
| @@ -1692,7 +1706,7 @@ static int bmc150_accel_probe(struct i2c_client *client, · 7 unmodified lines | ||
| 1692 | 1706 | ret = iio_device_register(indio_dev); |
| 1693 | 1707 | if (ret < 0) { |
| 1694 | 1708 | dev_err(&client->dev, "Unable to register iio device\n"); |
| 1695 | − goto err_buffer_cleanup; | |
| 1709 | + goto err_trigger_unregister; | |
| 1696 | 1710 | } |
| 1697 | 1711 | |
| 1698 | 1712 | ret = pm_runtime_set_active(&client->dev); |
| @@ -1708,11 +1722,10 @@ static int bmc150_accel_probe(struct i2c_client *client, · 9 unmodified lines | ||
| 1708 | 1722 | |
| 1709 | 1723 | err_iio_unregister: |
| 1710 | 1724 | iio_device_unregister(indio_dev); |
| 1711 | −err_buffer_cleanup: | |
| 1712 | − if (indio_dev->pollfunc) | |
| 1713 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 1714 | 1725 | err_trigger_unregister: |
| 1715 | 1726 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1727 | +err_buffer_cleanup: | |
| 1728 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 1716 | 1729 | |
| 1717 | 1730 | return ret; |
| 1718 | 1731 | } |
| @@ -1730,6 +1743,8 @@ static int bmc150_accel_remove(struct i2c_client *client) · 11 unmodified lines | ||
| 1730 | 1743 | |
| 1731 | 1744 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1732 | 1745 | |
| 1746 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 1747 | + | |
| 1733 | 1748 | mutex_lock(&data->mutex); |
| 1734 | 1749 | bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_DEEP_SUSPEND, 0); |
| 1735 | 1750 | mutex_unlock(&data->mutex); |
| @@ -299,7 +299,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev) · 298 unmodified lines | ||
| 299 | 299 | struct iio_dev *indio_dev; |
| 300 | 300 | struct accel_3d_state *accel_state; |
| 301 | 301 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 302 | − struct iio_chan_spec *channels; | |
| 303 | 302 | |
| 304 | 303 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 305 | 304 | sizeof(struct accel_3d_state)); |
| @@ -320,21 +319,21 @@ static int hid_accel_3d_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 320 | 319 | return ret; |
| 321 | 320 | } |
| 322 | 321 | |
| 323 | − channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels), | |
| 324 | − GFP_KERNEL); | |
| 325 | − if (!channels) { | |
| 322 | + indio_dev->channels = kmemdup(accel_3d_channels, | |
| 323 | + sizeof(accel_3d_channels), GFP_KERNEL); | |
| 324 | + if (!indio_dev->channels) { | |
| 326 | 325 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 327 | 326 | return -ENOMEM; |
| 328 | 327 | } |
| 329 | 328 | |
| 330 | − ret = accel_3d_parse_report(pdev, hsdev, channels, | |
| 331 | − HID_USAGE_SENSOR_ACCEL_3D, accel_state); | |
| 329 | + ret = accel_3d_parse_report(pdev, hsdev, | |
| 330 | + (struct iio_chan_spec *)indio_dev->channels, | |
| 331 | + HID_USAGE_SENSOR_ACCEL_3D, accel_state); | |
| 332 | 332 | if (ret) { |
| 333 | 333 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 334 | 334 | goto error_free_dev_mem; |
| 335 | 335 | } |
| 336 | 336 | |
| 337 | − indio_dev->channels = channels; | |
| 338 | 337 | indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels); |
| 339 | 338 | indio_dev->dev.parent = &pdev->dev; |
| 340 | 339 | indio_dev->info = &accel_3d_info; |
| @@ -400,7 +399,7 @@ static int hid_accel_3d_remove(struct platform_device *pdev) · 59 unmodified lines | ||
| 400 | 399 | return 0; |
| 401 | 400 | } |
| 402 | 401 | |
| 403 | −static struct platform_device_id hid_accel_3d_ids[] = { | |
| 402 | +static const struct platform_device_id hid_accel_3d_ids[] = { | |
| 404 | 403 | { |
| 405 | 404 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 406 | 405 | .name = "HID-SENSOR-200073", |
| @@ -875,15 +875,18 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, · 874 unmodified lines | ||
| 875 | 875 | return 0; |
| 876 | 876 | } |
| 877 | 877 | |
| 878 | −static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev, | |
| 879 | − struct iio_trigger *trig) | |
| 878 | +static int kxcjk1013_buffer_preenable(struct iio_dev *indio_dev) | |
| 880 | 879 | { |
| 881 | 880 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 882 | 881 | |
| 883 | − if (data->dready_trig != trig && data->motion_trig != trig) | |
| 884 | − return -EINVAL; | |
| 882 | + return kxcjk1013_set_power_state(data, true); | |
| 883 | +} | |
| 885 | 884 | |
| 886 | − return 0; | |
| 885 | +static int kxcjk1013_buffer_postdisable(struct iio_dev *indio_dev) | |
| 886 | +{ | |
| 887 | + struct kxcjk1013_data *data = iio_priv(indio_dev); | |
| 888 | + | |
| 889 | + return kxcjk1013_set_power_state(data, false); | |
| 887 | 890 | } |
| 888 | 891 | |
| 889 | 892 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( |
| @@ -935,6 +938,13 @@ static const struct iio_chan_spec kxcjk1013_channels[] = { · 45 unmodified lines | ||
| 935 | 938 | IIO_CHAN_SOFT_TIMESTAMP(3), |
| 936 | 939 | }; |
| 937 | 940 | |
| 941 | +static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = { | |
| 942 | + .preenable = kxcjk1013_buffer_preenable, | |
| 943 | + .postenable = iio_triggered_buffer_postenable, | |
| 944 | + .postdisable = kxcjk1013_buffer_postdisable, | |
| 945 | + .predisable = iio_triggered_buffer_predisable, | |
| 946 | +}; | |
| 947 | + | |
| 938 | 948 | static const struct iio_info kxcjk1013_info = { |
| 939 | 949 | .attrs = &kxcjk1013_attrs_group, |
| 940 | 950 | .read_raw = kxcjk1013_read_raw, |
| @@ -943,7 +953,6 @@ static const struct iio_info kxcjk1013_info = { · 2 unmodified lines | ||
| 943 | 953 | .write_event_value = kxcjk1013_write_event, |
| 944 | 954 | .write_event_config = kxcjk1013_write_event_config, |
| 945 | 955 | .read_event_config = kxcjk1013_read_event_config, |
| 946 | − .validate_trigger = kxcjk1013_validate_trigger, | |
| 947 | 956 | .driver_module = THIS_MODULE, |
| 948 | 957 | }; |
| 949 | 958 | |
| @@ -1147,8 +1156,10 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev, · 197 unmodified lines | ||
| 1147 | 1156 | id = acpi_match_device(dev->driver->acpi_match_table, dev); |
| 1148 | 1157 | if (!id) |
| 1149 | 1158 | return NULL; |
| 1159 | + | |
| 1150 | 1160 | if (strcmp(id->id, "SMO8500") == 0) |
| 1151 | 1161 | *is_smo8500_device = true; |
| 1162 | + | |
| 1152 | 1163 | *chipset = (enum kx_chipset)id->driver_data; |
| 1153 | 1164 | |
| 1154 | 1165 | return dev_name(dev); |
| @@ -1163,6 +1174,7 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client, · 8 unmodified lines | ||
| 1163 | 1174 | |
| 1164 | 1175 | if (!client) |
| 1165 | 1176 | return -EINVAL; |
| 1177 | + | |
| 1166 | 1178 | if (data->is_smo8500_device) |
| 1167 | 1179 | return -ENOTSUPP; |
| 1168 | 1180 | |
| @@ -1276,16 +1288,15 @@ static int kxcjk1013_probe(struct i2c_client *client, · 107 unmodified lines | ||
| 1276 | 1288 | data->motion_trig = NULL; |
| 1277 | 1289 | goto err_trigger_unregister; |
| 1278 | 1290 | } |
| 1291 | + } | |
| 1279 | 1292 | |
| 1280 | − ret = iio_triggered_buffer_setup(indio_dev, | |
| 1281 | − &iio_pollfunc_store_time, | |
| 1282 | − kxcjk1013_trigger_handler, | |
| 1283 | − NULL); | |
| 1284 | − if (ret < 0) { | |
| 1285 | − dev_err(&client->dev, | |
| 1286 | − "iio triggered buffer setup failed\n"); | |
| 1287 | − goto err_trigger_unregister; | |
| 1288 | − } | |
| 1293 | + ret = iio_triggered_buffer_setup(indio_dev, | |
| 1294 | + &iio_pollfunc_store_time, | |
| 1295 | + kxcjk1013_trigger_handler, | |
| 1296 | + &kxcjk1013_buffer_setup_ops); | |
| 1297 | + if (ret < 0) { | |
| 1298 | + dev_err(&client->dev, "iio triggered buffer setup failed\n"); | |
| 1299 | + goto err_trigger_unregister; | |
| 1289 | 1300 | } |
| 1290 | 1301 | |
| 1291 | 1302 | ret = iio_device_register(indio_dev); |
| @@ -1418,6 +1429,7 @@ static const struct dev_pm_ops kxcjk1013_pm_ops = { · 126 unmodified lines | ||
| 1418 | 1429 | static const struct acpi_device_id kx_acpi_match[] = { |
| 1419 | 1430 | {"KXCJ1013", KXCJK1013}, |
| 1420 | 1431 | {"KXCJ1008", KXCJ91008}, |
| 1432 | + {"KXCJ9000", KXCJ91008}, | |
| 1421 | 1433 | {"KXTJ1009", KXTJ21009}, |
| 1422 | 1434 | {"SMO8500", KXCJ91008}, |
| 1423 | 1435 | { }, |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | * |
| 10 | 10 | * 7-bit I2C slave address 0x1c/0x1d (pin selectable) |
| 11 | 11 | * |
| 12 | − * TODO: interrupt, thresholding, orientation / freefall events, autosleep | |
| 12 | + * TODO: orientation / freefall events, autosleep | |
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | 15 | #include <linux/module.h> |
| @@ -18,20 +18,42 @@ · 2 unmodified lines | ||
| 18 | 18 | #include <linux/iio/sysfs.h> |
| 19 | 19 | #include <linux/iio/trigger_consumer.h> |
| 20 | 20 | #include <linux/iio/buffer.h> |
| 21 | +#include <linux/iio/trigger.h> | |
| 22 | +#include <linux/iio/trigger_consumer.h> | |
| 21 | 23 | #include <linux/iio/triggered_buffer.h> |
| 24 | +#include <linux/iio/events.h> | |
| 22 | 25 | #include <linux/delay.h> |
| 23 | 26 | |
| 24 | 27 | #define MMA8452_STATUS 0x00 |
| 25 | 28 | #define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */ |
| 26 | 29 | #define MMA8452_OUT_Y 0x03 |
| 27 | 30 | #define MMA8452_OUT_Z 0x05 |
| 31 | +#define MMA8452_INT_SRC 0x0c | |
| 28 | 32 | #define MMA8452_WHO_AM_I 0x0d |
| 29 | 33 | #define MMA8452_DATA_CFG 0x0e |
| 34 | +#define MMA8452_HP_FILTER_CUTOFF 0x0f | |
| 35 | +#define MMA8452_HP_FILTER_CUTOFF_SEL_MASK (BIT(0) | BIT(1)) | |
| 36 | +#define MMA8452_TRANSIENT_CFG 0x1d | |
| 37 | +#define MMA8452_TRANSIENT_CFG_ELE BIT(4) | |
| 38 | +#define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1) | |
| 39 | +#define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0) | |
| 40 | +#define MMA8452_TRANSIENT_SRC 0x1e | |
| 41 | +#define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1) | |
| 42 | +#define MMA8452_TRANSIENT_SRC_YTRANSE BIT(3) | |
| 43 | +#define MMA8452_TRANSIENT_SRC_ZTRANSE BIT(5) | |
| 44 | +#define MMA8452_TRANSIENT_THS 0x1f | |
| 45 | +#define MMA8452_TRANSIENT_THS_MASK 0x7f | |
| 46 | +#define MMA8452_TRANSIENT_COUNT 0x20 | |
| 30 | 47 | #define MMA8452_OFF_X 0x2f |
| 31 | 48 | #define MMA8452_OFF_Y 0x30 |
| 32 | 49 | #define MMA8452_OFF_Z 0x31 |
| 33 | 50 | #define MMA8452_CTRL_REG1 0x2a |
| 34 | 51 | #define MMA8452_CTRL_REG2 0x2b |
| 52 | +#define MMA8452_CTRL_REG2_RST BIT(6) | |
| 53 | +#define MMA8452_CTRL_REG4 0x2d | |
| 54 | +#define MMA8452_CTRL_REG5 0x2e | |
| 55 | + | |
| 56 | +#define MMA8452_MAX_REG 0x31 | |
| 35 | 57 | |
| 36 | 58 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) |
| 37 | 59 | |
| @@ -44,6 +66,10 @@ · 6 unmodified lines | ||
| 44 | 66 | #define MMA8452_DATA_CFG_FS_2G 0 |
| 45 | 67 | #define MMA8452_DATA_CFG_FS_4G 1 |
| 46 | 68 | #define MMA8452_DATA_CFG_FS_8G 2 |
| 69 | +#define MMA8452_DATA_CFG_HPF_MASK BIT(4) | |
| 70 | + | |
| 71 | +#define MMA8452_INT_DRDY BIT(0) | |
| 72 | +#define MMA8452_INT_TRANS BIT(5) | |
| 47 | 73 | |
| 48 | 74 | #define MMA8452_DEVICE_ID 0x2a |
| 49 | 75 | |
| @@ -106,6 +132,12 @@ static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n, · 56 unmodified lines | ||
| 106 | 132 | return -EINVAL; |
| 107 | 133 | } |
| 108 | 134 | |
| 135 | +static int mma8452_get_odr_index(struct mma8452_data *data) | |
| 136 | +{ | |
| 137 | + return (data->ctrl_reg1 & MMA8452_CTRL_DR_MASK) >> | |
| 138 | + MMA8452_CTRL_DR_SHIFT; | |
| 139 | +} | |
| 140 | + | |
| 109 | 141 | static const int mma8452_samp_freq[8][2] = { |
| 110 | 142 | {800, 0}, {400, 0}, {200, 0}, {100, 0}, {50, 0}, {12, 500000}, |
| 111 | 143 | {6, 250000}, {1, 560000} |
| @@ -121,6 +153,30 @@ static const int mma8452_scales[3][2] = { · 9 unmodified lines | ||
| 121 | 153 | {0, 9577}, {0, 19154}, {0, 38307} |
| 122 | 154 | }; |
| 123 | 155 | |
| 156 | +/* Datasheet table 35 (step time vs sample frequency) */ | |
| 157 | +static const int mma8452_transient_time_step_us[8] = { | |
| 158 | + 1250, | |
| 159 | + 2500, | |
| 160 | + 5000, | |
| 161 | + 10000, | |
| 162 | + 20000, | |
| 163 | + 20000, | |
| 164 | + 20000, | |
| 165 | + 20000 | |
| 166 | +}; | |
| 167 | + | |
| 168 | +/* Datasheet table 18 (normal mode) */ | |
| 169 | +static const int mma8452_hp_filter_cutoff[8][4][2] = { | |
| 170 | + { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 800 Hz sample */ | |
| 171 | + { {16, 0}, {8, 0}, {4, 0}, {2, 0} }, /* 400 Hz sample */ | |
| 172 | + { {8, 0}, {4, 0}, {2, 0}, {1, 0} }, /* 200 Hz sample */ | |
| 173 | + { {4, 0}, {2, 0}, {1, 0}, {0, 500000} }, /* 100 Hz sample */ | |
| 174 | + { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 50 Hz sample */ | |
| 175 | + { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 12.5 Hz sample */ | |
| 176 | + { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} }, /* 6.25 Hz sample */ | |
| 177 | + { {2, 0}, {1, 0}, {0, 500000}, {0, 250000} } /* 1.56 Hz sample */ | |
| 178 | +}; | |
| 179 | + | |
| 124 | 180 | static ssize_t mma8452_show_samp_freq_avail(struct device *dev, |
| 125 | 181 | struct device_attribute *attr, char *buf) |
| 126 | 182 | { |
| @@ -135,9 +191,23 @@ static ssize_t mma8452_show_scale_avail(struct device *dev, · 8 unmodified lines | ||
| 135 | 191 | ARRAY_SIZE(mma8452_scales)); |
| 136 | 192 | } |
| 137 | 193 | |
| 194 | +static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev, | |
| 195 | + struct device_attribute *attr, | |
| 196 | + char *buf) | |
| 197 | +{ | |
| 198 | + struct iio_dev *indio_dev = dev_to_iio_dev(dev); | |
| 199 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 200 | + int i = mma8452_get_odr_index(data); | |
| 201 | + | |
| 202 | + return mma8452_show_int_plus_micros(buf, mma8452_hp_filter_cutoff[i], | |
| 203 | + ARRAY_SIZE(mma8452_hp_filter_cutoff[0])); | |
| 204 | +} | |
| 205 | + | |
| 138 | 206 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail); |
| 139 | 207 | static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, |
| 140 | 208 | mma8452_show_scale_avail, NULL, 0); |
| 209 | +static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available, | |
| 210 | + S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0); | |
| 141 | 211 | |
| 142 | 212 | static int mma8452_get_samp_freq_index(struct mma8452_data *data, |
| 143 | 213 | int val, int val2) |
| @@ -153,6 +223,31 @@ static int mma8452_get_scale_index(struct mma8452_data *data, · 9 unmodified lines | ||
| 153 | 223 | ARRAY_SIZE(mma8452_scales), val, val2); |
| 154 | 224 | } |
| 155 | 225 | |
| 226 | +static int mma8452_get_hp_filter_index(struct mma8452_data *data, | |
| 227 | + int val, int val2) | |
| 228 | +{ | |
| 229 | + int i = mma8452_get_odr_index(data); | |
| 230 | + | |
| 231 | + return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i], | |
| 232 | + ARRAY_SIZE(mma8452_scales[0]), val, val2); | |
| 233 | +} | |
| 234 | + | |
| 235 | +static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz) | |
| 236 | +{ | |
| 237 | + int i, ret; | |
| 238 | + | |
| 239 | + ret = i2c_smbus_read_byte_data(data->client, MMA8452_HP_FILTER_CUTOFF); | |
| 240 | + if (ret < 0) | |
| 241 | + return ret; | |
| 242 | + | |
| 243 | + i = mma8452_get_odr_index(data); | |
| 244 | + ret &= MMA8452_HP_FILTER_CUTOFF_SEL_MASK; | |
| 245 | + *hz = mma8452_hp_filter_cutoff[i][ret][0]; | |
| 246 | + *uHz = mma8452_hp_filter_cutoff[i][ret][1]; | |
| 247 | + | |
| 248 | + return 0; | |
| 249 | +} | |
| 250 | + | |
| 156 | 251 | static int mma8452_read_raw(struct iio_dev *indio_dev, |
| 157 | 252 | struct iio_chan_spec const *chan, |
| 158 | 253 | int *val, int *val2, long mask) |
| @@ -180,8 +275,7 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, · 21 unmodified lines | ||
| 180 | 275 | *val2 = mma8452_scales[i][1]; |
| 181 | 276 | return IIO_VAL_INT_PLUS_MICRO; |
| 182 | 277 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 183 | − i = (data->ctrl_reg1 & MMA8452_CTRL_DR_MASK) >> | |
| 184 | − MMA8452_CTRL_DR_SHIFT; | |
| 278 | + i = mma8452_get_odr_index(data); | |
| 185 | 279 | *val = mma8452_samp_freq[i][0]; |
| 186 | 280 | *val2 = mma8452_samp_freq[i][1]; |
| 187 | 281 | return IIO_VAL_INT_PLUS_MICRO; |
| @@ -192,6 +286,16 @@ static int mma8452_read_raw(struct iio_dev *indio_dev, · 4 unmodified lines | ||
| 192 | 286 | return ret; |
| 193 | 287 | *val = sign_extend32(ret, 7); |
| 194 | 288 | return IIO_VAL_INT; |
| 289 | + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: | |
| 290 | + if (data->data_cfg & MMA8452_DATA_CFG_HPF_MASK) { | |
| 291 | + ret = mma8452_read_hp_filter(data, val, val2); | |
| 292 | + if (ret < 0) | |
| 293 | + return ret; | |
| 294 | + } else { | |
| 295 | + *val = 0; | |
| 296 | + *val2 = 0; | |
| 297 | + } | |
| 298 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 195 | 299 | } |
| 196 | 300 | return -EINVAL; |
| 197 | 301 | } |
| @@ -233,12 +337,31 @@ fail: · 35 unmodified lines | ||
| 233 | 337 | return ret; |
| 234 | 338 | } |
| 235 | 339 | |
| 340 | +static int mma8452_set_hp_filter_frequency(struct mma8452_data *data, | |
| 341 | + int val, int val2) | |
| 342 | +{ | |
| 343 | + int i, reg; | |
| 344 | + | |
| 345 | + i = mma8452_get_hp_filter_index(data, val, val2); | |
| 346 | + if (i < 0) | |
| 347 | + return -EINVAL; | |
| 348 | + | |
| 349 | + reg = i2c_smbus_read_byte_data(data->client, | |
| 350 | + MMA8452_HP_FILTER_CUTOFF); | |
| 351 | + if (reg < 0) | |
| 352 | + return reg; | |
| 353 | + reg &= ~MMA8452_HP_FILTER_CUTOFF_SEL_MASK; | |
| 354 | + reg |= i; | |
| 355 | + | |
| 356 | + return mma8452_change_config(data, MMA8452_HP_FILTER_CUTOFF, reg); | |
| 357 | +} | |
| 358 | + | |
| 236 | 359 | static int mma8452_write_raw(struct iio_dev *indio_dev, |
| 237 | 360 | struct iio_chan_spec const *chan, |
| 238 | 361 | int val, int val2, long mask) |
| 239 | 362 | { |
| 240 | 363 | struct mma8452_data *data = iio_priv(indio_dev); |
| 241 | − int i; | |
| 364 | + int i, ret; | |
| 242 | 365 | |
| 243 | 366 | if (iio_buffer_enabled(indio_dev)) |
| 244 | 367 | return -EBUSY; |
| @@ -266,11 +389,217 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, · 21 unmodified lines | ||
| 266 | 389 | return -EINVAL; |
| 267 | 390 | return mma8452_change_config(data, MMA8452_OFF_X + |
| 268 | 391 | chan->scan_index, val); |
| 392 | + | |
| 393 | + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: | |
| 394 | + if (val == 0 && val2 == 0) { | |
| 395 | + data->data_cfg &= ~MMA8452_DATA_CFG_HPF_MASK; | |
| 396 | + } else { | |
| 397 | + data->data_cfg |= MMA8452_DATA_CFG_HPF_MASK; | |
| 398 | + ret = mma8452_set_hp_filter_frequency(data, val, val2); | |
| 399 | + if (ret < 0) | |
| 400 | + return ret; | |
| 401 | + } | |
| 402 | + return mma8452_change_config(data, MMA8452_DATA_CFG, | |
| 403 | + data->data_cfg); | |
| 404 | + | |
| 405 | + default: | |
| 406 | + return -EINVAL; | |
| 407 | + } | |
| 408 | +} | |
| 409 | + | |
| 410 | +static int mma8452_read_thresh(struct iio_dev *indio_dev, | |
| 411 | + const struct iio_chan_spec *chan, | |
| 412 | + enum iio_event_type type, | |
| 413 | + enum iio_event_direction dir, | |
| 414 | + enum iio_event_info info, | |
| 415 | + int *val, int *val2) | |
| 416 | +{ | |
| 417 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 418 | + int ret, us; | |
| 419 | + | |
| 420 | + switch (info) { | |
| 421 | + case IIO_EV_INFO_VALUE: | |
| 422 | + ret = i2c_smbus_read_byte_data(data->client, | |
| 423 | + MMA8452_TRANSIENT_THS); | |
| 424 | + if (ret < 0) | |
| 425 | + return ret; | |
| 426 | + | |
| 427 | + *val = ret & MMA8452_TRANSIENT_THS_MASK; | |
| 428 | + return IIO_VAL_INT; | |
| 429 | + | |
| 430 | + case IIO_EV_INFO_PERIOD: | |
| 431 | + ret = i2c_smbus_read_byte_data(data->client, | |
| 432 | + MMA8452_TRANSIENT_COUNT); | |
| 433 | + if (ret < 0) | |
| 434 | + return ret; | |
| 435 | + | |
| 436 | + us = ret * mma8452_transient_time_step_us[ | |
| 437 | + mma8452_get_odr_index(data)]; | |
| 438 | + *val = us / USEC_PER_SEC; | |
| 439 | + *val2 = us % USEC_PER_SEC; | |
| 440 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 441 | + | |
| 442 | + case IIO_EV_INFO_HIGH_PASS_FILTER_3DB: | |
| 443 | + ret = i2c_smbus_read_byte_data(data->client, | |
| 444 | + MMA8452_TRANSIENT_CFG); | |
| 445 | + if (ret < 0) | |
| 446 | + return ret; | |
| 447 | + | |
| 448 | + if (ret & MMA8452_TRANSIENT_CFG_HPF_BYP) { | |
| 449 | + *val = 0; | |
| 450 | + *val2 = 0; | |
| 451 | + } else { | |
| 452 | + ret = mma8452_read_hp_filter(data, val, val2); | |
| 453 | + if (ret < 0) | |
| 454 | + return ret; | |
| 455 | + } | |
| 456 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 457 | + | |
| 458 | + default: | |
| 459 | + return -EINVAL; | |
| 460 | + } | |
| 461 | +} | |
| 462 | + | |
| 463 | +static int mma8452_write_thresh(struct iio_dev *indio_dev, | |
| 464 | + const struct iio_chan_spec *chan, | |
| 465 | + enum iio_event_type type, | |
| 466 | + enum iio_event_direction dir, | |
| 467 | + enum iio_event_info info, | |
| 468 | + int val, int val2) | |
| 469 | +{ | |
| 470 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 471 | + int ret, reg, steps; | |
| 472 | + | |
| 473 | + switch (info) { | |
| 474 | + case IIO_EV_INFO_VALUE: | |
| 475 | + return mma8452_change_config(data, MMA8452_TRANSIENT_THS, | |
| 476 | + val & MMA8452_TRANSIENT_THS_MASK); | |
| 477 | + | |
| 478 | + case IIO_EV_INFO_PERIOD: | |
| 479 | + steps = (val * USEC_PER_SEC + val2) / | |
| 480 | + mma8452_transient_time_step_us[ | |
| 481 | + mma8452_get_odr_index(data)]; | |
| 482 | + | |
| 483 | + if (steps > 0xff) | |
| 484 | + return -EINVAL; | |
| 485 | + | |
| 486 | + return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT, | |
| 487 | + steps); | |
| 488 | + case IIO_EV_INFO_HIGH_PASS_FILTER_3DB: | |
| 489 | + reg = i2c_smbus_read_byte_data(data->client, | |
| 490 | + MMA8452_TRANSIENT_CFG); | |
| 491 | + if (reg < 0) | |
| 492 | + return reg; | |
| 493 | + | |
| 494 | + if (val == 0 && val2 == 0) { | |
| 495 | + reg |= MMA8452_TRANSIENT_CFG_HPF_BYP; | |
| 496 | + } else { | |
| 497 | + reg &= ~MMA8452_TRANSIENT_CFG_HPF_BYP; | |
| 498 | + ret = mma8452_set_hp_filter_frequency(data, val, val2); | |
| 499 | + if (ret < 0) | |
| 500 | + return ret; | |
| 501 | + } | |
| 502 | + return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg); | |
| 503 | + | |
| 269 | 504 | default: |
| 270 | 505 | return -EINVAL; |
| 271 | 506 | } |
| 272 | 507 | } |
| 273 | 508 | |
| 509 | +static int mma8452_read_event_config(struct iio_dev *indio_dev, | |
| 510 | + const struct iio_chan_spec *chan, | |
| 511 | + enum iio_event_type type, | |
| 512 | + enum iio_event_direction dir) | |
| 513 | +{ | |
| 514 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 515 | + int ret; | |
| 516 | + | |
| 517 | + ret = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG); | |
| 518 | + if (ret < 0) | |
| 519 | + return ret; | |
| 520 | + | |
| 521 | + return ret & MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index) ? 1 : 0; | |
| 522 | +} | |
| 523 | + | |
| 524 | +static int mma8452_write_event_config(struct iio_dev *indio_dev, | |
| 525 | + const struct iio_chan_spec *chan, | |
| 526 | + enum iio_event_type type, | |
| 527 | + enum iio_event_direction dir, | |
| 528 | + int state) | |
| 529 | +{ | |
| 530 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 531 | + int val; | |
| 532 | + | |
| 533 | + val = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_CFG); | |
| 534 | + if (val < 0) | |
| 535 | + return val; | |
| 536 | + | |
| 537 | + if (state) | |
| 538 | + val |= MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index); | |
| 539 | + else | |
| 540 | + val &= ~MMA8452_TRANSIENT_CFG_CHAN(chan->scan_index); | |
| 541 | + | |
| 542 | + val |= MMA8452_TRANSIENT_CFG_ELE; | |
| 543 | + | |
| 544 | + return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, val); | |
| 545 | +} | |
| 546 | + | |
| 547 | +static void mma8452_transient_interrupt(struct iio_dev *indio_dev) | |
| 548 | +{ | |
| 549 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 550 | + s64 ts = iio_get_time_ns(); | |
| 551 | + int src; | |
| 552 | + | |
| 553 | + src = i2c_smbus_read_byte_data(data->client, MMA8452_TRANSIENT_SRC); | |
| 554 | + if (src < 0) | |
| 555 | + return; | |
| 556 | + | |
| 557 | + if (src & MMA8452_TRANSIENT_SRC_XTRANSE) | |
| 558 | + iio_push_event(indio_dev, | |
| 559 | + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X, | |
| 560 | + IIO_EV_TYPE_THRESH, | |
| 561 | + IIO_EV_DIR_RISING), | |
| 562 | + ts); | |
| 563 | + | |
| 564 | + if (src & MMA8452_TRANSIENT_SRC_YTRANSE) | |
| 565 | + iio_push_event(indio_dev, | |
| 566 | + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y, | |
| 567 | + IIO_EV_TYPE_THRESH, | |
| 568 | + IIO_EV_DIR_RISING), | |
| 569 | + ts); | |
| 570 | + | |
| 571 | + if (src & MMA8452_TRANSIENT_SRC_ZTRANSE) | |
| 572 | + iio_push_event(indio_dev, | |
| 573 | + IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z, | |
| 574 | + IIO_EV_TYPE_THRESH, | |
| 575 | + IIO_EV_DIR_RISING), | |
| 576 | + ts); | |
| 577 | +} | |
| 578 | + | |
| 579 | +static irqreturn_t mma8452_interrupt(int irq, void *p) | |
| 580 | +{ | |
| 581 | + struct iio_dev *indio_dev = p; | |
| 582 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 583 | + int ret = IRQ_NONE; | |
| 584 | + int src; | |
| 585 | + | |
| 586 | + src = i2c_smbus_read_byte_data(data->client, MMA8452_INT_SRC); | |
| 587 | + if (src < 0) | |
| 588 | + return IRQ_NONE; | |
| 589 | + | |
| 590 | + if (src & MMA8452_INT_DRDY) { | |
| 591 | + iio_trigger_poll_chained(indio_dev->trig); | |
| 592 | + ret = IRQ_HANDLED; | |
| 593 | + } | |
| 594 | + | |
| 595 | + if (src & MMA8452_INT_TRANS) { | |
| 596 | + mma8452_transient_interrupt(indio_dev); | |
| 597 | + ret = IRQ_HANDLED; | |
| 598 | + } | |
| 599 | + | |
| 600 | + return ret; | |
| 601 | +} | |
| 602 | + | |
| 274 | 603 | static irqreturn_t mma8452_trigger_handler(int irq, void *p) |
| 275 | 604 | { |
| 276 | 605 | struct iio_poll_func *pf = p; |
| @@ -291,6 +620,55 @@ done: · 14 unmodified lines | ||
| 291 | 620 | return IRQ_HANDLED; |
| 292 | 621 | } |
| 293 | 622 | |
| 623 | +static int mma8452_reg_access_dbg(struct iio_dev *indio_dev, | |
| 624 | + unsigned reg, unsigned writeval, | |
| 625 | + unsigned *readval) | |
| 626 | +{ | |
| 627 | + int ret; | |
| 628 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 629 | + | |
| 630 | + if (reg > MMA8452_MAX_REG) | |
| 631 | + return -EINVAL; | |
| 632 | + | |
| 633 | + if (!readval) | |
| 634 | + return mma8452_change_config(data, reg, writeval); | |
| 635 | + | |
| 636 | + ret = i2c_smbus_read_byte_data(data->client, reg); | |
| 637 | + if (ret < 0) | |
| 638 | + return ret; | |
| 639 | + | |
| 640 | + *readval = ret; | |
| 641 | + | |
| 642 | + return 0; | |
| 643 | +} | |
| 644 | + | |
| 645 | +static const struct iio_event_spec mma8452_transient_event[] = { | |
| 646 | + { | |
| 647 | + .type = IIO_EV_TYPE_THRESH, | |
| 648 | + .dir = IIO_EV_DIR_RISING, | |
| 649 | + .mask_separate = BIT(IIO_EV_INFO_ENABLE), | |
| 650 | + .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) | | |
| 651 | + BIT(IIO_EV_INFO_PERIOD) | | |
| 652 | + BIT(IIO_EV_INFO_HIGH_PASS_FILTER_3DB) | |
| 653 | + }, | |
| 654 | +}; | |
| 655 | + | |
| 656 | +/* | |
| 657 | + * Threshold is configured in fixed 8G/127 steps regardless of | |
| 658 | + * currently selected scale for measurement. | |
| 659 | + */ | |
| 660 | +static IIO_CONST_ATTR_NAMED(accel_transient_scale, in_accel_scale, "0.617742"); | |
| 661 | + | |
| 662 | +static struct attribute *mma8452_event_attributes[] = { | |
| 663 | + &iio_const_attr_accel_transient_scale.dev_attr.attr, | |
| 664 | + NULL, | |
| 665 | +}; | |
| 666 | + | |
| 667 | +static struct attribute_group mma8452_event_attribute_group = { | |
| 668 | + .attrs = mma8452_event_attributes, | |
| 669 | + .name = "events", | |
| 670 | +}; | |
| 671 | + | |
| 294 | 672 | #define MMA8452_CHANNEL(axis, idx) { \ |
| 295 | 673 | .type = IIO_ACCEL, \ |
| 296 | 674 | .modified = 1, \ |
| @@ -298,7 +676,8 @@ done: · 1 unmodified line | ||
| 298 | 676 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
| 299 | 677 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
| 300 | 678 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ |
| 301 | − BIT(IIO_CHAN_INFO_SCALE), \ | |
| 679 | + BIT(IIO_CHAN_INFO_SCALE) | \ | |
| 680 | + BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \ | |
| 302 | 681 | .scan_index = idx, \ |
| 303 | 682 | .scan_type = { \ |
| 304 | 683 | .sign = 's', \ |
| @@ -307,6 +686,8 @@ done: · 2 unmodified lines | ||
| 307 | 686 | .shift = 4, \ |
| 308 | 687 | .endianness = IIO_BE, \ |
| 309 | 688 | }, \ |
| 689 | + .event_spec = mma8452_transient_event, \ | |
| 690 | + .num_event_specs = ARRAY_SIZE(mma8452_transient_event), \ | |
| 310 | 691 | } |
| 311 | 692 | |
| 312 | 693 | static const struct iio_chan_spec mma8452_channels[] = { |
| @@ -319,6 +700,7 @@ static const struct iio_chan_spec mma8452_channels[] = { · 6 unmodified lines | ||
| 319 | 700 | static struct attribute *mma8452_attributes[] = { |
| 320 | 701 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
| 321 | 702 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, |
| 703 | + &iio_dev_attr_in_accel_filter_high_pass_3db_frequency_available.dev_attr.attr, | |
| 322 | 704 | NULL |
| 323 | 705 | }; |
| 324 | 706 | |
| @@ -330,11 +712,107 @@ static const struct iio_info mma8452_info = { · 5 unmodified lines | ||
| 330 | 712 | .attrs = &mma8452_group, |
| 331 | 713 | .read_raw = &mma8452_read_raw, |
| 332 | 714 | .write_raw = &mma8452_write_raw, |
| 715 | + .event_attrs = &mma8452_event_attribute_group, | |
| 716 | + .read_event_value = &mma8452_read_thresh, | |
| 717 | + .write_event_value = &mma8452_write_thresh, | |
| 718 | + .read_event_config = &mma8452_read_event_config, | |
| 719 | + .write_event_config = &mma8452_write_event_config, | |
| 720 | + .debugfs_reg_access = &mma8452_reg_access_dbg, | |
| 333 | 721 | .driver_module = THIS_MODULE, |
| 334 | 722 | }; |
| 335 | 723 | |
| 336 | 724 | static const unsigned long mma8452_scan_masks[] = {0x7, 0}; |
| 337 | 725 | |
| 726 | +static int mma8452_data_rdy_trigger_set_state(struct iio_trigger *trig, | |
| 727 | + bool state) | |
| 728 | +{ | |
| 729 | + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | |
| 730 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 731 | + int reg; | |
| 732 | + | |
| 733 | + reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG4); | |
| 734 | + if (reg < 0) | |
| 735 | + return reg; | |
| 736 | + | |
| 737 | + if (state) | |
| 738 | + reg |= MMA8452_INT_DRDY; | |
| 739 | + else | |
| 740 | + reg &= ~MMA8452_INT_DRDY; | |
| 741 | + | |
| 742 | + return mma8452_change_config(data, MMA8452_CTRL_REG4, reg); | |
| 743 | +} | |
| 744 | + | |
| 745 | +static int mma8452_validate_device(struct iio_trigger *trig, | |
| 746 | + struct iio_dev *indio_dev) | |
| 747 | +{ | |
| 748 | + struct iio_dev *indio = iio_trigger_get_drvdata(trig); | |
| 749 | + | |
| 750 | + if (indio != indio_dev) | |
| 751 | + return -EINVAL; | |
| 752 | + | |
| 753 | + return 0; | |
| 754 | +} | |
| 755 | + | |
| 756 | +static const struct iio_trigger_ops mma8452_trigger_ops = { | |
| 757 | + .set_trigger_state = mma8452_data_rdy_trigger_set_state, | |
| 758 | + .validate_device = mma8452_validate_device, | |
| 759 | + .owner = THIS_MODULE, | |
| 760 | +}; | |
| 761 | + | |
| 762 | +static int mma8452_trigger_setup(struct iio_dev *indio_dev) | |
| 763 | +{ | |
| 764 | + struct mma8452_data *data = iio_priv(indio_dev); | |
| 765 | + struct iio_trigger *trig; | |
| 766 | + int ret; | |
| 767 | + | |
| 768 | + trig = devm_iio_trigger_alloc(&data->client->dev, "%s-dev%d", | |
| 769 | + indio_dev->name, | |
| 770 | + indio_dev->id); | |
| 771 | + if (!trig) | |
| 772 | + return -ENOMEM; | |
| 773 | + | |
| 774 | + trig->dev.parent = &data->client->dev; | |
| 775 | + trig->ops = &mma8452_trigger_ops; | |
| 776 | + iio_trigger_set_drvdata(trig, indio_dev); | |
| 777 | + | |
| 778 | + ret = iio_trigger_register(trig); | |
| 779 | + if (ret) | |
| 780 | + return ret; | |
| 781 | + | |
| 782 | + indio_dev->trig = trig; | |
| 783 | + return 0; | |
| 784 | +} | |
| 785 | + | |
| 786 | +static void mma8452_trigger_cleanup(struct iio_dev *indio_dev) | |
| 787 | +{ | |
| 788 | + if (indio_dev->trig) | |
| 789 | + iio_trigger_unregister(indio_dev->trig); | |
| 790 | +} | |
| 791 | + | |
| 792 | +static int mma8452_reset(struct i2c_client *client) | |
| 793 | +{ | |
| 794 | + int i; | |
| 795 | + int ret; | |
| 796 | + | |
| 797 | + ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG2, | |
| 798 | + MMA8452_CTRL_REG2_RST); | |
| 799 | + if (ret < 0) | |
| 800 | + return ret; | |
| 801 | + | |
| 802 | + for (i = 0; i < 10; i++) { | |
| 803 | + usleep_range(100, 200); | |
| 804 | + ret = i2c_smbus_read_byte_data(client, MMA8452_CTRL_REG2); | |
| 805 | + if (ret == -EIO) | |
| 806 | + continue; /* I2C comm reset */ | |
| 807 | + if (ret < 0) | |
| 808 | + return ret; | |
| 809 | + if (!(ret & MMA8452_CTRL_REG2_RST)) | |
| 810 | + return 0; | |
| 811 | + } | |
| 812 | + | |
| 813 | + return -ETIMEDOUT; | |
| 814 | +} | |
| 815 | + | |
| 338 | 816 | static int mma8452_probe(struct i2c_client *client, |
| 339 | 817 | const struct i2c_device_id *id) |
| 340 | 818 | { |
| @@ -365,10 +843,7 @@ static int mma8452_probe(struct i2c_client *client, · 24 unmodified lines | ||
| 365 | 843 | indio_dev->num_channels = ARRAY_SIZE(mma8452_channels); |
| 366 | 844 | indio_dev->available_scan_masks = mma8452_scan_masks; |
| 367 | 845 | |
| 368 | − data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | | |
| 369 | − (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT); | |
| 370 | − ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1, | |
| 371 | − data->ctrl_reg1); | |
| 846 | + ret = mma8452_reset(client); | |
| 372 | 847 | if (ret < 0) |
| 373 | 848 | return ret; |
| 374 | 849 | |
| @@ -378,18 +853,77 @@ static int mma8452_probe(struct i2c_client *client, · 3 unmodified lines | ||
| 378 | 853 | if (ret < 0) |
| 379 | 854 | return ret; |
| 380 | 855 | |
| 856 | + /* | |
| 857 | + * By default set transient threshold to max to avoid events if | |
| 858 | + * enabling without configuring threshold. | |
| 859 | + */ | |
| 860 | + ret = i2c_smbus_write_byte_data(client, MMA8452_TRANSIENT_THS, | |
| 861 | + MMA8452_TRANSIENT_THS_MASK); | |
| 862 | + if (ret < 0) | |
| 863 | + return ret; | |
| 864 | + | |
| 865 | + if (client->irq) { | |
| 866 | + /* | |
| 867 | + * Although we enable the transient interrupt source once and | |
| 868 | + * for all here the transient event detection itself is not | |
| 869 | + * enabled until userspace asks for it by | |
| 870 | + * mma8452_write_event_config() | |
| 871 | + */ | |
| 872 | + int supported_interrupts = MMA8452_INT_DRDY | MMA8452_INT_TRANS; | |
| 873 | + int enabled_interrupts = MMA8452_INT_TRANS; | |
| 874 | + | |
| 875 | + /* Assume wired to INT1 pin */ | |
| 876 | + ret = i2c_smbus_write_byte_data(client, | |
| 877 | + MMA8452_CTRL_REG5, | |
| 878 | + supported_interrupts); | |
| 879 | + if (ret < 0) | |
| 880 | + return ret; | |
| 881 | + | |
| 882 | + ret = i2c_smbus_write_byte_data(client, | |
| 883 | + MMA8452_CTRL_REG4, | |
| 884 | + enabled_interrupts); | |
| 885 | + if (ret < 0) | |
| 886 | + return ret; | |
| 887 | + | |
| 888 | + ret = mma8452_trigger_setup(indio_dev); | |
| 889 | + if (ret < 0) | |
| 890 | + return ret; | |
| 891 | + } | |
| 892 | + | |
| 893 | + data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | | |
| 894 | + (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT); | |
| 895 | + ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1, | |
| 896 | + data->ctrl_reg1); | |
| 897 | + if (ret < 0) | |
| 898 | + goto trigger_cleanup; | |
| 899 | + | |
| 381 | 900 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
| 382 | 901 | mma8452_trigger_handler, NULL); |
| 383 | 902 | if (ret < 0) |
| 384 | − return ret; | |
| 903 | + goto trigger_cleanup; | |
| 904 | + | |
| 905 | + if (client->irq) { | |
| 906 | + ret = devm_request_threaded_irq(&client->dev, | |
| 907 | + client->irq, | |
| 908 | + NULL, mma8452_interrupt, | |
| 909 | + IRQF_TRIGGER_LOW | IRQF_ONESHOT, | |
| 910 | + client->name, indio_dev); | |
| 911 | + if (ret) | |
| 912 | + goto buffer_cleanup; | |
| 913 | + } | |
| 385 | 914 | |
| 386 | 915 | ret = iio_device_register(indio_dev); |
| 387 | 916 | if (ret < 0) |
| 388 | 917 | goto buffer_cleanup; |
| 918 | + | |
| 389 | 919 | return 0; |
| 390 | 920 | |
| 391 | 921 | buffer_cleanup: |
| 392 | 922 | iio_triggered_buffer_cleanup(indio_dev); |
| 923 | + | |
| 924 | +trigger_cleanup: | |
| 925 | + mma8452_trigger_cleanup(indio_dev); | |
| 926 | + | |
| 393 | 927 | return ret; |
| 394 | 928 | } |
| 395 | 929 | |
| @@ -399,6 +933,7 @@ static int mma8452_remove(struct i2c_client *client) · 3 unmodified lines | ||
| 399 | 933 | |
| 400 | 934 | iio_device_unregister(indio_dev); |
| 401 | 935 | iio_triggered_buffer_cleanup(indio_dev); |
| 936 | + mma8452_trigger_cleanup(indio_dev); | |
| 402 | 937 | mma8452_standby(iio_priv(indio_dev)); |
| 403 | 938 | |
| 404 | 939 | return 0; |
| @@ -374,7 +374,7 @@ EXPORT_SYMBOL(mma9551_read_status_word); · 373 unmodified lines | ||
| 374 | 374 | * @app_id: Application ID |
| 375 | 375 | * @reg: Application register |
| 376 | 376 | * @len: Length of array to read in bytes |
| 377 | − * @val: Array of words to read | |
| 377 | + * @buf: Array of words to read | |
| 378 | 378 | * |
| 379 | 379 | * Read multiple configuration registers (word-sized registers). |
| 380 | 380 | * |
| @@ -414,7 +414,7 @@ EXPORT_SYMBOL(mma9551_read_config_words); · 33 unmodified lines | ||
| 414 | 414 | * @app_id: Application ID |
| 415 | 415 | * @reg: Application register |
| 416 | 416 | * @len: Length of array to read in bytes |
| 417 | − * @val: Array of words to read | |
| 417 | + * @buf: Array of words to read | |
| 418 | 418 | * |
| 419 | 419 | * Read multiple status registers (word-sized registers). |
| 420 | 420 | * |
| @@ -454,7 +454,7 @@ EXPORT_SYMBOL(mma9551_read_status_words); · 33 unmodified lines | ||
| 454 | 454 | * @app_id: Application ID |
| 455 | 455 | * @reg: Application register |
| 456 | 456 | * @len: Length of array to write in bytes |
| 457 | − * @val: Array of words to write | |
| 457 | + * @buf: Array of words to write | |
| 458 | 458 | * |
| 459 | 459 | * Write multiple configuration registers (word-sized registers). |
| 460 | 460 | * |
| @@ -800,7 +800,7 @@ EXPORT_SYMBOL(mma9551_read_accel_scale); · 339 unmodified lines | ||
| 800 | 800 | */ |
| 801 | 801 | int mma9551_app_reset(struct i2c_client *client, u32 app_mask) |
| 802 | 802 | { |
| 803 | − return mma9551_write_config_byte(client, MMA9551_APPID_RCS, | |
| 803 | + return mma9551_write_config_byte(client, MMA9551_APPID_RSC, | |
| 804 | 804 | MMA9551_RSC_RESET + |
| 805 | 805 | MMA9551_RSC_OFFSET(app_mask), |
| 806 | 806 | MMA9551_RSC_VAL(app_mask)); |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | ||
| 22 | 22 | #define MMA9551_APPID_TILT 0x0B |
| 23 | 23 | #define MMA9551_APPID_SLEEP_WAKE 0x12 |
| 24 | 24 | #define MMA9551_APPID_PEDOMETER 0x15 |
| 25 | −#define MMA9551_APPID_RCS 0x17 | |
| 25 | +#define MMA9551_APPID_RSC 0x17 | |
| 26 | 26 | #define MMA9551_APPID_NONE 0xff |
| 27 | 27 | |
| 28 | 28 | /* Reset/Suspend/Clear application app masks */ |
| @@ -63,8 +63,8 @@ · 62 unmodified lines | ||
| 63 | 63 | #define MMA9553_MASK_STATUS_STEPCHG BIT(13) |
| 64 | 64 | #define MMA9553_MASK_STATUS_ACTCHG BIT(12) |
| 65 | 65 | #define MMA9553_MASK_STATUS_SUSP BIT(11) |
| 66 | −#define MMA9553_MASK_STATUS_ACTIVITY (BIT(10) | BIT(9) | BIT(8)) | |
| 67 | −#define MMA9553_MASK_STATUS_VERSION 0x00FF | |
| 66 | +#define MMA9553_MASK_STATUS_ACTIVITY GENMASK(10, 8) | |
| 67 | +#define MMA9553_MASK_STATUS_VERSION GENMASK(7, 0) | |
| 68 | 68 | |
| 69 | 69 | #define MMA9553_REG_STEPCNT 0x02 |
| 70 | 70 | #define MMA9553_REG_DISTANCE 0x04 |
| @@ -76,14 +76,15 @@ · 5 unmodified lines | ||
| 76 | 76 | #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 |
| 77 | 77 | #define MMA9553_DEFAULT_GPIO_POLARITY 0 |
| 78 | 78 | |
| 79 | −/* Bitnum used for gpio configuration = bit number in high status byte */ | |
| 80 | −#define STATUS_TO_BITNUM(bit) (ffs(bit) - 9) | |
| 79 | +/* Bitnum used for GPIO configuration = bit number in high status byte */ | |
| 80 | +#define MMA9553_STATUS_TO_BITNUM(bit) (ffs(bit) - 9) | |
| 81 | +#define MMA9553_MAX_BITNUM MMA9553_STATUS_TO_BITNUM(BIT(16)) | |
| 81 | 82 | |
| 82 | 83 | #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ |
| 83 | 84 | |
| 84 | 85 | /* |
| 85 | 86 | * The internal activity level must be stable for ACTTHD samples before |
| 86 | − * ACTIVITY is updated.The ACTIVITY variable contains the current activity | |
| 87 | + * ACTIVITY is updated. The ACTIVITY variable contains the current activity | |
| 87 | 88 | * level and is updated every time a step is detected or once a second |
| 88 | 89 | * if there are no steps. |
| 89 | 90 | */ |
| @@ -351,11 +352,11 @@ static int mma9553_conf_gpio(struct mma9553_data *data) · 261 unmodified lines | ||
| 351 | 352 | * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. |
| 352 | 353 | */ |
| 353 | 354 | if (activity_enabled && ev_step_detect->enabled) |
| 354 | − bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); | |
| 355 | + bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_MRGFL); | |
| 355 | 356 | else if (ev_step_detect->enabled) |
| 356 | − bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); | |
| 357 | + bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_STEPCHG); | |
| 357 | 358 | else if (activity_enabled) |
| 358 | − bitnum = STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); | |
| 359 | + bitnum = MMA9553_STATUS_TO_BITNUM(MMA9553_MASK_STATUS_ACTCHG); | |
| 359 | 360 | else /* Reset */ |
| 360 | 361 | appid = MMA9551_APPID_NONE; |
| 361 | 362 | |
| @@ -363,9 +364,12 @@ static int mma9553_conf_gpio(struct mma9553_data *data) · 1 unmodified line | ||
| 363 | 364 | return 0; |
| 364 | 365 | |
| 365 | 366 | /* Save initial values for activity and stepcnt */ |
| 366 | − if (activity_enabled || ev_step_detect->enabled) | |
| 367 | − mma9553_read_activity_stepcnt(data, &data->activity, | |
| 368 | − &data->stepcnt); | |
| 367 | + if (activity_enabled || ev_step_detect->enabled) { | |
| 368 | + ret = mma9553_read_activity_stepcnt(data, &data->activity, | |
| 369 | + &data->stepcnt); | |
| 370 | + if (ret < 0) | |
| 371 | + return ret; | |
| 372 | + } | |
| 369 | 373 | |
| 370 | 374 | ret = mma9551_gpio_config(data->client, |
| 371 | 375 | MMA9553_DEFAULT_GPIO_PIN, |
| @@ -396,13 +400,13 @@ static int mma9553_init(struct mma9553_data *data) · 24 unmodified lines | ||
| 396 | 400 | sizeof(data->conf), (u16 *) &data->conf); |
| 397 | 401 | if (ret < 0) { |
| 398 | 402 | dev_err(&data->client->dev, |
| 399 | − "device is not MMA9553L: failed to read cfg regs\n"); | |
| 403 | + "failed to read configuration registers\n"); | |
| 400 | 404 | return ret; |
| 401 | 405 | } |
| 402 | 406 | |
| 403 | 407 | |
| 404 | − /* Reset gpio */ | |
| 405 | − data->gpio_bitnum = -1; | |
| 408 | + /* Reset GPIO */ | |
| 409 | + data->gpio_bitnum = MMA9553_MAX_BITNUM; | |
| 406 | 410 | ret = mma9553_conf_gpio(data); |
| 407 | 411 | if (ret < 0) |
| 408 | 412 | return ret; |
| @@ -436,6 +440,32 @@ static int mma9553_init(struct mma9553_data *data) · 27 unmodified lines | ||
| 436 | 440 | return mma9551_set_device_state(data->client, true); |
| 437 | 441 | } |
| 438 | 442 | |
| 443 | +static int mma9553_read_status_word(struct mma9553_data *data, u16 reg, | |
| 444 | + u16 *tmp) | |
| 445 | +{ | |
| 446 | + bool powered_on; | |
| 447 | + int ret; | |
| 448 | + | |
| 449 | + /* | |
| 450 | + * The HW only counts steps and other dependent | |
| 451 | + * parameters (speed, distance, calories, activity) | |
| 452 | + * if power is on (from enabling an event or the | |
| 453 | + * step counter). | |
| 454 | + */ | |
| 455 | + powered_on = mma9553_is_any_event_enabled(data, false, 0) || | |
| 456 | + data->stepcnt_enabled; | |
| 457 | + if (!powered_on) { | |
| 458 | + dev_err(&data->client->dev, "No channels enabled\n"); | |
| 459 | + return -EINVAL; | |
| 460 | + } | |
| 461 | + | |
| 462 | + mutex_lock(&data->mutex); | |
| 463 | + ret = mma9551_read_status_word(data->client, MMA9551_APPID_PEDOMETER, | |
| 464 | + reg, tmp); | |
| 465 | + mutex_unlock(&data->mutex); | |
| 466 | + return ret; | |
| 467 | +} | |
| 468 | + | |
| 439 | 469 | static int mma9553_read_raw(struct iio_dev *indio_dev, |
| 440 | 470 | struct iio_chan_spec const *chan, |
| 441 | 471 | int *val, int *val2, long mask) |
| @@ -444,69 +474,30 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, · 2 unmodified lines | ||
| 444 | 474 | int ret; |
| 445 | 475 | u16 tmp; |
| 446 | 476 | u8 activity; |
| 447 | − bool powered_on; | |
| 448 | 477 | |
| 449 | 478 | switch (mask) { |
| 450 | 479 | case IIO_CHAN_INFO_PROCESSED: |
| 451 | 480 | switch (chan->type) { |
| 452 | 481 | case IIO_STEPS: |
| 453 | − /* | |
| 454 | − * The HW only counts steps and other dependent | |
| 455 | − * parameters (speed, distance, calories, activity) | |
| 456 | − * if power is on (from enabling an event or the | |
| 457 | − * step counter */ | |
| 458 | − powered_on = | |
| 459 | − mma9553_is_any_event_enabled(data, false, 0) || | |
| 460 | − data->stepcnt_enabled; | |
| 461 | − if (!powered_on) { | |
| 462 | − dev_err(&data->client->dev, | |
| 463 | − "No channels enabled\n"); | |
| 464 | − return -EINVAL; | |
| 465 | − } | |
| 466 | − mutex_lock(&data->mutex); | |
| 467 | − ret = mma9551_read_status_word(data->client, | |
| 468 | − MMA9551_APPID_PEDOMETER, | |
| 482 | + ret = mma9553_read_status_word(data, | |
| 469 | 483 | MMA9553_REG_STEPCNT, |
| 470 | 484 | &tmp); |
| 471 | − mutex_unlock(&data->mutex); | |
| 472 | 485 | if (ret < 0) |
| 473 | 486 | return ret; |
| 474 | 487 | *val = tmp; |
| 475 | 488 | return IIO_VAL_INT; |
| 476 | 489 | case IIO_DISTANCE: |
| 477 | − powered_on = | |
| 478 | − mma9553_is_any_event_enabled(data, false, 0) || | |
| 479 | − data->stepcnt_enabled; | |
| 480 | − if (!powered_on) { | |
| 481 | − dev_err(&data->client->dev, | |
| 482 | − "No channels enabled\n"); | |
| 483 | − return -EINVAL; | |
| 484 | − } | |
| 485 | − mutex_lock(&data->mutex); | |
| 486 | − ret = mma9551_read_status_word(data->client, | |
| 487 | − MMA9551_APPID_PEDOMETER, | |
| 490 | + ret = mma9553_read_status_word(data, | |
| 488 | 491 | MMA9553_REG_DISTANCE, |
| 489 | 492 | &tmp); |
| 490 | − mutex_unlock(&data->mutex); | |
| 491 | 493 | if (ret < 0) |
| 492 | 494 | return ret; |
| 493 | 495 | *val = tmp; |
| 494 | 496 | return IIO_VAL_INT; |
| 495 | 497 | case IIO_ACTIVITY: |
| 496 | − powered_on = | |
| 497 | − mma9553_is_any_event_enabled(data, false, 0) || | |
| 498 | − data->stepcnt_enabled; | |
| 499 | − if (!powered_on) { | |
| 500 | − dev_err(&data->client->dev, | |
| 501 | − "No channels enabled\n"); | |
| 502 | − return -EINVAL; | |
| 503 | − } | |
| 504 | − mutex_lock(&data->mutex); | |
| 505 | − ret = mma9551_read_status_word(data->client, | |
| 506 | − MMA9551_APPID_PEDOMETER, | |
| 498 | + ret = mma9553_read_status_word(data, | |
| 507 | 499 | MMA9553_REG_STATUS, |
| 508 | 500 | &tmp); |
| 509 | − mutex_unlock(&data->mutex); | |
| 510 | 501 | if (ret < 0) |
| 511 | 502 | return ret; |
| 512 | 503 | |
| @@ -531,38 +522,17 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, · 18 unmodified lines | ||
| 531 | 522 | case IIO_VELOCITY: /* m/h */ |
| 532 | 523 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) |
| 533 | 524 | return -EINVAL; |
| 534 | − powered_on = | |
| 535 | − mma9553_is_any_event_enabled(data, false, 0) || | |
| 536 | − data->stepcnt_enabled; | |
| 537 | − if (!powered_on) { | |
| 538 | − dev_err(&data->client->dev, | |
| 539 | − "No channels enabled\n"); | |
| 540 | − return -EINVAL; | |
| 541 | − } | |
| 542 | − mutex_lock(&data->mutex); | |
| 543 | − ret = mma9551_read_status_word(data->client, | |
| 544 | − MMA9551_APPID_PEDOMETER, | |
| 545 | − MMA9553_REG_SPEED, &tmp); | |
| 546 | − mutex_unlock(&data->mutex); | |
| 525 | + ret = mma9553_read_status_word(data, | |
| 526 | + MMA9553_REG_SPEED, | |
| 527 | + &tmp); | |
| 547 | 528 | if (ret < 0) |
| 548 | 529 | return ret; |
| 549 | 530 | *val = tmp; |
| 550 | 531 | return IIO_VAL_INT; |
| 551 | 532 | case IIO_ENERGY: /* Cal or kcal */ |
| 552 | − powered_on = | |
| 553 | − mma9553_is_any_event_enabled(data, false, 0) || | |
| 554 | − data->stepcnt_enabled; | |
| 555 | − if (!powered_on) { | |
| 556 | − dev_err(&data->client->dev, | |
| 557 | − "No channels enabled\n"); | |
| 558 | − return -EINVAL; | |
| 559 | − } | |
| 560 | − mutex_lock(&data->mutex); | |
| 561 | − ret = mma9551_read_status_word(data->client, | |
| 562 | − MMA9551_APPID_PEDOMETER, | |
| 533 | + ret = mma9553_read_status_word(data, | |
| 563 | 534 | MMA9553_REG_CALORIES, |
| 564 | 535 | &tmp); |
| 565 | − mutex_unlock(&data->mutex); | |
| 566 | 536 | if (ret < 0) |
| 567 | 537 | return ret; |
| 568 | 538 | *val = tmp; |
| @@ -789,7 +759,7 @@ static int mma9553_write_event_config(struct iio_dev *indio_dev, · 220 unmodified lines | ||
| 789 | 759 | |
| 790 | 760 | mutex_unlock(&data->mutex); |
| 791 | 761 | |
| 792 | − return ret; | |
| 762 | + return 0; | |
| 793 | 763 | |
| 794 | 764 | err_conf_gpio: |
| 795 | 765 | if (state) { |
| @@ -897,7 +867,7 @@ static int mma9553_get_calibgender_mode(struct iio_dev *indio_dev, · 101 unmodified lines | ||
| 897 | 867 | gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); |
| 898 | 868 | /* |
| 899 | 869 | * HW expects 0 for female and 1 for male, |
| 900 | − * while iio index is 0 for male and 1 for female | |
| 870 | + * while iio index is 0 for male and 1 for female. | |
| 901 | 871 | */ |
| 902 | 872 | return !gender; |
| 903 | 873 | } |
| @@ -944,11 +914,11 @@ static const struct iio_event_spec mma9553_activity_events[] = { · 40 unmodified lines | ||
| 944 | 914 | }, |
| 945 | 915 | }; |
| 946 | 916 | |
| 947 | −static const char * const calibgender_modes[] = { "male", "female" }; | |
| 917 | +static const char * const mma9553_calibgender_modes[] = { "male", "female" }; | |
| 948 | 918 | |
| 949 | 919 | static const struct iio_enum mma9553_calibgender_enum = { |
| 950 | − .items = calibgender_modes, | |
| 951 | − .num_items = ARRAY_SIZE(calibgender_modes), | |
| 920 | + .items = mma9553_calibgender_modes, | |
| 921 | + .num_items = ARRAY_SIZE(mma9553_calibgender_modes), | |
| 952 | 922 | .get = mma9553_get_calibgender_mode, |
| 953 | 923 | .set = mma9553_set_calibgender_mode, |
| 954 | 924 | }; |
| @@ -1110,16 +1080,16 @@ static int mma9553_gpio_probe(struct i2c_client *client) · 155 unmodified lines | ||
| 1110 | 1080 | |
| 1111 | 1081 | dev = &client->dev; |
| 1112 | 1082 | |
| 1113 | − /* data ready gpio interrupt pin */ | |
| 1083 | + /* data ready GPIO interrupt pin */ | |
| 1114 | 1084 | gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN); |
| 1115 | 1085 | if (IS_ERR(gpio)) { |
| 1116 | − dev_err(dev, "acpi gpio get index failed\n"); | |
| 1086 | + dev_err(dev, "ACPI GPIO get index failed\n"); | |
| 1117 | 1087 | return PTR_ERR(gpio); |
| 1118 | 1088 | } |
| 1119 | 1089 | |
| 1120 | 1090 | ret = gpiod_to_irq(gpio); |
| 1121 | 1091 | |
| 1122 | − dev_dbg(dev, "gpio resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | |
| 1092 | + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | |
| 1123 | 1093 | |
| 1124 | 1094 | return ret; |
| 1125 | 1095 | } |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | #define LSM330D_ACCEL_DEV_NAME "lsm330d_accel" |
| 21 | 21 | #define LSM330DL_ACCEL_DEV_NAME "lsm330dl_accel" |
| 22 | 22 | #define LSM330DLC_ACCEL_DEV_NAME "lsm330dlc_accel" |
| 23 | +#define LIS331DL_ACCEL_DEV_NAME "lis331dl_accel" | |
| 23 | 24 | #define LIS331DLH_ACCEL_DEV_NAME "lis331dlh" |
| 24 | 25 | #define LSM303DL_ACCEL_DEV_NAME "lsm303dl_accel" |
| 25 | 26 | #define LSM303DLH_ACCEL_DEV_NAME "lsm303dlh_accel" |
| @@ -153,6 +153,44 @@ · 152 unmodified lines | ||
| 153 | 153 | #define ST_ACCEL_4_IG1_EN_MASK 0x08 |
| 154 | 154 | #define ST_ACCEL_4_MULTIREAD_BIT true |
| 155 | 155 | |
| 156 | +/* CUSTOM VALUES FOR SENSOR 5 */ | |
| 157 | +#define ST_ACCEL_5_WAI_EXP 0x3b | |
| 158 | +#define ST_ACCEL_5_ODR_ADDR 0x20 | |
| 159 | +#define ST_ACCEL_5_ODR_MASK 0x80 | |
| 160 | +#define ST_ACCEL_5_ODR_AVL_100HZ_VAL 0x00 | |
| 161 | +#define ST_ACCEL_5_ODR_AVL_400HZ_VAL 0x01 | |
| 162 | +#define ST_ACCEL_5_PW_ADDR 0x20 | |
| 163 | +#define ST_ACCEL_5_PW_MASK 0x40 | |
| 164 | +#define ST_ACCEL_5_FS_ADDR 0x20 | |
| 165 | +#define ST_ACCEL_5_FS_MASK 0x20 | |
| 166 | +#define ST_ACCEL_5_FS_AVL_2_VAL 0X00 | |
| 167 | +#define ST_ACCEL_5_FS_AVL_8_VAL 0X01 | |
| 168 | +/* TODO: check these resulting gain settings, these are not in the datsheet */ | |
| 169 | +#define ST_ACCEL_5_FS_AVL_2_GAIN IIO_G_TO_M_S_2(18000) | |
| 170 | +#define ST_ACCEL_5_FS_AVL_8_GAIN IIO_G_TO_M_S_2(72000) | |
| 171 | +#define ST_ACCEL_5_DRDY_IRQ_ADDR 0x22 | |
| 172 | +#define ST_ACCEL_5_DRDY_IRQ_INT1_MASK 0x04 | |
| 173 | +#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK 0x20 | |
| 174 | +#define ST_ACCEL_5_IG1_EN_ADDR 0x21 | |
| 175 | +#define ST_ACCEL_5_IG1_EN_MASK 0x08 | |
| 176 | +#define ST_ACCEL_5_MULTIREAD_BIT false | |
| 177 | + | |
| 178 | +static const struct iio_chan_spec st_accel_8bit_channels[] = { | |
| 179 | + ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | |
| 180 | + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | |
| 181 | + ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 8, 8, | |
| 182 | + ST_ACCEL_DEFAULT_OUT_X_L_ADDR+1), | |
| 183 | + ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | |
| 184 | + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | |
| 185 | + ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 8, 8, | |
| 186 | + ST_ACCEL_DEFAULT_OUT_Y_L_ADDR+1), | |
| 187 | + ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | |
| 188 | + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | |
| 189 | + ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 8, 8, | |
| 190 | + ST_ACCEL_DEFAULT_OUT_Z_L_ADDR+1), | |
| 191 | + IIO_CHAN_SOFT_TIMESTAMP(3) | |
| 192 | +}; | |
| 193 | + | |
| 156 | 194 | static const struct iio_chan_spec st_accel_12bit_channels[] = { |
| 157 | 195 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, |
| 158 | 196 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), |
| @@ -454,6 +492,54 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = { · 295 unmodified lines | ||
| 454 | 492 | .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT, |
| 455 | 493 | .bootime = 2, /* guess */ |
| 456 | 494 | }, |
| 495 | + { | |
| 496 | + .wai = ST_ACCEL_5_WAI_EXP, | |
| 497 | + .sensors_supported = { | |
| 498 | + [0] = LIS331DL_ACCEL_DEV_NAME, | |
| 499 | + }, | |
| 500 | + .ch = (struct iio_chan_spec *)st_accel_8bit_channels, | |
| 501 | + .odr = { | |
| 502 | + .addr = ST_ACCEL_5_ODR_ADDR, | |
| 503 | + .mask = ST_ACCEL_5_ODR_MASK, | |
| 504 | + .odr_avl = { | |
| 505 | + { 100, ST_ACCEL_5_ODR_AVL_100HZ_VAL }, | |
| 506 | + { 400, ST_ACCEL_5_ODR_AVL_400HZ_VAL, }, | |
| 507 | + }, | |
| 508 | + }, | |
| 509 | + .pw = { | |
| 510 | + .addr = ST_ACCEL_5_PW_ADDR, | |
| 511 | + .mask = ST_ACCEL_5_PW_MASK, | |
| 512 | + .value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE, | |
| 513 | + .value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE, | |
| 514 | + }, | |
| 515 | + .enable_axis = { | |
| 516 | + .addr = ST_SENSORS_DEFAULT_AXIS_ADDR, | |
| 517 | + .mask = ST_SENSORS_DEFAULT_AXIS_MASK, | |
| 518 | + }, | |
| 519 | + .fs = { | |
| 520 | + .addr = ST_ACCEL_5_FS_ADDR, | |
| 521 | + .mask = ST_ACCEL_5_FS_MASK, | |
| 522 | + .fs_avl = { | |
| 523 | + [0] = { | |
| 524 | + .num = ST_ACCEL_FS_AVL_2G, | |
| 525 | + .value = ST_ACCEL_5_FS_AVL_2_VAL, | |
| 526 | + .gain = ST_ACCEL_5_FS_AVL_2_GAIN, | |
| 527 | + }, | |
| 528 | + [1] = { | |
| 529 | + .num = ST_ACCEL_FS_AVL_8G, | |
| 530 | + .value = ST_ACCEL_5_FS_AVL_8_VAL, | |
| 531 | + .gain = ST_ACCEL_5_FS_AVL_8_GAIN, | |
| 532 | + }, | |
| 533 | + }, | |
| 534 | + }, | |
| 535 | + .drdy_irq = { | |
| 536 | + .addr = ST_ACCEL_5_DRDY_IRQ_ADDR, | |
| 537 | + .mask_int1 = ST_ACCEL_5_DRDY_IRQ_INT1_MASK, | |
| 538 | + .mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK, | |
| 539 | + }, | |
| 540 | + .multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT, | |
| 541 | + .bootime = 2, /* guess */ | |
| 542 | + }, | |
| 457 | 543 | }; |
| 458 | 544 | |
| 459 | 545 | static int st_accel_read_raw(struct iio_dev *indio_dev, |
| @@ -48,6 +48,10 @@ static const struct of_device_id st_accel_of_match[] = { · 47 unmodified lines | ||
| 48 | 48 | .compatible = "st,lsm330dlc-accel", |
| 49 | 49 | .data = LSM330DLC_ACCEL_DEV_NAME, |
| 50 | 50 | }, |
| 51 | + { | |
| 52 | + .compatible = "st,lis331dl-accel", | |
| 53 | + .data = LIS331DL_ACCEL_DEV_NAME, | |
| 54 | + }, | |
| 51 | 55 | { |
| 52 | 56 | .compatible = "st,lis331dlh-accel", |
| 53 | 57 | .data = LIS331DLH_ACCEL_DEV_NAME, |
| @@ -0,0 +1,390 @@ | ||
| 1 | +/** | |
| 2 | + * Sensortek STK8312 3-Axis Accelerometer | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015, Intel Corporation. | |
| 5 | + * | |
| 6 | + * This file is subject to the terms and conditions of version 2 of | |
| 7 | + * the GNU General Public License. See the file COPYING in the main | |
| 8 | + * directory of this archive for more details. | |
| 9 | + * | |
| 10 | + * IIO driver for STK8312; 7-bit I2C address: 0x3D. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/acpi.h> | |
| 14 | +#include <linux/i2c.h> | |
| 15 | +#include <linux/kernel.h> | |
| 16 | +#include <linux/module.h> | |
| 17 | +#include <linux/delay.h> | |
| 18 | +#include <linux/iio/iio.h> | |
| 19 | +#include <linux/iio/sysfs.h> | |
| 20 | + | |
| 21 | +#define STK8312_REG_XOUT 0x00 | |
| 22 | +#define STK8312_REG_YOUT 0x01 | |
| 23 | +#define STK8312_REG_ZOUT 0x02 | |
| 24 | +#define STK8312_REG_MODE 0x07 | |
| 25 | +#define STK8312_REG_STH 0x13 | |
| 26 | +#define STK8312_REG_RESET 0x20 | |
| 27 | +#define STK8312_REG_AFECTRL 0x24 | |
| 28 | +#define STK8312_REG_OTPADDR 0x3D | |
| 29 | +#define STK8312_REG_OTPDATA 0x3E | |
| 30 | +#define STK8312_REG_OTPCTRL 0x3F | |
| 31 | + | |
| 32 | +#define STK8312_MODE_ACTIVE 1 | |
| 33 | +#define STK8312_MODE_STANDBY 0 | |
| 34 | +#define STK8312_MODE_MASK 0x01 | |
| 35 | +#define STK8312_RNG_MASK 0xC0 | |
| 36 | +#define STK8312_RNG_SHIFT 6 | |
| 37 | +#define STK8312_READ_RETRIES 16 | |
| 38 | + | |
| 39 | +#define STK8312_DRIVER_NAME "stk8312" | |
| 40 | + | |
| 41 | +/* | |
| 42 | + * The accelerometer has two measurement ranges: | |
| 43 | + * | |
| 44 | + * -6g - +6g (8-bit, signed) | |
| 45 | + * -16g - +16g (8-bit, signed) | |
| 46 | + * | |
| 47 | + * scale1 = (6 + 6) * 9.81 / (2^8 - 1) = 0.4616 | |
| 48 | + * scale2 = (16 + 16) * 9.81 / (2^8 - 1) = 1.2311 | |
| 49 | + */ | |
| 50 | +#define STK8312_SCALE_AVAIL "0.4616 1.2311" | |
| 51 | + | |
| 52 | +static const int stk8312_scale_table[][2] = { | |
| 53 | + {0, 461600}, {1, 231100} | |
| 54 | +}; | |
| 55 | + | |
| 56 | +#define STK8312_ACCEL_CHANNEL(reg, axis) { \ | |
| 57 | + .type = IIO_ACCEL, \ | |
| 58 | + .address = reg, \ | |
| 59 | + .modified = 1, \ | |
| 60 | + .channel2 = IIO_MOD_##axis, \ | |
| 61 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 62 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
| 63 | +} | |
| 64 | + | |
| 65 | +static const struct iio_chan_spec stk8312_channels[] = { | |
| 66 | + STK8312_ACCEL_CHANNEL(STK8312_REG_XOUT, X), | |
| 67 | + STK8312_ACCEL_CHANNEL(STK8312_REG_YOUT, Y), | |
| 68 | + STK8312_ACCEL_CHANNEL(STK8312_REG_ZOUT, Z), | |
| 69 | +}; | |
| 70 | + | |
| 71 | +struct stk8312_data { | |
| 72 | + struct i2c_client *client; | |
| 73 | + struct mutex lock; | |
| 74 | + int range; | |
| 75 | + u8 mode; | |
| 76 | +}; | |
| 77 | + | |
| 78 | +static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL); | |
| 79 | + | |
| 80 | +static struct attribute *stk8312_attributes[] = { | |
| 81 | + &iio_const_attr_in_accel_scale_available.dev_attr.attr, | |
| 82 | + NULL, | |
| 83 | +}; | |
| 84 | + | |
| 85 | +static const struct attribute_group stk8312_attribute_group = { | |
| 86 | + .attrs = stk8312_attributes | |
| 87 | +}; | |
| 88 | + | |
| 89 | +static int stk8312_otp_init(struct stk8312_data *data) | |
| 90 | +{ | |
| 91 | + int ret; | |
| 92 | + int count = 10; | |
| 93 | + struct i2c_client *client = data->client; | |
| 94 | + | |
| 95 | + ret = i2c_smbus_write_byte_data(client, STK8312_REG_OTPADDR, 0x70); | |
| 96 | + if (ret < 0) | |
| 97 | + goto exit_err; | |
| 98 | + ret = i2c_smbus_write_byte_data(client, STK8312_REG_OTPCTRL, 0x02); | |
| 99 | + if (ret < 0) | |
| 100 | + goto exit_err; | |
| 101 | + | |
| 102 | + do { | |
| 103 | + usleep_range(1000, 5000); | |
| 104 | + ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPCTRL); | |
| 105 | + if (ret < 0) | |
| 106 | + goto exit_err; | |
| 107 | + count--; | |
| 108 | + } while (!(ret & 0x80) && count > 0); | |
| 109 | + | |
| 110 | + if (count == 0) | |
| 111 | + goto exit_err; | |
| 112 | + | |
| 113 | + ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPDATA); | |
| 114 | + if (ret < 0) | |
| 115 | + goto exit_err; | |
| 116 | + | |
| 117 | + ret = i2c_smbus_write_byte_data(data->client, | |
| 118 | + STK8312_REG_AFECTRL, ret); | |
| 119 | + if (ret < 0) | |
| 120 | + goto exit_err; | |
| 121 | + msleep(150); | |
| 122 | + | |
| 123 | + return ret; | |
| 124 | + | |
| 125 | +exit_err: | |
| 126 | + dev_err(&client->dev, "failed to initialize sensor\n"); | |
| 127 | + return ret; | |
| 128 | +} | |
| 129 | + | |
| 130 | +static int stk8312_set_mode(struct stk8312_data *data, u8 mode) | |
| 131 | +{ | |
| 132 | + int ret; | |
| 133 | + u8 masked_reg; | |
| 134 | + struct i2c_client *client = data->client; | |
| 135 | + | |
| 136 | + if (mode > 1) | |
| 137 | + return -EINVAL; | |
| 138 | + else if (mode == data->mode) | |
| 139 | + return 0; | |
| 140 | + | |
| 141 | + ret = i2c_smbus_read_byte_data(client, STK8312_REG_MODE); | |
| 142 | + if (ret < 0) { | |
| 143 | + dev_err(&client->dev, "failed to change sensor mode\n"); | |
| 144 | + return ret; | |
| 145 | + } | |
| 146 | + masked_reg = ret & (~STK8312_MODE_MASK); | |
| 147 | + masked_reg |= mode; | |
| 148 | + | |
| 149 | + ret = i2c_smbus_write_byte_data(client, | |
| 150 | + STK8312_REG_MODE, masked_reg); | |
| 151 | + if (ret < 0) { | |
| 152 | + dev_err(&client->dev, "failed to change sensor mode\n"); | |
| 153 | + return ret; | |
| 154 | + } | |
| 155 | + | |
| 156 | + data->mode = mode; | |
| 157 | + if (mode == STK8312_MODE_ACTIVE) { | |
| 158 | + /* Need to run OTP sequence before entering active mode */ | |
| 159 | + usleep_range(1000, 5000); | |
| 160 | + ret = stk8312_otp_init(data); | |
| 161 | + } | |
| 162 | + | |
| 163 | + return ret; | |
| 164 | +} | |
| 165 | + | |
| 166 | +static int stk8312_set_range(struct stk8312_data *data, u8 range) | |
| 167 | +{ | |
| 168 | + int ret; | |
| 169 | + u8 masked_reg; | |
| 170 | + u8 mode; | |
| 171 | + struct i2c_client *client = data->client; | |
| 172 | + | |
| 173 | + if (range != 1 && range != 2) | |
| 174 | + return -EINVAL; | |
| 175 | + else if (range == data->range) | |
| 176 | + return 0; | |
| 177 | + | |
| 178 | + mode = data->mode; | |
| 179 | + /* We need to go in standby mode to modify registers */ | |
| 180 | + ret = stk8312_set_mode(data, STK8312_MODE_STANDBY); | |
| 181 | + if (ret < 0) | |
| 182 | + return ret; | |
| 183 | + | |
| 184 | + ret = i2c_smbus_read_byte_data(client, STK8312_REG_STH); | |
| 185 | + if (ret < 0) { | |
| 186 | + dev_err(&client->dev, "failed to change sensor range\n"); | |
| 187 | + return ret; | |
| 188 | + } | |
| 189 | + | |
| 190 | + masked_reg = ret & (~STK8312_RNG_MASK); | |
| 191 | + masked_reg |= range << STK8312_RNG_SHIFT; | |
| 192 | + | |
| 193 | + ret = i2c_smbus_write_byte_data(client, STK8312_REG_STH, masked_reg); | |
| 194 | + if (ret < 0) | |
| 195 | + dev_err(&client->dev, "failed to change sensor range\n"); | |
| 196 | + else | |
| 197 | + data->range = range; | |
| 198 | + | |
| 199 | + return stk8312_set_mode(data, mode); | |
| 200 | +} | |
| 201 | + | |
| 202 | +static int stk8312_read_accel(struct stk8312_data *data, u8 address) | |
| 203 | +{ | |
| 204 | + int ret; | |
| 205 | + struct i2c_client *client = data->client; | |
| 206 | + | |
| 207 | + if (address > 2) | |
| 208 | + return -EINVAL; | |
| 209 | + | |
| 210 | + ret = i2c_smbus_read_byte_data(client, address); | |
| 211 | + if (ret < 0) { | |
| 212 | + dev_err(&client->dev, "register read failed\n"); | |
| 213 | + return ret; | |
| 214 | + } | |
| 215 | + | |
| 216 | + return sign_extend32(ret, 7); | |
| 217 | +} | |
| 218 | + | |
| 219 | +static int stk8312_read_raw(struct iio_dev *indio_dev, | |
| 220 | + struct iio_chan_spec const *chan, | |
| 221 | + int *val, int *val2, long mask) | |
| 222 | +{ | |
| 223 | + struct stk8312_data *data = iio_priv(indio_dev); | |
| 224 | + | |
| 225 | + if (chan->type != IIO_ACCEL) | |
| 226 | + return -EINVAL; | |
| 227 | + | |
| 228 | + switch (mask) { | |
| 229 | + case IIO_CHAN_INFO_RAW: | |
| 230 | + mutex_lock(&data->lock); | |
| 231 | + *val = stk8312_read_accel(data, chan->address); | |
| 232 | + mutex_unlock(&data->lock); | |
| 233 | + return IIO_VAL_INT; | |
| 234 | + case IIO_CHAN_INFO_SCALE: | |
| 235 | + *val = stk8312_scale_table[data->range - 1][0]; | |
| 236 | + *val2 = stk8312_scale_table[data->range - 1][1]; | |
| 237 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 238 | + } | |
| 239 | + | |
| 240 | + return -EINVAL; | |
| 241 | +} | |
| 242 | + | |
| 243 | +static int stk8312_write_raw(struct iio_dev *indio_dev, | |
| 244 | + struct iio_chan_spec const *chan, | |
| 245 | + int val, int val2, long mask) | |
| 246 | +{ | |
| 247 | + int i; | |
| 248 | + int index = -1; | |
| 249 | + int ret; | |
| 250 | + struct stk8312_data *data = iio_priv(indio_dev); | |
| 251 | + | |
| 252 | + switch (mask) { | |
| 253 | + case IIO_CHAN_INFO_SCALE: | |
| 254 | + for (i = 0; i < ARRAY_SIZE(stk8312_scale_table); i++) | |
| 255 | + if (val == stk8312_scale_table[i][0] && | |
| 256 | + val2 == stk8312_scale_table[i][1]) { | |
| 257 | + index = i + 1; | |
| 258 | + break; | |
| 259 | + } | |
| 260 | + if (index < 0) | |
| 261 | + return -EINVAL; | |
| 262 | + | |
| 263 | + mutex_lock(&data->lock); | |
| 264 | + ret = stk8312_set_range(data, index); | |
| 265 | + mutex_unlock(&data->lock); | |
| 266 | + | |
| 267 | + return ret; | |
| 268 | + } | |
| 269 | + | |
| 270 | + return -EINVAL; | |
| 271 | +} | |
| 272 | + | |
| 273 | +static const struct iio_info stk8312_info = { | |
| 274 | + .driver_module = THIS_MODULE, | |
| 275 | + .read_raw = stk8312_read_raw, | |
| 276 | + .write_raw = stk8312_write_raw, | |
| 277 | + .attrs = &stk8312_attribute_group, | |
| 278 | +}; | |
| 279 | + | |
| 280 | +static int stk8312_probe(struct i2c_client *client, | |
| 281 | + const struct i2c_device_id *id) | |
| 282 | +{ | |
| 283 | + int ret; | |
| 284 | + struct iio_dev *indio_dev; | |
| 285 | + struct stk8312_data *data; | |
| 286 | + | |
| 287 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 288 | + if (!indio_dev) { | |
| 289 | + dev_err(&client->dev, "iio allocation failed!\n"); | |
| 290 | + return -ENOMEM; | |
| 291 | + } | |
| 292 | + | |
| 293 | + data = iio_priv(indio_dev); | |
| 294 | + data->client = client; | |
| 295 | + i2c_set_clientdata(client, indio_dev); | |
| 296 | + mutex_init(&data->lock); | |
| 297 | + | |
| 298 | + indio_dev->dev.parent = &client->dev; | |
| 299 | + indio_dev->info = &stk8312_info; | |
| 300 | + indio_dev->name = STK8312_DRIVER_NAME; | |
| 301 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 302 | + indio_dev->channels = stk8312_channels; | |
| 303 | + indio_dev->num_channels = ARRAY_SIZE(stk8312_channels); | |
| 304 | + | |
| 305 | + /* A software reset is recommended at power-on */ | |
| 306 | + ret = i2c_smbus_write_byte_data(data->client, STK8312_REG_RESET, 0x00); | |
| 307 | + if (ret < 0) { | |
| 308 | + dev_err(&client->dev, "failed to reset sensor\n"); | |
| 309 | + return ret; | |
| 310 | + } | |
| 311 | + ret = stk8312_set_range(data, 1); | |
| 312 | + if (ret < 0) | |
| 313 | + return ret; | |
| 314 | + | |
| 315 | + ret = stk8312_set_mode(data, STK8312_MODE_ACTIVE); | |
| 316 | + if (ret < 0) | |
| 317 | + return ret; | |
| 318 | + | |
| 319 | + ret = iio_device_register(indio_dev); | |
| 320 | + if (ret < 0) { | |
| 321 | + dev_err(&client->dev, "device_register failed\n"); | |
| 322 | + stk8312_set_mode(data, STK8312_MODE_STANDBY); | |
| 323 | + } | |
| 324 | + | |
| 325 | + return ret; | |
| 326 | +} | |
| 327 | + | |
| 328 | +static int stk8312_remove(struct i2c_client *client) | |
| 329 | +{ | |
| 330 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 331 | + | |
| 332 | + iio_device_unregister(indio_dev); | |
| 333 | + | |
| 334 | + return stk8312_set_mode(iio_priv(indio_dev), STK8312_MODE_STANDBY); | |
| 335 | +} | |
| 336 | + | |
| 337 | +#ifdef CONFIG_PM_SLEEP | |
| 338 | +static int stk8312_suspend(struct device *dev) | |
| 339 | +{ | |
| 340 | + struct stk8312_data *data; | |
| 341 | + | |
| 342 | + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | |
| 343 | + | |
| 344 | + return stk8312_set_mode(data, STK8312_MODE_STANDBY); | |
| 345 | +} | |
| 346 | + | |
| 347 | +static int stk8312_resume(struct device *dev) | |
| 348 | +{ | |
| 349 | + struct stk8312_data *data; | |
| 350 | + | |
| 351 | + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | |
| 352 | + | |
| 353 | + return stk8312_set_mode(data, STK8312_MODE_ACTIVE); | |
| 354 | +} | |
| 355 | + | |
| 356 | +static SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, stk8312_resume); | |
| 357 | + | |
| 358 | +#define STK8312_PM_OPS (&stk8312_pm_ops) | |
| 359 | +#else | |
| 360 | +#define STK8312_PM_OPS NULL | |
| 361 | +#endif | |
| 362 | + | |
| 363 | +static const struct i2c_device_id stk8312_i2c_id[] = { | |
| 364 | + {"STK8312", 0}, | |
| 365 | + {} | |
| 366 | +}; | |
| 367 | + | |
| 368 | +static const struct acpi_device_id stk8312_acpi_id[] = { | |
| 369 | + {"STK8312", 0}, | |
| 370 | + {} | |
| 371 | +}; | |
| 372 | + | |
| 373 | +MODULE_DEVICE_TABLE(acpi, stk8312_acpi_id); | |
| 374 | + | |
| 375 | +static struct i2c_driver stk8312_driver = { | |
| 376 | + .driver = { | |
| 377 | + .name = "stk8312", | |
| 378 | + .pm = STK8312_PM_OPS, | |
| 379 | + .acpi_match_table = ACPI_PTR(stk8312_acpi_id), | |
| 380 | + }, | |
| 381 | + .probe = stk8312_probe, | |
| 382 | + .remove = stk8312_remove, | |
| 383 | + .id_table = stk8312_i2c_id, | |
| 384 | +}; | |
| 385 | + | |
| 386 | +module_i2c_driver(stk8312_driver); | |
| 387 | + | |
| 388 | +MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); | |
| 389 | +MODULE_DESCRIPTION("STK8312 3-Axis Accelerometer driver"); | |
| 390 | +MODULE_LICENSE("GPL v2"); | |
| @@ -0,0 +1,302 @@ | ||
| 1 | +/** | |
| 2 | + * Sensortek STK8BA50 3-Axis Accelerometer | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015, Intel Corporation. | |
| 5 | + * | |
| 6 | + * This file is subject to the terms and conditions of version 2 of | |
| 7 | + * the GNU General Public License. See the file COPYING in the main | |
| 8 | + * directory of this archive for more details. | |
| 9 | + * | |
| 10 | + * STK8BA50 7-bit I2C address: 0x18. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/acpi.h> | |
| 14 | +#include <linux/i2c.h> | |
| 15 | +#include <linux/kernel.h> | |
| 16 | +#include <linux/module.h> | |
| 17 | +#include <linux/iio/iio.h> | |
| 18 | +#include <linux/iio/sysfs.h> | |
| 19 | + | |
| 20 | +#define STK8BA50_REG_XOUT 0x02 | |
| 21 | +#define STK8BA50_REG_YOUT 0x04 | |
| 22 | +#define STK8BA50_REG_ZOUT 0x06 | |
| 23 | +#define STK8BA50_REG_RANGE 0x0F | |
| 24 | +#define STK8BA50_REG_POWMODE 0x11 | |
| 25 | +#define STK8BA50_REG_SWRST 0x14 | |
| 26 | + | |
| 27 | +#define STK8BA50_MODE_NORMAL 0 | |
| 28 | +#define STK8BA50_MODE_SUSPEND 1 | |
| 29 | +#define STK8BA50_MODE_POWERBIT BIT(7) | |
| 30 | +#define STK8BA50_DATA_SHIFT 6 | |
| 31 | +#define STK8BA50_RESET_CMD 0xB6 | |
| 32 | + | |
| 33 | +#define STK8BA50_DRIVER_NAME "stk8ba50" | |
| 34 | + | |
| 35 | +#define STK8BA50_SCALE_AVAIL "0.0384 0.0767 0.1534 0.3069" | |
| 36 | + | |
| 37 | +/* | |
| 38 | + * The accelerometer has four measurement ranges: | |
| 39 | + * +/-2g; +/-4g; +/-8g; +/-16g | |
| 40 | + * | |
| 41 | + * Acceleration values are 10-bit, 2's complement. | |
| 42 | + * Scales are calculated as following: | |
| 43 | + * | |
| 44 | + * scale1 = (2 + 2) * 9.81 / (2^10 - 1) = 0.0384 | |
| 45 | + * scale2 = (4 + 4) * 9.81 / (2^10 - 1) = 0.0767 | |
| 46 | + * etc. | |
| 47 | + * | |
| 48 | + * Scales are stored in this format: | |
| 49 | + * { <register value>, <scale value> } | |
| 50 | + * | |
| 51 | + * Locally, the range is stored as a table index. | |
| 52 | + */ | |
| 53 | +static const int stk8ba50_scale_table[][2] = { | |
| 54 | + {3, 38400}, {5, 76700}, {8, 153400}, {12, 306900} | |
| 55 | +}; | |
| 56 | + | |
| 57 | +struct stk8ba50_data { | |
| 58 | + struct i2c_client *client; | |
| 59 | + struct mutex lock; | |
| 60 | + int range; | |
| 61 | +}; | |
| 62 | + | |
| 63 | +#define STK8BA50_ACCEL_CHANNEL(reg, axis) { \ | |
| 64 | + .type = IIO_ACCEL, \ | |
| 65 | + .address = reg, \ | |
| 66 | + .modified = 1, \ | |
| 67 | + .channel2 = IIO_MOD_##axis, \ | |
| 68 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 69 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ | |
| 70 | +} | |
| 71 | + | |
| 72 | +static const struct iio_chan_spec stk8ba50_channels[] = { | |
| 73 | + STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_XOUT, X), | |
| 74 | + STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_YOUT, Y), | |
| 75 | + STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_ZOUT, Z), | |
| 76 | +}; | |
| 77 | + | |
| 78 | +static IIO_CONST_ATTR(in_accel_scale_available, STK8BA50_SCALE_AVAIL); | |
| 79 | + | |
| 80 | +static struct attribute *stk8ba50_attributes[] = { | |
| 81 | + &iio_const_attr_in_accel_scale_available.dev_attr.attr, | |
| 82 | + NULL, | |
| 83 | +}; | |
| 84 | + | |
| 85 | +static const struct attribute_group stk8ba50_attribute_group = { | |
| 86 | + .attrs = stk8ba50_attributes | |
| 87 | +}; | |
| 88 | + | |
| 89 | +static int stk8ba50_read_accel(struct stk8ba50_data *data, u8 reg) | |
| 90 | +{ | |
| 91 | + int ret; | |
| 92 | + struct i2c_client *client = data->client; | |
| 93 | + | |
| 94 | + ret = i2c_smbus_read_word_data(client, reg); | |
| 95 | + if (ret < 0) { | |
| 96 | + dev_err(&client->dev, "register read failed\n"); | |
| 97 | + return ret; | |
| 98 | + } | |
| 99 | + | |
| 100 | + return sign_extend32(ret >> STK8BA50_DATA_SHIFT, 9); | |
| 101 | +} | |
| 102 | + | |
| 103 | +static int stk8ba50_read_raw(struct iio_dev *indio_dev, | |
| 104 | + struct iio_chan_spec const *chan, | |
| 105 | + int *val, int *val2, long mask) | |
| 106 | +{ | |
| 107 | + struct stk8ba50_data *data = iio_priv(indio_dev); | |
| 108 | + | |
| 109 | + switch (mask) { | |
| 110 | + case IIO_CHAN_INFO_RAW: | |
| 111 | + mutex_lock(&data->lock); | |
| 112 | + *val = stk8ba50_read_accel(data, chan->address); | |
| 113 | + mutex_unlock(&data->lock); | |
| 114 | + return IIO_VAL_INT; | |
| 115 | + case IIO_CHAN_INFO_SCALE: | |
| 116 | + *val = 0; | |
| 117 | + *val2 = stk8ba50_scale_table[data->range][1]; | |
| 118 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 119 | + } | |
| 120 | + | |
| 121 | + return -EINVAL; | |
| 122 | +} | |
| 123 | + | |
| 124 | +static int stk8ba50_write_raw(struct iio_dev *indio_dev, | |
| 125 | + struct iio_chan_spec const *chan, | |
| 126 | + int val, int val2, long mask) | |
| 127 | +{ | |
| 128 | + int ret; | |
| 129 | + int i; | |
| 130 | + int index = -1; | |
| 131 | + struct stk8ba50_data *data = iio_priv(indio_dev); | |
| 132 | + | |
| 133 | + switch (mask) { | |
| 134 | + case IIO_CHAN_INFO_SCALE: | |
| 135 | + if (val != 0) | |
| 136 | + return -EINVAL; | |
| 137 | + | |
| 138 | + for (i = 0; i < ARRAY_SIZE(stk8ba50_scale_table); i++) | |
| 139 | + if (val2 == stk8ba50_scale_table[i][1]) { | |
| 140 | + index = i; | |
| 141 | + break; | |
| 142 | + } | |
| 143 | + if (index < 0) | |
| 144 | + return -EINVAL; | |
| 145 | + | |
| 146 | + ret = i2c_smbus_write_byte_data(data->client, | |
| 147 | + STK8BA50_REG_RANGE, | |
| 148 | + stk8ba50_scale_table[index][0]); | |
| 149 | + if (ret < 0) | |
| 150 | + dev_err(&data->client->dev, | |
| 151 | + "failed to set measurement range\n"); | |
| 152 | + else | |
| 153 | + data->range = index; | |
| 154 | + | |
| 155 | + return ret; | |
| 156 | + } | |
| 157 | + | |
| 158 | + return -EINVAL; | |
| 159 | +} | |
| 160 | + | |
| 161 | +static const struct iio_info stk8ba50_info = { | |
| 162 | + .driver_module = THIS_MODULE, | |
| 163 | + .read_raw = stk8ba50_read_raw, | |
| 164 | + .write_raw = stk8ba50_write_raw, | |
| 165 | + .attrs = &stk8ba50_attribute_group, | |
| 166 | +}; | |
| 167 | + | |
| 168 | +static int stk8ba50_set_power(struct stk8ba50_data *data, bool mode) | |
| 169 | +{ | |
| 170 | + int ret; | |
| 171 | + u8 masked_reg; | |
| 172 | + struct i2c_client *client = data->client; | |
| 173 | + | |
| 174 | + ret = i2c_smbus_read_byte_data(client, STK8BA50_REG_POWMODE); | |
| 175 | + if (ret < 0) | |
| 176 | + goto exit_err; | |
| 177 | + | |
| 178 | + if (mode) | |
| 179 | + masked_reg = ret | STK8BA50_MODE_POWERBIT; | |
| 180 | + else | |
| 181 | + masked_reg = ret & (~STK8BA50_MODE_POWERBIT); | |
| 182 | + | |
| 183 | + ret = i2c_smbus_write_byte_data(client, STK8BA50_REG_POWMODE, | |
| 184 | + masked_reg); | |
| 185 | + if (ret < 0) | |
| 186 | + goto exit_err; | |
| 187 | + | |
| 188 | + return ret; | |
| 189 | + | |
| 190 | +exit_err: | |
| 191 | + dev_err(&client->dev, "failed to change sensor mode\n"); | |
| 192 | + return ret; | |
| 193 | +} | |
| 194 | + | |
| 195 | +static int stk8ba50_probe(struct i2c_client *client, | |
| 196 | + const struct i2c_device_id *id) | |
| 197 | +{ | |
| 198 | + int ret; | |
| 199 | + struct iio_dev *indio_dev; | |
| 200 | + struct stk8ba50_data *data; | |
| 201 | + | |
| 202 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 203 | + if (!indio_dev) { | |
| 204 | + dev_err(&client->dev, "iio allocation failed!\n"); | |
| 205 | + return -ENOMEM; | |
| 206 | + } | |
| 207 | + | |
| 208 | + data = iio_priv(indio_dev); | |
| 209 | + data->client = client; | |
| 210 | + i2c_set_clientdata(client, indio_dev); | |
| 211 | + mutex_init(&data->lock); | |
| 212 | + | |
| 213 | + indio_dev->dev.parent = &client->dev; | |
| 214 | + indio_dev->info = &stk8ba50_info; | |
| 215 | + indio_dev->name = STK8BA50_DRIVER_NAME; | |
| 216 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 217 | + indio_dev->channels = stk8ba50_channels; | |
| 218 | + indio_dev->num_channels = ARRAY_SIZE(stk8ba50_channels); | |
| 219 | + | |
| 220 | + /* Reset all registers on startup */ | |
| 221 | + ret = i2c_smbus_write_byte_data(client, | |
| 222 | + STK8BA50_REG_SWRST, STK8BA50_RESET_CMD); | |
| 223 | + if (ret < 0) { | |
| 224 | + dev_err(&client->dev, "failed to reset sensor\n"); | |
| 225 | + return ret; | |
| 226 | + } | |
| 227 | + | |
| 228 | + /* The default range is +/-2g */ | |
| 229 | + data->range = 0; | |
| 230 | + | |
| 231 | + ret = iio_device_register(indio_dev); | |
| 232 | + if (ret < 0) { | |
| 233 | + dev_err(&client->dev, "device_register failed\n"); | |
| 234 | + stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND); | |
| 235 | + } | |
| 236 | + | |
| 237 | + return ret; | |
| 238 | +} | |
| 239 | + | |
| 240 | +static int stk8ba50_remove(struct i2c_client *client) | |
| 241 | +{ | |
| 242 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 243 | + | |
| 244 | + iio_device_unregister(indio_dev); | |
| 245 | + | |
| 246 | + return stk8ba50_set_power(iio_priv(indio_dev), STK8BA50_MODE_SUSPEND); | |
| 247 | +} | |
| 248 | + | |
| 249 | +#ifdef CONFIG_PM_SLEEP | |
| 250 | +static int stk8ba50_suspend(struct device *dev) | |
| 251 | +{ | |
| 252 | + struct stk8ba50_data *data; | |
| 253 | + | |
| 254 | + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | |
| 255 | + | |
| 256 | + return stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND); | |
| 257 | +} | |
| 258 | + | |
| 259 | +static int stk8ba50_resume(struct device *dev) | |
| 260 | +{ | |
| 261 | + struct stk8ba50_data *data; | |
| 262 | + | |
| 263 | + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | |
| 264 | + | |
| 265 | + return stk8ba50_set_power(data, STK8BA50_MODE_NORMAL); | |
| 266 | +} | |
| 267 | + | |
| 268 | +static SIMPLE_DEV_PM_OPS(stk8ba50_pm_ops, stk8ba50_suspend, stk8ba50_resume); | |
| 269 | + | |
| 270 | +#define STK8BA50_PM_OPS (&stk8ba50_pm_ops) | |
| 271 | +#else | |
| 272 | +#define STK8BA50_PM_OPS NULL | |
| 273 | +#endif | |
| 274 | + | |
| 275 | +static const struct i2c_device_id stk8ba50_i2c_id[] = { | |
| 276 | + {"stk8ba50", 0}, | |
| 277 | + {} | |
| 278 | +}; | |
| 279 | + | |
| 280 | +static const struct acpi_device_id stk8ba50_acpi_id[] = { | |
| 281 | + {"STK8BA50", 0}, | |
| 282 | + {} | |
| 283 | +}; | |
| 284 | + | |
| 285 | +MODULE_DEVICE_TABLE(acpi, stk8ba50_acpi_id); | |
| 286 | + | |
| 287 | +static struct i2c_driver stk8ba50_driver = { | |
| 288 | + .driver = { | |
| 289 | + .name = "stk8ba50", | |
| 290 | + .pm = STK8BA50_PM_OPS, | |
| 291 | + .acpi_match_table = ACPI_PTR(stk8ba50_acpi_id), | |
| 292 | + }, | |
| 293 | + .probe = stk8ba50_probe, | |
| 294 | + .remove = stk8ba50_remove, | |
| 295 | + .id_table = stk8ba50_i2c_id, | |
| 296 | +}; | |
| 297 | + | |
| 298 | +module_i2c_driver(stk8ba50_driver); | |
| 299 | + | |
| 300 | +MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); | |
| 301 | +MODULE_DESCRIPTION("STK8BA50 3-Axis Accelerometer driver"); | |
| 302 | +MODULE_LICENSE("GPL v2"); | |
| @@ -135,6 +135,13 @@ config AXP288_ADC · 134 unmodified lines | ||
| 135 | 135 | device. Depending on platform configuration, this general purpose ADC can |
| 136 | 136 | be used for sampling sensors such as thermal resistors. |
| 137 | 137 | |
| 138 | +config BERLIN2_ADC | |
| 139 | + tristate "Marvell Berlin2 ADC driver" | |
| 140 | + depends on ARCH_BERLIN | |
| 141 | + help | |
| 142 | + Marvell Berlin2 ADC driver. This ADC has 8 channels, with one used for | |
| 143 | + temperature measurement. | |
| 144 | + | |
| 138 | 145 | config DA9150_GPADC |
| 139 | 146 | tristate "Dialog DA9150 GPADC driver support" |
| 140 | 147 | depends on MFD_DA9150 |
| @@ -285,11 +292,11 @@ config TI_ADC081C · 144 unmodified lines | ||
| 285 | 292 | called ti-adc081c. |
| 286 | 293 | |
| 287 | 294 | config TI_ADC128S052 |
| 288 | − tristate "Texas Instruments ADC128S052" | |
| 295 | + tristate "Texas Instruments ADC128S052/ADC122S021" | |
| 289 | 296 | depends on SPI |
| 290 | 297 | help |
| 291 | 298 | If you say yes here you get support for Texas Instruments ADC128S052 |
| 292 | − chip. | |
| 299 | + and ADC122S021 chips. | |
| 293 | 300 | |
| 294 | 301 | This driver can also be built as a module. If so, the module will be |
| 295 | 302 | called ti-adc128s052. |
| @@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o · 14 unmodified lines | ||
| 15 | 15 | obj-$(CONFIG_AD799X) += ad799x.o |
| 16 | 16 | obj-$(CONFIG_AT91_ADC) += at91_adc.o |
| 17 | 17 | obj-$(CONFIG_AXP288_ADC) += axp288_adc.o |
| 18 | +obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o | |
| 18 | 19 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o |
| 19 | 20 | obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o |
| 20 | 21 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o |
| @@ -238,7 +238,7 @@ static int axp288_adc_remove(struct platform_device *pdev) · 237 unmodified lines | ||
| 238 | 238 | return 0; |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | −static struct platform_device_id axp288_adc_id_table[] = { | |
| 241 | +static const struct platform_device_id axp288_adc_id_table[] = { | |
| 242 | 242 | { .name = "axp288_adc" }, |
| 243 | 243 | {}, |
| 244 | 244 | }; |
| @@ -0,0 +1,378 @@ | ||
| 1 | +/* | |
| 2 | + * Marvell Berlin2 ADC driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2015 Marvell Technology Group Ltd. | |
| 5 | + * | |
| 6 | + * Antoine Tenart <antoine.tenart@free-electrons.com> | |
| 7 | + * | |
| 8 | + * This file is licensed under the terms of the GNU General Public | |
| 9 | + * License version 2. This program is licensed "as is" without any | |
| 10 | + * warranty of any kind, whether express or implied. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/iio/iio.h> | |
| 14 | +#include <linux/iio/driver.h> | |
| 15 | +#include <linux/iio/machine.h> | |
| 16 | +#include <linux/interrupt.h> | |
| 17 | +#include <linux/kernel.h> | |
| 18 | +#include <linux/module.h> | |
| 19 | +#include <linux/platform_device.h> | |
| 20 | +#include <linux/slab.h> | |
| 21 | +#include <linux/mfd/syscon.h> | |
| 22 | +#include <linux/regmap.h> | |
| 23 | +#include <linux/sched.h> | |
| 24 | +#include <linux/wait.h> | |
| 25 | + | |
| 26 | +#define BERLIN2_SM_CTRL 0x14 | |
| 27 | +#define BERLIN2_SM_CTRL_SM_SOC_INT BIT(1) | |
| 28 | +#define BERLIN2_SM_CTRL_SOC_SM_INT BIT(2) | |
| 29 | +#define BERLIN2_SM_CTRL_ADC_SEL(x) (BIT(x) << 5) /* 0-15 */ | |
| 30 | +#define BERLIN2_SM_CTRL_ADC_SEL_MASK (0xf << 5) | |
| 31 | +#define BERLIN2_SM_CTRL_ADC_POWER BIT(9) | |
| 32 | +#define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2 (0x0 << 10) | |
| 33 | +#define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV3 (0x1 << 10) | |
| 34 | +#define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV4 (0x2 << 10) | |
| 35 | +#define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV8 (0x3 << 10) | |
| 36 | +#define BERLIN2_SM_CTRL_ADC_CLKSEL_MASK (0x3 << 10) | |
| 37 | +#define BERLIN2_SM_CTRL_ADC_START BIT(12) | |
| 38 | +#define BERLIN2_SM_CTRL_ADC_RESET BIT(13) | |
| 39 | +#define BERLIN2_SM_CTRL_ADC_BANDGAP_RDY BIT(14) | |
| 40 | +#define BERLIN2_SM_CTRL_ADC_CONT_SINGLE (0x0 << 15) | |
| 41 | +#define BERLIN2_SM_CTRL_ADC_CONT_CONTINUOUS (0x1 << 15) | |
| 42 | +#define BERLIN2_SM_CTRL_ADC_BUFFER_EN BIT(16) | |
| 43 | +#define BERLIN2_SM_CTRL_ADC_VREF_EXT (0x0 << 17) | |
| 44 | +#define BERLIN2_SM_CTRL_ADC_VREF_INT (0x1 << 17) | |
| 45 | +#define BERLIN2_SM_CTRL_ADC_ROTATE BIT(19) | |
| 46 | +#define BERLIN2_SM_CTRL_TSEN_EN BIT(20) | |
| 47 | +#define BERLIN2_SM_CTRL_TSEN_CLK_SEL_125 (0x0 << 21) /* 1.25 MHz */ | |
| 48 | +#define BERLIN2_SM_CTRL_TSEN_CLK_SEL_250 (0x1 << 21) /* 2.5 MHz */ | |
| 49 | +#define BERLIN2_SM_CTRL_TSEN_MODE_0_125 (0x0 << 22) /* 0-125 C */ | |
| 50 | +#define BERLIN2_SM_CTRL_TSEN_MODE_10_50 (0x1 << 22) /* 10-50 C */ | |
| 51 | +#define BERLIN2_SM_CTRL_TSEN_RESET BIT(29) | |
| 52 | +#define BERLIN2_SM_ADC_DATA 0x20 | |
| 53 | +#define BERLIN2_SM_ADC_MASK 0x3ff | |
| 54 | +#define BERLIN2_SM_ADC_STATUS 0x1c | |
| 55 | +#define BERLIN2_SM_ADC_STATUS_DATA_RDY(x) BIT(x) /* 0-15 */ | |
| 56 | +#define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK 0xf | |
| 57 | +#define BERLIN2_SM_ADC_STATUS_INT_EN(x) (BIT(x) << 16) /* 0-15 */ | |
| 58 | +#define BERLIN2_SM_ADC_STATUS_INT_EN_MASK (0xf << 16) | |
| 59 | +#define BERLIN2_SM_TSEN_STATUS 0x24 | |
| 60 | +#define BERLIN2_SM_TSEN_STATUS_DATA_RDY BIT(0) | |
| 61 | +#define BERLIN2_SM_TSEN_STATUS_INT_EN BIT(1) | |
| 62 | +#define BERLIN2_SM_TSEN_DATA 0x28 | |
| 63 | +#define BERLIN2_SM_TSEN_MASK 0xfff | |
| 64 | +#define BERLIN2_SM_TSEN_CTRL 0x74 | |
| 65 | +#define BERLIN2_SM_TSEN_CTRL_START BIT(8) | |
| 66 | +#define BERLIN2_SM_TSEN_CTRL_SETTLING_4 (0x0 << 21) /* 4 us */ | |
| 67 | +#define BERLIN2_SM_TSEN_CTRL_SETTLING_12 (0x1 << 21) /* 12 us */ | |
| 68 | +#define BERLIN2_SM_TSEN_CTRL_SETTLING_MASK (0x1 << 21) | |
| 69 | +#define BERLIN2_SM_TSEN_CTRL_TRIM(x) ((x) << 22) | |
| 70 | +#define BERLIN2_SM_TSEN_CTRL_TRIM_MASK (0xf << 22) | |
| 71 | + | |
| 72 | +struct berlin2_adc_priv { | |
| 73 | + struct regmap *regmap; | |
| 74 | + struct mutex lock; | |
| 75 | + wait_queue_head_t wq; | |
| 76 | + bool data_available; | |
| 77 | + int data; | |
| 78 | +}; | |
| 79 | + | |
| 80 | +#define BERLIN2_ADC_CHANNEL(n, t) \ | |
| 81 | + { \ | |
| 82 | + .channel = n, \ | |
| 83 | + .datasheet_name = "channel"#n, \ | |
| 84 | + .type = t, \ | |
| 85 | + .indexed = 1, \ | |
| 86 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 87 | + } | |
| 88 | + | |
| 89 | +static struct iio_chan_spec berlin2_adc_channels[] = { | |
| 90 | + BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE), /* external input */ | |
| 91 | + BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE), /* external input */ | |
| 92 | + BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE), /* external input */ | |
| 93 | + BERLIN2_ADC_CHANNEL(3, IIO_VOLTAGE), /* external input */ | |
| 94 | + BERLIN2_ADC_CHANNEL(4, IIO_VOLTAGE), /* reserved */ | |
| 95 | + BERLIN2_ADC_CHANNEL(5, IIO_VOLTAGE), /* reserved */ | |
| 96 | + { /* temperature sensor */ | |
| 97 | + .channel = 6, | |
| 98 | + .datasheet_name = "channel6", | |
| 99 | + .type = IIO_TEMP, | |
| 100 | + .indexed = 0, | |
| 101 | + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | |
| 102 | + }, | |
| 103 | + BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE), /* reserved */ | |
| 104 | + IIO_CHAN_SOFT_TIMESTAMP(8), /* timestamp */ | |
| 105 | +}; | |
| 106 | +#define BERLIN2_N_CHANNELS ARRAY_SIZE(berlin2_adc_channels) | |
| 107 | + | |
| 108 | +static int berlin2_adc_read(struct iio_dev *indio_dev, int channel) | |
| 109 | +{ | |
| 110 | + struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
| 111 | + int data, ret; | |
| 112 | + | |
| 113 | + mutex_lock(&priv->lock); | |
| 114 | + | |
| 115 | + /* Configure the ADC */ | |
| 116 | + regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
| 117 | + BERLIN2_SM_CTRL_ADC_RESET | BERLIN2_SM_CTRL_ADC_SEL_MASK | |
| 118 | + | BERLIN2_SM_CTRL_ADC_START, | |
| 119 | + BERLIN2_SM_CTRL_ADC_SEL(channel) | BERLIN2_SM_CTRL_ADC_START); | |
| 120 | + | |
| 121 | + ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, | |
| 122 | + msecs_to_jiffies(1000)); | |
| 123 | + | |
| 124 | + /* Disable the interrupts */ | |
| 125 | + regmap_update_bits(priv->regmap, BERLIN2_SM_ADC_STATUS, | |
| 126 | + BERLIN2_SM_ADC_STATUS_INT_EN(channel), 0); | |
| 127 | + | |
| 128 | + if (ret == 0) | |
| 129 | + ret = -ETIMEDOUT; | |
| 130 | + if (ret < 0) { | |
| 131 | + mutex_unlock(&priv->lock); | |
| 132 | + return ret; | |
| 133 | + } | |
| 134 | + | |
| 135 | + regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
| 136 | + BERLIN2_SM_CTRL_ADC_START, 0); | |
| 137 | + | |
| 138 | + data = priv->data; | |
| 139 | + priv->data_available = false; | |
| 140 | + | |
| 141 | + mutex_unlock(&priv->lock); | |
| 142 | + | |
| 143 | + return data; | |
| 144 | +} | |
| 145 | + | |
| 146 | +static int berlin2_adc_tsen_read(struct iio_dev *indio_dev) | |
| 147 | +{ | |
| 148 | + struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
| 149 | + int data, ret; | |
| 150 | + | |
| 151 | + mutex_lock(&priv->lock); | |
| 152 | + | |
| 153 | + /* Configure the ADC */ | |
| 154 | + regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
| 155 | + BERLIN2_SM_CTRL_TSEN_RESET | BERLIN2_SM_CTRL_ADC_ROTATE, | |
| 156 | + BERLIN2_SM_CTRL_ADC_ROTATE); | |
| 157 | + | |
| 158 | + /* Configure the temperature sensor */ | |
| 159 | + regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, | |
| 160 | + BERLIN2_SM_TSEN_CTRL_TRIM_MASK | BERLIN2_SM_TSEN_CTRL_SETTLING_MASK | |
| 161 | + | BERLIN2_SM_TSEN_CTRL_START, | |
| 162 | + BERLIN2_SM_TSEN_CTRL_TRIM(3) | BERLIN2_SM_TSEN_CTRL_SETTLING_12 | |
| 163 | + | BERLIN2_SM_TSEN_CTRL_START); | |
| 164 | + | |
| 165 | + ret = wait_event_interruptible_timeout(priv->wq, priv->data_available, | |
| 166 | + msecs_to_jiffies(1000)); | |
| 167 | + | |
| 168 | + /* Disable interrupts */ | |
| 169 | + regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_STATUS, | |
| 170 | + BERLIN2_SM_TSEN_STATUS_INT_EN, 0); | |
| 171 | + | |
| 172 | + if (ret == 0) | |
| 173 | + ret = -ETIMEDOUT; | |
| 174 | + if (ret < 0) { | |
| 175 | + mutex_unlock(&priv->lock); | |
| 176 | + return ret; | |
| 177 | + } | |
| 178 | + | |
| 179 | + regmap_update_bits(priv->regmap, BERLIN2_SM_TSEN_CTRL, | |
| 180 | + BERLIN2_SM_TSEN_CTRL_START, 0); | |
| 181 | + | |
| 182 | + data = priv->data; | |
| 183 | + priv->data_available = false; | |
| 184 | + | |
| 185 | + mutex_unlock(&priv->lock); | |
| 186 | + | |
| 187 | + return data; | |
| 188 | +} | |
| 189 | + | |
| 190 | +static int berlin2_adc_read_raw(struct iio_dev *indio_dev, | |
| 191 | + struct iio_chan_spec const *chan, int *val, int *val2, | |
| 192 | + long mask) | |
| 193 | +{ | |
| 194 | + struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
| 195 | + int temp; | |
| 196 | + | |
| 197 | + switch (mask) { | |
| 198 | + case IIO_CHAN_INFO_RAW: | |
| 199 | + if (chan->type != IIO_VOLTAGE) | |
| 200 | + return -EINVAL; | |
| 201 | + | |
| 202 | + /* Enable the interrupts */ | |
| 203 | + regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS, | |
| 204 | + BERLIN2_SM_ADC_STATUS_INT_EN(chan->channel)); | |
| 205 | + | |
| 206 | + *val = berlin2_adc_read(indio_dev, chan->channel); | |
| 207 | + if (*val < 0) | |
| 208 | + return *val; | |
| 209 | + | |
| 210 | + return IIO_VAL_INT; | |
| 211 | + case IIO_CHAN_INFO_PROCESSED: | |
| 212 | + if (chan->type != IIO_TEMP) | |
| 213 | + return -EINVAL; | |
| 214 | + | |
| 215 | + /* Enable interrupts */ | |
| 216 | + regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS, | |
| 217 | + BERLIN2_SM_TSEN_STATUS_INT_EN); | |
| 218 | + | |
| 219 | + temp = berlin2_adc_tsen_read(indio_dev); | |
| 220 | + if (temp < 0) | |
| 221 | + return temp; | |
| 222 | + | |
| 223 | + if (temp > 2047) | |
| 224 | + temp = -(4096 - temp); | |
| 225 | + | |
| 226 | + /* Convert to milli Celsius */ | |
| 227 | + *val = ((temp * 100000) / 264 - 270000); | |
| 228 | + return IIO_VAL_INT; | |
| 229 | + default: | |
| 230 | + break; | |
| 231 | + } | |
| 232 | + | |
| 233 | + return -EINVAL; | |
| 234 | +} | |
| 235 | + | |
| 236 | +static irqreturn_t berlin2_adc_irq(int irq, void *private) | |
| 237 | +{ | |
| 238 | + struct berlin2_adc_priv *priv = iio_priv(private); | |
| 239 | + unsigned val; | |
| 240 | + | |
| 241 | + regmap_read(priv->regmap, BERLIN2_SM_ADC_STATUS, &val); | |
| 242 | + if (val & BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK) { | |
| 243 | + regmap_read(priv->regmap, BERLIN2_SM_ADC_DATA, &priv->data); | |
| 244 | + priv->data &= BERLIN2_SM_ADC_MASK; | |
| 245 | + | |
| 246 | + val &= ~BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK; | |
| 247 | + regmap_write(priv->regmap, BERLIN2_SM_ADC_STATUS, val); | |
| 248 | + | |
| 249 | + priv->data_available = true; | |
| 250 | + wake_up_interruptible(&priv->wq); | |
| 251 | + } | |
| 252 | + | |
| 253 | + return IRQ_HANDLED; | |
| 254 | +} | |
| 255 | + | |
| 256 | +static irqreturn_t berlin2_adc_tsen_irq(int irq, void *private) | |
| 257 | +{ | |
| 258 | + struct berlin2_adc_priv *priv = iio_priv(private); | |
| 259 | + unsigned val; | |
| 260 | + | |
| 261 | + regmap_read(priv->regmap, BERLIN2_SM_TSEN_STATUS, &val); | |
| 262 | + if (val & BERLIN2_SM_TSEN_STATUS_DATA_RDY) { | |
| 263 | + regmap_read(priv->regmap, BERLIN2_SM_TSEN_DATA, &priv->data); | |
| 264 | + priv->data &= BERLIN2_SM_TSEN_MASK; | |
| 265 | + | |
| 266 | + val &= ~BERLIN2_SM_TSEN_STATUS_DATA_RDY; | |
| 267 | + regmap_write(priv->regmap, BERLIN2_SM_TSEN_STATUS, val); | |
| 268 | + | |
| 269 | + priv->data_available = true; | |
| 270 | + wake_up_interruptible(&priv->wq); | |
| 271 | + } | |
| 272 | + | |
| 273 | + return IRQ_HANDLED; | |
| 274 | +} | |
| 275 | + | |
| 276 | +static const struct iio_info berlin2_adc_info = { | |
| 277 | + .driver_module = THIS_MODULE, | |
| 278 | + .read_raw = berlin2_adc_read_raw, | |
| 279 | +}; | |
| 280 | + | |
| 281 | +static int berlin2_adc_probe(struct platform_device *pdev) | |
| 282 | +{ | |
| 283 | + struct iio_dev *indio_dev; | |
| 284 | + struct berlin2_adc_priv *priv; | |
| 285 | + struct device_node *parent_np = of_get_parent(pdev->dev.of_node); | |
| 286 | + int irq, tsen_irq; | |
| 287 | + int ret; | |
| 288 | + | |
| 289 | + indio_dev = devm_iio_device_alloc(&pdev->dev, | |
| 290 | + sizeof(struct berlin2_adc_priv)); | |
| 291 | + if (!indio_dev) | |
| 292 | + return -ENOMEM; | |
| 293 | + | |
| 294 | + priv = iio_priv(indio_dev); | |
| 295 | + platform_set_drvdata(pdev, indio_dev); | |
| 296 | + | |
| 297 | + priv->regmap = syscon_node_to_regmap(parent_np); | |
| 298 | + of_node_put(parent_np); | |
| 299 | + if (IS_ERR(priv->regmap)) | |
| 300 | + return PTR_ERR(priv->regmap); | |
| 301 | + | |
| 302 | + irq = platform_get_irq_byname(pdev, "adc"); | |
| 303 | + if (irq < 0) | |
| 304 | + return -ENODEV; | |
| 305 | + | |
| 306 | + tsen_irq = platform_get_irq_byname(pdev, "tsen"); | |
| 307 | + if (tsen_irq < 0) | |
| 308 | + return -ENODEV; | |
| 309 | + | |
| 310 | + ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0, | |
| 311 | + pdev->dev.driver->name, indio_dev); | |
| 312 | + if (ret) | |
| 313 | + return ret; | |
| 314 | + | |
| 315 | + ret = devm_request_irq(&pdev->dev, tsen_irq, berlin2_adc_tsen_irq, | |
| 316 | + 0, pdev->dev.driver->name, indio_dev); | |
| 317 | + if (ret) | |
| 318 | + return ret; | |
| 319 | + | |
| 320 | + init_waitqueue_head(&priv->wq); | |
| 321 | + mutex_init(&priv->lock); | |
| 322 | + | |
| 323 | + indio_dev->dev.parent = &pdev->dev; | |
| 324 | + indio_dev->name = dev_name(&pdev->dev); | |
| 325 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 326 | + indio_dev->info = &berlin2_adc_info; | |
| 327 | + | |
| 328 | + indio_dev->num_channels = BERLIN2_N_CHANNELS; | |
| 329 | + indio_dev->channels = berlin2_adc_channels; | |
| 330 | + | |
| 331 | + /* Power up the ADC */ | |
| 332 | + regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
| 333 | + BERLIN2_SM_CTRL_ADC_POWER, BERLIN2_SM_CTRL_ADC_POWER); | |
| 334 | + | |
| 335 | + ret = iio_device_register(indio_dev); | |
| 336 | + if (ret) { | |
| 337 | + /* Power down the ADC */ | |
| 338 | + regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
| 339 | + BERLIN2_SM_CTRL_ADC_POWER, 0); | |
| 340 | + return ret; | |
| 341 | + } | |
| 342 | + | |
| 343 | + return 0; | |
| 344 | +} | |
| 345 | + | |
| 346 | +static int berlin2_adc_remove(struct platform_device *pdev) | |
| 347 | +{ | |
| 348 | + struct iio_dev *indio_dev = platform_get_drvdata(pdev); | |
| 349 | + struct berlin2_adc_priv *priv = iio_priv(indio_dev); | |
| 350 | + | |
| 351 | + iio_device_unregister(indio_dev); | |
| 352 | + | |
| 353 | + /* Power down the ADC */ | |
| 354 | + regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL, | |
| 355 | + BERLIN2_SM_CTRL_ADC_POWER, 0); | |
| 356 | + | |
| 357 | + return 0; | |
| 358 | +} | |
| 359 | + | |
| 360 | +static const struct of_device_id berlin2_adc_match[] = { | |
| 361 | + { .compatible = "marvell,berlin2-adc", }, | |
| 362 | + { }, | |
| 363 | +}; | |
| 364 | +MODULE_DEVICE_TABLE(of, berlin2_adc_match); | |
| 365 | + | |
| 366 | +static struct platform_driver berlin2_adc_driver = { | |
| 367 | + .driver = { | |
| 368 | + .name = "berlin2-adc", | |
| 369 | + .of_match_table = berlin2_adc_match, | |
| 370 | + }, | |
| 371 | + .probe = berlin2_adc_probe, | |
| 372 | + .remove = berlin2_adc_remove, | |
| 373 | +}; | |
| 374 | +module_platform_driver(berlin2_adc_driver); | |
| 375 | + | |
| 376 | +MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>"); | |
| 377 | +MODULE_DESCRIPTION("Marvell Berlin2 ADC driver"); | |
| 378 | +MODULE_LICENSE("GPL v2"); | |
| @@ -1,9 +1,10 @@ | ||
| 1 | 1 | /* |
| 2 | 2 | * Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com> |
| 3 | 3 | * |
| 4 | − * Driver for Texas Instruments' ADC128S052 ADC chip. | |
| 5 | − * Datasheet can be found here: | |
| 4 | + * Driver for Texas Instruments' ADC128S052 and ADC122S021 ADC chip. | |
| 5 | + * Datasheets can be found here: | |
| 6 | 6 | * http://www.ti.com/lit/ds/symlink/adc128s052.pdf |
| 7 | + * http://www.ti.com/lit/ds/symlink/adc122s021.pdf | |
| 7 | 8 | * |
| 8 | 9 | * This program is free software; you can redistribute it and/or modify |
| 9 | 10 | * it under the terms of the GNU General Public License version 2 as |
| @@ -16,6 +17,11 @@ · 6 unmodified lines | ||
| 16 | 17 | #include <linux/iio/iio.h> |
| 17 | 18 | #include <linux/regulator/consumer.h> |
| 18 | 19 | |
| 20 | +struct adc128_configuration { | |
| 21 | + const struct iio_chan_spec *channels; | |
| 22 | + u8 num_channels; | |
| 23 | +}; | |
| 24 | + | |
| 19 | 25 | struct adc128 { |
| 20 | 26 | struct spi_device *spi; |
| 21 | 27 | |
| @@ -92,7 +98,7 @@ static int adc128_read_raw(struct iio_dev *indio_dev, · 70 unmodified lines | ||
| 92 | 98 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ |
| 93 | 99 | } |
| 94 | 100 | |
| 95 | −static const struct iio_chan_spec adc128_channels[] = { | |
| 101 | +static const struct iio_chan_spec adc128s052_channels[] = { | |
| 96 | 102 | ADC128_VOLTAGE_CHANNEL(0), |
| 97 | 103 | ADC128_VOLTAGE_CHANNEL(1), |
| 98 | 104 | ADC128_VOLTAGE_CHANNEL(2), |
| @@ -103,6 +109,16 @@ static const struct iio_chan_spec adc128_channels[] = { · 4 unmodified lines | ||
| 103 | 109 | ADC128_VOLTAGE_CHANNEL(7), |
| 104 | 110 | }; |
| 105 | 111 | |
| 112 | +static const struct iio_chan_spec adc122s021_channels[] = { | |
| 113 | + ADC128_VOLTAGE_CHANNEL(0), | |
| 114 | + ADC128_VOLTAGE_CHANNEL(1), | |
| 115 | +}; | |
| 116 | + | |
| 117 | +static const struct adc128_configuration adc128_config[] = { | |
| 118 | + { adc128s052_channels, ARRAY_SIZE(adc128s052_channels) }, | |
| 119 | + { adc122s021_channels, ARRAY_SIZE(adc122s021_channels) }, | |
| 120 | +}; | |
| 121 | + | |
| 106 | 122 | static const struct iio_info adc128_info = { |
| 107 | 123 | .read_raw = adc128_read_raw, |
| 108 | 124 | .driver_module = THIS_MODULE, |
| @@ -112,6 +128,7 @@ static int adc128_probe(struct spi_device *spi) · 3 unmodified lines | ||
| 112 | 128 | { |
| 113 | 129 | struct iio_dev *indio_dev; |
| 114 | 130 | struct adc128 *adc; |
| 131 | + int config = spi_get_device_id(spi)->driver_data; | |
| 115 | 132 | int ret; |
| 116 | 133 | |
| 117 | 134 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); |
| @@ -128,8 +145,8 @@ static int adc128_probe(struct spi_device *spi) · 10 unmodified lines | ||
| 128 | 145 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 129 | 146 | indio_dev->info = &adc128_info; |
| 130 | 147 | |
| 131 | − indio_dev->channels = adc128_channels; | |
| 132 | − indio_dev->num_channels = ARRAY_SIZE(adc128_channels); | |
| 148 | + indio_dev->channels = adc128_config[config].channels; | |
| 149 | + indio_dev->num_channels = adc128_config[config].num_channels; | |
| 133 | 150 | |
| 134 | 151 | adc->reg = devm_regulator_get(&spi->dev, "vref"); |
| 135 | 152 | if (IS_ERR(adc->reg)) |
| @@ -158,7 +175,8 @@ static int adc128_remove(struct spi_device *spi) · 22 unmodified lines | ||
| 158 | 175 | } |
| 159 | 176 | |
| 160 | 177 | static const struct spi_device_id adc128_id[] = { |
| 161 | − { "adc128s052", 0}, | |
| 178 | + { "adc128s052", 0}, /* index into adc128_config */ | |
| 179 | + { "adc122s021", 1}, | |
| 162 | 180 | { } |
| 163 | 181 | }; |
| 164 | 182 | MODULE_DEVICE_TABLE(spi, adc128_id); |
| @@ -37,6 +37,7 @@ struct tiadc_device { · 36 unmodified lines | ||
| 37 | 37 | u8 channel_step[8]; |
| 38 | 38 | int buffer_en_ch_steps; |
| 39 | 39 | u16 data[8]; |
| 40 | + u32 open_delay[8], sample_delay[8], step_avg[8]; | |
| 40 | 41 | }; |
| 41 | 42 | |
| 42 | 43 | static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) |
| @@ -85,6 +86,7 @@ static u32 get_adc_step_bit(struct tiadc_device *adc_dev, int chan) · 42 unmodified lines | ||
| 85 | 86 | static void tiadc_step_config(struct iio_dev *indio_dev) |
| 86 | 87 | { |
| 87 | 88 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
| 89 | + struct device *dev = adc_dev->mfd_tscadc->dev; | |
| 88 | 90 | unsigned int stepconfig; |
| 89 | 91 | int i, steps = 0; |
| 90 | 92 | |
| @@ -98,20 +100,47 @@ static void tiadc_step_config(struct iio_dev *indio_dev) · 7 unmodified lines | ||
| 98 | 100 | * needs to be given to ADC to digitalize data. |
| 99 | 101 | */ |
| 100 | 102 | |
| 101 | − if (iio_buffer_enabled(indio_dev)) | |
| 102 | − stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1 | |
| 103 | − | STEPCONFIG_MODE_SWCNT; | |
| 104 | − else | |
| 105 | − stepconfig = STEPCONFIG_AVG_16 | STEPCONFIG_FIFO1; | |
| 106 | 103 | |
| 107 | 104 | for (i = 0; i < adc_dev->channels; i++) { |
| 108 | 105 | int chan; |
| 109 | 106 | |
| 110 | 107 | chan = adc_dev->channel_line[i]; |
| 108 | + | |
| 109 | + if (adc_dev->step_avg[i] > STEPCONFIG_AVG_16) { | |
| 110 | + dev_warn(dev, "chan %d step_avg truncating to %d\n", | |
| 111 | + chan, STEPCONFIG_AVG_16); | |
| 112 | + adc_dev->step_avg[i] = STEPCONFIG_AVG_16; | |
| 113 | + } | |
| 114 | + | |
| 115 | + if (adc_dev->step_avg[i]) | |
| 116 | + stepconfig = | |
| 117 | + STEPCONFIG_AVG(ffs(adc_dev->step_avg[i]) - 1) | | |
| 118 | + STEPCONFIG_FIFO1; | |
| 119 | + else | |
| 120 | + stepconfig = STEPCONFIG_FIFO1; | |
| 121 | + | |
| 122 | + if (iio_buffer_enabled(indio_dev)) | |
| 123 | + stepconfig |= STEPCONFIG_MODE_SWCNT; | |
| 124 | + | |
| 111 | 125 | tiadc_writel(adc_dev, REG_STEPCONFIG(steps), |
| 112 | 126 | stepconfig | STEPCONFIG_INP(chan)); |
| 127 | + | |
| 128 | + if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) { | |
| 129 | + dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n", | |
| 130 | + chan); | |
| 131 | + adc_dev->open_delay[i] = STEPDELAY_OPEN_MASK; | |
| 132 | + } | |
| 133 | + | |
| 134 | + if (adc_dev->sample_delay[i] > 0xFF) { | |
| 135 | + dev_warn(dev, "chan %d sample delay truncating to 0xFF\n", | |
| 136 | + chan); | |
| 137 | + adc_dev->sample_delay[i] = 0xFF; | |
| 138 | + } | |
| 139 | + | |
| 113 | 140 | tiadc_writel(adc_dev, REG_STEPDELAY(steps), |
| 114 | − STEPCONFIG_OPENDLY); | |
| 141 | + STEPDELAY_OPEN(adc_dev->open_delay[i]) | | |
| 142 | + STEPDELAY_SAMPLE(adc_dev->sample_delay[i])); | |
| 143 | + | |
| 115 | 144 | adc_dev->channel_step[i] = steps; |
| 116 | 145 | steps++; |
| 117 | 146 | } |
| @@ -395,16 +424,43 @@ static const struct iio_info tiadc_info = { · 277 unmodified lines | ||
| 395 | 424 | .driver_module = THIS_MODULE, |
| 396 | 425 | }; |
| 397 | 426 | |
| 427 | +static int tiadc_parse_dt(struct platform_device *pdev, | |
| 428 | + struct tiadc_device *adc_dev) | |
| 429 | +{ | |
| 430 | + struct device_node *node = pdev->dev.of_node; | |
| 431 | + struct property *prop; | |
| 432 | + const __be32 *cur; | |
| 433 | + int channels = 0; | |
| 434 | + u32 val; | |
| 435 | + | |
| 436 | + of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { | |
| 437 | + adc_dev->channel_line[channels] = val; | |
| 438 | + | |
| 439 | + /* Set Default values for optional DT parameters */ | |
| 440 | + adc_dev->open_delay[channels] = STEPCONFIG_OPENDLY; | |
| 441 | + adc_dev->sample_delay[channels] = STEPCONFIG_SAMPLEDLY; | |
| 442 | + adc_dev->step_avg[channels] = 16; | |
| 443 | + | |
| 444 | + channels++; | |
| 445 | + } | |
| 446 | + | |
| 447 | + of_property_read_u32_array(node, "ti,chan-step-avg", | |
| 448 | + adc_dev->step_avg, channels); | |
| 449 | + of_property_read_u32_array(node, "ti,chan-step-opendelay", | |
| 450 | + adc_dev->open_delay, channels); | |
| 451 | + of_property_read_u32_array(node, "ti,chan-step-sampledelay", | |
| 452 | + adc_dev->sample_delay, channels); | |
| 453 | + | |
| 454 | + adc_dev->channels = channels; | |
| 455 | + return 0; | |
| 456 | +} | |
| 457 | + | |
| 398 | 458 | static int tiadc_probe(struct platform_device *pdev) |
| 399 | 459 | { |
| 400 | 460 | struct iio_dev *indio_dev; |
| 401 | 461 | struct tiadc_device *adc_dev; |
| 402 | 462 | struct device_node *node = pdev->dev.of_node; |
| 403 | − struct property *prop; | |
| 404 | − const __be32 *cur; | |
| 405 | 463 | int err; |
| 406 | − u32 val; | |
| 407 | − int channels = 0; | |
| 408 | 464 | |
| 409 | 465 | if (!node) { |
| 410 | 466 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); |
| @@ -420,12 +476,7 @@ static int tiadc_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 420 | 476 | adc_dev = iio_priv(indio_dev); |
| 421 | 477 | |
| 422 | 478 | adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); |
| 423 | − | |
| 424 | − of_property_for_each_u32(node, "ti,adc-channels", prop, cur, val) { | |
| 425 | − adc_dev->channel_line[channels] = val; | |
| 426 | − channels++; | |
| 427 | − } | |
| 428 | − adc_dev->channels = channels; | |
| 479 | + tiadc_parse_dt(pdev, adc_dev); | |
| 429 | 480 | |
| 430 | 481 | indio_dev->dev.parent = &pdev->dev; |
| 431 | 482 | indio_dev->name = dev_name(&pdev->dev); |
| @@ -235,7 +235,7 @@ static int twl4030battery_temperature(int raw_volt) · 234 unmodified lines | ||
| 235 | 235 | if (ret < 0) |
| 236 | 236 | return ret; |
| 237 | 237 | |
| 238 | − curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10; | |
| 238 | + curr = ((val & TWL4030_BCI_ITHSENS) + 1) * 10; | |
| 239 | 239 | /* Getting and calculating the thermistor resistance in ohms */ |
| 240 | 240 | res = volt * 1000 / curr; |
| 241 | 241 | /* calculating temperature */ |
| @@ -662,10 +662,8 @@ EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion); · 420 unmodified lines | ||
| 662 | 662 | * |
| 663 | 663 | * @madc: pointer to twl4030_madc_data struct |
| 664 | 664 | * @chan: can be one of the two values: |
| 665 | − * TWL4030_BCI_ITHEN | |
| 666 | − * Enables bias current for main battery type reading | |
| 667 | − * TWL4030_BCI_TYPEN | |
| 668 | − * Enables bias current for main battery temperature sensing | |
| 665 | + * 0 - Enables bias current for main battery type reading | |
| 666 | + * 1 - Enables bias current for main battery temperature sensing | |
| 669 | 667 | * @on: enable or disable chan. |
| 670 | 668 | * |
| 671 | 669 | * Function to enable or disable bias current for |
| @@ -118,15 +118,21 @@ enum average_sel { · 117 unmodified lines | ||
| 118 | 118 | VF610_ADC_SAMPLE_32, |
| 119 | 119 | }; |
| 120 | 120 | |
| 121 | +enum conversion_mode_sel { | |
| 122 | + VF610_ADC_CONV_NORMAL, | |
| 123 | + VF610_ADC_CONV_HIGH_SPEED, | |
| 124 | + VF610_ADC_CONV_LOW_POWER, | |
| 125 | +}; | |
| 126 | + | |
| 121 | 127 | struct vf610_adc_feature { |
| 122 | 128 | enum clk_sel clk_sel; |
| 123 | 129 | enum vol_ref vol_ref; |
| 130 | + enum conversion_mode_sel conv_mode; | |
| 124 | 131 | |
| 125 | 132 | int clk_div; |
| 126 | 133 | int sample_rate; |
| 127 | 134 | int res_mode; |
| 128 | 135 | |
| 129 | − bool lpm; | |
| 130 | 136 | bool calibration; |
| 131 | 137 | bool ovwren; |
| 132 | 138 | }; |
| @@ -139,6 +145,8 @@ struct vf610_adc { · 6 unmodified lines | ||
| 139 | 145 | u32 vref_uv; |
| 140 | 146 | u32 value; |
| 141 | 147 | struct regulator *vref; |
| 148 | + | |
| 149 | + u32 max_adck_rate[3]; | |
| 142 | 150 | struct vf610_adc_feature adc_feature; |
| 143 | 151 | |
| 144 | 152 | u32 sample_freq_avail[5]; |
| @@ -148,46 +156,22 @@ struct vf610_adc { · 3 unmodified lines | ||
| 148 | 156 | |
| 149 | 157 | static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; |
| 150 | 158 | |
| 151 | −#define VF610_ADC_CHAN(_idx, _chan_type) { \ | |
| 152 | − .type = (_chan_type), \ | |
| 153 | − .indexed = 1, \ | |
| 154 | − .channel = (_idx), \ | |
| 155 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 156 | − .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | |
| 157 | − BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | |
| 158 | −} | |
| 159 | − | |
| 160 | −#define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \ | |
| 161 | − .type = (_chan_type), \ | |
| 162 | − .channel = (_idx), \ | |
| 163 | − .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | |
| 164 | −} | |
| 165 | − | |
| 166 | −static const struct iio_chan_spec vf610_adc_iio_channels[] = { | |
| 167 | − VF610_ADC_CHAN(0, IIO_VOLTAGE), | |
| 168 | − VF610_ADC_CHAN(1, IIO_VOLTAGE), | |
| 169 | − VF610_ADC_CHAN(2, IIO_VOLTAGE), | |
| 170 | − VF610_ADC_CHAN(3, IIO_VOLTAGE), | |
| 171 | − VF610_ADC_CHAN(4, IIO_VOLTAGE), | |
| 172 | − VF610_ADC_CHAN(5, IIO_VOLTAGE), | |
| 173 | − VF610_ADC_CHAN(6, IIO_VOLTAGE), | |
| 174 | − VF610_ADC_CHAN(7, IIO_VOLTAGE), | |
| 175 | − VF610_ADC_CHAN(8, IIO_VOLTAGE), | |
| 176 | − VF610_ADC_CHAN(9, IIO_VOLTAGE), | |
| 177 | − VF610_ADC_CHAN(10, IIO_VOLTAGE), | |
| 178 | − VF610_ADC_CHAN(11, IIO_VOLTAGE), | |
| 179 | − VF610_ADC_CHAN(12, IIO_VOLTAGE), | |
| 180 | − VF610_ADC_CHAN(13, IIO_VOLTAGE), | |
| 181 | − VF610_ADC_CHAN(14, IIO_VOLTAGE), | |
| 182 | − VF610_ADC_CHAN(15, IIO_VOLTAGE), | |
| 183 | − VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP), | |
| 184 | − /* sentinel */ | |
| 185 | −}; | |
| 186 | − | |
| 187 | 159 | static inline void vf610_adc_calculate_rates(struct vf610_adc *info) |
| 188 | 160 | { |
| 161 | + struct vf610_adc_feature *adc_feature = &info->adc_feature; | |
| 189 | 162 | unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk); |
| 190 | − int i; | |
| 163 | + int divisor, i; | |
| 164 | + | |
| 165 | + adck_rate = info->max_adck_rate[adc_feature->conv_mode]; | |
| 166 | + | |
| 167 | + if (adck_rate) { | |
| 168 | + /* calculate clk divider which is within specification */ | |
| 169 | + divisor = ipg_rate / adck_rate; | |
| 170 | + adc_feature->clk_div = 1 << fls(divisor + 1); | |
| 171 | + } else { | |
| 172 | + /* fall-back value using a safe divisor */ | |
| 173 | + adc_feature->clk_div = 8; | |
| 174 | + } | |
| 191 | 175 | |
| 192 | 176 | /* |
| 193 | 177 | * Calculate ADC sample frequencies |
| @@ -219,10 +203,8 @@ static inline void vf610_adc_cfg_init(struct vf610_adc *info) · 25 unmodified lines | ||
| 219 | 203 | |
| 220 | 204 | adc_feature->res_mode = 12; |
| 221 | 205 | adc_feature->sample_rate = 1; |
| 222 | − adc_feature->lpm = true; | |
| 223 | 206 | |
| 224 | − /* Use a save ADCK which is below 20MHz on all devices */ | |
| 225 | − adc_feature->clk_div = 8; | |
| 207 | + adc_feature->conv_mode = VF610_ADC_CONV_LOW_POWER; | |
| 226 | 208 | |
| 227 | 209 | vf610_adc_calculate_rates(info); |
| 228 | 210 | } |
| @@ -304,10 +286,12 @@ static void vf610_adc_cfg_set(struct vf610_adc *info) · 75 unmodified lines | ||
| 304 | 286 | cfg_data = readl(info->regs + VF610_REG_ADC_CFG); |
| 305 | 287 | |
| 306 | 288 | cfg_data &= ~VF610_ADC_ADLPC_EN; |
| 307 | − if (adc_feature->lpm) | |
| 289 | + if (adc_feature->conv_mode == VF610_ADC_CONV_LOW_POWER) | |
| 308 | 290 | cfg_data |= VF610_ADC_ADLPC_EN; |
| 309 | 291 | |
| 310 | 292 | cfg_data &= ~VF610_ADC_ADHSC_EN; |
| 293 | + if (adc_feature->conv_mode == VF610_ADC_CONV_HIGH_SPEED) | |
| 294 | + cfg_data |= VF610_ADC_ADHSC_EN; | |
| 311 | 295 | |
| 312 | 296 | writel(cfg_data, info->regs + VF610_REG_ADC_CFG); |
| 313 | 297 | } |
| @@ -409,6 +393,81 @@ static void vf610_adc_hw_init(struct vf610_adc *info) · 95 unmodified lines | ||
| 409 | 393 | vf610_adc_cfg_set(info); |
| 410 | 394 | } |
| 411 | 395 | |
| 396 | +static int vf610_set_conversion_mode(struct iio_dev *indio_dev, | |
| 397 | + const struct iio_chan_spec *chan, | |
| 398 | + unsigned int mode) | |
| 399 | +{ | |
| 400 | + struct vf610_adc *info = iio_priv(indio_dev); | |
| 401 | + | |
| 402 | + mutex_lock(&indio_dev->mlock); | |
| 403 | + info->adc_feature.conv_mode = mode; | |
| 404 | + vf610_adc_calculate_rates(info); | |
| 405 | + vf610_adc_hw_init(info); | |
| 406 | + mutex_unlock(&indio_dev->mlock); | |
| 407 | + | |
| 408 | + return 0; | |
| 409 | +} | |
| 410 | + | |
| 411 | +static int vf610_get_conversion_mode(struct iio_dev *indio_dev, | |
| 412 | + const struct iio_chan_spec *chan) | |
| 413 | +{ | |
| 414 | + struct vf610_adc *info = iio_priv(indio_dev); | |
| 415 | + | |
| 416 | + return info->adc_feature.conv_mode; | |
| 417 | +} | |
| 418 | + | |
| 419 | +static const char * const vf610_conv_modes[] = { "normal", "high-speed", | |
| 420 | + "low-power" }; | |
| 421 | + | |
| 422 | +static const struct iio_enum vf610_conversion_mode = { | |
| 423 | + .items = vf610_conv_modes, | |
| 424 | + .num_items = ARRAY_SIZE(vf610_conv_modes), | |
| 425 | + .get = vf610_get_conversion_mode, | |
| 426 | + .set = vf610_set_conversion_mode, | |
| 427 | +}; | |
| 428 | + | |
| 429 | +static const struct iio_chan_spec_ext_info vf610_ext_info[] = { | |
| 430 | + IIO_ENUM("conversion_mode", IIO_SHARED_BY_DIR, &vf610_conversion_mode), | |
| 431 | + {}, | |
| 432 | +}; | |
| 433 | + | |
| 434 | +#define VF610_ADC_CHAN(_idx, _chan_type) { \ | |
| 435 | + .type = (_chan_type), \ | |
| 436 | + .indexed = 1, \ | |
| 437 | + .channel = (_idx), \ | |
| 438 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 439 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | |
| 440 | + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | |
| 441 | + .ext_info = vf610_ext_info, \ | |
| 442 | +} | |
| 443 | + | |
| 444 | +#define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \ | |
| 445 | + .type = (_chan_type), \ | |
| 446 | + .channel = (_idx), \ | |
| 447 | + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | |
| 448 | +} | |
| 449 | + | |
| 450 | +static const struct iio_chan_spec vf610_adc_iio_channels[] = { | |
| 451 | + VF610_ADC_CHAN(0, IIO_VOLTAGE), | |
| 452 | + VF610_ADC_CHAN(1, IIO_VOLTAGE), | |
| 453 | + VF610_ADC_CHAN(2, IIO_VOLTAGE), | |
| 454 | + VF610_ADC_CHAN(3, IIO_VOLTAGE), | |
| 455 | + VF610_ADC_CHAN(4, IIO_VOLTAGE), | |
| 456 | + VF610_ADC_CHAN(5, IIO_VOLTAGE), | |
| 457 | + VF610_ADC_CHAN(6, IIO_VOLTAGE), | |
| 458 | + VF610_ADC_CHAN(7, IIO_VOLTAGE), | |
| 459 | + VF610_ADC_CHAN(8, IIO_VOLTAGE), | |
| 460 | + VF610_ADC_CHAN(9, IIO_VOLTAGE), | |
| 461 | + VF610_ADC_CHAN(10, IIO_VOLTAGE), | |
| 462 | + VF610_ADC_CHAN(11, IIO_VOLTAGE), | |
| 463 | + VF610_ADC_CHAN(12, IIO_VOLTAGE), | |
| 464 | + VF610_ADC_CHAN(13, IIO_VOLTAGE), | |
| 465 | + VF610_ADC_CHAN(14, IIO_VOLTAGE), | |
| 466 | + VF610_ADC_CHAN(15, IIO_VOLTAGE), | |
| 467 | + VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP), | |
| 468 | + /* sentinel */ | |
| 469 | +}; | |
| 470 | + | |
| 412 | 471 | static int vf610_adc_read_data(struct vf610_adc *info) |
| 413 | 472 | { |
| 414 | 473 | int result; |
| @@ -651,6 +710,9 @@ static int vf610_adc_probe(struct platform_device *pdev) · 236 unmodified lines | ||
| 651 | 710 | |
| 652 | 711 | info->vref_uv = regulator_get_voltage(info->vref); |
| 653 | 712 | |
| 713 | + of_property_read_u32_array(pdev->dev.of_node, "fsl,adck-max-frequency", | |
| 714 | + info->max_adck_rate, 3); | |
| 715 | + | |
| 654 | 716 | platform_set_drvdata(pdev, indio_dev); |
| 655 | 717 | |
| 656 | 718 | init_completion(&info->completion); |
| @@ -33,6 +33,8 @@ static void iio_buffer_cb_release(struct iio_buffer *buffer) · 32 unmodified lines | ||
| 33 | 33 | static const struct iio_buffer_access_funcs iio_cb_access = { |
| 34 | 34 | .store_to = &iio_buffer_cb_store_to, |
| 35 | 35 | .release = &iio_buffer_cb_release, |
| 36 | + | |
| 37 | + .modes = INDIO_BUFFER_SOFTWARE | INDIO_BUFFER_TRIGGERED, | |
| 36 | 38 | }; |
| 37 | 39 | |
| 38 | 40 | struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, |
| @@ -245,6 +245,16 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev, · 244 unmodified lines | ||
| 245 | 245 | { |
| 246 | 246 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
| 247 | 247 | |
| 248 | + /* Sensor does not support interrupts */ | |
| 249 | + if (sdata->sensor_settings->drdy_irq.addr == 0) { | |
| 250 | + if (pdata->drdy_int_pin) | |
| 251 | + dev_info(&indio_dev->dev, | |
| 252 | + "DRDY on pin INT%d specified, but sensor " | |
| 253 | + "does not support interrupts\n", | |
| 254 | + pdata->drdy_int_pin); | |
| 255 | + return 0; | |
| 256 | + } | |
| 257 | + | |
| 248 | 258 | switch (pdata->drdy_int_pin) { |
| 249 | 259 | case 1: |
| 250 | 260 | if (sdata->sensor_settings->drdy_irq.mask_int1 == 0) { |
| @@ -285,7 +295,7 @@ static struct st_sensors_platform_data *st_sensors_of_probe(struct device *dev, · 34 unmodified lines | ||
| 285 | 295 | if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2)) |
| 286 | 296 | pdata->drdy_int_pin = (u8) val; |
| 287 | 297 | else |
| 288 | − pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 1; | |
| 298 | + pdata->drdy_int_pin = defdata ? defdata->drdy_int_pin : 0; | |
| 289 | 299 | |
| 290 | 300 | return pdata; |
| 291 | 301 | } |
| @@ -332,11 +342,13 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, · 40 unmodified lines | ||
| 332 | 342 | return err; |
| 333 | 343 | |
| 334 | 344 | /* set BDU */ |
| 335 | − err = st_sensors_write_data_with_mask(indio_dev, | |
| 345 | + if (sdata->sensor_settings->bdu.addr) { | |
| 346 | + err = st_sensors_write_data_with_mask(indio_dev, | |
| 336 | 347 | sdata->sensor_settings->bdu.addr, |
| 337 | 348 | sdata->sensor_settings->bdu.mask, true); |
| 338 | − if (err < 0) | |
| 339 | − return err; | |
| 349 | + if (err < 0) | |
| 350 | + return err; | |
| 351 | + } | |
| 340 | 352 | |
| 341 | 353 | err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); |
| 342 | 354 | |
| @@ -419,7 +431,9 @@ static int st_sensors_read_axis_data(struct iio_dev *indio_dev, · 76 unmodified lines | ||
| 419 | 431 | if (err < 0) |
| 420 | 432 | goto st_sensors_free_memory; |
| 421 | 433 | |
| 422 | − if (byte_for_channel == 2) | |
| 434 | + if (byte_for_channel == 1) | |
| 435 | + *data = (s8)*outdata; | |
| 436 | + else if (byte_for_channel == 2) | |
| 423 | 437 | *data = (s16)get_unaligned_le16(outdata); |
| 424 | 438 | else if (byte_for_channel == 3) |
| 425 | 439 | *data = (s32)st_sensors_get_unaligned_le24(outdata); |
| @@ -489,7 +503,8 @@ int st_sensors_check_device_support(struct iio_dev *indio_dev, · 63 unmodified lines | ||
| 489 | 503 | break; |
| 490 | 504 | } |
| 491 | 505 | if (n == ARRAY_SIZE(sensor_settings[i].sensors_supported)) { |
| 492 | − dev_err(&indio_dev->dev, "device name and WhoAmI mismatch.\n"); | |
| 506 | + dev_err(&indio_dev->dev, "device name \"%s\" and WhoAmI (0x%02x) mismatch", | |
| 507 | + indio_dev->name, wai); | |
| 493 | 508 | goto sensor_name_mismatch; |
| 494 | 509 | } |
| 495 | 510 | |
| @@ -37,8 +37,10 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, · 36 unmodified lines | ||
| 37 | 37 | IRQF_TRIGGER_RISING, |
| 38 | 38 | sdata->trig->name, |
| 39 | 39 | sdata->trig); |
| 40 | − if (err) | |
| 40 | + if (err) { | |
| 41 | + dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); | |
| 41 | 42 | goto request_irq_error; |
| 43 | + } | |
| 42 | 44 | |
| 43 | 45 | iio_trigger_set_drvdata(sdata->trig, indio_dev); |
| 44 | 46 | sdata->trig->ops = trigger_ops; |
| @@ -142,6 +142,16 @@ config AD7303 · 141 unmodified lines | ||
| 142 | 142 | To compile this driver as module choose M here: the module will be called |
| 143 | 143 | ad7303. |
| 144 | 144 | |
| 145 | +config M62332 | |
| 146 | + tristate "Mitsubishi M62332 DAC driver" | |
| 147 | + depends on I2C | |
| 148 | + help | |
| 149 | + If you say yes here you get support for the Mitsubishi M62332 | |
| 150 | + (I2C 8-Bit DACs with rail-to-rail outputs). | |
| 151 | + | |
| 152 | + This driver can also be built as a module. If so, the module | |
| 153 | + will be called m62332. | |
| 154 | + | |
| 145 | 155 | config MAX517 |
| 146 | 156 | tristate "Maxim MAX517/518/519/520/521 DAC driver" |
| 147 | 157 | depends on I2C |
| @@ -16,6 +16,7 @@ obj-$(CONFIG_AD5764) += ad5764.o · 15 unmodified lines | ||
| 16 | 16 | obj-$(CONFIG_AD5791) += ad5791.o |
| 17 | 17 | obj-$(CONFIG_AD5686) += ad5686.o |
| 18 | 18 | obj-$(CONFIG_AD7303) += ad7303.o |
| 19 | +obj-$(CONFIG_M62332) += m62332.o | |
| 19 | 20 | obj-$(CONFIG_MAX517) += max517.o |
| 20 | 21 | obj-$(CONFIG_MAX5821) += max5821.o |
| 21 | 22 | obj-$(CONFIG_MCP4725) += mcp4725.o |
| @@ -0,0 +1,269 @@ | ||
| 1 | +/* | |
| 2 | + * m62332.c - Support for Mitsubishi m62332 DAC | |
| 3 | + * | |
| 4 | + * Copyright (c) 2014 Dmitry Eremin-Solenikov | |
| 5 | + * | |
| 6 | + * Based on max517 driver: | |
| 7 | + * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> | |
| 8 | + * | |
| 9 | + * This program is free software; you can redistribute it and/or modify | |
| 10 | + * it under the terms of the GNU General Public License as published by | |
| 11 | + * the Free Software Foundation; either version 2 of the License, or | |
| 12 | + * (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This program is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <linux/module.h> | |
| 21 | +#include <linux/slab.h> | |
| 22 | +#include <linux/i2c.h> | |
| 23 | +#include <linux/err.h> | |
| 24 | + | |
| 25 | +#include <linux/iio/iio.h> | |
| 26 | +#include <linux/iio/driver.h> | |
| 27 | + | |
| 28 | +#include <linux/regulator/consumer.h> | |
| 29 | + | |
| 30 | +#define M62332_CHANNELS 2 | |
| 31 | + | |
| 32 | +struct m62332_data { | |
| 33 | + struct i2c_client *client; | |
| 34 | + u16 vref_mv; | |
| 35 | + struct regulator *vcc; | |
| 36 | + struct mutex mutex; | |
| 37 | + u8 raw[M62332_CHANNELS]; | |
| 38 | +#ifdef CONFIG_PM_SLEEP | |
| 39 | + u8 save[M62332_CHANNELS]; | |
| 40 | +#endif | |
| 41 | +}; | |
| 42 | + | |
| 43 | +static int m62332_set_value(struct iio_dev *indio_dev, | |
| 44 | + u8 val, int channel) | |
| 45 | +{ | |
| 46 | + struct m62332_data *data = iio_priv(indio_dev); | |
| 47 | + struct i2c_client *client = data->client; | |
| 48 | + u8 outbuf[2]; | |
| 49 | + int res; | |
| 50 | + | |
| 51 | + if (val == data->raw[channel]) | |
| 52 | + return 0; | |
| 53 | + | |
| 54 | + outbuf[0] = channel; | |
| 55 | + outbuf[1] = val; | |
| 56 | + | |
| 57 | + mutex_lock(&data->mutex); | |
| 58 | + | |
| 59 | + if (val) { | |
| 60 | + res = regulator_enable(data->vcc); | |
| 61 | + if (res) | |
| 62 | + goto out; | |
| 63 | + } | |
| 64 | + | |
| 65 | + res = i2c_master_send(client, outbuf, 2); | |
| 66 | + if (res >= 0 && res != 2) | |
| 67 | + res = -EIO; | |
| 68 | + if (res < 0) | |
| 69 | + goto out; | |
| 70 | + | |
| 71 | + data->raw[channel] = val; | |
| 72 | + | |
| 73 | + if (!val) | |
| 74 | + regulator_disable(data->vcc); | |
| 75 | + | |
| 76 | + mutex_unlock(&data->mutex); | |
| 77 | + | |
| 78 | + return 0; | |
| 79 | + | |
| 80 | +out: | |
| 81 | + mutex_unlock(&data->mutex); | |
| 82 | + | |
| 83 | + return res; | |
| 84 | +} | |
| 85 | + | |
| 86 | +static int m62332_read_raw(struct iio_dev *indio_dev, | |
| 87 | + struct iio_chan_spec const *chan, | |
| 88 | + int *val, | |
| 89 | + int *val2, | |
| 90 | + long m) | |
| 91 | +{ | |
| 92 | + struct m62332_data *data = iio_priv(indio_dev); | |
| 93 | + | |
| 94 | + switch (m) { | |
| 95 | + case IIO_CHAN_INFO_SCALE: | |
| 96 | + /* Corresponds to Vref / 2^(bits) */ | |
| 97 | + *val = data->vref_mv; | |
| 98 | + *val2 = 8; | |
| 99 | + return IIO_VAL_FRACTIONAL_LOG2; | |
| 100 | + case IIO_CHAN_INFO_RAW: | |
| 101 | + *val = data->raw[chan->channel]; | |
| 102 | + return IIO_VAL_INT; | |
| 103 | + case IIO_CHAN_INFO_OFFSET: | |
| 104 | + *val = 1; | |
| 105 | + return IIO_VAL_INT; | |
| 106 | + default: | |
| 107 | + break; | |
| 108 | + } | |
| 109 | + return -EINVAL; | |
| 110 | +} | |
| 111 | + | |
| 112 | +static int m62332_write_raw(struct iio_dev *indio_dev, | |
| 113 | + struct iio_chan_spec const *chan, int val, int val2, long mask) | |
| 114 | +{ | |
| 115 | + int ret; | |
| 116 | + | |
| 117 | + switch (mask) { | |
| 118 | + case IIO_CHAN_INFO_RAW: | |
| 119 | + if (val < 0 || val > 255) | |
| 120 | + return -EINVAL; | |
| 121 | + | |
| 122 | + ret = m62332_set_value(indio_dev, val, chan->channel); | |
| 123 | + break; | |
| 124 | + default: | |
| 125 | + ret = -EINVAL; | |
| 126 | + break; | |
| 127 | + } | |
| 128 | + | |
| 129 | + return ret; | |
| 130 | +} | |
| 131 | + | |
| 132 | +#ifdef CONFIG_PM_SLEEP | |
| 133 | +static int m62332_suspend(struct device *dev) | |
| 134 | +{ | |
| 135 | + struct i2c_client *client = to_i2c_client(dev); | |
| 136 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 137 | + struct m62332_data *data = iio_priv(indio_dev); | |
| 138 | + int ret; | |
| 139 | + | |
| 140 | + data->save[0] = data->raw[0]; | |
| 141 | + data->save[1] = data->raw[1]; | |
| 142 | + | |
| 143 | + ret = m62332_set_value(indio_dev, 0, 0); | |
| 144 | + if (ret < 0) | |
| 145 | + return ret; | |
| 146 | + | |
| 147 | + return m62332_set_value(indio_dev, 0, 1); | |
| 148 | +} | |
| 149 | + | |
| 150 | +static int m62332_resume(struct device *dev) | |
| 151 | +{ | |
| 152 | + struct i2c_client *client = to_i2c_client(dev); | |
| 153 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 154 | + struct m62332_data *data = iio_priv(indio_dev); | |
| 155 | + int ret; | |
| 156 | + | |
| 157 | + ret = m62332_set_value(indio_dev, data->save[0], 0); | |
| 158 | + if (ret < 0) | |
| 159 | + return ret; | |
| 160 | + | |
| 161 | + return m62332_set_value(indio_dev, data->save[1], 1); | |
| 162 | +} | |
| 163 | + | |
| 164 | +static SIMPLE_DEV_PM_OPS(m62332_pm_ops, m62332_suspend, m62332_resume); | |
| 165 | +#define M62332_PM_OPS (&m62332_pm_ops) | |
| 166 | +#else | |
| 167 | +#define M62332_PM_OPS NULL | |
| 168 | +#endif | |
| 169 | + | |
| 170 | +static const struct iio_info m62332_info = { | |
| 171 | + .read_raw = m62332_read_raw, | |
| 172 | + .write_raw = m62332_write_raw, | |
| 173 | + .driver_module = THIS_MODULE, | |
| 174 | +}; | |
| 175 | + | |
| 176 | +#define M62332_CHANNEL(chan) { \ | |
| 177 | + .type = IIO_VOLTAGE, \ | |
| 178 | + .indexed = 1, \ | |
| 179 | + .output = 1, \ | |
| 180 | + .channel = (chan), \ | |
| 181 | + .datasheet_name = "CH" #chan, \ | |
| 182 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 183 | + BIT(IIO_CHAN_INFO_SCALE) | \ | |
| 184 | + BIT(IIO_CHAN_INFO_OFFSET), \ | |
| 185 | +} | |
| 186 | + | |
| 187 | +static const struct iio_chan_spec m62332_channels[M62332_CHANNELS] = { | |
| 188 | + M62332_CHANNEL(0), | |
| 189 | + M62332_CHANNEL(1) | |
| 190 | +}; | |
| 191 | + | |
| 192 | +static int m62332_probe(struct i2c_client *client, | |
| 193 | + const struct i2c_device_id *id) | |
| 194 | +{ | |
| 195 | + struct m62332_data *data; | |
| 196 | + struct iio_dev *indio_dev; | |
| 197 | + int ret; | |
| 198 | + | |
| 199 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 200 | + if (!indio_dev) | |
| 201 | + return -ENOMEM; | |
| 202 | + data = iio_priv(indio_dev); | |
| 203 | + i2c_set_clientdata(client, indio_dev); | |
| 204 | + data->client = client; | |
| 205 | + | |
| 206 | + mutex_init(&data->mutex); | |
| 207 | + | |
| 208 | + data->vcc = devm_regulator_get(&client->dev, "VCC"); | |
| 209 | + if (IS_ERR(data->vcc)) | |
| 210 | + return PTR_ERR(data->vcc); | |
| 211 | + | |
| 212 | + /* establish that the iio_dev is a child of the i2c device */ | |
| 213 | + indio_dev->dev.parent = &client->dev; | |
| 214 | + | |
| 215 | + indio_dev->num_channels = M62332_CHANNELS; | |
| 216 | + indio_dev->channels = m62332_channels; | |
| 217 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 218 | + indio_dev->info = &m62332_info; | |
| 219 | + | |
| 220 | + ret = regulator_get_voltage(data->vcc); | |
| 221 | + if (ret < 0) | |
| 222 | + return ret; | |
| 223 | + data->vref_mv = ret / 1000; /* mV */ | |
| 224 | + | |
| 225 | + ret = iio_map_array_register(indio_dev, client->dev.platform_data); | |
| 226 | + if (ret < 0) | |
| 227 | + return ret; | |
| 228 | + | |
| 229 | + ret = iio_device_register(indio_dev); | |
| 230 | + if (ret < 0) | |
| 231 | + goto err; | |
| 232 | + | |
| 233 | + return 0; | |
| 234 | + | |
| 235 | +err: | |
| 236 | + iio_map_array_unregister(indio_dev); | |
| 237 | + return ret; | |
| 238 | +} | |
| 239 | + | |
| 240 | +static int m62332_remove(struct i2c_client *client) | |
| 241 | +{ | |
| 242 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 243 | + | |
| 244 | + iio_device_unregister(indio_dev); | |
| 245 | + iio_map_array_unregister(indio_dev); | |
| 246 | + | |
| 247 | + return 0; | |
| 248 | +} | |
| 249 | + | |
| 250 | +static const struct i2c_device_id m62332_id[] = { | |
| 251 | + { "m62332", }, | |
| 252 | + { } | |
| 253 | +}; | |
| 254 | +MODULE_DEVICE_TABLE(i2c, m62332_id); | |
| 255 | + | |
| 256 | +static struct i2c_driver m62332_driver = { | |
| 257 | + .driver = { | |
| 258 | + .name = "m62332", | |
| 259 | + .pm = M62332_PM_OPS, | |
| 260 | + }, | |
| 261 | + .probe = m62332_probe, | |
| 262 | + .remove = m62332_remove, | |
| 263 | + .id_table = m62332_id, | |
| 264 | +}; | |
| 265 | +module_i2c_driver(m62332_driver); | |
| 266 | + | |
| 267 | +MODULE_AUTHOR("Dmitry Eremin-Solenikov"); | |
| 268 | +MODULE_DESCRIPTION("M62332 8-bit DAC"); | |
| 269 | +MODULE_LICENSE("GPL v2"); | |
| @@ -108,7 +108,6 @@ struct bmg160_data { · 107 unmodified lines | ||
| 108 | 108 | int slope_thres; |
| 109 | 109 | bool dready_trigger_on; |
| 110 | 110 | bool motion_trigger_on; |
| 111 | − int64_t timestamp; | |
| 112 | 111 | }; |
| 113 | 112 | |
| 114 | 113 | enum bmg160_axis { |
| @@ -738,17 +737,6 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev, · 623 unmodified lines | ||
| 738 | 737 | return 0; |
| 739 | 738 | } |
| 740 | 739 | |
| 741 | −static int bmg160_validate_trigger(struct iio_dev *indio_dev, | |
| 742 | − struct iio_trigger *trig) | |
| 743 | −{ | |
| 744 | − struct bmg160_data *data = iio_priv(indio_dev); | |
| 745 | − | |
| 746 | − if (data->dready_trig != trig && data->motion_trig != trig) | |
| 747 | − return -EINVAL; | |
| 748 | − | |
| 749 | − return 0; | |
| 750 | −} | |
| 751 | − | |
| 752 | 740 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000"); |
| 753 | 741 | |
| 754 | 742 | static IIO_CONST_ATTR(in_anglvel_scale_available, |
| @@ -810,7 +798,6 @@ static const struct iio_info bmg160_info = { · 55 unmodified lines | ||
| 810 | 798 | .write_event_value = bmg160_write_event, |
| 811 | 799 | .write_event_config = bmg160_write_event_config, |
| 812 | 800 | .read_event_config = bmg160_read_event_config, |
| 813 | − .validate_trigger = bmg160_validate_trigger, | |
| 814 | 801 | .driver_module = THIS_MODULE, |
| 815 | 802 | }; |
| 816 | 803 | |
| @@ -835,7 +822,7 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p) · 18 unmodified lines | ||
| 835 | 822 | mutex_unlock(&data->mutex); |
| 836 | 823 | |
| 837 | 824 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, |
| 838 | − data->timestamp); | |
| 825 | + pf->timestamp); | |
| 839 | 826 | err: |
| 840 | 827 | iio_trigger_notify_done(indio_dev->trig); |
| 841 | 828 | |
| @@ -938,21 +925,21 @@ static irqreturn_t bmg160_event_handler(int irq, void *private) · 96 unmodified lines | ||
| 938 | 925 | IIO_MOD_X, |
| 939 | 926 | IIO_EV_TYPE_ROC, |
| 940 | 927 | dir), |
| 941 | − data->timestamp); | |
| 928 | + iio_get_time_ns()); | |
| 942 | 929 | if (ret & BMG160_ANY_MOTION_BIT_Y) |
| 943 | 930 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, |
| 944 | 931 | 0, |
| 945 | 932 | IIO_MOD_Y, |
| 946 | 933 | IIO_EV_TYPE_ROC, |
| 947 | 934 | dir), |
| 948 | − data->timestamp); | |
| 935 | + iio_get_time_ns()); | |
| 949 | 936 | if (ret & BMG160_ANY_MOTION_BIT_Z) |
| 950 | 937 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, |
| 951 | 938 | 0, |
| 952 | 939 | IIO_MOD_Z, |
| 953 | 940 | IIO_EV_TYPE_ROC, |
| 954 | 941 | dir), |
| 955 | − data->timestamp); | |
| 942 | + iio_get_time_ns()); | |
| 956 | 943 | |
| 957 | 944 | ack_intr_status: |
| 958 | 945 | if (!data->dready_trigger_on) { |
| @@ -973,8 +960,6 @@ static irqreturn_t bmg160_data_rdy_trig_poll(int irq, void *private) · 14 unmodified lines | ||
| 973 | 960 | struct iio_dev *indio_dev = private; |
| 974 | 961 | struct bmg160_data *data = iio_priv(indio_dev); |
| 975 | 962 | |
| 976 | − data->timestamp = iio_get_time_ns(); | |
| 977 | − | |
| 978 | 963 | if (data->dready_trigger_on) |
| 979 | 964 | iio_trigger_poll(data->dready_trig); |
| 980 | 965 | else if (data->motion_trigger_on) |
| @@ -987,6 +972,27 @@ static irqreturn_t bmg160_data_rdy_trig_poll(int irq, void *private) · 6 unmodified lines | ||
| 987 | 972 | |
| 988 | 973 | } |
| 989 | 974 | |
| 975 | +static int bmg160_buffer_preenable(struct iio_dev *indio_dev) | |
| 976 | +{ | |
| 977 | + struct bmg160_data *data = iio_priv(indio_dev); | |
| 978 | + | |
| 979 | + return bmg160_set_power_state(data, true); | |
| 980 | +} | |
| 981 | + | |
| 982 | +static int bmg160_buffer_postdisable(struct iio_dev *indio_dev) | |
| 983 | +{ | |
| 984 | + struct bmg160_data *data = iio_priv(indio_dev); | |
| 985 | + | |
| 986 | + return bmg160_set_power_state(data, false); | |
| 987 | +} | |
| 988 | + | |
| 989 | +static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = { | |
| 990 | + .preenable = bmg160_buffer_preenable, | |
| 991 | + .postenable = iio_triggered_buffer_postenable, | |
| 992 | + .predisable = iio_triggered_buffer_predisable, | |
| 993 | + .postdisable = bmg160_buffer_postdisable, | |
| 994 | +}; | |
| 995 | + | |
| 990 | 996 | static int bmg160_gpio_probe(struct i2c_client *client, |
| 991 | 997 | struct bmg160_data *data) |
| 992 | 998 | |
| @@ -1103,16 +1109,16 @@ static int bmg160_probe(struct i2c_client *client, · 110 unmodified lines | ||
| 1103 | 1109 | data->motion_trig = NULL; |
| 1104 | 1110 | goto err_trigger_unregister; |
| 1105 | 1111 | } |
| 1112 | + } | |
| 1106 | 1113 | |
| 1107 | − ret = iio_triggered_buffer_setup(indio_dev, | |
| 1108 | − NULL, | |
| 1109 | − bmg160_trigger_handler, | |
| 1110 | − NULL); | |
| 1111 | − if (ret < 0) { | |
| 1112 | − dev_err(&client->dev, | |
| 1113 | − "iio triggered buffer setup failed\n"); | |
| 1114 | − goto err_trigger_unregister; | |
| 1115 | − } | |
| 1114 | + ret = iio_triggered_buffer_setup(indio_dev, | |
| 1115 | + iio_pollfunc_store_time, | |
| 1116 | + bmg160_trigger_handler, | |
| 1117 | + &bmg160_buffer_setup_ops); | |
| 1118 | + if (ret < 0) { | |
| 1119 | + dev_err(&client->dev, | |
| 1120 | + "iio triggered buffer setup failed\n"); | |
| 1121 | + goto err_trigger_unregister; | |
| 1116 | 1122 | } |
| 1117 | 1123 | |
| 1118 | 1124 | ret = iio_device_register(indio_dev); |
| @@ -1135,8 +1141,7 @@ static int bmg160_probe(struct i2c_client *client, · 16 unmodified lines | ||
| 1135 | 1141 | err_iio_unregister: |
| 1136 | 1142 | iio_device_unregister(indio_dev); |
| 1137 | 1143 | err_buffer_cleanup: |
| 1138 | − if (data->dready_trig) | |
| 1139 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 1144 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 1140 | 1145 | err_trigger_unregister: |
| 1141 | 1146 | if (data->dready_trig) |
| 1142 | 1147 | iio_trigger_unregister(data->dready_trig); |
| @@ -1156,9 +1161,9 @@ static int bmg160_remove(struct i2c_client *client) · 13 unmodified lines | ||
| 1156 | 1161 | pm_runtime_put_noidle(&client->dev); |
| 1157 | 1162 | |
| 1158 | 1163 | iio_device_unregister(indio_dev); |
| 1164 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 1159 | 1165 | |
| 1160 | 1166 | if (data->dready_trig) { |
| 1161 | − iio_triggered_buffer_cleanup(indio_dev); | |
| 1162 | 1167 | iio_trigger_unregister(data->dready_trig); |
| 1163 | 1168 | iio_trigger_unregister(data->motion_trig); |
| 1164 | 1169 | } |
| @@ -298,7 +298,6 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) · 297 unmodified lines | ||
| 298 | 298 | struct iio_dev *indio_dev; |
| 299 | 299 | struct gyro_3d_state *gyro_state; |
| 300 | 300 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 301 | − struct iio_chan_spec *channels; | |
| 302 | 301 | |
| 303 | 302 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state)); |
| 304 | 303 | if (!indio_dev) |
| @@ -317,21 +316,21 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) · 12 unmodified lines | ||
| 317 | 316 | return ret; |
| 318 | 317 | } |
| 319 | 318 | |
| 320 | − channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels), | |
| 321 | − GFP_KERNEL); | |
| 322 | − if (!channels) { | |
| 319 | + indio_dev->channels = kmemdup(gyro_3d_channels, | |
| 320 | + sizeof(gyro_3d_channels), GFP_KERNEL); | |
| 321 | + if (!indio_dev->channels) { | |
| 323 | 322 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 324 | 323 | return -ENOMEM; |
| 325 | 324 | } |
| 326 | 325 | |
| 327 | − ret = gyro_3d_parse_report(pdev, hsdev, channels, | |
| 328 | − HID_USAGE_SENSOR_GYRO_3D, gyro_state); | |
| 326 | + ret = gyro_3d_parse_report(pdev, hsdev, | |
| 327 | + (struct iio_chan_spec *)indio_dev->channels, | |
| 328 | + HID_USAGE_SENSOR_GYRO_3D, gyro_state); | |
| 329 | 329 | if (ret) { |
| 330 | 330 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 331 | 331 | goto error_free_dev_mem; |
| 332 | 332 | } |
| 333 | 333 | |
| 334 | − indio_dev->channels = channels; | |
| 335 | 334 | indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels); |
| 336 | 335 | indio_dev->dev.parent = &pdev->dev; |
| 337 | 336 | indio_dev->info = &gyro_3d_info; |
| @@ -397,7 +396,7 @@ static int hid_gyro_3d_remove(struct platform_device *pdev) · 59 unmodified lines | ||
| 397 | 396 | return 0; |
| 398 | 397 | } |
| 399 | 398 | |
| 400 | −static struct platform_device_id hid_gyro_3d_ids[] = { | |
| 399 | +static const struct platform_device_id hid_gyro_3d_ids[] = { | |
| 401 | 400 | { |
| 402 | 401 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 403 | 402 | .name = "HID-SENSOR-200076", |
| @@ -5,7 +5,7 @@ menu "Humidity sensors" · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | config DHT11 |
| 7 | 7 | tristate "DHT11 (and compatible sensors) driver" |
| 8 | − depends on GPIOLIB | |
| 8 | + depends on GPIOLIB || COMPILE_TEST | |
| 9 | 9 | help |
| 10 | 10 | This driver supports reading data via a single interrupt |
| 11 | 11 | generating GPIO line. Currently tested are DHT11 and DHT22. |
| @@ -239,13 +239,19 @@ static ssize_t iio_scan_el_show(struct device *dev, · 238 unmodified lines | ||
| 239 | 239 | /* Note NULL used as error indicator as it doesn't make sense. */ |
| 240 | 240 | static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, |
| 241 | 241 | unsigned int masklength, |
| 242 | − const unsigned long *mask) | |
| 242 | + const unsigned long *mask, | |
| 243 | + bool strict) | |
| 243 | 244 | { |
| 244 | 245 | if (bitmap_empty(mask, masklength)) |
| 245 | 246 | return NULL; |
| 246 | 247 | while (*av_masks) { |
| 247 | − if (bitmap_subset(mask, av_masks, masklength)) | |
| 248 | − return av_masks; | |
| 248 | + if (strict) { | |
| 249 | + if (bitmap_equal(mask, av_masks, masklength)) | |
| 250 | + return av_masks; | |
| 251 | + } else { | |
| 252 | + if (bitmap_subset(mask, av_masks, masklength)) | |
| 253 | + return av_masks; | |
| 254 | + } | |
| 249 | 255 | av_masks += BITS_TO_LONGS(masklength); |
| 250 | 256 | } |
| 251 | 257 | return NULL; |
| @@ -295,7 +301,7 @@ static int iio_scan_mask_set(struct iio_dev *indio_dev, · 43 unmodified lines | ||
| 295 | 301 | if (indio_dev->available_scan_masks) { |
| 296 | 302 | mask = iio_scan_mask_match(indio_dev->available_scan_masks, |
| 297 | 303 | indio_dev->masklength, |
| 298 | − trialmask); | |
| 304 | + trialmask, false); | |
| 299 | 305 | if (!mask) |
| 300 | 306 | goto err_invalid_mask; |
| 301 | 307 | } |
| @@ -539,26 +545,13 @@ static void iio_buffer_deactivate(struct iio_buffer *buffer) · 237 unmodified lines | ||
| 539 | 545 | iio_buffer_put(buffer); |
| 540 | 546 | } |
| 541 | 547 | |
| 542 | −void iio_disable_all_buffers(struct iio_dev *indio_dev) | |
| 548 | +static void iio_buffer_deactivate_all(struct iio_dev *indio_dev) | |
| 543 | 549 | { |
| 544 | 550 | struct iio_buffer *buffer, *_buffer; |
| 545 | 551 | |
| 546 | − if (list_empty(&indio_dev->buffer_list)) | |
| 547 | − return; | |
| 548 | − | |
| 549 | − if (indio_dev->setup_ops->predisable) | |
| 550 | − indio_dev->setup_ops->predisable(indio_dev); | |
| 551 | − | |
| 552 | 552 | list_for_each_entry_safe(buffer, _buffer, |
| 553 | 553 | &indio_dev->buffer_list, buffer_list) |
| 554 | 554 | iio_buffer_deactivate(buffer); |
| 555 | − | |
| 556 | − indio_dev->currentmode = INDIO_DIRECT_MODE; | |
| 557 | − if (indio_dev->setup_ops->postdisable) | |
| 558 | − indio_dev->setup_ops->postdisable(indio_dev); | |
| 559 | − | |
| 560 | − if (indio_dev->available_scan_masks == NULL) | |
| 561 | − kfree(indio_dev->active_scan_mask); | |
| 562 | 555 | } |
| 563 | 556 | |
| 564 | 557 | static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, |
| @@ -575,167 +568,277 @@ static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, · 10 unmodified lines | ||
| 575 | 568 | buffer->access->set_bytes_per_datum(buffer, bytes); |
| 576 | 569 | } |
| 577 | 570 | |
| 578 | −static int __iio_update_buffers(struct iio_dev *indio_dev, | |
| 579 | − struct iio_buffer *insert_buffer, | |
| 580 | − struct iio_buffer *remove_buffer) | |
| 571 | +static int iio_buffer_request_update(struct iio_dev *indio_dev, | |
| 572 | + struct iio_buffer *buffer) | |
| 581 | 573 | { |
| 582 | 574 | int ret; |
| 583 | − int success = 0; | |
| 584 | − struct iio_buffer *buffer; | |
| 585 | − unsigned long *compound_mask; | |
| 586 | − const unsigned long *old_mask; | |
| 587 | 575 | |
| 588 | − /* Wind down existing buffers - iff there are any */ | |
| 589 | − if (!list_empty(&indio_dev->buffer_list)) { | |
| 590 | − if (indio_dev->setup_ops->predisable) { | |
| 591 | − ret = indio_dev->setup_ops->predisable(indio_dev); | |
| 592 | − if (ret) | |
| 593 | − return ret; | |
| 594 | − } | |
| 595 | − indio_dev->currentmode = INDIO_DIRECT_MODE; | |
| 596 | − if (indio_dev->setup_ops->postdisable) { | |
| 597 | − ret = indio_dev->setup_ops->postdisable(indio_dev); | |
| 598 | − if (ret) | |
| 599 | − return ret; | |
| 576 | + iio_buffer_update_bytes_per_datum(indio_dev, buffer); | |
| 577 | + if (buffer->access->request_update) { | |
| 578 | + ret = buffer->access->request_update(buffer); | |
| 579 | + if (ret) { | |
| 580 | + dev_dbg(&indio_dev->dev, | |
| 581 | + "Buffer not started: buffer parameter update failed (%d)\n", | |
| 582 | + ret); | |
| 583 | + return ret; | |
| 600 | 584 | } |
| 601 | 585 | } |
| 602 | − /* Keep a copy of current setup to allow roll back */ | |
| 603 | − old_mask = indio_dev->active_scan_mask; | |
| 586 | + | |
| 587 | + return 0; | |
| 588 | +} | |
| 589 | + | |
| 590 | +static void iio_free_scan_mask(struct iio_dev *indio_dev, | |
| 591 | + const unsigned long *mask) | |
| 592 | +{ | |
| 593 | + /* If the mask is dynamically allocated free it, otherwise do nothing */ | |
| 604 | 594 | if (!indio_dev->available_scan_masks) |
| 605 | − indio_dev->active_scan_mask = NULL; | |
| 595 | + kfree(mask); | |
| 596 | +} | |
| 597 | + | |
| 598 | +struct iio_device_config { | |
| 599 | + unsigned int mode; | |
| 600 | + const unsigned long *scan_mask; | |
| 601 | + unsigned int scan_bytes; | |
| 602 | + bool scan_timestamp; | |
| 603 | +}; | |
| 604 | + | |
| 605 | +static int iio_verify_update(struct iio_dev *indio_dev, | |
| 606 | + struct iio_buffer *insert_buffer, struct iio_buffer *remove_buffer, | |
| 607 | + struct iio_device_config *config) | |
| 608 | +{ | |
| 609 | + unsigned long *compound_mask; | |
| 610 | + const unsigned long *scan_mask; | |
| 611 | + bool strict_scanmask = false; | |
| 612 | + struct iio_buffer *buffer; | |
| 613 | + bool scan_timestamp; | |
| 614 | + unsigned int modes; | |
| 615 | + | |
| 616 | + memset(config, 0, sizeof(*config)); | |
| 617 | + | |
| 618 | + /* | |
| 619 | + * If there is just one buffer and we are removing it there is nothing | |
| 620 | + * to verify. | |
| 621 | + */ | |
| 622 | + if (remove_buffer && !insert_buffer && | |
| 623 | + list_is_singular(&indio_dev->buffer_list)) | |
| 624 | + return 0; | |
| 625 | + | |
| 626 | + modes = indio_dev->modes; | |
| 627 | + | |
| 628 | + list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { | |
| 629 | + if (buffer == remove_buffer) | |
| 630 | + continue; | |
| 631 | + modes &= buffer->access->modes; | |
| 632 | + } | |
| 606 | 633 | |
| 607 | − if (remove_buffer) | |
| 608 | − iio_buffer_deactivate(remove_buffer); | |
| 609 | 634 | if (insert_buffer) |
| 610 | − iio_buffer_activate(indio_dev, insert_buffer); | |
| 635 | + modes &= insert_buffer->access->modes; | |
| 611 | 636 | |
| 612 | − /* If no buffers in list, we are done */ | |
| 613 | − if (list_empty(&indio_dev->buffer_list)) { | |
| 614 | − indio_dev->currentmode = INDIO_DIRECT_MODE; | |
| 615 | − if (indio_dev->available_scan_masks == NULL) | |
| 616 | − kfree(old_mask); | |
| 617 | − return 0; | |
| 637 | + /* Definitely possible for devices to support both of these. */ | |
| 638 | + if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { | |
| 639 | + config->mode = INDIO_BUFFER_TRIGGERED; | |
| 640 | + } else if (modes & INDIO_BUFFER_HARDWARE) { | |
| 641 | + /* | |
| 642 | + * Keep things simple for now and only allow a single buffer to | |
| 643 | + * be connected in hardware mode. | |
| 644 | + */ | |
| 645 | + if (insert_buffer && !list_empty(&indio_dev->buffer_list)) | |
| 646 | + return -EINVAL; | |
| 647 | + config->mode = INDIO_BUFFER_HARDWARE; | |
| 648 | + strict_scanmask = true; | |
| 649 | + } else if (modes & INDIO_BUFFER_SOFTWARE) { | |
| 650 | + config->mode = INDIO_BUFFER_SOFTWARE; | |
| 651 | + } else { | |
| 652 | + /* Can only occur on first buffer */ | |
| 653 | + if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) | |
| 654 | + dev_dbg(&indio_dev->dev, "Buffer not started: no trigger\n"); | |
| 655 | + return -EINVAL; | |
| 618 | 656 | } |
| 619 | 657 | |
| 620 | 658 | /* What scan mask do we actually have? */ |
| 621 | 659 | compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), |
| 622 | 660 | sizeof(long), GFP_KERNEL); |
| 623 | − if (compound_mask == NULL) { | |
| 624 | − if (indio_dev->available_scan_masks == NULL) | |
| 625 | − kfree(old_mask); | |
| 661 | + if (compound_mask == NULL) | |
| 626 | 662 | return -ENOMEM; |
| 627 | − } | |
| 628 | − indio_dev->scan_timestamp = 0; | |
| 663 | + | |
| 664 | + scan_timestamp = false; | |
| 629 | 665 | |
| 630 | 666 | list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { |
| 667 | + if (buffer == remove_buffer) | |
| 668 | + continue; | |
| 631 | 669 | bitmap_or(compound_mask, compound_mask, buffer->scan_mask, |
| 632 | 670 | indio_dev->masklength); |
| 633 | − indio_dev->scan_timestamp |= buffer->scan_timestamp; | |
| 671 | + scan_timestamp |= buffer->scan_timestamp; | |
| 672 | + } | |
| 673 | + | |
| 674 | + if (insert_buffer) { | |
| 675 | + bitmap_or(compound_mask, compound_mask, | |
| 676 | + insert_buffer->scan_mask, indio_dev->masklength); | |
| 677 | + scan_timestamp |= insert_buffer->scan_timestamp; | |
| 634 | 678 | } |
| 679 | + | |
| 635 | 680 | if (indio_dev->available_scan_masks) { |
| 636 | − indio_dev->active_scan_mask = | |
| 637 | − iio_scan_mask_match(indio_dev->available_scan_masks, | |
| 638 | − indio_dev->masklength, | |
| 639 | − compound_mask); | |
| 640 | − if (indio_dev->active_scan_mask == NULL) { | |
| 641 | − /* | |
| 642 | − * Roll back. | |
| 643 | − * Note can only occur when adding a buffer. | |
| 644 | − */ | |
| 645 | − iio_buffer_deactivate(insert_buffer); | |
| 646 | − if (old_mask) { | |
| 647 | − indio_dev->active_scan_mask = old_mask; | |
| 648 | − success = -EINVAL; | |
| 649 | − } | |
| 650 | − else { | |
| 651 | − kfree(compound_mask); | |
| 652 | − ret = -EINVAL; | |
| 653 | − return ret; | |
| 654 | − } | |
| 655 | − } | |
| 681 | + scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks, | |
| 682 | + indio_dev->masklength, | |
| 683 | + compound_mask, | |
| 684 | + strict_scanmask); | |
| 685 | + kfree(compound_mask); | |
| 686 | + if (scan_mask == NULL) | |
| 687 | + return -EINVAL; | |
| 656 | 688 | } else { |
| 657 | − indio_dev->active_scan_mask = compound_mask; | |
| 689 | + scan_mask = compound_mask; | |
| 658 | 690 | } |
| 659 | 691 | |
| 692 | + config->scan_bytes = iio_compute_scan_bytes(indio_dev, | |
| 693 | + scan_mask, scan_timestamp); | |
| 694 | + config->scan_mask = scan_mask; | |
| 695 | + config->scan_timestamp = scan_timestamp; | |
| 696 | + | |
| 697 | + return 0; | |
| 698 | +} | |
| 699 | + | |
| 700 | +static int iio_enable_buffers(struct iio_dev *indio_dev, | |
| 701 | + struct iio_device_config *config) | |
| 702 | +{ | |
| 703 | + int ret; | |
| 704 | + | |
| 705 | + indio_dev->active_scan_mask = config->scan_mask; | |
| 706 | + indio_dev->scan_timestamp = config->scan_timestamp; | |
| 707 | + indio_dev->scan_bytes = config->scan_bytes; | |
| 708 | + | |
| 660 | 709 | iio_update_demux(indio_dev); |
| 661 | 710 | |
| 662 | 711 | /* Wind up again */ |
| 663 | 712 | if (indio_dev->setup_ops->preenable) { |
| 664 | 713 | ret = indio_dev->setup_ops->preenable(indio_dev); |
| 665 | 714 | if (ret) { |
| 666 | − printk(KERN_ERR | |
| 715 | + dev_dbg(&indio_dev->dev, | |
| 667 | 716 | "Buffer not started: buffer preenable failed (%d)\n", ret); |
| 668 | − goto error_remove_inserted; | |
| 669 | − } | |
| 670 | − } | |
| 671 | − indio_dev->scan_bytes = | |
| 672 | − iio_compute_scan_bytes(indio_dev, | |
| 673 | − indio_dev->active_scan_mask, | |
| 674 | − indio_dev->scan_timestamp); | |
| 675 | − list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { | |
| 676 | − iio_buffer_update_bytes_per_datum(indio_dev, buffer); | |
| 677 | − if (buffer->access->request_update) { | |
| 678 | − ret = buffer->access->request_update(buffer); | |
| 679 | − if (ret) { | |
| 680 | − printk(KERN_INFO | |
| 681 | − "Buffer not started: buffer parameter update failed (%d)\n", ret); | |
| 682 | − goto error_run_postdisable; | |
| 683 | − } | |
| 717 | + goto err_undo_config; | |
| 684 | 718 | } |
| 685 | 719 | } |
| 720 | + | |
| 686 | 721 | if (indio_dev->info->update_scan_mode) { |
| 687 | 722 | ret = indio_dev->info |
| 688 | 723 | ->update_scan_mode(indio_dev, |
| 689 | 724 | indio_dev->active_scan_mask); |
| 690 | 725 | if (ret < 0) { |
| 691 | − printk(KERN_INFO "Buffer not started: update scan mode failed (%d)\n", ret); | |
| 692 | − goto error_run_postdisable; | |
| 726 | + dev_dbg(&indio_dev->dev, | |
| 727 | + "Buffer not started: update scan mode failed (%d)\n", | |
| 728 | + ret); | |
| 729 | + goto err_run_postdisable; | |
| 693 | 730 | } |
| 694 | 731 | } |
| 695 | − /* Definitely possible for devices to support both of these. */ | |
| 696 | − if ((indio_dev->modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { | |
| 697 | − indio_dev->currentmode = INDIO_BUFFER_TRIGGERED; | |
| 698 | − } else if (indio_dev->modes & INDIO_BUFFER_HARDWARE) { | |
| 699 | − indio_dev->currentmode = INDIO_BUFFER_HARDWARE; | |
| 700 | − } else if (indio_dev->modes & INDIO_BUFFER_SOFTWARE) { | |
| 701 | − indio_dev->currentmode = INDIO_BUFFER_SOFTWARE; | |
| 702 | − } else { /* Should never be reached */ | |
| 703 | − /* Can only occur on first buffer */ | |
| 704 | − if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) | |
| 705 | − pr_info("Buffer not started: no trigger\n"); | |
| 706 | − ret = -EINVAL; | |
| 707 | − goto error_run_postdisable; | |
| 708 | − } | |
| 732 | + | |
| 733 | + indio_dev->currentmode = config->mode; | |
| 709 | 734 | |
| 710 | 735 | if (indio_dev->setup_ops->postenable) { |
| 711 | 736 | ret = indio_dev->setup_ops->postenable(indio_dev); |
| 712 | 737 | if (ret) { |
| 713 | − printk(KERN_INFO | |
| 738 | + dev_dbg(&indio_dev->dev, | |
| 714 | 739 | "Buffer not started: postenable failed (%d)\n", ret); |
| 715 | − indio_dev->currentmode = INDIO_DIRECT_MODE; | |
| 716 | − if (indio_dev->setup_ops->postdisable) | |
| 717 | − indio_dev->setup_ops->postdisable(indio_dev); | |
| 718 | − goto error_disable_all_buffers; | |
| 740 | + goto err_run_postdisable; | |
| 719 | 741 | } |
| 720 | 742 | } |
| 721 | 743 | |
| 722 | − if (indio_dev->available_scan_masks) | |
| 723 | − kfree(compound_mask); | |
| 724 | − else | |
| 725 | − kfree(old_mask); | |
| 726 | − | |
| 727 | − return success; | |
| 744 | + return 0; | |
| 728 | 745 | |
| 729 | −error_disable_all_buffers: | |
| 746 | +err_run_postdisable: | |
| 730 | 747 | indio_dev->currentmode = INDIO_DIRECT_MODE; |
| 731 | −error_run_postdisable: | |
| 732 | 748 | if (indio_dev->setup_ops->postdisable) |
| 733 | 749 | indio_dev->setup_ops->postdisable(indio_dev); |
| 734 | −error_remove_inserted: | |
| 750 | +err_undo_config: | |
| 751 | + indio_dev->active_scan_mask = NULL; | |
| 752 | + | |
| 753 | + return ret; | |
| 754 | +} | |
| 755 | + | |
| 756 | +static int iio_disable_buffers(struct iio_dev *indio_dev) | |
| 757 | +{ | |
| 758 | + int ret = 0; | |
| 759 | + int ret2; | |
| 760 | + | |
| 761 | + /* Wind down existing buffers - iff there are any */ | |
| 762 | + if (list_empty(&indio_dev->buffer_list)) | |
| 763 | + return 0; | |
| 764 | + | |
| 765 | + /* | |
| 766 | + * If things go wrong at some step in disable we still need to continue | |
| 767 | + * to perform the other steps, otherwise we leave the device in a | |
| 768 | + * inconsistent state. We return the error code for the first error we | |
| 769 | + * encountered. | |
| 770 | + */ | |
| 771 | + | |
| 772 | + if (indio_dev->setup_ops->predisable) { | |
| 773 | + ret2 = indio_dev->setup_ops->predisable(indio_dev); | |
| 774 | + if (ret2 && !ret) | |
| 775 | + ret = ret2; | |
| 776 | + } | |
| 777 | + | |
| 778 | + indio_dev->currentmode = INDIO_DIRECT_MODE; | |
| 779 | + | |
| 780 | + if (indio_dev->setup_ops->postdisable) { | |
| 781 | + ret2 = indio_dev->setup_ops->postdisable(indio_dev); | |
| 782 | + if (ret2 && !ret) | |
| 783 | + ret = ret2; | |
| 784 | + } | |
| 785 | + | |
| 786 | + iio_free_scan_mask(indio_dev, indio_dev->active_scan_mask); | |
| 787 | + indio_dev->active_scan_mask = NULL; | |
| 788 | + | |
| 789 | + return ret; | |
| 790 | +} | |
| 791 | + | |
| 792 | +static int __iio_update_buffers(struct iio_dev *indio_dev, | |
| 793 | + struct iio_buffer *insert_buffer, | |
| 794 | + struct iio_buffer *remove_buffer) | |
| 795 | +{ | |
| 796 | + struct iio_device_config new_config; | |
| 797 | + int ret; | |
| 798 | + | |
| 799 | + ret = iio_verify_update(indio_dev, insert_buffer, remove_buffer, | |
| 800 | + &new_config); | |
| 801 | + if (ret) | |
| 802 | + return ret; | |
| 803 | + | |
| 804 | + if (insert_buffer) { | |
| 805 | + ret = iio_buffer_request_update(indio_dev, insert_buffer); | |
| 806 | + if (ret) | |
| 807 | + goto err_free_config; | |
| 808 | + } | |
| 809 | + | |
| 810 | + ret = iio_disable_buffers(indio_dev); | |
| 811 | + if (ret) | |
| 812 | + goto err_deactivate_all; | |
| 813 | + | |
| 814 | + if (remove_buffer) | |
| 815 | + iio_buffer_deactivate(remove_buffer); | |
| 735 | 816 | if (insert_buffer) |
| 736 | − iio_buffer_deactivate(insert_buffer); | |
| 737 | − indio_dev->active_scan_mask = old_mask; | |
| 738 | − kfree(compound_mask); | |
| 817 | + iio_buffer_activate(indio_dev, insert_buffer); | |
| 818 | + | |
| 819 | + /* If no buffers in list, we are done */ | |
| 820 | + if (list_empty(&indio_dev->buffer_list)) | |
| 821 | + return 0; | |
| 822 | + | |
| 823 | + ret = iio_enable_buffers(indio_dev, &new_config); | |
| 824 | + if (ret) | |
| 825 | + goto err_deactivate_all; | |
| 826 | + | |
| 827 | + return 0; | |
| 828 | + | |
| 829 | +err_deactivate_all: | |
| 830 | + /* | |
| 831 | + * We've already verified that the config is valid earlier. If things go | |
| 832 | + * wrong in either enable or disable the most likely reason is an IO | |
| 833 | + * error from the device. In this case there is no good recovery | |
| 834 | + * strategy. Just make sure to disable everything and leave the device | |
| 835 | + * in a sane state. With a bit of luck the device might come back to | |
| 836 | + * life again later and userspace can try again. | |
| 837 | + */ | |
| 838 | + iio_buffer_deactivate_all(indio_dev); | |
| 839 | + | |
| 840 | +err_free_config: | |
| 841 | + iio_free_scan_mask(indio_dev, new_config.scan_mask); | |
| 739 | 842 | return ret; |
| 740 | 843 | } |
| 741 | 844 | |
| @@ -777,6 +880,12 @@ out_unlock: · 35 unmodified lines | ||
| 777 | 880 | } |
| 778 | 881 | EXPORT_SYMBOL_GPL(iio_update_buffers); |
| 779 | 882 | |
| 883 | +void iio_disable_all_buffers(struct iio_dev *indio_dev) | |
| 884 | +{ | |
| 885 | + iio_disable_buffers(indio_dev); | |
| 886 | + iio_buffer_deactivate_all(indio_dev); | |
| 887 | +} | |
| 888 | + | |
| 780 | 889 | static ssize_t iio_buffer_store_enable(struct device *dev, |
| 781 | 890 | struct device_attribute *attr, |
| 782 | 891 | const char *buf, |
| @@ -806,8 +915,6 @@ static ssize_t iio_buffer_store_enable(struct device *dev, · 23 unmodified lines | ||
| 806 | 915 | ret = __iio_update_buffers(indio_dev, |
| 807 | 916 | NULL, indio_dev->buffer); |
| 808 | 917 | |
| 809 | − if (ret < 0) | |
| 810 | − goto done; | |
| 811 | 918 | done: |
| 812 | 919 | mutex_unlock(&indio_dev->mlock); |
| 813 | 920 | return (ret < 0) ? ret : len; |
| @@ -886,6 +993,15 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) · 72 unmodified lines | ||
| 886 | 993 | int ret, i, attrn, attrcount, attrcount_orig = 0; |
| 887 | 994 | const struct iio_chan_spec *channels; |
| 888 | 995 | |
| 996 | + channels = indio_dev->channels; | |
| 997 | + if (channels) { | |
| 998 | + int ml = indio_dev->masklength; | |
| 999 | + | |
| 1000 | + for (i = 0; i < indio_dev->num_channels; i++) | |
| 1001 | + ml = max(ml, channels[i].scan_index + 1); | |
| 1002 | + indio_dev->masklength = ml; | |
| 1003 | + } | |
| 1004 | + | |
| 889 | 1005 | if (!buffer) |
| 890 | 1006 | return 0; |
| 891 | 1007 | |
| @@ -929,12 +1045,6 @@ int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev) · 37 unmodified lines | ||
| 929 | 1045 | if (channels[i].scan_index < 0) |
| 930 | 1046 | continue; |
| 931 | 1047 | |
| 932 | − /* Establish necessary mask length */ | |
| 933 | − if (channels[i].scan_index > | |
| 934 | − (int)indio_dev->masklength - 1) | |
| 935 | − indio_dev->masklength | |
| 936 | − = channels[i].scan_index + 1; | |
| 937 | − | |
| 938 | 1048 | ret = iio_buffer_add_channel_sysfs(indio_dev, |
| 939 | 1049 | &channels[i]); |
| 940 | 1050 | if (ret < 0) |
| @@ -101,6 +101,8 @@ static const char * const iio_modifier_names[] = { · 100 unmodified lines | ||
| 101 | 101 | [IIO_MOD_WALKING] = "walking", |
| 102 | 102 | [IIO_MOD_STILL] = "still", |
| 103 | 103 | [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", |
| 104 | + [IIO_MOD_I] = "i", | |
| 105 | + [IIO_MOD_Q] = "q", | |
| 104 | 106 | }; |
| 105 | 107 | |
| 106 | 108 | /* relies on pairs of these shared then separate */ |
| @@ -117,6 +119,8 @@ static const char * const iio_chan_info_postfix[] = { · 10 unmodified lines | ||
| 117 | 119 | [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", |
| 118 | 120 | [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] |
| 119 | 121 | = "filter_low_pass_3db_frequency", |
| 122 | + [IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY] | |
| 123 | + = "filter_high_pass_3db_frequency", | |
| 120 | 124 | [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", |
| 121 | 125 | [IIO_CHAN_INFO_FREQUENCY] = "frequency", |
| 122 | 126 | [IIO_CHAN_INFO_PHASE] = "phase", |
| @@ -128,6 +132,8 @@ static const char * const iio_chan_info_postfix[] = { · 5 unmodified lines | ||
| 128 | 132 | [IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight", |
| 129 | 133 | [IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count", |
| 130 | 134 | [IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time", |
| 135 | + [IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity", | |
| 136 | + [IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio", | |
| 131 | 137 | }; |
| 132 | 138 | |
| 133 | 139 | /** |
| @@ -211,6 +211,8 @@ static const char * const iio_ev_info_text[] = { · 210 unmodified lines | ||
| 211 | 211 | [IIO_EV_INFO_VALUE] = "value", |
| 212 | 212 | [IIO_EV_INFO_HYSTERESIS] = "hysteresis", |
| 213 | 213 | [IIO_EV_INFO_PERIOD] = "period", |
| 214 | + [IIO_EV_INFO_HIGH_PASS_FILTER_3DB] = "high_pass_filter_3db", | |
| 215 | + [IIO_EV_INFO_LOW_PASS_FILTER_3DB] = "low_pass_filter_3db", | |
| 214 | 216 | }; |
| 215 | 217 | |
| 216 | 218 | static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr) |
| @@ -136,6 +136,8 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = { · 135 unmodified lines | ||
| 136 | 136 | .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, |
| 137 | 137 | .set_length = &iio_set_length_kfifo, |
| 138 | 138 | .release = &iio_kfifo_buffer_release, |
| 139 | + | |
| 140 | + .modes = INDIO_BUFFER_SOFTWARE | INDIO_BUFFER_TRIGGERED, | |
| 139 | 141 | }; |
| 140 | 142 | |
| 141 | 143 | struct iio_buffer *iio_kfifo_allocate(void) |
| @@ -5,6 +5,19 @@ · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | menu "Light sensors" |
| 7 | 7 | |
| 8 | +config ACPI_ALS | |
| 9 | + tristate "ACPI Ambient Light Sensor" | |
| 10 | + depends on ACPI | |
| 11 | + select IIO_BUFFER | |
| 12 | + select IIO_TRIGGERED_BUFFER | |
| 13 | + select IIO_KFIFO_BUF | |
| 14 | + help | |
| 15 | + Say Y here if you want to build a driver for the ACPI0008 | |
| 16 | + Ambient Light Sensor. | |
| 17 | + | |
| 18 | + To compile this driver as a module, choose M here: the module will | |
| 19 | + be called acpi-als. | |
| 20 | + | |
| 8 | 21 | config ADJD_S311 |
| 9 | 22 | tristate "ADJD-S311-CR999 digital color sensor" |
| 10 | 23 | select IIO_BUFFER |
| @@ -37,6 +50,16 @@ config APDS9300 · 26 unmodified lines | ||
| 37 | 50 | To compile this driver as a module, choose M here: the |
| 38 | 51 | module will be called apds9300. |
| 39 | 52 | |
| 53 | +config BH1750 | |
| 54 | + tristate "ROHM BH1750 ambient light sensor" | |
| 55 | + depends on I2C | |
| 56 | + help | |
| 57 | + Say Y here to build support for the ROHM BH1710, BH1715, BH1721, | |
| 58 | + BH1750, BH1751 ambient light sensors. | |
| 59 | + | |
| 60 | + To compile this driver as a module, choose M here: the module will | |
| 61 | + be called bh1750. | |
| 62 | + | |
| 40 | 63 | config CM32181 |
| 41 | 64 | depends on I2C |
| 42 | 65 | tristate "CM32181 driver" |
| @@ -169,11 +192,23 @@ config LTR501 · 126 unmodified lines | ||
| 169 | 192 | select IIO_TRIGGERED_BUFFER |
| 170 | 193 | help |
| 171 | 194 | If you say yes here you get support for the Lite-On LTR-501ALS-01 |
| 172 | − ambient light and proximity sensor. | |
| 195 | + ambient light and proximity sensor. This driver also supports LTR-559 | |
| 196 | + ALS/PS or LTR-301 ALS sensors. | |
| 173 | 197 | |
| 174 | 198 | This driver can also be built as a module. If so, the module |
| 175 | 199 | will be called ltr501. |
| 176 | 200 | |
| 201 | +config STK3310 | |
| 202 | + tristate "STK3310 ALS and proximity sensor" | |
| 203 | + depends on I2C | |
| 204 | + help | |
| 205 | + Say yes here to get support for the Sensortek STK3310 ambient light | |
| 206 | + and proximity sensor. The STK3311 model is also supported by this | |
| 207 | + driver. | |
| 208 | + | |
| 209 | + Choosing M will build the driver as a module. If so, the module | |
| 210 | + will be called stk3310. | |
| 211 | + | |
| 177 | 212 | config TCS3414 |
| 178 | 213 | tristate "TAOS TCS3414 digital color sensor" |
| 179 | 214 | depends on I2C |
| @@ -3,9 +3,11 @@ · 2 unmodified lines | ||
| 3 | 3 | # |
| 4 | 4 | |
| 5 | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | +obj-$(CONFIG_ACPI_ALS) += acpi-als.o | |
| 6 | 7 | obj-$(CONFIG_ADJD_S311) += adjd_s311.o |
| 7 | 8 | obj-$(CONFIG_AL3320A) += al3320a.o |
| 8 | 9 | obj-$(CONFIG_APDS9300) += apds9300.o |
| 10 | +obj-$(CONFIG_BH1750) += bh1750.o | |
| 9 | 11 | obj-$(CONFIG_CM32181) += cm32181.o |
| 10 | 12 | obj-$(CONFIG_CM3232) += cm3232.o |
| 11 | 13 | obj-$(CONFIG_CM3323) += cm3323.o |
| @@ -18,6 +20,7 @@ obj-$(CONFIG_JSA1212) += jsa1212.o · 6 unmodified lines | ||
| 18 | 20 | obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o |
| 19 | 21 | obj-$(CONFIG_LTR501) += ltr501.o |
| 20 | 22 | obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o |
| 23 | +obj-$(CONFIG_STK3310) += stk3310.o | |
| 21 | 24 | obj-$(CONFIG_TCS3414) += tcs3414.o |
| 22 | 25 | obj-$(CONFIG_TCS3472) += tcs3472.o |
| 23 | 26 | obj-$(CONFIG_TSL4531) += tsl4531.o |
| @@ -0,0 +1,231 @@ | ||
| 1 | +/* | |
| 2 | + * ACPI Ambient Light Sensor Driver | |
| 3 | + * | |
| 4 | + * Based on ALS driver: | |
| 5 | + * Copyright (C) 2009 Zhang Rui <rui.zhang@intel.com> | |
| 6 | + * | |
| 7 | + * Rework for IIO subsystem: | |
| 8 | + * Copyright (C) 2012-2013 Martin Liska <marxin.liska@gmail.com> | |
| 9 | + * | |
| 10 | + * Final cleanup and debugging: | |
| 11 | + * Copyright (C) 2013-2014 Marek Vasut <marex@denx.de> | |
| 12 | + * Copyright (C) 2015 Gabriele Mazzotta <gabriele.mzt@gmail.com> | |
| 13 | + * | |
| 14 | + * This program is free software; you can redistribute it and/or modify it | |
| 15 | + * under the terms of the GNU General Public License as published by the | |
| 16 | + * Free Software Foundation; either version 2 of the License, or (at your | |
| 17 | + * option) any later version. | |
| 18 | + * | |
| 19 | + * This program is distributed in the hope that it will be useful, but | |
| 20 | + * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 21 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 22 | + * General Public License for more details. | |
| 23 | + * | |
| 24 | + * You should have received a copy of the GNU General Public License along | |
| 25 | + * with this program; if not, write to the Free Software Foundation, Inc., | |
| 26 | + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 27 | + */ | |
| 28 | + | |
| 29 | +#include <linux/module.h> | |
| 30 | +#include <linux/acpi.h> | |
| 31 | +#include <linux/err.h> | |
| 32 | +#include <linux/mutex.h> | |
| 33 | + | |
| 34 | +#include <linux/iio/iio.h> | |
| 35 | +#include <linux/iio/buffer.h> | |
| 36 | +#include <linux/iio/kfifo_buf.h> | |
| 37 | + | |
| 38 | +#define ACPI_ALS_CLASS "als" | |
| 39 | +#define ACPI_ALS_DEVICE_NAME "acpi-als" | |
| 40 | +#define ACPI_ALS_NOTIFY_ILLUMINANCE 0x80 | |
| 41 | + | |
| 42 | +ACPI_MODULE_NAME("acpi-als"); | |
| 43 | + | |
| 44 | +/* | |
| 45 | + * So far, there's only one channel in here, but the specification for | |
| 46 | + * ACPI0008 says there can be more to what the block can report. Like | |
| 47 | + * chromaticity and such. We are ready for incoming additions! | |
| 48 | + */ | |
| 49 | +static const struct iio_chan_spec acpi_als_channels[] = { | |
| 50 | + { | |
| 51 | + .type = IIO_LIGHT, | |
| 52 | + .scan_type = { | |
| 53 | + .sign = 's', | |
| 54 | + .realbits = 32, | |
| 55 | + .storagebits = 32, | |
| 56 | + }, | |
| 57 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
| 58 | + }, | |
| 59 | +}; | |
| 60 | + | |
| 61 | +/* | |
| 62 | + * The event buffer contains timestamp and all the data from | |
| 63 | + * the ACPI0008 block. There are multiple, but so far we only | |
| 64 | + * support _ALI (illuminance). Once someone adds new channels | |
| 65 | + * to acpi_als_channels[], the evt_buffer below will grow | |
| 66 | + * automatically. | |
| 67 | + */ | |
| 68 | +#define EVT_NR_SOURCES ARRAY_SIZE(acpi_als_channels) | |
| 69 | +#define EVT_BUFFER_SIZE \ | |
| 70 | + (sizeof(s64) + (EVT_NR_SOURCES * sizeof(s32))) | |
| 71 | + | |
| 72 | +struct acpi_als { | |
| 73 | + struct acpi_device *device; | |
| 74 | + struct mutex lock; | |
| 75 | + | |
| 76 | + s32 evt_buffer[EVT_BUFFER_SIZE]; | |
| 77 | +}; | |
| 78 | + | |
| 79 | +/* | |
| 80 | + * All types of properties the ACPI0008 block can report. The ALI, ALC, ALT | |
| 81 | + * and ALP can all be handled by als_read_value() below, while the ALR is | |
| 82 | + * special. | |
| 83 | + * | |
| 84 | + * The _ALR property returns tables that can be used to fine-tune the values | |
| 85 | + * reported by the other props based on the particular hardware type and it's | |
| 86 | + * location (it contains tables for "rainy", "bright inhouse lighting" etc.). | |
| 87 | + * | |
| 88 | + * So far, we support only ALI (illuminance). | |
| 89 | + */ | |
| 90 | +#define ACPI_ALS_ILLUMINANCE "_ALI" | |
| 91 | +#define ACPI_ALS_CHROMATICITY "_ALC" | |
| 92 | +#define ACPI_ALS_COLOR_TEMP "_ALT" | |
| 93 | +#define ACPI_ALS_POLLING "_ALP" | |
| 94 | +#define ACPI_ALS_TABLES "_ALR" | |
| 95 | + | |
| 96 | +static int als_read_value(struct acpi_als *als, char *prop, s32 *val) | |
| 97 | +{ | |
| 98 | + unsigned long long temp_val; | |
| 99 | + acpi_status status; | |
| 100 | + | |
| 101 | + status = acpi_evaluate_integer(als->device->handle, prop, NULL, | |
| 102 | + &temp_val); | |
| 103 | + | |
| 104 | + if (ACPI_FAILURE(status)) { | |
| 105 | + ACPI_EXCEPTION((AE_INFO, status, "Error reading ALS %s", prop)); | |
| 106 | + return -EIO; | |
| 107 | + } | |
| 108 | + | |
| 109 | + *val = temp_val; | |
| 110 | + | |
| 111 | + return 0; | |
| 112 | +} | |
| 113 | + | |
| 114 | +static void acpi_als_notify(struct acpi_device *device, u32 event) | |
| 115 | +{ | |
| 116 | + struct iio_dev *indio_dev = acpi_driver_data(device); | |
| 117 | + struct acpi_als *als = iio_priv(indio_dev); | |
| 118 | + s32 *buffer = als->evt_buffer; | |
| 119 | + s64 time_ns = iio_get_time_ns(); | |
| 120 | + s32 val; | |
| 121 | + int ret; | |
| 122 | + | |
| 123 | + mutex_lock(&als->lock); | |
| 124 | + | |
| 125 | + memset(buffer, 0, EVT_BUFFER_SIZE); | |
| 126 | + | |
| 127 | + switch (event) { | |
| 128 | + case ACPI_ALS_NOTIFY_ILLUMINANCE: | |
| 129 | + ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &val); | |
| 130 | + if (ret < 0) | |
| 131 | + goto out; | |
| 132 | + *buffer++ = val; | |
| 133 | + break; | |
| 134 | + default: | |
| 135 | + /* Unhandled event */ | |
| 136 | + dev_dbg(&device->dev, "Unhandled ACPI ALS event (%08x)!\n", | |
| 137 | + event); | |
| 138 | + goto out; | |
| 139 | + } | |
| 140 | + | |
| 141 | + iio_push_to_buffers_with_timestamp(indio_dev, als->evt_buffer, time_ns); | |
| 142 | + | |
| 143 | +out: | |
| 144 | + mutex_unlock(&als->lock); | |
| 145 | +} | |
| 146 | + | |
| 147 | +static int acpi_als_read_raw(struct iio_dev *indio_dev, | |
| 148 | + struct iio_chan_spec const *chan, int *val, | |
| 149 | + int *val2, long mask) | |
| 150 | +{ | |
| 151 | + struct acpi_als *als = iio_priv(indio_dev); | |
| 152 | + s32 temp_val; | |
| 153 | + int ret; | |
| 154 | + | |
| 155 | + if (mask != IIO_CHAN_INFO_RAW) | |
| 156 | + return -EINVAL; | |
| 157 | + | |
| 158 | + /* we support only illumination (_ALI) so far. */ | |
| 159 | + if (chan->type != IIO_LIGHT) | |
| 160 | + return -EINVAL; | |
| 161 | + | |
| 162 | + ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val); | |
| 163 | + if (ret < 0) | |
| 164 | + return ret; | |
| 165 | + | |
| 166 | + *val = temp_val; | |
| 167 | + | |
| 168 | + return IIO_VAL_INT; | |
| 169 | +} | |
| 170 | + | |
| 171 | +static const struct iio_info acpi_als_info = { | |
| 172 | + .driver_module = THIS_MODULE, | |
| 173 | + .read_raw = acpi_als_read_raw, | |
| 174 | +}; | |
| 175 | + | |
| 176 | +static int acpi_als_add(struct acpi_device *device) | |
| 177 | +{ | |
| 178 | + struct acpi_als *als; | |
| 179 | + struct iio_dev *indio_dev; | |
| 180 | + struct iio_buffer *buffer; | |
| 181 | + | |
| 182 | + indio_dev = devm_iio_device_alloc(&device->dev, sizeof(*als)); | |
| 183 | + if (!indio_dev) | |
| 184 | + return -ENOMEM; | |
| 185 | + | |
| 186 | + als = iio_priv(indio_dev); | |
| 187 | + | |
| 188 | + device->driver_data = indio_dev; | |
| 189 | + als->device = device; | |
| 190 | + mutex_init(&als->lock); | |
| 191 | + | |
| 192 | + indio_dev->name = ACPI_ALS_DEVICE_NAME; | |
| 193 | + indio_dev->dev.parent = &device->dev; | |
| 194 | + indio_dev->info = &acpi_als_info; | |
| 195 | + indio_dev->modes = INDIO_BUFFER_SOFTWARE; | |
| 196 | + indio_dev->channels = acpi_als_channels; | |
| 197 | + indio_dev->num_channels = ARRAY_SIZE(acpi_als_channels); | |
| 198 | + | |
| 199 | + buffer = devm_iio_kfifo_allocate(&device->dev); | |
| 200 | + if (!buffer) | |
| 201 | + return -ENOMEM; | |
| 202 | + | |
| 203 | + iio_device_attach_buffer(indio_dev, buffer); | |
| 204 | + | |
| 205 | + return devm_iio_device_register(&device->dev, indio_dev); | |
| 206 | +} | |
| 207 | + | |
| 208 | +static const struct acpi_device_id acpi_als_device_ids[] = { | |
| 209 | + {"ACPI0008", 0}, | |
| 210 | + {}, | |
| 211 | +}; | |
| 212 | + | |
| 213 | +MODULE_DEVICE_TABLE(acpi, acpi_als_device_ids); | |
| 214 | + | |
| 215 | +static struct acpi_driver acpi_als_driver = { | |
| 216 | + .name = "acpi_als", | |
| 217 | + .class = ACPI_ALS_CLASS, | |
| 218 | + .ids = acpi_als_device_ids, | |
| 219 | + .ops = { | |
| 220 | + .add = acpi_als_add, | |
| 221 | + .notify = acpi_als_notify, | |
| 222 | + }, | |
| 223 | +}; | |
| 224 | + | |
| 225 | +module_acpi_driver(acpi_als_driver); | |
| 226 | + | |
| 227 | +MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>"); | |
| 228 | +MODULE_AUTHOR("Martin Liska <marxin.liska@gmail.com>"); | |
| 229 | +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | |
| 230 | +MODULE_DESCRIPTION("ACPI Ambient Light Sensor Driver"); | |
| 231 | +MODULE_LICENSE("GPL"); | |
| @@ -0,0 +1,334 @@ | ||
| 1 | +/* | |
| 2 | + * ROHM BH1710/BH1715/BH1721/BH1750/BH1751 ambient light sensor driver | |
| 3 | + * | |
| 4 | + * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License version 2 as | |
| 8 | + * published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * Data sheets: | |
| 11 | + * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1710fvc-e.pdf | |
| 12 | + * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1715fvc-e.pdf | |
| 13 | + * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1721fvc-e.pdf | |
| 14 | + * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf | |
| 15 | + * http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1751fvi-e.pdf | |
| 16 | + * | |
| 17 | + * 7-bit I2C slave addresses: | |
| 18 | + * 0x23 (ADDR pin low) | |
| 19 | + * 0x5C (ADDR pin high) | |
| 20 | + * | |
| 21 | + */ | |
| 22 | + | |
| 23 | +#include <linux/delay.h> | |
| 24 | +#include <linux/i2c.h> | |
| 25 | +#include <linux/iio/iio.h> | |
| 26 | +#include <linux/iio/sysfs.h> | |
| 27 | +#include <linux/module.h> | |
| 28 | + | |
| 29 | +#define BH1750_POWER_DOWN 0x00 | |
| 30 | +#define BH1750_ONE_TIME_H_RES_MODE 0x20 /* auto-mode for BH1721 */ | |
| 31 | +#define BH1750_CHANGE_INT_TIME_H_BIT 0x40 | |
| 32 | +#define BH1750_CHANGE_INT_TIME_L_BIT 0x60 | |
| 33 | + | |
| 34 | +enum { | |
| 35 | + BH1710, | |
| 36 | + BH1721, | |
| 37 | + BH1750, | |
| 38 | +}; | |
| 39 | + | |
| 40 | +struct bh1750_chip_info; | |
| 41 | +struct bh1750_data { | |
| 42 | + struct i2c_client *client; | |
| 43 | + struct mutex lock; | |
| 44 | + const struct bh1750_chip_info *chip_info; | |
| 45 | + u16 mtreg; | |
| 46 | +}; | |
| 47 | + | |
| 48 | +struct bh1750_chip_info { | |
| 49 | + u16 mtreg_min; | |
| 50 | + u16 mtreg_max; | |
| 51 | + u16 mtreg_default; | |
| 52 | + int mtreg_to_usec; | |
| 53 | + int mtreg_to_scale; | |
| 54 | + | |
| 55 | + /* | |
| 56 | + * For BH1710/BH1721 all possible integration time values won't fit | |
| 57 | + * into one page so displaying is limited to every second one. | |
| 58 | + * Note, that user can still write proper values which were not | |
| 59 | + * listed. | |
| 60 | + */ | |
| 61 | + int inc; | |
| 62 | + | |
| 63 | + u16 int_time_low_mask; | |
| 64 | + u16 int_time_high_mask; | |
| 65 | +} | |
| 66 | + | |
| 67 | +static const bh1750_chip_info_tbl[] = { | |
| 68 | + [BH1710] = { 140, 1022, 300, 400, 250000000, 2, 0x001F, 0x03E0 }, | |
| 69 | + [BH1721] = { 140, 1020, 300, 400, 250000000, 2, 0x0010, 0x03E0 }, | |
| 70 | + [BH1750] = { 31, 254, 69, 1740, 57500000, 1, 0x001F, 0x00E0 }, | |
| 71 | +}; | |
| 72 | + | |
| 73 | +static int bh1750_change_int_time(struct bh1750_data *data, int usec) | |
| 74 | +{ | |
| 75 | + int ret; | |
| 76 | + u16 val; | |
| 77 | + u8 regval; | |
| 78 | + const struct bh1750_chip_info *chip_info = data->chip_info; | |
| 79 | + | |
| 80 | + if ((usec % chip_info->mtreg_to_usec) != 0) | |
| 81 | + return -EINVAL; | |
| 82 | + | |
| 83 | + val = usec / chip_info->mtreg_to_usec; | |
| 84 | + if (val < chip_info->mtreg_min || val > chip_info->mtreg_max) | |
| 85 | + return -EINVAL; | |
| 86 | + | |
| 87 | + ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN); | |
| 88 | + if (ret < 0) | |
| 89 | + return ret; | |
| 90 | + | |
| 91 | + regval = (val & chip_info->int_time_high_mask) >> 5; | |
| 92 | + ret = i2c_smbus_write_byte(data->client, | |
| 93 | + BH1750_CHANGE_INT_TIME_H_BIT | regval); | |
| 94 | + if (ret < 0) | |
| 95 | + return ret; | |
| 96 | + | |
| 97 | + regval = val & chip_info->int_time_low_mask; | |
| 98 | + ret = i2c_smbus_write_byte(data->client, | |
| 99 | + BH1750_CHANGE_INT_TIME_L_BIT | regval); | |
| 100 | + if (ret < 0) | |
| 101 | + return ret; | |
| 102 | + | |
| 103 | + data->mtreg = val; | |
| 104 | + | |
| 105 | + return 0; | |
| 106 | +} | |
| 107 | + | |
| 108 | +static int bh1750_read(struct bh1750_data *data, int *val) | |
| 109 | +{ | |
| 110 | + int ret; | |
| 111 | + __be16 result; | |
| 112 | + const struct bh1750_chip_info *chip_info = data->chip_info; | |
| 113 | + unsigned long delay = chip_info->mtreg_to_usec * data->mtreg; | |
| 114 | + | |
| 115 | + /* | |
| 116 | + * BH1721 will enter continuous mode on receiving this command. | |
| 117 | + * Note, that this eliminates need for bh1750_resume(). | |
| 118 | + */ | |
| 119 | + ret = i2c_smbus_write_byte(data->client, BH1750_ONE_TIME_H_RES_MODE); | |
| 120 | + if (ret < 0) | |
| 121 | + return ret; | |
| 122 | + | |
| 123 | + usleep_range(delay + 15000, delay + 40000); | |
| 124 | + | |
| 125 | + ret = i2c_master_recv(data->client, (char *)&result, 2); | |
| 126 | + if (ret < 0) | |
| 127 | + return ret; | |
| 128 | + | |
| 129 | + *val = be16_to_cpu(result); | |
| 130 | + | |
| 131 | + return 0; | |
| 132 | +} | |
| 133 | + | |
| 134 | +static int bh1750_read_raw(struct iio_dev *indio_dev, | |
| 135 | + struct iio_chan_spec const *chan, | |
| 136 | + int *val, int *val2, long mask) | |
| 137 | +{ | |
| 138 | + int ret, tmp; | |
| 139 | + struct bh1750_data *data = iio_priv(indio_dev); | |
| 140 | + const struct bh1750_chip_info *chip_info = data->chip_info; | |
| 141 | + | |
| 142 | + switch (mask) { | |
| 143 | + case IIO_CHAN_INFO_RAW: | |
| 144 | + switch (chan->type) { | |
| 145 | + case IIO_LIGHT: | |
| 146 | + mutex_lock(&data->lock); | |
| 147 | + ret = bh1750_read(data, val); | |
| 148 | + mutex_unlock(&data->lock); | |
| 149 | + if (ret < 0) | |
| 150 | + return ret; | |
| 151 | + | |
| 152 | + return IIO_VAL_INT; | |
| 153 | + default: | |
| 154 | + return -EINVAL; | |
| 155 | + } | |
| 156 | + case IIO_CHAN_INFO_SCALE: | |
| 157 | + tmp = chip_info->mtreg_to_scale / data->mtreg; | |
| 158 | + *val = tmp / 1000000; | |
| 159 | + *val2 = tmp % 1000000; | |
| 160 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 161 | + case IIO_CHAN_INFO_INT_TIME: | |
| 162 | + *val = 0; | |
| 163 | + *val2 = chip_info->mtreg_to_usec * data->mtreg; | |
| 164 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 165 | + default: | |
| 166 | + return -EINVAL; | |
| 167 | + } | |
| 168 | +} | |
| 169 | + | |
| 170 | +static int bh1750_write_raw(struct iio_dev *indio_dev, | |
| 171 | + struct iio_chan_spec const *chan, | |
| 172 | + int val, int val2, long mask) | |
| 173 | +{ | |
| 174 | + int ret; | |
| 175 | + struct bh1750_data *data = iio_priv(indio_dev); | |
| 176 | + | |
| 177 | + switch (mask) { | |
| 178 | + case IIO_CHAN_INFO_INT_TIME: | |
| 179 | + if (val != 0) | |
| 180 | + return -EINVAL; | |
| 181 | + | |
| 182 | + mutex_lock(&data->lock); | |
| 183 | + ret = bh1750_change_int_time(data, val2); | |
| 184 | + mutex_unlock(&data->lock); | |
| 185 | + return ret; | |
| 186 | + default: | |
| 187 | + return -EINVAL; | |
| 188 | + } | |
| 189 | +} | |
| 190 | + | |
| 191 | +static ssize_t bh1750_show_int_time_available(struct device *dev, | |
| 192 | + struct device_attribute *attr, char *buf) | |
| 193 | +{ | |
| 194 | + int i; | |
| 195 | + size_t len = 0; | |
| 196 | + struct bh1750_data *data = iio_priv(dev_to_iio_dev(dev)); | |
| 197 | + const struct bh1750_chip_info *chip_info = data->chip_info; | |
| 198 | + | |
| 199 | + for (i = chip_info->mtreg_min; i <= chip_info->mtreg_max; i += chip_info->inc) | |
| 200 | + len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06d ", | |
| 201 | + chip_info->mtreg_to_usec * i); | |
| 202 | + | |
| 203 | + buf[len - 1] = '\n'; | |
| 204 | + | |
| 205 | + return len; | |
| 206 | +} | |
| 207 | + | |
| 208 | +static IIO_DEV_ATTR_INT_TIME_AVAIL(bh1750_show_int_time_available); | |
| 209 | + | |
| 210 | +static struct attribute *bh1750_attributes[] = { | |
| 211 | + &iio_dev_attr_integration_time_available.dev_attr.attr, | |
| 212 | + NULL, | |
| 213 | +}; | |
| 214 | + | |
| 215 | +static struct attribute_group bh1750_attribute_group = { | |
| 216 | + .attrs = bh1750_attributes, | |
| 217 | +}; | |
| 218 | + | |
| 219 | +static const struct iio_info bh1750_info = { | |
| 220 | + .driver_module = THIS_MODULE, | |
| 221 | + .attrs = &bh1750_attribute_group, | |
| 222 | + .read_raw = bh1750_read_raw, | |
| 223 | + .write_raw = bh1750_write_raw, | |
| 224 | +}; | |
| 225 | + | |
| 226 | +static const struct iio_chan_spec bh1750_channels[] = { | |
| 227 | + { | |
| 228 | + .type = IIO_LIGHT, | |
| 229 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
| 230 | + BIT(IIO_CHAN_INFO_SCALE) | | |
| 231 | + BIT(IIO_CHAN_INFO_INT_TIME) | |
| 232 | + } | |
| 233 | +}; | |
| 234 | + | |
| 235 | +static int bh1750_probe(struct i2c_client *client, | |
| 236 | + const struct i2c_device_id *id) | |
| 237 | +{ | |
| 238 | + int ret, usec; | |
| 239 | + struct bh1750_data *data; | |
| 240 | + struct iio_dev *indio_dev; | |
| 241 | + | |
| 242 | + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | | |
| 243 | + I2C_FUNC_SMBUS_WRITE_BYTE)) | |
| 244 | + return -ENODEV; | |
| 245 | + | |
| 246 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 247 | + if (!indio_dev) | |
| 248 | + return -ENOMEM; | |
| 249 | + | |
| 250 | + data = iio_priv(indio_dev); | |
| 251 | + i2c_set_clientdata(client, indio_dev); | |
| 252 | + data->client = client; | |
| 253 | + data->chip_info = &bh1750_chip_info_tbl[id->driver_data]; | |
| 254 | + | |
| 255 | + usec = data->chip_info->mtreg_to_usec * data->chip_info->mtreg_default; | |
| 256 | + ret = bh1750_change_int_time(data, usec); | |
| 257 | + if (ret < 0) | |
| 258 | + return ret; | |
| 259 | + | |
| 260 | + mutex_init(&data->lock); | |
| 261 | + indio_dev->dev.parent = &client->dev; | |
| 262 | + indio_dev->info = &bh1750_info; | |
| 263 | + indio_dev->name = id->name; | |
| 264 | + indio_dev->channels = bh1750_channels; | |
| 265 | + indio_dev->num_channels = ARRAY_SIZE(bh1750_channels); | |
| 266 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 267 | + | |
| 268 | + return iio_device_register(indio_dev); | |
| 269 | +} | |
| 270 | + | |
| 271 | +static int bh1750_remove(struct i2c_client *client) | |
| 272 | +{ | |
| 273 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 274 | + struct bh1750_data *data = iio_priv(indio_dev); | |
| 275 | + | |
| 276 | + iio_device_unregister(indio_dev); | |
| 277 | + | |
| 278 | + mutex_lock(&data->lock); | |
| 279 | + i2c_smbus_write_byte(client, BH1750_POWER_DOWN); | |
| 280 | + mutex_unlock(&data->lock); | |
| 281 | + | |
| 282 | + return 0; | |
| 283 | +} | |
| 284 | + | |
| 285 | +#ifdef CONFIG_PM_SLEEP | |
| 286 | +static int bh1750_suspend(struct device *dev) | |
| 287 | +{ | |
| 288 | + int ret; | |
| 289 | + struct bh1750_data *data = | |
| 290 | + iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | |
| 291 | + | |
| 292 | + /* | |
| 293 | + * This is mainly for BH1721 which doesn't enter power down | |
| 294 | + * mode automatically. | |
| 295 | + */ | |
| 296 | + mutex_lock(&data->lock); | |
| 297 | + ret = i2c_smbus_write_byte(data->client, BH1750_POWER_DOWN); | |
| 298 | + mutex_unlock(&data->lock); | |
| 299 | + | |
| 300 | + return ret; | |
| 301 | +} | |
| 302 | + | |
| 303 | +static SIMPLE_DEV_PM_OPS(bh1750_pm_ops, bh1750_suspend, NULL); | |
| 304 | +#define BH1750_PM_OPS (&bh1750_pm_ops) | |
| 305 | +#else | |
| 306 | +#define BH1750_PM_OPS NULL | |
| 307 | +#endif | |
| 308 | + | |
| 309 | +static const struct i2c_device_id bh1750_id[] = { | |
| 310 | + { "bh1710", BH1710 }, | |
| 311 | + { "bh1715", BH1750 }, | |
| 312 | + { "bh1721", BH1721 }, | |
| 313 | + { "bh1750", BH1750 }, | |
| 314 | + { "bh1751", BH1750 }, | |
| 315 | + { } | |
| 316 | +}; | |
| 317 | +MODULE_DEVICE_TABLE(i2c, bh1750_id); | |
| 318 | + | |
| 319 | +static struct i2c_driver bh1750_driver = { | |
| 320 | + .driver = { | |
| 321 | + .name = "bh1750", | |
| 322 | + .owner = THIS_MODULE, | |
| 323 | + .pm = BH1750_PM_OPS, | |
| 324 | + }, | |
| 325 | + .probe = bh1750_probe, | |
| 326 | + .remove = bh1750_remove, | |
| 327 | + .id_table = bh1750_id, | |
| 328 | + | |
| 329 | +}; | |
| 330 | +module_i2c_driver(bh1750_driver); | |
| 331 | + | |
| 332 | +MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>"); | |
| 333 | +MODULE_DESCRIPTION("ROHM BH1710/BH1715/BH1721/BH1750/BH1751 als driver"); | |
| 334 | +MODULE_LICENSE("GPL v2"); | |
| @@ -263,7 +263,6 @@ static int hid_als_probe(struct platform_device *pdev) · 262 unmodified lines | ||
| 263 | 263 | struct iio_dev *indio_dev; |
| 264 | 264 | struct als_state *als_state; |
| 265 | 265 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 266 | − struct iio_chan_spec *channels; | |
| 267 | 266 | |
| 268 | 267 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state)); |
| 269 | 268 | if (!indio_dev) |
| @@ -281,20 +280,21 @@ static int hid_als_probe(struct platform_device *pdev) · 11 unmodified lines | ||
| 281 | 280 | return ret; |
| 282 | 281 | } |
| 283 | 282 | |
| 284 | − channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL); | |
| 285 | − if (!channels) { | |
| 283 | + indio_dev->channels = kmemdup(als_channels, | |
| 284 | + sizeof(als_channels), GFP_KERNEL); | |
| 285 | + if (!indio_dev->channels) { | |
| 286 | 286 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 287 | 287 | return -ENOMEM; |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | − ret = als_parse_report(pdev, hsdev, channels, | |
| 291 | − HID_USAGE_SENSOR_ALS, als_state); | |
| 290 | + ret = als_parse_report(pdev, hsdev, | |
| 291 | + (struct iio_chan_spec *)indio_dev->channels, | |
| 292 | + HID_USAGE_SENSOR_ALS, als_state); | |
| 292 | 293 | if (ret) { |
| 293 | 294 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 294 | 295 | goto error_free_dev_mem; |
| 295 | 296 | } |
| 296 | 297 | |
| 297 | − indio_dev->channels = channels; | |
| 298 | 298 | indio_dev->num_channels = |
| 299 | 299 | ARRAY_SIZE(als_channels); |
| 300 | 300 | indio_dev->dev.parent = &pdev->dev; |
| @@ -361,7 +361,7 @@ static int hid_als_remove(struct platform_device *pdev) · 60 unmodified lines | ||
| 361 | 361 | return 0; |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | −static struct platform_device_id hid_als_ids[] = { | |
| 364 | +static const struct platform_device_id hid_als_ids[] = { | |
| 365 | 365 | { |
| 366 | 366 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 367 | 367 | .name = "HID-SENSOR-200041", |
| @@ -350,7 +350,7 @@ static int hid_prox_remove(struct platform_device *pdev) · 349 unmodified lines | ||
| 350 | 350 | return 0; |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | −static struct platform_device_id hid_prox_ids[] = { | |
| 353 | +static const struct platform_device_id hid_prox_ids[] = { | |
| 354 | 354 | { |
| 355 | 355 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 356 | 356 | .name = "HID-SENSOR-200011", |
| @@ -9,15 +9,18 @@ · 8 unmodified lines | ||
| 9 | 9 | * |
| 10 | 10 | * 7-bit I2C slave address 0x23 |
| 11 | 11 | * |
| 12 | − * TODO: interrupt, threshold, measurement rate, IR LED characteristics | |
| 12 | + * TODO: IR LED characteristics | |
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | 15 | #include <linux/module.h> |
| 16 | 16 | #include <linux/i2c.h> |
| 17 | 17 | #include <linux/err.h> |
| 18 | 18 | #include <linux/delay.h> |
| 19 | +#include <linux/regmap.h> | |
| 20 | +#include <linux/acpi.h> | |
| 19 | 21 | |
| 20 | 22 | #include <linux/iio/iio.h> |
| 23 | +#include <linux/iio/events.h> | |
| 21 | 24 | #include <linux/iio/sysfs.h> |
| 22 | 25 | #include <linux/iio/trigger_consumer.h> |
| 23 | 26 | #include <linux/iio/buffer.h> |
| @@ -27,12 +30,21 @@ · 3 unmodified lines | ||
| 27 | 30 | |
| 28 | 31 | #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */ |
| 29 | 32 | #define LTR501_PS_CONTR 0x81 /* PS operation mode */ |
| 33 | +#define LTR501_PS_MEAS_RATE 0x84 /* measurement rate*/ | |
| 34 | +#define LTR501_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/ | |
| 30 | 35 | #define LTR501_PART_ID 0x86 |
| 31 | 36 | #define LTR501_MANUFAC_ID 0x87 |
| 32 | 37 | #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ |
| 33 | 38 | #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ |
| 34 | 39 | #define LTR501_ALS_PS_STATUS 0x8c |
| 35 | 40 | #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ |
| 41 | +#define LTR501_INTR 0x8f /* output mode, polarity, mode */ | |
| 42 | +#define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */ | |
| 43 | +#define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */ | |
| 44 | +#define LTR501_ALS_THRESH_UP 0x97 /* 16 bit, ALS upper threshold */ | |
| 45 | +#define LTR501_ALS_THRESH_LOW 0x99 /* 16 bit, ALS lower threshold */ | |
| 46 | +#define LTR501_INTR_PRST 0x9e /* ps thresh, als thresh */ | |
| 47 | +#define LTR501_MAX_REG 0x9f | |
| 36 | 48 | |
| 37 | 49 | #define LTR501_ALS_CONTR_SW_RESET BIT(2) |
| 38 | 50 | #define LTR501_CONTR_PS_GAIN_MASK (BIT(3) | BIT(2)) |
| @@ -40,28 +52,288 @@ · 1 unmodified line | ||
| 40 | 52 | #define LTR501_CONTR_ALS_GAIN_MASK BIT(3) |
| 41 | 53 | #define LTR501_CONTR_ACTIVE BIT(1) |
| 42 | 54 | |
| 55 | +#define LTR501_STATUS_ALS_INTR BIT(3) | |
| 43 | 56 | #define LTR501_STATUS_ALS_RDY BIT(2) |
| 57 | +#define LTR501_STATUS_PS_INTR BIT(1) | |
| 44 | 58 | #define LTR501_STATUS_PS_RDY BIT(0) |
| 45 | 59 | |
| 46 | 60 | #define LTR501_PS_DATA_MASK 0x7ff |
| 61 | +#define LTR501_PS_THRESH_MASK 0x7ff | |
| 62 | +#define LTR501_ALS_THRESH_MASK 0xffff | |
| 63 | + | |
| 64 | +#define LTR501_ALS_DEF_PERIOD 500000 | |
| 65 | +#define LTR501_PS_DEF_PERIOD 100000 | |
| 66 | + | |
| 67 | +#define LTR501_REGMAP_NAME "ltr501_regmap" | |
| 68 | + | |
| 69 | +#define LTR501_LUX_CONV(vis_coeff, vis_data, ir_coeff, ir_data) \ | |
| 70 | + ((vis_coeff * vis_data) - (ir_coeff * ir_data)) | |
| 71 | + | |
| 72 | +static const int int_time_mapping[] = {100000, 50000, 200000, 400000}; | |
| 73 | + | |
| 74 | +static const struct reg_field reg_field_it = | |
| 75 | + REG_FIELD(LTR501_ALS_MEAS_RATE, 3, 4); | |
| 76 | +static const struct reg_field reg_field_als_intr = | |
| 77 | + REG_FIELD(LTR501_INTR, 0, 0); | |
| 78 | +static const struct reg_field reg_field_ps_intr = | |
| 79 | + REG_FIELD(LTR501_INTR, 1, 1); | |
| 80 | +static const struct reg_field reg_field_als_rate = | |
| 81 | + REG_FIELD(LTR501_ALS_MEAS_RATE, 0, 2); | |
| 82 | +static const struct reg_field reg_field_ps_rate = | |
| 83 | + REG_FIELD(LTR501_PS_MEAS_RATE, 0, 3); | |
| 84 | +static const struct reg_field reg_field_als_prst = | |
| 85 | + REG_FIELD(LTR501_INTR_PRST, 0, 3); | |
| 86 | +static const struct reg_field reg_field_ps_prst = | |
| 87 | + REG_FIELD(LTR501_INTR_PRST, 4, 7); | |
| 88 | + | |
| 89 | +struct ltr501_samp_table { | |
| 90 | + int freq_val; /* repetition frequency in micro HZ*/ | |
| 91 | + int time_val; /* repetition rate in micro seconds */ | |
| 92 | +}; | |
| 93 | + | |
| 94 | +#define LTR501_RESERVED_GAIN -1 | |
| 95 | + | |
| 96 | +enum { | |
| 97 | + ltr501 = 0, | |
| 98 | + ltr559, | |
| 99 | + ltr301, | |
| 100 | +}; | |
| 101 | + | |
| 102 | +struct ltr501_gain { | |
| 103 | + int scale; | |
| 104 | + int uscale; | |
| 105 | +}; | |
| 106 | + | |
| 107 | +static struct ltr501_gain ltr501_als_gain_tbl[] = { | |
| 108 | + {1, 0}, | |
| 109 | + {0, 5000}, | |
| 110 | +}; | |
| 111 | + | |
| 112 | +static struct ltr501_gain ltr559_als_gain_tbl[] = { | |
| 113 | + {1, 0}, | |
| 114 | + {0, 500000}, | |
| 115 | + {0, 250000}, | |
| 116 | + {0, 125000}, | |
| 117 | + {LTR501_RESERVED_GAIN, LTR501_RESERVED_GAIN}, | |
| 118 | + {LTR501_RESERVED_GAIN, LTR501_RESERVED_GAIN}, | |
| 119 | + {0, 20000}, | |
| 120 | + {0, 10000}, | |
| 121 | +}; | |
| 122 | + | |
| 123 | +static struct ltr501_gain ltr501_ps_gain_tbl[] = { | |
| 124 | + {1, 0}, | |
| 125 | + {0, 250000}, | |
| 126 | + {0, 125000}, | |
| 127 | + {0, 62500}, | |
| 128 | +}; | |
| 129 | + | |
| 130 | +static struct ltr501_gain ltr559_ps_gain_tbl[] = { | |
| 131 | + {0, 62500}, /* x16 gain */ | |
| 132 | + {0, 31250}, /* x32 gain */ | |
| 133 | + {0, 15625}, /* bits X1 are for x64 gain */ | |
| 134 | + {0, 15624}, | |
| 135 | +}; | |
| 136 | + | |
| 137 | +struct ltr501_chip_info { | |
| 138 | + u8 partid; | |
| 139 | + struct ltr501_gain *als_gain; | |
| 140 | + int als_gain_tbl_size; | |
| 141 | + struct ltr501_gain *ps_gain; | |
| 142 | + int ps_gain_tbl_size; | |
| 143 | + u8 als_mode_active; | |
| 144 | + u8 als_gain_mask; | |
| 145 | + u8 als_gain_shift; | |
| 146 | + struct iio_chan_spec const *channels; | |
| 147 | + const int no_channels; | |
| 148 | + const struct iio_info *info; | |
| 149 | + const struct iio_info *info_no_irq; | |
| 150 | +}; | |
| 47 | 151 | |
| 48 | 152 | struct ltr501_data { |
| 49 | 153 | struct i2c_client *client; |
| 50 | 154 | struct mutex lock_als, lock_ps; |
| 155 | + struct ltr501_chip_info *chip_info; | |
| 51 | 156 | u8 als_contr, ps_contr; |
| 157 | + int als_period, ps_period; /* period in micro seconds */ | |
| 158 | + struct regmap *regmap; | |
| 159 | + struct regmap_field *reg_it; | |
| 160 | + struct regmap_field *reg_als_intr; | |
| 161 | + struct regmap_field *reg_ps_intr; | |
| 162 | + struct regmap_field *reg_als_rate; | |
| 163 | + struct regmap_field *reg_ps_rate; | |
| 164 | + struct regmap_field *reg_als_prst; | |
| 165 | + struct regmap_field *reg_ps_prst; | |
| 166 | +}; | |
| 167 | + | |
| 168 | +static const struct ltr501_samp_table ltr501_als_samp_table[] = { | |
| 169 | + {20000000, 50000}, {10000000, 100000}, | |
| 170 | + {5000000, 200000}, {2000000, 500000}, | |
| 171 | + {1000000, 1000000}, {500000, 2000000}, | |
| 172 | + {500000, 2000000}, {500000, 2000000} | |
| 52 | 173 | }; |
| 53 | 174 | |
| 175 | +static const struct ltr501_samp_table ltr501_ps_samp_table[] = { | |
| 176 | + {20000000, 50000}, {14285714, 70000}, | |
| 177 | + {10000000, 100000}, {5000000, 200000}, | |
| 178 | + {2000000, 500000}, {1000000, 1000000}, | |
| 179 | + {500000, 2000000}, {500000, 2000000}, | |
| 180 | + {500000, 2000000} | |
| 181 | +}; | |
| 182 | + | |
| 183 | +static unsigned int ltr501_match_samp_freq(const struct ltr501_samp_table *tab, | |
| 184 | + int len, int val, int val2) | |
| 185 | +{ | |
| 186 | + int i, freq; | |
| 187 | + | |
| 188 | + freq = val * 1000000 + val2; | |
| 189 | + | |
| 190 | + for (i = 0; i < len; i++) { | |
| 191 | + if (tab[i].freq_val == freq) | |
| 192 | + return i; | |
| 193 | + } | |
| 194 | + | |
| 195 | + return -EINVAL; | |
| 196 | +} | |
| 197 | + | |
| 198 | +static int ltr501_als_read_samp_freq(struct ltr501_data *data, | |
| 199 | + int *val, int *val2) | |
| 200 | +{ | |
| 201 | + int ret, i; | |
| 202 | + | |
| 203 | + ret = regmap_field_read(data->reg_als_rate, &i); | |
| 204 | + if (ret < 0) | |
| 205 | + return ret; | |
| 206 | + | |
| 207 | + if (i < 0 || i >= ARRAY_SIZE(ltr501_als_samp_table)) | |
| 208 | + return -EINVAL; | |
| 209 | + | |
| 210 | + *val = ltr501_als_samp_table[i].freq_val / 1000000; | |
| 211 | + *val2 = ltr501_als_samp_table[i].freq_val % 1000000; | |
| 212 | + | |
| 213 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 214 | +} | |
| 215 | + | |
| 216 | +static int ltr501_ps_read_samp_freq(struct ltr501_data *data, | |
| 217 | + int *val, int *val2) | |
| 218 | +{ | |
| 219 | + int ret, i; | |
| 220 | + | |
| 221 | + ret = regmap_field_read(data->reg_ps_rate, &i); | |
| 222 | + if (ret < 0) | |
| 223 | + return ret; | |
| 224 | + | |
| 225 | + if (i < 0 || i >= ARRAY_SIZE(ltr501_ps_samp_table)) | |
| 226 | + return -EINVAL; | |
| 227 | + | |
| 228 | + *val = ltr501_ps_samp_table[i].freq_val / 1000000; | |
| 229 | + *val2 = ltr501_ps_samp_table[i].freq_val % 1000000; | |
| 230 | + | |
| 231 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 232 | +} | |
| 233 | + | |
| 234 | +static int ltr501_als_write_samp_freq(struct ltr501_data *data, | |
| 235 | + int val, int val2) | |
| 236 | +{ | |
| 237 | + int i, ret; | |
| 238 | + | |
| 239 | + i = ltr501_match_samp_freq(ltr501_als_samp_table, | |
| 240 | + ARRAY_SIZE(ltr501_als_samp_table), | |
| 241 | + val, val2); | |
| 242 | + | |
| 243 | + if (i < 0) | |
| 244 | + return i; | |
| 245 | + | |
| 246 | + mutex_lock(&data->lock_als); | |
| 247 | + ret = regmap_field_write(data->reg_als_rate, i); | |
| 248 | + mutex_unlock(&data->lock_als); | |
| 249 | + | |
| 250 | + return ret; | |
| 251 | +} | |
| 252 | + | |
| 253 | +static int ltr501_ps_write_samp_freq(struct ltr501_data *data, | |
| 254 | + int val, int val2) | |
| 255 | +{ | |
| 256 | + int i, ret; | |
| 257 | + | |
| 258 | + i = ltr501_match_samp_freq(ltr501_ps_samp_table, | |
| 259 | + ARRAY_SIZE(ltr501_ps_samp_table), | |
| 260 | + val, val2); | |
| 261 | + | |
| 262 | + if (i < 0) | |
| 263 | + return i; | |
| 264 | + | |
| 265 | + mutex_lock(&data->lock_ps); | |
| 266 | + ret = regmap_field_write(data->reg_ps_rate, i); | |
| 267 | + mutex_unlock(&data->lock_ps); | |
| 268 | + | |
| 269 | + return ret; | |
| 270 | +} | |
| 271 | + | |
| 272 | +static int ltr501_als_read_samp_period(struct ltr501_data *data, int *val) | |
| 273 | +{ | |
| 274 | + int ret, i; | |
| 275 | + | |
| 276 | + ret = regmap_field_read(data->reg_als_rate, &i); | |
| 277 | + if (ret < 0) | |
| 278 | + return ret; | |
| 279 | + | |
| 280 | + if (i < 0 || i >= ARRAY_SIZE(ltr501_als_samp_table)) | |
| 281 | + return -EINVAL; | |
| 282 | + | |
| 283 | + *val = ltr501_als_samp_table[i].time_val; | |
| 284 | + | |
| 285 | + return IIO_VAL_INT; | |
| 286 | +} | |
| 287 | + | |
| 288 | +static int ltr501_ps_read_samp_period(struct ltr501_data *data, int *val) | |
| 289 | +{ | |
| 290 | + int ret, i; | |
| 291 | + | |
| 292 | + ret = regmap_field_read(data->reg_ps_rate, &i); | |
| 293 | + if (ret < 0) | |
| 294 | + return ret; | |
| 295 | + | |
| 296 | + if (i < 0 || i >= ARRAY_SIZE(ltr501_ps_samp_table)) | |
| 297 | + return -EINVAL; | |
| 298 | + | |
| 299 | + *val = ltr501_ps_samp_table[i].time_val; | |
| 300 | + | |
| 301 | + return IIO_VAL_INT; | |
| 302 | +} | |
| 303 | + | |
| 304 | +/* IR and visible spectrum coeff's are given in data sheet */ | |
| 305 | +static unsigned long ltr501_calculate_lux(u16 vis_data, u16 ir_data) | |
| 306 | +{ | |
| 307 | + unsigned long ratio, lux; | |
| 308 | + | |
| 309 | + if (vis_data == 0) | |
| 310 | + return 0; | |
| 311 | + | |
| 312 | + /* multiply numerator by 100 to avoid handling ratio < 1 */ | |
| 313 | + ratio = DIV_ROUND_UP(ir_data * 100, ir_data + vis_data); | |
| 314 | + | |
| 315 | + if (ratio < 45) | |
| 316 | + lux = LTR501_LUX_CONV(1774, vis_data, -1105, ir_data); | |
| 317 | + else if (ratio >= 45 && ratio < 64) | |
| 318 | + lux = LTR501_LUX_CONV(3772, vis_data, 1336, ir_data); | |
| 319 | + else if (ratio >= 64 && ratio < 85) | |
| 320 | + lux = LTR501_LUX_CONV(1690, vis_data, 169, ir_data); | |
| 321 | + else | |
| 322 | + lux = 0; | |
| 323 | + | |
| 324 | + return lux / 1000; | |
| 325 | +} | |
| 326 | + | |
| 54 | 327 | static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) |
| 55 | 328 | { |
| 56 | 329 | int tries = 100; |
| 57 | − int ret; | |
| 330 | + int ret, status; | |
| 58 | 331 | |
| 59 | 332 | while (tries--) { |
| 60 | − ret = i2c_smbus_read_byte_data(data->client, | |
| 61 | − LTR501_ALS_PS_STATUS); | |
| 333 | + ret = regmap_read(data->regmap, LTR501_ALS_PS_STATUS, &status); | |
| 62 | 334 | if (ret < 0) |
| 63 | 335 | return ret; |
| 64 | − if ((ret & drdy_mask) == drdy_mask) | |
| 336 | + if ((status & drdy_mask) == drdy_mask) | |
| 65 | 337 | return 0; |
| 66 | 338 | msleep(25); |
| 67 | 339 | } |
| @@ -70,25 +342,221 @@ static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) · 2 unmodified lines | ||
| 70 | 342 | return -EIO; |
| 71 | 343 | } |
| 72 | 344 | |
| 345 | +static int ltr501_set_it_time(struct ltr501_data *data, int it) | |
| 346 | +{ | |
| 347 | + int ret, i, index = -1, status; | |
| 348 | + | |
| 349 | + for (i = 0; i < ARRAY_SIZE(int_time_mapping); i++) { | |
| 350 | + if (int_time_mapping[i] == it) { | |
| 351 | + index = i; | |
| 352 | + break; | |
| 353 | + } | |
| 354 | + } | |
| 355 | + /* Make sure integ time index is valid */ | |
| 356 | + if (index < 0) | |
| 357 | + return -EINVAL; | |
| 358 | + | |
| 359 | + ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status); | |
| 360 | + if (ret < 0) | |
| 361 | + return ret; | |
| 362 | + | |
| 363 | + if (status & LTR501_CONTR_ALS_GAIN_MASK) { | |
| 364 | + /* | |
| 365 | + * 200 ms and 400 ms integ time can only be | |
| 366 | + * used in dynamic range 1 | |
| 367 | + */ | |
| 368 | + if (index > 1) | |
| 369 | + return -EINVAL; | |
| 370 | + } else | |
| 371 | + /* 50 ms integ time can only be used in dynamic range 2 */ | |
| 372 | + if (index == 1) | |
| 373 | + return -EINVAL; | |
| 374 | + | |
| 375 | + return regmap_field_write(data->reg_it, index); | |
| 376 | +} | |
| 377 | + | |
| 378 | +/* read int time in micro seconds */ | |
| 379 | +static int ltr501_read_it_time(struct ltr501_data *data, int *val, int *val2) | |
| 380 | +{ | |
| 381 | + int ret, index; | |
| 382 | + | |
| 383 | + ret = regmap_field_read(data->reg_it, &index); | |
| 384 | + if (ret < 0) | |
| 385 | + return ret; | |
| 386 | + | |
| 387 | + /* Make sure integ time index is valid */ | |
| 388 | + if (index < 0 || index >= ARRAY_SIZE(int_time_mapping)) | |
| 389 | + return -EINVAL; | |
| 390 | + | |
| 391 | + *val2 = int_time_mapping[index]; | |
| 392 | + *val = 0; | |
| 393 | + | |
| 394 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 395 | +} | |
| 396 | + | |
| 73 | 397 | static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) |
| 74 | 398 | { |
| 75 | − int ret = ltr501_drdy(data, LTR501_STATUS_ALS_RDY); | |
| 399 | + int ret; | |
| 400 | + | |
| 401 | + ret = ltr501_drdy(data, LTR501_STATUS_ALS_RDY); | |
| 76 | 402 | if (ret < 0) |
| 77 | 403 | return ret; |
| 78 | 404 | /* always read both ALS channels in given order */ |
| 79 | − return i2c_smbus_read_i2c_block_data(data->client, | |
| 80 | − LTR501_ALS_DATA1, 2 * sizeof(__le16), (u8 *) buf); | |
| 405 | + return regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, | |
| 406 | + buf, 2 * sizeof(__le16)); | |
| 81 | 407 | } |
| 82 | 408 | |
| 83 | 409 | static int ltr501_read_ps(struct ltr501_data *data) |
| 84 | 410 | { |
| 85 | − int ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); | |
| 411 | + int ret, status; | |
| 412 | + | |
| 413 | + ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); | |
| 86 | 414 | if (ret < 0) |
| 87 | 415 | return ret; |
| 88 | − return i2c_smbus_read_word_data(data->client, LTR501_PS_DATA); | |
| 416 | + | |
| 417 | + ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, | |
| 418 | + &status, 2); | |
| 419 | + if (ret < 0) | |
| 420 | + return ret; | |
| 421 | + | |
| 422 | + return status; | |
| 423 | +} | |
| 424 | + | |
| 425 | +static int ltr501_read_intr_prst(struct ltr501_data *data, | |
| 426 | + enum iio_chan_type type, | |
| 427 | + int *val2) | |
| 428 | +{ | |
| 429 | + int ret, samp_period, prst; | |
| 430 | + | |
| 431 | + switch (type) { | |
| 432 | + case IIO_INTENSITY: | |
| 433 | + ret = regmap_field_read(data->reg_als_prst, &prst); | |
| 434 | + if (ret < 0) | |
| 435 | + return ret; | |
| 436 | + | |
| 437 | + ret = ltr501_als_read_samp_period(data, &samp_period); | |
| 438 | + | |
| 439 | + if (ret < 0) | |
| 440 | + return ret; | |
| 441 | + *val2 = samp_period * prst; | |
| 442 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 443 | + case IIO_PROXIMITY: | |
| 444 | + ret = regmap_field_read(data->reg_ps_prst, &prst); | |
| 445 | + if (ret < 0) | |
| 446 | + return ret; | |
| 447 | + | |
| 448 | + ret = ltr501_ps_read_samp_period(data, &samp_period); | |
| 449 | + | |
| 450 | + if (ret < 0) | |
| 451 | + return ret; | |
| 452 | + | |
| 453 | + *val2 = samp_period * prst; | |
| 454 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 455 | + default: | |
| 456 | + return -EINVAL; | |
| 457 | + } | |
| 458 | + | |
| 459 | + return -EINVAL; | |
| 89 | 460 | } |
| 90 | 461 | |
| 91 | −#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared) { \ | |
| 462 | +static int ltr501_write_intr_prst(struct ltr501_data *data, | |
| 463 | + enum iio_chan_type type, | |
| 464 | + int val, int val2) | |
| 465 | +{ | |
| 466 | + int ret, samp_period, new_val; | |
| 467 | + unsigned long period; | |
| 468 | + | |
| 469 | + if (val < 0 || val2 < 0) | |
| 470 | + return -EINVAL; | |
| 471 | + | |
| 472 | + /* period in microseconds */ | |
| 473 | + period = ((val * 1000000) + val2); | |
| 474 | + | |
| 475 | + switch (type) { | |
| 476 | + case IIO_INTENSITY: | |
| 477 | + ret = ltr501_als_read_samp_period(data, &samp_period); | |
| 478 | + if (ret < 0) | |
| 479 | + return ret; | |
| 480 | + | |
| 481 | + /* period should be atleast equal to sampling period */ | |
| 482 | + if (period < samp_period) | |
| 483 | + return -EINVAL; | |
| 484 | + | |
| 485 | + new_val = DIV_ROUND_UP(period, samp_period); | |
| 486 | + if (new_val < 0 || new_val > 0x0f) | |
| 487 | + return -EINVAL; | |
| 488 | + | |
| 489 | + mutex_lock(&data->lock_als); | |
| 490 | + ret = regmap_field_write(data->reg_als_prst, new_val); | |
| 491 | + mutex_unlock(&data->lock_als); | |
| 492 | + if (ret >= 0) | |
| 493 | + data->als_period = period; | |
| 494 | + | |
| 495 | + return ret; | |
| 496 | + case IIO_PROXIMITY: | |
| 497 | + ret = ltr501_ps_read_samp_period(data, &samp_period); | |
| 498 | + if (ret < 0) | |
| 499 | + return ret; | |
| 500 | + | |
| 501 | + /* period should be atleast equal to rate */ | |
| 502 | + if (period < samp_period) | |
| 503 | + return -EINVAL; | |
| 504 | + | |
| 505 | + new_val = DIV_ROUND_UP(period, samp_period); | |
| 506 | + if (new_val < 0 || new_val > 0x0f) | |
| 507 | + return -EINVAL; | |
| 508 | + | |
| 509 | + mutex_lock(&data->lock_ps); | |
| 510 | + ret = regmap_field_write(data->reg_ps_prst, new_val); | |
| 511 | + mutex_unlock(&data->lock_ps); | |
| 512 | + if (ret >= 0) | |
| 513 | + data->ps_period = period; | |
| 514 | + | |
| 515 | + return ret; | |
| 516 | + default: | |
| 517 | + return -EINVAL; | |
| 518 | + } | |
| 519 | + | |
| 520 | + return -EINVAL; | |
| 521 | +} | |
| 522 | + | |
| 523 | +static const struct iio_event_spec ltr501_als_event_spec[] = { | |
| 524 | + { | |
| 525 | + .type = IIO_EV_TYPE_THRESH, | |
| 526 | + .dir = IIO_EV_DIR_RISING, | |
| 527 | + .mask_separate = BIT(IIO_EV_INFO_VALUE), | |
| 528 | + }, { | |
| 529 | + .type = IIO_EV_TYPE_THRESH, | |
| 530 | + .dir = IIO_EV_DIR_FALLING, | |
| 531 | + .mask_separate = BIT(IIO_EV_INFO_VALUE), | |
| 532 | + }, { | |
| 533 | + .type = IIO_EV_TYPE_THRESH, | |
| 534 | + .dir = IIO_EV_DIR_EITHER, | |
| 535 | + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | | |
| 536 | + BIT(IIO_EV_INFO_PERIOD), | |
| 537 | + }, | |
| 538 | + | |
| 539 | +}; | |
| 540 | + | |
| 541 | +static const struct iio_event_spec ltr501_pxs_event_spec[] = { | |
| 542 | + { | |
| 543 | + .type = IIO_EV_TYPE_THRESH, | |
| 544 | + .dir = IIO_EV_DIR_RISING, | |
| 545 | + .mask_separate = BIT(IIO_EV_INFO_VALUE), | |
| 546 | + }, { | |
| 547 | + .type = IIO_EV_TYPE_THRESH, | |
| 548 | + .dir = IIO_EV_DIR_FALLING, | |
| 549 | + .mask_separate = BIT(IIO_EV_INFO_VALUE), | |
| 550 | + }, { | |
| 551 | + .type = IIO_EV_TYPE_THRESH, | |
| 552 | + .dir = IIO_EV_DIR_EITHER, | |
| 553 | + .mask_separate = BIT(IIO_EV_INFO_ENABLE) | | |
| 554 | + BIT(IIO_EV_INFO_PERIOD), | |
| 555 | + }, | |
| 556 | +}; | |
| 557 | + | |
| 558 | +#define LTR501_INTENSITY_CHANNEL(_idx, _addr, _mod, _shared, \ | |
| 559 | + _evspec, _evsize) { \ | |
| 92 | 560 | .type = IIO_INTENSITY, \ |
| 93 | 561 | .modified = 1, \ |
| 94 | 562 | .address = (_addr), \ |
| @@ -101,13 +569,27 @@ static int ltr501_read_ps(struct ltr501_data *data) · 6 unmodified lines | ||
| 101 | 569 | .realbits = 16, \ |
| 102 | 570 | .storagebits = 16, \ |
| 103 | 571 | .endianness = IIO_CPU, \ |
| 104 | − } \ | |
| 572 | + }, \ | |
| 573 | + .event_spec = _evspec,\ | |
| 574 | + .num_event_specs = _evsize,\ | |
| 575 | +} | |
| 576 | + | |
| 577 | +#define LTR501_LIGHT_CHANNEL() { \ | |
| 578 | + .type = IIO_LIGHT, \ | |
| 579 | + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \ | |
| 580 | + .scan_index = -1, \ | |
| 105 | 581 | } |
| 106 | 582 | |
| 107 | 583 | static const struct iio_chan_spec ltr501_channels[] = { |
| 108 | − LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0), | |
| 584 | + LTR501_LIGHT_CHANNEL(), | |
| 585 | + LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0, | |
| 586 | + ltr501_als_event_spec, | |
| 587 | + ARRAY_SIZE(ltr501_als_event_spec)), | |
| 109 | 588 | LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, |
| 110 | − BIT(IIO_CHAN_INFO_SCALE)), | |
| 589 | + BIT(IIO_CHAN_INFO_SCALE) | | |
| 590 | + BIT(IIO_CHAN_INFO_INT_TIME) | | |
| 591 | + BIT(IIO_CHAN_INFO_SAMP_FREQ), | |
| 592 | + NULL, 0), | |
| 111 | 593 | { |
| 112 | 594 | .type = IIO_PROXIMITY, |
| 113 | 595 | .address = LTR501_PS_DATA, |
| @@ -120,23 +602,51 @@ static const struct iio_chan_spec ltr501_channels[] = { · 6 unmodified lines | ||
| 120 | 602 | .storagebits = 16, |
| 121 | 603 | .endianness = IIO_CPU, |
| 122 | 604 | }, |
| 605 | + .event_spec = ltr501_pxs_event_spec, | |
| 606 | + .num_event_specs = ARRAY_SIZE(ltr501_pxs_event_spec), | |
| 123 | 607 | }, |
| 124 | 608 | IIO_CHAN_SOFT_TIMESTAMP(3), |
| 125 | 609 | }; |
| 126 | 610 | |
| 127 | −static const int ltr501_ps_gain[4][2] = { | |
| 128 | − {1, 0}, {0, 250000}, {0, 125000}, {0, 62500} | |
| 611 | +static const struct iio_chan_spec ltr301_channels[] = { | |
| 612 | + LTR501_LIGHT_CHANNEL(), | |
| 613 | + LTR501_INTENSITY_CHANNEL(0, LTR501_ALS_DATA0, IIO_MOD_LIGHT_BOTH, 0, | |
| 614 | + ltr501_als_event_spec, | |
| 615 | + ARRAY_SIZE(ltr501_als_event_spec)), | |
| 616 | + LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, | |
| 617 | + BIT(IIO_CHAN_INFO_SCALE) | | |
| 618 | + BIT(IIO_CHAN_INFO_INT_TIME) | | |
| 619 | + BIT(IIO_CHAN_INFO_SAMP_FREQ), | |
| 620 | + NULL, 0), | |
| 621 | + IIO_CHAN_SOFT_TIMESTAMP(2), | |
| 129 | 622 | }; |
| 130 | 623 | |
| 131 | 624 | static int ltr501_read_raw(struct iio_dev *indio_dev, |
| 132 | − struct iio_chan_spec const *chan, | |
| 133 | − int *val, int *val2, long mask) | |
| 625 | + struct iio_chan_spec const *chan, | |
| 626 | + int *val, int *val2, long mask) | |
| 134 | 627 | { |
| 135 | 628 | struct ltr501_data *data = iio_priv(indio_dev); |
| 136 | 629 | __le16 buf[2]; |
| 137 | 630 | int ret, i; |
| 138 | 631 | |
| 139 | 632 | switch (mask) { |
| 633 | + case IIO_CHAN_INFO_PROCESSED: | |
| 634 | + if (iio_buffer_enabled(indio_dev)) | |
| 635 | + return -EBUSY; | |
| 636 | + | |
| 637 | + switch (chan->type) { | |
| 638 | + case IIO_LIGHT: | |
| 639 | + mutex_lock(&data->lock_als); | |
| 640 | + ret = ltr501_read_als(data, buf); | |
| 641 | + mutex_unlock(&data->lock_als); | |
| 642 | + if (ret < 0) | |
| 643 | + return ret; | |
| 644 | + *val = ltr501_calculate_lux(le16_to_cpu(buf[1]), | |
| 645 | + le16_to_cpu(buf[0])); | |
| 646 | + return IIO_VAL_INT; | |
| 647 | + default: | |
| 648 | + return -EINVAL; | |
| 649 | + } | |
| 140 | 650 | case IIO_CHAN_INFO_RAW: |
| 141 | 651 | if (iio_buffer_enabled(indio_dev)) |
| 142 | 652 | return -EBUSY; |
| @@ -149,7 +659,7 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, · 6 unmodified lines | ||
| 149 | 659 | if (ret < 0) |
| 150 | 660 | return ret; |
| 151 | 661 | *val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ? |
| 152 | − buf[0] : buf[1]); | |
| 662 | + buf[0] : buf[1]); | |
| 153 | 663 | return IIO_VAL_INT; |
| 154 | 664 | case IIO_PROXIMITY: |
| 155 | 665 | mutex_lock(&data->lock_ps); |
| @@ -165,45 +675,59 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, · 9 unmodified lines | ||
| 165 | 675 | case IIO_CHAN_INFO_SCALE: |
| 166 | 676 | switch (chan->type) { |
| 167 | 677 | case IIO_INTENSITY: |
| 168 | − if (data->als_contr & LTR501_CONTR_ALS_GAIN_MASK) { | |
| 169 | − *val = 0; | |
| 170 | − *val2 = 5000; | |
| 171 | − return IIO_VAL_INT_PLUS_MICRO; | |
| 172 | − } else { | |
| 173 | − *val = 1; | |
| 174 | − *val2 = 0; | |
| 175 | − return IIO_VAL_INT; | |
| 176 | − } | |
| 678 | + i = (data->als_contr & data->chip_info->als_gain_mask) | |
| 679 | + >> data->chip_info->als_gain_shift; | |
| 680 | + *val = data->chip_info->als_gain[i].scale; | |
| 681 | + *val2 = data->chip_info->als_gain[i].uscale; | |
| 682 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 177 | 683 | case IIO_PROXIMITY: |
| 178 | 684 | i = (data->ps_contr & LTR501_CONTR_PS_GAIN_MASK) >> |
| 179 | 685 | LTR501_CONTR_PS_GAIN_SHIFT; |
| 180 | − *val = ltr501_ps_gain[i][0]; | |
| 181 | − *val2 = ltr501_ps_gain[i][1]; | |
| 686 | + *val = data->chip_info->ps_gain[i].scale; | |
| 687 | + *val2 = data->chip_info->ps_gain[i].uscale; | |
| 182 | 688 | return IIO_VAL_INT_PLUS_MICRO; |
| 183 | 689 | default: |
| 184 | 690 | return -EINVAL; |
| 185 | 691 | } |
| 692 | + case IIO_CHAN_INFO_INT_TIME: | |
| 693 | + switch (chan->type) { | |
| 694 | + case IIO_INTENSITY: | |
| 695 | + return ltr501_read_it_time(data, val, val2); | |
| 696 | + default: | |
| 697 | + return -EINVAL; | |
| 698 | + } | |
| 699 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 700 | + switch (chan->type) { | |
| 701 | + case IIO_INTENSITY: | |
| 702 | + return ltr501_als_read_samp_freq(data, val, val2); | |
| 703 | + case IIO_PROXIMITY: | |
| 704 | + return ltr501_ps_read_samp_freq(data, val, val2); | |
| 705 | + default: | |
| 706 | + return -EINVAL; | |
| 707 | + } | |
| 186 | 708 | } |
| 187 | 709 | return -EINVAL; |
| 188 | 710 | } |
| 189 | 711 | |
| 190 | −static int ltr501_get_ps_gain_index(int val, int val2) | |
| 712 | +static int ltr501_get_gain_index(struct ltr501_gain *gain, int size, | |
| 713 | + int val, int val2) | |
| 191 | 714 | { |
| 192 | 715 | int i; |
| 193 | 716 | |
| 194 | − for (i = 0; i < ARRAY_SIZE(ltr501_ps_gain); i++) | |
| 195 | − if (val == ltr501_ps_gain[i][0] && val2 == ltr501_ps_gain[i][1]) | |
| 717 | + for (i = 0; i < size; i++) | |
| 718 | + if (val == gain[i].scale && val2 == gain[i].uscale) | |
| 196 | 719 | return i; |
| 197 | 720 | |
| 198 | 721 | return -1; |
| 199 | 722 | } |
| 200 | 723 | |
| 201 | 724 | static int ltr501_write_raw(struct iio_dev *indio_dev, |
| 202 | − struct iio_chan_spec const *chan, | |
| 203 | − int val, int val2, long mask) | |
| 725 | + struct iio_chan_spec const *chan, | |
| 726 | + int val, int val2, long mask) | |
| 204 | 727 | { |
| 205 | 728 | struct ltr501_data *data = iio_priv(indio_dev); |
| 206 | − int i; | |
| 729 | + int i, ret, freq_val, freq_val2; | |
| 730 | + struct ltr501_chip_info *info = data->chip_info; | |
| 207 | 731 | |
| 208 | 732 | if (iio_buffer_enabled(indio_dev)) |
| 209 | 733 | return -EBUSY; |
| @@ -212,35 +736,382 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, · 2 unmodified lines | ||
| 212 | 736 | case IIO_CHAN_INFO_SCALE: |
| 213 | 737 | switch (chan->type) { |
| 214 | 738 | case IIO_INTENSITY: |
| 215 | − if (val == 0 && val2 == 5000) | |
| 216 | − data->als_contr |= LTR501_CONTR_ALS_GAIN_MASK; | |
| 217 | − else if (val == 1 && val2 == 0) | |
| 218 | − data->als_contr &= ~LTR501_CONTR_ALS_GAIN_MASK; | |
| 219 | − else | |
| 739 | + i = ltr501_get_gain_index(info->als_gain, | |
| 740 | + info->als_gain_tbl_size, | |
| 741 | + val, val2); | |
| 742 | + if (i < 0) | |
| 220 | 743 | return -EINVAL; |
| 221 | − return i2c_smbus_write_byte_data(data->client, | |
| 222 | − LTR501_ALS_CONTR, data->als_contr); | |
| 744 | + | |
| 745 | + data->als_contr &= ~info->als_gain_mask; | |
| 746 | + data->als_contr |= i << info->als_gain_shift; | |
| 747 | + | |
| 748 | + return regmap_write(data->regmap, LTR501_ALS_CONTR, | |
| 749 | + data->als_contr); | |
| 223 | 750 | case IIO_PROXIMITY: |
| 224 | − i = ltr501_get_ps_gain_index(val, val2); | |
| 751 | + i = ltr501_get_gain_index(info->ps_gain, | |
| 752 | + info->ps_gain_tbl_size, | |
| 753 | + val, val2); | |
| 225 | 754 | if (i < 0) |
| 226 | 755 | return -EINVAL; |
| 227 | 756 | data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; |
| 228 | 757 | data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; |
| 229 | − return i2c_smbus_write_byte_data(data->client, | |
| 230 | − LTR501_PS_CONTR, data->ps_contr); | |
| 758 | + | |
| 759 | + return regmap_write(data->regmap, LTR501_PS_CONTR, | |
| 760 | + data->ps_contr); | |
| 231 | 761 | default: |
| 232 | 762 | return -EINVAL; |
| 233 | 763 | } |
| 764 | + case IIO_CHAN_INFO_INT_TIME: | |
| 765 | + switch (chan->type) { | |
| 766 | + case IIO_INTENSITY: | |
| 767 | + if (val != 0) | |
| 768 | + return -EINVAL; | |
| 769 | + mutex_lock(&data->lock_als); | |
| 770 | + i = ltr501_set_it_time(data, val2); | |
| 771 | + mutex_unlock(&data->lock_als); | |
| 772 | + return i; | |
| 773 | + default: | |
| 774 | + return -EINVAL; | |
| 775 | + } | |
| 776 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 777 | + switch (chan->type) { | |
| 778 | + case IIO_INTENSITY: | |
| 779 | + ret = ltr501_als_read_samp_freq(data, &freq_val, | |
| 780 | + &freq_val2); | |
| 781 | + if (ret < 0) | |
| 782 | + return ret; | |
| 783 | + | |
| 784 | + ret = ltr501_als_write_samp_freq(data, val, val2); | |
| 785 | + if (ret < 0) | |
| 786 | + return ret; | |
| 787 | + | |
| 788 | + /* update persistence count when changing frequency */ | |
| 789 | + ret = ltr501_write_intr_prst(data, chan->type, | |
| 790 | + 0, data->als_period); | |
| 791 | + | |
| 792 | + if (ret < 0) | |
| 793 | + return ltr501_als_write_samp_freq(data, | |
| 794 | + freq_val, | |
| 795 | + freq_val2); | |
| 796 | + return ret; | |
| 797 | + case IIO_PROXIMITY: | |
| 798 | + ret = ltr501_ps_read_samp_freq(data, &freq_val, | |
| 799 | + &freq_val2); | |
| 800 | + if (ret < 0) | |
| 801 | + return ret; | |
| 802 | + | |
| 803 | + ret = ltr501_ps_write_samp_freq(data, val, val2); | |
| 804 | + if (ret < 0) | |
| 805 | + return ret; | |
| 806 | + | |
| 807 | + /* update persistence count when changing frequency */ | |
| 808 | + ret = ltr501_write_intr_prst(data, chan->type, | |
| 809 | + 0, data->ps_period); | |
| 810 | + | |
| 811 | + if (ret < 0) | |
| 812 | + return ltr501_ps_write_samp_freq(data, | |
| 813 | + freq_val, | |
| 814 | + freq_val2); | |
| 815 | + return ret; | |
| 816 | + default: | |
| 817 | + return -EINVAL; | |
| 818 | + } | |
| 819 | + } | |
| 820 | + return -EINVAL; | |
| 821 | +} | |
| 822 | + | |
| 823 | +static int ltr501_read_thresh(struct iio_dev *indio_dev, | |
| 824 | + const struct iio_chan_spec *chan, | |
| 825 | + enum iio_event_type type, | |
| 826 | + enum iio_event_direction dir, | |
| 827 | + enum iio_event_info info, | |
| 828 | + int *val, int *val2) | |
| 829 | +{ | |
| 830 | + struct ltr501_data *data = iio_priv(indio_dev); | |
| 831 | + int ret, thresh_data; | |
| 832 | + | |
| 833 | + switch (chan->type) { | |
| 834 | + case IIO_INTENSITY: | |
| 835 | + switch (dir) { | |
| 836 | + case IIO_EV_DIR_RISING: | |
| 837 | + ret = regmap_bulk_read(data->regmap, | |
| 838 | + LTR501_ALS_THRESH_UP, | |
| 839 | + &thresh_data, 2); | |
| 840 | + if (ret < 0) | |
| 841 | + return ret; | |
| 842 | + *val = thresh_data & LTR501_ALS_THRESH_MASK; | |
| 843 | + return IIO_VAL_INT; | |
| 844 | + case IIO_EV_DIR_FALLING: | |
| 845 | + ret = regmap_bulk_read(data->regmap, | |
| 846 | + LTR501_ALS_THRESH_LOW, | |
| 847 | + &thresh_data, 2); | |
| 848 | + if (ret < 0) | |
| 849 | + return ret; | |
| 850 | + *val = thresh_data & LTR501_ALS_THRESH_MASK; | |
| 851 | + return IIO_VAL_INT; | |
| 852 | + default: | |
| 853 | + return -EINVAL; | |
| 854 | + } | |
| 855 | + case IIO_PROXIMITY: | |
| 856 | + switch (dir) { | |
| 857 | + case IIO_EV_DIR_RISING: | |
| 858 | + ret = regmap_bulk_read(data->regmap, | |
| 859 | + LTR501_PS_THRESH_UP, | |
| 860 | + &thresh_data, 2); | |
| 861 | + if (ret < 0) | |
| 862 | + return ret; | |
| 863 | + *val = thresh_data & LTR501_PS_THRESH_MASK; | |
| 864 | + return IIO_VAL_INT; | |
| 865 | + case IIO_EV_DIR_FALLING: | |
| 866 | + ret = regmap_bulk_read(data->regmap, | |
| 867 | + LTR501_PS_THRESH_LOW, | |
| 868 | + &thresh_data, 2); | |
| 869 | + if (ret < 0) | |
| 870 | + return ret; | |
| 871 | + *val = thresh_data & LTR501_PS_THRESH_MASK; | |
| 872 | + return IIO_VAL_INT; | |
| 873 | + default: | |
| 874 | + return -EINVAL; | |
| 875 | + } | |
| 876 | + default: | |
| 877 | + return -EINVAL; | |
| 234 | 878 | } |
| 879 | + | |
| 235 | 880 | return -EINVAL; |
| 236 | 881 | } |
| 237 | 882 | |
| 238 | −static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); | |
| 239 | −static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); | |
| 883 | +static int ltr501_write_thresh(struct iio_dev *indio_dev, | |
| 884 | + const struct iio_chan_spec *chan, | |
| 885 | + enum iio_event_type type, | |
| 886 | + enum iio_event_direction dir, | |
| 887 | + enum iio_event_info info, | |
| 888 | + int val, int val2) | |
| 889 | +{ | |
| 890 | + struct ltr501_data *data = iio_priv(indio_dev); | |
| 891 | + int ret; | |
| 892 | + | |
| 893 | + if (val < 0) | |
| 894 | + return -EINVAL; | |
| 895 | + | |
| 896 | + switch (chan->type) { | |
| 897 | + case IIO_INTENSITY: | |
| 898 | + if (val > LTR501_ALS_THRESH_MASK) | |
| 899 | + return -EINVAL; | |
| 900 | + switch (dir) { | |
| 901 | + case IIO_EV_DIR_RISING: | |
| 902 | + mutex_lock(&data->lock_als); | |
| 903 | + ret = regmap_bulk_write(data->regmap, | |
| 904 | + LTR501_ALS_THRESH_UP, | |
| 905 | + &val, 2); | |
| 906 | + mutex_unlock(&data->lock_als); | |
| 907 | + return ret; | |
| 908 | + case IIO_EV_DIR_FALLING: | |
| 909 | + mutex_lock(&data->lock_als); | |
| 910 | + ret = regmap_bulk_write(data->regmap, | |
| 911 | + LTR501_ALS_THRESH_LOW, | |
| 912 | + &val, 2); | |
| 913 | + mutex_unlock(&data->lock_als); | |
| 914 | + return ret; | |
| 915 | + default: | |
| 916 | + return -EINVAL; | |
| 917 | + } | |
| 918 | + case IIO_PROXIMITY: | |
| 919 | + if (val > LTR501_PS_THRESH_MASK) | |
| 920 | + return -EINVAL; | |
| 921 | + switch (dir) { | |
| 922 | + case IIO_EV_DIR_RISING: | |
| 923 | + mutex_lock(&data->lock_ps); | |
| 924 | + ret = regmap_bulk_write(data->regmap, | |
| 925 | + LTR501_PS_THRESH_UP, | |
| 926 | + &val, 2); | |
| 927 | + mutex_unlock(&data->lock_ps); | |
| 928 | + return ret; | |
| 929 | + case IIO_EV_DIR_FALLING: | |
| 930 | + mutex_lock(&data->lock_ps); | |
| 931 | + ret = regmap_bulk_write(data->regmap, | |
| 932 | + LTR501_PS_THRESH_LOW, | |
| 933 | + &val, 2); | |
| 934 | + mutex_unlock(&data->lock_ps); | |
| 935 | + return ret; | |
| 936 | + default: | |
| 937 | + return -EINVAL; | |
| 938 | + } | |
| 939 | + default: | |
| 940 | + return -EINVAL; | |
| 941 | + } | |
| 942 | + | |
| 943 | + return -EINVAL; | |
| 944 | +} | |
| 945 | + | |
| 946 | +static int ltr501_read_event(struct iio_dev *indio_dev, | |
| 947 | + const struct iio_chan_spec *chan, | |
| 948 | + enum iio_event_type type, | |
| 949 | + enum iio_event_direction dir, | |
| 950 | + enum iio_event_info info, | |
| 951 | + int *val, int *val2) | |
| 952 | +{ | |
| 953 | + int ret; | |
| 954 | + | |
| 955 | + switch (info) { | |
| 956 | + case IIO_EV_INFO_VALUE: | |
| 957 | + return ltr501_read_thresh(indio_dev, chan, type, dir, | |
| 958 | + info, val, val2); | |
| 959 | + case IIO_EV_INFO_PERIOD: | |
| 960 | + ret = ltr501_read_intr_prst(iio_priv(indio_dev), | |
| 961 | + chan->type, val2); | |
| 962 | + *val = *val2 / 1000000; | |
| 963 | + *val2 = *val2 % 1000000; | |
| 964 | + return ret; | |
| 965 | + default: | |
| 966 | + return -EINVAL; | |
| 967 | + } | |
| 968 | + | |
| 969 | + return -EINVAL; | |
| 970 | +} | |
| 971 | + | |
| 972 | +static int ltr501_write_event(struct iio_dev *indio_dev, | |
| 973 | + const struct iio_chan_spec *chan, | |
| 974 | + enum iio_event_type type, | |
| 975 | + enum iio_event_direction dir, | |
| 976 | + enum iio_event_info info, | |
| 977 | + int val, int val2) | |
| 978 | +{ | |
| 979 | + switch (info) { | |
| 980 | + case IIO_EV_INFO_VALUE: | |
| 981 | + if (val2 != 0) | |
| 982 | + return -EINVAL; | |
| 983 | + return ltr501_write_thresh(indio_dev, chan, type, dir, | |
| 984 | + info, val, val2); | |
| 985 | + case IIO_EV_INFO_PERIOD: | |
| 986 | + return ltr501_write_intr_prst(iio_priv(indio_dev), chan->type, | |
| 987 | + val, val2); | |
| 988 | + default: | |
| 989 | + return -EINVAL; | |
| 990 | + } | |
| 991 | + | |
| 992 | + return -EINVAL; | |
| 993 | +} | |
| 994 | + | |
| 995 | +static int ltr501_read_event_config(struct iio_dev *indio_dev, | |
| 996 | + const struct iio_chan_spec *chan, | |
| 997 | + enum iio_event_type type, | |
| 998 | + enum iio_event_direction dir) | |
| 999 | +{ | |
| 1000 | + struct ltr501_data *data = iio_priv(indio_dev); | |
| 1001 | + int ret, status; | |
| 1002 | + | |
| 1003 | + switch (chan->type) { | |
| 1004 | + case IIO_INTENSITY: | |
| 1005 | + ret = regmap_field_read(data->reg_als_intr, &status); | |
| 1006 | + if (ret < 0) | |
| 1007 | + return ret; | |
| 1008 | + return status; | |
| 1009 | + case IIO_PROXIMITY: | |
| 1010 | + ret = regmap_field_read(data->reg_ps_intr, &status); | |
| 1011 | + if (ret < 0) | |
| 1012 | + return ret; | |
| 1013 | + return status; | |
| 1014 | + default: | |
| 1015 | + return -EINVAL; | |
| 1016 | + } | |
| 1017 | + | |
| 1018 | + return -EINVAL; | |
| 1019 | +} | |
| 1020 | + | |
| 1021 | +static int ltr501_write_event_config(struct iio_dev *indio_dev, | |
| 1022 | + const struct iio_chan_spec *chan, | |
| 1023 | + enum iio_event_type type, | |
| 1024 | + enum iio_event_direction dir, int state) | |
| 1025 | +{ | |
| 1026 | + struct ltr501_data *data = iio_priv(indio_dev); | |
| 1027 | + int ret; | |
| 1028 | + | |
| 1029 | + /* only 1 and 0 are valid inputs */ | |
| 1030 | + if (state != 1 && state != 0) | |
| 1031 | + return -EINVAL; | |
| 1032 | + | |
| 1033 | + switch (chan->type) { | |
| 1034 | + case IIO_INTENSITY: | |
| 1035 | + mutex_lock(&data->lock_als); | |
| 1036 | + ret = regmap_field_write(data->reg_als_intr, state); | |
| 1037 | + mutex_unlock(&data->lock_als); | |
| 1038 | + return ret; | |
| 1039 | + case IIO_PROXIMITY: | |
| 1040 | + mutex_lock(&data->lock_ps); | |
| 1041 | + ret = regmap_field_write(data->reg_ps_intr, state); | |
| 1042 | + mutex_unlock(&data->lock_ps); | |
| 1043 | + return ret; | |
| 1044 | + default: | |
| 1045 | + return -EINVAL; | |
| 1046 | + } | |
| 1047 | + | |
| 1048 | + return -EINVAL; | |
| 1049 | +} | |
| 1050 | + | |
| 1051 | +static ssize_t ltr501_show_proximity_scale_avail(struct device *dev, | |
| 1052 | + struct device_attribute *attr, | |
| 1053 | + char *buf) | |
| 1054 | +{ | |
| 1055 | + struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); | |
| 1056 | + struct ltr501_chip_info *info = data->chip_info; | |
| 1057 | + ssize_t len = 0; | |
| 1058 | + int i; | |
| 1059 | + | |
| 1060 | + for (i = 0; i < info->ps_gain_tbl_size; i++) { | |
| 1061 | + if (info->ps_gain[i].scale == LTR501_RESERVED_GAIN) | |
| 1062 | + continue; | |
| 1063 | + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ", | |
| 1064 | + info->ps_gain[i].scale, | |
| 1065 | + info->ps_gain[i].uscale); | |
| 1066 | + } | |
| 1067 | + | |
| 1068 | + buf[len - 1] = '\n'; | |
| 1069 | + | |
| 1070 | + return len; | |
| 1071 | +} | |
| 1072 | + | |
| 1073 | +static ssize_t ltr501_show_intensity_scale_avail(struct device *dev, | |
| 1074 | + struct device_attribute *attr, | |
| 1075 | + char *buf) | |
| 1076 | +{ | |
| 1077 | + struct ltr501_data *data = iio_priv(dev_to_iio_dev(dev)); | |
| 1078 | + struct ltr501_chip_info *info = data->chip_info; | |
| 1079 | + ssize_t len = 0; | |
| 1080 | + int i; | |
| 1081 | + | |
| 1082 | + for (i = 0; i < info->als_gain_tbl_size; i++) { | |
| 1083 | + if (info->als_gain[i].scale == LTR501_RESERVED_GAIN) | |
| 1084 | + continue; | |
| 1085 | + len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ", | |
| 1086 | + info->als_gain[i].scale, | |
| 1087 | + info->als_gain[i].uscale); | |
| 1088 | + } | |
| 1089 | + | |
| 1090 | + buf[len - 1] = '\n'; | |
| 1091 | + | |
| 1092 | + return len; | |
| 1093 | +} | |
| 1094 | + | |
| 1095 | +static IIO_CONST_ATTR_INT_TIME_AVAIL("0.05 0.1 0.2 0.4"); | |
| 1096 | +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("20 10 5 2 1 0.5"); | |
| 1097 | + | |
| 1098 | +static IIO_DEVICE_ATTR(in_proximity_scale_available, S_IRUGO, | |
| 1099 | + ltr501_show_proximity_scale_avail, NULL, 0); | |
| 1100 | +static IIO_DEVICE_ATTR(in_intensity_scale_available, S_IRUGO, | |
| 1101 | + ltr501_show_intensity_scale_avail, NULL, 0); | |
| 240 | 1102 | |
| 241 | 1103 | static struct attribute *ltr501_attributes[] = { |
| 242 | − &iio_const_attr_in_proximity_scale_available.dev_attr.attr, | |
| 243 | − &iio_const_attr_in_intensity_scale_available.dev_attr.attr, | |
| 1104 | + &iio_dev_attr_in_proximity_scale_available.dev_attr.attr, | |
| 1105 | + &iio_dev_attr_in_intensity_scale_available.dev_attr.attr, | |
| 1106 | + &iio_const_attr_integration_time_available.dev_attr.attr, | |
| 1107 | + &iio_const_attr_sampling_frequency_available.dev_attr.attr, | |
| 1108 | + NULL | |
| 1109 | +}; | |
| 1110 | + | |
| 1111 | +static struct attribute *ltr301_attributes[] = { | |
| 1112 | + &iio_dev_attr_in_intensity_scale_available.dev_attr.attr, | |
| 1113 | + &iio_const_attr_integration_time_available.dev_attr.attr, | |
| 1114 | + &iio_const_attr_sampling_frequency_available.dev_attr.attr, | |
| 244 | 1115 | NULL |
| 245 | 1116 | }; |
| 246 | 1117 | |
| @@ -248,20 +1119,98 @@ static const struct attribute_group ltr501_attribute_group = { · 1 unmodified line | ||
| 248 | 1119 | .attrs = ltr501_attributes, |
| 249 | 1120 | }; |
| 250 | 1121 | |
| 1122 | +static const struct attribute_group ltr301_attribute_group = { | |
| 1123 | + .attrs = ltr301_attributes, | |
| 1124 | +}; | |
| 1125 | + | |
| 1126 | +static const struct iio_info ltr501_info_no_irq = { | |
| 1127 | + .read_raw = ltr501_read_raw, | |
| 1128 | + .write_raw = ltr501_write_raw, | |
| 1129 | + .attrs = <r501_attribute_group, | |
| 1130 | + .driver_module = THIS_MODULE, | |
| 1131 | +}; | |
| 1132 | + | |
| 251 | 1133 | static const struct iio_info ltr501_info = { |
| 252 | 1134 | .read_raw = ltr501_read_raw, |
| 253 | 1135 | .write_raw = ltr501_write_raw, |
| 254 | 1136 | .attrs = <r501_attribute_group, |
| 1137 | + .read_event_value = <r501_read_event, | |
| 1138 | + .write_event_value = <r501_write_event, | |
| 1139 | + .read_event_config = <r501_read_event_config, | |
| 1140 | + .write_event_config = <r501_write_event_config, | |
| 1141 | + .driver_module = THIS_MODULE, | |
| 1142 | +}; | |
| 1143 | + | |
| 1144 | +static const struct iio_info ltr301_info_no_irq = { | |
| 1145 | + .read_raw = ltr501_read_raw, | |
| 1146 | + .write_raw = ltr501_write_raw, | |
| 1147 | + .attrs = <r301_attribute_group, | |
| 255 | 1148 | .driver_module = THIS_MODULE, |
| 256 | 1149 | }; |
| 257 | 1150 | |
| 258 | −static int ltr501_write_contr(struct i2c_client *client, u8 als_val, u8 ps_val) | |
| 1151 | +static const struct iio_info ltr301_info = { | |
| 1152 | + .read_raw = ltr501_read_raw, | |
| 1153 | + .write_raw = ltr501_write_raw, | |
| 1154 | + .attrs = <r301_attribute_group, | |
| 1155 | + .read_event_value = <r501_read_event, | |
| 1156 | + .write_event_value = <r501_write_event, | |
| 1157 | + .read_event_config = <r501_read_event_config, | |
| 1158 | + .write_event_config = <r501_write_event_config, | |
| 1159 | + .driver_module = THIS_MODULE, | |
| 1160 | +}; | |
| 1161 | + | |
| 1162 | +static struct ltr501_chip_info ltr501_chip_info_tbl[] = { | |
| 1163 | + [ltr501] = { | |
| 1164 | + .partid = 0x08, | |
| 1165 | + .als_gain = ltr501_als_gain_tbl, | |
| 1166 | + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl), | |
| 1167 | + .ps_gain = ltr501_ps_gain_tbl, | |
| 1168 | + .ps_gain_tbl_size = ARRAY_SIZE(ltr501_ps_gain_tbl), | |
| 1169 | + .als_mode_active = BIT(0) | BIT(1), | |
| 1170 | + .als_gain_mask = BIT(3), | |
| 1171 | + .als_gain_shift = 3, | |
| 1172 | + .info = <r501_info, | |
| 1173 | + .info_no_irq = <r501_info_no_irq, | |
| 1174 | + .channels = ltr501_channels, | |
| 1175 | + .no_channels = ARRAY_SIZE(ltr501_channels), | |
| 1176 | + }, | |
| 1177 | + [ltr559] = { | |
| 1178 | + .partid = 0x09, | |
| 1179 | + .als_gain = ltr559_als_gain_tbl, | |
| 1180 | + .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl), | |
| 1181 | + .ps_gain = ltr559_ps_gain_tbl, | |
| 1182 | + .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl), | |
| 1183 | + .als_mode_active = BIT(1), | |
| 1184 | + .als_gain_mask = BIT(2) | BIT(3) | BIT(4), | |
| 1185 | + .als_gain_shift = 2, | |
| 1186 | + .info = <r501_info, | |
| 1187 | + .info_no_irq = <r501_info_no_irq, | |
| 1188 | + .channels = ltr501_channels, | |
| 1189 | + .no_channels = ARRAY_SIZE(ltr501_channels), | |
| 1190 | + }, | |
| 1191 | + [ltr301] = { | |
| 1192 | + .partid = 0x08, | |
| 1193 | + .als_gain = ltr501_als_gain_tbl, | |
| 1194 | + .als_gain_tbl_size = ARRAY_SIZE(ltr501_als_gain_tbl), | |
| 1195 | + .als_mode_active = BIT(0) | BIT(1), | |
| 1196 | + .als_gain_mask = BIT(3), | |
| 1197 | + .als_gain_shift = 3, | |
| 1198 | + .info = <r301_info, | |
| 1199 | + .info_no_irq = <r301_info_no_irq, | |
| 1200 | + .channels = ltr301_channels, | |
| 1201 | + .no_channels = ARRAY_SIZE(ltr301_channels), | |
| 1202 | + }, | |
| 1203 | +}; | |
| 1204 | + | |
| 1205 | +static int ltr501_write_contr(struct ltr501_data *data, u8 als_val, u8 ps_val) | |
| 259 | 1206 | { |
| 260 | − int ret = i2c_smbus_write_byte_data(client, LTR501_ALS_CONTR, als_val); | |
| 1207 | + int ret; | |
| 1208 | + | |
| 1209 | + ret = regmap_write(data->regmap, LTR501_ALS_CONTR, als_val); | |
| 261 | 1210 | if (ret < 0) |
| 262 | 1211 | return ret; |
| 263 | 1212 | |
| 264 | − return i2c_smbus_write_byte_data(client, LTR501_PS_CONTR, ps_val); | |
| 1213 | + return regmap_write(data->regmap, LTR501_PS_CONTR, ps_val); | |
| 265 | 1214 | } |
| 266 | 1215 | |
| 267 | 1216 | static irqreturn_t ltr501_trigger_handler(int irq, void *p) |
| @@ -273,13 +1222,13 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) · 5 unmodified lines | ||
| 273 | 1222 | __le16 als_buf[2]; |
| 274 | 1223 | u8 mask = 0; |
| 275 | 1224 | int j = 0; |
| 276 | − int ret; | |
| 1225 | + int ret, psdata; | |
| 277 | 1226 | |
| 278 | 1227 | memset(buf, 0, sizeof(buf)); |
| 279 | 1228 | |
| 280 | 1229 | /* figure out which data needs to be ready */ |
| 281 | 1230 | if (test_bit(0, indio_dev->active_scan_mask) || |
| 282 | − test_bit(1, indio_dev->active_scan_mask)) | |
| 1231 | + test_bit(1, indio_dev->active_scan_mask)) | |
| 283 | 1232 | mask |= LTR501_STATUS_ALS_RDY; |
| 284 | 1233 | if (test_bit(2, indio_dev->active_scan_mask)) |
| 285 | 1234 | mask |= LTR501_STATUS_PS_RDY; |
| @@ -289,8 +1238,8 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) · 3 unmodified lines | ||
| 289 | 1238 | goto done; |
| 290 | 1239 | |
| 291 | 1240 | if (mask & LTR501_STATUS_ALS_RDY) { |
| 292 | − ret = i2c_smbus_read_i2c_block_data(data->client, | |
| 293 | − LTR501_ALS_DATA1, sizeof(als_buf), (u8 *) als_buf); | |
| 1241 | + ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, | |
| 1242 | + (u8 *)als_buf, sizeof(als_buf)); | |
| 294 | 1243 | if (ret < 0) |
| 295 | 1244 | return ret; |
| 296 | 1245 | if (test_bit(0, indio_dev->active_scan_mask)) |
| @@ -300,14 +1249,14 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) · 3 unmodified lines | ||
| 300 | 1249 | } |
| 301 | 1250 | |
| 302 | 1251 | if (mask & LTR501_STATUS_PS_RDY) { |
| 303 | − ret = i2c_smbus_read_word_data(data->client, LTR501_PS_DATA); | |
| 1252 | + ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, | |
| 1253 | + &psdata, 2); | |
| 304 | 1254 | if (ret < 0) |
| 305 | 1255 | goto done; |
| 306 | − buf[j++] = ret & LTR501_PS_DATA_MASK; | |
| 1256 | + buf[j++] = psdata & LTR501_PS_DATA_MASK; | |
| 307 | 1257 | } |
| 308 | 1258 | |
| 309 | − iio_push_to_buffers_with_timestamp(indio_dev, buf, | |
| 310 | − iio_get_time_ns()); | |
| 1259 | + iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); | |
| 311 | 1260 | |
| 312 | 1261 | done: |
| 313 | 1262 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -315,67 +1264,225 @@ done: · 1 unmodified line | ||
| 315 | 1264 | return IRQ_HANDLED; |
| 316 | 1265 | } |
| 317 | 1266 | |
| 1267 | +static irqreturn_t ltr501_interrupt_handler(int irq, void *private) | |
| 1268 | +{ | |
| 1269 | + struct iio_dev *indio_dev = private; | |
| 1270 | + struct ltr501_data *data = iio_priv(indio_dev); | |
| 1271 | + int ret, status; | |
| 1272 | + | |
| 1273 | + ret = regmap_read(data->regmap, LTR501_ALS_PS_STATUS, &status); | |
| 1274 | + if (ret < 0) { | |
| 1275 | + dev_err(&data->client->dev, | |
| 1276 | + "irq read int reg failed\n"); | |
| 1277 | + return IRQ_HANDLED; | |
| 1278 | + } | |
| 1279 | + | |
| 1280 | + if (status & LTR501_STATUS_ALS_INTR) | |
| 1281 | + iio_push_event(indio_dev, | |
| 1282 | + IIO_UNMOD_EVENT_CODE(IIO_INTENSITY, 0, | |
| 1283 | + IIO_EV_TYPE_THRESH, | |
| 1284 | + IIO_EV_DIR_EITHER), | |
| 1285 | + iio_get_time_ns()); | |
| 1286 | + | |
| 1287 | + if (status & LTR501_STATUS_PS_INTR) | |
| 1288 | + iio_push_event(indio_dev, | |
| 1289 | + IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, | |
| 1290 | + IIO_EV_TYPE_THRESH, | |
| 1291 | + IIO_EV_DIR_EITHER), | |
| 1292 | + iio_get_time_ns()); | |
| 1293 | + | |
| 1294 | + return IRQ_HANDLED; | |
| 1295 | +} | |
| 1296 | + | |
| 318 | 1297 | static int ltr501_init(struct ltr501_data *data) |
| 319 | 1298 | { |
| 320 | − int ret; | |
| 1299 | + int ret, status; | |
| 321 | 1300 | |
| 322 | − ret = i2c_smbus_read_byte_data(data->client, LTR501_ALS_CONTR); | |
| 1301 | + ret = regmap_read(data->regmap, LTR501_ALS_CONTR, &status); | |
| 323 | 1302 | if (ret < 0) |
| 324 | 1303 | return ret; |
| 325 | − data->als_contr = ret | LTR501_CONTR_ACTIVE; | |
| 326 | 1304 | |
| 327 | − ret = i2c_smbus_read_byte_data(data->client, LTR501_PS_CONTR); | |
| 1305 | + data->als_contr = ret | data->chip_info->als_mode_active; | |
| 1306 | + | |
| 1307 | + ret = regmap_read(data->regmap, LTR501_PS_CONTR, &status); | |
| 328 | 1308 | if (ret < 0) |
| 329 | 1309 | return ret; |
| 330 | − data->ps_contr = ret | LTR501_CONTR_ACTIVE; | |
| 331 | 1310 | |
| 332 | − return ltr501_write_contr(data->client, data->als_contr, | |
| 333 | − data->ps_contr); | |
| 1311 | + data->ps_contr = status | LTR501_CONTR_ACTIVE; | |
| 1312 | + | |
| 1313 | + ret = ltr501_read_intr_prst(data, IIO_INTENSITY, &data->als_period); | |
| 1314 | + if (ret < 0) | |
| 1315 | + return ret; | |
| 1316 | + | |
| 1317 | + ret = ltr501_read_intr_prst(data, IIO_PROXIMITY, &data->ps_period); | |
| 1318 | + if (ret < 0) | |
| 1319 | + return ret; | |
| 1320 | + | |
| 1321 | + return ltr501_write_contr(data, data->als_contr, data->ps_contr); | |
| 1322 | +} | |
| 1323 | + | |
| 1324 | +static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg) | |
| 1325 | +{ | |
| 1326 | + switch (reg) { | |
| 1327 | + case LTR501_ALS_DATA1: | |
| 1328 | + case LTR501_ALS_DATA0: | |
| 1329 | + case LTR501_ALS_PS_STATUS: | |
| 1330 | + case LTR501_PS_DATA: | |
| 1331 | + return true; | |
| 1332 | + default: | |
| 1333 | + return false; | |
| 1334 | + } | |
| 334 | 1335 | } |
| 335 | 1336 | |
| 1337 | +static struct regmap_config ltr501_regmap_config = { | |
| 1338 | + .name = LTR501_REGMAP_NAME, | |
| 1339 | + .reg_bits = 8, | |
| 1340 | + .val_bits = 8, | |
| 1341 | + .max_register = LTR501_MAX_REG, | |
| 1342 | + .cache_type = REGCACHE_RBTREE, | |
| 1343 | + .volatile_reg = ltr501_is_volatile_reg, | |
| 1344 | +}; | |
| 1345 | + | |
| 336 | 1346 | static int ltr501_powerdown(struct ltr501_data *data) |
| 337 | 1347 | { |
| 338 | − return ltr501_write_contr(data->client, | |
| 339 | − data->als_contr & ~LTR501_CONTR_ACTIVE, | |
| 1348 | + return ltr501_write_contr(data, data->als_contr & | |
| 1349 | + ~data->chip_info->als_mode_active, | |
| 340 | 1350 | data->ps_contr & ~LTR501_CONTR_ACTIVE); |
| 341 | 1351 | } |
| 342 | 1352 | |
| 1353 | +static const char *ltr501_match_acpi_device(struct device *dev, int *chip_idx) | |
| 1354 | +{ | |
| 1355 | + const struct acpi_device_id *id; | |
| 1356 | + | |
| 1357 | + id = acpi_match_device(dev->driver->acpi_match_table, dev); | |
| 1358 | + if (!id) | |
| 1359 | + return NULL; | |
| 1360 | + *chip_idx = id->driver_data; | |
| 1361 | + return dev_name(dev); | |
| 1362 | +} | |
| 1363 | + | |
| 343 | 1364 | static int ltr501_probe(struct i2c_client *client, |
| 344 | − const struct i2c_device_id *id) | |
| 1365 | + const struct i2c_device_id *id) | |
| 345 | 1366 | { |
| 346 | 1367 | struct ltr501_data *data; |
| 347 | 1368 | struct iio_dev *indio_dev; |
| 348 | − int ret; | |
| 1369 | + struct regmap *regmap; | |
| 1370 | + int ret, partid, chip_idx = 0; | |
| 1371 | + const char *name = NULL; | |
| 349 | 1372 | |
| 350 | 1373 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
| 351 | 1374 | if (!indio_dev) |
| 352 | 1375 | return -ENOMEM; |
| 353 | 1376 | |
| 1377 | + regmap = devm_regmap_init_i2c(client, <r501_regmap_config); | |
| 1378 | + if (IS_ERR(regmap)) { | |
| 1379 | + dev_err(&client->dev, "Regmap initialization failed.\n"); | |
| 1380 | + return PTR_ERR(regmap); | |
| 1381 | + } | |
| 1382 | + | |
| 354 | 1383 | data = iio_priv(indio_dev); |
| 355 | 1384 | i2c_set_clientdata(client, indio_dev); |
| 356 | 1385 | data->client = client; |
| 1386 | + data->regmap = regmap; | |
| 357 | 1387 | mutex_init(&data->lock_als); |
| 358 | 1388 | mutex_init(&data->lock_ps); |
| 359 | 1389 | |
| 360 | − ret = i2c_smbus_read_byte_data(data->client, LTR501_PART_ID); | |
| 1390 | + data->reg_it = devm_regmap_field_alloc(&client->dev, regmap, | |
| 1391 | + reg_field_it); | |
| 1392 | + if (IS_ERR(data->reg_it)) { | |
| 1393 | + dev_err(&client->dev, "Integ time reg field init failed.\n"); | |
| 1394 | + return PTR_ERR(data->reg_it); | |
| 1395 | + } | |
| 1396 | + | |
| 1397 | + data->reg_als_intr = devm_regmap_field_alloc(&client->dev, regmap, | |
| 1398 | + reg_field_als_intr); | |
| 1399 | + if (IS_ERR(data->reg_als_intr)) { | |
| 1400 | + dev_err(&client->dev, "ALS intr mode reg field init failed\n"); | |
| 1401 | + return PTR_ERR(data->reg_als_intr); | |
| 1402 | + } | |
| 1403 | + | |
| 1404 | + data->reg_ps_intr = devm_regmap_field_alloc(&client->dev, regmap, | |
| 1405 | + reg_field_ps_intr); | |
| 1406 | + if (IS_ERR(data->reg_ps_intr)) { | |
| 1407 | + dev_err(&client->dev, "PS intr mode reg field init failed.\n"); | |
| 1408 | + return PTR_ERR(data->reg_ps_intr); | |
| 1409 | + } | |
| 1410 | + | |
| 1411 | + data->reg_als_rate = devm_regmap_field_alloc(&client->dev, regmap, | |
| 1412 | + reg_field_als_rate); | |
| 1413 | + if (IS_ERR(data->reg_als_rate)) { | |
| 1414 | + dev_err(&client->dev, "ALS samp rate field init failed.\n"); | |
| 1415 | + return PTR_ERR(data->reg_als_rate); | |
| 1416 | + } | |
| 1417 | + | |
| 1418 | + data->reg_ps_rate = devm_regmap_field_alloc(&client->dev, regmap, | |
| 1419 | + reg_field_ps_rate); | |
| 1420 | + if (IS_ERR(data->reg_ps_rate)) { | |
| 1421 | + dev_err(&client->dev, "PS samp rate field init failed.\n"); | |
| 1422 | + return PTR_ERR(data->reg_ps_rate); | |
| 1423 | + } | |
| 1424 | + | |
| 1425 | + data->reg_als_prst = devm_regmap_field_alloc(&client->dev, regmap, | |
| 1426 | + reg_field_als_prst); | |
| 1427 | + if (IS_ERR(data->reg_als_prst)) { | |
| 1428 | + dev_err(&client->dev, "ALS prst reg field init failed\n"); | |
| 1429 | + return PTR_ERR(data->reg_als_prst); | |
| 1430 | + } | |
| 1431 | + | |
| 1432 | + data->reg_ps_prst = devm_regmap_field_alloc(&client->dev, regmap, | |
| 1433 | + reg_field_ps_prst); | |
| 1434 | + if (IS_ERR(data->reg_ps_prst)) { | |
| 1435 | + dev_err(&client->dev, "PS prst reg field init failed.\n"); | |
| 1436 | + return PTR_ERR(data->reg_ps_prst); | |
| 1437 | + } | |
| 1438 | + | |
| 1439 | + ret = regmap_read(data->regmap, LTR501_PART_ID, &partid); | |
| 361 | 1440 | if (ret < 0) |
| 362 | 1441 | return ret; |
| 363 | − if ((ret >> 4) != 0x8) | |
| 1442 | + | |
| 1443 | + if (id) { | |
| 1444 | + name = id->name; | |
| 1445 | + chip_idx = id->driver_data; | |
| 1446 | + } else if (ACPI_HANDLE(&client->dev)) { | |
| 1447 | + name = ltr501_match_acpi_device(&client->dev, &chip_idx); | |
| 1448 | + } else { | |
| 1449 | + return -ENODEV; | |
| 1450 | + } | |
| 1451 | + | |
| 1452 | + data->chip_info = <r501_chip_info_tbl[chip_idx]; | |
| 1453 | + | |
| 1454 | + if ((partid >> 4) != data->chip_info->partid) | |
| 364 | 1455 | return -ENODEV; |
| 365 | 1456 | |
| 366 | 1457 | indio_dev->dev.parent = &client->dev; |
| 367 | − indio_dev->info = <r501_info; | |
| 368 | − indio_dev->channels = ltr501_channels; | |
| 369 | − indio_dev->num_channels = ARRAY_SIZE(ltr501_channels); | |
| 370 | − indio_dev->name = LTR501_DRV_NAME; | |
| 1458 | + indio_dev->info = data->chip_info->info; | |
| 1459 | + indio_dev->channels = data->chip_info->channels; | |
| 1460 | + indio_dev->num_channels = data->chip_info->no_channels; | |
| 1461 | + indio_dev->name = name; | |
| 371 | 1462 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 372 | 1463 | |
| 373 | 1464 | ret = ltr501_init(data); |
| 374 | 1465 | if (ret < 0) |
| 375 | 1466 | return ret; |
| 376 | 1467 | |
| 1468 | + if (client->irq > 0) { | |
| 1469 | + ret = devm_request_threaded_irq(&client->dev, client->irq, | |
| 1470 | + NULL, ltr501_interrupt_handler, | |
| 1471 | + IRQF_TRIGGER_FALLING | | |
| 1472 | + IRQF_ONESHOT, | |
| 1473 | + "ltr501_thresh_event", | |
| 1474 | + indio_dev); | |
| 1475 | + if (ret) { | |
| 1476 | + dev_err(&client->dev, "request irq (%d) failed\n", | |
| 1477 | + client->irq); | |
| 1478 | + return ret; | |
| 1479 | + } | |
| 1480 | + } else { | |
| 1481 | + indio_dev->info = data->chip_info->info_no_irq; | |
| 1482 | + } | |
| 1483 | + | |
| 377 | 1484 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
| 378 | − ltr501_trigger_handler, NULL); | |
| 1485 | + ltr501_trigger_handler, NULL); | |
| 379 | 1486 | if (ret) |
| 380 | 1487 | goto powerdown_on_error; |
| 381 | 1488 | |
| @@ -407,24 +1514,34 @@ static int ltr501_remove(struct i2c_client *client) · 25 unmodified lines | ||
| 407 | 1514 | static int ltr501_suspend(struct device *dev) |
| 408 | 1515 | { |
| 409 | 1516 | struct ltr501_data *data = iio_priv(i2c_get_clientdata( |
| 410 | − to_i2c_client(dev))); | |
| 1517 | + to_i2c_client(dev))); | |
| 411 | 1518 | return ltr501_powerdown(data); |
| 412 | 1519 | } |
| 413 | 1520 | |
| 414 | 1521 | static int ltr501_resume(struct device *dev) |
| 415 | 1522 | { |
| 416 | 1523 | struct ltr501_data *data = iio_priv(i2c_get_clientdata( |
| 417 | − to_i2c_client(dev))); | |
| 1524 | + to_i2c_client(dev))); | |
| 418 | 1525 | |
| 419 | − return ltr501_write_contr(data->client, data->als_contr, | |
| 1526 | + return ltr501_write_contr(data, data->als_contr, | |
| 420 | 1527 | data->ps_contr); |
| 421 | 1528 | } |
| 422 | 1529 | #endif |
| 423 | 1530 | |
| 424 | 1531 | static SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume); |
| 425 | 1532 | |
| 1533 | +static const struct acpi_device_id ltr_acpi_match[] = { | |
| 1534 | + {"LTER0501", ltr501}, | |
| 1535 | + {"LTER0559", ltr559}, | |
| 1536 | + {"LTER0301", ltr301}, | |
| 1537 | + { }, | |
| 1538 | +}; | |
| 1539 | +MODULE_DEVICE_TABLE(acpi, ltr_acpi_match); | |
| 1540 | + | |
| 426 | 1541 | static const struct i2c_device_id ltr501_id[] = { |
| 427 | − { "ltr501", 0 }, | |
| 1542 | + { "ltr501", ltr501}, | |
| 1543 | + { "ltr559", ltr559}, | |
| 1544 | + { "ltr301", ltr301}, | |
| 428 | 1545 | { } |
| 429 | 1546 | }; |
| 430 | 1547 | MODULE_DEVICE_TABLE(i2c, ltr501_id); |
| @@ -433,6 +1550,7 @@ static struct i2c_driver ltr501_driver = { · 2 unmodified lines | ||
| 433 | 1550 | .driver = { |
| 434 | 1551 | .name = LTR501_DRV_NAME, |
| 435 | 1552 | .pm = <r501_pm_ops, |
| 1553 | + .acpi_match_table = ACPI_PTR(ltr_acpi_match), | |
| 436 | 1554 | .owner = THIS_MODULE, |
| 437 | 1555 | }, |
| 438 | 1556 | .probe = ltr501_probe, |
| @@ -0,0 +1,722 @@ | ||
| 1 | +/** | |
| 2 | + * Sensortek STK3310/STK3311 Ambient Light and Proximity Sensor | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015, Intel Corporation. | |
| 5 | + * | |
| 6 | + * This file is subject to the terms and conditions of version 2 of | |
| 7 | + * the GNU General Public License. See the file COPYING in the main | |
| 8 | + * directory of this archive for more details. | |
| 9 | + * | |
| 10 | + * IIO driver for STK3310/STK3311. 7-bit I2C address: 0x48. | |
| 11 | + */ | |
| 12 | + | |
| 13 | +#include <linux/acpi.h> | |
| 14 | +#include <linux/i2c.h> | |
| 15 | +#include <linux/interrupt.h> | |
| 16 | +#include <linux/kernel.h> | |
| 17 | +#include <linux/module.h> | |
| 18 | +#include <linux/regmap.h> | |
| 19 | +#include <linux/gpio/consumer.h> | |
| 20 | +#include <linux/iio/events.h> | |
| 21 | +#include <linux/iio/iio.h> | |
| 22 | +#include <linux/iio/sysfs.h> | |
| 23 | + | |
| 24 | +#define STK3310_REG_STATE 0x00 | |
| 25 | +#define STK3310_REG_PSCTRL 0x01 | |
| 26 | +#define STK3310_REG_ALSCTRL 0x02 | |
| 27 | +#define STK3310_REG_INT 0x04 | |
| 28 | +#define STK3310_REG_THDH_PS 0x06 | |
| 29 | +#define STK3310_REG_THDL_PS 0x08 | |
| 30 | +#define STK3310_REG_FLAG 0x10 | |
| 31 | +#define STK3310_REG_PS_DATA_MSB 0x11 | |
| 32 | +#define STK3310_REG_PS_DATA_LSB 0x12 | |
| 33 | +#define STK3310_REG_ALS_DATA_MSB 0x13 | |
| 34 | +#define STK3310_REG_ALS_DATA_LSB 0x14 | |
| 35 | +#define STK3310_REG_ID 0x3E | |
| 36 | +#define STK3310_MAX_REG 0x80 | |
| 37 | + | |
| 38 | +#define STK3310_STATE_EN_PS 0x01 | |
| 39 | +#define STK3310_STATE_EN_ALS 0x02 | |
| 40 | +#define STK3310_STATE_STANDBY 0x00 | |
| 41 | + | |
| 42 | +#define STK3310_CHIP_ID_VAL 0x13 | |
| 43 | +#define STK3311_CHIP_ID_VAL 0x1D | |
| 44 | +#define STK3310_PSINT_EN 0x01 | |
| 45 | +#define STK3310_PS_MAX_VAL 0xFFFF | |
| 46 | +#define STK3310_THRESH_MAX 0xFFFF | |
| 47 | + | |
| 48 | +#define STK3310_DRIVER_NAME "stk3310" | |
| 49 | +#define STK3310_REGMAP_NAME "stk3310_regmap" | |
| 50 | +#define STK3310_EVENT "stk3310_event" | |
| 51 | +#define STK3310_GPIO "stk3310_gpio" | |
| 52 | + | |
| 53 | +#define STK3310_SCALE_AVAILABLE "6.4 1.6 0.4 0.1" | |
| 54 | + | |
| 55 | +#define STK3310_IT_AVAILABLE \ | |
| 56 | + "0.000185 0.000370 0.000741 0.001480 0.002960 0.005920 0.011840 " \ | |
| 57 | + "0.023680 0.047360 0.094720 0.189440 0.378880 0.757760 1.515520 " \ | |
| 58 | + "3.031040 6.062080" | |
| 59 | + | |
| 60 | +#define STK3310_REGFIELD(name) \ | |
| 61 | + do { \ | |
| 62 | + data->reg_##name = \ | |
| 63 | + devm_regmap_field_alloc(&client->dev, regmap, \ | |
| 64 | + stk3310_reg_field_##name); \ | |
| 65 | + if (IS_ERR(data->reg_##name)) { \ | |
| 66 | + dev_err(&client->dev, "reg field alloc failed.\n"); \ | |
| 67 | + return PTR_ERR(data->reg_##name); \ | |
| 68 | + } \ | |
| 69 | + } while (0) | |
| 70 | + | |
| 71 | +static const struct reg_field stk3310_reg_field_state = | |
| 72 | + REG_FIELD(STK3310_REG_STATE, 0, 2); | |
| 73 | +static const struct reg_field stk3310_reg_field_als_gain = | |
| 74 | + REG_FIELD(STK3310_REG_ALSCTRL, 4, 5); | |
| 75 | +static const struct reg_field stk3310_reg_field_ps_gain = | |
| 76 | + REG_FIELD(STK3310_REG_PSCTRL, 4, 5); | |
| 77 | +static const struct reg_field stk3310_reg_field_als_it = | |
| 78 | + REG_FIELD(STK3310_REG_ALSCTRL, 0, 3); | |
| 79 | +static const struct reg_field stk3310_reg_field_ps_it = | |
| 80 | + REG_FIELD(STK3310_REG_PSCTRL, 0, 3); | |
| 81 | +static const struct reg_field stk3310_reg_field_int_ps = | |
| 82 | + REG_FIELD(STK3310_REG_INT, 0, 2); | |
| 83 | +static const struct reg_field stk3310_reg_field_flag_psint = | |
| 84 | + REG_FIELD(STK3310_REG_FLAG, 4, 4); | |
| 85 | +static const struct reg_field stk3310_reg_field_flag_nf = | |
| 86 | + REG_FIELD(STK3310_REG_FLAG, 0, 0); | |
| 87 | +/* | |
| 88 | + * Maximum PS values with regard to scale. Used to export the 'inverse' | |
| 89 | + * PS value (high values for far objects, low values for near objects). | |
| 90 | + */ | |
| 91 | +static const int stk3310_ps_max[4] = { | |
| 92 | + STK3310_PS_MAX_VAL / 64, | |
| 93 | + STK3310_PS_MAX_VAL / 16, | |
| 94 | + STK3310_PS_MAX_VAL / 4, | |
| 95 | + STK3310_PS_MAX_VAL, | |
| 96 | +}; | |
| 97 | + | |
| 98 | +static const int stk3310_scale_table[][2] = { | |
| 99 | + {6, 400000}, {1, 600000}, {0, 400000}, {0, 100000} | |
| 100 | +}; | |
| 101 | + | |
| 102 | +/* Integration time in seconds, microseconds */ | |
| 103 | +static const int stk3310_it_table[][2] = { | |
| 104 | + {0, 185}, {0, 370}, {0, 741}, {0, 1480}, | |
| 105 | + {0, 2960}, {0, 5920}, {0, 11840}, {0, 23680}, | |
| 106 | + {0, 47360}, {0, 94720}, {0, 189440}, {0, 378880}, | |
| 107 | + {0, 757760}, {1, 515520}, {3, 31040}, {6, 62080}, | |
| 108 | +}; | |
| 109 | + | |
| 110 | +struct stk3310_data { | |
| 111 | + struct i2c_client *client; | |
| 112 | + struct mutex lock; | |
| 113 | + bool als_enabled; | |
| 114 | + bool ps_enabled; | |
| 115 | + u64 timestamp; | |
| 116 | + struct regmap *regmap; | |
| 117 | + struct regmap_field *reg_state; | |
| 118 | + struct regmap_field *reg_als_gain; | |
| 119 | + struct regmap_field *reg_ps_gain; | |
| 120 | + struct regmap_field *reg_als_it; | |
| 121 | + struct regmap_field *reg_ps_it; | |
| 122 | + struct regmap_field *reg_int_ps; | |
| 123 | + struct regmap_field *reg_flag_psint; | |
| 124 | + struct regmap_field *reg_flag_nf; | |
| 125 | +}; | |
| 126 | + | |
| 127 | +static const struct iio_event_spec stk3310_events[] = { | |
| 128 | + /* Proximity event */ | |
| 129 | + { | |
| 130 | + .type = IIO_EV_TYPE_THRESH, | |
| 131 | + .dir = IIO_EV_DIR_FALLING, | |
| 132 | + .mask_separate = BIT(IIO_EV_INFO_VALUE) | | |
| 133 | + BIT(IIO_EV_INFO_ENABLE), | |
| 134 | + }, | |
| 135 | + /* Out-of-proximity event */ | |
| 136 | + { | |
| 137 | + .type = IIO_EV_TYPE_THRESH, | |
| 138 | + .dir = IIO_EV_DIR_RISING, | |
| 139 | + .mask_separate = BIT(IIO_EV_INFO_VALUE) | | |
| 140 | + BIT(IIO_EV_INFO_ENABLE), | |
| 141 | + }, | |
| 142 | +}; | |
| 143 | + | |
| 144 | +static const struct iio_chan_spec stk3310_channels[] = { | |
| 145 | + { | |
| 146 | + .type = IIO_LIGHT, | |
| 147 | + .info_mask_separate = | |
| 148 | + BIT(IIO_CHAN_INFO_RAW) | | |
| 149 | + BIT(IIO_CHAN_INFO_SCALE) | | |
| 150 | + BIT(IIO_CHAN_INFO_INT_TIME), | |
| 151 | + }, | |
| 152 | + { | |
| 153 | + .type = IIO_PROXIMITY, | |
| 154 | + .info_mask_separate = | |
| 155 | + BIT(IIO_CHAN_INFO_RAW) | | |
| 156 | + BIT(IIO_CHAN_INFO_SCALE) | | |
| 157 | + BIT(IIO_CHAN_INFO_INT_TIME), | |
| 158 | + .event_spec = stk3310_events, | |
| 159 | + .num_event_specs = ARRAY_SIZE(stk3310_events), | |
| 160 | + } | |
| 161 | +}; | |
| 162 | + | |
| 163 | +static IIO_CONST_ATTR(in_illuminance_scale_available, STK3310_SCALE_AVAILABLE); | |
| 164 | + | |
| 165 | +static IIO_CONST_ATTR(in_proximity_scale_available, STK3310_SCALE_AVAILABLE); | |
| 166 | + | |
| 167 | +static IIO_CONST_ATTR(in_illuminance_integration_time_available, | |
| 168 | + STK3310_IT_AVAILABLE); | |
| 169 | + | |
| 170 | +static IIO_CONST_ATTR(in_proximity_integration_time_available, | |
| 171 | + STK3310_IT_AVAILABLE); | |
| 172 | + | |
| 173 | +static struct attribute *stk3310_attributes[] = { | |
| 174 | + &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, | |
| 175 | + &iio_const_attr_in_proximity_scale_available.dev_attr.attr, | |
| 176 | + &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr, | |
| 177 | + &iio_const_attr_in_proximity_integration_time_available.dev_attr.attr, | |
| 178 | + NULL, | |
| 179 | +}; | |
| 180 | + | |
| 181 | +static const struct attribute_group stk3310_attribute_group = { | |
| 182 | + .attrs = stk3310_attributes | |
| 183 | +}; | |
| 184 | + | |
| 185 | +static int stk3310_get_index(const int table[][2], int table_size, | |
| 186 | + int val, int val2) | |
| 187 | +{ | |
| 188 | + int i; | |
| 189 | + | |
| 190 | + for (i = 0; i < table_size; i++) { | |
| 191 | + if (val == table[i][0] && val2 == table[i][1]) | |
| 192 | + return i; | |
| 193 | + } | |
| 194 | + | |
| 195 | + return -EINVAL; | |
| 196 | +} | |
| 197 | + | |
| 198 | +static int stk3310_read_event(struct iio_dev *indio_dev, | |
| 199 | + const struct iio_chan_spec *chan, | |
| 200 | + enum iio_event_type type, | |
| 201 | + enum iio_event_direction dir, | |
| 202 | + enum iio_event_info info, | |
| 203 | + int *val, int *val2) | |
| 204 | +{ | |
| 205 | + u8 reg; | |
| 206 | + u16 buf; | |
| 207 | + int ret; | |
| 208 | + unsigned int index; | |
| 209 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 210 | + | |
| 211 | + if (info != IIO_EV_INFO_VALUE) | |
| 212 | + return -EINVAL; | |
| 213 | + | |
| 214 | + /* | |
| 215 | + * Only proximity interrupts are implemented at the moment. | |
| 216 | + * Since we're inverting proximity values, the sensor's 'high' | |
| 217 | + * threshold will become our 'low' threshold, associated with | |
| 218 | + * 'near' events. Similarly, the sensor's 'low' threshold will | |
| 219 | + * be our 'high' threshold, associated with 'far' events. | |
| 220 | + */ | |
| 221 | + if (dir == IIO_EV_DIR_RISING) | |
| 222 | + reg = STK3310_REG_THDL_PS; | |
| 223 | + else if (dir == IIO_EV_DIR_FALLING) | |
| 224 | + reg = STK3310_REG_THDH_PS; | |
| 225 | + else | |
| 226 | + return -EINVAL; | |
| 227 | + | |
| 228 | + mutex_lock(&data->lock); | |
| 229 | + ret = regmap_bulk_read(data->regmap, reg, &buf, 2); | |
| 230 | + mutex_unlock(&data->lock); | |
| 231 | + if (ret < 0) { | |
| 232 | + dev_err(&data->client->dev, "register read failed\n"); | |
| 233 | + return ret; | |
| 234 | + } | |
| 235 | + regmap_field_read(data->reg_ps_gain, &index); | |
| 236 | + *val = swab16(stk3310_ps_max[index] - buf); | |
| 237 | + | |
| 238 | + return IIO_VAL_INT; | |
| 239 | +} | |
| 240 | + | |
| 241 | +static int stk3310_write_event(struct iio_dev *indio_dev, | |
| 242 | + const struct iio_chan_spec *chan, | |
| 243 | + enum iio_event_type type, | |
| 244 | + enum iio_event_direction dir, | |
| 245 | + enum iio_event_info info, | |
| 246 | + int val, int val2) | |
| 247 | +{ | |
| 248 | + u8 reg; | |
| 249 | + u16 buf; | |
| 250 | + int ret; | |
| 251 | + unsigned int index; | |
| 252 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 253 | + struct i2c_client *client = data->client; | |
| 254 | + | |
| 255 | + regmap_field_read(data->reg_ps_gain, &index); | |
| 256 | + if (val > stk3310_ps_max[index]) | |
| 257 | + return -EINVAL; | |
| 258 | + | |
| 259 | + if (dir == IIO_EV_DIR_RISING) | |
| 260 | + reg = STK3310_REG_THDL_PS; | |
| 261 | + else if (dir == IIO_EV_DIR_FALLING) | |
| 262 | + reg = STK3310_REG_THDH_PS; | |
| 263 | + else | |
| 264 | + return -EINVAL; | |
| 265 | + | |
| 266 | + buf = swab16(stk3310_ps_max[index] - val); | |
| 267 | + ret = regmap_bulk_write(data->regmap, reg, &buf, 2); | |
| 268 | + if (ret < 0) | |
| 269 | + dev_err(&client->dev, "failed to set PS threshold!\n"); | |
| 270 | + | |
| 271 | + return ret; | |
| 272 | +} | |
| 273 | + | |
| 274 | +static int stk3310_read_event_config(struct iio_dev *indio_dev, | |
| 275 | + const struct iio_chan_spec *chan, | |
| 276 | + enum iio_event_type type, | |
| 277 | + enum iio_event_direction dir) | |
| 278 | +{ | |
| 279 | + unsigned int event_val; | |
| 280 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 281 | + | |
| 282 | + regmap_field_read(data->reg_int_ps, &event_val); | |
| 283 | + | |
| 284 | + return event_val; | |
| 285 | +} | |
| 286 | + | |
| 287 | +static int stk3310_write_event_config(struct iio_dev *indio_dev, | |
| 288 | + const struct iio_chan_spec *chan, | |
| 289 | + enum iio_event_type type, | |
| 290 | + enum iio_event_direction dir, | |
| 291 | + int state) | |
| 292 | +{ | |
| 293 | + int ret; | |
| 294 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 295 | + struct i2c_client *client = data->client; | |
| 296 | + | |
| 297 | + if (state < 0 || state > 7) | |
| 298 | + return -EINVAL; | |
| 299 | + | |
| 300 | + /* Set INT_PS value */ | |
| 301 | + mutex_lock(&data->lock); | |
| 302 | + ret = regmap_field_write(data->reg_int_ps, state); | |
| 303 | + if (ret < 0) | |
| 304 | + dev_err(&client->dev, "failed to set interrupt mode\n"); | |
| 305 | + mutex_unlock(&data->lock); | |
| 306 | + | |
| 307 | + return ret; | |
| 308 | +} | |
| 309 | + | |
| 310 | +static int stk3310_read_raw(struct iio_dev *indio_dev, | |
| 311 | + struct iio_chan_spec const *chan, | |
| 312 | + int *val, int *val2, long mask) | |
| 313 | +{ | |
| 314 | + u8 reg; | |
| 315 | + u16 buf; | |
| 316 | + int ret; | |
| 317 | + unsigned int index; | |
| 318 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 319 | + struct i2c_client *client = data->client; | |
| 320 | + | |
| 321 | + switch (mask) { | |
| 322 | + case IIO_CHAN_INFO_RAW: | |
| 323 | + if (chan->type == IIO_LIGHT) | |
| 324 | + reg = STK3310_REG_ALS_DATA_MSB; | |
| 325 | + else if (chan->type == IIO_PROXIMITY) | |
| 326 | + reg = STK3310_REG_PS_DATA_MSB; | |
| 327 | + else | |
| 328 | + return -EINVAL; | |
| 329 | + mutex_lock(&data->lock); | |
| 330 | + ret = regmap_bulk_read(data->regmap, reg, &buf, 2); | |
| 331 | + if (ret < 0) { | |
| 332 | + dev_err(&client->dev, "register read failed\n"); | |
| 333 | + mutex_unlock(&data->lock); | |
| 334 | + return ret; | |
| 335 | + } | |
| 336 | + *val = swab16(buf); | |
| 337 | + if (chan->type == IIO_PROXIMITY) { | |
| 338 | + /* | |
| 339 | + * Invert the proximity data so we return low values | |
| 340 | + * for close objects and high values for far ones. | |
| 341 | + */ | |
| 342 | + regmap_field_read(data->reg_ps_gain, &index); | |
| 343 | + *val = stk3310_ps_max[index] - *val; | |
| 344 | + } | |
| 345 | + mutex_unlock(&data->lock); | |
| 346 | + return IIO_VAL_INT; | |
| 347 | + case IIO_CHAN_INFO_INT_TIME: | |
| 348 | + if (chan->type == IIO_LIGHT) | |
| 349 | + regmap_field_read(data->reg_als_it, &index); | |
| 350 | + else | |
| 351 | + regmap_field_read(data->reg_ps_it, &index); | |
| 352 | + *val = stk3310_it_table[index][0]; | |
| 353 | + *val2 = stk3310_it_table[index][1]; | |
| 354 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 355 | + case IIO_CHAN_INFO_SCALE: | |
| 356 | + if (chan->type == IIO_LIGHT) | |
| 357 | + regmap_field_read(data->reg_als_gain, &index); | |
| 358 | + else | |
| 359 | + regmap_field_read(data->reg_ps_gain, &index); | |
| 360 | + *val = stk3310_scale_table[index][0]; | |
| 361 | + *val2 = stk3310_scale_table[index][1]; | |
| 362 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 363 | + } | |
| 364 | + | |
| 365 | + return -EINVAL; | |
| 366 | +} | |
| 367 | + | |
| 368 | +static int stk3310_write_raw(struct iio_dev *indio_dev, | |
| 369 | + struct iio_chan_spec const *chan, | |
| 370 | + int val, int val2, long mask) | |
| 371 | +{ | |
| 372 | + int ret; | |
| 373 | + int index; | |
| 374 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 375 | + | |
| 376 | + switch (mask) { | |
| 377 | + case IIO_CHAN_INFO_INT_TIME: | |
| 378 | + index = stk3310_get_index(stk3310_it_table, | |
| 379 | + ARRAY_SIZE(stk3310_it_table), | |
| 380 | + val, val2); | |
| 381 | + if (index < 0) | |
| 382 | + return -EINVAL; | |
| 383 | + mutex_lock(&data->lock); | |
| 384 | + if (chan->type == IIO_LIGHT) | |
| 385 | + ret = regmap_field_write(data->reg_als_it, index); | |
| 386 | + else | |
| 387 | + ret = regmap_field_write(data->reg_ps_it, index); | |
| 388 | + if (ret < 0) | |
| 389 | + dev_err(&data->client->dev, | |
| 390 | + "sensor configuration failed\n"); | |
| 391 | + mutex_unlock(&data->lock); | |
| 392 | + return ret; | |
| 393 | + | |
| 394 | + case IIO_CHAN_INFO_SCALE: | |
| 395 | + index = stk3310_get_index(stk3310_scale_table, | |
| 396 | + ARRAY_SIZE(stk3310_scale_table), | |
| 397 | + val, val2); | |
| 398 | + if (index < 0) | |
| 399 | + return -EINVAL; | |
| 400 | + mutex_lock(&data->lock); | |
| 401 | + if (chan->type == IIO_LIGHT) | |
| 402 | + ret = regmap_field_write(data->reg_als_gain, index); | |
| 403 | + else | |
| 404 | + ret = regmap_field_write(data->reg_ps_gain, index); | |
| 405 | + if (ret < 0) | |
| 406 | + dev_err(&data->client->dev, | |
| 407 | + "sensor configuration failed\n"); | |
| 408 | + mutex_unlock(&data->lock); | |
| 409 | + return ret; | |
| 410 | + } | |
| 411 | + | |
| 412 | + return -EINVAL; | |
| 413 | +} | |
| 414 | + | |
| 415 | +static const struct iio_info stk3310_info = { | |
| 416 | + .driver_module = THIS_MODULE, | |
| 417 | + .read_raw = stk3310_read_raw, | |
| 418 | + .write_raw = stk3310_write_raw, | |
| 419 | + .attrs = &stk3310_attribute_group, | |
| 420 | + .read_event_value = stk3310_read_event, | |
| 421 | + .write_event_value = stk3310_write_event, | |
| 422 | + .read_event_config = stk3310_read_event_config, | |
| 423 | + .write_event_config = stk3310_write_event_config, | |
| 424 | +}; | |
| 425 | + | |
| 426 | +static int stk3310_set_state(struct stk3310_data *data, u8 state) | |
| 427 | +{ | |
| 428 | + int ret; | |
| 429 | + struct i2c_client *client = data->client; | |
| 430 | + | |
| 431 | + /* 3-bit state; 0b100 is not supported. */ | |
| 432 | + if (state > 7 || state == 4) | |
| 433 | + return -EINVAL; | |
| 434 | + | |
| 435 | + mutex_lock(&data->lock); | |
| 436 | + ret = regmap_field_write(data->reg_state, state); | |
| 437 | + if (ret < 0) { | |
| 438 | + dev_err(&client->dev, "failed to change sensor state\n"); | |
| 439 | + } else if (state != STK3310_STATE_STANDBY) { | |
| 440 | + /* Don't reset the 'enabled' flags if we're going in standby */ | |
| 441 | + data->ps_enabled = !!(state & 0x01); | |
| 442 | + data->als_enabled = !!(state & 0x02); | |
| 443 | + } | |
| 444 | + mutex_unlock(&data->lock); | |
| 445 | + | |
| 446 | + return ret; | |
| 447 | +} | |
| 448 | + | |
| 449 | +static int stk3310_init(struct iio_dev *indio_dev) | |
| 450 | +{ | |
| 451 | + int ret; | |
| 452 | + int chipid; | |
| 453 | + u8 state; | |
| 454 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 455 | + struct i2c_client *client = data->client; | |
| 456 | + | |
| 457 | + regmap_read(data->regmap, STK3310_REG_ID, &chipid); | |
| 458 | + if (chipid != STK3310_CHIP_ID_VAL && | |
| 459 | + chipid != STK3311_CHIP_ID_VAL) { | |
| 460 | + dev_err(&client->dev, "invalid chip id: 0x%x\n", chipid); | |
| 461 | + return -ENODEV; | |
| 462 | + } | |
| 463 | + | |
| 464 | + state = STK3310_STATE_EN_ALS | STK3310_STATE_EN_PS; | |
| 465 | + ret = stk3310_set_state(data, state); | |
| 466 | + if (ret < 0) { | |
| 467 | + dev_err(&client->dev, "failed to enable sensor"); | |
| 468 | + return ret; | |
| 469 | + } | |
| 470 | + | |
| 471 | + /* Enable PS interrupts */ | |
| 472 | + ret = regmap_field_write(data->reg_int_ps, STK3310_PSINT_EN); | |
| 473 | + if (ret < 0) | |
| 474 | + dev_err(&client->dev, "failed to enable interrupts!\n"); | |
| 475 | + | |
| 476 | + return ret; | |
| 477 | +} | |
| 478 | + | |
| 479 | +static int stk3310_gpio_probe(struct i2c_client *client) | |
| 480 | +{ | |
| 481 | + struct device *dev; | |
| 482 | + struct gpio_desc *gpio; | |
| 483 | + int ret; | |
| 484 | + | |
| 485 | + if (!client) | |
| 486 | + return -EINVAL; | |
| 487 | + | |
| 488 | + dev = &client->dev; | |
| 489 | + | |
| 490 | + /* gpio interrupt pin */ | |
| 491 | + gpio = devm_gpiod_get_index(dev, STK3310_GPIO, 0); | |
| 492 | + if (IS_ERR(gpio)) { | |
| 493 | + dev_err(dev, "acpi gpio get index failed\n"); | |
| 494 | + return PTR_ERR(gpio); | |
| 495 | + } | |
| 496 | + | |
| 497 | + ret = gpiod_direction_input(gpio); | |
| 498 | + if (ret) | |
| 499 | + return ret; | |
| 500 | + | |
| 501 | + ret = gpiod_to_irq(gpio); | |
| 502 | + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | |
| 503 | + | |
| 504 | + return ret; | |
| 505 | +} | |
| 506 | + | |
| 507 | +static bool stk3310_is_volatile_reg(struct device *dev, unsigned int reg) | |
| 508 | +{ | |
| 509 | + switch (reg) { | |
| 510 | + case STK3310_REG_ALS_DATA_MSB: | |
| 511 | + case STK3310_REG_ALS_DATA_LSB: | |
| 512 | + case STK3310_REG_PS_DATA_LSB: | |
| 513 | + case STK3310_REG_PS_DATA_MSB: | |
| 514 | + case STK3310_REG_FLAG: | |
| 515 | + return true; | |
| 516 | + default: | |
| 517 | + return false; | |
| 518 | + } | |
| 519 | +} | |
| 520 | + | |
| 521 | +static struct regmap_config stk3310_regmap_config = { | |
| 522 | + .name = STK3310_REGMAP_NAME, | |
| 523 | + .reg_bits = 8, | |
| 524 | + .val_bits = 8, | |
| 525 | + .max_register = STK3310_MAX_REG, | |
| 526 | + .cache_type = REGCACHE_RBTREE, | |
| 527 | + .volatile_reg = stk3310_is_volatile_reg, | |
| 528 | +}; | |
| 529 | + | |
| 530 | +static int stk3310_regmap_init(struct stk3310_data *data) | |
| 531 | +{ | |
| 532 | + struct regmap *regmap; | |
| 533 | + struct i2c_client *client; | |
| 534 | + | |
| 535 | + client = data->client; | |
| 536 | + regmap = devm_regmap_init_i2c(client, &stk3310_regmap_config); | |
| 537 | + if (IS_ERR(regmap)) { | |
| 538 | + dev_err(&client->dev, "regmap initialization failed.\n"); | |
| 539 | + return PTR_ERR(regmap); | |
| 540 | + } | |
| 541 | + data->regmap = regmap; | |
| 542 | + | |
| 543 | + STK3310_REGFIELD(state); | |
| 544 | + STK3310_REGFIELD(als_gain); | |
| 545 | + STK3310_REGFIELD(ps_gain); | |
| 546 | + STK3310_REGFIELD(als_it); | |
| 547 | + STK3310_REGFIELD(ps_it); | |
| 548 | + STK3310_REGFIELD(int_ps); | |
| 549 | + STK3310_REGFIELD(flag_psint); | |
| 550 | + STK3310_REGFIELD(flag_nf); | |
| 551 | + | |
| 552 | + return 0; | |
| 553 | +} | |
| 554 | + | |
| 555 | +static irqreturn_t stk3310_irq_handler(int irq, void *private) | |
| 556 | +{ | |
| 557 | + struct iio_dev *indio_dev = private; | |
| 558 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 559 | + | |
| 560 | + data->timestamp = iio_get_time_ns(); | |
| 561 | + | |
| 562 | + return IRQ_WAKE_THREAD; | |
| 563 | +} | |
| 564 | + | |
| 565 | +static irqreturn_t stk3310_irq_event_handler(int irq, void *private) | |
| 566 | +{ | |
| 567 | + int ret; | |
| 568 | + unsigned int dir; | |
| 569 | + u64 event; | |
| 570 | + | |
| 571 | + struct iio_dev *indio_dev = private; | |
| 572 | + struct stk3310_data *data = iio_priv(indio_dev); | |
| 573 | + | |
| 574 | + /* Read FLAG_NF to figure out what threshold has been met. */ | |
| 575 | + mutex_lock(&data->lock); | |
| 576 | + ret = regmap_field_read(data->reg_flag_nf, &dir); | |
| 577 | + if (ret < 0) { | |
| 578 | + dev_err(&data->client->dev, "register read failed\n"); | |
| 579 | + mutex_unlock(&data->lock); | |
| 580 | + return ret; | |
| 581 | + } | |
| 582 | + event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, | |
| 583 | + IIO_EV_TYPE_THRESH, | |
| 584 | + (dir ? IIO_EV_DIR_RISING : | |
| 585 | + IIO_EV_DIR_FALLING)); | |
| 586 | + iio_push_event(indio_dev, event, data->timestamp); | |
| 587 | + | |
| 588 | + /* Reset the interrupt flag */ | |
| 589 | + ret = regmap_field_write(data->reg_flag_psint, 0); | |
| 590 | + if (ret < 0) | |
| 591 | + dev_err(&data->client->dev, "failed to reset interrupts\n"); | |
| 592 | + mutex_unlock(&data->lock); | |
| 593 | + | |
| 594 | + return IRQ_HANDLED; | |
| 595 | +} | |
| 596 | + | |
| 597 | +static int stk3310_probe(struct i2c_client *client, | |
| 598 | + const struct i2c_device_id *id) | |
| 599 | +{ | |
| 600 | + int ret; | |
| 601 | + struct iio_dev *indio_dev; | |
| 602 | + struct stk3310_data *data; | |
| 603 | + | |
| 604 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 605 | + if (!indio_dev) { | |
| 606 | + dev_err(&client->dev, "iio allocation failed!\n"); | |
| 607 | + return -ENOMEM; | |
| 608 | + } | |
| 609 | + | |
| 610 | + data = iio_priv(indio_dev); | |
| 611 | + data->client = client; | |
| 612 | + i2c_set_clientdata(client, indio_dev); | |
| 613 | + mutex_init(&data->lock); | |
| 614 | + | |
| 615 | + ret = stk3310_regmap_init(data); | |
| 616 | + if (ret < 0) | |
| 617 | + return ret; | |
| 618 | + | |
| 619 | + indio_dev->dev.parent = &client->dev; | |
| 620 | + indio_dev->info = &stk3310_info; | |
| 621 | + indio_dev->name = STK3310_DRIVER_NAME; | |
| 622 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 623 | + indio_dev->channels = stk3310_channels; | |
| 624 | + indio_dev->num_channels = ARRAY_SIZE(stk3310_channels); | |
| 625 | + | |
| 626 | + ret = stk3310_init(indio_dev); | |
| 627 | + if (ret < 0) | |
| 628 | + return ret; | |
| 629 | + | |
| 630 | + ret = iio_device_register(indio_dev); | |
| 631 | + if (ret < 0) { | |
| 632 | + dev_err(&client->dev, "device_register failed\n"); | |
| 633 | + stk3310_set_state(data, STK3310_STATE_STANDBY); | |
| 634 | + } | |
| 635 | + | |
| 636 | + if (client->irq <= 0) | |
| 637 | + client->irq = stk3310_gpio_probe(client); | |
| 638 | + | |
| 639 | + if (client->irq >= 0) { | |
| 640 | + ret = devm_request_threaded_irq(&client->dev, client->irq, | |
| 641 | + stk3310_irq_handler, | |
| 642 | + stk3310_irq_event_handler, | |
| 643 | + IRQF_TRIGGER_FALLING | | |
| 644 | + IRQF_ONESHOT, | |
| 645 | + STK3310_EVENT, indio_dev); | |
| 646 | + if (ret < 0) | |
| 647 | + dev_err(&client->dev, "request irq %d failed\n", | |
| 648 | + client->irq); | |
| 649 | + } | |
| 650 | + | |
| 651 | + return ret; | |
| 652 | +} | |
| 653 | + | |
| 654 | +static int stk3310_remove(struct i2c_client *client) | |
| 655 | +{ | |
| 656 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 657 | + | |
| 658 | + iio_device_unregister(indio_dev); | |
| 659 | + return stk3310_set_state(iio_priv(indio_dev), STK3310_STATE_STANDBY); | |
| 660 | +} | |
| 661 | + | |
| 662 | +#ifdef CONFIG_PM_SLEEP | |
| 663 | +static int stk3310_suspend(struct device *dev) | |
| 664 | +{ | |
| 665 | + struct stk3310_data *data; | |
| 666 | + | |
| 667 | + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | |
| 668 | + | |
| 669 | + return stk3310_set_state(data, STK3310_STATE_STANDBY); | |
| 670 | +} | |
| 671 | + | |
| 672 | +static int stk3310_resume(struct device *dev) | |
| 673 | +{ | |
| 674 | + int state = 0; | |
| 675 | + struct stk3310_data *data; | |
| 676 | + | |
| 677 | + data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | |
| 678 | + if (data->ps_enabled) | |
| 679 | + state |= STK3310_STATE_EN_PS; | |
| 680 | + if (data->als_enabled) | |
| 681 | + state |= STK3310_STATE_EN_ALS; | |
| 682 | + | |
| 683 | + return stk3310_set_state(data, state); | |
| 684 | +} | |
| 685 | + | |
| 686 | +static SIMPLE_DEV_PM_OPS(stk3310_pm_ops, stk3310_suspend, stk3310_resume); | |
| 687 | + | |
| 688 | +#define STK3310_PM_OPS (&stk3310_pm_ops) | |
| 689 | +#else | |
| 690 | +#define STK3310_PM_OPS NULL | |
| 691 | +#endif | |
| 692 | + | |
| 693 | +static const struct i2c_device_id stk3310_i2c_id[] = { | |
| 694 | + {"STK3310", 0}, | |
| 695 | + {"STK3311", 0}, | |
| 696 | + {} | |
| 697 | +}; | |
| 698 | + | |
| 699 | +static const struct acpi_device_id stk3310_acpi_id[] = { | |
| 700 | + {"STK3310", 0}, | |
| 701 | + {"STK3311", 0}, | |
| 702 | + {} | |
| 703 | +}; | |
| 704 | + | |
| 705 | +MODULE_DEVICE_TABLE(acpi, stk3310_acpi_id); | |
| 706 | + | |
| 707 | +static struct i2c_driver stk3310_driver = { | |
| 708 | + .driver = { | |
| 709 | + .name = "stk3310", | |
| 710 | + .pm = STK3310_PM_OPS, | |
| 711 | + .acpi_match_table = ACPI_PTR(stk3310_acpi_id), | |
| 712 | + }, | |
| 713 | + .probe = stk3310_probe, | |
| 714 | + .remove = stk3310_remove, | |
| 715 | + .id_table = stk3310_i2c_id, | |
| 716 | +}; | |
| 717 | + | |
| 718 | +module_i2c_driver(stk3310_driver); | |
| 719 | + | |
| 720 | +MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>"); | |
| 721 | +MODULE_DESCRIPTION("STK3310 Ambient Light and Proximity Sensor driver"); | |
| 722 | +MODULE_LICENSE("GPL v2"); | |
| @@ -240,7 +240,7 @@ static int tsl2563_read_id(struct tsl2563_chip *chip, u8 *id) · 239 unmodified lines | ||
| 240 | 240 | * convert between normalized values and HW values obtained using given |
| 241 | 241 | * timing and gain settings. |
| 242 | 242 | */ |
| 243 | −static int adc_shiftbits(u8 timing) | |
| 243 | +static int tsl2563_adc_shiftbits(u8 timing) | |
| 244 | 244 | { |
| 245 | 245 | int shift = 0; |
| 246 | 246 | |
| @@ -263,9 +263,9 @@ static int adc_shiftbits(u8 timing) · 16 unmodified lines | ||
| 263 | 263 | } |
| 264 | 264 | |
| 265 | 265 | /* Convert a HW ADC value to normalized scale. */ |
| 266 | −static u32 normalize_adc(u16 adc, u8 timing) | |
| 266 | +static u32 tsl2563_normalize_adc(u16 adc, u8 timing) | |
| 267 | 267 | { |
| 268 | − return adc << adc_shiftbits(timing); | |
| 268 | + return adc << tsl2563_adc_shiftbits(timing); | |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | 271 | static void tsl2563_wait_adc(struct tsl2563_chip *chip) |
| @@ -350,8 +350,8 @@ static int tsl2563_get_adc(struct tsl2563_chip *chip) · 78 unmodified lines | ||
| 350 | 350 | retry = tsl2563_adjust_gainlevel(chip, adc0); |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | − chip->data0 = normalize_adc(adc0, chip->gainlevel->gaintime); | |
| 354 | − chip->data1 = normalize_adc(adc1, chip->gainlevel->gaintime); | |
| 353 | + chip->data0 = tsl2563_normalize_adc(adc0, chip->gainlevel->gaintime); | |
| 354 | + chip->data1 = tsl2563_normalize_adc(adc1, chip->gainlevel->gaintime); | |
| 355 | 355 | |
| 356 | 356 | if (!chip->int_enabled) |
| 357 | 357 | schedule_delayed_work(&chip->poweroff_work, 5 * HZ); |
| @@ -361,13 +361,13 @@ out: · 3 unmodified lines | ||
| 361 | 361 | return ret; |
| 362 | 362 | } |
| 363 | 363 | |
| 364 | −static inline int calib_to_sysfs(u32 calib) | |
| 364 | +static inline int tsl2563_calib_to_sysfs(u32 calib) | |
| 365 | 365 | { |
| 366 | 366 | return (int) (((calib * CALIB_BASE_SYSFS) + |
| 367 | 367 | CALIB_FRAC_HALF) >> CALIB_FRAC_BITS); |
| 368 | 368 | } |
| 369 | 369 | |
| 370 | −static inline u32 calib_from_sysfs(int value) | |
| 370 | +static inline u32 tsl2563_calib_from_sysfs(int value) | |
| 371 | 371 | { |
| 372 | 372 | return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS; |
| 373 | 373 | } |
| @@ -426,7 +426,7 @@ static const struct tsl2563_lux_coeff lux_table[] = { · 52 unmodified lines | ||
| 426 | 426 | }; |
| 427 | 427 | |
| 428 | 428 | /* Convert normalized, scaled ADC values to lux. */ |
| 429 | −static unsigned int adc_to_lux(u32 adc0, u32 adc1) | |
| 429 | +static unsigned int tsl2563_adc_to_lux(u32 adc0, u32 adc1) | |
| 430 | 430 | { |
| 431 | 431 | const struct tsl2563_lux_coeff *lp = lux_table; |
| 432 | 432 | unsigned long ratio, lux, ch0 = adc0, ch1 = adc1; |
| @@ -442,7 +442,7 @@ static unsigned int adc_to_lux(u32 adc0, u32 adc1) · 9 unmodified lines | ||
| 442 | 442 | } |
| 443 | 443 | |
| 444 | 444 | /* Apply calibration coefficient to ADC count. */ |
| 445 | −static u32 calib_adc(u32 adc, u32 calib) | |
| 445 | +static u32 tsl2563_calib_adc(u32 adc, u32 calib) | |
| 446 | 446 | { |
| 447 | 447 | unsigned long scaled = adc; |
| 448 | 448 | |
| @@ -463,9 +463,9 @@ static int tsl2563_write_raw(struct iio_dev *indio_dev, · 14 unmodified lines | ||
| 463 | 463 | if (mask != IIO_CHAN_INFO_CALIBSCALE) |
| 464 | 464 | return -EINVAL; |
| 465 | 465 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) |
| 466 | − chip->calib0 = calib_from_sysfs(val); | |
| 466 | + chip->calib0 = tsl2563_calib_from_sysfs(val); | |
| 467 | 467 | else if (chan->channel2 == IIO_MOD_LIGHT_IR) |
| 468 | − chip->calib1 = calib_from_sysfs(val); | |
| 468 | + chip->calib1 = tsl2563_calib_from_sysfs(val); | |
| 469 | 469 | else |
| 470 | 470 | return -EINVAL; |
| 471 | 471 | |
| @@ -491,11 +491,11 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, · 19 unmodified lines | ||
| 491 | 491 | ret = tsl2563_get_adc(chip); |
| 492 | 492 | if (ret) |
| 493 | 493 | goto error_ret; |
| 494 | − calib0 = calib_adc(chip->data0, chip->calib0) * | |
| 494 | + calib0 = tsl2563_calib_adc(chip->data0, chip->calib0) * | |
| 495 | 495 | chip->cover_comp_gain; |
| 496 | − calib1 = calib_adc(chip->data1, chip->calib1) * | |
| 496 | + calib1 = tsl2563_calib_adc(chip->data1, chip->calib1) * | |
| 497 | 497 | chip->cover_comp_gain; |
| 498 | − *val = adc_to_lux(calib0, calib1); | |
| 498 | + *val = tsl2563_adc_to_lux(calib0, calib1); | |
| 499 | 499 | ret = IIO_VAL_INT; |
| 500 | 500 | break; |
| 501 | 501 | case IIO_INTENSITY: |
| @@ -515,9 +515,9 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, · 13 unmodified lines | ||
| 515 | 515 | |
| 516 | 516 | case IIO_CHAN_INFO_CALIBSCALE: |
| 517 | 517 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) |
| 518 | − *val = calib_to_sysfs(chip->calib0); | |
| 518 | + *val = tsl2563_calib_to_sysfs(chip->calib0); | |
| 519 | 519 | else |
| 520 | − *val = calib_to_sysfs(chip->calib1); | |
| 520 | + *val = tsl2563_calib_to_sysfs(chip->calib1); | |
| 521 | 521 | ret = IIO_VAL_INT; |
| 522 | 522 | break; |
| 523 | 523 | default: |
| @@ -750,8 +750,8 @@ static int tsl2563_probe(struct i2c_client *client, · 226 unmodified lines | ||
| 750 | 750 | chip->high_thres = 0xffff; |
| 751 | 751 | chip->gainlevel = tsl2563_gainlevel_table; |
| 752 | 752 | chip->intr = TSL2563_INT_PERSIST(4); |
| 753 | − chip->calib0 = calib_from_sysfs(CALIB_BASE_SYSFS); | |
| 754 | − chip->calib1 = calib_from_sysfs(CALIB_BASE_SYSFS); | |
| 753 | + chip->calib0 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); | |
| 754 | + chip->calib1 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); | |
| 755 | 755 | |
| 756 | 756 | if (pdata) |
| 757 | 757 | chip->cover_comp_gain = pdata->cover_comp_gain; |
| @@ -24,12 +24,12 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | #define TSL4531_DRV_NAME "tsl4531" |
| 26 | 26 | |
| 27 | −#define TCS3472_COMMAND BIT(7) | |
| 27 | +#define TSL4531_COMMAND BIT(7) | |
| 28 | 28 | |
| 29 | −#define TSL4531_CONTROL (TCS3472_COMMAND | 0x00) | |
| 30 | −#define TSL4531_CONFIG (TCS3472_COMMAND | 0x01) | |
| 31 | −#define TSL4531_DATA (TCS3472_COMMAND | 0x04) | |
| 32 | −#define TSL4531_ID (TCS3472_COMMAND | 0x0a) | |
| 29 | +#define TSL4531_CONTROL (TSL4531_COMMAND | 0x00) | |
| 30 | +#define TSL4531_CONFIG (TSL4531_COMMAND | 0x01) | |
| 31 | +#define TSL4531_DATA (TSL4531_COMMAND | 0x04) | |
| 32 | +#define TSL4531_ID (TSL4531_COMMAND | 0x0a) | |
| 33 | 33 | |
| 34 | 34 | /* operating modes in control register */ |
| 35 | 35 | #define TSL4531_MODE_POWERDOWN 0x00 |
| @@ -8,7 +8,7 @@ menu "Magnetometer sensors" · 7 unmodified lines | ||
| 8 | 8 | config AK8975 |
| 9 | 9 | tristate "Asahi Kasei AK 3-Axis Magnetometer" |
| 10 | 10 | depends on I2C |
| 11 | − depends on GPIOLIB | |
| 11 | + depends on GPIOLIB || COMPILE_TEST | |
| 12 | 12 | help |
| 13 | 13 | Say yes here to build support for Asahi Kasei AK8975, AK8963, |
| 14 | 14 | AK09911 or AK09912 3-Axis Magnetometer. |
| @@ -19,7 +19,7 @@ config AK8975 · 4 unmodified lines | ||
| 19 | 19 | config AK09911 |
| 20 | 20 | tristate "Asahi Kasei AK09911 3-axis Compass" |
| 21 | 21 | depends on I2C |
| 22 | − depends on GPIOLIB | |
| 22 | + depends on GPIOLIB || COMPILE_TEST | |
| 23 | 23 | select AK8975 |
| 24 | 24 | help |
| 25 | 25 | Deprecated: AK09911 is now supported by AK8975 driver. |
| @@ -47,6 +47,17 @@ config HID_SENSOR_MAGNETOMETER_3D · 21 unmodified lines | ||
| 47 | 47 | Say yes here to build support for the HID SENSOR |
| 48 | 48 | Magnetometer 3D. |
| 49 | 49 | |
| 50 | +config MMC35240 | |
| 51 | + tristate "MEMSIC MMC35240 3-axis magnetic sensor" | |
| 52 | + select REGMAP_I2C | |
| 53 | + depends on I2C | |
| 54 | + help | |
| 55 | + Say yes here to build support for the MEMSIC MMC35240 3-axis | |
| 56 | + magnetic sensor. | |
| 57 | + | |
| 58 | + To compile this driver as a module, choose M here: the module | |
| 59 | + will be called mmc35240. | |
| 60 | + | |
| 50 | 61 | config IIO_ST_MAGN_3AXIS |
| 51 | 62 | tristate "STMicroelectronics magnetometers 3-Axis Driver" |
| 52 | 63 | depends on (I2C || SPI_MASTER) && SYSFS |
| @@ -76,4 +87,18 @@ config IIO_ST_MAGN_SPI_3AXIS · 23 unmodified lines | ||
| 76 | 87 | depends on IIO_ST_MAGN_3AXIS |
| 77 | 88 | depends on IIO_ST_SENSORS_SPI |
| 78 | 89 | |
| 90 | +config BMC150_MAGN | |
| 91 | + tristate "Bosch BMC150 Magnetometer Driver" | |
| 92 | + depends on I2C | |
| 93 | + select IIO_BUFFER | |
| 94 | + select IIO_TRIGGERED_BUFFER | |
| 95 | + help | |
| 96 | + Say yes here to build support for the BMC150 magnetometer. | |
| 97 | + | |
| 98 | + Currently this only supports the device via an i2c interface. | |
| 99 | + | |
| 100 | + This is a combo module with both accelerometer and magnetometer. | |
| 101 | + This driver is only implementing magnetometer part, which has | |
| 102 | + its own address and register map. | |
| 103 | + | |
| 79 | 104 | endmenu |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | obj-$(CONFIG_AK8975) += ak8975.o |
| 7 | 7 | obj-$(CONFIG_MAG3110) += mag3110.o |
| 8 | 8 | obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o |
| 9 | +obj-$(CONFIG_MMC35240) += mmc35240.o | |
| 9 | 10 | |
| 10 | 11 | obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o |
| 11 | 12 | st_magn-y := st_magn_core.o |
| @@ -13,3 +14,5 @@ st_magn-$(CONFIG_IIO_BUFFER) += st_magn_buffer.o · 1 unmodified line | ||
| 13 | 14 | |
| 14 | 15 | obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o |
| 15 | 16 | obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o |
| 17 | + | |
| 18 | +obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o | |
| @@ -0,0 +1,1109 @@ | ||
| 1 | +/* | |
| 2 | + * Bosch BMC150 three-axis magnetic field sensor driver | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015, Intel Corporation. | |
| 5 | + * | |
| 6 | + * This code is based on bmm050_api.c authored by contact@bosch.sensortec.com: | |
| 7 | + * | |
| 8 | + * (C) Copyright 2011~2014 Bosch Sensortec GmbH All Rights Reserved | |
| 9 | + * | |
| 10 | + * This program is free software; you can redistribute it and/or modify it | |
| 11 | + * under the terms and conditions of the GNU General Public License, | |
| 12 | + * version 2, as published by the Free Software Foundation. | |
| 13 | + * | |
| 14 | + * This program is distributed in the hope it will be useful, but WITHOUT | |
| 15 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 17 | + * more details. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <linux/module.h> | |
| 21 | +#include <linux/i2c.h> | |
| 22 | +#include <linux/interrupt.h> | |
| 23 | +#include <linux/delay.h> | |
| 24 | +#include <linux/slab.h> | |
| 25 | +#include <linux/acpi.h> | |
| 26 | +#include <linux/gpio/consumer.h> | |
| 27 | +#include <linux/pm.h> | |
| 28 | +#include <linux/pm_runtime.h> | |
| 29 | +#include <linux/iio/iio.h> | |
| 30 | +#include <linux/iio/sysfs.h> | |
| 31 | +#include <linux/iio/buffer.h> | |
| 32 | +#include <linux/iio/events.h> | |
| 33 | +#include <linux/iio/trigger.h> | |
| 34 | +#include <linux/iio/trigger_consumer.h> | |
| 35 | +#include <linux/iio/triggered_buffer.h> | |
| 36 | +#include <linux/regmap.h> | |
| 37 | + | |
| 38 | +#define BMC150_MAGN_DRV_NAME "bmc150_magn" | |
| 39 | +#define BMC150_MAGN_IRQ_NAME "bmc150_magn_event" | |
| 40 | +#define BMC150_MAGN_GPIO_INT "interrupt" | |
| 41 | + | |
| 42 | +#define BMC150_MAGN_REG_CHIP_ID 0x40 | |
| 43 | +#define BMC150_MAGN_CHIP_ID_VAL 0x32 | |
| 44 | + | |
| 45 | +#define BMC150_MAGN_REG_X_L 0x42 | |
| 46 | +#define BMC150_MAGN_REG_X_M 0x43 | |
| 47 | +#define BMC150_MAGN_REG_Y_L 0x44 | |
| 48 | +#define BMC150_MAGN_REG_Y_M 0x45 | |
| 49 | +#define BMC150_MAGN_SHIFT_XY_L 3 | |
| 50 | +#define BMC150_MAGN_REG_Z_L 0x46 | |
| 51 | +#define BMC150_MAGN_REG_Z_M 0x47 | |
| 52 | +#define BMC150_MAGN_SHIFT_Z_L 1 | |
| 53 | +#define BMC150_MAGN_REG_RHALL_L 0x48 | |
| 54 | +#define BMC150_MAGN_REG_RHALL_M 0x49 | |
| 55 | +#define BMC150_MAGN_SHIFT_RHALL_L 2 | |
| 56 | + | |
| 57 | +#define BMC150_MAGN_REG_INT_STATUS 0x4A | |
| 58 | + | |
| 59 | +#define BMC150_MAGN_REG_POWER 0x4B | |
| 60 | +#define BMC150_MAGN_MASK_POWER_CTL BIT(0) | |
| 61 | + | |
| 62 | +#define BMC150_MAGN_REG_OPMODE_ODR 0x4C | |
| 63 | +#define BMC150_MAGN_MASK_OPMODE GENMASK(2, 1) | |
| 64 | +#define BMC150_MAGN_SHIFT_OPMODE 1 | |
| 65 | +#define BMC150_MAGN_MODE_NORMAL 0x00 | |
| 66 | +#define BMC150_MAGN_MODE_FORCED 0x01 | |
| 67 | +#define BMC150_MAGN_MODE_SLEEP 0x03 | |
| 68 | +#define BMC150_MAGN_MASK_ODR GENMASK(5, 3) | |
| 69 | +#define BMC150_MAGN_SHIFT_ODR 3 | |
| 70 | + | |
| 71 | +#define BMC150_MAGN_REG_INT 0x4D | |
| 72 | + | |
| 73 | +#define BMC150_MAGN_REG_INT_DRDY 0x4E | |
| 74 | +#define BMC150_MAGN_MASK_DRDY_EN BIT(7) | |
| 75 | +#define BMC150_MAGN_SHIFT_DRDY_EN 7 | |
| 76 | +#define BMC150_MAGN_MASK_DRDY_INT3 BIT(6) | |
| 77 | +#define BMC150_MAGN_MASK_DRDY_Z_EN BIT(5) | |
| 78 | +#define BMC150_MAGN_MASK_DRDY_Y_EN BIT(4) | |
| 79 | +#define BMC150_MAGN_MASK_DRDY_X_EN BIT(3) | |
| 80 | +#define BMC150_MAGN_MASK_DRDY_DR_POLARITY BIT(2) | |
| 81 | +#define BMC150_MAGN_MASK_DRDY_LATCHING BIT(1) | |
| 82 | +#define BMC150_MAGN_MASK_DRDY_INT3_POLARITY BIT(0) | |
| 83 | + | |
| 84 | +#define BMC150_MAGN_REG_LOW_THRESH 0x4F | |
| 85 | +#define BMC150_MAGN_REG_HIGH_THRESH 0x50 | |
| 86 | +#define BMC150_MAGN_REG_REP_XY 0x51 | |
| 87 | +#define BMC150_MAGN_REG_REP_Z 0x52 | |
| 88 | + | |
| 89 | +#define BMC150_MAGN_REG_TRIM_START 0x5D | |
| 90 | +#define BMC150_MAGN_REG_TRIM_END 0x71 | |
| 91 | + | |
| 92 | +#define BMC150_MAGN_XY_OVERFLOW_VAL -4096 | |
| 93 | +#define BMC150_MAGN_Z_OVERFLOW_VAL -16384 | |
| 94 | + | |
| 95 | +/* Time from SUSPEND to SLEEP */ | |
| 96 | +#define BMC150_MAGN_START_UP_TIME_MS 3 | |
| 97 | + | |
| 98 | +#define BMC150_MAGN_AUTO_SUSPEND_DELAY_MS 2000 | |
| 99 | + | |
| 100 | +#define BMC150_MAGN_REGVAL_TO_REPXY(regval) (((regval) * 2) + 1) | |
| 101 | +#define BMC150_MAGN_REGVAL_TO_REPZ(regval) ((regval) + 1) | |
| 102 | +#define BMC150_MAGN_REPXY_TO_REGVAL(rep) (((rep) - 1) / 2) | |
| 103 | +#define BMC150_MAGN_REPZ_TO_REGVAL(rep) ((rep) - 1) | |
| 104 | + | |
| 105 | +enum bmc150_magn_axis { | |
| 106 | + AXIS_X, | |
| 107 | + AXIS_Y, | |
| 108 | + AXIS_Z, | |
| 109 | + RHALL, | |
| 110 | + AXIS_XYZ_MAX = RHALL, | |
| 111 | + AXIS_XYZR_MAX, | |
| 112 | +}; | |
| 113 | + | |
| 114 | +enum bmc150_magn_power_modes { | |
| 115 | + BMC150_MAGN_POWER_MODE_SUSPEND, | |
| 116 | + BMC150_MAGN_POWER_MODE_SLEEP, | |
| 117 | + BMC150_MAGN_POWER_MODE_NORMAL, | |
| 118 | +}; | |
| 119 | + | |
| 120 | +struct bmc150_magn_trim_regs { | |
| 121 | + s8 x1; | |
| 122 | + s8 y1; | |
| 123 | + __le16 reserved1; | |
| 124 | + u8 reserved2; | |
| 125 | + __le16 z4; | |
| 126 | + s8 x2; | |
| 127 | + s8 y2; | |
| 128 | + __le16 reserved3; | |
| 129 | + __le16 z2; | |
| 130 | + __le16 z1; | |
| 131 | + __le16 xyz1; | |
| 132 | + __le16 z3; | |
| 133 | + s8 xy2; | |
| 134 | + u8 xy1; | |
| 135 | +} __packed; | |
| 136 | + | |
| 137 | +struct bmc150_magn_data { | |
| 138 | + struct i2c_client *client; | |
| 139 | + /* | |
| 140 | + * 1. Protect this structure. | |
| 141 | + * 2. Serialize sequences that power on/off the device and access HW. | |
| 142 | + */ | |
| 143 | + struct mutex mutex; | |
| 144 | + struct regmap *regmap; | |
| 145 | + /* 4 x 32 bits for x, y z, 4 bytes align, 64 bits timestamp */ | |
| 146 | + s32 buffer[6]; | |
| 147 | + struct iio_trigger *dready_trig; | |
| 148 | + bool dready_trigger_on; | |
| 149 | + int max_odr; | |
| 150 | +}; | |
| 151 | + | |
| 152 | +static const struct { | |
| 153 | + int freq; | |
| 154 | + u8 reg_val; | |
| 155 | +} bmc150_magn_samp_freq_table[] = { {2, 0x01}, | |
| 156 | + {6, 0x02}, | |
| 157 | + {8, 0x03}, | |
| 158 | + {10, 0x00}, | |
| 159 | + {15, 0x04}, | |
| 160 | + {20, 0x05}, | |
| 161 | + {25, 0x06}, | |
| 162 | + {30, 0x07} }; | |
| 163 | + | |
| 164 | +enum bmc150_magn_presets { | |
| 165 | + LOW_POWER_PRESET, | |
| 166 | + REGULAR_PRESET, | |
| 167 | + ENHANCED_REGULAR_PRESET, | |
| 168 | + HIGH_ACCURACY_PRESET | |
| 169 | +}; | |
| 170 | + | |
| 171 | +static const struct bmc150_magn_preset { | |
| 172 | + u8 rep_xy; | |
| 173 | + u8 rep_z; | |
| 174 | + u8 odr; | |
| 175 | +} bmc150_magn_presets_table[] = { | |
| 176 | + [LOW_POWER_PRESET] = {3, 3, 10}, | |
| 177 | + [REGULAR_PRESET] = {9, 15, 10}, | |
| 178 | + [ENHANCED_REGULAR_PRESET] = {15, 27, 10}, | |
| 179 | + [HIGH_ACCURACY_PRESET] = {47, 83, 20}, | |
| 180 | +}; | |
| 181 | + | |
| 182 | +#define BMC150_MAGN_DEFAULT_PRESET REGULAR_PRESET | |
| 183 | + | |
| 184 | +static bool bmc150_magn_is_writeable_reg(struct device *dev, unsigned int reg) | |
| 185 | +{ | |
| 186 | + switch (reg) { | |
| 187 | + case BMC150_MAGN_REG_POWER: | |
| 188 | + case BMC150_MAGN_REG_OPMODE_ODR: | |
| 189 | + case BMC150_MAGN_REG_INT: | |
| 190 | + case BMC150_MAGN_REG_INT_DRDY: | |
| 191 | + case BMC150_MAGN_REG_LOW_THRESH: | |
| 192 | + case BMC150_MAGN_REG_HIGH_THRESH: | |
| 193 | + case BMC150_MAGN_REG_REP_XY: | |
| 194 | + case BMC150_MAGN_REG_REP_Z: | |
| 195 | + return true; | |
| 196 | + default: | |
| 197 | + return false; | |
| 198 | + }; | |
| 199 | +} | |
| 200 | + | |
| 201 | +static bool bmc150_magn_is_volatile_reg(struct device *dev, unsigned int reg) | |
| 202 | +{ | |
| 203 | + switch (reg) { | |
| 204 | + case BMC150_MAGN_REG_X_L: | |
| 205 | + case BMC150_MAGN_REG_X_M: | |
| 206 | + case BMC150_MAGN_REG_Y_L: | |
| 207 | + case BMC150_MAGN_REG_Y_M: | |
| 208 | + case BMC150_MAGN_REG_Z_L: | |
| 209 | + case BMC150_MAGN_REG_Z_M: | |
| 210 | + case BMC150_MAGN_REG_RHALL_L: | |
| 211 | + case BMC150_MAGN_REG_RHALL_M: | |
| 212 | + case BMC150_MAGN_REG_INT_STATUS: | |
| 213 | + return true; | |
| 214 | + default: | |
| 215 | + return false; | |
| 216 | + } | |
| 217 | +} | |
| 218 | + | |
| 219 | +static const struct regmap_config bmc150_magn_regmap_config = { | |
| 220 | + .reg_bits = 8, | |
| 221 | + .val_bits = 8, | |
| 222 | + | |
| 223 | + .max_register = BMC150_MAGN_REG_TRIM_END, | |
| 224 | + .cache_type = REGCACHE_RBTREE, | |
| 225 | + | |
| 226 | + .writeable_reg = bmc150_magn_is_writeable_reg, | |
| 227 | + .volatile_reg = bmc150_magn_is_volatile_reg, | |
| 228 | +}; | |
| 229 | + | |
| 230 | +static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data, | |
| 231 | + enum bmc150_magn_power_modes mode, | |
| 232 | + bool state) | |
| 233 | +{ | |
| 234 | + int ret; | |
| 235 | + | |
| 236 | + switch (mode) { | |
| 237 | + case BMC150_MAGN_POWER_MODE_SUSPEND: | |
| 238 | + ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_POWER, | |
| 239 | + BMC150_MAGN_MASK_POWER_CTL, !state); | |
| 240 | + if (ret < 0) | |
| 241 | + return ret; | |
| 242 | + usleep_range(BMC150_MAGN_START_UP_TIME_MS * 1000, 20000); | |
| 243 | + return 0; | |
| 244 | + case BMC150_MAGN_POWER_MODE_SLEEP: | |
| 245 | + return regmap_update_bits(data->regmap, | |
| 246 | + BMC150_MAGN_REG_OPMODE_ODR, | |
| 247 | + BMC150_MAGN_MASK_OPMODE, | |
| 248 | + BMC150_MAGN_MODE_SLEEP << | |
| 249 | + BMC150_MAGN_SHIFT_OPMODE); | |
| 250 | + case BMC150_MAGN_POWER_MODE_NORMAL: | |
| 251 | + return regmap_update_bits(data->regmap, | |
| 252 | + BMC150_MAGN_REG_OPMODE_ODR, | |
| 253 | + BMC150_MAGN_MASK_OPMODE, | |
| 254 | + BMC150_MAGN_MODE_NORMAL << | |
| 255 | + BMC150_MAGN_SHIFT_OPMODE); | |
| 256 | + } | |
| 257 | + | |
| 258 | + return -EINVAL; | |
| 259 | +} | |
| 260 | + | |
| 261 | +static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) | |
| 262 | +{ | |
| 263 | +#ifdef CONFIG_PM | |
| 264 | + int ret; | |
| 265 | + | |
| 266 | + if (on) { | |
| 267 | + ret = pm_runtime_get_sync(&data->client->dev); | |
| 268 | + } else { | |
| 269 | + pm_runtime_mark_last_busy(&data->client->dev); | |
| 270 | + ret = pm_runtime_put_autosuspend(&data->client->dev); | |
| 271 | + } | |
| 272 | + | |
| 273 | + if (ret < 0) { | |
| 274 | + dev_err(&data->client->dev, | |
| 275 | + "failed to change power state to %d\n", on); | |
| 276 | + if (on) | |
| 277 | + pm_runtime_put_noidle(&data->client->dev); | |
| 278 | + | |
| 279 | + return ret; | |
| 280 | + } | |
| 281 | +#endif | |
| 282 | + | |
| 283 | + return 0; | |
| 284 | +} | |
| 285 | + | |
| 286 | +static int bmc150_magn_get_odr(struct bmc150_magn_data *data, int *val) | |
| 287 | +{ | |
| 288 | + int ret, reg_val; | |
| 289 | + u8 i, odr_val; | |
| 290 | + | |
| 291 | + ret = regmap_read(data->regmap, BMC150_MAGN_REG_OPMODE_ODR, ®_val); | |
| 292 | + if (ret < 0) | |
| 293 | + return ret; | |
| 294 | + odr_val = (reg_val & BMC150_MAGN_MASK_ODR) >> BMC150_MAGN_SHIFT_ODR; | |
| 295 | + | |
| 296 | + for (i = 0; i < ARRAY_SIZE(bmc150_magn_samp_freq_table); i++) | |
| 297 | + if (bmc150_magn_samp_freq_table[i].reg_val == odr_val) { | |
| 298 | + *val = bmc150_magn_samp_freq_table[i].freq; | |
| 299 | + return 0; | |
| 300 | + } | |
| 301 | + | |
| 302 | + return -EINVAL; | |
| 303 | +} | |
| 304 | + | |
| 305 | +static int bmc150_magn_set_odr(struct bmc150_magn_data *data, int val) | |
| 306 | +{ | |
| 307 | + int ret; | |
| 308 | + u8 i; | |
| 309 | + | |
| 310 | + for (i = 0; i < ARRAY_SIZE(bmc150_magn_samp_freq_table); i++) { | |
| 311 | + if (bmc150_magn_samp_freq_table[i].freq == val) { | |
| 312 | + ret = regmap_update_bits(data->regmap, | |
| 313 | + BMC150_MAGN_REG_OPMODE_ODR, | |
| 314 | + BMC150_MAGN_MASK_ODR, | |
| 315 | + bmc150_magn_samp_freq_table[i]. | |
| 316 | + reg_val << | |
| 317 | + BMC150_MAGN_SHIFT_ODR); | |
| 318 | + if (ret < 0) | |
| 319 | + return ret; | |
| 320 | + return 0; | |
| 321 | + } | |
| 322 | + } | |
| 323 | + | |
| 324 | + return -EINVAL; | |
| 325 | +} | |
| 326 | + | |
| 327 | +static int bmc150_magn_set_max_odr(struct bmc150_magn_data *data, int rep_xy, | |
| 328 | + int rep_z, int odr) | |
| 329 | +{ | |
| 330 | + int ret, reg_val, max_odr; | |
| 331 | + | |
| 332 | + if (rep_xy <= 0) { | |
| 333 | + ret = regmap_read(data->regmap, BMC150_MAGN_REG_REP_XY, | |
| 334 | + ®_val); | |
| 335 | + if (ret < 0) | |
| 336 | + return ret; | |
| 337 | + rep_xy = BMC150_MAGN_REGVAL_TO_REPXY(reg_val); | |
| 338 | + } | |
| 339 | + if (rep_z <= 0) { | |
| 340 | + ret = regmap_read(data->regmap, BMC150_MAGN_REG_REP_Z, | |
| 341 | + ®_val); | |
| 342 | + if (ret < 0) | |
| 343 | + return ret; | |
| 344 | + rep_z = BMC150_MAGN_REGVAL_TO_REPZ(reg_val); | |
| 345 | + } | |
| 346 | + if (odr <= 0) { | |
| 347 | + ret = bmc150_magn_get_odr(data, &odr); | |
| 348 | + if (ret < 0) | |
| 349 | + return ret; | |
| 350 | + } | |
| 351 | + /* the maximum selectable read-out frequency from datasheet */ | |
| 352 | + max_odr = 1000000 / (145 * rep_xy + 500 * rep_z + 980); | |
| 353 | + if (odr > max_odr) { | |
| 354 | + dev_err(&data->client->dev, | |
| 355 | + "Can't set oversampling with sampling freq %d\n", | |
| 356 | + odr); | |
| 357 | + return -EINVAL; | |
| 358 | + } | |
| 359 | + data->max_odr = max_odr; | |
| 360 | + | |
| 361 | + return 0; | |
| 362 | +} | |
| 363 | + | |
| 364 | +static s32 bmc150_magn_compensate_x(struct bmc150_magn_trim_regs *tregs, s16 x, | |
| 365 | + u16 rhall) | |
| 366 | +{ | |
| 367 | + s16 val; | |
| 368 | + u16 xyz1 = le16_to_cpu(tregs->xyz1); | |
| 369 | + | |
| 370 | + if (x == BMC150_MAGN_XY_OVERFLOW_VAL) | |
| 371 | + return S32_MIN; | |
| 372 | + | |
| 373 | + if (!rhall) | |
| 374 | + rhall = xyz1; | |
| 375 | + | |
| 376 | + val = ((s16)(((u16)((((s32)xyz1) << 14) / rhall)) - ((u16)0x4000))); | |
| 377 | + val = ((s16)((((s32)x) * ((((((((s32)tregs->xy2) * ((((s32)val) * | |
| 378 | + ((s32)val)) >> 7)) + (((s32)val) * | |
| 379 | + ((s32)(((s16)tregs->xy1) << 7)))) >> 9) + ((s32)0x100000)) * | |
| 380 | + ((s32)(((s16)tregs->x2) + ((s16)0xA0)))) >> 12)) >> 13)) + | |
| 381 | + (((s16)tregs->x1) << 3); | |
| 382 | + | |
| 383 | + return (s32)val; | |
| 384 | +} | |
| 385 | + | |
| 386 | +static s32 bmc150_magn_compensate_y(struct bmc150_magn_trim_regs *tregs, s16 y, | |
| 387 | + u16 rhall) | |
| 388 | +{ | |
| 389 | + s16 val; | |
| 390 | + u16 xyz1 = le16_to_cpu(tregs->xyz1); | |
| 391 | + | |
| 392 | + if (y == BMC150_MAGN_XY_OVERFLOW_VAL) | |
| 393 | + return S32_MIN; | |
| 394 | + | |
| 395 | + if (!rhall) | |
| 396 | + rhall = xyz1; | |
| 397 | + | |
| 398 | + val = ((s16)(((u16)((((s32)xyz1) << 14) / rhall)) - ((u16)0x4000))); | |
| 399 | + val = ((s16)((((s32)y) * ((((((((s32)tregs->xy2) * ((((s32)val) * | |
| 400 | + ((s32)val)) >> 7)) + (((s32)val) * | |
| 401 | + ((s32)(((s16)tregs->xy1) << 7)))) >> 9) + ((s32)0x100000)) * | |
| 402 | + ((s32)(((s16)tregs->y2) + ((s16)0xA0)))) >> 12)) >> 13)) + | |
| 403 | + (((s16)tregs->y1) << 3); | |
| 404 | + | |
| 405 | + return (s32)val; | |
| 406 | +} | |
| 407 | + | |
| 408 | +static s32 bmc150_magn_compensate_z(struct bmc150_magn_trim_regs *tregs, s16 z, | |
| 409 | + u16 rhall) | |
| 410 | +{ | |
| 411 | + s32 val; | |
| 412 | + u16 xyz1 = le16_to_cpu(tregs->xyz1); | |
| 413 | + u16 z1 = le16_to_cpu(tregs->z1); | |
| 414 | + s16 z2 = le16_to_cpu(tregs->z2); | |
| 415 | + s16 z3 = le16_to_cpu(tregs->z3); | |
| 416 | + s16 z4 = le16_to_cpu(tregs->z4); | |
| 417 | + | |
| 418 | + if (z == BMC150_MAGN_Z_OVERFLOW_VAL) | |
| 419 | + return S32_MIN; | |
| 420 | + | |
| 421 | + val = (((((s32)(z - z4)) << 15) - ((((s32)z3) * ((s32)(((s16)rhall) - | |
| 422 | + ((s16)xyz1)))) >> 2)) / (z2 + ((s16)(((((s32)z1) * | |
| 423 | + ((((s16)rhall) << 1))) + (1 << 15)) >> 16)))); | |
| 424 | + | |
| 425 | + return val; | |
| 426 | +} | |
| 427 | + | |
| 428 | +static int bmc150_magn_read_xyz(struct bmc150_magn_data *data, s32 *buffer) | |
| 429 | +{ | |
| 430 | + int ret; | |
| 431 | + __le16 values[AXIS_XYZR_MAX]; | |
| 432 | + s16 raw_x, raw_y, raw_z; | |
| 433 | + u16 rhall; | |
| 434 | + struct bmc150_magn_trim_regs tregs; | |
| 435 | + | |
| 436 | + ret = regmap_bulk_read(data->regmap, BMC150_MAGN_REG_X_L, | |
| 437 | + values, sizeof(values)); | |
| 438 | + if (ret < 0) | |
| 439 | + return ret; | |
| 440 | + | |
| 441 | + raw_x = (s16)le16_to_cpu(values[AXIS_X]) >> BMC150_MAGN_SHIFT_XY_L; | |
| 442 | + raw_y = (s16)le16_to_cpu(values[AXIS_Y]) >> BMC150_MAGN_SHIFT_XY_L; | |
| 443 | + raw_z = (s16)le16_to_cpu(values[AXIS_Z]) >> BMC150_MAGN_SHIFT_Z_L; | |
| 444 | + rhall = le16_to_cpu(values[RHALL]) >> BMC150_MAGN_SHIFT_RHALL_L; | |
| 445 | + | |
| 446 | + ret = regmap_bulk_read(data->regmap, BMC150_MAGN_REG_TRIM_START, | |
| 447 | + &tregs, sizeof(tregs)); | |
| 448 | + if (ret < 0) | |
| 449 | + return ret; | |
| 450 | + | |
| 451 | + buffer[AXIS_X] = bmc150_magn_compensate_x(&tregs, raw_x, rhall); | |
| 452 | + buffer[AXIS_Y] = bmc150_magn_compensate_y(&tregs, raw_y, rhall); | |
| 453 | + buffer[AXIS_Z] = bmc150_magn_compensate_z(&tregs, raw_z, rhall); | |
| 454 | + | |
| 455 | + return 0; | |
| 456 | +} | |
| 457 | + | |
| 458 | +static int bmc150_magn_read_raw(struct iio_dev *indio_dev, | |
| 459 | + struct iio_chan_spec const *chan, | |
| 460 | + int *val, int *val2, long mask) | |
| 461 | +{ | |
| 462 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 463 | + int ret, tmp; | |
| 464 | + s32 values[AXIS_XYZ_MAX]; | |
| 465 | + | |
| 466 | + switch (mask) { | |
| 467 | + case IIO_CHAN_INFO_RAW: | |
| 468 | + if (iio_buffer_enabled(indio_dev)) | |
| 469 | + return -EBUSY; | |
| 470 | + mutex_lock(&data->mutex); | |
| 471 | + | |
| 472 | + ret = bmc150_magn_set_power_state(data, true); | |
| 473 | + if (ret < 0) { | |
| 474 | + mutex_unlock(&data->mutex); | |
| 475 | + return ret; | |
| 476 | + } | |
| 477 | + | |
| 478 | + ret = bmc150_magn_read_xyz(data, values); | |
| 479 | + if (ret < 0) { | |
| 480 | + bmc150_magn_set_power_state(data, false); | |
| 481 | + mutex_unlock(&data->mutex); | |
| 482 | + return ret; | |
| 483 | + } | |
| 484 | + *val = values[chan->scan_index]; | |
| 485 | + | |
| 486 | + ret = bmc150_magn_set_power_state(data, false); | |
| 487 | + if (ret < 0) { | |
| 488 | + mutex_unlock(&data->mutex); | |
| 489 | + return ret; | |
| 490 | + } | |
| 491 | + | |
| 492 | + mutex_unlock(&data->mutex); | |
| 493 | + return IIO_VAL_INT; | |
| 494 | + case IIO_CHAN_INFO_SCALE: | |
| 495 | + /* | |
| 496 | + * The API/driver performs an off-chip temperature | |
| 497 | + * compensation and outputs x/y/z magnetic field data in | |
| 498 | + * 16 LSB/uT to the upper application layer. | |
| 499 | + */ | |
| 500 | + *val = 0; | |
| 501 | + *val2 = 625; | |
| 502 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 503 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 504 | + ret = bmc150_magn_get_odr(data, val); | |
| 505 | + if (ret < 0) | |
| 506 | + return ret; | |
| 507 | + return IIO_VAL_INT; | |
| 508 | + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | |
| 509 | + switch (chan->channel2) { | |
| 510 | + case IIO_MOD_X: | |
| 511 | + case IIO_MOD_Y: | |
| 512 | + ret = regmap_read(data->regmap, BMC150_MAGN_REG_REP_XY, | |
| 513 | + &tmp); | |
| 514 | + if (ret < 0) | |
| 515 | + return ret; | |
| 516 | + *val = BMC150_MAGN_REGVAL_TO_REPXY(tmp); | |
| 517 | + return IIO_VAL_INT; | |
| 518 | + case IIO_MOD_Z: | |
| 519 | + ret = regmap_read(data->regmap, BMC150_MAGN_REG_REP_Z, | |
| 520 | + &tmp); | |
| 521 | + if (ret < 0) | |
| 522 | + return ret; | |
| 523 | + *val = BMC150_MAGN_REGVAL_TO_REPZ(tmp); | |
| 524 | + return IIO_VAL_INT; | |
| 525 | + default: | |
| 526 | + return -EINVAL; | |
| 527 | + } | |
| 528 | + default: | |
| 529 | + return -EINVAL; | |
| 530 | + } | |
| 531 | +} | |
| 532 | + | |
| 533 | +static int bmc150_magn_write_raw(struct iio_dev *indio_dev, | |
| 534 | + struct iio_chan_spec const *chan, | |
| 535 | + int val, int val2, long mask) | |
| 536 | +{ | |
| 537 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 538 | + int ret; | |
| 539 | + | |
| 540 | + switch (mask) { | |
| 541 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 542 | + if (val > data->max_odr) | |
| 543 | + return -EINVAL; | |
| 544 | + mutex_lock(&data->mutex); | |
| 545 | + ret = bmc150_magn_set_odr(data, val); | |
| 546 | + mutex_unlock(&data->mutex); | |
| 547 | + return ret; | |
| 548 | + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: | |
| 549 | + switch (chan->channel2) { | |
| 550 | + case IIO_MOD_X: | |
| 551 | + case IIO_MOD_Y: | |
| 552 | + if (val < 1 || val > 511) | |
| 553 | + return -EINVAL; | |
| 554 | + mutex_lock(&data->mutex); | |
| 555 | + ret = bmc150_magn_set_max_odr(data, val, 0, 0); | |
| 556 | + if (ret < 0) { | |
| 557 | + mutex_unlock(&data->mutex); | |
| 558 | + return ret; | |
| 559 | + } | |
| 560 | + ret = regmap_update_bits(data->regmap, | |
| 561 | + BMC150_MAGN_REG_REP_XY, | |
| 562 | + 0xFF, | |
| 563 | + BMC150_MAGN_REPXY_TO_REGVAL | |
| 564 | + (val)); | |
| 565 | + mutex_unlock(&data->mutex); | |
| 566 | + return ret; | |
| 567 | + case IIO_MOD_Z: | |
| 568 | + if (val < 1 || val > 256) | |
| 569 | + return -EINVAL; | |
| 570 | + mutex_lock(&data->mutex); | |
| 571 | + ret = bmc150_magn_set_max_odr(data, 0, val, 0); | |
| 572 | + if (ret < 0) { | |
| 573 | + mutex_unlock(&data->mutex); | |
| 574 | + return ret; | |
| 575 | + } | |
| 576 | + ret = regmap_update_bits(data->regmap, | |
| 577 | + BMC150_MAGN_REG_REP_Z, | |
| 578 | + 0xFF, | |
| 579 | + BMC150_MAGN_REPZ_TO_REGVAL | |
| 580 | + (val)); | |
| 581 | + mutex_unlock(&data->mutex); | |
| 582 | + return ret; | |
| 583 | + default: | |
| 584 | + return -EINVAL; | |
| 585 | + } | |
| 586 | + default: | |
| 587 | + return -EINVAL; | |
| 588 | + } | |
| 589 | +} | |
| 590 | + | |
| 591 | +static int bmc150_magn_validate_trigger(struct iio_dev *indio_dev, | |
| 592 | + struct iio_trigger *trig) | |
| 593 | +{ | |
| 594 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 595 | + | |
| 596 | + if (data->dready_trig != trig) | |
| 597 | + return -EINVAL; | |
| 598 | + | |
| 599 | + return 0; | |
| 600 | +} | |
| 601 | + | |
| 602 | +static ssize_t bmc150_magn_show_samp_freq_avail(struct device *dev, | |
| 603 | + struct device_attribute *attr, | |
| 604 | + char *buf) | |
| 605 | +{ | |
| 606 | + struct iio_dev *indio_dev = dev_to_iio_dev(dev); | |
| 607 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 608 | + size_t len = 0; | |
| 609 | + u8 i; | |
| 610 | + | |
| 611 | + for (i = 0; i < ARRAY_SIZE(bmc150_magn_samp_freq_table); i++) { | |
| 612 | + if (bmc150_magn_samp_freq_table[i].freq > data->max_odr) | |
| 613 | + break; | |
| 614 | + len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", | |
| 615 | + bmc150_magn_samp_freq_table[i].freq); | |
| 616 | + } | |
| 617 | + /* replace last space with a newline */ | |
| 618 | + buf[len - 1] = '\n'; | |
| 619 | + | |
| 620 | + return len; | |
| 621 | +} | |
| 622 | + | |
| 623 | +static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(bmc150_magn_show_samp_freq_avail); | |
| 624 | + | |
| 625 | +static struct attribute *bmc150_magn_attributes[] = { | |
| 626 | + &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | |
| 627 | + NULL, | |
| 628 | +}; | |
| 629 | + | |
| 630 | +static const struct attribute_group bmc150_magn_attrs_group = { | |
| 631 | + .attrs = bmc150_magn_attributes, | |
| 632 | +}; | |
| 633 | + | |
| 634 | +#define BMC150_MAGN_CHANNEL(_axis) { \ | |
| 635 | + .type = IIO_MAGN, \ | |
| 636 | + .modified = 1, \ | |
| 637 | + .channel2 = IIO_MOD_##_axis, \ | |
| 638 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | |
| 639 | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ | |
| 640 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | |
| 641 | + BIT(IIO_CHAN_INFO_SCALE), \ | |
| 642 | + .scan_index = AXIS_##_axis, \ | |
| 643 | + .scan_type = { \ | |
| 644 | + .sign = 's', \ | |
| 645 | + .realbits = 32, \ | |
| 646 | + .storagebits = 32, \ | |
| 647 | + .endianness = IIO_LE \ | |
| 648 | + }, \ | |
| 649 | +} | |
| 650 | + | |
| 651 | +static const struct iio_chan_spec bmc150_magn_channels[] = { | |
| 652 | + BMC150_MAGN_CHANNEL(X), | |
| 653 | + BMC150_MAGN_CHANNEL(Y), | |
| 654 | + BMC150_MAGN_CHANNEL(Z), | |
| 655 | + IIO_CHAN_SOFT_TIMESTAMP(3), | |
| 656 | +}; | |
| 657 | + | |
| 658 | +static const struct iio_info bmc150_magn_info = { | |
| 659 | + .attrs = &bmc150_magn_attrs_group, | |
| 660 | + .read_raw = bmc150_magn_read_raw, | |
| 661 | + .write_raw = bmc150_magn_write_raw, | |
| 662 | + .validate_trigger = bmc150_magn_validate_trigger, | |
| 663 | + .driver_module = THIS_MODULE, | |
| 664 | +}; | |
| 665 | + | |
| 666 | +static const unsigned long bmc150_magn_scan_masks[] = {0x07, 0}; | |
| 667 | + | |
| 668 | +static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p) | |
| 669 | +{ | |
| 670 | + struct iio_poll_func *pf = p; | |
| 671 | + struct iio_dev *indio_dev = pf->indio_dev; | |
| 672 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 673 | + int ret; | |
| 674 | + | |
| 675 | + mutex_lock(&data->mutex); | |
| 676 | + ret = bmc150_magn_read_xyz(data, data->buffer); | |
| 677 | + mutex_unlock(&data->mutex); | |
| 678 | + if (ret < 0) | |
| 679 | + goto err; | |
| 680 | + | |
| 681 | + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | |
| 682 | + pf->timestamp); | |
| 683 | + | |
| 684 | +err: | |
| 685 | + iio_trigger_notify_done(data->dready_trig); | |
| 686 | + | |
| 687 | + return IRQ_HANDLED; | |
| 688 | +} | |
| 689 | + | |
| 690 | +static int bmc150_magn_init(struct bmc150_magn_data *data) | |
| 691 | +{ | |
| 692 | + int ret, chip_id; | |
| 693 | + struct bmc150_magn_preset preset; | |
| 694 | + | |
| 695 | + ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, | |
| 696 | + false); | |
| 697 | + if (ret < 0) { | |
| 698 | + dev_err(&data->client->dev, | |
| 699 | + "Failed to bring up device from suspend mode\n"); | |
| 700 | + return ret; | |
| 701 | + } | |
| 702 | + | |
| 703 | + ret = regmap_read(data->regmap, BMC150_MAGN_REG_CHIP_ID, &chip_id); | |
| 704 | + if (ret < 0) { | |
| 705 | + dev_err(&data->client->dev, "Failed reading chip id\n"); | |
| 706 | + goto err_poweroff; | |
| 707 | + } | |
| 708 | + if (chip_id != BMC150_MAGN_CHIP_ID_VAL) { | |
| 709 | + dev_err(&data->client->dev, "Invalid chip id 0x%x\n", ret); | |
| 710 | + ret = -ENODEV; | |
| 711 | + goto err_poweroff; | |
| 712 | + } | |
| 713 | + dev_dbg(&data->client->dev, "Chip id %x\n", ret); | |
| 714 | + | |
| 715 | + preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET]; | |
| 716 | + ret = bmc150_magn_set_odr(data, preset.odr); | |
| 717 | + if (ret < 0) { | |
| 718 | + dev_err(&data->client->dev, "Failed to set ODR to %d\n", | |
| 719 | + preset.odr); | |
| 720 | + goto err_poweroff; | |
| 721 | + } | |
| 722 | + | |
| 723 | + ret = regmap_write(data->regmap, BMC150_MAGN_REG_REP_XY, | |
| 724 | + BMC150_MAGN_REPXY_TO_REGVAL(preset.rep_xy)); | |
| 725 | + if (ret < 0) { | |
| 726 | + dev_err(&data->client->dev, "Failed to set REP XY to %d\n", | |
| 727 | + preset.rep_xy); | |
| 728 | + goto err_poweroff; | |
| 729 | + } | |
| 730 | + | |
| 731 | + ret = regmap_write(data->regmap, BMC150_MAGN_REG_REP_Z, | |
| 732 | + BMC150_MAGN_REPZ_TO_REGVAL(preset.rep_z)); | |
| 733 | + if (ret < 0) { | |
| 734 | + dev_err(&data->client->dev, "Failed to set REP Z to %d\n", | |
| 735 | + preset.rep_z); | |
| 736 | + goto err_poweroff; | |
| 737 | + } | |
| 738 | + | |
| 739 | + ret = bmc150_magn_set_max_odr(data, preset.rep_xy, preset.rep_z, | |
| 740 | + preset.odr); | |
| 741 | + if (ret < 0) | |
| 742 | + goto err_poweroff; | |
| 743 | + | |
| 744 | + ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL, | |
| 745 | + true); | |
| 746 | + if (ret < 0) { | |
| 747 | + dev_err(&data->client->dev, "Failed to power on device\n"); | |
| 748 | + goto err_poweroff; | |
| 749 | + } | |
| 750 | + | |
| 751 | + return 0; | |
| 752 | + | |
| 753 | +err_poweroff: | |
| 754 | + bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); | |
| 755 | + return ret; | |
| 756 | +} | |
| 757 | + | |
| 758 | +static int bmc150_magn_reset_intr(struct bmc150_magn_data *data) | |
| 759 | +{ | |
| 760 | + int tmp; | |
| 761 | + | |
| 762 | + /* | |
| 763 | + * Data Ready (DRDY) is always cleared after | |
| 764 | + * readout of data registers ends. | |
| 765 | + */ | |
| 766 | + return regmap_read(data->regmap, BMC150_MAGN_REG_X_L, &tmp); | |
| 767 | +} | |
| 768 | + | |
| 769 | +static int bmc150_magn_trig_try_reen(struct iio_trigger *trig) | |
| 770 | +{ | |
| 771 | + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | |
| 772 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 773 | + int ret; | |
| 774 | + | |
| 775 | + if (!data->dready_trigger_on) | |
| 776 | + return 0; | |
| 777 | + | |
| 778 | + mutex_lock(&data->mutex); | |
| 779 | + ret = bmc150_magn_reset_intr(data); | |
| 780 | + mutex_unlock(&data->mutex); | |
| 781 | + | |
| 782 | + return ret; | |
| 783 | +} | |
| 784 | + | |
| 785 | +static int bmc150_magn_data_rdy_trigger_set_state(struct iio_trigger *trig, | |
| 786 | + bool state) | |
| 787 | +{ | |
| 788 | + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); | |
| 789 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 790 | + int ret = 0; | |
| 791 | + | |
| 792 | + mutex_lock(&data->mutex); | |
| 793 | + if (state == data->dready_trigger_on) | |
| 794 | + goto err_unlock; | |
| 795 | + | |
| 796 | + ret = bmc150_magn_set_power_state(data, state); | |
| 797 | + if (ret < 0) | |
| 798 | + goto err_unlock; | |
| 799 | + | |
| 800 | + ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY, | |
| 801 | + BMC150_MAGN_MASK_DRDY_EN, | |
| 802 | + state << BMC150_MAGN_SHIFT_DRDY_EN); | |
| 803 | + if (ret < 0) | |
| 804 | + goto err_poweroff; | |
| 805 | + | |
| 806 | + data->dready_trigger_on = state; | |
| 807 | + | |
| 808 | + if (state) { | |
| 809 | + ret = bmc150_magn_reset_intr(data); | |
| 810 | + if (ret < 0) | |
| 811 | + goto err_poweroff; | |
| 812 | + } | |
| 813 | + mutex_unlock(&data->mutex); | |
| 814 | + | |
| 815 | + return 0; | |
| 816 | + | |
| 817 | +err_poweroff: | |
| 818 | + bmc150_magn_set_power_state(data, false); | |
| 819 | +err_unlock: | |
| 820 | + mutex_unlock(&data->mutex); | |
| 821 | + return ret; | |
| 822 | +} | |
| 823 | + | |
| 824 | +static const struct iio_trigger_ops bmc150_magn_trigger_ops = { | |
| 825 | + .set_trigger_state = bmc150_magn_data_rdy_trigger_set_state, | |
| 826 | + .try_reenable = bmc150_magn_trig_try_reen, | |
| 827 | + .owner = THIS_MODULE, | |
| 828 | +}; | |
| 829 | + | |
| 830 | +static int bmc150_magn_gpio_probe(struct i2c_client *client) | |
| 831 | +{ | |
| 832 | + struct device *dev; | |
| 833 | + struct gpio_desc *gpio; | |
| 834 | + int ret; | |
| 835 | + | |
| 836 | + if (!client) | |
| 837 | + return -EINVAL; | |
| 838 | + | |
| 839 | + dev = &client->dev; | |
| 840 | + | |
| 841 | + /* data ready GPIO interrupt pin */ | |
| 842 | + gpio = devm_gpiod_get_index(dev, BMC150_MAGN_GPIO_INT, 0); | |
| 843 | + if (IS_ERR(gpio)) { | |
| 844 | + dev_err(dev, "ACPI GPIO get index failed\n"); | |
| 845 | + return PTR_ERR(gpio); | |
| 846 | + } | |
| 847 | + | |
| 848 | + ret = gpiod_direction_input(gpio); | |
| 849 | + if (ret) | |
| 850 | + return ret; | |
| 851 | + | |
| 852 | + ret = gpiod_to_irq(gpio); | |
| 853 | + | |
| 854 | + dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | |
| 855 | + | |
| 856 | + return ret; | |
| 857 | +} | |
| 858 | + | |
| 859 | +static const char *bmc150_magn_match_acpi_device(struct device *dev) | |
| 860 | +{ | |
| 861 | + const struct acpi_device_id *id; | |
| 862 | + | |
| 863 | + id = acpi_match_device(dev->driver->acpi_match_table, dev); | |
| 864 | + if (!id) | |
| 865 | + return NULL; | |
| 866 | + | |
| 867 | + return dev_name(dev); | |
| 868 | +} | |
| 869 | + | |
| 870 | +static int bmc150_magn_probe(struct i2c_client *client, | |
| 871 | + const struct i2c_device_id *id) | |
| 872 | +{ | |
| 873 | + struct bmc150_magn_data *data; | |
| 874 | + struct iio_dev *indio_dev; | |
| 875 | + const char *name = NULL; | |
| 876 | + int ret; | |
| 877 | + | |
| 878 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 879 | + if (!indio_dev) | |
| 880 | + return -ENOMEM; | |
| 881 | + | |
| 882 | + data = iio_priv(indio_dev); | |
| 883 | + i2c_set_clientdata(client, indio_dev); | |
| 884 | + data->client = client; | |
| 885 | + | |
| 886 | + if (id) | |
| 887 | + name = id->name; | |
| 888 | + else if (ACPI_HANDLE(&client->dev)) | |
| 889 | + name = bmc150_magn_match_acpi_device(&client->dev); | |
| 890 | + else | |
| 891 | + return -ENOSYS; | |
| 892 | + | |
| 893 | + mutex_init(&data->mutex); | |
| 894 | + data->regmap = devm_regmap_init_i2c(client, &bmc150_magn_regmap_config); | |
| 895 | + if (IS_ERR(data->regmap)) { | |
| 896 | + dev_err(&client->dev, "Failed to allocate register map\n"); | |
| 897 | + return PTR_ERR(data->regmap); | |
| 898 | + } | |
| 899 | + | |
| 900 | + ret = bmc150_magn_init(data); | |
| 901 | + if (ret < 0) | |
| 902 | + return ret; | |
| 903 | + | |
| 904 | + indio_dev->dev.parent = &client->dev; | |
| 905 | + indio_dev->channels = bmc150_magn_channels; | |
| 906 | + indio_dev->num_channels = ARRAY_SIZE(bmc150_magn_channels); | |
| 907 | + indio_dev->available_scan_masks = bmc150_magn_scan_masks; | |
| 908 | + indio_dev->name = name; | |
| 909 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 910 | + indio_dev->info = &bmc150_magn_info; | |
| 911 | + | |
| 912 | + if (client->irq <= 0) | |
| 913 | + client->irq = bmc150_magn_gpio_probe(client); | |
| 914 | + | |
| 915 | + if (client->irq > 0) { | |
| 916 | + data->dready_trig = devm_iio_trigger_alloc(&client->dev, | |
| 917 | + "%s-dev%d", | |
| 918 | + indio_dev->name, | |
| 919 | + indio_dev->id); | |
| 920 | + if (!data->dready_trig) { | |
| 921 | + ret = -ENOMEM; | |
| 922 | + dev_err(&client->dev, "iio trigger alloc failed\n"); | |
| 923 | + goto err_poweroff; | |
| 924 | + } | |
| 925 | + | |
| 926 | + data->dready_trig->dev.parent = &client->dev; | |
| 927 | + data->dready_trig->ops = &bmc150_magn_trigger_ops; | |
| 928 | + iio_trigger_set_drvdata(data->dready_trig, indio_dev); | |
| 929 | + ret = iio_trigger_register(data->dready_trig); | |
| 930 | + if (ret) { | |
| 931 | + dev_err(&client->dev, "iio trigger register failed\n"); | |
| 932 | + goto err_poweroff; | |
| 933 | + } | |
| 934 | + | |
| 935 | + ret = iio_triggered_buffer_setup(indio_dev, | |
| 936 | + &iio_pollfunc_store_time, | |
| 937 | + bmc150_magn_trigger_handler, | |
| 938 | + NULL); | |
| 939 | + if (ret < 0) { | |
| 940 | + dev_err(&client->dev, | |
| 941 | + "iio triggered buffer setup failed\n"); | |
| 942 | + goto err_trigger_unregister; | |
| 943 | + } | |
| 944 | + | |
| 945 | + ret = request_threaded_irq(client->irq, | |
| 946 | + iio_trigger_generic_data_rdy_poll, | |
| 947 | + NULL, | |
| 948 | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
| 949 | + BMC150_MAGN_IRQ_NAME, | |
| 950 | + data->dready_trig); | |
| 951 | + if (ret < 0) { | |
| 952 | + dev_err(&client->dev, "request irq %d failed\n", | |
| 953 | + client->irq); | |
| 954 | + goto err_buffer_cleanup; | |
| 955 | + } | |
| 956 | + } | |
| 957 | + | |
| 958 | + ret = iio_device_register(indio_dev); | |
| 959 | + if (ret < 0) { | |
| 960 | + dev_err(&client->dev, "unable to register iio device\n"); | |
| 961 | + goto err_free_irq; | |
| 962 | + } | |
| 963 | + | |
| 964 | + ret = pm_runtime_set_active(&client->dev); | |
| 965 | + if (ret) | |
| 966 | + goto err_iio_unregister; | |
| 967 | + | |
| 968 | + pm_runtime_enable(&client->dev); | |
| 969 | + pm_runtime_set_autosuspend_delay(&client->dev, | |
| 970 | + BMC150_MAGN_AUTO_SUSPEND_DELAY_MS); | |
| 971 | + pm_runtime_use_autosuspend(&client->dev); | |
| 972 | + | |
| 973 | + dev_dbg(&indio_dev->dev, "Registered device %s\n", name); | |
| 974 | + | |
| 975 | + return 0; | |
| 976 | + | |
| 977 | +err_iio_unregister: | |
| 978 | + iio_device_unregister(indio_dev); | |
| 979 | +err_free_irq: | |
| 980 | + if (client->irq > 0) | |
| 981 | + free_irq(client->irq, data->dready_trig); | |
| 982 | +err_buffer_cleanup: | |
| 983 | + if (data->dready_trig) | |
| 984 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 985 | +err_trigger_unregister: | |
| 986 | + if (data->dready_trig) | |
| 987 | + iio_trigger_unregister(data->dready_trig); | |
| 988 | +err_poweroff: | |
| 989 | + bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); | |
| 990 | + return ret; | |
| 991 | +} | |
| 992 | + | |
| 993 | +static int bmc150_magn_remove(struct i2c_client *client) | |
| 994 | +{ | |
| 995 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 996 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 997 | + | |
| 998 | + pm_runtime_disable(&client->dev); | |
| 999 | + pm_runtime_set_suspended(&client->dev); | |
| 1000 | + pm_runtime_put_noidle(&client->dev); | |
| 1001 | + | |
| 1002 | + iio_device_unregister(indio_dev); | |
| 1003 | + | |
| 1004 | + if (client->irq > 0) | |
| 1005 | + free_irq(data->client->irq, data->dready_trig); | |
| 1006 | + | |
| 1007 | + if (data->dready_trig) { | |
| 1008 | + iio_triggered_buffer_cleanup(indio_dev); | |
| 1009 | + iio_trigger_unregister(data->dready_trig); | |
| 1010 | + } | |
| 1011 | + | |
| 1012 | + mutex_lock(&data->mutex); | |
| 1013 | + bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); | |
| 1014 | + mutex_unlock(&data->mutex); | |
| 1015 | + | |
| 1016 | + return 0; | |
| 1017 | +} | |
| 1018 | + | |
| 1019 | +#ifdef CONFIG_PM | |
| 1020 | +static int bmc150_magn_runtime_suspend(struct device *dev) | |
| 1021 | +{ | |
| 1022 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 1023 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 1024 | + int ret; | |
| 1025 | + | |
| 1026 | + mutex_lock(&data->mutex); | |
| 1027 | + ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SLEEP, | |
| 1028 | + true); | |
| 1029 | + mutex_unlock(&data->mutex); | |
| 1030 | + if (ret < 0) { | |
| 1031 | + dev_err(&data->client->dev, "powering off device failed\n"); | |
| 1032 | + return ret; | |
| 1033 | + } | |
| 1034 | + return 0; | |
| 1035 | +} | |
| 1036 | + | |
| 1037 | +static int bmc150_magn_runtime_resume(struct device *dev) | |
| 1038 | +{ | |
| 1039 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 1040 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 1041 | + | |
| 1042 | + return bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL, | |
| 1043 | + true); | |
| 1044 | +} | |
| 1045 | +#endif | |
| 1046 | + | |
| 1047 | +#ifdef CONFIG_PM_SLEEP | |
| 1048 | +static int bmc150_magn_suspend(struct device *dev) | |
| 1049 | +{ | |
| 1050 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 1051 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 1052 | + int ret; | |
| 1053 | + | |
| 1054 | + mutex_lock(&data->mutex); | |
| 1055 | + ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SLEEP, | |
| 1056 | + true); | |
| 1057 | + mutex_unlock(&data->mutex); | |
| 1058 | + | |
| 1059 | + return ret; | |
| 1060 | +} | |
| 1061 | + | |
| 1062 | +static int bmc150_magn_resume(struct device *dev) | |
| 1063 | +{ | |
| 1064 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 1065 | + struct bmc150_magn_data *data = iio_priv(indio_dev); | |
| 1066 | + int ret; | |
| 1067 | + | |
| 1068 | + mutex_lock(&data->mutex); | |
| 1069 | + ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_NORMAL, | |
| 1070 | + true); | |
| 1071 | + mutex_unlock(&data->mutex); | |
| 1072 | + | |
| 1073 | + return ret; | |
| 1074 | +} | |
| 1075 | +#endif | |
| 1076 | + | |
| 1077 | +static const struct dev_pm_ops bmc150_magn_pm_ops = { | |
| 1078 | + SET_SYSTEM_SLEEP_PM_OPS(bmc150_magn_suspend, bmc150_magn_resume) | |
| 1079 | + SET_RUNTIME_PM_OPS(bmc150_magn_runtime_suspend, | |
| 1080 | + bmc150_magn_runtime_resume, NULL) | |
| 1081 | +}; | |
| 1082 | + | |
| 1083 | +static const struct acpi_device_id bmc150_magn_acpi_match[] = { | |
| 1084 | + {"BMC150B", 0}, | |
| 1085 | + {}, | |
| 1086 | +}; | |
| 1087 | +MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match); | |
| 1088 | + | |
| 1089 | +static const struct i2c_device_id bmc150_magn_id[] = { | |
| 1090 | + {"bmc150_magn", 0}, | |
| 1091 | + {}, | |
| 1092 | +}; | |
| 1093 | +MODULE_DEVICE_TABLE(i2c, bmc150_magn_id); | |
| 1094 | + | |
| 1095 | +static struct i2c_driver bmc150_magn_driver = { | |
| 1096 | + .driver = { | |
| 1097 | + .name = BMC150_MAGN_DRV_NAME, | |
| 1098 | + .acpi_match_table = ACPI_PTR(bmc150_magn_acpi_match), | |
| 1099 | + .pm = &bmc150_magn_pm_ops, | |
| 1100 | + }, | |
| 1101 | + .probe = bmc150_magn_probe, | |
| 1102 | + .remove = bmc150_magn_remove, | |
| 1103 | + .id_table = bmc150_magn_id, | |
| 1104 | +}; | |
| 1105 | +module_i2c_driver(bmc150_magn_driver); | |
| 1106 | + | |
| 1107 | +MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); | |
| 1108 | +MODULE_LICENSE("GPL v2"); | |
| 1109 | +MODULE_DESCRIPTION("BMC150 magnetometer driver"); | |
| @@ -510,7 +510,7 @@ static int hid_magn_3d_remove(struct platform_device *pdev) · 509 unmodified lines | ||
| 510 | 510 | return 0; |
| 511 | 511 | } |
| 512 | 512 | |
| 513 | −static struct platform_device_id hid_magn_3d_ids[] = { | |
| 513 | +static const struct platform_device_id hid_magn_3d_ids[] = { | |
| 514 | 514 | { |
| 515 | 515 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 516 | 516 | .name = "HID-SENSOR-200083", |
| @@ -0,0 +1,579 @@ | ||
| 1 | +/* | |
| 2 | + * MMC35240 - MEMSIC 3-axis Magnetic Sensor | |
| 3 | + * | |
| 4 | + * Copyright (c) 2015, Intel Corporation. | |
| 5 | + * | |
| 6 | + * This file is subject to the terms and conditions of version 2 of | |
| 7 | + * the GNU General Public License. See the file COPYING in the main | |
| 8 | + * directory of this archive for more details. | |
| 9 | + * | |
| 10 | + * IIO driver for MMC35240 (7-bit I2C slave address 0x30). | |
| 11 | + * | |
| 12 | + * TODO: offset, ACPI, continuous measurement mode, PM | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#include <linux/module.h> | |
| 16 | +#include <linux/init.h> | |
| 17 | +#include <linux/i2c.h> | |
| 18 | +#include <linux/delay.h> | |
| 19 | +#include <linux/regmap.h> | |
| 20 | +#include <linux/acpi.h> | |
| 21 | +#include <linux/pm.h> | |
| 22 | + | |
| 23 | +#include <linux/iio/iio.h> | |
| 24 | +#include <linux/iio/sysfs.h> | |
| 25 | + | |
| 26 | +#define MMC35240_DRV_NAME "mmc35240" | |
| 27 | +#define MMC35240_REGMAP_NAME "mmc35240_regmap" | |
| 28 | + | |
| 29 | +#define MMC35240_REG_XOUT_L 0x00 | |
| 30 | +#define MMC35240_REG_XOUT_H 0x01 | |
| 31 | +#define MMC35240_REG_YOUT_L 0x02 | |
| 32 | +#define MMC35240_REG_YOUT_H 0x03 | |
| 33 | +#define MMC35240_REG_ZOUT_L 0x04 | |
| 34 | +#define MMC35240_REG_ZOUT_H 0x05 | |
| 35 | + | |
| 36 | +#define MMC35240_REG_STATUS 0x06 | |
| 37 | +#define MMC35240_REG_CTRL0 0x07 | |
| 38 | +#define MMC35240_REG_CTRL1 0x08 | |
| 39 | + | |
| 40 | +#define MMC35240_REG_ID 0x20 | |
| 41 | + | |
| 42 | +#define MMC35240_STATUS_MEAS_DONE_BIT BIT(0) | |
| 43 | + | |
| 44 | +#define MMC35240_CTRL0_REFILL_BIT BIT(7) | |
| 45 | +#define MMC35240_CTRL0_RESET_BIT BIT(6) | |
| 46 | +#define MMC35240_CTRL0_SET_BIT BIT(5) | |
| 47 | +#define MMC35240_CTRL0_CMM_BIT BIT(1) | |
| 48 | +#define MMC35240_CTRL0_TM_BIT BIT(0) | |
| 49 | + | |
| 50 | +/* output resolution bits */ | |
| 51 | +#define MMC35240_CTRL1_BW0_BIT BIT(0) | |
| 52 | +#define MMC35240_CTRL1_BW1_BIT BIT(1) | |
| 53 | + | |
| 54 | +#define MMC35240_CTRL1_BW_MASK (MMC35240_CTRL1_BW0_BIT | \ | |
| 55 | + MMC35240_CTRL1_BW1_BIT) | |
| 56 | +#define MMC35240_CTRL1_BW_SHIFT 0 | |
| 57 | + | |
| 58 | +#define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */ | |
| 59 | +#define MMC53240_WAIT_SET_RESET 1000 /* us */ | |
| 60 | + | |
| 61 | +/* | |
| 62 | + * Memsic OTP process code piece is put here for reference: | |
| 63 | + * | |
| 64 | + * #define OTP_CONVERT(REG) ((float)((REG) >=32 ? (32 - (REG)) : (REG)) * 0.006 | |
| 65 | + * 1) For X axis, the COEFFICIENT is always 1. | |
| 66 | + * 2) For Y axis, the COEFFICIENT is as below: | |
| 67 | + * f_OTP_matrix[4] = OTP_CONVERT(((reg_data[1] & 0x03) << 4) | | |
| 68 | + * (reg_data[2] >> 4)) + 1.0; | |
| 69 | + * 3) For Z axis, the COEFFICIENT is as below: | |
| 70 | + * f_OTP_matrix[8] = (OTP_CONVERT(reg_data[3] & 0x3f) + 1) * 1.35; | |
| 71 | + * We implemented the OTP logic into driver. | |
| 72 | + */ | |
| 73 | + | |
| 74 | +/* scale = 1000 here for Y otp */ | |
| 75 | +#define MMC35240_OTP_CONVERT_Y(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6) | |
| 76 | + | |
| 77 | +/* 0.6 * 1.35 = 0.81, scale 10000 for Z otp */ | |
| 78 | +#define MMC35240_OTP_CONVERT_Z(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 81) | |
| 79 | + | |
| 80 | +#define MMC35240_X_COEFF(x) (x) | |
| 81 | +#define MMC35240_Y_COEFF(y) (y + 1000) | |
| 82 | +#define MMC35240_Z_COEFF(z) (z + 13500) | |
| 83 | + | |
| 84 | +#define MMC35240_OTP_START_ADDR 0x1B | |
| 85 | + | |
| 86 | +enum mmc35240_resolution { | |
| 87 | + MMC35240_16_BITS_SLOW = 0, /* 100 Hz */ | |
| 88 | + MMC35240_16_BITS_FAST, /* 200 Hz */ | |
| 89 | + MMC35240_14_BITS, /* 333 Hz */ | |
| 90 | + MMC35240_12_BITS, /* 666 Hz */ | |
| 91 | +}; | |
| 92 | + | |
| 93 | +enum mmc35240_axis { | |
| 94 | + AXIS_X = 0, | |
| 95 | + AXIS_Y, | |
| 96 | + AXIS_Z, | |
| 97 | +}; | |
| 98 | + | |
| 99 | +static const struct { | |
| 100 | + int sens[3]; /* sensitivity per X, Y, Z axis */ | |
| 101 | + int nfo; /* null field output */ | |
| 102 | +} mmc35240_props_table[] = { | |
| 103 | + /* 16 bits, 100Hz ODR */ | |
| 104 | + { | |
| 105 | + {1024, 1024, 1024}, | |
| 106 | + 32768, | |
| 107 | + }, | |
| 108 | + /* 16 bits, 200Hz ODR */ | |
| 109 | + { | |
| 110 | + {1024, 1024, 770}, | |
| 111 | + 32768, | |
| 112 | + }, | |
| 113 | + /* 14 bits, 333Hz ODR */ | |
| 114 | + { | |
| 115 | + {256, 256, 193}, | |
| 116 | + 8192, | |
| 117 | + }, | |
| 118 | + /* 12 bits, 666Hz ODR */ | |
| 119 | + { | |
| 120 | + {64, 64, 48}, | |
| 121 | + 2048, | |
| 122 | + }, | |
| 123 | +}; | |
| 124 | + | |
| 125 | +struct mmc35240_data { | |
| 126 | + struct i2c_client *client; | |
| 127 | + struct mutex mutex; | |
| 128 | + struct regmap *regmap; | |
| 129 | + enum mmc35240_resolution res; | |
| 130 | + | |
| 131 | + /* OTP compensation */ | |
| 132 | + int axis_coef[3]; | |
| 133 | + int axis_scale[3]; | |
| 134 | +}; | |
| 135 | + | |
| 136 | +static const int mmc35240_samp_freq[] = {100, 200, 333, 666}; | |
| 137 | + | |
| 138 | +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 333 666"); | |
| 139 | + | |
| 140 | +#define MMC35240_CHANNEL(_axis) { \ | |
| 141 | + .type = IIO_MAGN, \ | |
| 142 | + .modified = 1, \ | |
| 143 | + .channel2 = IIO_MOD_ ## _axis, \ | |
| 144 | + .address = AXIS_ ## _axis, \ | |
| 145 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ | |
| 146 | + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | |
| 147 | + BIT(IIO_CHAN_INFO_SCALE), \ | |
| 148 | +} | |
| 149 | + | |
| 150 | +static const struct iio_chan_spec mmc35240_channels[] = { | |
| 151 | + MMC35240_CHANNEL(X), | |
| 152 | + MMC35240_CHANNEL(Y), | |
| 153 | + MMC35240_CHANNEL(Z), | |
| 154 | +}; | |
| 155 | + | |
| 156 | +static struct attribute *mmc35240_attributes[] = { | |
| 157 | + &iio_const_attr_sampling_frequency_available.dev_attr.attr, | |
| 158 | + NULL | |
| 159 | +}; | |
| 160 | + | |
| 161 | +static const struct attribute_group mmc35240_attribute_group = { | |
| 162 | + .attrs = mmc35240_attributes, | |
| 163 | +}; | |
| 164 | + | |
| 165 | +static int mmc35240_get_samp_freq_index(struct mmc35240_data *data, | |
| 166 | + int val, int val2) | |
| 167 | +{ | |
| 168 | + int i; | |
| 169 | + | |
| 170 | + for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++) | |
| 171 | + if (mmc35240_samp_freq[i] == val) | |
| 172 | + return i; | |
| 173 | + return -EINVAL; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static int mmc35240_hw_set(struct mmc35240_data *data, bool set) | |
| 177 | +{ | |
| 178 | + int ret; | |
| 179 | + u8 coil_bit; | |
| 180 | + | |
| 181 | + /* | |
| 182 | + * Recharge the capacitor at VCAP pin, requested to be issued | |
| 183 | + * before a SET/RESET command. | |
| 184 | + */ | |
| 185 | + ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, | |
| 186 | + MMC35240_CTRL0_REFILL_BIT, | |
| 187 | + MMC35240_CTRL0_REFILL_BIT); | |
| 188 | + if (ret < 0) | |
| 189 | + return ret; | |
| 190 | + usleep_range(MMC35240_WAIT_CHARGE_PUMP, MMC35240_WAIT_CHARGE_PUMP + 1); | |
| 191 | + | |
| 192 | + if (set) | |
| 193 | + coil_bit = MMC35240_CTRL0_SET_BIT; | |
| 194 | + else | |
| 195 | + coil_bit = MMC35240_CTRL0_RESET_BIT; | |
| 196 | + | |
| 197 | + return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0, | |
| 198 | + MMC35240_CTRL0_REFILL_BIT, | |
| 199 | + coil_bit); | |
| 200 | +} | |
| 201 | + | |
| 202 | +static int mmc35240_init(struct mmc35240_data *data) | |
| 203 | +{ | |
| 204 | + int ret, y_convert, z_convert; | |
| 205 | + unsigned int reg_id; | |
| 206 | + u8 otp_data[6]; | |
| 207 | + | |
| 208 | + ret = regmap_read(data->regmap, MMC35240_REG_ID, ®_id); | |
| 209 | + if (ret < 0) { | |
| 210 | + dev_err(&data->client->dev, "Error reading product id\n"); | |
| 211 | + return ret; | |
| 212 | + } | |
| 213 | + | |
| 214 | + dev_dbg(&data->client->dev, "MMC35240 chip id %x\n", reg_id); | |
| 215 | + | |
| 216 | + /* | |
| 217 | + * make sure we restore sensor characteristics, by doing | |
| 218 | + * a RESET/SET sequence | |
| 219 | + */ | |
| 220 | + ret = mmc35240_hw_set(data, false); | |
| 221 | + if (ret < 0) | |
| 222 | + return ret; | |
| 223 | + usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1); | |
| 224 | + | |
| 225 | + ret = mmc35240_hw_set(data, true); | |
| 226 | + if (ret < 0) | |
| 227 | + return ret; | |
| 228 | + | |
| 229 | + /* set default sampling frequency */ | |
| 230 | + ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, | |
| 231 | + MMC35240_CTRL1_BW_MASK, | |
| 232 | + data->res << MMC35240_CTRL1_BW_SHIFT); | |
| 233 | + if (ret < 0) | |
| 234 | + return ret; | |
| 235 | + | |
| 236 | + ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR, | |
| 237 | + (u8 *)otp_data, sizeof(otp_data)); | |
| 238 | + if (ret < 0) | |
| 239 | + return ret; | |
| 240 | + | |
| 241 | + y_convert = MMC35240_OTP_CONVERT_Y(((otp_data[1] & 0x03) << 4) | | |
| 242 | + (otp_data[2] >> 4)); | |
| 243 | + z_convert = MMC35240_OTP_CONVERT_Z(otp_data[3] & 0x3f); | |
| 244 | + | |
| 245 | + data->axis_coef[0] = MMC35240_X_COEFF(1); | |
| 246 | + data->axis_coef[1] = MMC35240_Y_COEFF(y_convert); | |
| 247 | + data->axis_coef[2] = MMC35240_Z_COEFF(z_convert); | |
| 248 | + | |
| 249 | + data->axis_scale[0] = 1; | |
| 250 | + data->axis_scale[1] = 1000; | |
| 251 | + data->axis_scale[2] = 10000; | |
| 252 | + | |
| 253 | + return 0; | |
| 254 | +} | |
| 255 | + | |
| 256 | +static int mmc35240_take_measurement(struct mmc35240_data *data) | |
| 257 | +{ | |
| 258 | + int ret, tries = 100; | |
| 259 | + unsigned int reg_status; | |
| 260 | + | |
| 261 | + ret = regmap_write(data->regmap, MMC35240_REG_CTRL0, | |
| 262 | + MMC35240_CTRL0_TM_BIT); | |
| 263 | + if (ret < 0) | |
| 264 | + return ret; | |
| 265 | + | |
| 266 | + while (tries-- > 0) { | |
| 267 | + ret = regmap_read(data->regmap, MMC35240_REG_STATUS, | |
| 268 | + ®_status); | |
| 269 | + if (ret < 0) | |
| 270 | + return ret; | |
| 271 | + if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT) | |
| 272 | + break; | |
| 273 | + /* minimum wait time to complete measurement is 10 ms */ | |
| 274 | + usleep_range(10000, 11000); | |
| 275 | + } | |
| 276 | + | |
| 277 | + if (tries < 0) { | |
| 278 | + dev_err(&data->client->dev, "data not ready\n"); | |
| 279 | + return -EIO; | |
| 280 | + } | |
| 281 | + | |
| 282 | + return 0; | |
| 283 | +} | |
| 284 | + | |
| 285 | +static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3]) | |
| 286 | +{ | |
| 287 | + int ret; | |
| 288 | + | |
| 289 | + ret = mmc35240_take_measurement(data); | |
| 290 | + if (ret < 0) | |
| 291 | + return ret; | |
| 292 | + | |
| 293 | + return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, (u8 *)buf, | |
| 294 | + 3 * sizeof(__le16)); | |
| 295 | +} | |
| 296 | + | |
| 297 | +/** | |
| 298 | + * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply | |
| 299 | + compensation for output value. | |
| 300 | + * | |
| 301 | + * @data: device private data | |
| 302 | + * @index: axis index for which we want the conversion | |
| 303 | + * @buf: raw data to be converted, 2 bytes in little endian format | |
| 304 | + * @val: compensated output reading (unit is milli gauss) | |
| 305 | + * | |
| 306 | + * Returns: 0 in case of success, -EINVAL when @index is not valid | |
| 307 | + */ | |
| 308 | +static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index, | |
| 309 | + __le16 buf[], int *val) | |
| 310 | +{ | |
| 311 | + int raw_x, raw_y, raw_z; | |
| 312 | + int sens_x, sens_y, sens_z; | |
| 313 | + int nfo; | |
| 314 | + | |
| 315 | + raw_x = le16_to_cpu(buf[AXIS_X]); | |
| 316 | + raw_y = le16_to_cpu(buf[AXIS_Y]); | |
| 317 | + raw_z = le16_to_cpu(buf[AXIS_Z]); | |
| 318 | + | |
| 319 | + sens_x = mmc35240_props_table[data->res].sens[AXIS_X]; | |
| 320 | + sens_y = mmc35240_props_table[data->res].sens[AXIS_Y]; | |
| 321 | + sens_z = mmc35240_props_table[data->res].sens[AXIS_Z]; | |
| 322 | + | |
| 323 | + nfo = mmc35240_props_table[data->res].nfo; | |
| 324 | + | |
| 325 | + switch (index) { | |
| 326 | + case AXIS_X: | |
| 327 | + *val = (raw_x - nfo) * 1000 / sens_x; | |
| 328 | + break; | |
| 329 | + case AXIS_Y: | |
| 330 | + *val = (raw_y - nfo) * 1000 / sens_y - | |
| 331 | + (raw_z - nfo) * 1000 / sens_z; | |
| 332 | + break; | |
| 333 | + case AXIS_Z: | |
| 334 | + *val = (raw_y - nfo) * 1000 / sens_y + | |
| 335 | + (raw_z - nfo) * 1000 / sens_z; | |
| 336 | + break; | |
| 337 | + default: | |
| 338 | + return -EINVAL; | |
| 339 | + } | |
| 340 | + /* apply OTP compensation */ | |
| 341 | + *val = (*val) * data->axis_coef[index] / data->axis_scale[index]; | |
| 342 | + | |
| 343 | + return 0; | |
| 344 | +} | |
| 345 | + | |
| 346 | +static int mmc35240_read_raw(struct iio_dev *indio_dev, | |
| 347 | + struct iio_chan_spec const *chan, int *val, | |
| 348 | + int *val2, long mask) | |
| 349 | +{ | |
| 350 | + struct mmc35240_data *data = iio_priv(indio_dev); | |
| 351 | + int ret, i; | |
| 352 | + unsigned int reg; | |
| 353 | + __le16 buf[3]; | |
| 354 | + | |
| 355 | + switch (mask) { | |
| 356 | + case IIO_CHAN_INFO_RAW: | |
| 357 | + mutex_lock(&data->mutex); | |
| 358 | + ret = mmc35240_read_measurement(data, buf); | |
| 359 | + mutex_unlock(&data->mutex); | |
| 360 | + if (ret < 0) | |
| 361 | + return ret; | |
| 362 | + ret = mmc35240_raw_to_mgauss(data, chan->address, buf, val); | |
| 363 | + if (ret < 0) | |
| 364 | + return ret; | |
| 365 | + return IIO_VAL_INT; | |
| 366 | + case IIO_CHAN_INFO_SCALE: | |
| 367 | + *val = 0; | |
| 368 | + *val2 = 1000; | |
| 369 | + return IIO_VAL_INT_PLUS_MICRO; | |
| 370 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 371 | + mutex_lock(&data->mutex); | |
| 372 | + ret = regmap_read(data->regmap, MMC35240_REG_CTRL1, ®); | |
| 373 | + mutex_unlock(&data->mutex); | |
| 374 | + if (ret < 0) | |
| 375 | + return ret; | |
| 376 | + | |
| 377 | + i = (reg & MMC35240_CTRL1_BW_MASK) >> MMC35240_CTRL1_BW_SHIFT; | |
| 378 | + if (i < 0 || i >= ARRAY_SIZE(mmc35240_samp_freq)) | |
| 379 | + return -EINVAL; | |
| 380 | + | |
| 381 | + *val = mmc35240_samp_freq[i]; | |
| 382 | + *val2 = 0; | |
| 383 | + return IIO_VAL_INT; | |
| 384 | + default: | |
| 385 | + return -EINVAL; | |
| 386 | + } | |
| 387 | +} | |
| 388 | + | |
| 389 | +static int mmc35240_write_raw(struct iio_dev *indio_dev, | |
| 390 | + struct iio_chan_spec const *chan, int val, | |
| 391 | + int val2, long mask) | |
| 392 | +{ | |
| 393 | + struct mmc35240_data *data = iio_priv(indio_dev); | |
| 394 | + int i, ret; | |
| 395 | + | |
| 396 | + switch (mask) { | |
| 397 | + case IIO_CHAN_INFO_SAMP_FREQ: | |
| 398 | + i = mmc35240_get_samp_freq_index(data, val, val2); | |
| 399 | + if (i < 0) | |
| 400 | + return -EINVAL; | |
| 401 | + mutex_lock(&data->mutex); | |
| 402 | + ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1, | |
| 403 | + MMC35240_CTRL1_BW_MASK, | |
| 404 | + i << MMC35240_CTRL1_BW_SHIFT); | |
| 405 | + mutex_unlock(&data->mutex); | |
| 406 | + return ret; | |
| 407 | + default: | |
| 408 | + return -EINVAL; | |
| 409 | + } | |
| 410 | +} | |
| 411 | + | |
| 412 | +static const struct iio_info mmc35240_info = { | |
| 413 | + .driver_module = THIS_MODULE, | |
| 414 | + .read_raw = mmc35240_read_raw, | |
| 415 | + .write_raw = mmc35240_write_raw, | |
| 416 | + .attrs = &mmc35240_attribute_group, | |
| 417 | +}; | |
| 418 | + | |
| 419 | +static bool mmc35240_is_writeable_reg(struct device *dev, unsigned int reg) | |
| 420 | +{ | |
| 421 | + switch (reg) { | |
| 422 | + case MMC35240_REG_CTRL0: | |
| 423 | + case MMC35240_REG_CTRL1: | |
| 424 | + return true; | |
| 425 | + default: | |
| 426 | + return false; | |
| 427 | + } | |
| 428 | +} | |
| 429 | + | |
| 430 | +static bool mmc35240_is_readable_reg(struct device *dev, unsigned int reg) | |
| 431 | +{ | |
| 432 | + switch (reg) { | |
| 433 | + case MMC35240_REG_XOUT_L: | |
| 434 | + case MMC35240_REG_XOUT_H: | |
| 435 | + case MMC35240_REG_YOUT_L: | |
| 436 | + case MMC35240_REG_YOUT_H: | |
| 437 | + case MMC35240_REG_ZOUT_L: | |
| 438 | + case MMC35240_REG_ZOUT_H: | |
| 439 | + case MMC35240_REG_STATUS: | |
| 440 | + case MMC35240_REG_ID: | |
| 441 | + return true; | |
| 442 | + default: | |
| 443 | + return false; | |
| 444 | + } | |
| 445 | +} | |
| 446 | + | |
| 447 | +static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg) | |
| 448 | +{ | |
| 449 | + switch (reg) { | |
| 450 | + case MMC35240_REG_CTRL0: | |
| 451 | + case MMC35240_REG_CTRL1: | |
| 452 | + return false; | |
| 453 | + default: | |
| 454 | + return true; | |
| 455 | + } | |
| 456 | +} | |
| 457 | + | |
| 458 | +static struct reg_default mmc35240_reg_defaults[] = { | |
| 459 | + { MMC35240_REG_CTRL0, 0x00 }, | |
| 460 | + { MMC35240_REG_CTRL1, 0x00 }, | |
| 461 | +}; | |
| 462 | + | |
| 463 | +static const struct regmap_config mmc35240_regmap_config = { | |
| 464 | + .name = MMC35240_REGMAP_NAME, | |
| 465 | + | |
| 466 | + .reg_bits = 8, | |
| 467 | + .val_bits = 8, | |
| 468 | + | |
| 469 | + .max_register = MMC35240_REG_ID, | |
| 470 | + .cache_type = REGCACHE_FLAT, | |
| 471 | + | |
| 472 | + .writeable_reg = mmc35240_is_writeable_reg, | |
| 473 | + .readable_reg = mmc35240_is_readable_reg, | |
| 474 | + .volatile_reg = mmc35240_is_volatile_reg, | |
| 475 | + | |
| 476 | + .reg_defaults = mmc35240_reg_defaults, | |
| 477 | + .num_reg_defaults = ARRAY_SIZE(mmc35240_reg_defaults), | |
| 478 | +}; | |
| 479 | + | |
| 480 | +static int mmc35240_probe(struct i2c_client *client, | |
| 481 | + const struct i2c_device_id *id) | |
| 482 | +{ | |
| 483 | + struct mmc35240_data *data; | |
| 484 | + struct iio_dev *indio_dev; | |
| 485 | + struct regmap *regmap; | |
| 486 | + int ret; | |
| 487 | + | |
| 488 | + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
| 489 | + if (!indio_dev) | |
| 490 | + return -ENOMEM; | |
| 491 | + | |
| 492 | + regmap = devm_regmap_init_i2c(client, &mmc35240_regmap_config); | |
| 493 | + if (IS_ERR(regmap)) { | |
| 494 | + dev_err(&client->dev, "regmap initialization failed\n"); | |
| 495 | + return PTR_ERR(regmap); | |
| 496 | + } | |
| 497 | + | |
| 498 | + data = iio_priv(indio_dev); | |
| 499 | + data->client = client; | |
| 500 | + data->regmap = regmap; | |
| 501 | + data->res = MMC35240_16_BITS_SLOW; | |
| 502 | + | |
| 503 | + mutex_init(&data->mutex); | |
| 504 | + | |
| 505 | + indio_dev->dev.parent = &client->dev; | |
| 506 | + indio_dev->info = &mmc35240_info; | |
| 507 | + indio_dev->name = MMC35240_DRV_NAME; | |
| 508 | + indio_dev->channels = mmc35240_channels; | |
| 509 | + indio_dev->num_channels = ARRAY_SIZE(mmc35240_channels); | |
| 510 | + indio_dev->modes = INDIO_DIRECT_MODE; | |
| 511 | + | |
| 512 | + ret = mmc35240_init(data); | |
| 513 | + if (ret < 0) { | |
| 514 | + dev_err(&client->dev, "mmc35240 chip init failed\n"); | |
| 515 | + return ret; | |
| 516 | + } | |
| 517 | + return devm_iio_device_register(&client->dev, indio_dev); | |
| 518 | +} | |
| 519 | + | |
| 520 | +#ifdef CONFIG_PM_SLEEP | |
| 521 | +static int mmc35240_suspend(struct device *dev) | |
| 522 | +{ | |
| 523 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 524 | + struct mmc35240_data *data = iio_priv(indio_dev); | |
| 525 | + | |
| 526 | + regcache_cache_only(data->regmap, true); | |
| 527 | + | |
| 528 | + return 0; | |
| 529 | +} | |
| 530 | + | |
| 531 | +static int mmc35240_resume(struct device *dev) | |
| 532 | +{ | |
| 533 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 534 | + struct mmc35240_data *data = iio_priv(indio_dev); | |
| 535 | + int ret; | |
| 536 | + | |
| 537 | + regcache_mark_dirty(data->regmap); | |
| 538 | + ret = regcache_sync_region(data->regmap, MMC35240_REG_CTRL0, | |
| 539 | + MMC35240_REG_CTRL1); | |
| 540 | + if (ret < 0) | |
| 541 | + dev_err(dev, "Failed to restore control registers\n"); | |
| 542 | + | |
| 543 | + regcache_cache_only(data->regmap, false); | |
| 544 | + | |
| 545 | + return 0; | |
| 546 | +} | |
| 547 | +#endif | |
| 548 | + | |
| 549 | +static const struct dev_pm_ops mmc35240_pm_ops = { | |
| 550 | + SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume) | |
| 551 | +}; | |
| 552 | + | |
| 553 | +static const struct acpi_device_id mmc35240_acpi_match[] = { | |
| 554 | + {"MMC35240", 0}, | |
| 555 | + { }, | |
| 556 | +}; | |
| 557 | +MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match); | |
| 558 | + | |
| 559 | +static const struct i2c_device_id mmc35240_id[] = { | |
| 560 | + {"mmc35240", 0}, | |
| 561 | + {} | |
| 562 | +}; | |
| 563 | +MODULE_DEVICE_TABLE(i2c, mmc35240_id); | |
| 564 | + | |
| 565 | +static struct i2c_driver mmc35240_driver = { | |
| 566 | + .driver = { | |
| 567 | + .name = MMC35240_DRV_NAME, | |
| 568 | + .pm = &mmc35240_pm_ops, | |
| 569 | + .acpi_match_table = ACPI_PTR(mmc35240_acpi_match), | |
| 570 | + }, | |
| 571 | + .probe = mmc35240_probe, | |
| 572 | + .id_table = mmc35240_id, | |
| 573 | +}; | |
| 574 | + | |
| 575 | +module_i2c_driver(mmc35240_driver); | |
| 576 | + | |
| 577 | +MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>"); | |
| 578 | +MODULE_DESCRIPTION("MEMSIC MMC35240 magnetic sensor driver"); | |
| 579 | +MODULE_LICENSE("GPL v2"); | |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <linux/types.h> |
| 15 | 15 | #include <linux/iio/common/st_sensors.h> |
| 16 | 16 | |
| 17 | +#define LSM303DLH_MAGN_DEV_NAME "lsm303dlh_magn" | |
| 17 | 18 | #define LSM303DLHC_MAGN_DEV_NAME "lsm303dlhc_magn" |
| 18 | 19 | #define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn" |
| 19 | 20 | #define LIS3MDL_MAGN_DEV_NAME "lis3mdl" |
| @@ -45,6 +45,46 @@ · 44 unmodified lines | ||
| 45 | 45 | #define ST_MAGN_FS_AVL_12000MG 12000 |
| 46 | 46 | #define ST_MAGN_FS_AVL_16000MG 16000 |
| 47 | 47 | |
| 48 | +/* CUSTOM VALUES FOR SENSOR 0 */ | |
| 49 | +#define ST_MAGN_0_ODR_ADDR 0x00 | |
| 50 | +#define ST_MAGN_0_ODR_MASK 0x1c | |
| 51 | +#define ST_MAGN_0_ODR_AVL_1HZ_VAL 0x00 | |
| 52 | +#define ST_MAGN_0_ODR_AVL_2HZ_VAL 0x01 | |
| 53 | +#define ST_MAGN_0_ODR_AVL_3HZ_VAL 0x02 | |
| 54 | +#define ST_MAGN_0_ODR_AVL_8HZ_VAL 0x03 | |
| 55 | +#define ST_MAGN_0_ODR_AVL_15HZ_VAL 0x04 | |
| 56 | +#define ST_MAGN_0_ODR_AVL_30HZ_VAL 0x05 | |
| 57 | +#define ST_MAGN_0_ODR_AVL_75HZ_VAL 0x06 | |
| 58 | +#define ST_MAGN_0_ODR_AVL_220HZ_VAL 0x07 | |
| 59 | +#define ST_MAGN_0_PW_ADDR 0x02 | |
| 60 | +#define ST_MAGN_0_PW_MASK 0x03 | |
| 61 | +#define ST_MAGN_0_PW_ON 0x00 | |
| 62 | +#define ST_MAGN_0_PW_OFF 0x03 | |
| 63 | +#define ST_MAGN_0_FS_ADDR 0x01 | |
| 64 | +#define ST_MAGN_0_FS_MASK 0xe0 | |
| 65 | +#define ST_MAGN_0_FS_AVL_1300_VAL 0x01 | |
| 66 | +#define ST_MAGN_0_FS_AVL_1900_VAL 0x02 | |
| 67 | +#define ST_MAGN_0_FS_AVL_2500_VAL 0x03 | |
| 68 | +#define ST_MAGN_0_FS_AVL_4000_VAL 0x04 | |
| 69 | +#define ST_MAGN_0_FS_AVL_4700_VAL 0x05 | |
| 70 | +#define ST_MAGN_0_FS_AVL_5600_VAL 0x06 | |
| 71 | +#define ST_MAGN_0_FS_AVL_8100_VAL 0x07 | |
| 72 | +#define ST_MAGN_0_FS_AVL_1300_GAIN_XY 1100 | |
| 73 | +#define ST_MAGN_0_FS_AVL_1900_GAIN_XY 855 | |
| 74 | +#define ST_MAGN_0_FS_AVL_2500_GAIN_XY 670 | |
| 75 | +#define ST_MAGN_0_FS_AVL_4000_GAIN_XY 450 | |
| 76 | +#define ST_MAGN_0_FS_AVL_4700_GAIN_XY 400 | |
| 77 | +#define ST_MAGN_0_FS_AVL_5600_GAIN_XY 330 | |
| 78 | +#define ST_MAGN_0_FS_AVL_8100_GAIN_XY 230 | |
| 79 | +#define ST_MAGN_0_FS_AVL_1300_GAIN_Z 980 | |
| 80 | +#define ST_MAGN_0_FS_AVL_1900_GAIN_Z 760 | |
| 81 | +#define ST_MAGN_0_FS_AVL_2500_GAIN_Z 600 | |
| 82 | +#define ST_MAGN_0_FS_AVL_4000_GAIN_Z 400 | |
| 83 | +#define ST_MAGN_0_FS_AVL_4700_GAIN_Z 355 | |
| 84 | +#define ST_MAGN_0_FS_AVL_5600_GAIN_Z 295 | |
| 85 | +#define ST_MAGN_0_FS_AVL_8100_GAIN_Z 205 | |
| 86 | +#define ST_MAGN_0_MULTIREAD_BIT false | |
| 87 | + | |
| 48 | 88 | /* CUSTOM VALUES FOR SENSOR 1 */ |
| 49 | 89 | #define ST_MAGN_1_WAI_EXP 0x3c |
| 50 | 90 | #define ST_MAGN_1_ODR_ADDR 0x00 |
| @@ -150,6 +190,82 @@ static const struct iio_chan_spec st_magn_2_16bit_channels[] = { · 99 unmodified lines | ||
| 150 | 190 | }; |
| 151 | 191 | |
| 152 | 192 | static const struct st_sensor_settings st_magn_sensors_settings[] = { |
| 193 | + { | |
| 194 | + .wai = 0, /* This sensor has no valid WhoAmI report 0 */ | |
| 195 | + .sensors_supported = { | |
| 196 | + [0] = LSM303DLH_MAGN_DEV_NAME, | |
| 197 | + }, | |
| 198 | + .ch = (struct iio_chan_spec *)st_magn_16bit_channels, | |
| 199 | + .odr = { | |
| 200 | + .addr = ST_MAGN_0_ODR_ADDR, | |
| 201 | + .mask = ST_MAGN_0_ODR_MASK, | |
| 202 | + .odr_avl = { | |
| 203 | + { 1, ST_MAGN_0_ODR_AVL_1HZ_VAL, }, | |
| 204 | + { 2, ST_MAGN_0_ODR_AVL_2HZ_VAL, }, | |
| 205 | + { 3, ST_MAGN_0_ODR_AVL_3HZ_VAL, }, | |
| 206 | + { 8, ST_MAGN_0_ODR_AVL_8HZ_VAL, }, | |
| 207 | + { 15, ST_MAGN_0_ODR_AVL_15HZ_VAL, }, | |
| 208 | + { 30, ST_MAGN_0_ODR_AVL_30HZ_VAL, }, | |
| 209 | + { 75, ST_MAGN_0_ODR_AVL_75HZ_VAL, }, | |
| 210 | + }, | |
| 211 | + }, | |
| 212 | + .pw = { | |
| 213 | + .addr = ST_MAGN_0_PW_ADDR, | |
| 214 | + .mask = ST_MAGN_0_PW_MASK, | |
| 215 | + .value_on = ST_MAGN_0_PW_ON, | |
| 216 | + .value_off = ST_MAGN_0_PW_OFF, | |
| 217 | + }, | |
| 218 | + .fs = { | |
| 219 | + .addr = ST_MAGN_0_FS_ADDR, | |
| 220 | + .mask = ST_MAGN_0_FS_MASK, | |
| 221 | + .fs_avl = { | |
| 222 | + [0] = { | |
| 223 | + .num = ST_MAGN_FS_AVL_1300MG, | |
| 224 | + .value = ST_MAGN_0_FS_AVL_1300_VAL, | |
| 225 | + .gain = ST_MAGN_0_FS_AVL_1300_GAIN_XY, | |
| 226 | + .gain2 = ST_MAGN_0_FS_AVL_1300_GAIN_Z, | |
| 227 | + }, | |
| 228 | + [1] = { | |
| 229 | + .num = ST_MAGN_FS_AVL_1900MG, | |
| 230 | + .value = ST_MAGN_0_FS_AVL_1900_VAL, | |
| 231 | + .gain = ST_MAGN_0_FS_AVL_1900_GAIN_XY, | |
| 232 | + .gain2 = ST_MAGN_0_FS_AVL_1900_GAIN_Z, | |
| 233 | + }, | |
| 234 | + [2] = { | |
| 235 | + .num = ST_MAGN_FS_AVL_2500MG, | |
| 236 | + .value = ST_MAGN_0_FS_AVL_2500_VAL, | |
| 237 | + .gain = ST_MAGN_0_FS_AVL_2500_GAIN_XY, | |
| 238 | + .gain2 = ST_MAGN_0_FS_AVL_2500_GAIN_Z, | |
| 239 | + }, | |
| 240 | + [3] = { | |
| 241 | + .num = ST_MAGN_FS_AVL_4000MG, | |
| 242 | + .value = ST_MAGN_0_FS_AVL_4000_VAL, | |
| 243 | + .gain = ST_MAGN_0_FS_AVL_4000_GAIN_XY, | |
| 244 | + .gain2 = ST_MAGN_0_FS_AVL_4000_GAIN_Z, | |
| 245 | + }, | |
| 246 | + [4] = { | |
| 247 | + .num = ST_MAGN_FS_AVL_4700MG, | |
| 248 | + .value = ST_MAGN_0_FS_AVL_4700_VAL, | |
| 249 | + .gain = ST_MAGN_0_FS_AVL_4700_GAIN_XY, | |
| 250 | + .gain2 = ST_MAGN_0_FS_AVL_4700_GAIN_Z, | |
| 251 | + }, | |
| 252 | + [5] = { | |
| 253 | + .num = ST_MAGN_FS_AVL_5600MG, | |
| 254 | + .value = ST_MAGN_0_FS_AVL_5600_VAL, | |
| 255 | + .gain = ST_MAGN_0_FS_AVL_5600_GAIN_XY, | |
| 256 | + .gain2 = ST_MAGN_0_FS_AVL_5600_GAIN_Z, | |
| 257 | + }, | |
| 258 | + [6] = { | |
| 259 | + .num = ST_MAGN_FS_AVL_8100MG, | |
| 260 | + .value = ST_MAGN_0_FS_AVL_8100_VAL, | |
| 261 | + .gain = ST_MAGN_0_FS_AVL_8100_GAIN_XY, | |
| 262 | + .gain2 = ST_MAGN_0_FS_AVL_8100_GAIN_Z, | |
| 263 | + }, | |
| 264 | + }, | |
| 265 | + }, | |
| 266 | + .multi_read_bit = ST_MAGN_0_MULTIREAD_BIT, | |
| 267 | + .bootime = 2, | |
| 268 | + }, | |
| 153 | 269 | { |
| 154 | 270 | .wai = ST_MAGN_1_WAI_EXP, |
| 155 | 271 | .sensors_supported = { |
| @@ -20,6 +20,10 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | #ifdef CONFIG_OF |
| 22 | 22 | static const struct of_device_id st_magn_of_match[] = { |
| 23 | + { | |
| 24 | + .compatible = "st,lsm303dlh-magn", | |
| 25 | + .data = LSM303DLH_MAGN_DEV_NAME, | |
| 26 | + }, | |
| 23 | 27 | { |
| 24 | 28 | .compatible = "st,lsm303dlhc-magn", |
| 25 | 29 | .data = LSM303DLHC_MAGN_DEV_NAME, |
| @@ -71,6 +75,7 @@ static int st_magn_i2c_remove(struct i2c_client *client) · 45 unmodified lines | ||
| 71 | 75 | } |
| 72 | 76 | |
| 73 | 77 | static const struct i2c_device_id st_magn_id_table[] = { |
| 78 | + { LSM303DLH_MAGN_DEV_NAME }, | |
| 74 | 79 | { LSM303DLHC_MAGN_DEV_NAME }, |
| 75 | 80 | { LSM303DLM_MAGN_DEV_NAME }, |
| 76 | 81 | { LIS3MDL_MAGN_DEV_NAME }, |
| @@ -315,7 +315,6 @@ static int hid_incl_3d_probe(struct platform_device *pdev) · 314 unmodified lines | ||
| 315 | 315 | struct iio_dev *indio_dev; |
| 316 | 316 | struct incl_3d_state *incl_state; |
| 317 | 317 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 318 | − struct iio_chan_spec *channels; | |
| 319 | 318 | |
| 320 | 319 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 321 | 320 | sizeof(struct incl_3d_state)); |
| @@ -336,21 +335,22 @@ static int hid_incl_3d_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 336 | 335 | return ret; |
| 337 | 336 | } |
| 338 | 337 | |
| 339 | − channels = kmemdup(incl_3d_channels, sizeof(incl_3d_channels), | |
| 340 | − GFP_KERNEL); | |
| 341 | − if (!channels) { | |
| 338 | + indio_dev->channels = kmemdup(incl_3d_channels, | |
| 339 | + sizeof(incl_3d_channels), GFP_KERNEL); | |
| 340 | + if (!indio_dev->channels) { | |
| 342 | 341 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 343 | 342 | return -ENOMEM; |
| 344 | 343 | } |
| 345 | 344 | |
| 346 | − ret = incl_3d_parse_report(pdev, hsdev, channels, | |
| 347 | − HID_USAGE_SENSOR_INCLINOMETER_3D, incl_state); | |
| 345 | + ret = incl_3d_parse_report(pdev, hsdev, | |
| 346 | + (struct iio_chan_spec *)indio_dev->channels, | |
| 347 | + HID_USAGE_SENSOR_INCLINOMETER_3D, | |
| 348 | + incl_state); | |
| 348 | 349 | if (ret) { |
| 349 | 350 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 350 | 351 | goto error_free_dev_mem; |
| 351 | 352 | } |
| 352 | 353 | |
| 353 | − indio_dev->channels = channels; | |
| 354 | 354 | indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels); |
| 355 | 355 | indio_dev->dev.parent = &pdev->dev; |
| 356 | 356 | indio_dev->info = &incl_3d_info; |
| @@ -417,7 +417,7 @@ static int hid_incl_3d_remove(struct platform_device *pdev) · 60 unmodified lines | ||
| 417 | 417 | return 0; |
| 418 | 418 | } |
| 419 | 419 | |
| 420 | −static struct platform_device_id hid_incl_3d_ids[] = { | |
| 420 | +static const struct platform_device_id hid_incl_3d_ids[] = { | |
| 421 | 421 | { |
| 422 | 422 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 423 | 423 | .name = "HID-SENSOR-200086", |
| @@ -222,7 +222,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev) · 221 unmodified lines | ||
| 222 | 222 | struct iio_dev *indio_dev; |
| 223 | 223 | struct dev_rot_state *rot_state; |
| 224 | 224 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 225 | − struct iio_chan_spec *channels; | |
| 226 | 225 | |
| 227 | 226 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 228 | 227 | sizeof(struct dev_rot_state)); |
| @@ -243,21 +242,23 @@ static int hid_dev_rot_probe(struct platform_device *pdev) · 14 unmodified lines | ||
| 243 | 242 | return ret; |
| 244 | 243 | } |
| 245 | 244 | |
| 246 | − channels = devm_kmemdup(&pdev->dev, dev_rot_channels, | |
| 247 | − sizeof(dev_rot_channels), GFP_KERNEL); | |
| 248 | − if (!channels) { | |
| 245 | + indio_dev->channels = devm_kmemdup(&pdev->dev, dev_rot_channels, | |
| 246 | + sizeof(dev_rot_channels), | |
| 247 | + GFP_KERNEL); | |
| 248 | + if (!indio_dev->channels) { | |
| 249 | 249 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 250 | 250 | return -ENOMEM; |
| 251 | 251 | } |
| 252 | 252 | |
| 253 | − ret = dev_rot_parse_report(pdev, hsdev, channels, | |
| 254 | − HID_USAGE_SENSOR_DEVICE_ORIENTATION, rot_state); | |
| 253 | + ret = dev_rot_parse_report(pdev, hsdev, | |
| 254 | + (struct iio_chan_spec *)indio_dev->channels, | |
| 255 | + HID_USAGE_SENSOR_DEVICE_ORIENTATION, | |
| 256 | + rot_state); | |
| 255 | 257 | if (ret) { |
| 256 | 258 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 257 | 259 | return ret; |
| 258 | 260 | } |
| 259 | 261 | |
| 260 | − indio_dev->channels = channels; | |
| 261 | 262 | indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); |
| 262 | 263 | indio_dev->dev.parent = &pdev->dev; |
| 263 | 264 | indio_dev->info = &dev_rot_info; |
| @@ -321,7 +322,7 @@ static int hid_dev_rot_remove(struct platform_device *pdev) · 57 unmodified lines | ||
| 321 | 322 | return 0; |
| 322 | 323 | } |
| 323 | 324 | |
| 324 | −static struct platform_device_id hid_dev_rot_ids[] = { | |
| 325 | +static const struct platform_device_id hid_dev_rot_ids[] = { | |
| 325 | 326 | { |
| 326 | 327 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 327 | 328 | .name = "HID-SENSOR-20008a", |
| @@ -260,7 +260,6 @@ static int hid_press_probe(struct platform_device *pdev) · 259 unmodified lines | ||
| 260 | 260 | struct iio_dev *indio_dev; |
| 261 | 261 | struct press_state *press_state; |
| 262 | 262 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 263 | − struct iio_chan_spec *channels; | |
| 264 | 263 | |
| 265 | 264 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 266 | 265 | sizeof(struct press_state)); |
| @@ -280,20 +279,21 @@ static int hid_press_probe(struct platform_device *pdev) · 13 unmodified lines | ||
| 280 | 279 | return ret; |
| 281 | 280 | } |
| 282 | 281 | |
| 283 | − channels = kmemdup(press_channels, sizeof(press_channels), GFP_KERNEL); | |
| 284 | − if (!channels) { | |
| 282 | + indio_dev->channels = kmemdup(press_channels, sizeof(press_channels), | |
| 283 | + GFP_KERNEL); | |
| 284 | + if (!indio_dev->channels) { | |
| 285 | 285 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 286 | 286 | return -ENOMEM; |
| 287 | 287 | } |
| 288 | 288 | |
| 289 | − ret = press_parse_report(pdev, hsdev, channels, | |
| 290 | − HID_USAGE_SENSOR_PRESSURE, press_state); | |
| 289 | + ret = press_parse_report(pdev, hsdev, | |
| 290 | + (struct iio_chan_spec *)indio_dev->channels, | |
| 291 | + HID_USAGE_SENSOR_PRESSURE, press_state); | |
| 291 | 292 | if (ret) { |
| 292 | 293 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 293 | 294 | goto error_free_dev_mem; |
| 294 | 295 | } |
| 295 | 296 | |
| 296 | − indio_dev->channels = channels; | |
| 297 | 297 | indio_dev->num_channels = |
| 298 | 298 | ARRAY_SIZE(press_channels); |
| 299 | 299 | indio_dev->dev.parent = &pdev->dev; |
| @@ -360,7 +360,7 @@ static int hid_press_remove(struct platform_device *pdev) · 60 unmodified lines | ||
| 360 | 360 | return 0; |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | −static struct platform_device_id hid_press_ids[] = { | |
| 363 | +static const struct platform_device_id hid_press_ids[] = { | |
| 364 | 364 | { |
| 365 | 365 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 366 | 366 | .name = "HID-SENSOR-200031", |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/acpi.h> |
| 19 | 19 | #include <linux/gpio/consumer.h> |
| 20 | 20 | #include <linux/regmap.h> |
| 21 | +#include <linux/pm.h> | |
| 22 | +#include <linux/delay.h> | |
| 21 | 23 | |
| 22 | 24 | #include <linux/iio/iio.h> |
| 23 | 25 | #include <linux/iio/buffer.h> |
| @@ -29,7 +31,9 @@ · 5 unmodified lines | ||
| 29 | 31 | |
| 30 | 32 | #define SX9500_DRIVER_NAME "sx9500" |
| 31 | 33 | #define SX9500_IRQ_NAME "sx9500_event" |
| 32 | −#define SX9500_GPIO_NAME "sx9500_gpio" | |
| 34 | + | |
| 35 | +#define SX9500_GPIO_INT "interrupt" | |
| 36 | +#define SX9500_GPIO_RESET "reset" | |
| 33 | 37 | |
| 34 | 38 | /* Register definitions. */ |
| 35 | 39 | #define SX9500_REG_IRQ_SRC 0x00 |
| @@ -73,6 +77,7 @@ · 37 unmodified lines | ||
| 73 | 77 | #define SX9500_CONVDONE_IRQ BIT(3) |
| 74 | 78 | |
| 75 | 79 | #define SX9500_PROXSTAT_SHIFT 4 |
| 80 | +#define SX9500_COMPSTAT_MASK GENMASK(3, 0) | |
| 76 | 81 | |
| 77 | 82 | #define SX9500_NUM_CHANNELS 4 |
| 78 | 83 | |
| @@ -81,6 +86,7 @@ struct sx9500_data { · 2 unmodified lines | ||
| 81 | 86 | struct i2c_client *client; |
| 82 | 87 | struct iio_trigger *trig; |
| 83 | 88 | struct regmap *regmap; |
| 89 | + struct gpio_desc *gpiod_rst; | |
| 84 | 90 | /* |
| 85 | 91 | * Last reading of the proximity status for each channel. We |
| 86 | 92 | * only send an event to user space when this changes. |
| @@ -89,6 +95,11 @@ struct sx9500_data { · 2 unmodified lines | ||
| 89 | 95 | bool event_enabled[SX9500_NUM_CHANNELS]; |
| 90 | 96 | bool trigger_enabled; |
| 91 | 97 | u16 *buffer; |
| 98 | + /* Remember enabled channels and sample rate during suspend. */ | |
| 99 | + unsigned int suspend_ctrl0; | |
| 100 | + struct completion completion; | |
| 101 | + int data_rdy_users, close_far_users; | |
| 102 | + int channel_users[SX9500_NUM_CHANNELS]; | |
| 92 | 103 | }; |
| 93 | 104 | |
| 94 | 105 | static const struct iio_event_spec sx9500_events[] = { |
| @@ -139,6 +150,10 @@ static const struct { · 44 unmodified lines | ||
| 139 | 150 | {2, 500000}, |
| 140 | 151 | }; |
| 141 | 152 | |
| 153 | +static const unsigned int sx9500_scan_period_table[] = { | |
| 154 | + 30, 60, 90, 120, 150, 200, 300, 400, | |
| 155 | +}; | |
| 156 | + | |
| 142 | 157 | static const struct regmap_range sx9500_writable_reg_ranges[] = { |
| 143 | 158 | regmap_reg_range(SX9500_REG_IRQ_MSK, SX9500_REG_IRQ_MSK), |
| 144 | 159 | regmap_reg_range(SX9500_REG_PROX_CTRL0, SX9500_REG_PROX_CTRL8), |
| @@ -191,7 +206,67 @@ static const struct regmap_config sx9500_regmap_config = { · 46 unmodified lines | ||
| 191 | 206 | .volatile_table = &sx9500_volatile_regs, |
| 192 | 207 | }; |
| 193 | 208 | |
| 194 | −static int sx9500_read_proximity(struct sx9500_data *data, | |
| 209 | +static int sx9500_inc_users(struct sx9500_data *data, int *counter, | |
| 210 | + unsigned int reg, unsigned int bitmask) | |
| 211 | +{ | |
| 212 | + (*counter)++; | |
| 213 | + if (*counter != 1) | |
| 214 | + /* Bit is already active, nothing to do. */ | |
| 215 | + return 0; | |
| 216 | + | |
| 217 | + return regmap_update_bits(data->regmap, reg, bitmask, bitmask); | |
| 218 | +} | |
| 219 | + | |
| 220 | +static int sx9500_dec_users(struct sx9500_data *data, int *counter, | |
| 221 | + unsigned int reg, unsigned int bitmask) | |
| 222 | +{ | |
| 223 | + (*counter)--; | |
| 224 | + if (*counter != 0) | |
| 225 | + /* There are more users, do not deactivate. */ | |
| 226 | + return 0; | |
| 227 | + | |
| 228 | + return regmap_update_bits(data->regmap, reg, bitmask, 0); | |
| 229 | +} | |
| 230 | + | |
| 231 | +static int sx9500_inc_chan_users(struct sx9500_data *data, int chan) | |
| 232 | +{ | |
| 233 | + return sx9500_inc_users(data, &data->channel_users[chan], | |
| 234 | + SX9500_REG_PROX_CTRL0, BIT(chan)); | |
| 235 | +} | |
| 236 | + | |
| 237 | +static int sx9500_dec_chan_users(struct sx9500_data *data, int chan) | |
| 238 | +{ | |
| 239 | + return sx9500_dec_users(data, &data->channel_users[chan], | |
| 240 | + SX9500_REG_PROX_CTRL0, BIT(chan)); | |
| 241 | +} | |
| 242 | + | |
| 243 | +static int sx9500_inc_data_rdy_users(struct sx9500_data *data) | |
| 244 | +{ | |
| 245 | + return sx9500_inc_users(data, &data->data_rdy_users, | |
| 246 | + SX9500_REG_IRQ_MSK, SX9500_CONVDONE_IRQ); | |
| 247 | +} | |
| 248 | + | |
| 249 | +static int sx9500_dec_data_rdy_users(struct sx9500_data *data) | |
| 250 | +{ | |
| 251 | + return sx9500_dec_users(data, &data->data_rdy_users, | |
| 252 | + SX9500_REG_IRQ_MSK, SX9500_CONVDONE_IRQ); | |
| 253 | +} | |
| 254 | + | |
| 255 | +static int sx9500_inc_close_far_users(struct sx9500_data *data) | |
| 256 | +{ | |
| 257 | + return sx9500_inc_users(data, &data->close_far_users, | |
| 258 | + SX9500_REG_IRQ_MSK, | |
| 259 | + SX9500_CLOSE_IRQ | SX9500_FAR_IRQ); | |
| 260 | +} | |
| 261 | + | |
| 262 | +static int sx9500_dec_close_far_users(struct sx9500_data *data) | |
| 263 | +{ | |
| 264 | + return sx9500_dec_users(data, &data->close_far_users, | |
| 265 | + SX9500_REG_IRQ_MSK, | |
| 266 | + SX9500_CLOSE_IRQ | SX9500_FAR_IRQ); | |
| 267 | +} | |
| 268 | + | |
| 269 | +static int sx9500_read_prox_data(struct sx9500_data *data, | |
| 195 | 270 | const struct iio_chan_spec *chan, |
| 196 | 271 | int *val) |
| 197 | 272 | { |
| @@ -211,6 +286,79 @@ static int sx9500_read_proximity(struct sx9500_data *data, · 13 unmodified lines | ||
| 211 | 286 | return IIO_VAL_INT; |
| 212 | 287 | } |
| 213 | 288 | |
| 289 | +/* | |
| 290 | + * If we have no interrupt support, we have to wait for a scan period | |
| 291 | + * after enabling a channel to get a result. | |
| 292 | + */ | |
| 293 | +static int sx9500_wait_for_sample(struct sx9500_data *data) | |
| 294 | +{ | |
| 295 | + int ret; | |
| 296 | + unsigned int val; | |
| 297 | + | |
| 298 | + ret = regmap_read(data->regmap, SX9500_REG_PROX_CTRL0, &val); | |
| 299 | + if (ret < 0) | |
| 300 | + return ret; | |
| 301 | + | |
| 302 | + val = (val & SX9500_SCAN_PERIOD_MASK) >> SX9500_SCAN_PERIOD_SHIFT; | |
| 303 | + | |
| 304 | + msleep(sx9500_scan_period_table[val]); | |
| 305 | + | |
| 306 | + return 0; | |
| 307 | +} | |
| 308 | + | |
| 309 | +static int sx9500_read_proximity(struct sx9500_data *data, | |
| 310 | + const struct iio_chan_spec *chan, | |
| 311 | + int *val) | |
| 312 | +{ | |
| 313 | + int ret; | |
| 314 | + | |
| 315 | + mutex_lock(&data->mutex); | |
| 316 | + | |
| 317 | + ret = sx9500_inc_chan_users(data, chan->channel); | |
| 318 | + if (ret < 0) | |
| 319 | + goto out; | |
| 320 | + | |
| 321 | + ret = sx9500_inc_data_rdy_users(data); | |
| 322 | + if (ret < 0) | |
| 323 | + goto out_dec_chan; | |
| 324 | + | |
| 325 | + mutex_unlock(&data->mutex); | |
| 326 | + | |
| 327 | + if (data->client->irq > 0) | |
| 328 | + ret = wait_for_completion_interruptible(&data->completion); | |
| 329 | + else | |
| 330 | + ret = sx9500_wait_for_sample(data); | |
| 331 | + | |
| 332 | + if (ret < 0) | |
| 333 | + return ret; | |
| 334 | + | |
| 335 | + mutex_lock(&data->mutex); | |
| 336 | + | |
| 337 | + ret = sx9500_read_prox_data(data, chan, val); | |
| 338 | + if (ret < 0) | |
| 339 | + goto out; | |
| 340 | + | |
| 341 | + ret = sx9500_dec_chan_users(data, chan->channel); | |
| 342 | + if (ret < 0) | |
| 343 | + goto out; | |
| 344 | + | |
| 345 | + ret = sx9500_dec_data_rdy_users(data); | |
| 346 | + if (ret < 0) | |
| 347 | + goto out; | |
| 348 | + | |
| 349 | + ret = IIO_VAL_INT; | |
| 350 | + | |
| 351 | + goto out; | |
| 352 | + | |
| 353 | +out_dec_chan: | |
| 354 | + sx9500_dec_chan_users(data, chan->channel); | |
| 355 | +out: | |
| 356 | + mutex_unlock(&data->mutex); | |
| 357 | + reinit_completion(&data->completion); | |
| 358 | + | |
| 359 | + return ret; | |
| 360 | +} | |
| 361 | + | |
| 214 | 362 | static int sx9500_read_samp_freq(struct sx9500_data *data, |
| 215 | 363 | int *val, int *val2) |
| 216 | 364 | { |
| @@ -236,7 +384,6 @@ static int sx9500_read_raw(struct iio_dev *indio_dev, · 19 unmodified lines | ||
| 236 | 384 | int *val, int *val2, long mask) |
| 237 | 385 | { |
| 238 | 386 | struct sx9500_data *data = iio_priv(indio_dev); |
| 239 | − int ret; | |
| 240 | 387 | |
| 241 | 388 | switch (chan->type) { |
| 242 | 389 | case IIO_PROXIMITY: |
| @@ -244,10 +391,7 @@ static int sx9500_read_raw(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 244 | 391 | case IIO_CHAN_INFO_RAW: |
| 245 | 392 | if (iio_buffer_enabled(indio_dev)) |
| 246 | 393 | return -EBUSY; |
| 247 | − mutex_lock(&data->mutex); | |
| 248 | − ret = sx9500_read_proximity(data, chan, val); | |
| 249 | − mutex_unlock(&data->mutex); | |
| 250 | − return ret; | |
| 394 | + return sx9500_read_proximity(data, chan, val); | |
| 251 | 395 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 252 | 396 | return sx9500_read_samp_freq(data, val, val2); |
| 253 | 397 | default: |
| @@ -318,28 +462,16 @@ static irqreturn_t sx9500_irq_handler(int irq, void *private) · 64 unmodified lines | ||
| 318 | 462 | return IRQ_WAKE_THREAD; |
| 319 | 463 | } |
| 320 | 464 | |
| 321 | −static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) | |
| 465 | +static void sx9500_push_events(struct iio_dev *indio_dev) | |
| 322 | 466 | { |
| 323 | − struct iio_dev *indio_dev = private; | |
| 324 | − struct sx9500_data *data = iio_priv(indio_dev); | |
| 325 | 467 | int ret; |
| 326 | 468 | unsigned int val, chan; |
| 327 | − | |
| 328 | − mutex_lock(&data->mutex); | |
| 329 | − | |
| 330 | − ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); | |
| 331 | − if (ret < 0) { | |
| 332 | − dev_err(&data->client->dev, "i2c transfer error in irq\n"); | |
| 333 | − goto out; | |
| 334 | − } | |
| 335 | − | |
| 336 | − if (!(val & (SX9500_CLOSE_IRQ | SX9500_FAR_IRQ))) | |
| 337 | − goto out; | |
| 469 | + struct sx9500_data *data = iio_priv(indio_dev); | |
| 338 | 470 | |
| 339 | 471 | ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); |
| 340 | 472 | if (ret < 0) { |
| 341 | 473 | dev_err(&data->client->dev, "i2c transfer error in irq\n"); |
| 342 | − goto out; | |
| 474 | + return; | |
| 343 | 475 | } |
| 344 | 476 | |
| 345 | 477 | val >>= SX9500_PROXSTAT_SHIFT; |
| @@ -354,15 +486,34 @@ static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) · 8 unmodified lines | ||
| 354 | 486 | /* No change on this channel. */ |
| 355 | 487 | continue; |
| 356 | 488 | |
| 357 | − dir = new_prox ? IIO_EV_DIR_FALLING : | |
| 358 | − IIO_EV_DIR_RISING; | |
| 359 | − ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, | |
| 360 | − chan, | |
| 361 | − IIO_EV_TYPE_THRESH, | |
| 362 | − dir); | |
| 489 | + dir = new_prox ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING; | |
| 490 | + ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan, | |
| 491 | + IIO_EV_TYPE_THRESH, dir); | |
| 363 | 492 | iio_push_event(indio_dev, ev, iio_get_time_ns()); |
| 364 | 493 | data->prox_stat[chan] = new_prox; |
| 365 | 494 | } |
| 495 | +} | |
| 496 | + | |
| 497 | +static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) | |
| 498 | +{ | |
| 499 | + struct iio_dev *indio_dev = private; | |
| 500 | + struct sx9500_data *data = iio_priv(indio_dev); | |
| 501 | + int ret; | |
| 502 | + unsigned int val; | |
| 503 | + | |
| 504 | + mutex_lock(&data->mutex); | |
| 505 | + | |
| 506 | + ret = regmap_read(data->regmap, SX9500_REG_IRQ_SRC, &val); | |
| 507 | + if (ret < 0) { | |
| 508 | + dev_err(&data->client->dev, "i2c transfer error in irq\n"); | |
| 509 | + goto out; | |
| 510 | + } | |
| 511 | + | |
| 512 | + if (val & (SX9500_CLOSE_IRQ | SX9500_FAR_IRQ)) | |
| 513 | + sx9500_push_events(indio_dev); | |
| 514 | + | |
| 515 | + if (val & SX9500_CONVDONE_IRQ) | |
| 516 | + complete_all(&data->completion); | |
| 366 | 517 | |
| 367 | 518 | out: |
| 368 | 519 | mutex_unlock(&data->mutex); |
| @@ -391,9 +542,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev, · 22 unmodified lines | ||
| 391 | 542 | int state) |
| 392 | 543 | { |
| 393 | 544 | struct sx9500_data *data = iio_priv(indio_dev); |
| 394 | − int ret, i; | |
| 395 | − bool any_active = false; | |
| 396 | − unsigned int irqmask; | |
| 545 | + int ret; | |
| 397 | 546 | |
| 398 | 547 | if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || |
| 399 | 548 | dir != IIO_EV_DIR_EITHER) |
| @@ -401,24 +550,32 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev, · 1 unmodified line | ||
| 401 | 550 | |
| 402 | 551 | mutex_lock(&data->mutex); |
| 403 | 552 | |
| 404 | − data->event_enabled[chan->channel] = state; | |
| 553 | + if (state == 1) { | |
| 554 | + ret = sx9500_inc_chan_users(data, chan->channel); | |
| 555 | + if (ret < 0) | |
| 556 | + goto out_unlock; | |
| 557 | + ret = sx9500_inc_close_far_users(data); | |
| 558 | + if (ret < 0) | |
| 559 | + goto out_undo_chan; | |
| 560 | + } else { | |
| 561 | + ret = sx9500_dec_chan_users(data, chan->channel); | |
| 562 | + if (ret < 0) | |
| 563 | + goto out_unlock; | |
| 564 | + ret = sx9500_dec_close_far_users(data); | |
| 565 | + if (ret < 0) | |
| 566 | + goto out_undo_chan; | |
| 567 | + } | |
| 405 | 568 | |
| 406 | − for (i = 0; i < SX9500_NUM_CHANNELS; i++) | |
| 407 | − if (data->event_enabled[i]) { | |
| 408 | − any_active = true; | |
| 409 | − break; | |
| 410 | − } | |
| 569 | + data->event_enabled[chan->channel] = state; | |
| 570 | + goto out_unlock; | |
| 411 | 571 | |
| 412 | − irqmask = SX9500_CLOSE_IRQ | SX9500_FAR_IRQ; | |
| 413 | − if (any_active) | |
| 414 | − ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, | |
| 415 | − irqmask, irqmask); | |
| 572 | +out_undo_chan: | |
| 573 | + if (state == 1) | |
| 574 | + sx9500_dec_chan_users(data, chan->channel); | |
| 416 | 575 | else |
| 417 | − ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, | |
| 418 | − irqmask, 0); | |
| 419 | − | |
| 576 | + sx9500_inc_chan_users(data, chan->channel); | |
| 577 | +out_unlock: | |
| 420 | 578 | mutex_unlock(&data->mutex); |
| 421 | − | |
| 422 | 579 | return ret; |
| 423 | 580 | } |
| 424 | 581 | |
| @@ -469,12 +626,16 @@ static int sx9500_set_trigger_state(struct iio_trigger *trig, · 44 unmodified lines | ||
| 469 | 626 | |
| 470 | 627 | mutex_lock(&data->mutex); |
| 471 | 628 | |
| 472 | − ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, | |
| 473 | − SX9500_CONVDONE_IRQ, | |
| 474 | − state ? SX9500_CONVDONE_IRQ : 0); | |
| 475 | − if (ret == 0) | |
| 476 | − data->trigger_enabled = state; | |
| 629 | + if (state) | |
| 630 | + ret = sx9500_inc_data_rdy_users(data); | |
| 631 | + else | |
| 632 | + ret = sx9500_dec_data_rdy_users(data); | |
| 633 | + if (ret < 0) | |
| 634 | + goto out; | |
| 635 | + | |
| 636 | + data->trigger_enabled = state; | |
| 477 | 637 | |
| 638 | +out: | |
| 478 | 639 | mutex_unlock(&data->mutex); |
| 479 | 640 | |
| 480 | 641 | return ret; |
| @@ -496,7 +657,7 @@ static irqreturn_t sx9500_trigger_handler(int irq, void *private) · 15 unmodified lines | ||
| 496 | 657 | |
| 497 | 658 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
| 498 | 659 | indio_dev->masklength) { |
| 499 | − ret = sx9500_read_proximity(data, &indio_dev->channels[bit], | |
| 660 | + ret = sx9500_read_prox_data(data, &indio_dev->channels[bit], | |
| 500 | 661 | &val); |
| 501 | 662 | if (ret < 0) |
| 502 | 663 | goto out; |
| @@ -515,6 +676,62 @@ out: · 12 unmodified lines | ||
| 515 | 676 | return IRQ_HANDLED; |
| 516 | 677 | } |
| 517 | 678 | |
| 679 | +static int sx9500_buffer_preenable(struct iio_dev *indio_dev) | |
| 680 | +{ | |
| 681 | + struct sx9500_data *data = iio_priv(indio_dev); | |
| 682 | + int ret, i; | |
| 683 | + | |
| 684 | + mutex_lock(&data->mutex); | |
| 685 | + | |
| 686 | + for (i = 0; i < SX9500_NUM_CHANNELS; i++) | |
| 687 | + if (test_bit(i, indio_dev->active_scan_mask)) { | |
| 688 | + ret = sx9500_inc_chan_users(data, i); | |
| 689 | + if (ret) | |
| 690 | + break; | |
| 691 | + } | |
| 692 | + | |
| 693 | + if (ret) | |
| 694 | + for (i = i - 1; i >= 0; i--) | |
| 695 | + if (test_bit(i, indio_dev->active_scan_mask)) | |
| 696 | + sx9500_dec_chan_users(data, i); | |
| 697 | + | |
| 698 | + mutex_unlock(&data->mutex); | |
| 699 | + | |
| 700 | + return ret; | |
| 701 | +} | |
| 702 | + | |
| 703 | +static int sx9500_buffer_predisable(struct iio_dev *indio_dev) | |
| 704 | +{ | |
| 705 | + struct sx9500_data *data = iio_priv(indio_dev); | |
| 706 | + int ret, i; | |
| 707 | + | |
| 708 | + iio_triggered_buffer_predisable(indio_dev); | |
| 709 | + | |
| 710 | + mutex_lock(&data->mutex); | |
| 711 | + | |
| 712 | + for (i = 0; i < SX9500_NUM_CHANNELS; i++) | |
| 713 | + if (test_bit(i, indio_dev->active_scan_mask)) { | |
| 714 | + ret = sx9500_dec_chan_users(data, i); | |
| 715 | + if (ret) | |
| 716 | + break; | |
| 717 | + } | |
| 718 | + | |
| 719 | + if (ret) | |
| 720 | + for (i = i - 1; i >= 0; i--) | |
| 721 | + if (test_bit(i, indio_dev->active_scan_mask)) | |
| 722 | + sx9500_inc_chan_users(data, i); | |
| 723 | + | |
| 724 | + mutex_unlock(&data->mutex); | |
| 725 | + | |
| 726 | + return ret; | |
| 727 | +} | |
| 728 | + | |
| 729 | +static const struct iio_buffer_setup_ops sx9500_buffer_setup_ops = { | |
| 730 | + .preenable = sx9500_buffer_preenable, | |
| 731 | + .postenable = iio_triggered_buffer_postenable, | |
| 732 | + .predisable = sx9500_buffer_predisable, | |
| 733 | +}; | |
| 734 | + | |
| 518 | 735 | struct sx9500_reg_default { |
| 519 | 736 | u8 reg; |
| 520 | 737 | u8 def; |
| @@ -570,17 +787,57 @@ static const struct sx9500_reg_default sx9500_default_regs[] = { · 49 unmodified lines | ||
| 570 | 787 | }, |
| 571 | 788 | { |
| 572 | 789 | .reg = SX9500_REG_PROX_CTRL0, |
| 573 | − /* Scan period: 30ms, all sensors enabled. */ | |
| 574 | − .def = 0x0f, | |
| 790 | + /* Scan period: 30ms, all sensors disabled. */ | |
| 791 | + .def = 0x00, | |
| 575 | 792 | }, |
| 576 | 793 | }; |
| 577 | 794 | |
| 795 | +/* Activate all channels and perform an initial compensation. */ | |
| 796 | +static int sx9500_init_compensation(struct iio_dev *indio_dev) | |
| 797 | +{ | |
| 798 | + struct sx9500_data *data = iio_priv(indio_dev); | |
| 799 | + int i, ret; | |
| 800 | + unsigned int val; | |
| 801 | + | |
| 802 | + ret = regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, | |
| 803 | + GENMASK(SX9500_NUM_CHANNELS, 0), | |
| 804 | + GENMASK(SX9500_NUM_CHANNELS, 0)); | |
| 805 | + if (ret < 0) | |
| 806 | + return ret; | |
| 807 | + | |
| 808 | + for (i = 10; i >= 0; i--) { | |
| 809 | + usleep_range(10000, 20000); | |
| 810 | + ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); | |
| 811 | + if (ret < 0) | |
| 812 | + goto out; | |
| 813 | + if (!(val & SX9500_COMPSTAT_MASK)) | |
| 814 | + break; | |
| 815 | + } | |
| 816 | + | |
| 817 | + if (i < 0) { | |
| 818 | + dev_err(&data->client->dev, "initial compensation timed out"); | |
| 819 | + ret = -ETIMEDOUT; | |
| 820 | + } | |
| 821 | + | |
| 822 | +out: | |
| 823 | + regmap_update_bits(data->regmap, SX9500_REG_PROX_CTRL0, | |
| 824 | + GENMASK(SX9500_NUM_CHANNELS, 0), 0); | |
| 825 | + return ret; | |
| 826 | +} | |
| 827 | + | |
| 578 | 828 | static int sx9500_init_device(struct iio_dev *indio_dev) |
| 579 | 829 | { |
| 580 | 830 | struct sx9500_data *data = iio_priv(indio_dev); |
| 581 | 831 | int ret, i; |
| 582 | 832 | unsigned int val; |
| 583 | 833 | |
| 834 | + if (data->gpiod_rst) { | |
| 835 | + gpiod_set_value_cansleep(data->gpiod_rst, 0); | |
| 836 | + usleep_range(1000, 2000); | |
| 837 | + gpiod_set_value_cansleep(data->gpiod_rst, 1); | |
| 838 | + usleep_range(1000, 2000); | |
| 839 | + } | |
| 840 | + | |
| 584 | 841 | ret = regmap_write(data->regmap, SX9500_REG_IRQ_MSK, 0); |
| 585 | 842 | if (ret < 0) |
| 586 | 843 | return ret; |
| @@ -602,33 +859,34 @@ static int sx9500_init_device(struct iio_dev *indio_dev) · 15 unmodified lines | ||
| 602 | 859 | return ret; |
| 603 | 860 | } |
| 604 | 861 | |
| 605 | − return 0; | |
| 862 | + return sx9500_init_compensation(indio_dev); | |
| 606 | 863 | } |
| 607 | 864 | |
| 608 | −static int sx9500_gpio_probe(struct i2c_client *client, | |
| 609 | − struct sx9500_data *data) | |
| 865 | +static void sx9500_gpio_probe(struct i2c_client *client, | |
| 866 | + struct sx9500_data *data) | |
| 610 | 867 | { |
| 611 | 868 | struct device *dev; |
| 612 | 869 | struct gpio_desc *gpio; |
| 613 | − int ret; | |
| 614 | 870 | |
| 615 | 871 | if (!client) |
| 616 | − return -EINVAL; | |
| 872 | + return; | |
| 617 | 873 | |
| 618 | 874 | dev = &client->dev; |
| 619 | 875 | |
| 620 | − /* data ready gpio interrupt pin */ | |
| 621 | − gpio = devm_gpiod_get_index(dev, SX9500_GPIO_NAME, 0, GPIOD_IN); | |
| 622 | − if (IS_ERR(gpio)) { | |
| 623 | − dev_err(dev, "acpi gpio get index failed\n"); | |
| 624 | − return PTR_ERR(gpio); | |
| 876 | + if (client->irq <= 0) { | |
| 877 | + gpio = devm_gpiod_get_index(dev, SX9500_GPIO_INT, 0, GPIOD_IN); | |
| 878 | + if (IS_ERR(gpio)) | |
| 879 | + dev_err(dev, "gpio get irq failed\n"); | |
| 880 | + else | |
| 881 | + client->irq = gpiod_to_irq(gpio); | |
| 625 | 882 | } |
| 626 | 883 | |
| 627 | − ret = gpiod_to_irq(gpio); | |
| 628 | − | |
| 629 | − dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | |
| 630 | − | |
| 631 | − return ret; | |
| 884 | + data->gpiod_rst = devm_gpiod_get_index(dev, SX9500_GPIO_RESET, | |
| 885 | + 0, GPIOD_OUT_HIGH); | |
| 886 | + if (IS_ERR(data->gpiod_rst)) { | |
| 887 | + dev_warn(dev, "gpio get reset pin failed\n"); | |
| 888 | + data->gpiod_rst = NULL; | |
| 889 | + } | |
| 632 | 890 | } |
| 633 | 891 | |
| 634 | 892 | static int sx9500_probe(struct i2c_client *client, |
| @@ -645,14 +903,13 @@ static int sx9500_probe(struct i2c_client *client, · 10 unmodified lines | ||
| 645 | 903 | data = iio_priv(indio_dev); |
| 646 | 904 | data->client = client; |
| 647 | 905 | mutex_init(&data->mutex); |
| 906 | + init_completion(&data->completion); | |
| 648 | 907 | data->trigger_enabled = false; |
| 649 | 908 | |
| 650 | 909 | data->regmap = devm_regmap_init_i2c(client, &sx9500_regmap_config); |
| 651 | 910 | if (IS_ERR(data->regmap)) |
| 652 | 911 | return PTR_ERR(data->regmap); |
| 653 | 912 | |
| 654 | − sx9500_init_device(indio_dev); | |
| 655 | − | |
| 656 | 913 | indio_dev->dev.parent = &client->dev; |
| 657 | 914 | indio_dev->name = SX9500_DRIVER_NAME; |
| 658 | 915 | indio_dev->channels = sx9500_channels; |
| @@ -661,10 +918,15 @@ static int sx9500_probe(struct i2c_client *client, · 2 unmodified lines | ||
| 661 | 918 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 662 | 919 | i2c_set_clientdata(client, indio_dev); |
| 663 | 920 | |
| 664 | − if (client->irq <= 0) | |
| 665 | − client->irq = sx9500_gpio_probe(client, data); | |
| 921 | + sx9500_gpio_probe(client, data); | |
| 666 | 922 | |
| 667 | − if (client->irq > 0) { | |
| 923 | + ret = sx9500_init_device(indio_dev); | |
| 924 | + if (ret < 0) | |
| 925 | + return ret; | |
| 926 | + | |
| 927 | + if (client->irq <= 0) | |
| 928 | + dev_warn(&client->dev, "no valid irq found\n"); | |
| 929 | + else { | |
| 668 | 930 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
| 669 | 931 | sx9500_irq_handler, sx9500_irq_thread_handler, |
| 670 | 932 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
| @@ -687,7 +949,8 @@ static int sx9500_probe(struct i2c_client *client, · 16 unmodified lines | ||
| 687 | 949 | } |
| 688 | 950 | |
| 689 | 951 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
| 690 | − sx9500_trigger_handler, NULL); | |
| 952 | + sx9500_trigger_handler, | |
| 953 | + &sx9500_buffer_setup_ops); | |
| 691 | 954 | if (ret < 0) |
| 692 | 955 | goto out_trigger_unregister; |
| 693 | 956 | |
| @@ -720,6 +983,49 @@ static int sx9500_remove(struct i2c_client *client) · 26 unmodified lines | ||
| 720 | 983 | return 0; |
| 721 | 984 | } |
| 722 | 985 | |
| 986 | +#ifdef CONFIG_PM_SLEEP | |
| 987 | +static int sx9500_suspend(struct device *dev) | |
| 988 | +{ | |
| 989 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 990 | + struct sx9500_data *data = iio_priv(indio_dev); | |
| 991 | + int ret; | |
| 992 | + | |
| 993 | + mutex_lock(&data->mutex); | |
| 994 | + ret = regmap_read(data->regmap, SX9500_REG_PROX_CTRL0, | |
| 995 | + &data->suspend_ctrl0); | |
| 996 | + if (ret < 0) | |
| 997 | + goto out; | |
| 998 | + | |
| 999 | + /* | |
| 1000 | + * Scan period doesn't matter because when all the sensors are | |
| 1001 | + * deactivated the device is in sleep mode. | |
| 1002 | + */ | |
| 1003 | + ret = regmap_write(data->regmap, SX9500_REG_PROX_CTRL0, 0); | |
| 1004 | + | |
| 1005 | +out: | |
| 1006 | + mutex_unlock(&data->mutex); | |
| 1007 | + return ret; | |
| 1008 | +} | |
| 1009 | + | |
| 1010 | +static int sx9500_resume(struct device *dev) | |
| 1011 | +{ | |
| 1012 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 1013 | + struct sx9500_data *data = iio_priv(indio_dev); | |
| 1014 | + int ret; | |
| 1015 | + | |
| 1016 | + mutex_lock(&data->mutex); | |
| 1017 | + ret = regmap_write(data->regmap, SX9500_REG_PROX_CTRL0, | |
| 1018 | + data->suspend_ctrl0); | |
| 1019 | + mutex_unlock(&data->mutex); | |
| 1020 | + | |
| 1021 | + return ret; | |
| 1022 | +} | |
| 1023 | +#endif /* CONFIG_PM_SLEEP */ | |
| 1024 | + | |
| 1025 | +static const struct dev_pm_ops sx9500_pm_ops = { | |
| 1026 | + SET_SYSTEM_SLEEP_PM_OPS(sx9500_suspend, sx9500_resume) | |
| 1027 | +}; | |
| 1028 | + | |
| 723 | 1029 | static const struct acpi_device_id sx9500_acpi_match[] = { |
| 724 | 1030 | {"SSX9500", 0}, |
| 725 | 1031 | { }, |
| @@ -728,7 +1034,7 @@ MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); · 2 unmodified lines | ||
| 728 | 1034 | |
| 729 | 1035 | static const struct i2c_device_id sx9500_id[] = { |
| 730 | 1036 | {"sx9500", 0}, |
| 731 | − {} | |
| 1037 | + { }, | |
| 732 | 1038 | }; |
| 733 | 1039 | MODULE_DEVICE_TABLE(i2c, sx9500_id); |
| 734 | 1040 | |
| @@ -736,6 +1042,7 @@ static struct i2c_driver sx9500_driver = { · 1 unmodified line | ||
| 736 | 1042 | .driver = { |
| 737 | 1043 | .name = SX9500_DRIVER_NAME, |
| 738 | 1044 | .acpi_match_table = ACPI_PTR(sx9500_acpi_match), |
| 1045 | + .pm = &sx9500_pm_ops, | |
| 739 | 1046 | }, |
| 740 | 1047 | .probe = sx9500_probe, |
| 741 | 1048 | .remove = sx9500_remove, |
| @@ -12,12 +12,24 @@ · 11 unmodified lines | ||
| 12 | 12 | * |
| 13 | 13 | * (7-bit I2C slave address 0x5a, 100KHz bus speed only!) |
| 14 | 14 | * |
| 15 | − * TODO: sleep mode, configuration EEPROM | |
| 15 | + * To wake up from sleep mode, the SDA line must be held low while SCL is high | |
| 16 | + * for at least 33ms. This is achieved with an extra GPIO that can be connected | |
| 17 | + * directly to the SDA line. In normal operation, the GPIO is set as input and | |
| 18 | + * will not interfere in I2C communication. While the GPIO is driven low, the | |
| 19 | + * i2c adapter is locked since it cannot be used by other clients. The SCL line | |
| 20 | + * always has a pull-up so we do not need an extra GPIO to drive it high. If | |
| 21 | + * the "wakeup" GPIO is not given, power management will be disabled. | |
| 22 | + * | |
| 23 | + * TODO: filter configuration | |
| 16 | 24 | */ |
| 17 | 25 | |
| 18 | 26 | #include <linux/err.h> |
| 19 | 27 | #include <linux/i2c.h> |
| 20 | 28 | #include <linux/module.h> |
| 29 | +#include <linux/delay.h> | |
| 30 | +#include <linux/jiffies.h> | |
| 31 | +#include <linux/gpio/consumer.h> | |
| 32 | +#include <linux/pm_runtime.h> | |
| 21 | 33 | |
| 22 | 34 | #include <linux/iio/iio.h> |
| 23 | 35 | |
| @@ -51,10 +63,101 @@ · 27 unmodified lines | ||
| 51 | 63 | #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */ |
| 52 | 64 | #define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */ |
| 53 | 65 | |
| 66 | +#define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */ | |
| 67 | + | |
| 54 | 68 | struct mlx90614_data { |
| 55 | 69 | struct i2c_client *client; |
| 70 | + struct mutex lock; /* for EEPROM access only */ | |
| 71 | + struct gpio_desc *wakeup_gpio; /* NULL to disable sleep/wake-up */ | |
| 72 | + unsigned long ready_timestamp; /* in jiffies */ | |
| 56 | 73 | }; |
| 57 | 74 | |
| 75 | +/* | |
| 76 | + * Erase an address and write word. | |
| 77 | + * The mutex must be locked before calling. | |
| 78 | + */ | |
| 79 | +static s32 mlx90614_write_word(const struct i2c_client *client, u8 command, | |
| 80 | + u16 value) | |
| 81 | +{ | |
| 82 | + /* | |
| 83 | + * Note: The mlx90614 requires a PEC on writing but does not send us a | |
| 84 | + * valid PEC on reading. Hence, we cannot set I2C_CLIENT_PEC in | |
| 85 | + * i2c_client.flags. As a workaround, we use i2c_smbus_xfer here. | |
| 86 | + */ | |
| 87 | + union i2c_smbus_data data; | |
| 88 | + s32 ret; | |
| 89 | + | |
| 90 | + dev_dbg(&client->dev, "Writing 0x%x to address 0x%x", value, command); | |
| 91 | + | |
| 92 | + data.word = 0x0000; /* erase command */ | |
| 93 | + ret = i2c_smbus_xfer(client->adapter, client->addr, | |
| 94 | + client->flags | I2C_CLIENT_PEC, | |
| 95 | + I2C_SMBUS_WRITE, command, | |
| 96 | + I2C_SMBUS_WORD_DATA, &data); | |
| 97 | + if (ret < 0) | |
| 98 | + return ret; | |
| 99 | + | |
| 100 | + msleep(MLX90614_TIMING_EEPROM); | |
| 101 | + | |
| 102 | + data.word = value; /* actual write */ | |
| 103 | + ret = i2c_smbus_xfer(client->adapter, client->addr, | |
| 104 | + client->flags | I2C_CLIENT_PEC, | |
| 105 | + I2C_SMBUS_WRITE, command, | |
| 106 | + I2C_SMBUS_WORD_DATA, &data); | |
| 107 | + | |
| 108 | + msleep(MLX90614_TIMING_EEPROM); | |
| 109 | + | |
| 110 | + return ret; | |
| 111 | +} | |
| 112 | + | |
| 113 | +#ifdef CONFIG_PM | |
| 114 | +/* | |
| 115 | + * If @startup is true, make sure MLX90614_TIMING_STARTUP ms have elapsed since | |
| 116 | + * the last wake-up. This is normally only needed to get a valid temperature | |
| 117 | + * reading. EEPROM access does not need such delay. | |
| 118 | + * Return 0 on success, <0 on error. | |
| 119 | + */ | |
| 120 | +static int mlx90614_power_get(struct mlx90614_data *data, bool startup) | |
| 121 | +{ | |
| 122 | + unsigned long now; | |
| 123 | + | |
| 124 | + if (!data->wakeup_gpio) | |
| 125 | + return 0; | |
| 126 | + | |
| 127 | + pm_runtime_get_sync(&data->client->dev); | |
| 128 | + | |
| 129 | + if (startup) { | |
| 130 | + now = jiffies; | |
| 131 | + if (time_before(now, data->ready_timestamp) && | |
| 132 | + msleep_interruptible(jiffies_to_msecs( | |
| 133 | + data->ready_timestamp - now)) != 0) { | |
| 134 | + pm_runtime_put_autosuspend(&data->client->dev); | |
| 135 | + return -EINTR; | |
| 136 | + } | |
| 137 | + } | |
| 138 | + | |
| 139 | + return 0; | |
| 140 | +} | |
| 141 | + | |
| 142 | +static void mlx90614_power_put(struct mlx90614_data *data) | |
| 143 | +{ | |
| 144 | + if (!data->wakeup_gpio) | |
| 145 | + return; | |
| 146 | + | |
| 147 | + pm_runtime_mark_last_busy(&data->client->dev); | |
| 148 | + pm_runtime_put_autosuspend(&data->client->dev); | |
| 149 | +} | |
| 150 | +#else | |
| 151 | +static inline int mlx90614_power_get(struct mlx90614_data *data, bool startup) | |
| 152 | +{ | |
| 153 | + return 0; | |
| 154 | +} | |
| 155 | + | |
| 156 | +static inline void mlx90614_power_put(struct mlx90614_data *data) | |
| 157 | +{ | |
| 158 | +} | |
| 159 | +#endif | |
| 160 | + | |
| 58 | 161 | static int mlx90614_read_raw(struct iio_dev *indio_dev, |
| 59 | 162 | struct iio_chan_spec const *channel, int *val, |
| 60 | 163 | int *val2, long mask) |
| @@ -85,9 +188,19 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, · 24 unmodified lines | ||
| 85 | 188 | return -EINVAL; |
| 86 | 189 | } |
| 87 | 190 | |
| 191 | + ret = mlx90614_power_get(data, true); | |
| 192 | + if (ret < 0) | |
| 193 | + return ret; | |
| 88 | 194 | ret = i2c_smbus_read_word_data(data->client, cmd); |
| 195 | + mlx90614_power_put(data); | |
| 196 | + | |
| 89 | 197 | if (ret < 0) |
| 90 | 198 | return ret; |
| 199 | + | |
| 200 | + /* MSB is an error flag */ | |
| 201 | + if (ret & 0x8000) | |
| 202 | + return -EIO; | |
| 203 | + | |
| 91 | 204 | *val = ret; |
| 92 | 205 | return IIO_VAL_INT; |
| 93 | 206 | case IIO_CHAN_INFO_OFFSET: |
| @@ -97,6 +210,63 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, · 3 unmodified lines | ||
| 97 | 210 | case IIO_CHAN_INFO_SCALE: |
| 98 | 211 | *val = 20; |
| 99 | 212 | return IIO_VAL_INT; |
| 213 | + case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ | |
| 214 | + mlx90614_power_get(data, false); | |
| 215 | + mutex_lock(&data->lock); | |
| 216 | + ret = i2c_smbus_read_word_data(data->client, | |
| 217 | + MLX90614_EMISSIVITY); | |
| 218 | + mutex_unlock(&data->lock); | |
| 219 | + mlx90614_power_put(data); | |
| 220 | + | |
| 221 | + if (ret < 0) | |
| 222 | + return ret; | |
| 223 | + | |
| 224 | + if (ret == 65535) { | |
| 225 | + *val = 1; | |
| 226 | + *val2 = 0; | |
| 227 | + } else { | |
| 228 | + *val = 0; | |
| 229 | + *val2 = ret * 15259; /* 1/65535 ~ 0.000015259 */ | |
| 230 | + } | |
| 231 | + return IIO_VAL_INT_PLUS_NANO; | |
| 232 | + default: | |
| 233 | + return -EINVAL; | |
| 234 | + } | |
| 235 | +} | |
| 236 | + | |
| 237 | +static int mlx90614_write_raw(struct iio_dev *indio_dev, | |
| 238 | + struct iio_chan_spec const *channel, int val, | |
| 239 | + int val2, long mask) | |
| 240 | +{ | |
| 241 | + struct mlx90614_data *data = iio_priv(indio_dev); | |
| 242 | + s32 ret; | |
| 243 | + | |
| 244 | + switch (mask) { | |
| 245 | + case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */ | |
| 246 | + if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0)) | |
| 247 | + return -EINVAL; | |
| 248 | + val = val * 65535 + val2 / 15259; /* 1/65535 ~ 0.000015259 */ | |
| 249 | + | |
| 250 | + mlx90614_power_get(data, false); | |
| 251 | + mutex_lock(&data->lock); | |
| 252 | + ret = mlx90614_write_word(data->client, MLX90614_EMISSIVITY, | |
| 253 | + val); | |
| 254 | + mutex_unlock(&data->lock); | |
| 255 | + mlx90614_power_put(data); | |
| 256 | + | |
| 257 | + return ret; | |
| 258 | + default: | |
| 259 | + return -EINVAL; | |
| 260 | + } | |
| 261 | +} | |
| 262 | + | |
| 263 | +static int mlx90614_write_raw_get_fmt(struct iio_dev *indio_dev, | |
| 264 | + struct iio_chan_spec const *channel, | |
| 265 | + long mask) | |
| 266 | +{ | |
| 267 | + switch (mask) { | |
| 268 | + case IIO_CHAN_INFO_CALIBEMISSIVITY: | |
| 269 | + return IIO_VAL_INT_PLUS_NANO; | |
| 100 | 270 | default: |
| 101 | 271 | return -EINVAL; |
| 102 | 272 | } |
| @@ -115,7 +285,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { · 12 unmodified lines | ||
| 115 | 285 | .type = IIO_TEMP, |
| 116 | 286 | .modified = 1, |
| 117 | 287 | .channel2 = IIO_MOD_TEMP_OBJECT, |
| 118 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
| 288 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
| 289 | + BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), | |
| 119 | 290 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
| 120 | 291 | BIT(IIO_CHAN_INFO_SCALE), |
| 121 | 292 | }, |
| @@ -125,7 +296,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { · 3 unmodified lines | ||
| 125 | 296 | .modified = 1, |
| 126 | 297 | .channel = 1, |
| 127 | 298 | .channel2 = IIO_MOD_TEMP_OBJECT, |
| 128 | − .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
| 299 | + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
| 300 | + BIT(IIO_CHAN_INFO_CALIBEMISSIVITY), | |
| 129 | 301 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
| 130 | 302 | BIT(IIO_CHAN_INFO_SCALE), |
| 131 | 303 | }, |
| @@ -133,9 +305,103 @@ static const struct iio_chan_spec mlx90614_channels[] = { · 1 unmodified line | ||
| 133 | 305 | |
| 134 | 306 | static const struct iio_info mlx90614_info = { |
| 135 | 307 | .read_raw = mlx90614_read_raw, |
| 308 | + .write_raw = mlx90614_write_raw, | |
| 309 | + .write_raw_get_fmt = mlx90614_write_raw_get_fmt, | |
| 136 | 310 | .driver_module = THIS_MODULE, |
| 137 | 311 | }; |
| 138 | 312 | |
| 313 | +#ifdef CONFIG_PM | |
| 314 | +static int mlx90614_sleep(struct mlx90614_data *data) | |
| 315 | +{ | |
| 316 | + s32 ret; | |
| 317 | + | |
| 318 | + if (!data->wakeup_gpio) { | |
| 319 | + dev_dbg(&data->client->dev, "Sleep disabled"); | |
| 320 | + return -ENOSYS; | |
| 321 | + } | |
| 322 | + | |
| 323 | + dev_dbg(&data->client->dev, "Requesting sleep"); | |
| 324 | + | |
| 325 | + mutex_lock(&data->lock); | |
| 326 | + ret = i2c_smbus_xfer(data->client->adapter, data->client->addr, | |
| 327 | + data->client->flags | I2C_CLIENT_PEC, | |
| 328 | + I2C_SMBUS_WRITE, MLX90614_OP_SLEEP, | |
| 329 | + I2C_SMBUS_BYTE, NULL); | |
| 330 | + mutex_unlock(&data->lock); | |
| 331 | + | |
| 332 | + return ret; | |
| 333 | +} | |
| 334 | + | |
| 335 | +static int mlx90614_wakeup(struct mlx90614_data *data) | |
| 336 | +{ | |
| 337 | + if (!data->wakeup_gpio) { | |
| 338 | + dev_dbg(&data->client->dev, "Wake-up disabled"); | |
| 339 | + return -ENOSYS; | |
| 340 | + } | |
| 341 | + | |
| 342 | + dev_dbg(&data->client->dev, "Requesting wake-up"); | |
| 343 | + | |
| 344 | + i2c_lock_adapter(data->client->adapter); | |
| 345 | + gpiod_direction_output(data->wakeup_gpio, 0); | |
| 346 | + msleep(MLX90614_TIMING_WAKEUP); | |
| 347 | + gpiod_direction_input(data->wakeup_gpio); | |
| 348 | + i2c_unlock_adapter(data->client->adapter); | |
| 349 | + | |
| 350 | + data->ready_timestamp = jiffies + | |
| 351 | + msecs_to_jiffies(MLX90614_TIMING_STARTUP); | |
| 352 | + | |
| 353 | + /* | |
| 354 | + * Quirk: the i2c controller may get confused right after the | |
| 355 | + * wake-up signal has been sent. As a workaround, do a dummy read. | |
| 356 | + * If the read fails, the controller will probably be reset so that | |
| 357 | + * further reads will work. | |
| 358 | + */ | |
| 359 | + i2c_smbus_read_word_data(data->client, MLX90614_CONFIG); | |
| 360 | + | |
| 361 | + return 0; | |
| 362 | +} | |
| 363 | + | |
| 364 | +/* Return wake-up GPIO or NULL if sleep functionality should be disabled. */ | |
| 365 | +static struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client) | |
| 366 | +{ | |
| 367 | + struct gpio_desc *gpio; | |
| 368 | + | |
| 369 | + if (!i2c_check_functionality(client->adapter, | |
| 370 | + I2C_FUNC_SMBUS_WRITE_BYTE)) { | |
| 371 | + dev_info(&client->dev, | |
| 372 | + "i2c adapter does not support SMBUS_WRITE_BYTE, sleep disabled"); | |
| 373 | + return NULL; | |
| 374 | + } | |
| 375 | + | |
| 376 | + gpio = devm_gpiod_get_optional(&client->dev, "wakeup", GPIOD_IN); | |
| 377 | + | |
| 378 | + if (IS_ERR(gpio)) { | |
| 379 | + dev_warn(&client->dev, | |
| 380 | + "gpio acquisition failed with error %ld, sleep disabled", | |
| 381 | + PTR_ERR(gpio)); | |
| 382 | + return NULL; | |
| 383 | + } else if (!gpio) { | |
| 384 | + dev_info(&client->dev, | |
| 385 | + "wakeup-gpio not found, sleep disabled"); | |
| 386 | + } | |
| 387 | + | |
| 388 | + return gpio; | |
| 389 | +} | |
| 390 | +#else | |
| 391 | +static inline int mlx90614_sleep(struct mlx90614_data *data) | |
| 392 | +{ | |
| 393 | + return -ENOSYS; | |
| 394 | +} | |
| 395 | +static inline int mlx90614_wakeup(struct mlx90614_data *data) | |
| 396 | +{ | |
| 397 | + return -ENOSYS; | |
| 398 | +} | |
| 399 | +static inline struct gpio_desc *mlx90614_probe_wakeup(struct i2c_client *client) | |
| 400 | +{ | |
| 401 | + return NULL; | |
| 402 | +} | |
| 403 | +#endif | |
| 404 | + | |
| 139 | 405 | /* Return 0 for single sensor, 1 for dual sensor, <0 on error. */ |
| 140 | 406 | static int mlx90614_probe_num_ir_sensors(struct i2c_client *client) |
| 141 | 407 | { |
| @@ -166,6 +432,10 @@ static int mlx90614_probe(struct i2c_client *client, · 24 unmodified lines | ||
| 166 | 432 | data = iio_priv(indio_dev); |
| 167 | 433 | i2c_set_clientdata(client, indio_dev); |
| 168 | 434 | data->client = client; |
| 435 | + mutex_init(&data->lock); | |
| 436 | + data->wakeup_gpio = mlx90614_probe_wakeup(client); | |
| 437 | + | |
| 438 | + mlx90614_wakeup(data); | |
| 169 | 439 | |
| 170 | 440 | indio_dev->dev.parent = &client->dev; |
| 171 | 441 | indio_dev->name = id->name; |
| @@ -188,12 +458,30 @@ static int mlx90614_probe(struct i2c_client *client, · 16 unmodified lines | ||
| 188 | 458 | return ret; |
| 189 | 459 | } |
| 190 | 460 | |
| 461 | + if (data->wakeup_gpio) { | |
| 462 | + pm_runtime_set_autosuspend_delay(&client->dev, | |
| 463 | + MLX90614_AUTOSLEEP_DELAY); | |
| 464 | + pm_runtime_use_autosuspend(&client->dev); | |
| 465 | + pm_runtime_set_active(&client->dev); | |
| 466 | + pm_runtime_enable(&client->dev); | |
| 467 | + } | |
| 468 | + | |
| 191 | 469 | return iio_device_register(indio_dev); |
| 192 | 470 | } |
| 193 | 471 | |
| 194 | 472 | static int mlx90614_remove(struct i2c_client *client) |
| 195 | 473 | { |
| 196 | − iio_device_unregister(i2c_get_clientdata(client)); | |
| 474 | + struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
| 475 | + struct mlx90614_data *data = iio_priv(indio_dev); | |
| 476 | + | |
| 477 | + iio_device_unregister(indio_dev); | |
| 478 | + | |
| 479 | + if (data->wakeup_gpio) { | |
| 480 | + pm_runtime_disable(&client->dev); | |
| 481 | + if (!pm_runtime_status_suspended(&client->dev)) | |
| 482 | + mlx90614_sleep(data); | |
| 483 | + pm_runtime_set_suspended(&client->dev); | |
| 484 | + } | |
| 197 | 485 | |
| 198 | 486 | return 0; |
| 199 | 487 | } |
| @@ -204,10 +492,67 @@ static const struct i2c_device_id mlx90614_id[] = { · 4 unmodified lines | ||
| 204 | 492 | }; |
| 205 | 493 | MODULE_DEVICE_TABLE(i2c, mlx90614_id); |
| 206 | 494 | |
| 495 | +#ifdef CONFIG_PM_SLEEP | |
| 496 | +static int mlx90614_pm_suspend(struct device *dev) | |
| 497 | +{ | |
| 498 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 499 | + struct mlx90614_data *data = iio_priv(indio_dev); | |
| 500 | + | |
| 501 | + if (data->wakeup_gpio && pm_runtime_active(dev)) | |
| 502 | + return mlx90614_sleep(data); | |
| 503 | + | |
| 504 | + return 0; | |
| 505 | +} | |
| 506 | + | |
| 507 | +static int mlx90614_pm_resume(struct device *dev) | |
| 508 | +{ | |
| 509 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 510 | + struct mlx90614_data *data = iio_priv(indio_dev); | |
| 511 | + int err; | |
| 512 | + | |
| 513 | + if (data->wakeup_gpio) { | |
| 514 | + err = mlx90614_wakeup(data); | |
| 515 | + if (err < 0) | |
| 516 | + return err; | |
| 517 | + | |
| 518 | + pm_runtime_disable(dev); | |
| 519 | + pm_runtime_set_active(dev); | |
| 520 | + pm_runtime_enable(dev); | |
| 521 | + } | |
| 522 | + | |
| 523 | + return 0; | |
| 524 | +} | |
| 525 | +#endif | |
| 526 | + | |
| 527 | +#ifdef CONFIG_PM | |
| 528 | +static int mlx90614_pm_runtime_suspend(struct device *dev) | |
| 529 | +{ | |
| 530 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 531 | + struct mlx90614_data *data = iio_priv(indio_dev); | |
| 532 | + | |
| 533 | + return mlx90614_sleep(data); | |
| 534 | +} | |
| 535 | + | |
| 536 | +static int mlx90614_pm_runtime_resume(struct device *dev) | |
| 537 | +{ | |
| 538 | + struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev)); | |
| 539 | + struct mlx90614_data *data = iio_priv(indio_dev); | |
| 540 | + | |
| 541 | + return mlx90614_wakeup(data); | |
| 542 | +} | |
| 543 | +#endif | |
| 544 | + | |
| 545 | +static const struct dev_pm_ops mlx90614_pm_ops = { | |
| 546 | + SET_SYSTEM_SLEEP_PM_OPS(mlx90614_pm_suspend, mlx90614_pm_resume) | |
| 547 | + SET_RUNTIME_PM_OPS(mlx90614_pm_runtime_suspend, | |
| 548 | + mlx90614_pm_runtime_resume, NULL) | |
| 549 | +}; | |
| 550 | + | |
| 207 | 551 | static struct i2c_driver mlx90614_driver = { |
| 208 | 552 | .driver = { |
| 209 | 553 | .name = "mlx90614", |
| 210 | 554 | .owner = THIS_MODULE, |
| 555 | + .pm = &mlx90614_pm_ops, | |
| 211 | 556 | }, |
| 212 | 557 | .probe = mlx90614_probe, |
| 213 | 558 | .remove = mlx90614_remove, |
| @@ -41,8 +41,8 @@ · 40 unmodified lines | ||
| 41 | 41 | #define TMP006_CONFIG_CR_MASK 0x0e00 |
| 42 | 42 | #define TMP006_CONFIG_CR_SHIFT 9 |
| 43 | 43 | |
| 44 | −#define MANUFACTURER_MAGIC 0x5449 | |
| 45 | −#define DEVICE_MAGIC 0x0067 | |
| 44 | +#define TMP006_MANUFACTURER_MAGIC 0x5449 | |
| 45 | +#define TMP006_DEVICE_MAGIC 0x0067 | |
| 46 | 46 | |
| 47 | 47 | struct tmp006_data { |
| 48 | 48 | struct i2c_client *client; |
| @@ -191,7 +191,7 @@ static bool tmp006_check_identification(struct i2c_client *client) · 142 unmodified lines | ||
| 191 | 191 | if (did < 0) |
| 192 | 192 | return false; |
| 193 | 193 | |
| 194 | − return mid == MANUFACTURER_MAGIC && did == DEVICE_MAGIC; | |
| 194 | + return mid == TMP006_MANUFACTURER_MAGIC && did == TMP006_DEVICE_MAGIC; | |
| 195 | 195 | } |
| 196 | 196 | |
| 197 | 197 | static int tmp006_probe(struct i2c_client *client, |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | ***************************************************************************/ |
| 16 | 16 | |
| 17 | 17 | #include <linux/module.h> |
| 18 | −#include <linux/version.h> | |
| 19 | 18 | #include <linux/stringify.h> |
| 20 | 19 | #include <linux/delay.h> |
| 21 | 20 | #include <linux/kthread.h> |
| @@ -158,8 +158,8 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) · 157 unmodified lines | ||
| 158 | 158 | struct goldfish_pipe_dev *dev = pipe->dev; |
| 159 | 159 | |
| 160 | 160 | spin_lock_irqsave(&dev->lock, flags); |
| 161 | − gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL, | |
| 162 | − dev->base + PIPE_REG_CHANNEL_HIGH); | |
| 161 | + gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, | |
| 162 | + dev->base + PIPE_REG_CHANNEL_HIGH); | |
| 163 | 163 | writel(cmd, dev->base + PIPE_REG_COMMAND); |
| 164 | 164 | status = readl(dev->base + PIPE_REG_STATUS); |
| 165 | 165 | spin_unlock_irqrestore(&dev->lock, flags); |
| @@ -172,8 +172,8 @@ static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd) · 6 unmodified lines | ||
| 172 | 172 | struct goldfish_pipe_dev *dev = pipe->dev; |
| 173 | 173 | |
| 174 | 174 | spin_lock_irqsave(&dev->lock, flags); |
| 175 | − gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL, | |
| 176 | − dev->base + PIPE_REG_CHANNEL_HIGH); | |
| 175 | + gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, | |
| 176 | + dev->base + PIPE_REG_CHANNEL_HIGH); | |
| 177 | 177 | writel(cmd, dev->base + PIPE_REG_COMMAND); |
| 178 | 178 | spin_unlock_irqrestore(&dev->lock, flags); |
| 179 | 179 | } |
| @@ -327,12 +327,12 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, · 147 unmodified lines | ||
| 327 | 327 | spin_lock_irqsave(&dev->lock, irq_flags); |
| 328 | 328 | if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, |
| 329 | 329 | address, avail, pipe, &status)) { |
| 330 | − gf_write64((u64)(unsigned long)pipe, | |
| 331 | − dev->base + PIPE_REG_CHANNEL, | |
| 332 | − dev->base + PIPE_REG_CHANNEL_HIGH); | |
| 330 | + gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, | |
| 331 | + dev->base + PIPE_REG_CHANNEL_HIGH); | |
| 333 | 332 | writel(avail, dev->base + PIPE_REG_SIZE); |
| 334 | − gf_write64(address, dev->base + PIPE_REG_ADDRESS, | |
| 335 | − dev->base + PIPE_REG_ADDRESS_HIGH); | |
| 333 | + gf_write_ptr((void *)address, | |
| 334 | + dev->base + PIPE_REG_ADDRESS, | |
| 335 | + dev->base + PIPE_REG_ADDRESS_HIGH); | |
| 336 | 336 | writel(CMD_WRITE_BUFFER + cmd_offset, |
| 337 | 337 | dev->base + PIPE_REG_COMMAND); |
| 338 | 338 | status = readl(dev->base + PIPE_REG_STATUS); |
| @@ -108,8 +108,8 @@ source "drivers/staging/clocking-wizard/Kconfig" · 107 unmodified lines | ||
| 108 | 108 | |
| 109 | 109 | source "drivers/staging/fbtft/Kconfig" |
| 110 | 110 | |
| 111 | −source "drivers/staging/i2o/Kconfig" | |
| 112 | − | |
| 113 | 111 | source "drivers/staging/fsl-mc/Kconfig" |
| 114 | 112 | |
| 113 | +source "drivers/staging/wilc1000/Kconfig" | |
| 114 | + | |
| 115 | 115 | endif # STAGING |
| @@ -23,7 +23,7 @@ obj-$(CONFIG_VT6656) += vt6656/ · 22 unmodified lines | ||
| 23 | 23 | obj-$(CONFIG_VME_BUS) += vme/ |
| 24 | 24 | obj-$(CONFIG_IIO) += iio/ |
| 25 | 25 | obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ |
| 26 | −obj-$(CONFIG_FB_SM7XX) += sm750fb/ | |
| 26 | +obj-$(CONFIG_FB_SM750) += sm750fb/ | |
| 27 | 27 | obj-$(CONFIG_FB_XGI) += xgifb/ |
| 28 | 28 | obj-$(CONFIG_USB_EMXX) += emxx_udc/ |
| 29 | 29 | obj-$(CONFIG_FT1000) += ft1000/ |
| @@ -46,5 +46,5 @@ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ · 16 unmodified lines | ||
| 46 | 46 | obj-$(CONFIG_UNISYSSPAR) += unisys/ |
| 47 | 47 | obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ |
| 48 | 48 | obj-$(CONFIG_FB_TFT) += fbtft/ |
| 49 | −obj-$(CONFIG_I2O) += i2o/ | |
| 50 | 49 | obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ |
| 50 | +obj-$(CONFIG_WILC1000) += wilc1000/ | |
| @@ -22,11 +22,20 @@ config ANDROID_TIMED_GPIO · 21 unmodified lines | ||
| 22 | 22 | tristate "Android timed gpio driver" |
| 23 | 23 | depends on GPIOLIB && ANDROID_TIMED_OUTPUT |
| 24 | 24 | default n |
| 25 | + ---help--- | |
| 26 | + Unlike generic gpio is to allow programs to access and manipulate gpio | |
| 27 | + registers from user space, timed output/gpio is a system to allow changing | |
| 28 | + a gpio pin and restore it automatically after a specified timeout. | |
| 25 | 29 | |
| 26 | 30 | config ANDROID_LOW_MEMORY_KILLER |
| 27 | 31 | bool "Android Low Memory Killer" |
| 28 | 32 | ---help--- |
| 29 | − Registers processes to be killed when memory is low | |
| 33 | + Registers processes to be killed when low memory conditions, this is useful | |
| 34 | + as there is no particular swap space on android. | |
| 35 | + | |
| 36 | + The registered process will kills according to the priorities in android init | |
| 37 | + scripts (/init.rc), and it defines priority values with minimum free memory size | |
| 38 | + for each priority. | |
| 30 | 39 | |
| 31 | 40 | config SYNC |
| 32 | 41 | bool "Synchronization framework" |
| @@ -1579,6 +1579,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) · 1578 unmodified lines | ||
| 1579 | 1579 | ret = misc_register(&idev->dev); |
| 1580 | 1580 | if (ret) { |
| 1581 | 1581 | pr_err("ion: failed to register misc device.\n"); |
| 1582 | + kfree(idev); | |
| 1582 | 1583 | return ERR_PTR(ret); |
| 1583 | 1584 | } |
| 1584 | 1585 | |
| @@ -173,7 +173,7 @@ struct ion_heap *ion_chunk_heap_create(struct ion_platform_heap *heap_data) · 172 unmodified lines | ||
| 173 | 173 | chunk_heap->heap.ops = &chunk_heap_ops; |
| 174 | 174 | chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; |
| 175 | 175 | chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; |
| 176 | − pr_info("%s: base %lu size %zu align %ld\n", __func__, chunk_heap->base, | |
| 176 | + pr_debug("%s: base %lu size %zu align %ld\n", __func__, chunk_heap->base, | |
| 177 | 177 | heap_data->size, heap_data->align); |
| 178 | 178 | |
| 179 | 179 | return &chunk_heap->heap; |
| @@ -33,7 +33,7 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); · 32 unmodified lines | ||
| 33 | 33 | |
| 34 | 34 | /** |
| 35 | 35 | * struct ion_buffer - metadata for a particular buffer |
| 36 | − * @ref: refernce count | |
| 36 | + * @ref: reference count | |
| 37 | 37 | * @node: node in the ion_device buffers tree |
| 38 | 38 | * @dev: back pointer to the ion_device |
| 39 | 39 | * @heap: back pointer to the heap the buffer came from |
| @@ -46,7 +46,7 @@ struct ion_buffer *ion_handle_buffer(struct ion_handle *handle); · 6 unmodified lines | ||
| 46 | 46 | * an ion_phys_addr_t (and someday a phys_addr_t) |
| 47 | 47 | * @lock: protects the buffers cnt fields |
| 48 | 48 | * @kmap_cnt: number of times the buffer is mapped to the kernel |
| 49 | − * @vaddr: the kenrel mapping if kmap_cnt is not zero | |
| 49 | + * @vaddr: the kernel mapping if kmap_cnt is not zero | |
| 50 | 50 | * @dmap_cnt: number of times the buffer is mapped for dma |
| 51 | 51 | * @sg_table: the sg table for the buffer if dmap_cnt is not zero |
| 52 | 52 | * @pages: flat array of pages in the buffer -- used by fault |
| @@ -266,7 +266,7 @@ void ion_heap_freelist_add(struct ion_heap *heap, struct ion_buffer *buffer); · 213 unmodified lines | ||
| 266 | 266 | /** |
| 267 | 267 | * ion_heap_freelist_drain - drain the deferred free list |
| 268 | 268 | * @heap: the heap |
| 269 | − * @size: ammount of memory to drain in bytes | |
| 269 | + * @size: amount of memory to drain in bytes | |
| 270 | 270 | * |
| 271 | 271 | * Drains the indicated amount of memory from the deferred freelist immediately. |
| 272 | 272 | * Returns the total amount freed. The total freed may be higher depending |
| @@ -261,7 +261,20 @@ static int __init ion_test_probe(struct platform_device *pdev) · 260 unmodified lines | ||
| 261 | 261 | return 0; |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | +static int ion_test_remove(struct platform_device *pdev) | |
| 265 | +{ | |
| 266 | + struct ion_test_device *testdev; | |
| 267 | + | |
| 268 | + testdev = platform_get_drvdata(pdev); | |
| 269 | + if (!testdev) | |
| 270 | + return -ENODATA; | |
| 271 | + | |
| 272 | + return misc_deregister(&testdev->misc); | |
| 273 | +} | |
| 274 | + | |
| 275 | +static struct platform_device *ion_test_pdev; | |
| 264 | 276 | static struct platform_driver ion_test_platform_driver = { |
| 277 | + .remove = ion_test_remove, | |
| 265 | 278 | .driver = { |
| 266 | 279 | .name = "ion-test", |
| 267 | 280 | }, |
| @@ -269,13 +282,18 @@ static struct platform_driver ion_test_platform_driver = { · 1 unmodified line | ||
| 269 | 282 | |
| 270 | 283 | static int __init ion_test_init(void) |
| 271 | 284 | { |
| 272 | − platform_device_register_simple("ion-test", -1, NULL, 0); | |
| 285 | + ion_test_pdev = platform_device_register_simple("ion-test", | |
| 286 | + -1, NULL, 0); | |
| 287 | + if (!ion_test_pdev) | |
| 288 | + return -ENODEV; | |
| 289 | + | |
| 273 | 290 | return platform_driver_probe(&ion_test_platform_driver, ion_test_probe); |
| 274 | 291 | } |
| 275 | 292 | |
| 276 | 293 | static void __exit ion_test_exit(void) |
| 277 | 294 | { |
| 278 | 295 | platform_driver_unregister(&ion_test_platform_driver); |
| 296 | + platform_device_unregister(ion_test_pdev); | |
| 279 | 297 | } |
| 280 | 298 | |
| 281 | 299 | module_init(ion_test_init); |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | */ |
| 16 | 16 | |
| 17 | 17 | #include <linux/err.h> |
| 18 | +#include <linux/module.h> | |
| 18 | 19 | #include <linux/platform_device.h> |
| 19 | 20 | #include <linux/slab.h> |
| 20 | 21 | #include "../ion.h" |
| @@ -156,20 +156,27 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) · 155 unmodified lines | ||
| 156 | 156 | p->pid, p->comm, oom_score_adj, tasksize); |
| 157 | 157 | } |
| 158 | 158 | if (selected) { |
| 159 | − lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n", | |
| 160 | − selected->pid, selected->comm, | |
| 161 | − selected_oom_score_adj, selected_tasksize); | |
| 162 | − lowmem_deathpending_timeout = jiffies + HZ; | |
| 159 | + task_lock(selected); | |
| 160 | + if (!selected->mm) { | |
| 161 | + /* Already exited, cannot do mark_tsk_oom_victim() */ | |
| 162 | + task_unlock(selected); | |
| 163 | + goto out; | |
| 164 | + } | |
| 163 | 165 | /* |
| 164 | 166 | * FIXME: lowmemorykiller shouldn't abuse global OOM killer |
| 165 | 167 | * infrastructure. There is no real reason why the selected |
| 166 | 168 | * task should have access to the memory reserves. |
| 167 | 169 | */ |
| 168 | 170 | mark_oom_victim(selected); |
| 171 | + task_unlock(selected); | |
| 172 | + lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n", | |
| 173 | + selected->pid, selected->comm, | |
| 174 | + selected_oom_score_adj, selected_tasksize); | |
| 175 | + lowmem_deathpending_timeout = jiffies + HZ; | |
| 169 | 176 | send_sig(SIGKILL, selected, 0); |
| 170 | 177 | rem += selected_tasksize; |
| 171 | 178 | } |
| 172 | − | |
| 179 | +out: | |
| 173 | 180 | lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n", |
| 174 | 181 | sc->nr_to_scan, sc->gfp_mask, rem); |
| 175 | 182 | rcu_read_unlock(); |
| @@ -179,7 +179,7 @@ struct ion_custom_data { · 178 unmodified lines | ||
| 179 | 179 | * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory |
| 180 | 180 | * |
| 181 | 181 | * Deprecated in favor of using the dma_buf api's correctly (syncing |
| 182 | − * will happend automatically when the buffer is mapped to a device). | |
| 182 | + * will happen automatically when the buffer is mapped to a device). | |
| 183 | 183 | * If necessary should be used after touching a cached buffer from the cpu, |
| 184 | 184 | * this will make the buffer in memory coherent. |
| 185 | 185 | */ |
| @@ -1,7 +1,6 @@ | ||
| 1 | 1 | config STAGING_BOARD |
| 2 | 2 | bool "Staging Board Support" |
| 3 | 3 | depends on OF_ADDRESS |
| 4 | − depends on BROKEN | |
| 5 | 4 | help |
| 6 | 5 | Select to enable per-board staging support code. |
| 7 | 6 | |
| @@ -1,2 +1,3 @@ | ||
| 1 | 1 | obj-y := board.o |
| 2 | −obj-$(CONFIG_ARCH_EMEV2) += kzm9d.o | |
| 2 | +obj-$(CONFIG_ARCH_EMEV2) += kzm9d.o | |
| 3 | +obj-$(CONFIG_ARCH_R8A7740) += armadillo800eva.o | |
| @@ -0,0 +1,105 @@ | ||
| 1 | +/* | |
| 2 | + * Staging board support for Armadillo 800 eva. | |
| 3 | + * Enable not-yet-DT-capable devices here. | |
| 4 | + * | |
| 5 | + * Based on board-armadillo800eva.c | |
| 6 | + * | |
| 7 | + * Copyright (C) 2012 Renesas Solutions Corp. | |
| 8 | + * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | |
| 9 | + * | |
| 10 | + * This program is free software; you can redistribute it and/or modify | |
| 11 | + * it under the terms of the GNU General Public License as published by | |
| 12 | + * the Free Software Foundation; version 2 of the License. | |
| 13 | + * | |
| 14 | + * This program is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <linux/dma-mapping.h> | |
| 21 | +#include <linux/fb.h> | |
| 22 | +#include <linux/kernel.h> | |
| 23 | +#include <linux/platform_device.h> | |
| 24 | +#include <linux/videodev2.h> | |
| 25 | + | |
| 26 | +#include <video/sh_mobile_lcdc.h> | |
| 27 | + | |
| 28 | +#include "board.h" | |
| 29 | + | |
| 30 | + | |
| 31 | +static struct fb_videomode lcdc0_mode = { | |
| 32 | + .name = "AMPIER/AM-800480", | |
| 33 | + .xres = 800, | |
| 34 | + .yres = 480, | |
| 35 | + .left_margin = 88, | |
| 36 | + .right_margin = 40, | |
| 37 | + .hsync_len = 128, | |
| 38 | + .upper_margin = 20, | |
| 39 | + .lower_margin = 5, | |
| 40 | + .vsync_len = 5, | |
| 41 | + .sync = 0, | |
| 42 | +}; | |
| 43 | + | |
| 44 | +static struct sh_mobile_lcdc_info lcdc0_info = { | |
| 45 | + .clock_source = LCDC_CLK_BUS, | |
| 46 | + .ch[0] = { | |
| 47 | + .chan = LCDC_CHAN_MAINLCD, | |
| 48 | + .fourcc = V4L2_PIX_FMT_RGB565, | |
| 49 | + .interface_type = RGB24, | |
| 50 | + .clock_divider = 5, | |
| 51 | + .flags = 0, | |
| 52 | + .lcd_modes = &lcdc0_mode, | |
| 53 | + .num_modes = 1, | |
| 54 | + .panel_cfg = { | |
| 55 | + .width = 111, | |
| 56 | + .height = 68, | |
| 57 | + }, | |
| 58 | + }, | |
| 59 | +}; | |
| 60 | + | |
| 61 | +static struct resource lcdc0_resources[] = { | |
| 62 | + [0] = { | |
| 63 | + .name = "LCD0", | |
| 64 | + .start = 0xfe940000, | |
| 65 | + .end = 0xfe943fff, | |
| 66 | + .flags = IORESOURCE_MEM, | |
| 67 | + }, | |
| 68 | + [1] = { | |
| 69 | + .start = 177 + 32, | |
| 70 | + .flags = IORESOURCE_IRQ, | |
| 71 | + }, | |
| 72 | +}; | |
| 73 | + | |
| 74 | +static struct platform_device lcdc0_device = { | |
| 75 | + .name = "sh_mobile_lcdc_fb", | |
| 76 | + .num_resources = ARRAY_SIZE(lcdc0_resources), | |
| 77 | + .resource = lcdc0_resources, | |
| 78 | + .id = 0, | |
| 79 | + .dev = { | |
| 80 | + .platform_data = &lcdc0_info, | |
| 81 | + .coherent_dma_mask = DMA_BIT_MASK(32), | |
| 82 | + }, | |
| 83 | +}; | |
| 84 | + | |
| 85 | +static const struct board_staging_clk lcdc0_clocks[] __initconst = { | |
| 86 | + { "lcdc0", NULL, "sh_mobile_lcdc_fb.0" }, | |
| 87 | +}; | |
| 88 | + | |
| 89 | +static const struct board_staging_dev armadillo800eva_devices[] __initconst = { | |
| 90 | + { | |
| 91 | + .pdev = &lcdc0_device, | |
| 92 | + .clocks = lcdc0_clocks, | |
| 93 | + .nclocks = ARRAY_SIZE(lcdc0_clocks), | |
| 94 | + .domain = "a4lc", | |
| 95 | + }, | |
| 96 | +}; | |
| 97 | + | |
| 98 | +static void __init armadillo800eva_init(void) | |
| 99 | +{ | |
| 100 | + board_staging_gic_setup_xlate("arm,cortex-a9-gic", 32); | |
| 101 | + board_staging_register_devices(armadillo800eva_devices, | |
| 102 | + ARRAY_SIZE(armadillo800eva_devices)); | |
| 103 | +} | |
| 104 | + | |
| 105 | +board_staging("renesas,armadillo800eva", armadillo800eva_init); | |
| @@ -1,10 +1,30 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2014 Magnus Damm | |
| 3 | + * Copyright (C) 2015 Glider bvba | |
| 4 | + * | |
| 5 | + * This file is subject to the terms and conditions of the GNU General Public | |
| 6 | + * License. See the file "COPYING" in the main directory of this archive | |
| 7 | + * for more details. | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#define pr_fmt(fmt) "board_staging: " fmt | |
| 11 | + | |
| 12 | +#include <linux/clkdev.h> | |
| 1 | 13 | #include <linux/init.h> |
| 14 | +#include <linux/irq.h> | |
| 2 | 15 | #include <linux/device.h> |
| 3 | 16 | #include <linux/kernel.h> |
| 4 | 17 | #include <linux/of.h> |
| 5 | 18 | #include <linux/of_address.h> |
| 19 | +#include <linux/of_irq.h> | |
| 20 | +#include <linux/platform_device.h> | |
| 21 | +#include <linux/pm_domain.h> | |
| 22 | + | |
| 6 | 23 | #include "board.h" |
| 7 | 24 | |
| 25 | +static struct device_node *irqc_node __initdata; | |
| 26 | +static unsigned int irqc_base __initdata; | |
| 27 | + | |
| 8 | 28 | static bool find_by_address(u64 base_address) |
| 9 | 29 | { |
| 10 | 30 | struct device_node *dn = of_find_all_nodes(NULL); |
| @@ -38,3 +58,119 @@ bool __init board_staging_dt_node_available(const struct resource *resource, · 27 unmodified lines | ||
| 38 | 58 | |
| 39 | 59 | return false; /* Nothing found */ |
| 40 | 60 | } |
| 61 | + | |
| 62 | +int __init board_staging_gic_setup_xlate(const char *gic_match, | |
| 63 | + unsigned int base) | |
| 64 | +{ | |
| 65 | + WARN_ON(irqc_node); | |
| 66 | + | |
| 67 | + irqc_node = of_find_compatible_node(NULL, NULL, gic_match); | |
| 68 | + | |
| 69 | + WARN_ON(!irqc_node); | |
| 70 | + if (!irqc_node) | |
| 71 | + return -ENOENT; | |
| 72 | + | |
| 73 | + irqc_base = base; | |
| 74 | + return 0; | |
| 75 | +} | |
| 76 | + | |
| 77 | +static void __init gic_fixup_resource(struct resource *res) | |
| 78 | +{ | |
| 79 | + struct of_phandle_args irq_data; | |
| 80 | + unsigned int hwirq = res->start; | |
| 81 | + unsigned int virq; | |
| 82 | + | |
| 83 | + if (resource_type(res) != IORESOURCE_IRQ || !irqc_node) | |
| 84 | + return; | |
| 85 | + | |
| 86 | + irq_data.np = irqc_node; | |
| 87 | + irq_data.args_count = 3; | |
| 88 | + irq_data.args[0] = 0; | |
| 89 | + irq_data.args[1] = hwirq - irqc_base; | |
| 90 | + switch (res->flags & | |
| 91 | + (IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE | | |
| 92 | + IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL)) { | |
| 93 | + case IORESOURCE_IRQ_LOWEDGE: | |
| 94 | + irq_data.args[2] = IRQ_TYPE_EDGE_FALLING; | |
| 95 | + break; | |
| 96 | + case IORESOURCE_IRQ_HIGHEDGE: | |
| 97 | + irq_data.args[2] = IRQ_TYPE_EDGE_RISING; | |
| 98 | + break; | |
| 99 | + case IORESOURCE_IRQ_LOWLEVEL: | |
| 100 | + irq_data.args[2] = IRQ_TYPE_LEVEL_LOW; | |
| 101 | + break; | |
| 102 | + case IORESOURCE_IRQ_HIGHLEVEL: | |
| 103 | + default: | |
| 104 | + irq_data.args[2] = IRQ_TYPE_LEVEL_HIGH; | |
| 105 | + break; | |
| 106 | + } | |
| 107 | + | |
| 108 | + virq = irq_create_of_mapping(&irq_data); | |
| 109 | + if (WARN_ON(!virq)) | |
| 110 | + return; | |
| 111 | + | |
| 112 | + pr_debug("hwirq %u -> virq %u\n", hwirq, virq); | |
| 113 | + res->start = virq; | |
| 114 | +} | |
| 115 | + | |
| 116 | +void __init board_staging_gic_fixup_resources(struct resource *res, | |
| 117 | + unsigned int nres) | |
| 118 | +{ | |
| 119 | + unsigned int i; | |
| 120 | + | |
| 121 | + for (i = 0; i < nres; i++) | |
| 122 | + gic_fixup_resource(&res[i]); | |
| 123 | +} | |
| 124 | + | |
| 125 | +int __init board_staging_register_clock(const struct board_staging_clk *bsc) | |
| 126 | +{ | |
| 127 | + int error; | |
| 128 | + | |
| 129 | + pr_debug("Aliasing clock %s for con_id %s dev_id %s\n", bsc->clk, | |
| 130 | + bsc->con_id, bsc->dev_id); | |
| 131 | + error = clk_add_alias(bsc->con_id, bsc->dev_id, bsc->clk, NULL); | |
| 132 | + if (error) | |
| 133 | + pr_err("Failed to alias clock %s (%d)\n", bsc->clk, error); | |
| 134 | + | |
| 135 | + return error; | |
| 136 | +} | |
| 137 | + | |
| 138 | +int __init board_staging_register_device(const struct board_staging_dev *dev) | |
| 139 | +{ | |
| 140 | + struct platform_device *pdev = dev->pdev; | |
| 141 | + unsigned int i; | |
| 142 | + int error; | |
| 143 | + | |
| 144 | + pr_debug("Trying to register device %s\n", pdev->name); | |
| 145 | + if (board_staging_dt_node_available(pdev->resource, | |
| 146 | + pdev->num_resources)) { | |
| 147 | + pr_warn("Skipping %s, already in DT\n", pdev->name); | |
| 148 | + return -EEXIST; | |
| 149 | + } | |
| 150 | + | |
| 151 | + board_staging_gic_fixup_resources(pdev->resource, pdev->num_resources); | |
| 152 | + | |
| 153 | + for (i = 0; i < dev->nclocks; i++) | |
| 154 | + board_staging_register_clock(&dev->clocks[i]); | |
| 155 | + | |
| 156 | + error = platform_device_register(pdev); | |
| 157 | + if (error) { | |
| 158 | + pr_err("Failed to register device %s (%d)\n", pdev->name, | |
| 159 | + error); | |
| 160 | + return error; | |
| 161 | + } | |
| 162 | + | |
| 163 | + if (dev->domain) | |
| 164 | + __pm_genpd_name_add_device(dev->domain, &pdev->dev, NULL); | |
| 165 | + | |
| 166 | + return error; | |
| 167 | +} | |
| 168 | + | |
| 169 | +void __init board_staging_register_devices(const struct board_staging_dev *devs, | |
| 170 | + unsigned int ndevs) | |
| 171 | +{ | |
| 172 | + unsigned int i; | |
| 173 | + | |
| 174 | + for (i = 0; i < ndevs; i++) | |
| 175 | + board_staging_register_device(&devs[i]); | |
| 176 | +} | |
| @@ -1,10 +1,35 @@ | ||
| 1 | 1 | #ifndef __BOARD_H__ |
| 2 | 2 | #define __BOARD_H__ |
| 3 | + | |
| 3 | 4 | #include <linux/init.h> |
| 4 | 5 | #include <linux/of.h> |
| 5 | 6 | |
| 7 | +struct board_staging_clk { | |
| 8 | + const char *clk; | |
| 9 | + const char *con_id; | |
| 10 | + const char *dev_id; | |
| 11 | +}; | |
| 12 | + | |
| 13 | +struct board_staging_dev { | |
| 14 | + /* Platform Device */ | |
| 15 | + struct platform_device *pdev; | |
| 16 | + /* Clocks (optional) */ | |
| 17 | + const struct board_staging_clk *clocks; | |
| 18 | + unsigned int nclocks; | |
| 19 | + /* Generic PM Domain (optional) */ | |
| 20 | + const char *domain; | |
| 21 | +}; | |
| 22 | + | |
| 23 | +struct resource; | |
| 24 | + | |
| 6 | 25 | bool board_staging_dt_node_available(const struct resource *resource, |
| 7 | 26 | unsigned int num_resources); |
| 27 | +int board_staging_gic_setup_xlate(const char *gic_match, unsigned int base); | |
| 28 | +void board_staging_gic_fixup_resources(struct resource *res, unsigned int nres); | |
| 29 | +int board_staging_register_clock(const struct board_staging_clk *bsc); | |
| 30 | +int board_staging_register_device(const struct board_staging_dev *dev); | |
| 31 | +void board_staging_register_devices(const struct board_staging_dev *devs, | |
| 32 | + unsigned int ndevs); | |
| 8 | 33 | |
| 9 | 34 | #define board_staging(str, fn) \ |
| 10 | 35 | static int __init runtime_board_check(void) \ |
| @@ -15,6 +40,6 @@ static int __init runtime_board_check(void) \ · 4 unmodified lines | ||
| 15 | 40 | return 0; \ |
| 16 | 41 | } \ |
| 17 | 42 | \ |
| 18 | −late_initcall(runtime_board_check) | |
| 43 | +device_initcall(runtime_board_check) | |
| 19 | 44 | |
| 20 | 45 | #endif /* __BOARD_H__ */ |
| @@ -4,16 +4,22 @@ · 3 unmodified lines | ||
| 4 | 4 | #include <linux/platform_device.h> |
| 5 | 5 | #include "board.h" |
| 6 | 6 | |
| 7 | −static const struct resource usbs1_res[] __initconst = { | |
| 7 | +static struct resource usbs1_res[] __initdata = { | |
| 8 | 8 | DEFINE_RES_MEM(0xe2800000, 0x2000), |
| 9 | 9 | DEFINE_RES_IRQ(159), |
| 10 | 10 | }; |
| 11 | 11 | |
| 12 | 12 | static void __init kzm9d_init(void) |
| 13 | 13 | { |
| 14 | − if (!board_staging_dt_node_available(usbs1_res, ARRAY_SIZE(usbs1_res))) | |
| 14 | + board_staging_gic_setup_xlate("arm,cortex-a9-gic", 32); | |
| 15 | + | |
| 16 | + if (!board_staging_dt_node_available(usbs1_res, | |
| 17 | + ARRAY_SIZE(usbs1_res))) { | |
| 18 | + board_staging_gic_fixup_resources(usbs1_res, | |
| 19 | + ARRAY_SIZE(usbs1_res)); | |
| 15 | 20 | platform_device_register_simple("emxx_udc", -1, usbs1_res, |
| 16 | 21 | ARRAY_SIZE(usbs1_res)); |
| 22 | + } | |
| 17 | 23 | } |
| 18 | 24 | |
| 19 | 25 | board_staging("renesas,kzm9d", kzm9d_init); |
| @@ -1247,16 +1247,22 @@ config COMEDI_8254 · 1246 unmodified lines | ||
| 1247 | 1247 | tristate |
| 1248 | 1248 | |
| 1249 | 1249 | config COMEDI_8255 |
| 1250 | − tristate "Generic 8255 support" | |
| 1250 | + tristate | |
| 1251 | + | |
| 1252 | +config COMEDI_8255_SA | |
| 1253 | + tristate "Standalone 8255 support" | |
| 1254 | + select COMEDI_8255 | |
| 1251 | 1255 | ---help--- |
| 1252 | − Enable generic 8255 support. | |
| 1256 | + Enable support for 8255 digital I/O as a standalone driver. | |
| 1253 | 1257 | |
| 1254 | 1258 | You should enable compilation this driver if you plan to use a board |
| 1255 | − that has an 8255 chip. For multifunction boards, the main driver will | |
| 1256 | − configure the 8255 subdevice automatically. | |
| 1259 | + that has an 8255 chip at a known I/O base address and there are no | |
| 1260 | + other Comedi drivers for the board. | |
| 1257 | 1261 | |
| 1258 | − Note that most PCI based 8255 boards use the 8255_pci driver as a | |
| 1259 | − wrapper around this driver. | |
| 1262 | + Note that Comedi drivers for most multi-function boards incorporating | |
| 1263 | + an 8255 chip use the 'comedi_8255' module. Most PCI-based 8255 | |
| 1264 | + boards use the 8255_pci driver as a wrapper around the 'comedi_8255' | |
| 1265 | + module. | |
| 1260 | 1266 | |
| 1261 | 1267 | To compile this driver as a module, choose M here: the module will be |
| 1262 | 1268 | called 8255. |
| @@ -217,7 +217,7 @@ · 216 unmodified lines | ||
| 217 | 217 | #define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */ |
| 218 | 218 | #define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */ |
| 219 | 219 | #define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */ |
| 220 | −/* re recyle these flags for PWM */ | |
| 220 | +/* re recycle these flags for PWM */ | |
| 221 | 221 | #define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */ |
| 222 | 222 | #define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */ |
| 223 | 223 | |
| @@ -43,6 +43,23 @@ · 42 unmodified lines | ||
| 43 | 43 | |
| 44 | 44 | #include "comedi_internal.h" |
| 45 | 45 | |
| 46 | +/** | |
| 47 | + * comedi_subdevice "runflags" | |
| 48 | + * @COMEDI_SRF_RT: DEPRECATED: command is running real-time | |
| 49 | + * @COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred | |
| 50 | + * since the last command was started | |
| 51 | + * @COMEDI_SRF_RUNNING: command is running | |
| 52 | + * @COMEDI_SRF_FREE_SPRIV: free s->private on detach | |
| 53 | + * | |
| 54 | + * @COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" | |
| 55 | + */ | |
| 56 | +#define COMEDI_SRF_RT BIT(1) | |
| 57 | +#define COMEDI_SRF_ERROR BIT(2) | |
| 58 | +#define COMEDI_SRF_RUNNING BIT(27) | |
| 59 | +#define COMEDI_SRF_FREE_SPRIV BIT(31) | |
| 60 | + | |
| 61 | +#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) | |
| 62 | + | |
| 46 | 63 | /** |
| 47 | 64 | * struct comedi_file - per-file private data for comedi device |
| 48 | 65 | * @dev: comedi_device struct |
| @@ -679,8 +696,28 @@ static bool comedi_is_subdevice_idle(struct comedi_subdevice *s) · 630 unmodified lines | ||
| 679 | 696 | return !(runflags & COMEDI_SRF_BUSY_MASK); |
| 680 | 697 | } |
| 681 | 698 | |
| 699 | +bool comedi_can_auto_free_spriv(struct comedi_subdevice *s) | |
| 700 | +{ | |
| 701 | + unsigned runflags = __comedi_get_subdevice_runflags(s); | |
| 702 | + | |
| 703 | + return runflags & COMEDI_SRF_FREE_SPRIV; | |
| 704 | +} | |
| 705 | + | |
| 682 | 706 | /** |
| 683 | − * comedi_alloc_spriv() - Allocate memory for the subdevice private data. | |
| 707 | + * comedi_set_spriv_auto_free - mark subdevice private data as freeable | |
| 708 | + * @s: comedi_subdevice struct | |
| 709 | + * | |
| 710 | + * Mark the subdevice as having a pointer to private data that can be | |
| 711 | + * automatically freed by the comedi core during the detach. | |
| 712 | + */ | |
| 713 | +void comedi_set_spriv_auto_free(struct comedi_subdevice *s) | |
| 714 | +{ | |
| 715 | + __comedi_set_subdevice_runflags(s, COMEDI_SRF_FREE_SPRIV); | |
| 716 | +} | |
| 717 | +EXPORT_SYMBOL_GPL(comedi_set_spriv_auto_free); | |
| 718 | + | |
| 719 | +/** | |
| 720 | + * comedi_alloc_spriv - Allocate memory for the subdevice private data. | |
| 684 | 721 | * @s: comedi_subdevice struct |
| 685 | 722 | * @size: size of the memory to allocate |
| 686 | 723 | * |
| @@ -691,7 +728,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) · 4 unmodified lines | ||
| 691 | 728 | { |
| 692 | 729 | s->private = kzalloc(size, GFP_KERNEL); |
| 693 | 730 | if (s->private) |
| 694 | − s->runflags |= COMEDI_SRF_FREE_SPRIV; | |
| 731 | + comedi_set_spriv_auto_free(s); | |
| 695 | 732 | return s->private; |
| 696 | 733 | } |
| 697 | 734 | EXPORT_SYMBOL_GPL(comedi_alloc_spriv); |
| @@ -1048,11 +1085,6 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, · 350 unmodified lines | ||
| 1048 | 1085 | if (put_user(x, it.rangelist + i)) |
| 1049 | 1086 | return -EFAULT; |
| 1050 | 1087 | } |
| 1051 | −#if 0 | |
| 1052 | − if (copy_to_user(it.rangelist, s->range_type_list, | |
| 1053 | − s->n_chan * sizeof(unsigned int))) | |
| 1054 | − return -EFAULT; | |
| 1055 | −#endif | |
| 1056 | 1088 | } |
| 1057 | 1089 | |
| 1058 | 1090 | return 0; |
| @@ -1725,7 +1757,7 @@ cleanup: · 666 unmodified lines | ||
| 1725 | 1757 | |
| 1726 | 1758 | /* |
| 1727 | 1759 | * COMEDI_CMDTEST ioctl |
| 1728 | − * asynchronous aquisition command testing | |
| 1760 | + * asynchronous acquisition command testing | |
| 1729 | 1761 | * |
| 1730 | 1762 | * arg: |
| 1731 | 1763 | * pointer to comedi_cmd structure |
| @@ -33,6 +33,7 @@ struct comedi_buf_map *comedi_buf_map_from_subdev_get( · 32 unmodified lines | ||
| 33 | 33 | struct comedi_subdevice *s); |
| 34 | 34 | unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s); |
| 35 | 35 | void comedi_device_cancel_all(struct comedi_device *dev); |
| 36 | +bool comedi_can_auto_free_spriv(struct comedi_subdevice *s); | |
| 36 | 37 | |
| 37 | 38 | extern unsigned int comedi_default_buf_size_kb; |
| 38 | 39 | extern unsigned int comedi_default_buf_maxsize_kb; |
| @@ -227,12 +227,12 @@ struct comedi_async { · 226 unmodified lines | ||
| 227 | 227 | * @COMEDI_CB_ERROR_MASK: events that indicate an error has occurred |
| 228 | 228 | * @COMEDI_CB_CANCEL_MASK: events that will cancel an async command |
| 229 | 229 | */ |
| 230 | −#define COMEDI_CB_EOS (1 << 0) | |
| 231 | −#define COMEDI_CB_EOA (1 << 1) | |
| 232 | −#define COMEDI_CB_BLOCK (1 << 2) | |
| 233 | −#define COMEDI_CB_EOBUF (1 << 3) | |
| 234 | −#define COMEDI_CB_ERROR (1 << 4) | |
| 235 | −#define COMEDI_CB_OVERFLOW (1 << 5) | |
| 230 | +#define COMEDI_CB_EOS BIT(0) | |
| 231 | +#define COMEDI_CB_EOA BIT(1) | |
| 232 | +#define COMEDI_CB_BLOCK BIT(2) | |
| 233 | +#define COMEDI_CB_EOBUF BIT(3) | |
| 234 | +#define COMEDI_CB_ERROR BIT(4) | |
| 235 | +#define COMEDI_CB_OVERFLOW BIT(5) | |
| 236 | 236 | |
| 237 | 237 | #define COMEDI_CB_ERROR_MASK (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW) |
| 238 | 238 | #define COMEDI_CB_CANCEL_MASK (COMEDI_CB_EOA | COMEDI_CB_ERROR_MASK) |
| @@ -303,26 +303,10 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); · 64 unmodified lines | ||
| 303 | 303 | struct comedi_device *comedi_dev_get_from_minor(unsigned minor); |
| 304 | 304 | int comedi_dev_put(struct comedi_device *dev); |
| 305 | 305 | |
| 306 | −/** | |
| 307 | − * comedi_subdevice "runflags" | |
| 308 | − * @COMEDI_SRF_RT: DEPRECATED: command is running real-time | |
| 309 | − * @COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred | |
| 310 | − * since the last command was started | |
| 311 | − * @COMEDI_SRF_RUNNING: command is running | |
| 312 | − * @COMEDI_SRF_FREE_SPRIV: free s->private on detach | |
| 313 | − * | |
| 314 | − * @COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy" | |
| 315 | − */ | |
| 316 | −#define COMEDI_SRF_RT BIT(1) | |
| 317 | −#define COMEDI_SRF_ERROR BIT(2) | |
| 318 | −#define COMEDI_SRF_RUNNING BIT(27) | |
| 319 | −#define COMEDI_SRF_FREE_SPRIV BIT(31) | |
| 320 | − | |
| 321 | −#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING) | |
| 322 | − | |
| 323 | 306 | bool comedi_is_subdevice_running(struct comedi_subdevice *s); |
| 324 | 307 | |
| 325 | 308 | void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size); |
| 309 | +void comedi_set_spriv_auto_free(struct comedi_subdevice *s); | |
| 326 | 310 | |
| 327 | 311 | int comedi_check_chanlist(struct comedi_subdevice *s, |
| 328 | 312 | int n, |
| @@ -125,7 +125,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) · 124 unmodified lines | ||
| 125 | 125 | if (dev->subdevices) { |
| 126 | 126 | for (i = 0; i < dev->n_subdevices; i++) { |
| 127 | 127 | s = &dev->subdevices[i]; |
| 128 | − if (s->runflags & COMEDI_SRF_FREE_SPRIV) | |
| 128 | + if (comedi_can_auto_free_spriv(s)) | |
| 129 | 129 | kfree(s->private); |
| 130 | 130 | comedi_free_subdevice_minor(s); |
| 131 | 131 | if (s->async) { |
| @@ -53,221 +53,6 @@ · 52 unmodified lines | ||
| 53 | 53 | |
| 54 | 54 | #include "8255.h" |
| 55 | 55 | |
| 56 | −struct subdev_8255_private { | |
| 57 | − unsigned long regbase; | |
| 58 | − int (*io)(struct comedi_device *, int, int, int, unsigned long); | |
| 59 | −}; | |
| 60 | − | |
| 61 | −static int subdev_8255_io(struct comedi_device *dev, | |
| 62 | − int dir, int port, int data, unsigned long regbase) | |
| 63 | −{ | |
| 64 | − if (dir) { | |
| 65 | − outb(data, dev->iobase + regbase + port); | |
| 66 | − return 0; | |
| 67 | − } | |
| 68 | − return inb(dev->iobase + regbase + port); | |
| 69 | −} | |
| 70 | − | |
| 71 | −static int subdev_8255_mmio(struct comedi_device *dev, | |
| 72 | − int dir, int port, int data, unsigned long regbase) | |
| 73 | −{ | |
| 74 | − if (dir) { | |
| 75 | − writeb(data, dev->mmio + regbase + port); | |
| 76 | − return 0; | |
| 77 | − } | |
| 78 | − return readb(dev->mmio + regbase + port); | |
| 79 | −} | |
| 80 | − | |
| 81 | −static int subdev_8255_insn(struct comedi_device *dev, | |
| 82 | − struct comedi_subdevice *s, | |
| 83 | − struct comedi_insn *insn, | |
| 84 | − unsigned int *data) | |
| 85 | −{ | |
| 86 | − struct subdev_8255_private *spriv = s->private; | |
| 87 | − unsigned long regbase = spriv->regbase; | |
| 88 | − unsigned int mask; | |
| 89 | − unsigned int v; | |
| 90 | − | |
| 91 | − mask = comedi_dio_update_state(s, data); | |
| 92 | − if (mask) { | |
| 93 | − if (mask & 0xff) | |
| 94 | − spriv->io(dev, 1, I8255_DATA_A_REG, | |
| 95 | − s->state & 0xff, regbase); | |
| 96 | − if (mask & 0xff00) | |
| 97 | − spriv->io(dev, 1, I8255_DATA_B_REG, | |
| 98 | − (s->state >> 8) & 0xff, regbase); | |
| 99 | − if (mask & 0xff0000) | |
| 100 | − spriv->io(dev, 1, I8255_DATA_C_REG, | |
| 101 | − (s->state >> 16) & 0xff, regbase); | |
| 102 | − } | |
| 103 | − | |
| 104 | − v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, regbase); | |
| 105 | − v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, regbase) << 8); | |
| 106 | − v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, regbase) << 16); | |
| 107 | − | |
| 108 | − data[1] = v; | |
| 109 | − | |
| 110 | − return insn->n; | |
| 111 | −} | |
| 112 | − | |
| 113 | −static void subdev_8255_do_config(struct comedi_device *dev, | |
| 114 | − struct comedi_subdevice *s) | |
| 115 | −{ | |
| 116 | − struct subdev_8255_private *spriv = s->private; | |
| 117 | − unsigned long regbase = spriv->regbase; | |
| 118 | − int config; | |
| 119 | − | |
| 120 | − config = I8255_CTRL_CW; | |
| 121 | − /* 1 in io_bits indicates output, 1 in config indicates input */ | |
| 122 | − if (!(s->io_bits & 0x0000ff)) | |
| 123 | − config |= I8255_CTRL_A_IO; | |
| 124 | − if (!(s->io_bits & 0x00ff00)) | |
| 125 | − config |= I8255_CTRL_B_IO; | |
| 126 | − if (!(s->io_bits & 0x0f0000)) | |
| 127 | − config |= I8255_CTRL_C_LO_IO; | |
| 128 | − if (!(s->io_bits & 0xf00000)) | |
| 129 | − config |= I8255_CTRL_C_HI_IO; | |
| 130 | − | |
| 131 | − spriv->io(dev, 1, I8255_CTRL_REG, config, regbase); | |
| 132 | −} | |
| 133 | − | |
| 134 | −static int subdev_8255_insn_config(struct comedi_device *dev, | |
| 135 | − struct comedi_subdevice *s, | |
| 136 | − struct comedi_insn *insn, | |
| 137 | − unsigned int *data) | |
| 138 | −{ | |
| 139 | − unsigned int chan = CR_CHAN(insn->chanspec); | |
| 140 | − unsigned int mask; | |
| 141 | − int ret; | |
| 142 | − | |
| 143 | − if (chan < 8) | |
| 144 | − mask = 0x0000ff; | |
| 145 | − else if (chan < 16) | |
| 146 | − mask = 0x00ff00; | |
| 147 | − else if (chan < 20) | |
| 148 | − mask = 0x0f0000; | |
| 149 | − else | |
| 150 | − mask = 0xf00000; | |
| 151 | − | |
| 152 | − ret = comedi_dio_insn_config(dev, s, insn, data, mask); | |
| 153 | − if (ret) | |
| 154 | − return ret; | |
| 155 | − | |
| 156 | − subdev_8255_do_config(dev, s); | |
| 157 | − | |
| 158 | − return insn->n; | |
| 159 | −} | |
| 160 | − | |
| 161 | −static int __subdev_8255_init(struct comedi_device *dev, | |
| 162 | − struct comedi_subdevice *s, | |
| 163 | − int (*io)(struct comedi_device *, | |
| 164 | − int, int, int, unsigned long), | |
| 165 | − unsigned long regbase, | |
| 166 | − bool is_mmio) | |
| 167 | −{ | |
| 168 | − struct subdev_8255_private *spriv; | |
| 169 | − | |
| 170 | − spriv = comedi_alloc_spriv(s, sizeof(*spriv)); | |
| 171 | − if (!spriv) | |
| 172 | − return -ENOMEM; | |
| 173 | − | |
| 174 | − if (io) | |
| 175 | − spriv->io = io; | |
| 176 | − else if (is_mmio) | |
| 177 | − spriv->io = subdev_8255_mmio; | |
| 178 | − else | |
| 179 | − spriv->io = subdev_8255_io; | |
| 180 | − spriv->regbase = regbase; | |
| 181 | − | |
| 182 | − s->type = COMEDI_SUBD_DIO; | |
| 183 | − s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
| 184 | − s->n_chan = 24; | |
| 185 | − s->range_table = &range_digital; | |
| 186 | − s->maxdata = 1; | |
| 187 | − s->insn_bits = subdev_8255_insn; | |
| 188 | − s->insn_config = subdev_8255_insn_config; | |
| 189 | − | |
| 190 | − subdev_8255_do_config(dev, s); | |
| 191 | − | |
| 192 | − return 0; | |
| 193 | −} | |
| 194 | − | |
| 195 | −/** | |
| 196 | − * subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255 | |
| 197 | − * @dev: comedi device owning subdevice | |
| 198 | − * @s: comedi subdevice to initialize | |
| 199 | − * @io: (optional) register I/O call-back function | |
| 200 | − * @regbase: offset of 8255 registers from dev->iobase, or call-back context | |
| 201 | − * | |
| 202 | − * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. | |
| 203 | − * | |
| 204 | − * If the optional I/O call-back function is provided, its prototype is of | |
| 205 | − * the following form: | |
| 206 | − * | |
| 207 | − * int my_8255_callback(struct comedi_device *dev, | |
| 208 | − * struct comedi_subdevice *s, int dir, int port, | |
| 209 | − * int data, unsigned long regbase); | |
| 210 | − * | |
| 211 | − * where 'dev', 's', and 'regbase' match the values passed to this function, | |
| 212 | − * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' | |
| 213 | − * is the direction (0 for read, 1 for write) and 'data' is the value to be | |
| 214 | − * written. It should return 0 if writing or the value read if reading. | |
| 215 | − * | |
| 216 | − * If the optional I/O call-back function is not provided, an internal | |
| 217 | − * call-back function is used which uses consecutive I/O port addresses | |
| 218 | − * starting at dev->iobase + regbase. | |
| 219 | − * | |
| 220 | − * Return: -ENOMEM if failed to allocate memory, zero on success. | |
| 221 | − */ | |
| 222 | −int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 223 | − int (*io)(struct comedi_device *, | |
| 224 | − int, int, int, unsigned long), | |
| 225 | − unsigned long regbase) | |
| 226 | −{ | |
| 227 | − return __subdev_8255_init(dev, s, io, regbase, false); | |
| 228 | −} | |
| 229 | −EXPORT_SYMBOL_GPL(subdev_8255_init); | |
| 230 | − | |
| 231 | −/** | |
| 232 | − * subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255 | |
| 233 | − * @dev: comedi device owning subdevice | |
| 234 | − * @s: comedi subdevice to initialize | |
| 235 | − * @io: (optional) register I/O call-back function | |
| 236 | − * @regbase: offset of 8255 registers from dev->mmio, or call-back context | |
| 237 | − * | |
| 238 | − * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. | |
| 239 | − * | |
| 240 | − * If the optional I/O call-back function is provided, its prototype is of | |
| 241 | − * the following form: | |
| 242 | − * | |
| 243 | − * int my_8255_callback(struct comedi_device *dev, | |
| 244 | − * struct comedi_subdevice *s, int dir, int port, | |
| 245 | − * int data, unsigned long regbase); | |
| 246 | − * | |
| 247 | − * where 'dev', 's', and 'regbase' match the values passed to this function, | |
| 248 | − * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' | |
| 249 | − * is the direction (0 for read, 1 for write) and 'data' is the value to be | |
| 250 | − * written. It should return 0 if writing or the value read if reading. | |
| 251 | − * | |
| 252 | − * If the optional I/O call-back function is not provided, an internal | |
| 253 | − * call-back function is used which uses consecutive MMIO virtual addresses | |
| 254 | − * starting at dev->mmio + regbase. | |
| 255 | − * | |
| 256 | − * Return: -ENOMEM if failed to allocate memory, zero on success. | |
| 257 | − */ | |
| 258 | −int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 259 | − int (*io)(struct comedi_device *, | |
| 260 | − int, int, int, unsigned long), | |
| 261 | − unsigned long regbase) | |
| 262 | −{ | |
| 263 | − return __subdev_8255_init(dev, s, io, regbase, true); | |
| 264 | −} | |
| 265 | −EXPORT_SYMBOL_GPL(subdev_8255_mm_init); | |
| 266 | − | |
| 267 | −/* | |
| 268 | − * Start of the 8255 standalone device | |
| 269 | − */ | |
| 270 | − | |
| 271 | 56 | static int dev_8255_attach(struct comedi_device *dev, |
| 272 | 57 | struct comedi_devconfig *it) |
| 273 | 58 | { |
| @@ -306,8 +91,15 @@ static int dev_8255_attach(struct comedi_device *dev, · 32 unmodified lines | ||
| 306 | 91 | s->type = COMEDI_SUBD_UNUSED; |
| 307 | 92 | } else { |
| 308 | 93 | ret = subdev_8255_init(dev, s, NULL, iobase); |
| 309 | − if (ret) | |
| 94 | + if (ret) { | |
| 95 | + /* | |
| 96 | + * Release the I/O port region here, as the | |
| 97 | + * "detach" handler cannot find it. | |
| 98 | + */ | |
| 99 | + release_region(iobase, I8255_SIZE); | |
| 100 | + s->type = COMEDI_SUBD_UNUSED; | |
| 310 | 101 | return ret; |
| 102 | + } | |
| 311 | 103 | } |
| 312 | 104 | } |
| 313 | 105 | |
| @@ -317,14 +109,14 @@ static int dev_8255_attach(struct comedi_device *dev, · 3 unmodified lines | ||
| 317 | 109 | static void dev_8255_detach(struct comedi_device *dev) |
| 318 | 110 | { |
| 319 | 111 | struct comedi_subdevice *s; |
| 320 | − struct subdev_8255_private *spriv; | |
| 321 | 112 | int i; |
| 322 | 113 | |
| 323 | 114 | for (i = 0; i < dev->n_subdevices; i++) { |
| 324 | 115 | s = &dev->subdevices[i]; |
| 325 | 116 | if (s->type != COMEDI_SUBD_UNUSED) { |
| 326 | − spriv = s->private; | |
| 327 | − release_region(spriv->regbase, I8255_SIZE); | |
| 117 | + unsigned long regbase = subdev_8255_regbase(s); | |
| 118 | + | |
| 119 | + release_region(regbase, I8255_SIZE); | |
| 328 | 120 | } |
| 329 | 121 | } |
| 330 | 122 | } |
| @@ -338,5 +130,5 @@ static struct comedi_driver dev_8255_driver = { · 7 unmodified lines | ||
| 338 | 130 | module_comedi_driver(dev_8255_driver); |
| 339 | 131 | |
| 340 | 132 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 341 | −MODULE_DESCRIPTION("Comedi low-level driver"); | |
| 133 | +MODULE_DESCRIPTION("Comedi driver for standalone 8255 devices"); | |
| 342 | 134 | MODULE_LICENSE("GPL"); |
| @@ -19,8 +19,6 @@ · 18 unmodified lines | ||
| 19 | 19 | #ifndef _8255_H |
| 20 | 20 | #define _8255_H |
| 21 | 21 | |
| 22 | −#include "../comedidev.h" | |
| 23 | − | |
| 24 | 22 | #define I8255_SIZE 0x04 |
| 25 | 23 | |
| 26 | 24 | #define I8255_DATA_A_REG 0x00 |
| @@ -35,14 +33,19 @@ · 8 unmodified lines | ||
| 35 | 33 | #define I8255_CTRL_A_MODE(x) ((x) << 5) |
| 36 | 34 | #define I8255_CTRL_CW (1 << 7) |
| 37 | 35 | |
| 38 | −int subdev_8255_init(struct comedi_device *, struct comedi_subdevice *, | |
| 39 | − int (*io)(struct comedi_device *, | |
| 40 | − int, int, int, unsigned long), | |
| 36 | +struct comedi_device; | |
| 37 | +struct comedi_subdevice; | |
| 38 | + | |
| 39 | +int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 40 | + int (*io)(struct comedi_device *dev, int dir, int port, | |
| 41 | + int data, unsigned long regbase), | |
| 41 | 42 | unsigned long regbase); |
| 42 | 43 | |
| 43 | −int subdev_8255_mm_init(struct comedi_device *, struct comedi_subdevice *, | |
| 44 | − int (*io)(struct comedi_device *, | |
| 45 | − int, int, int, unsigned long), | |
| 44 | +int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 45 | + int (*io)(struct comedi_device *dev, int dir, int port, | |
| 46 | + int data, unsigned long regbase), | |
| 46 | 47 | unsigned long regbase); |
| 47 | 48 | |
| 49 | +unsigned long subdev_8255_regbase(struct comedi_subdevice *s); | |
| 50 | + | |
| 48 | 51 | #endif |
| @@ -139,7 +139,8 @@ obj-$(CONFIG_COMEDI_NI_TIOCMD) += ni_tiocmd.o · 138 unmodified lines | ||
| 139 | 139 | obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc_common.o |
| 140 | 140 | obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA) += ni_labpc_isadma.o |
| 141 | 141 | |
| 142 | −obj-$(CONFIG_COMEDI_8255) += 8255.o | |
| 142 | +obj-$(CONFIG_COMEDI_8255) += comedi_8255.o | |
| 143 | +obj-$(CONFIG_COMEDI_8255_SA) += 8255.o | |
| 143 | 144 | obj-$(CONFIG_COMEDI_AMPLC_DIO200) += amplc_dio200_common.o |
| 144 | 145 | obj-$(CONFIG_COMEDI_AMPLC_PC236) += amplc_pc236_common.o |
| 145 | 146 | obj-$(CONFIG_COMEDI_DAS08) += das08.o |
| @@ -100,10 +100,10 @@ static int apci1516_do_insn_bits(struct comedi_device *dev, · 99 unmodified lines | ||
| 100 | 100 | |
| 101 | 101 | static int apci1516_reset(struct comedi_device *dev) |
| 102 | 102 | { |
| 103 | − const struct apci1516_boardinfo *this_board = dev->board_ptr; | |
| 103 | + const struct apci1516_boardinfo *board = dev->board_ptr; | |
| 104 | 104 | struct apci1516_private *devpriv = dev->private; |
| 105 | 105 | |
| 106 | − if (!this_board->has_wdog) | |
| 106 | + if (!board->has_wdog) | |
| 107 | 107 | return 0; |
| 108 | 108 | |
| 109 | 109 | outw(0x0, dev->iobase + APCI1516_DO_REG); |
| @@ -117,17 +117,17 @@ static int apci1516_auto_attach(struct comedi_device *dev, · 7 unmodified lines | ||
| 117 | 117 | unsigned long context) |
| 118 | 118 | { |
| 119 | 119 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 120 | − const struct apci1516_boardinfo *this_board = NULL; | |
| 120 | + const struct apci1516_boardinfo *board = NULL; | |
| 121 | 121 | struct apci1516_private *devpriv; |
| 122 | 122 | struct comedi_subdevice *s; |
| 123 | 123 | int ret; |
| 124 | 124 | |
| 125 | 125 | if (context < ARRAY_SIZE(apci1516_boardtypes)) |
| 126 | − this_board = &apci1516_boardtypes[context]; | |
| 127 | − if (!this_board) | |
| 126 | + board = &apci1516_boardtypes[context]; | |
| 127 | + if (!board) | |
| 128 | 128 | return -ENODEV; |
| 129 | − dev->board_ptr = this_board; | |
| 130 | − dev->board_name = this_board->name; | |
| 129 | + dev->board_ptr = board; | |
| 130 | + dev->board_name = board->name; | |
| 131 | 131 | |
| 132 | 132 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 133 | 133 | if (!devpriv) |
| @@ -146,10 +146,10 @@ static int apci1516_auto_attach(struct comedi_device *dev, · 12 unmodified lines | ||
| 146 | 146 | |
| 147 | 147 | /* Initialize the digital input subdevice */ |
| 148 | 148 | s = &dev->subdevices[0]; |
| 149 | − if (this_board->di_nchan) { | |
| 149 | + if (board->di_nchan) { | |
| 150 | 150 | s->type = COMEDI_SUBD_DI; |
| 151 | 151 | s->subdev_flags = SDF_READABLE; |
| 152 | − s->n_chan = this_board->di_nchan; | |
| 152 | + s->n_chan = board->di_nchan; | |
| 153 | 153 | s->maxdata = 1; |
| 154 | 154 | s->range_table = &range_digital; |
| 155 | 155 | s->insn_bits = apci1516_di_insn_bits; |
| @@ -159,10 +159,10 @@ static int apci1516_auto_attach(struct comedi_device *dev, · 3 unmodified lines | ||
| 159 | 159 | |
| 160 | 160 | /* Initialize the digital output subdevice */ |
| 161 | 161 | s = &dev->subdevices[1]; |
| 162 | − if (this_board->do_nchan) { | |
| 162 | + if (board->do_nchan) { | |
| 163 | 163 | s->type = COMEDI_SUBD_DO; |
| 164 | 164 | s->subdev_flags = SDF_WRITABLE; |
| 165 | − s->n_chan = this_board->do_nchan; | |
| 165 | + s->n_chan = board->do_nchan; | |
| 166 | 166 | s->maxdata = 1; |
| 167 | 167 | s->range_table = &range_digital; |
| 168 | 168 | s->insn_bits = apci1516_do_insn_bits; |
| @@ -172,7 +172,7 @@ static int apci1516_auto_attach(struct comedi_device *dev, · 3 unmodified lines | ||
| 172 | 172 | |
| 173 | 173 | /* Initialize the watchdog subdevice */ |
| 174 | 174 | s = &dev->subdevices[2]; |
| 175 | − if (this_board->has_wdog) { | |
| 175 | + if (board->has_wdog) { | |
| 176 | 176 | ret = addi_watchdog_init(s, devpriv->wdog_iobase); |
| 177 | 177 | if (ret) |
| 178 | 178 | return ret; |
| @@ -977,18 +977,18 @@ static int apci3120_auto_attach(struct comedi_device *dev, · 976 unmodified lines | ||
| 977 | 977 | unsigned long context) |
| 978 | 978 | { |
| 979 | 979 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 980 | − const struct apci3120_board *this_board = NULL; | |
| 980 | + const struct apci3120_board *board = NULL; | |
| 981 | 981 | struct apci3120_private *devpriv; |
| 982 | 982 | struct comedi_subdevice *s; |
| 983 | 983 | unsigned int status; |
| 984 | 984 | int ret; |
| 985 | 985 | |
| 986 | 986 | if (context < ARRAY_SIZE(apci3120_boardtypes)) |
| 987 | − this_board = &apci3120_boardtypes[context]; | |
| 988 | − if (!this_board) | |
| 987 | + board = &apci3120_boardtypes[context]; | |
| 988 | + if (!board) | |
| 989 | 989 | return -ENODEV; |
| 990 | − dev->board_ptr = this_board; | |
| 991 | − dev->board_name = this_board->name; | |
| 990 | + dev->board_ptr = board; | |
| 991 | + dev->board_name = board->name; | |
| 992 | 992 | |
| 993 | 993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 994 | 994 | if (!devpriv) |
| @@ -1031,7 +1031,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, · 36 unmodified lines | ||
| 1031 | 1031 | s->type = COMEDI_SUBD_AI; |
| 1032 | 1032 | s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; |
| 1033 | 1033 | s->n_chan = 16; |
| 1034 | − s->maxdata = this_board->ai_is_16bit ? 0xffff : 0x0fff; | |
| 1034 | + s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff; | |
| 1035 | 1035 | s->range_table = &apci3120_ai_range; |
| 1036 | 1036 | s->insn_read = apci3120_ai_insn_read; |
| 1037 | 1037 | if (dev->irq) { |
| @@ -1045,7 +1045,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, · 7 unmodified lines | ||
| 1045 | 1045 | |
| 1046 | 1046 | /* Analog Output subdevice */ |
| 1047 | 1047 | s = &dev->subdevices[1]; |
| 1048 | − if (this_board->has_ao) { | |
| 1048 | + if (board->has_ao) { | |
| 1049 | 1049 | s->type = COMEDI_SUBD_AO; |
| 1050 | 1050 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; |
| 1051 | 1051 | s->n_chan = 8; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | #ifndef _ADDI_WATCHDOG_H |
| 2 | 2 | #define _ADDI_WATCHDOG_H |
| 3 | 3 | |
| 4 | −#include "../comedidev.h" | |
| 4 | +struct comedi_subdevice; | |
| 5 | 5 | |
| 6 | 6 | void addi_watchdog_reset(unsigned long iobase); |
| 7 | 7 | int addi_watchdog_init(struct comedi_subdevice *, unsigned long iobase); |
| @@ -180,11 +180,7 @@ static int adv_pci1724_auto_attach(struct comedi_device *dev, · 179 unmodified lines | ||
| 180 | 180 | s->insn_write = adv_pci1724_insn_write; |
| 181 | 181 | s->private = (void *)PCI1724_DAC_CTRL_MODE_GAIN; |
| 182 | 182 | |
| 183 | − ret = comedi_alloc_subdev_readback(s); | |
| 184 | − if (ret) | |
| 185 | − return ret; | |
| 186 | − | |
| 187 | − return 0; | |
| 183 | + return comedi_alloc_subdev_readback(s); | |
| 188 | 184 | } |
| 189 | 185 | |
| 190 | 186 | static struct comedi_driver adv_pci1724_driver = { |
| @@ -732,9 +732,9 @@ static int pci1760_reset(struct comedi_device *dev) · 731 unmodified lines | ||
| 732 | 732 | */ |
| 733 | 733 | static int pci_dio_reset(struct comedi_device *dev) |
| 734 | 734 | { |
| 735 | − const struct dio_boardtype *this_board = dev->board_ptr; | |
| 735 | + const struct dio_boardtype *board = dev->board_ptr; | |
| 736 | 736 | |
| 737 | − switch (this_board->cardtype) { | |
| 737 | + switch (board->cardtype) { | |
| 738 | 738 | case TYPE_PCI1730: |
| 739 | 739 | outb(0, dev->iobase + PCI1730_DO); /* clear outputs */ |
| 740 | 740 | outb(0, dev->iobase + PCI1730_DO + 1); |
| @@ -887,7 +887,7 @@ static int pci_dio_add_di(struct comedi_device *dev, · 146 unmodified lines | ||
| 887 | 887 | struct comedi_subdevice *s, |
| 888 | 888 | const struct diosubd_data *d) |
| 889 | 889 | { |
| 890 | − const struct dio_boardtype *this_board = dev->board_ptr; | |
| 890 | + const struct dio_boardtype *board = dev->board_ptr; | |
| 891 | 891 | |
| 892 | 892 | s->type = COMEDI_SUBD_DI; |
| 893 | 893 | s->subdev_flags = SDF_READABLE | d->specflags; |
| @@ -897,7 +897,7 @@ static int pci_dio_add_di(struct comedi_device *dev, · 3 unmodified lines | ||
| 897 | 897 | s->maxdata = 1; |
| 898 | 898 | s->len_chanlist = d->chans; |
| 899 | 899 | s->range_table = &range_digital; |
| 900 | − switch (this_board->io_access) { | |
| 900 | + switch (board->io_access) { | |
| 901 | 901 | case IO_8b: |
| 902 | 902 | s->insn_bits = pci_dio_insn_bits_di_b; |
| 903 | 903 | break; |
| @@ -917,7 +917,7 @@ static int pci_dio_add_do(struct comedi_device *dev, · 13 unmodified lines | ||
| 917 | 917 | struct comedi_subdevice *s, |
| 918 | 918 | const struct diosubd_data *d) |
| 919 | 919 | { |
| 920 | − const struct dio_boardtype *this_board = dev->board_ptr; | |
| 920 | + const struct dio_boardtype *board = dev->board_ptr; | |
| 921 | 921 | |
| 922 | 922 | s->type = COMEDI_SUBD_DO; |
| 923 | 923 | s->subdev_flags = SDF_WRITABLE; |
| @@ -928,7 +928,7 @@ static int pci_dio_add_do(struct comedi_device *dev, · 4 unmodified lines | ||
| 928 | 928 | s->len_chanlist = d->chans; |
| 929 | 929 | s->range_table = &range_digital; |
| 930 | 930 | s->state = 0; |
| 931 | − switch (this_board->io_access) { | |
| 931 | + switch (board->io_access) { | |
| 932 | 932 | case IO_8b: |
| 933 | 933 | s->insn_bits = pci_dio_insn_bits_do_b; |
| 934 | 934 | break; |
| @@ -978,17 +978,17 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 43 unmodified lines | ||
| 978 | 978 | unsigned long context) |
| 979 | 979 | { |
| 980 | 980 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 981 | − const struct dio_boardtype *this_board = NULL; | |
| 981 | + const struct dio_boardtype *board = NULL; | |
| 982 | 982 | struct pci_dio_private *devpriv; |
| 983 | 983 | struct comedi_subdevice *s; |
| 984 | 984 | int ret, subdev, i, j; |
| 985 | 985 | |
| 986 | 986 | if (context < ARRAY_SIZE(boardtypes)) |
| 987 | − this_board = &boardtypes[context]; | |
| 988 | − if (!this_board) | |
| 987 | + board = &boardtypes[context]; | |
| 988 | + if (!board) | |
| 989 | 989 | return -ENODEV; |
| 990 | − dev->board_ptr = this_board; | |
| 991 | − dev->board_name = this_board->name; | |
| 990 | + dev->board_ptr = board; | |
| 991 | + dev->board_name = board->name; | |
| 992 | 992 | |
| 993 | 993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 994 | 994 | if (!devpriv) |
| @@ -997,50 +997,50 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 2 unmodified lines | ||
| 997 | 997 | ret = comedi_pci_enable(dev); |
| 998 | 998 | if (ret) |
| 999 | 999 | return ret; |
| 1000 | − dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region); | |
| 1000 | + dev->iobase = pci_resource_start(pcidev, board->main_pci_region); | |
| 1001 | 1001 | |
| 1002 | − ret = comedi_alloc_subdevices(dev, this_board->nsubdevs); | |
| 1002 | + ret = comedi_alloc_subdevices(dev, board->nsubdevs); | |
| 1003 | 1003 | if (ret) |
| 1004 | 1004 | return ret; |
| 1005 | 1005 | |
| 1006 | 1006 | subdev = 0; |
| 1007 | 1007 | for (i = 0; i < MAX_DI_SUBDEVS; i++) |
| 1008 | − if (this_board->sdi[i].chans) { | |
| 1008 | + if (board->sdi[i].chans) { | |
| 1009 | 1009 | s = &dev->subdevices[subdev]; |
| 1010 | − pci_dio_add_di(dev, s, &this_board->sdi[i]); | |
| 1010 | + pci_dio_add_di(dev, s, &board->sdi[i]); | |
| 1011 | 1011 | subdev++; |
| 1012 | 1012 | } |
| 1013 | 1013 | |
| 1014 | 1014 | for (i = 0; i < MAX_DO_SUBDEVS; i++) |
| 1015 | − if (this_board->sdo[i].chans) { | |
| 1015 | + if (board->sdo[i].chans) { | |
| 1016 | 1016 | s = &dev->subdevices[subdev]; |
| 1017 | − pci_dio_add_do(dev, s, &this_board->sdo[i]); | |
| 1017 | + pci_dio_add_do(dev, s, &board->sdo[i]); | |
| 1018 | 1018 | subdev++; |
| 1019 | 1019 | } |
| 1020 | 1020 | |
| 1021 | 1021 | for (i = 0; i < MAX_DIO_SUBDEVG; i++) |
| 1022 | − for (j = 0; j < this_board->sdio[i].regs; j++) { | |
| 1022 | + for (j = 0; j < board->sdio[i].regs; j++) { | |
| 1023 | 1023 | s = &dev->subdevices[subdev]; |
| 1024 | 1024 | ret = subdev_8255_init(dev, s, NULL, |
| 1025 | − this_board->sdio[i].addr + | |
| 1025 | + board->sdio[i].addr + | |
| 1026 | 1026 | j * I8255_SIZE); |
| 1027 | 1027 | if (ret) |
| 1028 | 1028 | return ret; |
| 1029 | 1029 | subdev++; |
| 1030 | 1030 | } |
| 1031 | 1031 | |
| 1032 | − if (this_board->boardid.chans) { | |
| 1032 | + if (board->boardid.chans) { | |
| 1033 | 1033 | s = &dev->subdevices[subdev]; |
| 1034 | 1034 | s->type = COMEDI_SUBD_DI; |
| 1035 | − pci_dio_add_di(dev, s, &this_board->boardid); | |
| 1035 | + pci_dio_add_di(dev, s, &board->boardid); | |
| 1036 | 1036 | subdev++; |
| 1037 | 1037 | } |
| 1038 | 1038 | |
| 1039 | − if (this_board->timer_regbase) { | |
| 1039 | + if (board->timer_regbase) { | |
| 1040 | 1040 | s = &dev->subdevices[subdev]; |
| 1041 | 1041 | |
| 1042 | 1042 | dev->pacer = comedi_8254_init(dev->iobase + |
| 1043 | − this_board->timer_regbase, | |
| 1043 | + board->timer_regbase, | |
| 1044 | 1044 | 0, I8254_IO8, 0); |
| 1045 | 1045 | if (!dev->pacer) |
| 1046 | 1046 | return -ENOMEM; |
| @@ -1050,7 +1050,7 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 3 unmodified lines | ||
| 1050 | 1050 | subdev++; |
| 1051 | 1051 | } |
| 1052 | 1052 | |
| 1053 | − if (this_board->cardtype == TYPE_PCI1760) | |
| 1053 | + if (board->cardtype == TYPE_PCI1760) | |
| 1054 | 1054 | pci1760_attach(dev); |
| 1055 | 1055 | |
| 1056 | 1056 | pci_dio_reset(dev); |
| @@ -1,23 +1,24 @@ | ||
| 1 | 1 | /* |
| 2 | − comedi/drivers/amplc_dio200.c | |
| 3 | − | |
| 4 | − Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. | |
| 5 | − | |
| 6 | − Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 7 | − | |
| 8 | − COMEDI - Linux Control and Measurement Device Interface | |
| 9 | − Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 10 | − | |
| 11 | − This program is free software; you can redistribute it and/or modify | |
| 12 | − it under the terms of the GNU General Public License as published by | |
| 13 | − the Free Software Foundation; either version 2 of the License, or | |
| 14 | − (at your option) any later version. | |
| 2 | + * comedi/drivers/amplc_dio200.c | |
| 3 | + * | |
| 4 | + * Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. | |
| 5 | + * | |
| 6 | + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 7 | + * | |
| 8 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 9 | + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 10 | + * | |
| 11 | + * This program is free software; you can redistribute it and/or modify | |
| 12 | + * it under the terms of the GNU General Public License as published by | |
| 13 | + * the Free Software Foundation; either version 2 of the License, or | |
| 14 | + * (at your option) any later version. | |
| 15 | + * | |
| 16 | + * This program is distributed in the hope that it will be useful, | |
| 17 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | + * GNU General Public License for more details. | |
| 20 | + */ | |
| 15 | 21 | |
| 16 | − This program is distributed in the hope that it will be useful, | |
| 17 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | − GNU General Public License for more details. | |
| 20 | −*/ | |
| 21 | 22 | /* |
| 22 | 23 | * Driver: amplc_dio200 |
| 23 | 24 | * Description: Amplicon 200 Series ISA Digital I/O |
| @@ -1,28 +1,32 @@ | ||
| 1 | 1 | /* |
| 2 | − comedi/drivers/amplc_dio.h | |
| 3 | − | |
| 4 | − Header for amplc_dio200.c, amplc_dio200_common.c and | |
| 5 | − amplc_dio200_pci.c. | |
| 6 | − | |
| 7 | − Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 8 | − | |
| 9 | − COMEDI - Linux Control and Measurement Device Interface | |
| 10 | − Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 11 | − | |
| 12 | − This program is free software; you can redistribute it and/or modify | |
| 13 | − it under the terms of the GNU General Public License as published by | |
| 14 | − the Free Software Foundation; either version 2 of the License, or | |
| 15 | − (at your option) any later version. | |
| 16 | − | |
| 17 | − This program is distributed in the hope that it will be useful, | |
| 18 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 | − GNU General Public License for more details. | |
| 21 | −*/ | |
| 2 | + * comedi/drivers/amplc_dio.h | |
| 3 | + * | |
| 4 | + * Header for amplc_dio200.c, amplc_dio200_common.c and | |
| 5 | + * amplc_dio200_pci.c. | |
| 6 | + * | |
| 7 | + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 8 | + * | |
| 9 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 10 | + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 11 | + * | |
| 12 | + * This program is free software; you can redistribute it and/or modify | |
| 13 | + * it under the terms of the GNU General Public License as published by | |
| 14 | + * the Free Software Foundation; either version 2 of the License, or | |
| 15 | + * (at your option) any later version. | |
| 16 | + * | |
| 17 | + * This program is distributed in the hope that it will be useful, | |
| 18 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 19 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 20 | + * GNU General Public License for more details. | |
| 21 | + */ | |
| 22 | 22 | |
| 23 | 23 | #ifndef AMPLC_DIO200_H_INCLUDED |
| 24 | 24 | #define AMPLC_DIO200_H_INCLUDED |
| 25 | 25 | |
| 26 | +#include <linux/types.h> | |
| 27 | + | |
| 28 | +struct comedi_device; | |
| 29 | + | |
| 26 | 30 | /* |
| 27 | 31 | * Subdevice types. |
| 28 | 32 | */ |
| @@ -1,23 +1,23 @@ | ||
| 1 | 1 | /* |
| 2 | − comedi/drivers/amplc_dio200_common.c | |
| 3 | − | |
| 4 | − Common support code for "amplc_dio200" and "amplc_dio200_pci". | |
| 5 | − | |
| 6 | − Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 7 | − | |
| 8 | − COMEDI - Linux Control and Measurement Device Interface | |
| 9 | − Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 10 | − | |
| 11 | − This program is free software; you can redistribute it and/or modify | |
| 12 | − it under the terms of the GNU General Public License as published by | |
| 13 | − the Free Software Foundation; either version 2 of the License, or | |
| 14 | − (at your option) any later version. | |
| 15 | − | |
| 16 | − This program is distributed in the hope that it will be useful, | |
| 17 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | − GNU General Public License for more details. | |
| 20 | −*/ | |
| 2 | + * comedi/drivers/amplc_dio200_common.c | |
| 3 | + * | |
| 4 | + * Common support code for "amplc_dio200" and "amplc_dio200_pci". | |
| 5 | + * | |
| 6 | + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 7 | + * | |
| 8 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 9 | + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 10 | + * | |
| 11 | + * This program is free software; you can redistribute it and/or modify | |
| 12 | + * it under the terms of the GNU General Public License as published by | |
| 13 | + * the Free Software Foundation; either version 2 of the License, or | |
| 14 | + * (at your option) any later version. | |
| 15 | + * | |
| 16 | + * This program is distributed in the hope that it will be useful, | |
| 17 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | + * GNU General Public License for more details. | |
| 20 | + */ | |
| 21 | 21 | |
| 22 | 22 | #include <linux/module.h> |
| 23 | 23 | #include <linux/interrupt.h> |
| @@ -337,9 +337,10 @@ static int dio200_handle_read_intr(struct comedi_device *dev, · 313 unmodified lines | ||
| 337 | 337 | * interested in (just in case there's a race |
| 338 | 338 | * condition). |
| 339 | 339 | */ |
| 340 | − if (triggered & subpriv->enabled_isns) | |
| 340 | + if (triggered & subpriv->enabled_isns) { | |
| 341 | 341 | /* Collect scan data. */ |
| 342 | 342 | dio200_read_scan_intr(dev, s, triggered); |
| 343 | + } | |
| 343 | 344 | } |
| 344 | 345 | } |
| 345 | 346 | spin_unlock_irqrestore(&subpriv->spinlock, flags); |
| @@ -576,12 +577,13 @@ static int dio200_subdev_8254_init(struct comedi_device *dev, · 230 unmodified lines | ||
| 576 | 577 | regshift = 0; |
| 577 | 578 | } |
| 578 | 579 | |
| 579 | − if (dev->mmio) | |
| 580 | + if (dev->mmio) { | |
| 580 | 581 | i8254 = comedi_8254_mm_init(dev->mmio + offset, |
| 581 | 582 | 0, I8254_IO8, regshift); |
| 582 | − else | |
| 583 | + } else { | |
| 583 | 584 | i8254 = comedi_8254_init(dev->iobase + offset, |
| 584 | 585 | 0, I8254_IO8, regshift); |
| 586 | + } | |
| 585 | 587 | if (!i8254) |
| 586 | 588 | return -ENOMEM; |
| 587 | 589 | |
| @@ -593,10 +595,10 @@ static int dio200_subdev_8254_init(struct comedi_device *dev, · 5 unmodified lines | ||
| 593 | 595 | * There could be multiple timers so this driver does not |
| 594 | 596 | * use dev->pacer to save the i8254 pointer. Instead, |
| 595 | 597 | * comedi_8254_subdevice_init() saved the i8254 pointer in |
| 596 | − * s->private. Set the runflag bit so that the core will | |
| 597 | − * automatically free it when the driver is detached. | |
| 598 | + * s->private. Mark the subdevice as having private data | |
| 599 | + * to be automatically freed when the device is detached. | |
| 598 | 600 | */ |
| 599 | − s->runflags |= COMEDI_SRF_FREE_SPRIV; | |
| 601 | + comedi_set_spriv_auto_free(s); | |
| 600 | 602 | |
| 601 | 603 | /* Initialize channels. */ |
| 602 | 604 | if (board->has_clk_gat_sce) { |
| @@ -641,15 +643,18 @@ static int dio200_subdev_8255_bits(struct comedi_device *dev, · 38 unmodified lines | ||
| 641 | 643 | |
| 642 | 644 | mask = comedi_dio_update_state(s, data); |
| 643 | 645 | if (mask) { |
| 644 | − if (mask & 0xff) | |
| 646 | + if (mask & 0xff) { | |
| 645 | 647 | dio200_write8(dev, subpriv->ofs + I8255_DATA_A_REG, |
| 646 | 648 | s->state & 0xff); |
| 647 | − if (mask & 0xff00) | |
| 649 | + } | |
| 650 | + if (mask & 0xff00) { | |
| 648 | 651 | dio200_write8(dev, subpriv->ofs + I8255_DATA_B_REG, |
| 649 | 652 | (s->state >> 8) & 0xff); |
| 650 | − if (mask & 0xff0000) | |
| 653 | + } | |
| 654 | + if (mask & 0xff0000) { | |
| 651 | 655 | dio200_write8(dev, subpriv->ofs + I8255_DATA_C_REG, |
| 652 | 656 | (s->state >> 16) & 0xff); |
| 657 | + } | |
| 653 | 658 | } |
| 654 | 659 | |
| 655 | 660 | val = dio200_read8(dev, subpriv->ofs + I8255_DATA_A_REG); |
| @@ -1,22 +1,23 @@ | ||
| 1 | 1 | /* comedi/drivers/amplc_dio200_pci.c |
| 2 | + * | |
| 3 | + * Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. | |
| 4 | + * | |
| 5 | + * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 6 | + * | |
| 7 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 8 | + * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 9 | + * | |
| 10 | + * This program is free software; you can redistribute it and/or modify | |
| 11 | + * it under the terms of the GNU General Public License as published by | |
| 12 | + * the Free Software Foundation; either version 2 of the License, or | |
| 13 | + * (at your option) any later version. | |
| 14 | + * | |
| 15 | + * This program is distributed in the hope that it will be useful, | |
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | + * GNU General Public License for more details. | |
| 19 | + */ | |
| 2 | 20 | |
| 3 | − Driver for Amplicon PCI215, PCI272, PCIe215, PCIe236, PCIe296. | |
| 4 | − | |
| 5 | − Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | |
| 6 | − | |
| 7 | − COMEDI - Linux Control and Measurement Device Interface | |
| 8 | − Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | |
| 9 | − | |
| 10 | − This program is free software; you can redistribute it and/or modify | |
| 11 | − it under the terms of the GNU General Public License as published by | |
| 12 | − the Free Software Foundation; either version 2 of the License, or | |
| 13 | − (at your option) any later version. | |
| 14 | − | |
| 15 | − This program is distributed in the hope that it will be useful, | |
| 16 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − GNU General Public License for more details. | |
| 19 | −*/ | |
| 20 | 21 | /* |
| 21 | 22 | * Driver: amplc_dio200_pci |
| 22 | 23 | * Description: Amplicon 200 Series PCI Digital I/O |
| @@ -28,14 +28,14 @@ · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | static void pc236_intr_update(struct comedi_device *dev, bool enable) |
| 30 | 30 | { |
| 31 | − const struct pc236_board *thisboard = dev->board_ptr; | |
| 31 | + const struct pc236_board *board = dev->board_ptr; | |
| 32 | 32 | struct pc236_private *devpriv = dev->private; |
| 33 | 33 | unsigned long flags; |
| 34 | 34 | |
| 35 | 35 | spin_lock_irqsave(&dev->spinlock, flags); |
| 36 | 36 | devpriv->enable_irq = enable; |
| 37 | − if (thisboard->intr_update_cb) | |
| 38 | − thisboard->intr_update_cb(dev, enable); | |
| 37 | + if (board->intr_update_cb) | |
| 38 | + board->intr_update_cb(dev, enable); | |
| 39 | 39 | spin_unlock_irqrestore(&dev->spinlock, flags); |
| 40 | 40 | } |
| 41 | 41 | |
| @@ -48,15 +48,15 @@ static void pc236_intr_update(struct comedi_device *dev, bool enable) · 6 unmodified lines | ||
| 48 | 48 | */ |
| 49 | 49 | static bool pc236_intr_check(struct comedi_device *dev) |
| 50 | 50 | { |
| 51 | − const struct pc236_board *thisboard = dev->board_ptr; | |
| 51 | + const struct pc236_board *board = dev->board_ptr; | |
| 52 | 52 | struct pc236_private *devpriv = dev->private; |
| 53 | 53 | bool retval = false; |
| 54 | 54 | unsigned long flags; |
| 55 | 55 | |
| 56 | 56 | spin_lock_irqsave(&dev->spinlock, flags); |
| 57 | 57 | if (devpriv->enable_irq) { |
| 58 | − if (thisboard->intr_chk_clr_cb) | |
| 59 | − retval = thisboard->intr_chk_clr_cb(dev); | |
| 58 | + if (board->intr_chk_clr_cb) | |
| 59 | + retval = board->intr_chk_clr_cb(dev); | |
| 60 | 60 | else |
| 61 | 61 | retval = true; |
| 62 | 62 | } |
| @@ -385,14 +385,14 @@ static void · 384 unmodified lines | ||
| 385 | 385 | pci224_ao_set_data(struct comedi_device *dev, int chan, int range, |
| 386 | 386 | unsigned int data) |
| 387 | 387 | { |
| 388 | − const struct pci224_board *thisboard = dev->board_ptr; | |
| 388 | + const struct pci224_board *board = dev->board_ptr; | |
| 389 | 389 | struct pci224_private *devpriv = dev->private; |
| 390 | 390 | unsigned short mangled; |
| 391 | 391 | |
| 392 | 392 | /* Enable the channel. */ |
| 393 | 393 | outw(1 << chan, dev->iobase + PCI224_DACCEN); |
| 394 | 394 | /* Set range and reset FIFO. */ |
| 395 | − devpriv->daccon = COMBINE(devpriv->daccon, thisboard->ao_hwrange[range], | |
| 395 | + devpriv->daccon = COMBINE(devpriv->daccon, board->ao_hwrange[range], | |
| 396 | 396 | PCI224_DACCON_POLAR_MASK | |
| 397 | 397 | PCI224_DACCON_VREF_MASK); |
| 398 | 398 | outw(devpriv->daccon | PCI224_DACCON_FIFORESET, |
| @@ -402,7 +402,7 @@ pci224_ao_set_data(struct comedi_device *dev, int chan, int range, · 3 unmodified lines | ||
| 402 | 402 | * - bipolar: 16-bit 2's complement |
| 403 | 403 | * - unipolar: 16-bit unsigned |
| 404 | 404 | */ |
| 405 | − mangled = (unsigned short)data << (16 - thisboard->ao_bits); | |
| 405 | + mangled = (unsigned short)data << (16 - board->ao_bits); | |
| 406 | 406 | if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) == |
| 407 | 407 | PCI224_DACCON_POLAR_BI) { |
| 408 | 408 | mangled ^= 0x8000; |
| @@ -620,12 +620,12 @@ static int pci224_ao_check_chanlist(struct comedi_device *dev, · 211 unmodified lines | ||
| 620 | 620 | struct comedi_subdevice *s, |
| 621 | 621 | struct comedi_cmd *cmd) |
| 622 | 622 | { |
| 623 | − const struct pci224_board *thisboard = dev->board_ptr; | |
| 623 | + const struct pci224_board *board = dev->board_ptr; | |
| 624 | 624 | unsigned int range_check_0; |
| 625 | 625 | unsigned int chan_mask = 0; |
| 626 | 626 | int i; |
| 627 | 627 | |
| 628 | − range_check_0 = thisboard->ao_range_check[CR_RANGE(cmd->chanlist[0])]; | |
| 628 | + range_check_0 = board->ao_range_check[CR_RANGE(cmd->chanlist[0])]; | |
| 629 | 629 | for (i = 0; i < cmd->chanlist_len; i++) { |
| 630 | 630 | unsigned int chan = CR_CHAN(cmd->chanlist[i]); |
| 631 | 631 | |
| @@ -637,7 +637,7 @@ static int pci224_ao_check_chanlist(struct comedi_device *dev, · 5 unmodified lines | ||
| 637 | 637 | } |
| 638 | 638 | chan_mask |= 1 << chan; |
| 639 | 639 | |
| 640 | − if (thisboard->ao_range_check[CR_RANGE(cmd->chanlist[i])] != | |
| 640 | + if (board->ao_range_check[CR_RANGE(cmd->chanlist[i])] != | |
| 641 | 641 | range_check_0) { |
| 642 | 642 | dev_dbg(dev->class_dev, |
| 643 | 643 | "%s: entries in chanlist have incompatible ranges\n", |
| @@ -826,7 +826,7 @@ static void pci224_ao_start_pacer(struct comedi_device *dev, · 182 unmodified lines | ||
| 826 | 826 | |
| 827 | 827 | static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
| 828 | 828 | { |
| 829 | − const struct pci224_board *thisboard = dev->board_ptr; | |
| 829 | + const struct pci224_board *board = dev->board_ptr; | |
| 830 | 830 | struct pci224_private *devpriv = dev->private; |
| 831 | 831 | struct comedi_cmd *cmd = &s->async->cmd; |
| 832 | 832 | int range; |
| @@ -869,7 +869,7 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 36 unmodified lines | ||
| 869 | 869 | */ |
| 870 | 870 | devpriv->daccon = |
| 871 | 871 | COMBINE(devpriv->daccon, |
| 872 | − thisboard->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE | | |
| 872 | + board->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE | | |
| 873 | 873 | PCI224_DACCON_FIFOINTR_NHALF, |
| 874 | 874 | PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK | |
| 875 | 875 | PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK); |
| @@ -911,7 +911,7 @@ static void · 35 unmodified lines | ||
| 911 | 911 | pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, |
| 912 | 912 | void *data, unsigned int num_bytes, unsigned int chan_index) |
| 913 | 913 | { |
| 914 | − const struct pci224_board *thisboard = dev->board_ptr; | |
| 914 | + const struct pci224_board *board = dev->board_ptr; | |
| 915 | 915 | struct comedi_cmd *cmd = &s->async->cmd; |
| 916 | 916 | unsigned short *array = data; |
| 917 | 917 | unsigned int length = num_bytes / sizeof(*array); |
| @@ -920,9 +920,9 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, · 2 unmodified lines | ||
| 920 | 920 | unsigned int i; |
| 921 | 921 | |
| 922 | 922 | /* The hardware expects 16-bit numbers. */ |
| 923 | − shift = 16 - thisboard->ao_bits; | |
| 923 | + shift = 16 - board->ao_bits; | |
| 924 | 924 | /* Channels will be all bipolar or all unipolar. */ |
| 925 | − if ((thisboard->ao_hwrange[CR_RANGE(cmd->chanlist[0])] & | |
| 925 | + if ((board->ao_hwrange[CR_RANGE(cmd->chanlist[0])] & | |
| 926 | 926 | PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) { |
| 927 | 927 | /* Unipolar */ |
| 928 | 928 | offset = 0; |
| @@ -988,21 +988,21 @@ static int · 59 unmodified lines | ||
| 988 | 988 | pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) |
| 989 | 989 | { |
| 990 | 990 | struct pci_dev *pci_dev = comedi_to_pci_dev(dev); |
| 991 | − const struct pci224_board *thisboard = NULL; | |
| 991 | + const struct pci224_board *board = NULL; | |
| 992 | 992 | struct pci224_private *devpriv; |
| 993 | 993 | struct comedi_subdevice *s; |
| 994 | 994 | unsigned int irq; |
| 995 | 995 | int ret; |
| 996 | 996 | |
| 997 | 997 | if (context_model < ARRAY_SIZE(pci224_boards)) |
| 998 | − thisboard = &pci224_boards[context_model]; | |
| 999 | − if (!thisboard || !thisboard->name) { | |
| 998 | + board = &pci224_boards[context_model]; | |
| 999 | + if (!board || !board->name) { | |
| 1000 | 1000 | dev_err(dev->class_dev, |
| 1001 | 1001 | "amplc_pci224: BUG! cannot determine board type!\n"); |
| 1002 | 1002 | return -EINVAL; |
| 1003 | 1003 | } |
| 1004 | − dev->board_ptr = thisboard; | |
| 1005 | − dev->board_name = thisboard->name; | |
| 1004 | + dev->board_ptr = board; | |
| 1005 | + dev->board_name = board->name; | |
| 1006 | 1006 | |
| 1007 | 1007 | dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n", |
| 1008 | 1008 | pci_name(pci_dev), dev->board_name); |
| @@ -1023,13 +1023,13 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) · 14 unmodified lines | ||
| 1023 | 1023 | |
| 1024 | 1024 | /* Allocate buffer to hold values for AO channel scan. */ |
| 1025 | 1025 | devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) * |
| 1026 | − thisboard->ao_chans, GFP_KERNEL); | |
| 1026 | + board->ao_chans, GFP_KERNEL); | |
| 1027 | 1027 | if (!devpriv->ao_scan_vals) |
| 1028 | 1028 | return -ENOMEM; |
| 1029 | 1029 | |
| 1030 | 1030 | /* Allocate buffer to hold AO channel scan order. */ |
| 1031 | 1031 | devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) * |
| 1032 | − thisboard->ao_chans, GFP_KERNEL); | |
| 1032 | + board->ao_chans, GFP_KERNEL); | |
| 1033 | 1033 | if (!devpriv->ao_scan_order) |
| 1034 | 1034 | return -ENOMEM; |
| 1035 | 1035 | |
| @@ -1059,9 +1059,9 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) · 23 unmodified lines | ||
| 1059 | 1059 | /* Analog output subdevice. */ |
| 1060 | 1060 | s->type = COMEDI_SUBD_AO; |
| 1061 | 1061 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; |
| 1062 | − s->n_chan = thisboard->ao_chans; | |
| 1063 | − s->maxdata = (1 << thisboard->ao_bits) - 1; | |
| 1064 | − s->range_table = thisboard->ao_range; | |
| 1062 | + s->n_chan = board->ao_chans; | |
| 1063 | + s->maxdata = (1 << board->ao_bits) - 1; | |
| 1064 | + s->range_table = board->ao_range; | |
| 1065 | 1065 | s->insn_write = pci224_ao_insn_write; |
| 1066 | 1066 | s->len_chanlist = s->n_chan; |
| 1067 | 1067 | dev->write_subdev = s; |
| @@ -528,7 +528,7 @@ static const struct comedi_lrange pci230_ao_range = { · 527 unmodified lines | ||
| 528 | 528 | |
| 529 | 529 | static unsigned short pci230_ai_read(struct comedi_device *dev) |
| 530 | 530 | { |
| 531 | − const struct pci230_board *thisboard = dev->board_ptr; | |
| 531 | + const struct pci230_board *board = dev->board_ptr; | |
| 532 | 532 | struct pci230_private *devpriv = dev->private; |
| 533 | 533 | unsigned short data; |
| 534 | 534 | |
| @@ -543,21 +543,21 @@ static unsigned short pci230_ai_read(struct comedi_device *dev) · 8 unmodified lines | ||
| 543 | 543 | */ |
| 544 | 544 | if (devpriv->ai_bipolar) |
| 545 | 545 | data ^= 0x8000; |
| 546 | − data >>= (16 - thisboard->ai_bits); | |
| 546 | + data >>= (16 - board->ai_bits); | |
| 547 | 547 | return data; |
| 548 | 548 | } |
| 549 | 549 | |
| 550 | 550 | static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, |
| 551 | 551 | unsigned short datum) |
| 552 | 552 | { |
| 553 | − const struct pci230_board *thisboard = dev->board_ptr; | |
| 553 | + const struct pci230_board *board = dev->board_ptr; | |
| 554 | 554 | struct pci230_private *devpriv = dev->private; |
| 555 | 555 | |
| 556 | 556 | /* |
| 557 | 557 | * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower |
| 558 | 558 | * four bits reserved for expansion). PCI230+ is also 12 bit AO. |
| 559 | 559 | */ |
| 560 | − datum <<= (16 - thisboard->ao_bits); | |
| 560 | + datum <<= (16 - board->ao_bits); | |
| 561 | 561 | /* |
| 562 | 562 | * If a bipolar range was specified, mangle it |
| 563 | 563 | * (straight binary->twos complement). |
| @@ -877,7 +877,7 @@ static int pci230_ao_check_chanlist(struct comedi_device *dev, · 313 unmodified lines | ||
| 877 | 877 | static int pci230_ao_cmdtest(struct comedi_device *dev, |
| 878 | 878 | struct comedi_subdevice *s, struct comedi_cmd *cmd) |
| 879 | 879 | { |
| 880 | − const struct pci230_board *thisboard = dev->board_ptr; | |
| 880 | + const struct pci230_board *board = dev->board_ptr; | |
| 881 | 881 | struct pci230_private *devpriv = dev->private; |
| 882 | 882 | int err = 0; |
| 883 | 883 | unsigned int tmp; |
| @@ -887,14 +887,14 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, · 3 unmodified lines | ||
| 887 | 887 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT); |
| 888 | 888 | |
| 889 | 889 | tmp = TRIG_TIMER | TRIG_INT; |
| 890 | − if (thisboard->min_hwver > 0 && devpriv->hwver >= 2) { | |
| 890 | + if (board->min_hwver > 0 && devpriv->hwver >= 2) { | |
| 891 | 891 | /* |
| 892 | 892 | * For PCI230+ hardware version 2 onwards, allow external |
| 893 | 893 | * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25). |
| 894 | 894 | * |
| 895 | 895 | * FIXME: The permitted scan_begin_src values shouldn't depend |
| 896 | 896 | * on devpriv->hwver (the detected card's actual hardware |
| 897 | − * version). They should only depend on thisboard->min_hwver | |
| 897 | + * version). They should only depend on board->min_hwver | |
| 898 | 898 | * (the static capabilities of the configured card). To fix |
| 899 | 899 | * it, a new card model, e.g. "pci230+2" would have to be |
| 900 | 900 | * defined with min_hwver set to 2. It doesn't seem worth it |
| @@ -1500,7 +1500,7 @@ static int pci230_ai_check_chanlist(struct comedi_device *dev, · 599 unmodified lines | ||
| 1500 | 1500 | static int pci230_ai_cmdtest(struct comedi_device *dev, |
| 1501 | 1501 | struct comedi_subdevice *s, struct comedi_cmd *cmd) |
| 1502 | 1502 | { |
| 1503 | − const struct pci230_board *thisboard = dev->board_ptr; | |
| 1503 | + const struct pci230_board *board = dev->board_ptr; | |
| 1504 | 1504 | struct pci230_private *devpriv = dev->private; |
| 1505 | 1505 | int err = 0; |
| 1506 | 1506 | unsigned int tmp; |
| @@ -1510,7 +1510,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, · 3 unmodified lines | ||
| 1510 | 1510 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); |
| 1511 | 1511 | |
| 1512 | 1512 | tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT; |
| 1513 | − if (thisboard->have_dio || thisboard->min_hwver > 0) { | |
| 1513 | + if (board->have_dio || board->min_hwver > 0) { | |
| 1514 | 1514 | /* |
| 1515 | 1515 | * Unfortunately, we cannot trigger a scan off an external |
| 1516 | 1516 | * source on the PCI260 board, since it uses the PPIC0 (DIO) |
| @@ -2011,17 +2011,17 @@ static void pci230_handle_ai(struct comedi_device *dev, · 494 unmodified lines | ||
| 2011 | 2011 | struct comedi_cmd *cmd = &async->cmd; |
| 2012 | 2012 | unsigned int status_fifo; |
| 2013 | 2013 | unsigned int i; |
| 2014 | − unsigned int todo; | |
| 2014 | + unsigned int nsamples; | |
| 2015 | 2015 | unsigned int fifoamount; |
| 2016 | 2016 | unsigned short val; |
| 2017 | 2017 | |
| 2018 | 2018 | /* Determine number of samples to read. */ |
| 2019 | − todo = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); | |
| 2020 | − if (todo == 0) | |
| 2019 | + nsamples = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); | |
| 2020 | + if (nsamples == 0) | |
| 2021 | 2021 | return; |
| 2022 | 2022 | |
| 2023 | 2023 | fifoamount = 0; |
| 2024 | − for (i = 0; i < todo; i++) { | |
| 2024 | + for (i = 0; i < nsamples; i++) { | |
| 2025 | 2025 | if (fifoamount == 0) { |
| 2026 | 2026 | /* Read FIFO state. */ |
| 2027 | 2027 | status_fifo = inw(devpriv->daqio + PCI230_ADCCON); |
| @@ -2364,7 +2364,7 @@ static int pci230_auto_attach(struct comedi_device *dev, · 336 unmodified lines | ||
| 2364 | 2364 | unsigned long context_unused) |
| 2365 | 2365 | { |
| 2366 | 2366 | struct pci_dev *pci_dev = comedi_to_pci_dev(dev); |
| 2367 | − const struct pci230_board *thisboard; | |
| 2367 | + const struct pci230_board *board; | |
| 2368 | 2368 | struct pci230_private *devpriv; |
| 2369 | 2369 | struct comedi_subdevice *s; |
| 2370 | 2370 | int rc; |
| @@ -2381,14 +2381,14 @@ static int pci230_auto_attach(struct comedi_device *dev, · 10 unmodified lines | ||
| 2381 | 2381 | spin_lock_init(&devpriv->ai_stop_spinlock); |
| 2382 | 2382 | spin_lock_init(&devpriv->ao_stop_spinlock); |
| 2383 | 2383 | |
| 2384 | − dev->board_ptr = pci230_find_pci_board(pci_dev); | |
| 2385 | − if (!dev->board_ptr) { | |
| 2384 | + board = pci230_find_pci_board(pci_dev); | |
| 2385 | + if (!board) { | |
| 2386 | 2386 | dev_err(dev->class_dev, |
| 2387 | 2387 | "amplc_pci230: BUG! cannot determine board type!\n"); |
| 2388 | 2388 | return -EINVAL; |
| 2389 | 2389 | } |
| 2390 | − thisboard = dev->board_ptr; | |
| 2391 | − dev->board_name = thisboard->name; | |
| 2390 | + dev->board_ptr = board; | |
| 2391 | + dev->board_name = board->name; | |
| 2392 | 2392 | |
| 2393 | 2393 | rc = comedi_pci_enable(dev); |
| 2394 | 2394 | if (rc) |
| @@ -2414,15 +2414,15 @@ static int pci230_auto_attach(struct comedi_device *dev, · 19 unmodified lines | ||
| 2414 | 2414 | unsigned short extfunc = 0; |
| 2415 | 2415 | |
| 2416 | 2416 | devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER); |
| 2417 | − if (devpriv->hwver < thisboard->min_hwver) { | |
| 2417 | + if (devpriv->hwver < board->min_hwver) { | |
| 2418 | 2418 | dev_err(dev->class_dev, |
| 2419 | 2419 | "%s - bad hardware version - got %u, need %u\n", |
| 2420 | 2420 | dev->board_name, devpriv->hwver, |
| 2421 | − thisboard->min_hwver); | |
| 2421 | + board->min_hwver); | |
| 2422 | 2422 | return -EIO; |
| 2423 | 2423 | } |
| 2424 | 2424 | if (devpriv->hwver > 0) { |
| 2425 | − if (!thisboard->have_dio) { | |
| 2425 | + if (!board->have_dio) { | |
| 2426 | 2426 | /* |
| 2427 | 2427 | * No DIO ports. Route counters' external gates |
| 2428 | 2428 | * to the EXTTRIG signal (PCI260+ pin 17). |
| @@ -2432,7 +2432,7 @@ static int pci230_auto_attach(struct comedi_device *dev, · 3 unmodified lines | ||
| 2432 | 2432 | */ |
| 2433 | 2433 | extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; |
| 2434 | 2434 | } |
| 2435 | − if (thisboard->ao_bits && devpriv->hwver >= 2) { | |
| 2435 | + if (board->ao_bits && devpriv->hwver >= 2) { | |
| 2436 | 2436 | /* Enable DAC FIFO functionality. */ |
| 2437 | 2437 | extfunc |= PCI230P2_EXTFUNC_DACFIFO; |
| 2438 | 2438 | } |
| @@ -2484,7 +2484,7 @@ static int pci230_auto_attach(struct comedi_device *dev, · 45 unmodified lines | ||
| 2484 | 2484 | s->type = COMEDI_SUBD_AI; |
| 2485 | 2485 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; |
| 2486 | 2486 | s->n_chan = 16; |
| 2487 | − s->maxdata = (1 << thisboard->ai_bits) - 1; | |
| 2487 | + s->maxdata = (1 << board->ai_bits) - 1; | |
| 2488 | 2488 | s->range_table = &pci230_ai_range; |
| 2489 | 2489 | s->insn_read = pci230_ai_insn_read; |
| 2490 | 2490 | s->len_chanlist = 256; /* but there are restrictions. */ |
| @@ -2498,11 +2498,11 @@ static int pci230_auto_attach(struct comedi_device *dev, · 7 unmodified lines | ||
| 2498 | 2498 | |
| 2499 | 2499 | s = &dev->subdevices[1]; |
| 2500 | 2500 | /* analog output subdevice */ |
| 2501 | − if (thisboard->ao_bits) { | |
| 2501 | + if (board->ao_bits) { | |
| 2502 | 2502 | s->type = COMEDI_SUBD_AO; |
| 2503 | 2503 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND; |
| 2504 | 2504 | s->n_chan = 2; |
| 2505 | − s->maxdata = (1 << thisboard->ao_bits) - 1; | |
| 2505 | + s->maxdata = (1 << board->ao_bits) - 1; | |
| 2506 | 2506 | s->range_table = &pci230_ao_range; |
| 2507 | 2507 | s->insn_write = pci230_ao_insn_write; |
| 2508 | 2508 | s->len_chanlist = 2; |
| @@ -2523,7 +2523,7 @@ static int pci230_auto_attach(struct comedi_device *dev, · 14 unmodified lines | ||
| 2523 | 2523 | |
| 2524 | 2524 | s = &dev->subdevices[2]; |
| 2525 | 2525 | /* digital i/o subdevice */ |
| 2526 | − if (thisboard->have_dio) { | |
| 2526 | + if (board->have_dio) { | |
| 2527 | 2527 | rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE); |
| 2528 | 2528 | if (rc) |
| 2529 | 2529 | return rc; |
| @@ -705,9 +705,9 @@ static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, · 704 unmodified lines | ||
| 705 | 705 | static void cb_pcidas_trimpot_write(struct comedi_device *dev, |
| 706 | 706 | unsigned int chan, unsigned int val) |
| 707 | 707 | { |
| 708 | − const struct cb_pcidas_board *thisboard = dev->board_ptr; | |
| 708 | + const struct cb_pcidas_board *board = dev->board_ptr; | |
| 709 | 709 | |
| 710 | − switch (thisboard->trimpot) { | |
| 710 | + switch (board->trimpot) { | |
| 711 | 711 | case AD7376: |
| 712 | 712 | trimpot_7376_write(dev, val); |
| 713 | 713 | break; |
| @@ -770,7 +770,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, · 56 unmodified lines | ||
| 770 | 770 | struct comedi_subdevice *s, |
| 771 | 771 | struct comedi_cmd *cmd) |
| 772 | 772 | { |
| 773 | − const struct cb_pcidas_board *thisboard = dev->board_ptr; | |
| 773 | + const struct cb_pcidas_board *board = dev->board_ptr; | |
| 774 | 774 | int err = 0; |
| 775 | 775 | unsigned int arg; |
| 776 | 776 | |
| @@ -821,7 +821,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, · 44 unmodified lines | ||
| 821 | 821 | ~(CR_EDGE | CR_INVERT)); |
| 822 | 822 | err |= -EINVAL; |
| 823 | 823 | } |
| 824 | − if (!thisboard->is_1602 && (cmd->start_arg & CR_INVERT)) { | |
| 824 | + if (!board->is_1602 && (cmd->start_arg & CR_INVERT)) { | |
| 825 | 825 | cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT); |
| 826 | 826 | err |= -EINVAL; |
| 827 | 827 | } |
| @@ -830,13 +830,13 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, · 2 unmodified lines | ||
| 830 | 830 | |
| 831 | 831 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 832 | 832 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 833 | − thisboard->ai_speed * | |
| 833 | + board->ai_speed * | |
| 834 | 834 | cmd->chanlist_len); |
| 835 | 835 | } |
| 836 | 836 | |
| 837 | 837 | if (cmd->convert_src == TRIG_TIMER) { |
| 838 | 838 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 839 | − thisboard->ai_speed); | |
| 839 | + board->ai_speed); | |
| 840 | 840 | } |
| 841 | 841 | |
| 842 | 842 | err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, |
| @@ -879,7 +879,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, · 36 unmodified lines | ||
| 879 | 879 | static int cb_pcidas_ai_cmd(struct comedi_device *dev, |
| 880 | 880 | struct comedi_subdevice *s) |
| 881 | 881 | { |
| 882 | − const struct cb_pcidas_board *thisboard = dev->board_ptr; | |
| 882 | + const struct cb_pcidas_board *board = dev->board_ptr; | |
| 883 | 883 | struct cb_pcidas_private *devpriv = dev->private; |
| 884 | 884 | struct comedi_async *async = s->async; |
| 885 | 885 | struct comedi_cmd *cmd = &async->cmd; |
| @@ -945,7 +945,7 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, · 59 unmodified lines | ||
| 945 | 945 | bits |= SW_TRIGGER; |
| 946 | 946 | } else { /* TRIG_EXT */ |
| 947 | 947 | bits |= EXT_TRIGGER | TGEN | XTRCL; |
| 948 | − if (thisboard->is_1602) { | |
| 948 | + if (board->is_1602) { | |
| 949 | 949 | if (cmd->start_arg & CR_INVERT) |
| 950 | 950 | bits |= TGPOL; |
| 951 | 951 | if (cmd->start_arg & CR_EDGE) |
| @@ -982,7 +982,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, · 30 unmodified lines | ||
| 982 | 982 | struct comedi_subdevice *s, |
| 983 | 983 | struct comedi_cmd *cmd) |
| 984 | 984 | { |
| 985 | − const struct cb_pcidas_board *thisboard = dev->board_ptr; | |
| 985 | + const struct cb_pcidas_board *board = dev->board_ptr; | |
| 986 | 986 | struct cb_pcidas_private *devpriv = dev->private; |
| 987 | 987 | int err = 0; |
| 988 | 988 | |
| @@ -1014,7 +1014,7 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev, · 25 unmodified lines | ||
| 1014 | 1014 | |
| 1015 | 1015 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 1016 | 1016 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 1017 | − thisboard->ao_scan_speed); | |
| 1017 | + board->ao_scan_speed); | |
| 1018 | 1018 | } |
| 1019 | 1019 | |
| 1020 | 1020 | err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, |
| @@ -1090,7 +1090,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, · 69 unmodified lines | ||
| 1090 | 1090 | struct comedi_subdevice *s, |
| 1091 | 1091 | unsigned int trig_num) |
| 1092 | 1092 | { |
| 1093 | − const struct cb_pcidas_board *thisboard = dev->board_ptr; | |
| 1093 | + const struct cb_pcidas_board *board = dev->board_ptr; | |
| 1094 | 1094 | struct cb_pcidas_private *devpriv = dev->private; |
| 1095 | 1095 | struct comedi_async *async = s->async; |
| 1096 | 1096 | struct comedi_cmd *cmd = &async->cmd; |
| @@ -1099,7 +1099,7 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev, · 2 unmodified lines | ||
| 1099 | 1099 | if (trig_num != cmd->start_arg) |
| 1100 | 1100 | return -EINVAL; |
| 1101 | 1101 | |
| 1102 | − cb_pcidas_ao_load_fifo(dev, s, thisboard->fifo_size); | |
| 1102 | + cb_pcidas_ao_load_fifo(dev, s, board->fifo_size); | |
| 1103 | 1103 | |
| 1104 | 1104 | /* enable dac half-full and empty interrupts */ |
| 1105 | 1105 | spin_lock_irqsave(&dev->spinlock, flags); |
| @@ -1197,7 +1197,7 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev, · 91 unmodified lines | ||
| 1197 | 1197 | |
| 1198 | 1198 | static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) |
| 1199 | 1199 | { |
| 1200 | − const struct cb_pcidas_board *thisboard = dev->board_ptr; | |
| 1200 | + const struct cb_pcidas_board *board = dev->board_ptr; | |
| 1201 | 1201 | struct cb_pcidas_private *devpriv = dev->private; |
| 1202 | 1202 | struct comedi_subdevice *s = dev->write_subdev; |
| 1203 | 1203 | struct comedi_async *async = s->async; |
| @@ -1220,7 +1220,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) · 16 unmodified lines | ||
| 1220 | 1220 | } |
| 1221 | 1221 | } |
| 1222 | 1222 | } else if (status & DAHFI) { |
| 1223 | − cb_pcidas_ao_load_fifo(dev, s, thisboard->fifo_size / 2); | |
| 1223 | + cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2); | |
| 1224 | 1224 | |
| 1225 | 1225 | /* clear half-full interrupt latch */ |
| 1226 | 1226 | spin_lock_irqsave(&dev->spinlock, flags); |
| @@ -1235,13 +1235,13 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) · 8 unmodified lines | ||
| 1235 | 1235 | static irqreturn_t cb_pcidas_interrupt(int irq, void *d) |
| 1236 | 1236 | { |
| 1237 | 1237 | struct comedi_device *dev = (struct comedi_device *)d; |
| 1238 | − const struct cb_pcidas_board *thisboard = dev->board_ptr; | |
| 1238 | + const struct cb_pcidas_board *board = dev->board_ptr; | |
| 1239 | 1239 | struct cb_pcidas_private *devpriv = dev->private; |
| 1240 | 1240 | struct comedi_subdevice *s = dev->read_subdev; |
| 1241 | 1241 | struct comedi_async *async; |
| 1242 | 1242 | struct comedi_cmd *cmd; |
| 1243 | 1243 | int status, s5933_status; |
| 1244 | − int half_fifo = thisboard->fifo_size / 2; | |
| 1244 | + int half_fifo = board->fifo_size / 2; | |
| 1245 | 1245 | unsigned int num_samples, i; |
| 1246 | 1246 | static const int timeout = 10000; |
| 1247 | 1247 | unsigned long flags; |
| @@ -1338,18 +1338,18 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 90 unmodified lines | ||
| 1338 | 1338 | unsigned long context) |
| 1339 | 1339 | { |
| 1340 | 1340 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 1341 | − const struct cb_pcidas_board *thisboard = NULL; | |
| 1341 | + const struct cb_pcidas_board *board = NULL; | |
| 1342 | 1342 | struct cb_pcidas_private *devpriv; |
| 1343 | 1343 | struct comedi_subdevice *s; |
| 1344 | 1344 | int i; |
| 1345 | 1345 | int ret; |
| 1346 | 1346 | |
| 1347 | 1347 | if (context < ARRAY_SIZE(cb_pcidas_boards)) |
| 1348 | − thisboard = &cb_pcidas_boards[context]; | |
| 1349 | − if (!thisboard) | |
| 1348 | + board = &cb_pcidas_boards[context]; | |
| 1349 | + if (!board) | |
| 1350 | 1350 | return -ENODEV; |
| 1351 | − dev->board_ptr = thisboard; | |
| 1352 | − dev->board_name = thisboard->name; | |
| 1351 | + dev->board_ptr = board; | |
| 1352 | + dev->board_name = board->name; | |
| 1353 | 1353 | |
| 1354 | 1354 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 1355 | 1355 | if (!devpriv) |
| @@ -1363,7 +1363,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 7 unmodified lines | ||
| 1363 | 1363 | devpriv->control_status = pci_resource_start(pcidev, 1); |
| 1364 | 1364 | devpriv->adc_fifo = pci_resource_start(pcidev, 2); |
| 1365 | 1365 | dev->iobase = pci_resource_start(pcidev, 3); |
| 1366 | − if (thisboard->ao_nchan) | |
| 1366 | + if (board->ao_nchan) | |
| 1367 | 1367 | devpriv->ao_registers = pci_resource_start(pcidev, 4); |
| 1368 | 1368 | |
| 1369 | 1369 | /* disable and clear interrupts on amcc s5933 */ |
| @@ -1400,10 +1400,10 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 30 unmodified lines | ||
| 1400 | 1400 | s->type = COMEDI_SUBD_AI; |
| 1401 | 1401 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; |
| 1402 | 1402 | /* WARNING: Number of inputs in differential mode is ignored */ |
| 1403 | − s->n_chan = thisboard->ai_nchan; | |
| 1404 | − s->len_chanlist = thisboard->ai_nchan; | |
| 1405 | − s->maxdata = (1 << thisboard->ai_bits) - 1; | |
| 1406 | − s->range_table = thisboard->ranges; | |
| 1403 | + s->n_chan = board->ai_nchan; | |
| 1404 | + s->len_chanlist = board->ai_nchan; | |
| 1405 | + s->maxdata = (1 << board->ai_bits) - 1; | |
| 1406 | + s->range_table = board->ranges; | |
| 1407 | 1407 | s->insn_read = cb_pcidas_ai_rinsn; |
| 1408 | 1408 | s->insn_config = ai_config_insn; |
| 1409 | 1409 | s->do_cmd = cb_pcidas_ai_cmd; |
| @@ -1412,15 +1412,15 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 2 unmodified lines | ||
| 1412 | 1412 | |
| 1413 | 1413 | /* analog output subdevice */ |
| 1414 | 1414 | s = &dev->subdevices[1]; |
| 1415 | − if (thisboard->ao_nchan) { | |
| 1415 | + if (board->ao_nchan) { | |
| 1416 | 1416 | s->type = COMEDI_SUBD_AO; |
| 1417 | 1417 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; |
| 1418 | − s->n_chan = thisboard->ao_nchan; | |
| 1418 | + s->n_chan = board->ao_nchan; | |
| 1419 | 1419 | /* |
| 1420 | 1420 | * analog out resolution is the same as |
| 1421 | 1421 | * analog input resolution, so use ai_bits |
| 1422 | 1422 | */ |
| 1423 | − s->maxdata = (1 << thisboard->ai_bits) - 1; | |
| 1423 | + s->maxdata = (1 << board->ai_bits) - 1; | |
| 1424 | 1424 | s->range_table = &cb_pcidas_ao_ranges; |
| 1425 | 1425 | /* default to no fifo (*insn_write) */ |
| 1426 | 1426 | s->insn_write = cb_pcidas_ao_nofifo_winsn; |
| @@ -1429,7 +1429,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 2 unmodified lines | ||
| 1429 | 1429 | if (ret) |
| 1430 | 1430 | return ret; |
| 1431 | 1431 | |
| 1432 | − if (thisboard->has_ao_fifo) { | |
| 1432 | + if (board->has_ao_fifo) { | |
| 1433 | 1433 | dev->write_subdev = s; |
| 1434 | 1434 | s->subdev_flags |= SDF_CMD_WRITE; |
| 1435 | 1435 | /* use fifo (*insn_write) instead */ |
| @@ -1477,7 +1477,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 41 unmodified lines | ||
| 1477 | 1477 | s = &dev->subdevices[5]; |
| 1478 | 1478 | s->type = COMEDI_SUBD_CALIB; |
| 1479 | 1479 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 1480 | − if (thisboard->trimpot == AD7376) { | |
| 1480 | + if (board->trimpot == AD7376) { | |
| 1481 | 1481 | s->n_chan = NUM_CHANNELS_7376; |
| 1482 | 1482 | s->maxdata = 0x7f; |
| 1483 | 1483 | } else { |
| @@ -1497,7 +1497,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 13 unmodified lines | ||
| 1497 | 1497 | |
| 1498 | 1498 | /* dac08 caldac */ |
| 1499 | 1499 | s = &dev->subdevices[6]; |
| 1500 | − if (thisboard->has_dac08) { | |
| 1500 | + if (board->has_dac08) { | |
| 1501 | 1501 | s->type = COMEDI_SUBD_CALIB; |
| 1502 | 1502 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 1503 | 1503 | s->n_chan = NUM_CHANNELS_DAC08; |
| @@ -155,8 +155,10 @@ static inline unsigned int dac_msb_4020_reg(unsigned int channel) · 154 unmodified lines | ||
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 157 | enum read_only_registers { |
| 158 | − /* hardware status register, | |
| 159 | − * reading this apparently clears pending interrupts as well */ | |
| 158 | + /* | |
| 159 | + * hardware status register, | |
| 160 | + * reading this apparently clears pending interrupts as well | |
| 161 | + */ | |
| 160 | 162 | HW_STATUS_REG = 0x0, |
| 161 | 163 | PIPE1_READ_REG = 0x4, |
| 162 | 164 | ADC_READ_PNTR_REG = 0x8, |
| @@ -243,7 +245,8 @@ enum adc_control0_contents { · 80 unmodified lines | ||
| 243 | 245 | ADC_SOFT_GATE_BITS = 0x1, /* software gate */ |
| 244 | 246 | ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ |
| 245 | 247 | ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ |
| 246 | − ADC_GATE_LEVEL_BIT = 0x4, /* level-sensitive gate (for digital) */ | |
| 248 | + /* level-sensitive gate (for digital) */ | |
| 249 | + ADC_GATE_LEVEL_BIT = 0x4, | |
| 247 | 250 | ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ |
| 248 | 251 | ADC_START_TRIG_SOFT_BITS = 0x10, |
| 249 | 252 | ADC_START_TRIG_EXT_BITS = 0x20, |
| @@ -300,7 +303,8 @@ enum calibration_contents { · 50 unmodified lines | ||
| 300 | 303 | CAL_GAIN_BIT = 0x800, |
| 301 | 304 | }; |
| 302 | 305 | |
| 303 | −/* calibration sources for 6025 are: | |
| 306 | +/* | |
| 307 | + * calibration sources for 6025 are: | |
| 304 | 308 | * 0 : ground |
| 305 | 309 | * 1 : 10V |
| 306 | 310 | * 2 : 5V |
| @@ -660,8 +664,10 @@ static const struct hw_fifo_info ai_fifo_60xx = { · 353 unmodified lines | ||
| 660 | 664 | .fifo_size_reg_mask = 0x7f, |
| 661 | 665 | }; |
| 662 | 666 | |
| 663 | −/* maximum number of dma transfers we will chain together into a ring | |
| 664 | − * (and the maximum number of dma buffers we maintain) */ | |
| 667 | +/* | |
| 668 | + * maximum number of dma transfers we will chain together into a ring | |
| 669 | + * (and the maximum number of dma buffers we maintain) | |
| 670 | + */ | |
| 665 | 671 | #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE) |
| 666 | 672 | #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) |
| 667 | 673 | #define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) |
| @@ -1100,10 +1106,10 @@ static const struct pcidas64_board pcidas64_boards[] = { · 432 unmodified lines | ||
| 1100 | 1106 | static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, |
| 1101 | 1107 | int use_differential) |
| 1102 | 1108 | { |
| 1103 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1109 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1104 | 1110 | |
| 1105 | − if ((thisboard->layout == LAYOUT_64XX && !use_differential) || | |
| 1106 | − (thisboard->layout == LAYOUT_60XX && use_differential)) | |
| 1111 | + if ((board->layout == LAYOUT_64XX && !use_differential) || | |
| 1112 | + (board->layout == LAYOUT_60XX && use_differential)) | |
| 1107 | 1113 | return ADC_SE_DIFF_BIT; |
| 1108 | 1114 | |
| 1109 | 1115 | return 0; |
| @@ -1176,17 +1182,17 @@ struct pcidas64_private { · 66 unmodified lines | ||
| 1176 | 1182 | static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, |
| 1177 | 1183 | unsigned int range_index) |
| 1178 | 1184 | { |
| 1179 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1185 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1180 | 1186 | |
| 1181 | − return thisboard->ai_range_code[range_index] << 8; | |
| 1187 | + return board->ai_range_code[range_index] << 8; | |
| 1182 | 1188 | } |
| 1183 | 1189 | |
| 1184 | 1190 | static unsigned int hw_revision(const struct comedi_device *dev, |
| 1185 | 1191 | uint16_t hw_status_bits) |
| 1186 | 1192 | { |
| 1187 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1193 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1188 | 1194 | |
| 1189 | − if (thisboard->layout == LAYOUT_4020) | |
| 1195 | + if (board->layout == LAYOUT_4020) | |
| 1190 | 1196 | return (hw_status_bits >> 13) & 0x7; |
| 1191 | 1197 | |
| 1192 | 1198 | return (hw_status_bits >> 12) & 0xf; |
| @@ -1196,8 +1202,8 @@ static void set_dac_range_bits(struct comedi_device *dev, · 3 unmodified lines | ||
| 1196 | 1202 | uint16_t *bits, unsigned int channel, |
| 1197 | 1203 | unsigned int range) |
| 1198 | 1204 | { |
| 1199 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1200 | − unsigned int code = thisboard->ao_range_code[range]; | |
| 1205 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1206 | + unsigned int code = board->ao_range_code[range]; | |
| 1201 | 1207 | |
| 1202 | 1208 | if (channel > 1) |
| 1203 | 1209 | dev_err(dev->class_dev, "bug! bad channel?\n"); |
| @@ -1253,18 +1259,20 @@ static void disable_ai_interrupts(struct comedi_device *dev) · 49 unmodified lines | ||
| 1253 | 1259 | static void enable_ai_interrupts(struct comedi_device *dev, |
| 1254 | 1260 | const struct comedi_cmd *cmd) |
| 1255 | 1261 | { |
| 1256 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1262 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1257 | 1263 | struct pcidas64_private *devpriv = dev->private; |
| 1258 | 1264 | uint32_t bits; |
| 1259 | 1265 | unsigned long flags; |
| 1260 | 1266 | |
| 1261 | 1267 | bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT | |
| 1262 | 1268 | EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT; |
| 1263 | − /* Use pio transfer and interrupt on end of conversion | |
| 1264 | − * if CMDF_WAKE_EOS flag is set. */ | |
| 1269 | + /* | |
| 1270 | + * Use pio transfer and interrupt on end of conversion | |
| 1271 | + * if CMDF_WAKE_EOS flag is set. | |
| 1272 | + */ | |
| 1265 | 1273 | if (cmd->flags & CMDF_WAKE_EOS) { |
| 1266 | 1274 | /* 4020 doesn't support pio transfers except for fifo dregs */ |
| 1267 | − if (thisboard->layout != LAYOUT_4020) | |
| 1275 | + if (board->layout != LAYOUT_4020) | |
| 1268 | 1276 | bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; |
| 1269 | 1277 | } |
| 1270 | 1278 | spin_lock_irqsave(&dev->spinlock, flags); |
| @@ -1277,7 +1285,7 @@ static void enable_ai_interrupts(struct comedi_device *dev, · 6 unmodified lines | ||
| 1277 | 1285 | /* initialize plx9080 chip */ |
| 1278 | 1286 | static void init_plx9080(struct comedi_device *dev) |
| 1279 | 1287 | { |
| 1280 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1288 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1281 | 1289 | struct pcidas64_private *devpriv = dev->private; |
| 1282 | 1290 | uint32_t bits; |
| 1283 | 1291 | void __iomem *plx_iobase = devpriv->plx9080_iobase; |
| @@ -1318,12 +1326,12 @@ static void init_plx9080(struct comedi_device *dev) · 34 unmodified lines | ||
| 1318 | 1326 | /* enable local burst mode */ |
| 1319 | 1327 | bits |= PLX_DMA_LOCAL_BURST_EN_BIT; |
| 1320 | 1328 | /* 4020 uses 32 bit dma */ |
| 1321 | − if (thisboard->layout == LAYOUT_4020) | |
| 1329 | + if (board->layout == LAYOUT_4020) | |
| 1322 | 1330 | bits |= PLX_LOCAL_BUS_32_WIDE_BITS; |
| 1323 | 1331 | else /* localspace0 bus is 16 bits wide */ |
| 1324 | 1332 | bits |= PLX_LOCAL_BUS_16_WIDE_BITS; |
| 1325 | 1333 | writel(bits, plx_iobase + PLX_DMA1_MODE_REG); |
| 1326 | − if (ao_cmd_is_supported(thisboard)) | |
| 1334 | + if (ao_cmd_is_supported(board)) | |
| 1327 | 1335 | writel(bits, plx_iobase + PLX_DMA0_MODE_REG); |
| 1328 | 1336 | |
| 1329 | 1337 | /* enable interrupts on plx 9080 */ |
| @@ -1355,10 +1363,10 @@ static void disable_ai_pacing(struct comedi_device *dev) · 25 unmodified lines | ||
| 1355 | 1363 | static int set_ai_fifo_segment_length(struct comedi_device *dev, |
| 1356 | 1364 | unsigned int num_entries) |
| 1357 | 1365 | { |
| 1358 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1366 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1359 | 1367 | struct pcidas64_private *devpriv = dev->private; |
| 1360 | 1368 | static const int increment_size = 0x100; |
| 1361 | − const struct hw_fifo_info *const fifo = thisboard->ai_fifo; | |
| 1369 | + const struct hw_fifo_info *const fifo = board->ai_fifo; | |
| 1362 | 1370 | unsigned int num_increments; |
| 1363 | 1371 | uint16_t bits; |
| 1364 | 1372 | |
| @@ -1381,13 +1389,15 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev, · 16 unmodified lines | ||
| 1381 | 1389 | return devpriv->ai_fifo_segment_length; |
| 1382 | 1390 | } |
| 1383 | 1391 | |
| 1384 | −/* adjusts the size of hardware fifo (which determines block size for dma xfers) */ | |
| 1392 | +/* | |
| 1393 | + * adjusts the size of hardware fifo (which determines block size for dma xfers) | |
| 1394 | + */ | |
| 1385 | 1395 | static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) |
| 1386 | 1396 | { |
| 1387 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1397 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1388 | 1398 | unsigned int num_fifo_entries; |
| 1389 | 1399 | int retval; |
| 1390 | − const struct hw_fifo_info *const fifo = thisboard->ai_fifo; | |
| 1400 | + const struct hw_fifo_info *const fifo = board->ai_fifo; | |
| 1391 | 1401 | |
| 1392 | 1402 | num_fifo_entries = num_samples / fifo->sample_packing_ratio; |
| 1393 | 1403 | |
| @@ -1405,25 +1415,27 @@ static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) · 11 unmodified lines | ||
| 1405 | 1415 | /* query length of fifo */ |
| 1406 | 1416 | static unsigned int ai_fifo_size(struct comedi_device *dev) |
| 1407 | 1417 | { |
| 1408 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1418 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1409 | 1419 | struct pcidas64_private *devpriv = dev->private; |
| 1410 | 1420 | |
| 1411 | 1421 | return devpriv->ai_fifo_segment_length * |
| 1412 | − thisboard->ai_fifo->num_segments * | |
| 1413 | − thisboard->ai_fifo->sample_packing_ratio; | |
| 1422 | + board->ai_fifo->num_segments * | |
| 1423 | + board->ai_fifo->sample_packing_ratio; | |
| 1414 | 1424 | } |
| 1415 | 1425 | |
| 1416 | 1426 | static void init_stc_registers(struct comedi_device *dev) |
| 1417 | 1427 | { |
| 1418 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1428 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1419 | 1429 | struct pcidas64_private *devpriv = dev->private; |
| 1420 | 1430 | uint16_t bits; |
| 1421 | 1431 | unsigned long flags; |
| 1422 | 1432 | |
| 1423 | 1433 | spin_lock_irqsave(&dev->spinlock, flags); |
| 1424 | 1434 | |
| 1425 | − /* bit should be set for 6025, | |
| 1426 | − * although docs say boards with <= 16 chans should be cleared XXX */ | |
| 1435 | + /* | |
| 1436 | + * bit should be set for 6025, | |
| 1437 | + * although docs say boards with <= 16 chans should be cleared XXX | |
| 1438 | + */ | |
| 1427 | 1439 | if (1) |
| 1428 | 1440 | devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT; |
| 1429 | 1441 | writew(devpriv->adc_control1_bits, |
| @@ -1433,7 +1445,7 @@ static void init_stc_registers(struct comedi_device *dev) · 3 unmodified lines | ||
| 1433 | 1445 | writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); |
| 1434 | 1446 | |
| 1435 | 1447 | bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; |
| 1436 | − if (thisboard->layout == LAYOUT_4020) | |
| 1448 | + if (board->layout == LAYOUT_4020) | |
| 1437 | 1449 | bits |= INTERNAL_CLOCK_4020_BITS; |
| 1438 | 1450 | devpriv->hw_config_bits |= bits; |
| 1439 | 1451 | writew(devpriv->hw_config_bits, |
| @@ -1446,8 +1458,7 @@ static void init_stc_registers(struct comedi_device *dev) · 6 unmodified lines | ||
| 1446 | 1458 | |
| 1447 | 1459 | /* set fifos to maximum size */ |
| 1448 | 1460 | devpriv->fifo_size_bits |= DAC_FIFO_BITS; |
| 1449 | − set_ai_fifo_segment_length(dev, | |
| 1450 | − thisboard->ai_fifo->max_segment_length); | |
| 1461 | + set_ai_fifo_segment_length(dev, board->ai_fifo->max_segment_length); | |
| 1451 | 1462 | |
| 1452 | 1463 | devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT; |
| 1453 | 1464 | devpriv->intr_enable_bits = |
| @@ -1461,13 +1472,13 @@ static void init_stc_registers(struct comedi_device *dev) · 7 unmodified lines | ||
| 1461 | 1472 | |
| 1462 | 1473 | static int alloc_and_init_dma_members(struct comedi_device *dev) |
| 1463 | 1474 | { |
| 1464 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1475 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1465 | 1476 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 1466 | 1477 | struct pcidas64_private *devpriv = dev->private; |
| 1467 | 1478 | int i; |
| 1468 | 1479 | |
| 1469 | 1480 | /* allocate pci dma buffers */ |
| 1470 | − for (i = 0; i < ai_dma_ring_count(thisboard); i++) { | |
| 1481 | + for (i = 0; i < ai_dma_ring_count(board); i++) { | |
| 1471 | 1482 | devpriv->ai_buffer[i] = |
| 1472 | 1483 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, |
| 1473 | 1484 | &devpriv->ai_buffer_bus_addr[i]); |
| @@ -1475,7 +1486,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) · 1 unmodified line | ||
| 1475 | 1486 | return -ENOMEM; |
| 1476 | 1487 | } |
| 1477 | 1488 | for (i = 0; i < AO_DMA_RING_COUNT; i++) { |
| 1478 | − if (ao_cmd_is_supported(thisboard)) { | |
| 1489 | + if (ao_cmd_is_supported(board)) { | |
| 1479 | 1490 | devpriv->ao_buffer[i] = |
| 1480 | 1491 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, |
| 1481 | 1492 | &devpriv-> |
| @@ -1487,12 +1498,12 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) · 5 unmodified lines | ||
| 1487 | 1498 | /* allocate dma descriptors */ |
| 1488 | 1499 | devpriv->ai_dma_desc = |
| 1489 | 1500 | pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * |
| 1490 | − ai_dma_ring_count(thisboard), | |
| 1501 | + ai_dma_ring_count(board), | |
| 1491 | 1502 | &devpriv->ai_dma_desc_bus_addr); |
| 1492 | 1503 | if (!devpriv->ai_dma_desc) |
| 1493 | 1504 | return -ENOMEM; |
| 1494 | 1505 | |
| 1495 | − if (ao_cmd_is_supported(thisboard)) { | |
| 1506 | + if (ao_cmd_is_supported(board)) { | |
| 1496 | 1507 | devpriv->ao_dma_desc = |
| 1497 | 1508 | pci_alloc_consistent(pcidev, |
| 1498 | 1509 | sizeof(struct plx_dma_desc) * |
| @@ -1502,10 +1513,10 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) · 3 unmodified lines | ||
| 1502 | 1513 | return -ENOMEM; |
| 1503 | 1514 | } |
| 1504 | 1515 | /* initialize dma descriptors */ |
| 1505 | − for (i = 0; i < ai_dma_ring_count(thisboard); i++) { | |
| 1516 | + for (i = 0; i < ai_dma_ring_count(board); i++) { | |
| 1506 | 1517 | devpriv->ai_dma_desc[i].pci_start_addr = |
| 1507 | 1518 | cpu_to_le32(devpriv->ai_buffer_bus_addr[i]); |
| 1508 | − if (thisboard->layout == LAYOUT_4020) | |
| 1519 | + if (board->layout == LAYOUT_4020) | |
| 1509 | 1520 | devpriv->ai_dma_desc[i].local_start_addr = |
| 1510 | 1521 | cpu_to_le32(devpriv->local1_iobase + |
| 1511 | 1522 | ADC_FIFO_REG); |
| @@ -1516,12 +1527,12 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) · 4 unmodified lines | ||
| 1516 | 1527 | devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(0); |
| 1517 | 1528 | devpriv->ai_dma_desc[i].next = |
| 1518 | 1529 | cpu_to_le32((devpriv->ai_dma_desc_bus_addr + |
| 1519 | − ((i + 1) % ai_dma_ring_count(thisboard)) * | |
| 1530 | + ((i + 1) % ai_dma_ring_count(board)) * | |
| 1520 | 1531 | sizeof(devpriv->ai_dma_desc[0])) | |
| 1521 | 1532 | PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | |
| 1522 | 1533 | PLX_XFER_LOCAL_TO_PCI); |
| 1523 | 1534 | } |
| 1524 | − if (ao_cmd_is_supported(thisboard)) { | |
| 1535 | + if (ao_cmd_is_supported(board)) { | |
| 1525 | 1536 | for (i = 0; i < AO_DMA_RING_COUNT; i++) { |
| 1526 | 1537 | devpriv->ao_dma_desc[i].pci_start_addr = |
| 1527 | 1538 | cpu_to_le32(devpriv->ao_buffer_bus_addr[i]); |
| @@ -1542,7 +1553,7 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) · 14 unmodified lines | ||
| 1542 | 1553 | |
| 1543 | 1554 | static void cb_pcidas64_free_dma(struct comedi_device *dev) |
| 1544 | 1555 | { |
| 1545 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1556 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1546 | 1557 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 1547 | 1558 | struct pcidas64_private *devpriv = dev->private; |
| 1548 | 1559 | int i; |
| @@ -1551,7 +1562,7 @@ static void cb_pcidas64_free_dma(struct comedi_device *dev) · 2 unmodified lines | ||
| 1551 | 1562 | return; |
| 1552 | 1563 | |
| 1553 | 1564 | /* free pci dma buffers */ |
| 1554 | − for (i = 0; i < ai_dma_ring_count(thisboard); i++) { | |
| 1565 | + for (i = 0; i < ai_dma_ring_count(board); i++) { | |
| 1555 | 1566 | if (devpriv->ai_buffer[i]) |
| 1556 | 1567 | pci_free_consistent(pcidev, |
| 1557 | 1568 | DMA_BUFFER_SIZE, |
| @@ -1569,7 +1580,7 @@ static void cb_pcidas64_free_dma(struct comedi_device *dev) · 11 unmodified lines | ||
| 1569 | 1580 | if (devpriv->ai_dma_desc) |
| 1570 | 1581 | pci_free_consistent(pcidev, |
| 1571 | 1582 | sizeof(struct plx_dma_desc) * |
| 1572 | − ai_dma_ring_count(thisboard), | |
| 1583 | + ai_dma_ring_count(board), | |
| 1573 | 1584 | devpriv->ai_dma_desc, |
| 1574 | 1585 | devpriv->ai_dma_desc_bus_addr); |
| 1575 | 1586 | if (devpriv->ao_dma_desc) |
| @@ -1588,7 +1599,9 @@ static inline void warn_external_queue(struct comedi_device *dev) · 12 unmodified lines | ||
| 1588 | 1599 | "Use internal AI channel queue (channels must be consecutive and use same range/aref)\n"); |
| 1589 | 1600 | } |
| 1590 | 1601 | |
| 1591 | −/* Their i2c requires a huge delay on setting clock or data high for some reason */ | |
| 1602 | +/* | |
| 1603 | + * their i2c requires a huge delay on setting clock or data high for some reason | |
| 1604 | + */ | |
| 1592 | 1605 | static const int i2c_high_udelay = 1000; |
| 1593 | 1606 | static const int i2c_low_udelay = 10; |
| 1594 | 1607 | |
| @@ -1684,8 +1697,10 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, · 89 unmodified lines | ||
| 1684 | 1697 | uint8_t bitstream; |
| 1685 | 1698 | static const int read_bit = 0x1; |
| 1686 | 1699 | |
| 1687 | − /* XXX need mutex to prevent simultaneous attempts to access | |
| 1688 | − * eeprom and i2c bus */ | |
| 1700 | + /* | |
| 1701 | + * XXX need mutex to prevent simultaneous attempts to access | |
| 1702 | + * eeprom and i2c bus | |
| 1703 | + */ | |
| 1689 | 1704 | |
| 1690 | 1705 | /* make sure we dont send anything to eeprom */ |
| 1691 | 1706 | devpriv->plx_control_bits &= ~CTL_EE_CS; |
| @@ -1720,12 +1735,12 @@ static int cb_pcidas64_ai_eoc(struct comedi_device *dev, · 28 unmodified lines | ||
| 1720 | 1735 | struct comedi_insn *insn, |
| 1721 | 1736 | unsigned long context) |
| 1722 | 1737 | { |
| 1723 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1738 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1724 | 1739 | struct pcidas64_private *devpriv = dev->private; |
| 1725 | 1740 | unsigned int status; |
| 1726 | 1741 | |
| 1727 | 1742 | status = readw(devpriv->main_iobase + HW_STATUS_REG); |
| 1728 | − if (thisboard->layout == LAYOUT_4020) { | |
| 1743 | + if (board->layout == LAYOUT_4020) { | |
| 1729 | 1744 | status = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG); |
| 1730 | 1745 | if (status) |
| 1731 | 1746 | return 0; |
| @@ -1739,7 +1754,7 @@ static int cb_pcidas64_ai_eoc(struct comedi_device *dev, · 7 unmodified lines | ||
| 1739 | 1754 | static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, |
| 1740 | 1755 | struct comedi_insn *insn, unsigned int *data) |
| 1741 | 1756 | { |
| 1742 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1757 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1743 | 1758 | struct pcidas64_private *devpriv = dev->private; |
| 1744 | 1759 | unsigned int bits = 0, n; |
| 1745 | 1760 | unsigned int channel, range, aref; |
| @@ -1763,7 +1778,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 17 unmodified lines | ||
| 1763 | 1778 | devpriv->main_iobase + ADC_CONTROL1_REG); |
| 1764 | 1779 | spin_unlock_irqrestore(&dev->spinlock, flags); |
| 1765 | 1780 | |
| 1766 | − if (thisboard->layout != LAYOUT_4020) { | |
| 1781 | + if (board->layout != LAYOUT_4020) { | |
| 1767 | 1782 | /* use internal queue */ |
| 1768 | 1783 | devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; |
| 1769 | 1784 | writew(devpriv->hw_config_bits, |
| @@ -1773,18 +1788,22 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 3 unmodified lines | ||
| 1773 | 1788 | if (insn->chanspec & CR_ALT_SOURCE) { |
| 1774 | 1789 | unsigned int cal_en_bit; |
| 1775 | 1790 | |
| 1776 | − if (thisboard->layout == LAYOUT_60XX) | |
| 1791 | + if (board->layout == LAYOUT_60XX) | |
| 1777 | 1792 | cal_en_bit = CAL_EN_60XX_BIT; |
| 1778 | 1793 | else |
| 1779 | 1794 | cal_en_bit = CAL_EN_64XX_BIT; |
| 1780 | − /* select internal reference source to connect | |
| 1781 | − * to channel 0 */ | |
| 1795 | + /* | |
| 1796 | + * select internal reference source to connect | |
| 1797 | + * to channel 0 | |
| 1798 | + */ | |
| 1782 | 1799 | writew(cal_en_bit | |
| 1783 | 1800 | adc_src_bits(devpriv->calibration_source), |
| 1784 | 1801 | devpriv->main_iobase + CALIBRATION_REG); |
| 1785 | 1802 | } else { |
| 1786 | − /* make sure internal calibration source | |
| 1787 | − * is turned off */ | |
| 1803 | + /* | |
| 1804 | + * make sure internal calibration source | |
| 1805 | + * is turned off | |
| 1806 | + */ | |
| 1788 | 1807 | writew(0, devpriv->main_iobase + CALIBRATION_REG); |
| 1789 | 1808 | } |
| 1790 | 1809 | /* load internal queue */ |
| @@ -1816,8 +1835,10 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 25 unmodified lines | ||
| 1816 | 1835 | devpriv->i2c_cal_range_bits |= attenuate_bit(channel); |
| 1817 | 1836 | else |
| 1818 | 1837 | devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel); |
| 1819 | − /* update calibration/range i2c register only if necessary, | |
| 1820 | − * as it is very slow */ | |
| 1838 | + /* | |
| 1839 | + * update calibration/range i2c register only if necessary, | |
| 1840 | + * as it is very slow | |
| 1841 | + */ | |
| 1821 | 1842 | if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { |
| 1822 | 1843 | uint8_t i2c_data = devpriv->i2c_cal_range_bits; |
| 1823 | 1844 | |
| @@ -1825,10 +1846,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 1 unmodified line | ||
| 1825 | 1846 | sizeof(i2c_data)); |
| 1826 | 1847 | } |
| 1827 | 1848 | |
| 1828 | − /* 4020 manual asks that sample interval register to be set | |
| 1849 | + /* | |
| 1850 | + * 4020 manual asks that sample interval register to be set | |
| 1829 | 1851 | * before writing to convert register. |
| 1830 | 1852 | * Using somewhat arbitrary setting of 4 master clock ticks |
| 1831 | − * = 0.1 usec */ | |
| 1853 | + * = 0.1 usec | |
| 1854 | + */ | |
| 1832 | 1855 | writew(0, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); |
| 1833 | 1856 | writew(2, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); |
| 1834 | 1857 | } |
| @@ -1846,7 +1869,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 11 unmodified lines | ||
| 1846 | 1869 | if (ret) |
| 1847 | 1870 | return ret; |
| 1848 | 1871 | |
| 1849 | − if (thisboard->layout == LAYOUT_4020) | |
| 1872 | + if (board->layout == LAYOUT_4020) | |
| 1850 | 1873 | data[n] = readl(dev->mmio + ADC_FIFO_REG) & 0xffff; |
| 1851 | 1874 | else |
| 1852 | 1875 | data[n] = readw(devpriv->main_iobase + PIPE1_READ_REG); |
| @@ -1858,12 +1881,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 5 unmodified lines | ||
| 1858 | 1881 | static int ai_config_calibration_source(struct comedi_device *dev, |
| 1859 | 1882 | unsigned int *data) |
| 1860 | 1883 | { |
| 1861 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1884 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1862 | 1885 | struct pcidas64_private *devpriv = dev->private; |
| 1863 | 1886 | unsigned int source = data[1]; |
| 1864 | 1887 | int num_calibration_sources; |
| 1865 | 1888 | |
| 1866 | − if (thisboard->layout == LAYOUT_60XX) | |
| 1889 | + if (board->layout == LAYOUT_60XX) | |
| 1867 | 1890 | num_calibration_sources = 16; |
| 1868 | 1891 | else |
| 1869 | 1892 | num_calibration_sources = 8; |
| @@ -1880,9 +1903,9 @@ static int ai_config_calibration_source(struct comedi_device *dev, · 10 unmodified lines | ||
| 1880 | 1903 | |
| 1881 | 1904 | static int ai_config_block_size(struct comedi_device *dev, unsigned int *data) |
| 1882 | 1905 | { |
| 1883 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1906 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1884 | 1907 | int fifo_size; |
| 1885 | − const struct hw_fifo_info *const fifo = thisboard->ai_fifo; | |
| 1908 | + const struct hw_fifo_info *const fifo = board->ai_fifo; | |
| 1886 | 1909 | unsigned int block_size, requested_block_size; |
| 1887 | 1910 | int retval; |
| 1888 | 1911 | |
| @@ -1933,9 +1956,9 @@ static int ai_config_master_clock_4020(struct comedi_device *dev, · 44 unmodified lines | ||
| 1933 | 1956 | /* XXX could add support for 60xx series */ |
| 1934 | 1957 | static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data) |
| 1935 | 1958 | { |
| 1936 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 1959 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1937 | 1960 | |
| 1938 | − switch (thisboard->layout) { | |
| 1961 | + switch (board->layout) { | |
| 1939 | 1962 | case LAYOUT_4020: |
| 1940 | 1963 | return ai_config_master_clock_4020(dev, data); |
| 1941 | 1964 | default: |
| @@ -1963,9 +1986,11 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, · 21 unmodified lines | ||
| 1963 | 1986 | return -EINVAL; |
| 1964 | 1987 | } |
| 1965 | 1988 | |
| 1966 | −/* Gets nearest achievable timing given master clock speed, does not | |
| 1989 | +/* | |
| 1990 | + * Gets nearest achievable timing given master clock speed, does not | |
| 1967 | 1991 | * take into account possible minimum/maximum divisor values. Used |
| 1968 | − * by other timing checking functions. */ | |
| 1992 | + * by other timing checking functions. | |
| 1993 | + */ | |
| 1969 | 1994 | static unsigned int get_divisor(unsigned int ns, unsigned int flags) |
| 1970 | 1995 | { |
| 1971 | 1996 | unsigned int divisor; |
| @@ -1985,13 +2010,15 @@ static unsigned int get_divisor(unsigned int ns, unsigned int flags) · 13 unmodified lines | ||
| 1985 | 2010 | return divisor; |
| 1986 | 2011 | } |
| 1987 | 2012 | |
| 1988 | −/* utility function that rounds desired timing to an achievable time, and | |
| 2013 | +/* | |
| 2014 | + * utility function that rounds desired timing to an achievable time, and | |
| 1989 | 2015 | * sets cmd members appropriately. |
| 1990 | − * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number | |
| 2016 | + * adc paces conversions from master clock by dividing by (x + 3) where x is | |
| 2017 | + * 24 bit number | |
| 1991 | 2018 | */ |
| 1992 | 2019 | static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) |
| 1993 | 2020 | { |
| 1994 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2021 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 1995 | 2022 | unsigned long long convert_divisor = 0; |
| 1996 | 2023 | unsigned int scan_divisor; |
| 1997 | 2024 | static const int min_convert_divisor = 3; |
| @@ -2001,7 +2028,7 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) · 3 unmodified lines | ||
| 2001 | 2028 | unsigned long long max_scan_divisor, min_scan_divisor; |
| 2002 | 2029 | |
| 2003 | 2030 | if (cmd->convert_src == TRIG_TIMER) { |
| 2004 | − if (thisboard->layout == LAYOUT_4020) { | |
| 2031 | + if (board->layout == LAYOUT_4020) { | |
| 2005 | 2032 | cmd->convert_arg = 0; |
| 2006 | 2033 | } else { |
| 2007 | 2034 | convert_divisor = get_divisor(cmd->convert_arg, |
| @@ -2078,7 +2105,7 @@ static int cb_pcidas64_ai_check_chanlist(struct comedi_device *dev, · 70 unmodified lines | ||
| 2078 | 2105 | static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, |
| 2079 | 2106 | struct comedi_cmd *cmd) |
| 2080 | 2107 | { |
| 2081 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2108 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2082 | 2109 | int err = 0; |
| 2083 | 2110 | unsigned int tmp_arg, tmp_arg2; |
| 2084 | 2111 | unsigned int triggers; |
| @@ -2088,14 +2115,14 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, · 3 unmodified lines | ||
| 2088 | 2115 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); |
| 2089 | 2116 | |
| 2090 | 2117 | triggers = TRIG_TIMER; |
| 2091 | − if (thisboard->layout == LAYOUT_4020) | |
| 2118 | + if (board->layout == LAYOUT_4020) | |
| 2092 | 2119 | triggers |= TRIG_OTHER; |
| 2093 | 2120 | else |
| 2094 | 2121 | triggers |= TRIG_FOLLOW; |
| 2095 | 2122 | err |= comedi_check_trigger_src(&cmd->scan_begin_src, triggers); |
| 2096 | 2123 | |
| 2097 | 2124 | triggers = TRIG_TIMER; |
| 2098 | − if (thisboard->layout == LAYOUT_4020) | |
| 2125 | + if (board->layout == LAYOUT_4020) | |
| 2099 | 2126 | triggers |= TRIG_NOW; |
| 2100 | 2127 | else |
| 2101 | 2128 | triggers |= TRIG_EXT; |
| @@ -2137,13 +2164,12 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, · 35 unmodified lines | ||
| 2137 | 2164 | } |
| 2138 | 2165 | |
| 2139 | 2166 | if (cmd->convert_src == TRIG_TIMER) { |
| 2140 | − if (thisboard->layout == LAYOUT_4020) { | |
| 2167 | + if (board->layout == LAYOUT_4020) { | |
| 2141 | 2168 | err |= comedi_check_trigger_arg_is(&cmd->convert_arg, |
| 2142 | 2169 | 0); |
| 2143 | 2170 | } else { |
| 2144 | 2171 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 2145 | − thisboard-> | |
| 2146 | − ai_speed); | |
| 2172 | + board->ai_speed); | |
| 2147 | 2173 | /* |
| 2148 | 2174 | * if scans are timed faster than conversion rate |
| 2149 | 2175 | * allows |
| @@ -2231,12 +2257,12 @@ static void setup_sample_counters(struct comedi_device *dev, · 81 unmodified lines | ||
| 2231 | 2257 | |
| 2232 | 2258 | static inline unsigned int dma_transfer_size(struct comedi_device *dev) |
| 2233 | 2259 | { |
| 2234 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2260 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2235 | 2261 | struct pcidas64_private *devpriv = dev->private; |
| 2236 | 2262 | unsigned int num_samples; |
| 2237 | 2263 | |
| 2238 | 2264 | num_samples = devpriv->ai_fifo_segment_length * |
| 2239 | − thisboard->ai_fifo->sample_packing_ratio; | |
| 2265 | + board->ai_fifo->sample_packing_ratio; | |
| 2240 | 2266 | if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t)) |
| 2241 | 2267 | num_samples = DMA_BUFFER_SIZE / sizeof(uint16_t); |
| 2242 | 2268 | |
| @@ -2318,9 +2344,9 @@ static void select_master_clock_4020(struct comedi_device *dev, · 75 unmodified lines | ||
| 2318 | 2344 | static void select_master_clock(struct comedi_device *dev, |
| 2319 | 2345 | const struct comedi_cmd *cmd) |
| 2320 | 2346 | { |
| 2321 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2347 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2322 | 2348 | |
| 2323 | − switch (thisboard->layout) { | |
| 2349 | + switch (board->layout) { | |
| 2324 | 2350 | case LAYOUT_4020: |
| 2325 | 2351 | select_master_clock_4020(dev, cmd); |
| 2326 | 2352 | break; |
| @@ -2350,7 +2376,7 @@ static inline void dma_start_sync(struct comedi_device *dev, · 23 unmodified lines | ||
| 2350 | 2376 | |
| 2351 | 2377 | static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) |
| 2352 | 2378 | { |
| 2353 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2379 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2354 | 2380 | struct pcidas64_private *devpriv = dev->private; |
| 2355 | 2381 | uint32_t convert_counter = 0, scan_counter = 0; |
| 2356 | 2382 | |
| @@ -2358,7 +2384,7 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) · 1 unmodified line | ||
| 2358 | 2384 | |
| 2359 | 2385 | select_master_clock(dev, cmd); |
| 2360 | 2386 | |
| 2361 | − if (thisboard->layout == LAYOUT_4020) { | |
| 2387 | + if (board->layout == LAYOUT_4020) { | |
| 2362 | 2388 | convert_counter = ai_convert_counter_4020(dev, cmd); |
| 2363 | 2389 | } else { |
| 2364 | 2390 | convert_counter = ai_convert_counter_6xxx(dev, cmd); |
| @@ -2399,12 +2425,12 @@ static int use_internal_queue_6xxx(const struct comedi_cmd *cmd) · 34 unmodified lines | ||
| 2399 | 2425 | static int setup_channel_queue(struct comedi_device *dev, |
| 2400 | 2426 | const struct comedi_cmd *cmd) |
| 2401 | 2427 | { |
| 2402 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2428 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2403 | 2429 | struct pcidas64_private *devpriv = dev->private; |
| 2404 | 2430 | unsigned short bits; |
| 2405 | 2431 | int i; |
| 2406 | 2432 | |
| 2407 | − if (thisboard->layout != LAYOUT_4020) { | |
| 2433 | + if (board->layout != LAYOUT_4020) { | |
| 2408 | 2434 | if (use_internal_queue_6xxx(cmd)) { |
| 2409 | 2435 | devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; |
| 2410 | 2436 | writew(devpriv->hw_config_bits, |
| @@ -2468,8 +2494,10 @@ static int setup_channel_queue(struct comedi_device *dev, · 57 unmodified lines | ||
| 2468 | 2494 | devpriv->main_iobase + |
| 2469 | 2495 | ADC_QUEUE_FIFO_REG); |
| 2470 | 2496 | } |
| 2471 | − /* doing a queue clear is not specified in board docs, | |
| 2472 | − * but required for reliable operation */ | |
| 2497 | + /* | |
| 2498 | + * doing a queue clear is not specified in board docs, | |
| 2499 | + * but required for reliable operation | |
| 2500 | + */ | |
| 2473 | 2501 | writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); |
| 2474 | 2502 | /* prime queue holding register */ |
| 2475 | 2503 | writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); |
| @@ -2492,8 +2520,10 @@ static int setup_channel_queue(struct comedi_device *dev, · 16 unmodified lines | ||
| 2492 | 2520 | devpriv->i2c_cal_range_bits &= |
| 2493 | 2521 | ~attenuate_bit(channel); |
| 2494 | 2522 | } |
| 2495 | − /* update calibration/range i2c register only if necessary, | |
| 2496 | − * as it is very slow */ | |
| 2523 | + /* | |
| 2524 | + * update calibration/range i2c register only if necessary, | |
| 2525 | + * as it is very slow | |
| 2526 | + */ | |
| 2497 | 2527 | if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { |
| 2498 | 2528 | uint8_t i2c_data = devpriv->i2c_cal_range_bits; |
| 2499 | 2529 | |
| @@ -2510,11 +2540,13 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev, · 10 unmodified lines | ||
| 2510 | 2540 | { |
| 2511 | 2541 | struct pcidas64_private *devpriv = dev->private; |
| 2512 | 2542 | |
| 2513 | − /* The transfer size, pci address, and local address registers | |
| 2543 | + /* | |
| 2544 | + * The transfer size, pci address, and local address registers | |
| 2514 | 2545 | * are supposedly unused during chained dma, |
| 2515 | 2546 | * but I have found that left over values from last operation |
| 2516 | 2547 | * occasionally cause problems with transfer of first dma |
| 2517 | − * block. Initializing them to zero seems to fix the problem. */ | |
| 2548 | + * block. Initializing them to zero seems to fix the problem. | |
| 2549 | + */ | |
| 2518 | 2550 | if (dma_channel) { |
| 2519 | 2551 | writel(0, |
| 2520 | 2552 | devpriv->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG); |
| @@ -2536,7 +2568,7 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev, · 15 unmodified lines | ||
| 2536 | 2568 | |
| 2537 | 2569 | static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
| 2538 | 2570 | { |
| 2539 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2571 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2540 | 2572 | struct pcidas64_private *devpriv = dev->private; |
| 2541 | 2573 | struct comedi_async *async = s->async; |
| 2542 | 2574 | struct comedi_cmd *cmd = &async->cmd; |
| @@ -2565,7 +2597,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 22 unmodified lines | ||
| 2565 | 2597 | /* set mode, allow conversions through software gate */ |
| 2566 | 2598 | devpriv->adc_control1_bits |= ADC_SW_GATE_BIT; |
| 2567 | 2599 | devpriv->adc_control1_bits &= ~ADC_DITHER_BIT; |
| 2568 | − if (thisboard->layout != LAYOUT_4020) { | |
| 2600 | + if (board->layout != LAYOUT_4020) { | |
| 2569 | 2601 | devpriv->adc_control1_bits &= ~ADC_MODE_MASK; |
| 2570 | 2602 | if (cmd->convert_src == TRIG_EXT) |
| 2571 | 2603 | /* good old mode 13 */ |
| @@ -2595,11 +2627,11 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 23 unmodified lines | ||
| 2595 | 2627 | writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); |
| 2596 | 2628 | |
| 2597 | 2629 | if ((cmd->flags & CMDF_WAKE_EOS) == 0 || |
| 2598 | − thisboard->layout == LAYOUT_4020) { | |
| 2630 | + board->layout == LAYOUT_4020) { | |
| 2599 | 2631 | devpriv->ai_dma_index = 0; |
| 2600 | 2632 | |
| 2601 | 2633 | /* set dma transfer size */ |
| 2602 | − for (i = 0; i < ai_dma_ring_count(thisboard); i++) | |
| 2634 | + for (i = 0; i < ai_dma_ring_count(board); i++) | |
| 2603 | 2635 | devpriv->ai_dma_desc[i].transfer_size = |
| 2604 | 2636 | cpu_to_le32(dma_transfer_size(dev) * |
| 2605 | 2637 | sizeof(uint16_t)); |
| @@ -2614,7 +2646,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 8 unmodified lines | ||
| 2614 | 2646 | dma_start_sync(dev, 1); |
| 2615 | 2647 | } |
| 2616 | 2648 | |
| 2617 | − if (thisboard->layout == LAYOUT_4020) { | |
| 2649 | + if (board->layout == LAYOUT_4020) { | |
| 2618 | 2650 | /* set source for external triggers */ |
| 2619 | 2651 | bits = 0; |
| 2620 | 2652 | if (cmd->start_src == TRIG_EXT && CR_CHAN(cmd->start_arg)) |
| @@ -2669,15 +2701,19 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) · 48 unmodified lines | ||
| 2669 | 2701 | 0x7fff; |
| 2670 | 2702 | write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & |
| 2671 | 2703 | 0x7fff; |
| 2672 | − /* Get most significant bits (grey code). | |
| 2704 | + /* | |
| 2705 | + * Get most significant bits (grey code). | |
| 2673 | 2706 | * Different boards use different code so use a scheme |
| 2674 | 2707 | * that doesn't depend on encoding. This read must |
| 2675 | 2708 | * occur after reading least significant 15 bits to avoid race |
| 2676 | − * with fifo switching to next segment. */ | |
| 2709 | + * with fifo switching to next segment. | |
| 2710 | + */ | |
| 2677 | 2711 | prepost_bits = readw(devpriv->main_iobase + PREPOST_REG); |
| 2678 | 2712 | |
| 2679 | − /* if read and write pointers are not on the same fifo segment, | |
| 2680 | − * read to the end of the read segment */ | |
| 2713 | + /* | |
| 2714 | + * if read and write pointers are not on the same fifo segment, | |
| 2715 | + * read to the end of the read segment | |
| 2716 | + */ | |
| 2681 | 2717 | read_segment = adc_upper_read_ptr_code(prepost_bits); |
| 2682 | 2718 | write_segment = adc_upper_write_ptr_code(prepost_bits); |
| 2683 | 2719 | |
| @@ -2706,7 +2742,8 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) · 22 unmodified lines | ||
| 2706 | 2742 | } while (read_segment != write_segment); |
| 2707 | 2743 | } |
| 2708 | 2744 | |
| 2709 | −/* Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of | |
| 2745 | +/* | |
| 2746 | + * Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of | |
| 2710 | 2747 | * pointers. The pci-4020 hardware only supports dma transfers (it only |
| 2711 | 2748 | * supports the use of pio for draining the last remaining points from the |
| 2712 | 2749 | * fifo when a data acquisition operation has completed). |
| @@ -2744,9 +2781,9 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev) · 31 unmodified lines | ||
| 2744 | 2781 | /* empty fifo */ |
| 2745 | 2782 | static void pio_drain_ai_fifo(struct comedi_device *dev) |
| 2746 | 2783 | { |
| 2747 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2784 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2748 | 2785 | |
| 2749 | − if (thisboard->layout == LAYOUT_4020) | |
| 2786 | + if (board->layout == LAYOUT_4020) | |
| 2750 | 2787 | pio_drain_ai_fifo_32(dev); |
| 2751 | 2788 | else |
| 2752 | 2789 | pio_drain_ai_fifo_16(dev); |
| @@ -2754,7 +2791,7 @@ static void pio_drain_ai_fifo(struct comedi_device *dev) · 1 unmodified line | ||
| 2754 | 2791 | |
| 2755 | 2792 | static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) |
| 2756 | 2793 | { |
| 2757 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2794 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2758 | 2795 | struct pcidas64_private *devpriv = dev->private; |
| 2759 | 2796 | struct comedi_subdevice *s = dev->read_subdev; |
| 2760 | 2797 | uint32_t next_transfer_addr; |
| @@ -2775,24 +2812,26 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) · 14 unmodified lines | ||
| 2775 | 2812 | devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] || |
| 2776 | 2813 | next_transfer_addr >= |
| 2777 | 2814 | devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] + |
| 2778 | − DMA_BUFFER_SIZE) && j < ai_dma_ring_count(thisboard); j++) { | |
| 2815 | + DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board); j++) { | |
| 2779 | 2816 | /* transfer data from dma buffer to comedi buffer */ |
| 2780 | 2817 | num_samples = comedi_nsamples_left(s, dma_transfer_size(dev)); |
| 2781 | 2818 | comedi_buf_write_samples(s, |
| 2782 | 2819 | devpriv->ai_buffer[devpriv->ai_dma_index], |
| 2783 | 2820 | num_samples); |
| 2784 | 2821 | devpriv->ai_dma_index = (devpriv->ai_dma_index + 1) % |
| 2785 | − ai_dma_ring_count(thisboard); | |
| 2822 | + ai_dma_ring_count(board); | |
| 2786 | 2823 | } |
| 2787 | − /* XXX check for dma ring buffer overrun | |
| 2788 | − * (use end-of-chain bit to mark last unused buffer) */ | |
| 2824 | + /* | |
| 2825 | + * XXX check for dma ring buffer overrun | |
| 2826 | + * (use end-of-chain bit to mark last unused buffer) | |
| 2827 | + */ | |
| 2789 | 2828 | } |
| 2790 | 2829 | |
| 2791 | 2830 | static void handle_ai_interrupt(struct comedi_device *dev, |
| 2792 | 2831 | unsigned short status, |
| 2793 | 2832 | unsigned int plx_status) |
| 2794 | 2833 | { |
| 2795 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 2834 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 2796 | 2835 | struct pcidas64_private *devpriv = dev->private; |
| 2797 | 2836 | struct comedi_subdevice *s = dev->read_subdev; |
| 2798 | 2837 | struct comedi_async *async = s->async; |
| @@ -2821,7 +2860,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, · 22 unmodified lines | ||
| 2821 | 2860 | if ((status & ADC_DONE_BIT) || |
| 2822 | 2861 | ((cmd->flags & CMDF_WAKE_EOS) && |
| 2823 | 2862 | (status & ADC_INTR_PENDING_BIT) && |
| 2824 | − (thisboard->layout != LAYOUT_4020))) { | |
| 2863 | + (board->layout != LAYOUT_4020))) { | |
| 2825 | 2864 | spin_lock_irqsave(&dev->spinlock, flags); |
| 2826 | 2865 | if (devpriv->ai_cmd_running) { |
| 2827 | 2866 | spin_unlock_irqrestore(&dev->spinlock, flags); |
| @@ -2933,8 +2972,10 @@ static unsigned int load_ao_dma_buffer(struct comedi_device *dev, · 105 unmodified lines | ||
| 2933 | 2972 | next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next); |
| 2934 | 2973 | next_bits |= PLX_END_OF_CHAIN_BIT; |
| 2935 | 2974 | devpriv->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits); |
| 2936 | − /* clear end of chain bit on previous buffer now that we have set it | |
| 2937 | − * for the last buffer */ | |
| 2975 | + /* | |
| 2976 | + * clear end of chain bit on previous buffer now that we have set it | |
| 2977 | + * for the last buffer | |
| 2978 | + */ | |
| 2938 | 2979 | next_bits = le32_to_cpu(devpriv->ao_dma_desc[prev_buffer_index].next); |
| 2939 | 2980 | next_bits &= ~PLX_END_OF_CHAIN_BIT; |
| 2940 | 2981 | devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits); |
| @@ -3027,9 +3068,11 @@ static irqreturn_t handle_interrupt(int irq, void *d) · 86 unmodified lines | ||
| 3027 | 3068 | plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG); |
| 3028 | 3069 | status = readw(devpriv->main_iobase + HW_STATUS_REG); |
| 3029 | 3070 | |
| 3030 | − /* an interrupt before all the postconfig stuff gets done could | |
| 3071 | + /* | |
| 3072 | + * an interrupt before all the postconfig stuff gets done could | |
| 3031 | 3073 | * cause a NULL dereference if we continue through the |
| 3032 | − * interrupt handler */ | |
| 3074 | + * interrupt handler | |
| 3075 | + */ | |
| 3033 | 3076 | if (!dev->attached) |
| 3034 | 3077 | return IRQ_HANDLED; |
| 3035 | 3078 | |
| @@ -3068,7 +3111,7 @@ static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) · 32 unmodified lines | ||
| 3068 | 3111 | static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, |
| 3069 | 3112 | struct comedi_insn *insn, unsigned int *data) |
| 3070 | 3113 | { |
| 3071 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 3114 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 3072 | 3115 | struct pcidas64_private *devpriv = dev->private; |
| 3073 | 3116 | int chan = CR_CHAN(insn->chanspec); |
| 3074 | 3117 | int range = CR_RANGE(insn->chanspec); |
| @@ -3082,7 +3125,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, · 7 unmodified lines | ||
| 3082 | 3125 | devpriv->main_iobase + DAC_CONTROL1_REG); |
| 3083 | 3126 | |
| 3084 | 3127 | /* write to channel */ |
| 3085 | − if (thisboard->layout == LAYOUT_4020) { | |
| 3128 | + if (board->layout == LAYOUT_4020) { | |
| 3086 | 3129 | writew(data[0] & 0xff, |
| 3087 | 3130 | devpriv->main_iobase + dac_lsb_4020_reg(chan)); |
| 3088 | 3131 | writew((data[0] >> 8) & 0xf, |
| @@ -3189,8 +3232,10 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) · 100 unmodified lines | ||
| 3189 | 3232 | unsigned int nbytes; |
| 3190 | 3233 | int i; |
| 3191 | 3234 | |
| 3192 | − /* clear queue pointer too, since external queue has | |
| 3193 | − * weird interactions with ao fifo */ | |
| 3235 | + /* | |
| 3236 | + * clear queue pointer too, since external queue has | |
| 3237 | + * weird interactions with ao fifo | |
| 3238 | + */ | |
| 3194 | 3239 | writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); |
| 3195 | 3240 | writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG); |
| 3196 | 3241 | |
| @@ -3223,11 +3268,11 @@ static inline int external_ai_queue_in_use(struct comedi_device *dev, · 26 unmodified lines | ||
| 3223 | 3268 | struct comedi_subdevice *s, |
| 3224 | 3269 | struct comedi_cmd *cmd) |
| 3225 | 3270 | { |
| 3226 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 3271 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 3227 | 3272 | |
| 3228 | 3273 | if (s->busy) |
| 3229 | 3274 | return 0; |
| 3230 | − if (thisboard->layout == LAYOUT_4020) | |
| 3275 | + if (board->layout == LAYOUT_4020) | |
| 3231 | 3276 | return 0; |
| 3232 | 3277 | else if (use_internal_queue_6xxx(cmd)) |
| 3233 | 3278 | return 0; |
| @@ -3306,7 +3351,7 @@ static int cb_pcidas64_ao_check_chanlist(struct comedi_device *dev, · 72 unmodified lines | ||
| 3306 | 3351 | static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, |
| 3307 | 3352 | struct comedi_cmd *cmd) |
| 3308 | 3353 | { |
| 3309 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 3354 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 3310 | 3355 | int err = 0; |
| 3311 | 3356 | unsigned int tmp_arg; |
| 3312 | 3357 | |
| @@ -3344,7 +3389,7 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, · 31 unmodified lines | ||
| 3344 | 3389 | |
| 3345 | 3390 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 3346 | 3391 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 3347 | − thisboard->ao_scan_speed); | |
| 3392 | + board->ao_scan_speed); | |
| 3348 | 3393 | if (get_ao_divisor(cmd->scan_begin_arg, cmd->flags) > |
| 3349 | 3394 | max_counter_value) { |
| 3350 | 3395 | cmd->scan_begin_arg = (max_counter_value + 2) * |
| @@ -3459,7 +3504,8 @@ static int dio_60xx_wbits(struct comedi_device *dev, · 108 unmodified lines | ||
| 3459 | 3504 | return insn->n; |
| 3460 | 3505 | } |
| 3461 | 3506 | |
| 3462 | −/* pci-6025 8800 caldac: | |
| 3507 | +/* | |
| 3508 | + * pci-6025 8800 caldac: | |
| 3463 | 3509 | * address 0 == dac channel 0 offset |
| 3464 | 3510 | * address 1 == dac channel 0 gain |
| 3465 | 3511 | * address 2 == dac channel 1 offset |
| @@ -3469,7 +3515,8 @@ static int dio_60xx_wbits(struct comedi_device *dev, · 3 unmodified lines | ||
| 3469 | 3515 | * address 6 == coarse adc gain |
| 3470 | 3516 | * address 7 == fine adc gain |
| 3471 | 3517 | */ |
| 3472 | −/* pci-6402/16 uses all 8 channels for dac: | |
| 3518 | +/* | |
| 3519 | + * pci-6402/16 uses all 8 channels for dac: | |
| 3473 | 3520 | * address 0 == dac channel 0 fine gain |
| 3474 | 3521 | * address 1 == dac channel 0 coarse gain |
| 3475 | 3522 | * address 2 == dac channel 0 coarse offset |
| @@ -3478,7 +3525,7 @@ static int dio_60xx_wbits(struct comedi_device *dev, · 2 unmodified lines | ||
| 3478 | 3525 | * address 5 == dac channel 1 coarse gain |
| 3479 | 3526 | * address 6 == dac channel 0 fine offset |
| 3480 | 3527 | * address 7 == dac channel 1 fine offset |
| 3481 | −*/ | |
| 3528 | + */ | |
| 3482 | 3529 | |
| 3483 | 3530 | static int caldac_8800_write(struct comedi_device *dev, unsigned int address, |
| 3484 | 3531 | uint8_t value) |
| @@ -3575,9 +3622,9 @@ static int caldac_i2c_write(struct comedi_device *dev, · 90 unmodified lines | ||
| 3575 | 3622 | static void caldac_write(struct comedi_device *dev, unsigned int channel, |
| 3576 | 3623 | unsigned int value) |
| 3577 | 3624 | { |
| 3578 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 3625 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 3579 | 3626 | |
| 3580 | − switch (thisboard->layout) { | |
| 3627 | + switch (board->layout) { | |
| 3581 | 3628 | case LAYOUT_60XX: |
| 3582 | 3629 | case LAYOUT_64XX: |
| 3583 | 3630 | caldac_8800_write(dev, channel, value); |
| @@ -3738,11 +3785,12 @@ static int eeprom_read_insn(struct comedi_device *dev, · 154 unmodified lines | ||
| 3738 | 3785 | return 1; |
| 3739 | 3786 | } |
| 3740 | 3787 | |
| 3741 | −/* Allocate and initialize the subdevice structures. | |
| 3788 | +/* | |
| 3789 | + * Allocate and initialize the subdevice structures. | |
| 3742 | 3790 | */ |
| 3743 | 3791 | static int setup_subdevices(struct comedi_device *dev) |
| 3744 | 3792 | { |
| 3745 | − const struct pcidas64_board *thisboard = dev->board_ptr; | |
| 3793 | + const struct pcidas64_board *board = dev->board_ptr; | |
| 3746 | 3794 | struct pcidas64_private *devpriv = dev->private; |
| 3747 | 3795 | struct comedi_subdevice *s; |
| 3748 | 3796 | int i; |
| @@ -3757,24 +3805,26 @@ static int setup_subdevices(struct comedi_device *dev) · 8 unmodified lines | ||
| 3757 | 3805 | dev->read_subdev = s; |
| 3758 | 3806 | s->type = COMEDI_SUBD_AI; |
| 3759 | 3807 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ; |
| 3760 | − if (thisboard->layout == LAYOUT_60XX) | |
| 3808 | + if (board->layout == LAYOUT_60XX) | |
| 3761 | 3809 | s->subdev_flags |= SDF_COMMON | SDF_DIFF; |
| 3762 | − else if (thisboard->layout == LAYOUT_64XX) | |
| 3810 | + else if (board->layout == LAYOUT_64XX) | |
| 3763 | 3811 | s->subdev_flags |= SDF_DIFF; |
| 3764 | 3812 | /* XXX Number of inputs in differential mode is ignored */ |
| 3765 | − s->n_chan = thisboard->ai_se_chans; | |
| 3813 | + s->n_chan = board->ai_se_chans; | |
| 3766 | 3814 | s->len_chanlist = 0x2000; |
| 3767 | − s->maxdata = (1 << thisboard->ai_bits) - 1; | |
| 3768 | − s->range_table = thisboard->ai_range_table; | |
| 3815 | + s->maxdata = (1 << board->ai_bits) - 1; | |
| 3816 | + s->range_table = board->ai_range_table; | |
| 3769 | 3817 | s->insn_read = ai_rinsn; |
| 3770 | 3818 | s->insn_config = ai_config_insn; |
| 3771 | 3819 | s->do_cmd = ai_cmd; |
| 3772 | 3820 | s->do_cmdtest = ai_cmdtest; |
| 3773 | 3821 | s->cancel = ai_cancel; |
| 3774 | − if (thisboard->layout == LAYOUT_4020) { | |
| 3822 | + if (board->layout == LAYOUT_4020) { | |
| 3775 | 3823 | uint8_t data; |
| 3776 | − /* set adc to read from inputs | |
| 3777 | − * (not internal calibration sources) */ | |
| 3824 | + /* | |
| 3825 | + * set adc to read from inputs | |
| 3826 | + * (not internal calibration sources) | |
| 3827 | + */ | |
| 3778 | 3828 | devpriv->i2c_cal_range_bits = adc_src_4020_bits(4); |
| 3779 | 3829 | /* set channels to +-5 volt input ranges */ |
| 3780 | 3830 | for (i = 0; i < s->n_chan; i++) |
| @@ -3785,24 +3835,24 @@ static int setup_subdevices(struct comedi_device *dev) · 4 unmodified lines | ||
| 3785 | 3835 | |
| 3786 | 3836 | /* analog output subdevice */ |
| 3787 | 3837 | s = &dev->subdevices[1]; |
| 3788 | − if (thisboard->ao_nchan) { | |
| 3838 | + if (board->ao_nchan) { | |
| 3789 | 3839 | s->type = COMEDI_SUBD_AO; |
| 3790 | 3840 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | |
| 3791 | 3841 | SDF_GROUND | SDF_CMD_WRITE; |
| 3792 | − s->n_chan = thisboard->ao_nchan; | |
| 3793 | − s->maxdata = (1 << thisboard->ao_bits) - 1; | |
| 3794 | − s->range_table = thisboard->ao_range_table; | |
| 3842 | + s->n_chan = board->ao_nchan; | |
| 3843 | + s->maxdata = (1 << board->ao_bits) - 1; | |
| 3844 | + s->range_table = board->ao_range_table; | |
| 3795 | 3845 | s->insn_write = ao_winsn; |
| 3796 | 3846 | |
| 3797 | 3847 | ret = comedi_alloc_subdev_readback(s); |
| 3798 | 3848 | if (ret) |
| 3799 | 3849 | return ret; |
| 3800 | 3850 | |
| 3801 | − if (ao_cmd_is_supported(thisboard)) { | |
| 3851 | + if (ao_cmd_is_supported(board)) { | |
| 3802 | 3852 | dev->write_subdev = s; |
| 3803 | 3853 | s->do_cmdtest = ao_cmdtest; |
| 3804 | 3854 | s->do_cmd = ao_cmd; |
| 3805 | − s->len_chanlist = thisboard->ao_nchan; | |
| 3855 | + s->len_chanlist = board->ao_nchan; | |
| 3806 | 3856 | s->cancel = ao_cancel; |
| 3807 | 3857 | } |
| 3808 | 3858 | } else { |
| @@ -3811,7 +3861,7 @@ static int setup_subdevices(struct comedi_device *dev) · 2 unmodified lines | ||
| 3811 | 3861 | |
| 3812 | 3862 | /* digital input */ |
| 3813 | 3863 | s = &dev->subdevices[2]; |
| 3814 | − if (thisboard->layout == LAYOUT_64XX) { | |
| 3864 | + if (board->layout == LAYOUT_64XX) { | |
| 3815 | 3865 | s->type = COMEDI_SUBD_DI; |
| 3816 | 3866 | s->subdev_flags = SDF_READABLE; |
| 3817 | 3867 | s->n_chan = 4; |
| @@ -3823,7 +3873,7 @@ static int setup_subdevices(struct comedi_device *dev) · 5 unmodified lines | ||
| 3823 | 3873 | } |
| 3824 | 3874 | |
| 3825 | 3875 | /* digital output */ |
| 3826 | − if (thisboard->layout == LAYOUT_64XX) { | |
| 3876 | + if (board->layout == LAYOUT_64XX) { | |
| 3827 | 3877 | s = &dev->subdevices[3]; |
| 3828 | 3878 | s->type = COMEDI_SUBD_DO; |
| 3829 | 3879 | s->subdev_flags = SDF_WRITABLE; |
| @@ -3837,8 +3887,8 @@ static int setup_subdevices(struct comedi_device *dev) · 7 unmodified lines | ||
| 3837 | 3887 | |
| 3838 | 3888 | /* 8255 */ |
| 3839 | 3889 | s = &dev->subdevices[4]; |
| 3840 | − if (thisboard->has_8255) { | |
| 3841 | − if (thisboard->layout == LAYOUT_4020) { | |
| 3890 | + if (board->has_8255) { | |
| 3891 | + if (board->layout == LAYOUT_4020) { | |
| 3842 | 3892 | ret = subdev_8255_init(dev, s, dio_callback_4020, |
| 3843 | 3893 | I8255_4020_REG); |
| 3844 | 3894 | } else { |
| @@ -3853,7 +3903,7 @@ static int setup_subdevices(struct comedi_device *dev) · 8 unmodified lines | ||
| 3853 | 3903 | |
| 3854 | 3904 | /* 8 channel dio for 60xx */ |
| 3855 | 3905 | s = &dev->subdevices[5]; |
| 3856 | − if (thisboard->layout == LAYOUT_60XX) { | |
| 3906 | + if (board->layout == LAYOUT_60XX) { | |
| 3857 | 3907 | s->type = COMEDI_SUBD_DIO; |
| 3858 | 3908 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; |
| 3859 | 3909 | s->n_chan = 8; |
| @@ -3870,7 +3920,7 @@ static int setup_subdevices(struct comedi_device *dev) · 10 unmodified lines | ||
| 3870 | 3920 | s->type = COMEDI_SUBD_CALIB; |
| 3871 | 3921 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 3872 | 3922 | s->n_chan = 8; |
| 3873 | − if (thisboard->layout == LAYOUT_4020) | |
| 3923 | + if (board->layout == LAYOUT_4020) | |
| 3874 | 3924 | s->maxdata = 0xfff; |
| 3875 | 3925 | else |
| 3876 | 3926 | s->maxdata = 0xff; |
| @@ -3887,7 +3937,7 @@ static int setup_subdevices(struct comedi_device *dev) · 10 unmodified lines | ||
| 3887 | 3937 | |
| 3888 | 3938 | /* 2 channel ad8402 potentiometer */ |
| 3889 | 3939 | s = &dev->subdevices[7]; |
| 3890 | − if (thisboard->layout == LAYOUT_64XX) { | |
| 3940 | + if (board->layout == LAYOUT_64XX) { | |
| 3891 | 3941 | s->type = COMEDI_SUBD_CALIB; |
| 3892 | 3942 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 3893 | 3943 | s->n_chan = 2; |
| @@ -3929,16 +3979,16 @@ static int auto_attach(struct comedi_device *dev, · 35 unmodified lines | ||
| 3929 | 3979 | unsigned long context) |
| 3930 | 3980 | { |
| 3931 | 3981 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 3932 | − const struct pcidas64_board *thisboard = NULL; | |
| 3982 | + const struct pcidas64_board *board = NULL; | |
| 3933 | 3983 | struct pcidas64_private *devpriv; |
| 3934 | 3984 | uint32_t local_range, local_decode; |
| 3935 | 3985 | int retval; |
| 3936 | 3986 | |
| 3937 | 3987 | if (context < ARRAY_SIZE(pcidas64_boards)) |
| 3938 | − thisboard = &pcidas64_boards[context]; | |
| 3939 | − if (!thisboard) | |
| 3988 | + board = &pcidas64_boards[context]; | |
| 3989 | + if (!board) | |
| 3940 | 3990 | return -ENODEV; |
| 3941 | − dev->board_ptr = thisboard; | |
| 3991 | + dev->board_ptr = board; | |
| 3942 | 3992 | |
| 3943 | 3993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 3944 | 3994 | if (!devpriv) |
| @@ -3950,7 +4000,7 @@ static int auto_attach(struct comedi_device *dev, · 5 unmodified lines | ||
| 3950 | 4000 | pci_set_master(pcidev); |
| 3951 | 4001 | |
| 3952 | 4002 | /* Initialize dev->board_name */ |
| 3953 | − dev->board_name = thisboard->name; | |
| 4003 | + dev->board_name = board->name; | |
| 3954 | 4004 | |
| 3955 | 4005 | devpriv->main_phys_iobase = pci_resource_start(pcidev, 2); |
| 3956 | 4006 | devpriv->dio_counter_phys_iobase = pci_resource_start(pcidev, 3); |
| @@ -335,18 +335,18 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, · 334 unmodified lines | ||
| 335 | 335 | unsigned long context) |
| 336 | 336 | { |
| 337 | 337 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 338 | − const struct cb_pcidda_board *thisboard = NULL; | |
| 338 | + const struct cb_pcidda_board *board = NULL; | |
| 339 | 339 | struct cb_pcidda_private *devpriv; |
| 340 | 340 | struct comedi_subdevice *s; |
| 341 | 341 | int i; |
| 342 | 342 | int ret; |
| 343 | 343 | |
| 344 | 344 | if (context < ARRAY_SIZE(cb_pcidda_boards)) |
| 345 | − thisboard = &cb_pcidda_boards[context]; | |
| 346 | − if (!thisboard) | |
| 345 | + board = &cb_pcidda_boards[context]; | |
| 346 | + if (!board) | |
| 347 | 347 | return -ENODEV; |
| 348 | − dev->board_ptr = thisboard; | |
| 349 | − dev->board_name = thisboard->name; | |
| 348 | + dev->board_ptr = board; | |
| 349 | + dev->board_name = board->name; | |
| 350 | 350 | |
| 351 | 351 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 352 | 352 | if (!devpriv) |
| @@ -366,8 +366,8 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, · 13 unmodified lines | ||
| 366 | 366 | /* analog output subdevice */ |
| 367 | 367 | s->type = COMEDI_SUBD_AO; |
| 368 | 368 | s->subdev_flags = SDF_WRITABLE; |
| 369 | − s->n_chan = thisboard->ao_chans; | |
| 370 | − s->maxdata = (1 << thisboard->ao_bits) - 1; | |
| 369 | + s->n_chan = board->ao_chans; | |
| 370 | + s->maxdata = (1 << board->ao_bits) - 1; | |
| 371 | 371 | s->range_table = &cb_pcidda_ranges; |
| 372 | 372 | s->insn_write = cb_pcidda_ao_insn_write; |
| 373 | 373 | |
| @@ -384,7 +384,7 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, · 10 unmodified lines | ||
| 384 | 384 | devpriv->eeprom_data[i] = cb_pcidda_read_eeprom(dev, i); |
| 385 | 385 | |
| 386 | 386 | /* set calibrations dacs */ |
| 387 | − for (i = 0; i < thisboard->ao_chans; i++) | |
| 387 | + for (i = 0; i < board->ao_chans; i++) | |
| 388 | 388 | cb_pcidda_calibrate(dev, i, devpriv->ao_range[i]); |
| 389 | 389 | |
| 390 | 390 | return 0; |
| @@ -243,7 +243,7 @@ static int cb_pcimdas_ao_insn_write(struct comedi_device *dev, · 242 unmodified lines | ||
| 243 | 243 | return insn->n; |
| 244 | 244 | } |
| 245 | 245 | |
| 246 | −static int cb_pcimdas_di_insn_read(struct comedi_device *dev, | |
| 246 | +static int cb_pcimdas_di_insn_bits(struct comedi_device *dev, | |
| 247 | 247 | struct comedi_subdevice *s, |
| 248 | 248 | struct comedi_insn *insn, |
| 249 | 249 | unsigned int *data) |
| @@ -258,7 +258,7 @@ static int cb_pcimdas_di_insn_read(struct comedi_device *dev, · 8 unmodified lines | ||
| 258 | 258 | return insn->n; |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | −static int cb_pcimdas_do_insn_write(struct comedi_device *dev, | |
| 261 | +static int cb_pcimdas_do_insn_bits(struct comedi_device *dev, | |
| 262 | 262 | struct comedi_subdevice *s, |
| 263 | 263 | struct comedi_insn *insn, |
| 264 | 264 | unsigned int *data) |
| @@ -424,7 +424,7 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, · 159 unmodified lines | ||
| 424 | 424 | s->n_chan = 4; |
| 425 | 425 | s->maxdata = 1; |
| 426 | 426 | s->range_table = &range_digital; |
| 427 | − s->insn_read = cb_pcimdas_di_insn_read; | |
| 427 | + s->insn_bits = cb_pcimdas_di_insn_bits; | |
| 428 | 428 | |
| 429 | 429 | /* Digital Output subdevice (main connector) */ |
| 430 | 430 | s = &dev->subdevices[4]; |
| @@ -433,7 +433,7 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, · 2 unmodified lines | ||
| 433 | 433 | s->n_chan = 4; |
| 434 | 434 | s->maxdata = 1; |
| 435 | 435 | s->range_table = &range_digital; |
| 436 | − s->insn_write = cb_pcimdas_do_insn_write; | |
| 436 | + s->insn_bits = cb_pcimdas_do_insn_bits; | |
| 437 | 437 | |
| 438 | 438 | /* Counter subdevice (8254) */ |
| 439 | 439 | s = &dev->subdevices[5]; |
| @@ -164,11 +164,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev, · 163 unmodified lines | ||
| 164 | 164 | |
| 165 | 165 | s = &dev->subdevices[1]; |
| 166 | 166 | /* digital i/o subdevice */ |
| 167 | − ret = subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); | |
| 168 | − if (ret) | |
| 169 | − return ret; | |
| 170 | − | |
| 171 | − return 0; | |
| 167 | + return subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); | |
| 172 | 168 | } |
| 173 | 169 | |
| 174 | 170 | static struct comedi_driver cb_pcimdda_driver = { |
| @@ -20,6 +20,12 @@ · 19 unmodified lines | ||
| 20 | 20 | #ifndef _COMEDI_8254_H |
| 21 | 21 | #define _COMEDI_8254_H |
| 22 | 22 | |
| 23 | +#include <linux/types.h> | |
| 24 | + | |
| 25 | +struct comedi_device; | |
| 26 | +struct comedi_insn; | |
| 27 | +struct comedi_subdevice; | |
| 28 | + | |
| 23 | 29 | /* |
| 24 | 30 | * Common oscillator base values in nanoseconds |
| 25 | 31 | */ |
| @@ -0,0 +1,285 @@ | ||
| 1 | +/* | |
| 2 | + * comedi_8255.c | |
| 3 | + * Generic 8255 digital I/O support | |
| 4 | + * | |
| 5 | + * Split from the Comedi "8255" driver module. | |
| 6 | + * | |
| 7 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 8 | + * Copyright (C) 1998 David A. Schleef <ds@schleef.org> | |
| 9 | + * | |
| 10 | + * This program is free software; you can redistribute it and/or modify | |
| 11 | + * it under the terms of the GNU General Public License as published by | |
| 12 | + * the Free Software Foundation; either version 2 of the License, or | |
| 13 | + * (at your option) any later version. | |
| 14 | + * | |
| 15 | + * This program is distributed in the hope that it will be useful, | |
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | + * GNU General Public License for more details. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +/* | |
| 22 | + * Module: comedi_8255 | |
| 23 | + * Description: Generic 8255 support | |
| 24 | + * Author: ds | |
| 25 | + * Updated: Fri, 22 May 2015 12:14:17 +0000 | |
| 26 | + * Status: works | |
| 27 | + * | |
| 28 | + * This module is not used directly by end-users. Rather, it is used by | |
| 29 | + * other drivers to provide support for an 8255 "Programmable Peripheral | |
| 30 | + * Interface" (PPI) chip. | |
| 31 | + * | |
| 32 | + * The classic in digital I/O. The 8255 appears in Comedi as a single | |
| 33 | + * digital I/O subdevice with 24 channels. The channel 0 corresponds to | |
| 34 | + * the 8255's port A, bit 0; channel 23 corresponds to port C, bit 7. | |
| 35 | + * Direction configuration is done in blocks, with channels 0-7, 8-15, | |
| 36 | + * 16-19, and 20-23 making up the 4 blocks. The only 8255 mode | |
| 37 | + * supported is mode 0. | |
| 38 | + */ | |
| 39 | + | |
| 40 | +#include <linux/module.h> | |
| 41 | +#include "../comedidev.h" | |
| 42 | + | |
| 43 | +#include "8255.h" | |
| 44 | + | |
| 45 | +struct subdev_8255_private { | |
| 46 | + unsigned long regbase; | |
| 47 | + int (*io)(struct comedi_device *dev, int dir, int port, int data, | |
| 48 | + unsigned long regbase); | |
| 49 | +}; | |
| 50 | + | |
| 51 | +static int subdev_8255_io(struct comedi_device *dev, | |
| 52 | + int dir, int port, int data, unsigned long regbase) | |
| 53 | +{ | |
| 54 | + if (dir) { | |
| 55 | + outb(data, dev->iobase + regbase + port); | |
| 56 | + return 0; | |
| 57 | + } | |
| 58 | + return inb(dev->iobase + regbase + port); | |
| 59 | +} | |
| 60 | + | |
| 61 | +static int subdev_8255_mmio(struct comedi_device *dev, | |
| 62 | + int dir, int port, int data, unsigned long regbase) | |
| 63 | +{ | |
| 64 | + if (dir) { | |
| 65 | + writeb(data, dev->mmio + regbase + port); | |
| 66 | + return 0; | |
| 67 | + } | |
| 68 | + return readb(dev->mmio + regbase + port); | |
| 69 | +} | |
| 70 | + | |
| 71 | +static int subdev_8255_insn(struct comedi_device *dev, | |
| 72 | + struct comedi_subdevice *s, | |
| 73 | + struct comedi_insn *insn, | |
| 74 | + unsigned int *data) | |
| 75 | +{ | |
| 76 | + struct subdev_8255_private *spriv = s->private; | |
| 77 | + unsigned long regbase = spriv->regbase; | |
| 78 | + unsigned int mask; | |
| 79 | + unsigned int v; | |
| 80 | + | |
| 81 | + mask = comedi_dio_update_state(s, data); | |
| 82 | + if (mask) { | |
| 83 | + if (mask & 0xff) | |
| 84 | + spriv->io(dev, 1, I8255_DATA_A_REG, | |
| 85 | + s->state & 0xff, regbase); | |
| 86 | + if (mask & 0xff00) | |
| 87 | + spriv->io(dev, 1, I8255_DATA_B_REG, | |
| 88 | + (s->state >> 8) & 0xff, regbase); | |
| 89 | + if (mask & 0xff0000) | |
| 90 | + spriv->io(dev, 1, I8255_DATA_C_REG, | |
| 91 | + (s->state >> 16) & 0xff, regbase); | |
| 92 | + } | |
| 93 | + | |
| 94 | + v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, regbase); | |
| 95 | + v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, regbase) << 8); | |
| 96 | + v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, regbase) << 16); | |
| 97 | + | |
| 98 | + data[1] = v; | |
| 99 | + | |
| 100 | + return insn->n; | |
| 101 | +} | |
| 102 | + | |
| 103 | +static void subdev_8255_do_config(struct comedi_device *dev, | |
| 104 | + struct comedi_subdevice *s) | |
| 105 | +{ | |
| 106 | + struct subdev_8255_private *spriv = s->private; | |
| 107 | + unsigned long regbase = spriv->regbase; | |
| 108 | + int config; | |
| 109 | + | |
| 110 | + config = I8255_CTRL_CW; | |
| 111 | + /* 1 in io_bits indicates output, 1 in config indicates input */ | |
| 112 | + if (!(s->io_bits & 0x0000ff)) | |
| 113 | + config |= I8255_CTRL_A_IO; | |
| 114 | + if (!(s->io_bits & 0x00ff00)) | |
| 115 | + config |= I8255_CTRL_B_IO; | |
| 116 | + if (!(s->io_bits & 0x0f0000)) | |
| 117 | + config |= I8255_CTRL_C_LO_IO; | |
| 118 | + if (!(s->io_bits & 0xf00000)) | |
| 119 | + config |= I8255_CTRL_C_HI_IO; | |
| 120 | + | |
| 121 | + spriv->io(dev, 1, I8255_CTRL_REG, config, regbase); | |
| 122 | +} | |
| 123 | + | |
| 124 | +static int subdev_8255_insn_config(struct comedi_device *dev, | |
| 125 | + struct comedi_subdevice *s, | |
| 126 | + struct comedi_insn *insn, | |
| 127 | + unsigned int *data) | |
| 128 | +{ | |
| 129 | + unsigned int chan = CR_CHAN(insn->chanspec); | |
| 130 | + unsigned int mask; | |
| 131 | + int ret; | |
| 132 | + | |
| 133 | + if (chan < 8) | |
| 134 | + mask = 0x0000ff; | |
| 135 | + else if (chan < 16) | |
| 136 | + mask = 0x00ff00; | |
| 137 | + else if (chan < 20) | |
| 138 | + mask = 0x0f0000; | |
| 139 | + else | |
| 140 | + mask = 0xf00000; | |
| 141 | + | |
| 142 | + ret = comedi_dio_insn_config(dev, s, insn, data, mask); | |
| 143 | + if (ret) | |
| 144 | + return ret; | |
| 145 | + | |
| 146 | + subdev_8255_do_config(dev, s); | |
| 147 | + | |
| 148 | + return insn->n; | |
| 149 | +} | |
| 150 | + | |
| 151 | +static int __subdev_8255_init(struct comedi_device *dev, | |
| 152 | + struct comedi_subdevice *s, | |
| 153 | + int (*io)(struct comedi_device *dev, | |
| 154 | + int dir, int port, int data, | |
| 155 | + unsigned long regbase), | |
| 156 | + unsigned long regbase, | |
| 157 | + bool is_mmio) | |
| 158 | +{ | |
| 159 | + struct subdev_8255_private *spriv; | |
| 160 | + | |
| 161 | + spriv = comedi_alloc_spriv(s, sizeof(*spriv)); | |
| 162 | + if (!spriv) | |
| 163 | + return -ENOMEM; | |
| 164 | + | |
| 165 | + if (io) | |
| 166 | + spriv->io = io; | |
| 167 | + else if (is_mmio) | |
| 168 | + spriv->io = subdev_8255_mmio; | |
| 169 | + else | |
| 170 | + spriv->io = subdev_8255_io; | |
| 171 | + spriv->regbase = regbase; | |
| 172 | + | |
| 173 | + s->type = COMEDI_SUBD_DIO; | |
| 174 | + s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
| 175 | + s->n_chan = 24; | |
| 176 | + s->range_table = &range_digital; | |
| 177 | + s->maxdata = 1; | |
| 178 | + s->insn_bits = subdev_8255_insn; | |
| 179 | + s->insn_config = subdev_8255_insn_config; | |
| 180 | + | |
| 181 | + subdev_8255_do_config(dev, s); | |
| 182 | + | |
| 183 | + return 0; | |
| 184 | +} | |
| 185 | + | |
| 186 | +/** | |
| 187 | + * subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255 | |
| 188 | + * @dev: comedi device owning subdevice | |
| 189 | + * @s: comedi subdevice to initialize | |
| 190 | + * @io: (optional) register I/O call-back function | |
| 191 | + * @regbase: offset of 8255 registers from dev->iobase, or call-back context | |
| 192 | + * | |
| 193 | + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. | |
| 194 | + * | |
| 195 | + * If the optional I/O call-back function is provided, its prototype is of | |
| 196 | + * the following form: | |
| 197 | + * | |
| 198 | + * int my_8255_callback(struct comedi_device *dev, int dir, int port, | |
| 199 | + * int data, unsigned long regbase); | |
| 200 | + * | |
| 201 | + * where 'dev', and 'regbase' match the values passed to this function, | |
| 202 | + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' | |
| 203 | + * is the direction (0 for read, 1 for write) and 'data' is the value to be | |
| 204 | + * written. It should return 0 if writing or the value read if reading. | |
| 205 | + * | |
| 206 | + * If the optional I/O call-back function is not provided, an internal | |
| 207 | + * call-back function is used which uses consecutive I/O port addresses | |
| 208 | + * starting at dev->iobase + regbase. | |
| 209 | + * | |
| 210 | + * Return: -ENOMEM if failed to allocate memory, zero on success. | |
| 211 | + */ | |
| 212 | +int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 213 | + int (*io)(struct comedi_device *dev, int dir, int port, | |
| 214 | + int data, unsigned long regbase), | |
| 215 | + unsigned long regbase) | |
| 216 | +{ | |
| 217 | + return __subdev_8255_init(dev, s, io, regbase, false); | |
| 218 | +} | |
| 219 | +EXPORT_SYMBOL_GPL(subdev_8255_init); | |
| 220 | + | |
| 221 | +/** | |
| 222 | + * subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255 | |
| 223 | + * @dev: comedi device owning subdevice | |
| 224 | + * @s: comedi subdevice to initialize | |
| 225 | + * @io: (optional) register I/O call-back function | |
| 226 | + * @regbase: offset of 8255 registers from dev->mmio, or call-back context | |
| 227 | + * | |
| 228 | + * Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip. | |
| 229 | + * | |
| 230 | + * If the optional I/O call-back function is provided, its prototype is of | |
| 231 | + * the following form: | |
| 232 | + * | |
| 233 | + * int my_8255_callback(struct comedi_device *dev, int dir, int port, | |
| 234 | + * int data, unsigned long regbase); | |
| 235 | + * | |
| 236 | + * where 'dev', and 'regbase' match the values passed to this function, | |
| 237 | + * 'port' is the 8255 port number 0 to 3 (including the control port), 'dir' | |
| 238 | + * is the direction (0 for read, 1 for write) and 'data' is the value to be | |
| 239 | + * written. It should return 0 if writing or the value read if reading. | |
| 240 | + * | |
| 241 | + * If the optional I/O call-back function is not provided, an internal | |
| 242 | + * call-back function is used which uses consecutive MMIO virtual addresses | |
| 243 | + * starting at dev->mmio + regbase. | |
| 244 | + * | |
| 245 | + * Return: -ENOMEM if failed to allocate memory, zero on success. | |
| 246 | + */ | |
| 247 | +int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 248 | + int (*io)(struct comedi_device *dev, int dir, int port, | |
| 249 | + int data, unsigned long regbase), | |
| 250 | + unsigned long regbase) | |
| 251 | +{ | |
| 252 | + return __subdev_8255_init(dev, s, io, regbase, true); | |
| 253 | +} | |
| 254 | +EXPORT_SYMBOL_GPL(subdev_8255_mm_init); | |
| 255 | + | |
| 256 | +/** | |
| 257 | + * subdev_8255_regbase - get offset of 8255 registers or call-back context | |
| 258 | + * @s: comedi subdevice | |
| 259 | + * | |
| 260 | + * Returns the 'regbase' parameter that was previously passed to to | |
| 261 | + * subdev_8255_init() or subdev_8255_mm_init() to set up the subdevice. | |
| 262 | + * Only valid if the subdevice was set up successfully. | |
| 263 | + */ | |
| 264 | +unsigned long subdev_8255_regbase(struct comedi_subdevice *s) | |
| 265 | +{ | |
| 266 | + struct subdev_8255_private *spriv = s->private; | |
| 267 | + | |
| 268 | + return spriv->regbase; | |
| 269 | +} | |
| 270 | +EXPORT_SYMBOL_GPL(subdev_8255_regbase); | |
| 271 | + | |
| 272 | +static int __init comedi_8255_module_init(void) | |
| 273 | +{ | |
| 274 | + return 0; | |
| 275 | +} | |
| 276 | +module_init(comedi_8255_module_init); | |
| 277 | + | |
| 278 | +static void __exit comedi_8255_module_exit(void) | |
| 279 | +{ | |
| 280 | +} | |
| 281 | +module_exit(comedi_8255_module_exit); | |
| 282 | + | |
| 283 | +MODULE_AUTHOR("Comedi http://www.comedi.org"); | |
| 284 | +MODULE_DESCRIPTION("Comedi: Generic 8255 digital I/O support"); | |
| 285 | +MODULE_LICENSE("GPL"); | |
| @@ -101,7 +101,8 @@ static int bonding_dio_insn_bits(struct comedi_device *dev, · 100 unmodified lines | ||
| 101 | 101 | b_chans = bdev->nchans - base_chan; |
| 102 | 102 | if (b_chans > n_left) |
| 103 | 103 | b_chans = n_left; |
| 104 | − b_mask = (1U << b_chans) - 1; | |
| 104 | + b_mask = (b_chans < 32) ? ((1 << b_chans) - 1) | |
| 105 | + : 0xffffffff; | |
| 105 | 106 | b_write_mask = (write_mask >> n_done) & b_mask; |
| 106 | 107 | b_data_bits = (data_bits >> n_done) & b_mask; |
| 107 | 108 | /* Read/Write the new digital lines. */ |
| @@ -16,6 +16,10 @@ · 15 unmodified lines | ||
| 16 | 16 | #ifndef _COMEDI_ISADMA_H |
| 17 | 17 | #define _COMEDI_ISADMA_H |
| 18 | 18 | |
| 19 | +#include <linux/types.h> | |
| 20 | + | |
| 21 | +struct comedi_device; | |
| 22 | + | |
| 19 | 23 | /* |
| 20 | 24 | * These are used to avoid issues when <asm/dma.h> and the DMA_MODE_ |
| 21 | 25 | * defines are not available. |
| @@ -1,105 +1,105 @@ | ||
| 1 | 1 | /* |
| 2 | − comedi/drivers/daqboard2000.c | |
| 3 | − hardware driver for IOtech DAQboard/2000 | |
| 4 | − | |
| 5 | − COMEDI - Linux Control and Measurement Device Interface | |
| 6 | − Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> | |
| 7 | − | |
| 8 | − This program is free software; you can redistribute it and/or modify | |
| 9 | − it under the terms of the GNU General Public License as published by | |
| 10 | − the Free Software Foundation; either version 2 of the License, or | |
| 11 | − (at your option) any later version. | |
| 12 | − | |
| 13 | − This program is distributed in the hope that it will be useful, | |
| 14 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − GNU General Public License for more details. | |
| 2 | + * comedi/drivers/daqboard2000.c | |
| 3 | + * hardware driver for IOtech DAQboard/2000 | |
| 4 | + * | |
| 5 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 6 | + * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | 17 | */ |
| 18 | 18 | /* |
| 19 | −Driver: daqboard2000 | |
| 20 | −Description: IOTech DAQBoard/2000 | |
| 21 | −Author: Anders Blomdell <anders.blomdell@control.lth.se> | |
| 22 | −Status: works | |
| 23 | −Updated: Mon, 14 Apr 2008 15:28:52 +0100 | |
| 24 | −Devices: [IOTech] DAQBoard/2000 (daqboard2000) | |
| 25 | − | |
| 26 | −Much of the functionality of this driver was determined from reading | |
| 27 | −the source code for the Windows driver. | |
| 28 | − | |
| 29 | −The FPGA on the board requires fimware, which is available from | |
| 30 | −http://www.comedi.org in the comedi_nonfree_firmware tarball. | |
| 31 | − | |
| 32 | −Configuration options: not applicable, uses PCI auto config | |
| 33 | −*/ | |
| 19 | + * Driver: daqboard2000 | |
| 20 | + * Description: IOTech DAQBoard/2000 | |
| 21 | + * Author: Anders Blomdell <anders.blomdell@control.lth.se> | |
| 22 | + * Status: works | |
| 23 | + * Updated: Mon, 14 Apr 2008 15:28:52 +0100 | |
| 24 | + * Devices: [IOTech] DAQBoard/2000 (daqboard2000) | |
| 25 | + * | |
| 26 | + * Much of the functionality of this driver was determined from reading | |
| 27 | + * the source code for the Windows driver. | |
| 28 | + * | |
| 29 | + * The FPGA on the board requires fimware, which is available from | |
| 30 | + * http://www.comedi.org in the comedi_nonfree_firmware tarball. | |
| 31 | + * | |
| 32 | + * Configuration options: not applicable, uses PCI auto config | |
| 33 | + */ | |
| 34 | 34 | /* |
| 35 | − This card was obviously never intended to leave the Windows world, | |
| 36 | − since it lacked all kind of hardware documentation (except for cable | |
| 37 | − pinouts, plug and pray has something to catch up with yet). | |
| 38 | − | |
| 39 | − With some help from our swedish distributor, we got the Windows sourcecode | |
| 40 | − for the card, and here are the findings so far. | |
| 41 | − | |
| 42 | − 1. A good document that describes the PCI interface chip is 9080db-106.pdf | |
| 43 | − available from http://www.plxtech.com/products/io/pci9080 | |
| 44 | − | |
| 45 | − 2. The initialization done so far is: | |
| 46 | − a. program the FPGA (windows code sans a lot of error messages) | |
| 47 | − b. | |
| 48 | − | |
| 49 | − 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, | |
| 50 | − you have to output values to all enabled DAC's until result appears, I | |
| 51 | − guess that it has something to do with pacer clocks, but the source | |
| 52 | − gives me no clues. I'll keep it simple so far. | |
| 53 | − | |
| 54 | − 4. Analog in. | |
| 55 | − Each channel in the scanlist seems to be controlled by four | |
| 56 | − control words: | |
| 57 | − | |
| 58 | − Word0: | |
| 59 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 60 | − ! | | | ! | | | ! | | | ! | | | ! | |
| 61 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 62 | − | |
| 63 | − Word1: | |
| 64 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 65 | − ! | | | ! | | | ! | | | ! | | | ! | |
| 66 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 67 | − | | | | | | | | |
| 68 | − +------+------+ | | | | +-- Digital input (??) | |
| 69 | − | | | | +---- 10 us settling time | |
| 70 | − | | | +------ Suspend acquisition (last to scan) | |
| 71 | − | | +-------- Simultaneous sample and hold | |
| 72 | − | +---------- Signed data format | |
| 73 | − +------------------------- Correction offset low | |
| 74 | − | |
| 75 | − Word2: | |
| 76 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 77 | − ! | | | ! | | | ! | | | ! | | | ! | |
| 78 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 79 | − | | | | | | | | | | | |
| 80 | − +-----+ +--+--+ +++ +++ +--+--+ | |
| 81 | − | | | | +----- Expansion channel | |
| 82 | − | | | +----------- Expansion gain | |
| 83 | − | | +--------------- Channel (low) | |
| 84 | − | +--------------------- Correction offset high | |
| 85 | − +----------------------------- Correction gain low | |
| 86 | − Word3: | |
| 87 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 88 | − ! | | | ! | | | ! | | | ! | | | ! | |
| 89 | − +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 90 | − | | | | | | | | | | |
| 91 | − +------+------+ | | +-+-+ | | +-- Low bank enable | |
| 92 | − | | | | | +---- High bank enable | |
| 93 | − | | | | +------ Hi/low select | |
| 94 | − | | | +---------- Gain (1,?,2,4,8,16,32,64) | |
| 95 | − | | +-------------- differential/single ended | |
| 96 | − | +---------------- Unipolar | |
| 97 | − +------------------------- Correction gain high | |
| 98 | − | |
| 99 | − 999. The card seems to have an incredible amount of capabilities, but | |
| 100 | − trying to reverse engineer them from the Windows source is beyond my | |
| 101 | − patience. | |
| 102 | − | |
| 35 | + * This card was obviously never intended to leave the Windows world, | |
| 36 | + * since it lacked all kind of hardware documentation (except for cable | |
| 37 | + * pinouts, plug and pray has something to catch up with yet). | |
| 38 | + * | |
| 39 | + * With some help from our swedish distributor, we got the Windows sourcecode | |
| 40 | + * for the card, and here are the findings so far. | |
| 41 | + * | |
| 42 | + * 1. A good document that describes the PCI interface chip is 9080db-106.pdf | |
| 43 | + * available from http://www.plxtech.com/products/io/pci9080 | |
| 44 | + * | |
| 45 | + * 2. The initialization done so far is: | |
| 46 | + * a. program the FPGA (windows code sans a lot of error messages) | |
| 47 | + * b. | |
| 48 | + * | |
| 49 | + * 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, | |
| 50 | + * you have to output values to all enabled DAC's until result appears, I | |
| 51 | + * guess that it has something to do with pacer clocks, but the source | |
| 52 | + * gives me no clues. I'll keep it simple so far. | |
| 53 | + * | |
| 54 | + * 4. Analog in. | |
| 55 | + * Each channel in the scanlist seems to be controlled by four | |
| 56 | + * control words: | |
| 57 | + * | |
| 58 | + * Word0: | |
| 59 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 60 | + * ! | | | ! | | | ! | | | ! | | | ! | |
| 61 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 62 | + * | |
| 63 | + * Word1: | |
| 64 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 65 | + * ! | | | ! | | | ! | | | ! | | | ! | |
| 66 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 67 | + * | | | | | | | | |
| 68 | + * +------+------+ | | | | +-- Digital input (??) | |
| 69 | + * | | | | +---- 10 us settling time | |
| 70 | + * | | | +------ Suspend acquisition (last to scan) | |
| 71 | + * | | +-------- Simultaneous sample and hold | |
| 72 | + * | +---------- Signed data format | |
| 73 | + * +------------------------- Correction offset low | |
| 74 | + * | |
| 75 | + * Word2: | |
| 76 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 77 | + * ! | | | ! | | | ! | | | ! | | | ! | |
| 78 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 79 | + * | | | | | | | | | | | |
| 80 | + * +-----+ +--+--+ +++ +++ +--+--+ | |
| 81 | + * | | | | +----- Expansion channel | |
| 82 | + * | | | +----------- Expansion gain | |
| 83 | + * | | +--------------- Channel (low) | |
| 84 | + * | +--------------------- Correction offset high | |
| 85 | + * +----------------------------- Correction gain low | |
| 86 | + * Word3: | |
| 87 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 88 | + * ! | | | ! | | | ! | | | ! | | | ! | |
| 89 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| 90 | + * | | | | | | | | | | |
| 91 | + * +------+------+ | | +-+-+ | | +-- Low bank enable | |
| 92 | + * | | | | | +---- High bank enable | |
| 93 | + * | | | | +------ Hi/low select | |
| 94 | + * | | | +---------- Gain (1,?,2,4,8,16,32,64) | |
| 95 | + * | | +-------------- differential/single ended | |
| 96 | + * | +---------------- Unipolar | |
| 97 | + * +------------------------- Correction gain high | |
| 98 | + * | |
| 99 | + * 999. The card seems to have an incredible amount of capabilities, but | |
| 100 | + * trying to reverse engineer them from the Windows source is beyond my | |
| 101 | + * patience. | |
| 102 | + * | |
| 103 | 103 | */ |
| 104 | 104 | |
| 105 | 105 | #include <linux/module.h> |
| @@ -1,21 +1,21 @@ | ||
| 1 | 1 | /* |
| 2 | − * comedi/drivers/das08.c | |
| 3 | − * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) | |
| 2 | + * comedi/drivers/das08.c | |
| 3 | + * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) | |
| 4 | 4 | * |
| 5 | − * COMEDI - Linux Control and Measurement Device Interface | |
| 6 | − * Copyright (C) 2000 David A. Schleef <ds@schleef.org> | |
| 7 | − * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> | |
| 8 | − * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org> | |
| 5 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 6 | + * Copyright (C) 2000 David A. Schleef <ds@schleef.org> | |
| 7 | + * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> | |
| 8 | + * Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org> | |
| 9 | 9 | * |
| 10 | − * This program is free software; you can redistribute it and/or modify | |
| 11 | − * it under the terms of the GNU General Public License as published by | |
| 12 | − * the Free Software Foundation; either version 2 of the License, or | |
| 13 | − * (at your option) any later version. | |
| 10 | + * This program is free software; you can redistribute it and/or modify | |
| 11 | + * it under the terms of the GNU General Public License as published by | |
| 12 | + * the Free Software Foundation; either version 2 of the License, or | |
| 13 | + * (at your option) any later version. | |
| 14 | 14 | * |
| 15 | − * This program is distributed in the hope that it will be useful, | |
| 16 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | − * GNU General Public License for more details. | |
| 15 | + * This program is distributed in the hope that it will be useful, | |
| 16 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 17 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 18 | + * GNU General Public License for more details. | |
| 19 | 19 | */ |
| 20 | 20 | |
| 21 | 21 | #include <linux/module.h> |
| @@ -27,85 +27,74 @@ · 5 unmodified lines | ||
| 27 | 27 | #include "das08.h" |
| 28 | 28 | |
| 29 | 29 | /* |
| 30 | − cio-das08.pdf | |
| 31 | − | |
| 32 | − "isa-das08" | |
| 33 | − | |
| 34 | − 0 a/d bits 0-3 start 8 bit | |
| 35 | − 1 a/d bits 4-11 start 12 bit | |
| 36 | − 2 eoc, ip1-3, irq, mux op1-4, inte, mux | |
| 37 | − 3 unused unused | |
| 38 | − 4567 8254 | |
| 39 | − 89ab 8255 | |
| 40 | − | |
| 41 | − requires hard-wiring for async ai | |
| 42 | − | |
| 43 | −*/ | |
| 44 | − | |
| 45 | −#define DAS08_LSB 0 | |
| 46 | −#define DAS08_MSB 1 | |
| 47 | −#define DAS08_TRIG_12BIT 1 | |
| 48 | −#define DAS08_STATUS 2 | |
| 49 | −#define DAS08_EOC (1<<7) | |
| 50 | −#define DAS08_IRQ (1<<3) | |
| 51 | −#define DAS08_IP(x) (((x)>>4)&0x7) | |
| 52 | −#define DAS08_CONTROL 2 | |
| 53 | −#define DAS08_MUX_MASK 0x7 | |
| 54 | −#define DAS08_MUX(x) ((x) & DAS08_MUX_MASK) | |
| 55 | −#define DAS08_INTE (1<<3) | |
| 56 | −#define DAS08_DO_MASK 0xf0 | |
| 57 | −#define DAS08_OP(x) (((x) << 4) & DAS08_DO_MASK) | |
| 58 | − | |
| 30 | + * Data format of DAS08_AI_LSB_REG and DAS08_AI_MSB_REG depends on | |
| 31 | + * 'ai_encoding' member of board structure: | |
| 32 | + * | |
| 33 | + * das08_encode12 : DATA[11..4] = MSB[7..0], DATA[3..0] = LSB[7..4]. | |
| 34 | + * das08_pcm_encode12 : DATA[11..8] = MSB[3..0], DATA[7..9] = LSB[7..0]. | |
| 35 | + * das08_encode16 : SIGN = MSB[7], MAGNITUDE[14..8] = MSB[6..0], | |
| 36 | + * MAGNITUDE[7..0] = LSB[7..0]. | |
| 37 | + * SIGN==0 for negative input, SIGN==1 for positive input. | |
| 38 | + * Note: when read a second time after conversion | |
| 39 | + * complete, MSB[7] is an "over-range" bit. | |
| 40 | + */ | |
| 41 | +#define DAS08_AI_LSB_REG 0x00 /* (R) AI least significant bits */ | |
| 42 | +#define DAS08_AI_MSB_REG 0x01 /* (R) AI most significant bits */ | |
| 43 | +#define DAS08_AI_TRIG_REG 0x01 /* (W) AI software trigger */ | |
| 44 | +#define DAS08_STATUS_REG 0x02 /* (R) status */ | |
| 45 | +#define DAS08_STATUS_AI_BUSY BIT(7) /* AI conversion in progress */ | |
| 59 | 46 | /* |
| 60 | − cio-das08jr.pdf | |
| 61 | − | |
| 62 | − "das08/jr-ao" | |
| 63 | − | |
| 64 | − 0 a/d bits 0-3 unused | |
| 65 | − 1 a/d bits 4-11 start 12 bit | |
| 66 | − 2 eoc, mux mux | |
| 67 | − 3 di do | |
| 68 | − 4 unused ao0_lsb | |
| 69 | − 5 unused ao0_msb | |
| 70 | − 6 unused ao1_lsb | |
| 71 | − 7 unused ao1_msb | |
| 72 | − | |
| 73 | −*/ | |
| 74 | − | |
| 75 | −#define DAS08JR_DIO 3 | |
| 76 | −#define DAS08JR_AO_LSB(x) ((x) ? 6 : 4) | |
| 77 | −#define DAS08JR_AO_MSB(x) ((x) ? 7 : 5) | |
| 47 | + * The IRQ status bit is set to 1 by a rising edge on the external interrupt | |
| 48 | + * input (which may be jumpered to the pacer output). It is cleared by | |
| 49 | + * setting the INTE control bit to 0. Not present on "JR" boards. | |
| 50 | + */ | |
| 51 | +#define DAS08_STATUS_IRQ BIT(3) /* latched interrupt input */ | |
| 52 | +/* digital inputs (not "JR" boards) */ | |
| 53 | +#define DAS08_STATUS_DI(x) (((x) & 0x70) >> 4) | |
| 54 | +#define DAS08_CONTROL_REG 0x02 /* (W) control */ | |
| 55 | +/* | |
| 56 | + * Note: The AI multiplexor channel can also be read from status register using | |
| 57 | + * the same mask. | |
| 58 | + */ | |
| 59 | +#define DAS08_CONTROL_MUX_MASK 0x7 /* multiplexor channel mask */ | |
| 60 | +#define DAS08_CONTROL_MUX(x) ((x) & DAS08_CONTROL_MUX_MASK) /* mux channel */ | |
| 61 | +#define DAS08_CONTROL_INTE BIT(3) /* interrupt enable (not "JR" boards) */ | |
| 62 | +#define DAS08_CONTROL_DO_MASK 0xf0 /* digital outputs mask (not "JR") */ | |
| 63 | +/* digital outputs (not "JR" boards) */ | |
| 64 | +#define DAS08_CONTROL_DO(x) (((x) << 4) & DAS08_CONTROL_DO_MASK) | |
| 65 | +/* | |
| 66 | + * (R/W) programmable AI gain ("PGx" and "AOx" boards): | |
| 67 | + * + bits 3..0 (R/W) show/set the gain for the current AI mux channel | |
| 68 | + * + bits 6..4 (R) show the current AI mux channel | |
| 69 | + * + bit 7 (R) not unused | |
| 70 | + */ | |
| 71 | +#define DAS08_GAIN_REG 0x03 | |
| 72 | + | |
| 73 | +#define DAS08JR_DI_REG 0x03 /* (R) digital inputs ("JR" boards) */ | |
| 74 | +#define DAS08JR_DO_REG 0x03 /* (W) digital outputs ("JR" boards) */ | |
| 75 | +/* (W) analog output l.s.b. registers for 2 channels ("JR" boards) */ | |
| 76 | +#define DAS08JR_AO_LSB_REG(x) ((x) ? 0x06 : 0x04) | |
| 77 | +/* (W) analog output m.s.b. registers for 2 channels ("JR" boards) */ | |
| 78 | +#define DAS08JR_AO_MSB_REG(x) ((x) ? 0x07 : 0x05) | |
| 79 | +/* | |
| 80 | + * (R) update analog outputs ("JR" boards set for simultaneous output) | |
| 81 | + * (same register as digital inputs) | |
| 82 | + */ | |
| 83 | +#define DAS08JR_AO_UPDATE_REG 0x03 | |
| 78 | 84 | |
| 85 | +/* (W) analog output l.s.b. registers for 2 channels ("AOx" boards) */ | |
| 86 | +#define DAS08AOX_AO_LSB_REG(x) ((x) ? 0x0a : 0x08) | |
| 87 | +/* (W) analog output m.s.b. registers for 2 channels ("AOx" boards) */ | |
| 88 | +#define DAS08AOX_AO_MSB_REG(x) ((x) ? 0x0b : 0x09) | |
| 79 | 89 | /* |
| 80 | − cio-das08_aox.pdf | |
| 81 | − | |
| 82 | − "das08-aoh" | |
| 83 | − "das08-aol" | |
| 84 | − "das08-aom" | |
| 85 | − | |
| 86 | − 0 a/d bits 0-3 start 8 bit | |
| 87 | − 1 a/d bits 4-11 start 12 bit | |
| 88 | − 2 eoc, ip1-3, irq, mux op1-4, inte, mux | |
| 89 | − 3 mux, gain status gain control | |
| 90 | − 4567 8254 | |
| 91 | − 8 unused ao0_lsb | |
| 92 | − 9 unused ao0_msb | |
| 93 | − a unused ao1_lsb | |
| 94 | − b unused ao1_msb | |
| 95 | − 89ab | |
| 96 | − cdef 8255 | |
| 97 | −*/ | |
| 98 | − | |
| 99 | −#define DAS08AO_GAIN_CONTROL 3 | |
| 100 | −#define DAS08AO_GAIN_STATUS 3 | |
| 101 | − | |
| 102 | −#define DAS08AO_AO_LSB(x) ((x) ? 0xa : 8) | |
| 103 | −#define DAS08AO_AO_MSB(x) ((x) ? 0xb : 9) | |
| 104 | −#define DAS08AO_AO_UPDATE 8 | |
| 90 | + * (R) update analog outputs ("AOx" boards set for simultaneous output) | |
| 91 | + * (any of the analog output registers could be used for this) | |
| 92 | + */ | |
| 93 | +#define DAS08AOX_AO_UPDATE_REG 0x08 | |
| 105 | 94 | |
| 106 | 95 | /* gainlist same as _pgx_ below */ |
| 107 | 96 | |
| 108 | −static const struct comedi_lrange range_das08_pgl = { | |
| 97 | +static const struct comedi_lrange das08_pgl_ai_range = { | |
| 109 | 98 | 9, { |
| 110 | 99 | BIP_RANGE(10), |
| 111 | 100 | BIP_RANGE(5), |
| @@ -119,7 +108,7 @@ static const struct comedi_lrange range_das08_pgl = { · 7 unmodified lines | ||
| 119 | 108 | } |
| 120 | 109 | }; |
| 121 | 110 | |
| 122 | −static const struct comedi_lrange range_das08_pgh = { | |
| 111 | +static const struct comedi_lrange das08_pgh_ai_range = { | |
| 123 | 112 | 12, { |
| 124 | 113 | BIP_RANGE(10), |
| 125 | 114 | BIP_RANGE(5), |
| @@ -136,7 +125,7 @@ static const struct comedi_lrange range_das08_pgh = { · 10 unmodified lines | ||
| 136 | 125 | } |
| 137 | 126 | }; |
| 138 | 127 | |
| 139 | −static const struct comedi_lrange range_das08_pgm = { | |
| 128 | +static const struct comedi_lrange das08_pgm_ai_range = { | |
| 140 | 129 | 9, { |
| 141 | 130 | BIP_RANGE(10), |
| 142 | 131 | BIP_RANGE(5), |
| @@ -148,42 +137,28 @@ static const struct comedi_lrange range_das08_pgm = { · 5 unmodified lines | ||
| 148 | 137 | UNI_RANGE(0.1), |
| 149 | 138 | UNI_RANGE(0.01) |
| 150 | 139 | } |
| 151 | −}; /* | |
| 152 | − cio-das08jr.pdf | |
| 153 | − | |
| 154 | − "das08/jr-ao" | |
| 155 | − | |
| 156 | − 0 a/d bits 0-3 unused | |
| 157 | − 1 a/d bits 4-11 start 12 bit | |
| 158 | − 2 eoc, mux mux | |
| 159 | − 3 di do | |
| 160 | − 4 unused ao0_lsb | |
| 161 | − 5 unused ao0_msb | |
| 162 | − 6 unused ao1_lsb | |
| 163 | − 7 unused ao1_msb | |
| 164 | − | |
| 165 | − */ | |
| 140 | +}; | |
| 166 | 141 | |
| 167 | 142 | static const struct comedi_lrange *const das08_ai_lranges[] = { |
| 168 | − &range_unknown, | |
| 169 | − &range_bipolar5, | |
| 170 | − &range_das08_pgh, | |
| 171 | − &range_das08_pgl, | |
| 172 | − &range_das08_pgm, | |
| 143 | + [das08_pg_none] = &range_unknown, | |
| 144 | + [das08_bipolar5] = &range_bipolar5, | |
| 145 | + [das08_pgh] = &das08_pgh_ai_range, | |
| 146 | + [das08_pgl] = &das08_pgl_ai_range, | |
| 147 | + [das08_pgm] = &das08_pgm_ai_range, | |
| 173 | 148 | }; |
| 174 | 149 | |
| 175 | −static const int das08_pgh_gainlist[] = { | |
| 150 | +static const int das08_pgh_ai_gainlist[] = { | |
| 176 | 151 | 8, 0, 10, 2, 12, 4, 14, 6, 1, 3, 5, 7 |
| 177 | 152 | }; |
| 178 | −static const int das08_pgl_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 }; | |
| 179 | −static const int das08_pgm_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 }; | |
| 180 | − | |
| 181 | −static const int *const das08_gainlists[] = { | |
| 182 | − NULL, | |
| 183 | − NULL, | |
| 184 | − das08_pgh_gainlist, | |
| 185 | − das08_pgl_gainlist, | |
| 186 | − das08_pgm_gainlist, | |
| 153 | +static const int das08_pgl_ai_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 }; | |
| 154 | +static const int das08_pgm_ai_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 }; | |
| 155 | + | |
| 156 | +static const int *const das08_ai_gainlists[] = { | |
| 157 | + [das08_pg_none] = NULL, | |
| 158 | + [das08_bipolar5] = NULL, | |
| 159 | + [das08_pgh] = das08_pgh_ai_gainlist, | |
| 160 | + [das08_pgl] = das08_pgl_ai_gainlist, | |
| 161 | + [das08_pgm] = das08_pgm_ai_gainlist, | |
| 187 | 162 | }; |
| 188 | 163 | |
| 189 | 164 | static int das08_ai_eoc(struct comedi_device *dev, |
| @@ -193,16 +168,17 @@ static int das08_ai_eoc(struct comedi_device *dev, · 3 unmodified lines | ||
| 193 | 168 | { |
| 194 | 169 | unsigned int status; |
| 195 | 170 | |
| 196 | − status = inb(dev->iobase + DAS08_STATUS); | |
| 197 | − if ((status & DAS08_EOC) == 0) | |
| 171 | + status = inb(dev->iobase + DAS08_STATUS_REG); | |
| 172 | + if ((status & DAS08_STATUS_AI_BUSY) == 0) | |
| 198 | 173 | return 0; |
| 199 | 174 | return -EBUSY; |
| 200 | 175 | } |
| 201 | 176 | |
| 202 | −static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 203 | − struct comedi_insn *insn, unsigned int *data) | |
| 177 | +static int das08_ai_insn_read(struct comedi_device *dev, | |
| 178 | + struct comedi_subdevice *s, | |
| 179 | + struct comedi_insn *insn, unsigned int *data) | |
| 204 | 180 | { |
| 205 | − const struct das08_board_struct *thisboard = dev->board_ptr; | |
| 181 | + const struct das08_board_struct *board = dev->board_ptr; | |
| 206 | 182 | struct das08_private_struct *devpriv = dev->private; |
| 207 | 183 | int n; |
| 208 | 184 | int chan; |
| @@ -214,49 +190,64 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 5 unmodified lines | ||
| 214 | 190 | range = CR_RANGE(insn->chanspec); |
| 215 | 191 | |
| 216 | 192 | /* clear crap */ |
| 217 | − inb(dev->iobase + DAS08_LSB); | |
| 218 | − inb(dev->iobase + DAS08_MSB); | |
| 193 | + inb(dev->iobase + DAS08_AI_LSB_REG); | |
| 194 | + inb(dev->iobase + DAS08_AI_MSB_REG); | |
| 219 | 195 | |
| 220 | 196 | /* set multiplexer */ |
| 221 | − /* lock to prevent race with digital output */ | |
| 197 | + /* lock to prevent race with digital output */ | |
| 222 | 198 | spin_lock(&dev->spinlock); |
| 223 | − devpriv->do_mux_bits &= ~DAS08_MUX_MASK; | |
| 224 | − devpriv->do_mux_bits |= DAS08_MUX(chan); | |
| 225 | − outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); | |
| 199 | + devpriv->do_mux_bits &= ~DAS08_CONTROL_MUX_MASK; | |
| 200 | + devpriv->do_mux_bits |= DAS08_CONTROL_MUX(chan); | |
| 201 | + outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL_REG); | |
| 226 | 202 | spin_unlock(&dev->spinlock); |
| 227 | 203 | |
| 228 | − if (s->range_table->length > 1) { | |
| 204 | + if (devpriv->pg_gainlist) { | |
| 229 | 205 | /* set gain/range */ |
| 230 | 206 | range = CR_RANGE(insn->chanspec); |
| 231 | 207 | outb(devpriv->pg_gainlist[range], |
| 232 | − dev->iobase + DAS08AO_GAIN_CONTROL); | |
| 208 | + dev->iobase + DAS08_GAIN_REG); | |
| 233 | 209 | } |
| 234 | 210 | |
| 235 | 211 | for (n = 0; n < insn->n; n++) { |
| 236 | 212 | /* clear over-range bits for 16-bit boards */ |
| 237 | − if (thisboard->ai_nbits == 16) | |
| 238 | − if (inb(dev->iobase + DAS08_MSB) & 0x80) | |
| 213 | + if (board->ai_nbits == 16) | |
| 214 | + if (inb(dev->iobase + DAS08_AI_MSB_REG) & 0x80) | |
| 239 | 215 | dev_info(dev->class_dev, "over-range\n"); |
| 240 | 216 | |
| 241 | 217 | /* trigger conversion */ |
| 242 | − outb_p(0, dev->iobase + DAS08_TRIG_12BIT); | |
| 218 | + outb_p(0, dev->iobase + DAS08_AI_TRIG_REG); | |
| 243 | 219 | |
| 244 | 220 | ret = comedi_timeout(dev, s, insn, das08_ai_eoc, 0); |
| 245 | 221 | if (ret) |
| 246 | 222 | return ret; |
| 247 | 223 | |
| 248 | − msb = inb(dev->iobase + DAS08_MSB); | |
| 249 | − lsb = inb(dev->iobase + DAS08_LSB); | |
| 250 | − if (thisboard->ai_encoding == das08_encode12) { | |
| 224 | + msb = inb(dev->iobase + DAS08_AI_MSB_REG); | |
| 225 | + lsb = inb(dev->iobase + DAS08_AI_LSB_REG); | |
| 226 | + if (board->ai_encoding == das08_encode12) { | |
| 251 | 227 | data[n] = (lsb >> 4) | (msb << 4); |
| 252 | − } else if (thisboard->ai_encoding == das08_pcm_encode12) { | |
| 228 | + } else if (board->ai_encoding == das08_pcm_encode12) { | |
| 253 | 229 | data[n] = (msb << 8) + lsb; |
| 254 | − } else if (thisboard->ai_encoding == das08_encode16) { | |
| 255 | − /* FPOS 16-bit boards are sign-magnitude */ | |
| 230 | + } else if (board->ai_encoding == das08_encode16) { | |
| 231 | + /* | |
| 232 | + * "JR" 16-bit boards are sign-magnitude. | |
| 233 | + * | |
| 234 | + * XXX The manual seems to imply that 0 is full-scale | |
| 235 | + * negative and 65535 is full-scale positive, but the | |
| 236 | + * original COMEDI patch to add support for the | |
| 237 | + * DAS08/JR/16 and DAS08/JR/16-AO boards have it | |
| 238 | + * encoded as sign-magnitude. Assume the original | |
| 239 | + * COMEDI code is correct for now. | |
| 240 | + */ | |
| 241 | + unsigned int magnitude = lsb | ((msb & 0x7f) << 8); | |
| 242 | + | |
| 243 | + /* | |
| 244 | + * MSB bit 7 is 0 for negative, 1 for positive voltage. | |
| 245 | + * COMEDI 16-bit bipolar data value for 0V is 0x8000. | |
| 246 | + */ | |
| 256 | 247 | if (msb & 0x80) |
| 257 | − data[n] = (1 << 15) | lsb | ((msb & 0x7f) << 8); | |
| 248 | + data[n] = (1 << 15) + magnitude; | |
| 258 | 249 | else |
| 259 | − data[n] = (1 << 15) - (lsb | (msb & 0x7f) << 8); | |
| 250 | + data[n] = (1 << 15) - magnitude; | |
| 260 | 251 | } else { |
| 261 | 252 | dev_err(dev->class_dev, "bug! unknown ai encoding\n"); |
| 262 | 253 | return -1; |
| @@ -266,28 +257,28 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 3 unmodified lines | ||
| 266 | 257 | return n; |
| 267 | 258 | } |
| 268 | 259 | |
| 269 | −static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, | |
| 270 | − struct comedi_insn *insn, unsigned int *data) | |
| 260 | +static int das08_di_insn_bits(struct comedi_device *dev, | |
| 261 | + struct comedi_subdevice *s, | |
| 262 | + struct comedi_insn *insn, unsigned int *data) | |
| 271 | 263 | { |
| 272 | 264 | data[0] = 0; |
| 273 | − data[1] = DAS08_IP(inb(dev->iobase + DAS08_STATUS)); | |
| 265 | + data[1] = DAS08_STATUS_DI(inb(dev->iobase + DAS08_STATUS_REG)); | |
| 274 | 266 | |
| 275 | 267 | return insn->n; |
| 276 | 268 | } |
| 277 | 269 | |
| 278 | −static int das08_do_wbits(struct comedi_device *dev, | |
| 279 | − struct comedi_subdevice *s, | |
| 280 | − struct comedi_insn *insn, | |
| 281 | − unsigned int *data) | |
| 270 | +static int das08_do_insn_bits(struct comedi_device *dev, | |
| 271 | + struct comedi_subdevice *s, | |
| 272 | + struct comedi_insn *insn, unsigned int *data) | |
| 282 | 273 | { |
| 283 | 274 | struct das08_private_struct *devpriv = dev->private; |
| 284 | 275 | |
| 285 | 276 | if (comedi_dio_update_state(s, data)) { |
| 286 | 277 | /* prevent race with setting of analog input mux */ |
| 287 | 278 | spin_lock(&dev->spinlock); |
| 288 | − devpriv->do_mux_bits &= ~DAS08_DO_MASK; | |
| 289 | − devpriv->do_mux_bits |= DAS08_OP(s->state); | |
| 290 | − outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); | |
| 279 | + devpriv->do_mux_bits &= ~DAS08_CONTROL_DO_MASK; | |
| 280 | + devpriv->do_mux_bits |= DAS08_CONTROL_DO(s->state); | |
| 281 | + outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL_REG); | |
| 291 | 282 | spin_unlock(&dev->spinlock); |
| 292 | 283 | } |
| 293 | 284 | |
| @@ -296,23 +287,22 @@ static int das08_do_wbits(struct comedi_device *dev, · 2 unmodified lines | ||
| 296 | 287 | return insn->n; |
| 297 | 288 | } |
| 298 | 289 | |
| 299 | −static int das08jr_di_rbits(struct comedi_device *dev, | |
| 300 | − struct comedi_subdevice *s, | |
| 301 | − struct comedi_insn *insn, unsigned int *data) | |
| 290 | +static int das08jr_di_insn_bits(struct comedi_device *dev, | |
| 291 | + struct comedi_subdevice *s, | |
| 292 | + struct comedi_insn *insn, unsigned int *data) | |
| 302 | 293 | { |
| 303 | 294 | data[0] = 0; |
| 304 | − data[1] = inb(dev->iobase + DAS08JR_DIO); | |
| 295 | + data[1] = inb(dev->iobase + DAS08JR_DI_REG); | |
| 305 | 296 | |
| 306 | 297 | return insn->n; |
| 307 | 298 | } |
| 308 | 299 | |
| 309 | −static int das08jr_do_wbits(struct comedi_device *dev, | |
| 310 | − struct comedi_subdevice *s, | |
| 311 | − struct comedi_insn *insn, | |
| 312 | − unsigned int *data) | |
| 300 | +static int das08jr_do_insn_bits(struct comedi_device *dev, | |
| 301 | + struct comedi_subdevice *s, | |
| 302 | + struct comedi_insn *insn, unsigned int *data) | |
| 313 | 303 | { |
| 314 | 304 | if (comedi_dio_update_state(s, data)) |
| 315 | − outb(s->state, dev->iobase + DAS08JR_DIO); | |
| 305 | + outb(s->state, dev->iobase + DAS08JR_DO_REG); | |
| 316 | 306 | |
| 317 | 307 | data[1] = s->state; |
| 318 | 308 | |
| @@ -322,22 +312,22 @@ static int das08jr_do_wbits(struct comedi_device *dev, · 3 unmodified lines | ||
| 322 | 312 | static void das08_ao_set_data(struct comedi_device *dev, |
| 323 | 313 | unsigned int chan, unsigned int data) |
| 324 | 314 | { |
| 325 | − const struct das08_board_struct *thisboard = dev->board_ptr; | |
| 315 | + const struct das08_board_struct *board = dev->board_ptr; | |
| 326 | 316 | unsigned char lsb; |
| 327 | 317 | unsigned char msb; |
| 328 | 318 | |
| 329 | 319 | lsb = data & 0xff; |
| 330 | 320 | msb = (data >> 8) & 0xff; |
| 331 | − if (thisboard->is_jr) { | |
| 332 | − outb(lsb, dev->iobase + DAS08JR_AO_LSB(chan)); | |
| 333 | − outb(msb, dev->iobase + DAS08JR_AO_MSB(chan)); | |
| 321 | + if (board->is_jr) { | |
| 322 | + outb(lsb, dev->iobase + DAS08JR_AO_LSB_REG(chan)); | |
| 323 | + outb(msb, dev->iobase + DAS08JR_AO_MSB_REG(chan)); | |
| 334 | 324 | /* load DACs */ |
| 335 | − inb(dev->iobase + DAS08JR_DIO); | |
| 325 | + inb(dev->iobase + DAS08JR_AO_UPDATE_REG); | |
| 336 | 326 | } else { |
| 337 | − outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan)); | |
| 338 | − outb(msb, dev->iobase + DAS08AO_AO_MSB(chan)); | |
| 327 | + outb(lsb, dev->iobase + DAS08AOX_AO_LSB_REG(chan)); | |
| 328 | + outb(msb, dev->iobase + DAS08AOX_AO_MSB_REG(chan)); | |
| 339 | 329 | /* load DACs */ |
| 340 | − inb(dev->iobase + DAS08AO_AO_UPDATE); | |
| 330 | + inb(dev->iobase + DAS08AOX_AO_UPDATE_REG); | |
| 341 | 331 | } |
| 342 | 332 | } |
| 343 | 333 | |
| @@ -361,7 +351,7 @@ static int das08_ao_insn_write(struct comedi_device *dev, · 17 unmodified lines | ||
| 361 | 351 | |
| 362 | 352 | int das08_common_attach(struct comedi_device *dev, unsigned long iobase) |
| 363 | 353 | { |
| 364 | − const struct das08_board_struct *thisboard = dev->board_ptr; | |
| 354 | + const struct das08_board_struct *board = dev->board_ptr; | |
| 365 | 355 | struct das08_private_struct *devpriv = dev->private; |
| 366 | 356 | struct comedi_subdevice *s; |
| 367 | 357 | int ret; |
| @@ -369,7 +359,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) · 1 unmodified line | ||
| 369 | 359 | |
| 370 | 360 | dev->iobase = iobase; |
| 371 | 361 | |
| 372 | − dev->board_name = thisboard->name; | |
| 362 | + dev->board_name = board->name; | |
| 373 | 363 | |
| 374 | 364 | ret = comedi_alloc_subdevices(dev, 6); |
| 375 | 365 | if (ret) |
| @@ -377,30 +367,31 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) · 1 unmodified line | ||
| 377 | 367 | |
| 378 | 368 | s = &dev->subdevices[0]; |
| 379 | 369 | /* ai */ |
| 380 | − if (thisboard->ai_nbits) { | |
| 370 | + if (board->ai_nbits) { | |
| 381 | 371 | s->type = COMEDI_SUBD_AI; |
| 382 | − /* XXX some boards actually have differential | |
| 372 | + /* | |
| 373 | + * XXX some boards actually have differential | |
| 383 | 374 | * inputs instead of single ended. |
| 384 | 375 | * The driver does nothing with arefs though, |
| 385 | 376 | * so it's no big deal. |
| 386 | 377 | */ |
| 387 | 378 | s->subdev_flags = SDF_READABLE | SDF_GROUND; |
| 388 | 379 | s->n_chan = 8; |
| 389 | − s->maxdata = (1 << thisboard->ai_nbits) - 1; | |
| 390 | − s->range_table = das08_ai_lranges[thisboard->ai_pg]; | |
| 391 | − s->insn_read = das08_ai_rinsn; | |
| 392 | − devpriv->pg_gainlist = das08_gainlists[thisboard->ai_pg]; | |
| 380 | + s->maxdata = (1 << board->ai_nbits) - 1; | |
| 381 | + s->range_table = das08_ai_lranges[board->ai_pg]; | |
| 382 | + s->insn_read = das08_ai_insn_read; | |
| 383 | + devpriv->pg_gainlist = das08_ai_gainlists[board->ai_pg]; | |
| 393 | 384 | } else { |
| 394 | 385 | s->type = COMEDI_SUBD_UNUSED; |
| 395 | 386 | } |
| 396 | 387 | |
| 397 | 388 | s = &dev->subdevices[1]; |
| 398 | 389 | /* ao */ |
| 399 | − if (thisboard->ao_nbits) { | |
| 390 | + if (board->ao_nbits) { | |
| 400 | 391 | s->type = COMEDI_SUBD_AO; |
| 401 | 392 | s->subdev_flags = SDF_WRITABLE; |
| 402 | 393 | s->n_chan = 2; |
| 403 | − s->maxdata = (1 << thisboard->ao_nbits) - 1; | |
| 394 | + s->maxdata = (1 << board->ao_nbits) - 1; | |
| 404 | 395 | s->range_table = &range_bipolar5; |
| 405 | 396 | s->insn_write = das08_ao_insn_write; |
| 406 | 397 | |
| @@ -419,36 +410,36 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) · 12 unmodified lines | ||
| 419 | 410 | |
| 420 | 411 | s = &dev->subdevices[2]; |
| 421 | 412 | /* di */ |
| 422 | − if (thisboard->di_nchan) { | |
| 413 | + if (board->di_nchan) { | |
| 423 | 414 | s->type = COMEDI_SUBD_DI; |
| 424 | 415 | s->subdev_flags = SDF_READABLE; |
| 425 | − s->n_chan = thisboard->di_nchan; | |
| 416 | + s->n_chan = board->di_nchan; | |
| 426 | 417 | s->maxdata = 1; |
| 427 | 418 | s->range_table = &range_digital; |
| 428 | − s->insn_bits = | |
| 429 | − thisboard->is_jr ? das08jr_di_rbits : das08_di_rbits; | |
| 419 | + s->insn_bits = board->is_jr ? das08jr_di_insn_bits : | |
| 420 | + das08_di_insn_bits; | |
| 430 | 421 | } else { |
| 431 | 422 | s->type = COMEDI_SUBD_UNUSED; |
| 432 | 423 | } |
| 433 | 424 | |
| 434 | 425 | s = &dev->subdevices[3]; |
| 435 | 426 | /* do */ |
| 436 | − if (thisboard->do_nchan) { | |
| 427 | + if (board->do_nchan) { | |
| 437 | 428 | s->type = COMEDI_SUBD_DO; |
| 438 | 429 | s->subdev_flags = SDF_WRITABLE; |
| 439 | − s->n_chan = thisboard->do_nchan; | |
| 430 | + s->n_chan = board->do_nchan; | |
| 440 | 431 | s->maxdata = 1; |
| 441 | 432 | s->range_table = &range_digital; |
| 442 | − s->insn_bits = | |
| 443 | − thisboard->is_jr ? das08jr_do_wbits : das08_do_wbits; | |
| 433 | + s->insn_bits = board->is_jr ? das08jr_do_insn_bits : | |
| 434 | + das08_do_insn_bits; | |
| 444 | 435 | } else { |
| 445 | 436 | s->type = COMEDI_SUBD_UNUSED; |
| 446 | 437 | } |
| 447 | 438 | |
| 448 | 439 | s = &dev->subdevices[4]; |
| 449 | 440 | /* 8255 */ |
| 450 | − if (thisboard->i8255_offset != 0) { | |
| 451 | − ret = subdev_8255_init(dev, s, NULL, thisboard->i8255_offset); | |
| 441 | + if (board->i8255_offset != 0) { | |
| 442 | + ret = subdev_8255_init(dev, s, NULL, board->i8255_offset); | |
| 452 | 443 | if (ret) |
| 453 | 444 | return ret; |
| 454 | 445 | } else { |
| @@ -457,9 +448,8 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) · 2 unmodified lines | ||
| 457 | 448 | |
| 458 | 449 | /* Counter subdevice (8254) */ |
| 459 | 450 | s = &dev->subdevices[5]; |
| 460 | − if (thisboard->i8254_offset) { | |
| 461 | − dev->pacer = comedi_8254_init(dev->iobase + | |
| 462 | − thisboard->i8254_offset, | |
| 451 | + if (board->i8254_offset) { | |
| 452 | + dev->pacer = comedi_8254_init(dev->iobase + board->i8254_offset, | |
| 463 | 453 | 0, I8254_IO8, 0); |
| 464 | 454 | if (!dev->pacer) |
| 465 | 455 | return -ENOMEM; |
| @@ -485,5 +475,5 @@ static void __exit das08_exit(void) · 19 unmodified lines | ||
| 485 | 475 | module_exit(das08_exit); |
| 486 | 476 | |
| 487 | 477 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 488 | −MODULE_DESCRIPTION("Comedi low-level driver"); | |
| 478 | +MODULE_DESCRIPTION("Comedi common DAS08 support module"); | |
| 489 | 479 | MODULE_LICENSE("GPL"); |
| @@ -1,28 +1,33 @@ | ||
| 1 | 1 | /* |
| 2 | − das08.h | |
| 3 | − | |
| 4 | − Header for das08.c and das08_cs.c | |
| 5 | − | |
| 6 | − Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> | |
| 7 | − | |
| 8 | − This program is free software; you can redistribute it and/or modify | |
| 9 | − it under the terms of the GNU General Public License as published by | |
| 10 | − the Free Software Foundation; either version 2 of the License, or | |
| 11 | − (at your option) any later version. | |
| 12 | − | |
| 13 | − This program is distributed in the hope that it will be useful, | |
| 14 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − GNU General Public License for more details. | |
| 17 | −*/ | |
| 2 | + * das08.h | |
| 3 | + * | |
| 4 | + * Header for common DAS08 support (used by ISA/PCI/PCMCIA drivers) | |
| 5 | + * | |
| 6 | + * Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + */ | |
| 18 | 18 | |
| 19 | 19 | #ifndef _DAS08_H |
| 20 | 20 | #define _DAS08_H |
| 21 | 21 | |
| 22 | +#include <linux/types.h> | |
| 23 | + | |
| 24 | +struct comedi_device; | |
| 25 | + | |
| 22 | 26 | /* different ways ai data is encoded in first two registers */ |
| 23 | 27 | enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 }; |
| 24 | −enum das08_lrange { das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, | |
| 25 | − das08_pgm | |
| 28 | +/* types of ai range table used by different boards */ | |
| 29 | +enum das08_lrange { | |
| 30 | + das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, das08_pgm | |
| 26 | 31 | }; |
| 27 | 32 | |
| 28 | 33 | struct das08_board_struct { |
| @@ -36,13 +41,12 @@ struct das08_board_struct { · 7 unmodified lines | ||
| 36 | 41 | unsigned int do_nchan; |
| 37 | 42 | unsigned int i8255_offset; |
| 38 | 43 | unsigned int i8254_offset; |
| 39 | − unsigned int iosize; /* number of ioports used */ | |
| 44 | + unsigned int iosize; /* number of ioports used */ | |
| 40 | 45 | }; |
| 41 | 46 | |
| 42 | 47 | struct das08_private_struct { |
| 43 | − unsigned int do_mux_bits; /* bits for do/mux register on boards | |
| 44 | − * without separate do register | |
| 45 | − */ | |
| 48 | + /* bits for do/mux register on boards without separate do register */ | |
| 49 | + unsigned int do_mux_bits; | |
| 46 | 50 | const unsigned int *pg_gainlist; |
| 47 | 51 | }; |
| 48 | 52 | |
| @@ -168,7 +168,7 @@ static const struct das08_board_struct das08_isa_boards[] = { · 167 unmodified lines | ||
| 168 | 168 | static int das08_isa_attach(struct comedi_device *dev, |
| 169 | 169 | struct comedi_devconfig *it) |
| 170 | 170 | { |
| 171 | − const struct das08_board_struct *thisboard = dev->board_ptr; | |
| 171 | + const struct das08_board_struct *board = dev->board_ptr; | |
| 172 | 172 | struct das08_private_struct *devpriv; |
| 173 | 173 | int ret; |
| 174 | 174 | |
| @@ -176,7 +176,7 @@ static int das08_isa_attach(struct comedi_device *dev, · 1 unmodified line | ||
| 176 | 176 | if (!devpriv) |
| 177 | 177 | return -ENOMEM; |
| 178 | 178 | |
| 179 | − ret = comedi_request_region(dev, it->options[0], thisboard->iosize); | |
| 179 | + ret = comedi_request_region(dev, it->options[0], board->iosize); | |
| 180 | 180 | if (ret) |
| 181 | 181 | return ret; |
| 182 | 182 | |
| @@ -46,8 +46,8 @@ list has 2 or more channels in it, then two conditions must be satisfied: · 45 unmodified lines | ||
| 46 | 46 | (2) - the list must have an even number of entries. |
| 47 | 47 | |
| 48 | 48 | Options: |
| 49 | − [0] - base io address | |
| 50 | − [1] - irq (optional, but you probably want it) | |
| 49 | + [0] - base io address | |
| 50 | + [1] - irq (optional, but you probably want it) | |
| 51 | 51 | |
| 52 | 52 | irq can be omitted, although the cmd interface will not work without it. |
| 53 | 53 | */ |
| @@ -444,9 +444,9 @@ static const struct comedi_lrange range_ao_2 = { · 443 unmodified lines | ||
| 444 | 444 | static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, |
| 445 | 445 | uint16_t sample) |
| 446 | 446 | { |
| 447 | − const struct das1800_board *thisboard = dev->board_ptr; | |
| 447 | + const struct das1800_board *board = dev->board_ptr; | |
| 448 | 448 | |
| 449 | − sample += 1 << (thisboard->resolution - 1); | |
| 449 | + sample += 1 << (board->resolution - 1); | |
| 450 | 450 | return sample; |
| 451 | 451 | } |
| 452 | 452 | |
| @@ -725,7 +725,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, · 272 unmodified lines | ||
| 725 | 725 | struct comedi_subdevice *s, |
| 726 | 726 | struct comedi_cmd *cmd) |
| 727 | 727 | { |
| 728 | − const struct das1800_board *thisboard = dev->board_ptr; | |
| 728 | + const struct das1800_board *board = dev->board_ptr; | |
| 729 | 729 | int err = 0; |
| 730 | 730 | unsigned int arg; |
| 731 | 731 | |
| @@ -765,7 +765,7 @@ static int das1800_ai_do_cmdtest(struct comedi_device *dev, · 33 unmodified lines | ||
| 765 | 765 | |
| 766 | 766 | if (cmd->convert_src == TRIG_TIMER) { |
| 767 | 767 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 768 | − thisboard->ai_speed); | |
| 768 | + board->ai_speed); | |
| 769 | 769 | } |
| 770 | 770 | |
| 771 | 771 | err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); |
| @@ -1048,7 +1048,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, · 276 unmodified lines | ||
| 1048 | 1048 | struct comedi_subdevice *s, |
| 1049 | 1049 | struct comedi_insn *insn, unsigned int *data) |
| 1050 | 1050 | { |
| 1051 | − const struct das1800_board *thisboard = dev->board_ptr; | |
| 1051 | + const struct das1800_board *board = dev->board_ptr; | |
| 1052 | 1052 | int i, n; |
| 1053 | 1053 | int chan, range, aref, chan_range; |
| 1054 | 1054 | int timeout = 1000; |
| @@ -1098,7 +1098,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, · 43 unmodified lines | ||
| 1098 | 1098 | dpnt = inw(dev->iobase + DAS1800_FIFO); |
| 1099 | 1099 | /* shift data to offset binary for bipolar ranges */ |
| 1100 | 1100 | if ((conv_flags & UB) == 0) |
| 1101 | − dpnt += 1 << (thisboard->resolution - 1); | |
| 1101 | + dpnt += 1 << (board->resolution - 1); | |
| 1102 | 1102 | data[n] = dpnt; |
| 1103 | 1103 | } |
| 1104 | 1104 | exit: |
| @@ -1112,16 +1112,16 @@ static int das1800_ao_winsn(struct comedi_device *dev, · 7 unmodified lines | ||
| 1112 | 1112 | struct comedi_subdevice *s, |
| 1113 | 1113 | struct comedi_insn *insn, unsigned int *data) |
| 1114 | 1114 | { |
| 1115 | − const struct das1800_board *thisboard = dev->board_ptr; | |
| 1115 | + const struct das1800_board *board = dev->board_ptr; | |
| 1116 | 1116 | struct das1800_private *devpriv = dev->private; |
| 1117 | 1117 | int chan = CR_CHAN(insn->chanspec); |
| 1118 | 1118 | /* int range = CR_RANGE(insn->chanspec); */ |
| 1119 | − int update_chan = thisboard->ao_n_chan - 1; | |
| 1119 | + int update_chan = board->ao_n_chan - 1; | |
| 1120 | 1120 | unsigned short output; |
| 1121 | 1121 | unsigned long irq_flags; |
| 1122 | 1122 | |
| 1123 | 1123 | /* card expects two's complement data */ |
| 1124 | − output = data[0] - (1 << (thisboard->resolution - 1)); | |
| 1124 | + output = data[0] - (1 << (board->resolution - 1)); | |
| 1125 | 1125 | /* if the write is to the 'update' channel, we need to remember its value */ |
| 1126 | 1126 | if (chan == update_chan) |
| 1127 | 1127 | devpriv->ao_update_bits = output; |
| @@ -1216,72 +1216,76 @@ static void das1800_free_dma(struct comedi_device *dev) · 88 unmodified lines | ||
| 1216 | 1216 | comedi_isadma_free(devpriv->dma); |
| 1217 | 1217 | } |
| 1218 | 1218 | |
| 1219 | −static int das1800_probe(struct comedi_device *dev) | |
| 1219 | +static const struct das1800_board *das1800_probe(struct comedi_device *dev) | |
| 1220 | 1220 | { |
| 1221 | 1221 | const struct das1800_board *board = dev->board_ptr; |
| 1222 | − int index; | |
| 1222 | + int index = board ? board - das1800_boards : -EINVAL; | |
| 1223 | 1223 | int id; |
| 1224 | 1224 | |
| 1225 | − /* calc the offset to the boardinfo that was found by the core */ | |
| 1226 | − index = board - das1800_boards; | |
| 1227 | − | |
| 1228 | − /* verify that the board id matches the boardinfo */ | |
| 1225 | + /* | |
| 1226 | + * The dev->board_ptr will be set by comedi_device_attach() if the | |
| 1227 | + * board name provided by the user matches a board->name in this | |
| 1228 | + * driver. If so, this function sanity checks the id to verify that | |
| 1229 | + * the board is correct. | |
| 1230 | + * | |
| 1231 | + * If the dev->board_ptr is not set, the user is trying to attach | |
| 1232 | + * an unspecified board to this driver. In this case the id is used | |
| 1233 | + * to 'probe' for the correct dev->board_ptr. | |
| 1234 | + */ | |
| 1229 | 1235 | id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; |
| 1230 | 1236 | switch (id) { |
| 1231 | 1237 | case 0x3: |
| 1232 | 1238 | if (index == das1801st_da || index == das1802st_da || |
| 1233 | 1239 | index == das1701st_da || index == das1702st_da) |
| 1234 | − return index; | |
| 1240 | + return board; | |
| 1235 | 1241 | index = das1801st; |
| 1236 | 1242 | break; |
| 1237 | 1243 | case 0x4: |
| 1238 | 1244 | if (index == das1802hr_da || index == das1702hr_da) |
| 1239 | − return index; | |
| 1245 | + return board; | |
| 1240 | 1246 | index = das1802hr; |
| 1241 | 1247 | break; |
| 1242 | 1248 | case 0x5: |
| 1243 | 1249 | if (index == das1801ao || index == das1802ao || |
| 1244 | 1250 | index == das1701ao || index == das1702ao) |
| 1245 | − return index; | |
| 1251 | + return board; | |
| 1246 | 1252 | index = das1801ao; |
| 1247 | 1253 | break; |
| 1248 | 1254 | case 0x6: |
| 1249 | 1255 | if (index == das1802hr || index == das1702hr) |
| 1250 | − return index; | |
| 1256 | + return board; | |
| 1251 | 1257 | index = das1802hr; |
| 1252 | 1258 | break; |
| 1253 | 1259 | case 0x7: |
| 1254 | 1260 | if (index == das1801st || index == das1802st || |
| 1255 | 1261 | index == das1701st || index == das1702st) |
| 1256 | − return index; | |
| 1262 | + return board; | |
| 1257 | 1263 | index = das1801st; |
| 1258 | 1264 | break; |
| 1259 | 1265 | case 0x8: |
| 1260 | 1266 | if (index == das1801hc || index == das1802hc) |
| 1261 | − return index; | |
| 1267 | + return board; | |
| 1262 | 1268 | index = das1801hc; |
| 1263 | − break; | |
| 1264 | 1269 | default: |
| 1265 | 1270 | dev_err(dev->class_dev, |
| 1266 | 1271 | "Board model: probe returned 0x%x (unknown, please report)\n", |
| 1267 | 1272 | id); |
| 1268 | − break; | |
| 1273 | + return NULL; | |
| 1269 | 1274 | } |
| 1270 | 1275 | dev_err(dev->class_dev, |
| 1271 | 1276 | "Board model (probed, not recommended): %s series\n", |
| 1272 | 1277 | das1800_boards[index].name); |
| 1273 | 1278 | |
| 1274 | − return index; | |
| 1279 | + return &das1800_boards[index]; | |
| 1275 | 1280 | } |
| 1276 | 1281 | |
| 1277 | 1282 | static int das1800_attach(struct comedi_device *dev, |
| 1278 | 1283 | struct comedi_devconfig *it) |
| 1279 | 1284 | { |
| 1280 | − const struct das1800_board *thisboard; | |
| 1285 | + const struct das1800_board *board; | |
| 1281 | 1286 | struct das1800_private *devpriv; |
| 1282 | 1287 | struct comedi_subdevice *s; |
| 1283 | 1288 | unsigned int irq = it->options[1]; |
| 1284 | − int board; | |
| 1285 | 1289 | int ret; |
| 1286 | 1290 | |
| 1287 | 1291 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| @@ -1293,17 +1297,15 @@ static int das1800_attach(struct comedi_device *dev, · 5 unmodified lines | ||
| 1293 | 1297 | return ret; |
| 1294 | 1298 | |
| 1295 | 1299 | board = das1800_probe(dev); |
| 1296 | − if (board < 0) { | |
| 1300 | + if (!board) { | |
| 1297 | 1301 | dev_err(dev->class_dev, "unable to determine board type\n"); |
| 1298 | 1302 | return -ENODEV; |
| 1299 | 1303 | } |
| 1300 | − | |
| 1301 | − dev->board_ptr = das1800_boards + board; | |
| 1302 | − thisboard = dev->board_ptr; | |
| 1303 | − dev->board_name = thisboard->name; | |
| 1304 | + dev->board_ptr = board; | |
| 1305 | + dev->board_name = board->name; | |
| 1304 | 1306 | |
| 1305 | 1307 | /* if it is an 'ao' board with fancy analog out then we need extra io ports */ |
| 1306 | − if (thisboard->ao_ability == 2) { | |
| 1308 | + if (board->ao_ability == 2) { | |
| 1307 | 1309 | unsigned long iobase2 = dev->iobase + IOBASE2; |
| 1308 | 1310 | |
| 1309 | 1311 | ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE); |
| @@ -1363,11 +1365,11 @@ static int das1800_attach(struct comedi_device *dev, · 53 unmodified lines | ||
| 1363 | 1365 | s = &dev->subdevices[0]; |
| 1364 | 1366 | s->type = COMEDI_SUBD_AI; |
| 1365 | 1367 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; |
| 1366 | − if (thisboard->common) | |
| 1368 | + if (board->common) | |
| 1367 | 1369 | s->subdev_flags |= SDF_COMMON; |
| 1368 | − s->n_chan = thisboard->qram_len; | |
| 1369 | − s->maxdata = (1 << thisboard->resolution) - 1; | |
| 1370 | − s->range_table = thisboard->range_ai; | |
| 1370 | + s->n_chan = board->qram_len; | |
| 1371 | + s->maxdata = (1 << board->resolution) - 1; | |
| 1372 | + s->range_table = board->range_ai; | |
| 1371 | 1373 | s->insn_read = das1800_ai_rinsn; |
| 1372 | 1374 | if (dev->irq) { |
| 1373 | 1375 | dev->read_subdev = s; |
| @@ -1381,11 +1383,11 @@ static int das1800_attach(struct comedi_device *dev, · 7 unmodified lines | ||
| 1381 | 1383 | |
| 1382 | 1384 | /* analog out */ |
| 1383 | 1385 | s = &dev->subdevices[1]; |
| 1384 | − if (thisboard->ao_ability == 1) { | |
| 1386 | + if (board->ao_ability == 1) { | |
| 1385 | 1387 | s->type = COMEDI_SUBD_AO; |
| 1386 | 1388 | s->subdev_flags = SDF_WRITABLE; |
| 1387 | − s->n_chan = thisboard->ao_n_chan; | |
| 1388 | − s->maxdata = (1 << thisboard->resolution) - 1; | |
| 1389 | + s->n_chan = board->ao_n_chan; | |
| 1390 | + s->maxdata = (1 << board->resolution) - 1; | |
| 1389 | 1391 | s->range_table = &range_bipolar10; |
| 1390 | 1392 | s->insn_write = das1800_ao_winsn; |
| 1391 | 1393 | } else { |
| @@ -1405,7 +1407,7 @@ static int das1800_attach(struct comedi_device *dev, · 13 unmodified lines | ||
| 1405 | 1407 | s = &dev->subdevices[3]; |
| 1406 | 1408 | s->type = COMEDI_SUBD_DO; |
| 1407 | 1409 | s->subdev_flags = SDF_WRITABLE; |
| 1408 | − s->n_chan = thisboard->do_n_chan; | |
| 1410 | + s->n_chan = board->do_n_chan; | |
| 1409 | 1411 | s->maxdata = 1; |
| 1410 | 1412 | s->range_table = &range_digital; |
| 1411 | 1413 | s->insn_bits = das1800_do_wbits; |
| @@ -1416,9 +1418,9 @@ static int das1800_attach(struct comedi_device *dev, · 4 unmodified lines | ||
| 1416 | 1418 | outb(0, dev->iobase + DAS1800_DIGITAL); |
| 1417 | 1419 | |
| 1418 | 1420 | /* initialize analog out channels */ |
| 1419 | − if (thisboard->ao_ability == 1) { | |
| 1421 | + if (board->ao_ability == 1) { | |
| 1420 | 1422 | /* select 'update' dac channel for baseAddress + 0x0 */ |
| 1421 | − outb(DAC(thisboard->ao_n_chan - 1), | |
| 1423 | + outb(DAC(board->ao_n_chan - 1), | |
| 1422 | 1424 | dev->iobase + DAS1800_SELECT); |
| 1423 | 1425 | outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); |
| 1424 | 1426 | } |
| @@ -240,13 +240,13 @@ static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg) · 239 unmodified lines | ||
| 240 | 240 | |
| 241 | 241 | static void das800_enable(struct comedi_device *dev) |
| 242 | 242 | { |
| 243 | − const struct das800_board *thisboard = dev->board_ptr; | |
| 243 | + const struct das800_board *board = dev->board_ptr; | |
| 244 | 244 | struct das800_private *devpriv = dev->private; |
| 245 | 245 | unsigned long irq_flags; |
| 246 | 246 | |
| 247 | 247 | spin_lock_irqsave(&dev->spinlock, irq_flags); |
| 248 | 248 | /* enable fifo-half full interrupts for cio-das802/16 */ |
| 249 | − if (thisboard->resolution == 16) | |
| 249 | + if (board->resolution == 16) | |
| 250 | 250 | outb(CIO_ENHF, dev->iobase + DAS800_GAIN); |
| 251 | 251 | /* enable hardware triggering */ |
| 252 | 252 | das800_ind_write(dev, CONV_HCEN, CONV_CONTROL); |
| @@ -303,7 +303,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, · 50 unmodified lines | ||
| 303 | 303 | struct comedi_subdevice *s, |
| 304 | 304 | struct comedi_cmd *cmd) |
| 305 | 305 | { |
| 306 | − const struct das800_board *thisboard = dev->board_ptr; | |
| 306 | + const struct das800_board *board = dev->board_ptr; | |
| 307 | 307 | int err = 0; |
| 308 | 308 | |
| 309 | 309 | /* Step 1 : check if triggers are trivially valid */ |
| @@ -335,7 +335,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, · 25 unmodified lines | ||
| 335 | 335 | |
| 336 | 336 | if (cmd->convert_src == TRIG_TIMER) { |
| 337 | 337 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 338 | − thisboard->ai_speed); | |
| 338 | + board->ai_speed); | |
| 339 | 339 | } |
| 340 | 340 | |
| 341 | 341 | err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); |
| @@ -375,7 +375,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev, · 33 unmodified lines | ||
| 375 | 375 | static int das800_ai_do_cmd(struct comedi_device *dev, |
| 376 | 376 | struct comedi_subdevice *s) |
| 377 | 377 | { |
| 378 | − const struct das800_board *thisboard = dev->board_ptr; | |
| 378 | + const struct das800_board *board = dev->board_ptr; | |
| 379 | 379 | struct comedi_async *async = s->async; |
| 380 | 380 | struct comedi_cmd *cmd = &async->cmd; |
| 381 | 381 | unsigned int gain = CR_RANGE(cmd->chanlist[0]); |
| @@ -393,7 +393,7 @@ static int das800_ai_do_cmd(struct comedi_device *dev, · 11 unmodified lines | ||
| 393 | 393 | spin_unlock_irqrestore(&dev->spinlock, irq_flags); |
| 394 | 394 | |
| 395 | 395 | /* set gain */ |
| 396 | − if (thisboard->resolution == 12 && gain > 0) | |
| 396 | + if (board->resolution == 12 && gain > 0) | |
| 397 | 397 | gain += 0x7; |
| 398 | 398 | gain &= 0xf; |
| 399 | 399 | outb(gain, dev->iobase + DAS800_GAIN); |
| @@ -604,54 +604,62 @@ static int das800_do_insn_bits(struct comedi_device *dev, · 204 unmodified lines | ||
| 604 | 604 | return insn->n; |
| 605 | 605 | } |
| 606 | 606 | |
| 607 | −static int das800_probe(struct comedi_device *dev) | |
| 607 | +static const struct das800_board *das800_probe(struct comedi_device *dev) | |
| 608 | 608 | { |
| 609 | − const struct das800_board *thisboard = dev->board_ptr; | |
| 610 | − int board = thisboard ? thisboard - das800_boards : -EINVAL; | |
| 609 | + const struct das800_board *board = dev->board_ptr; | |
| 610 | + int index = board ? board - das800_boards : -EINVAL; | |
| 611 | 611 | int id_bits; |
| 612 | 612 | unsigned long irq_flags; |
| 613 | 613 | |
| 614 | + /* | |
| 615 | + * The dev->board_ptr will be set by comedi_device_attach() if the | |
| 616 | + * board name provided by the user matches a board->name in this | |
| 617 | + * driver. If so, this function sanity checks the id_bits to verify | |
| 618 | + * that the board is correct. | |
| 619 | + * | |
| 620 | + * If the dev->board_ptr is not set, the user is trying to attach | |
| 621 | + * an unspecified board to this driver. In this case the id_bits | |
| 622 | + * are used to 'probe' for the correct dev->board_ptr. | |
| 623 | + */ | |
| 614 | 624 | spin_lock_irqsave(&dev->spinlock, irq_flags); |
| 615 | 625 | id_bits = das800_ind_read(dev, ID) & 0x3; |
| 616 | 626 | spin_unlock_irqrestore(&dev->spinlock, irq_flags); |
| 617 | 627 | |
| 618 | 628 | switch (id_bits) { |
| 619 | 629 | case 0x0: |
| 620 | − if (board == BOARD_DAS800 || board == BOARD_CIODAS800) | |
| 621 | − break; | |
| 622 | − dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n"); | |
| 623 | − board = BOARD_DAS800; | |
| 630 | + if (index == BOARD_DAS800 || index == BOARD_CIODAS800) | |
| 631 | + return board; | |
| 632 | + index = BOARD_DAS800; | |
| 624 | 633 | break; |
| 625 | 634 | case 0x2: |
| 626 | − if (board == BOARD_DAS801 || board == BOARD_CIODAS801) | |
| 627 | − break; | |
| 628 | − dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n"); | |
| 629 | − board = BOARD_DAS801; | |
| 635 | + if (index == BOARD_DAS801 || index == BOARD_CIODAS801) | |
| 636 | + return board; | |
| 637 | + index = BOARD_DAS801; | |
| 630 | 638 | break; |
| 631 | 639 | case 0x3: |
| 632 | − if (board == BOARD_DAS802 || board == BOARD_CIODAS802 || | |
| 633 | − board == BOARD_CIODAS80216) | |
| 634 | − break; | |
| 635 | − dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n"); | |
| 636 | − board = BOARD_DAS802; | |
| 640 | + if (index == BOARD_DAS802 || index == BOARD_CIODAS802 || | |
| 641 | + index == BOARD_CIODAS80216) | |
| 642 | + return board; | |
| 643 | + index = BOARD_DAS802; | |
| 637 | 644 | break; |
| 638 | 645 | default: |
| 639 | 646 | dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n", |
| 640 | 647 | id_bits); |
| 641 | − board = -EINVAL; | |
| 642 | − break; | |
| 648 | + return NULL; | |
| 643 | 649 | } |
| 644 | − return board; | |
| 650 | + dev_dbg(dev->class_dev, "Board model (probed): %s series\n", | |
| 651 | + das800_boards[index].name); | |
| 652 | + | |
| 653 | + return &das800_boards[index]; | |
| 645 | 654 | } |
| 646 | 655 | |
| 647 | 656 | static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) |
| 648 | 657 | { |
| 649 | − const struct das800_board *thisboard; | |
| 658 | + const struct das800_board *board; | |
| 650 | 659 | struct das800_private *devpriv; |
| 651 | 660 | struct comedi_subdevice *s; |
| 652 | 661 | unsigned int irq = it->options[1]; |
| 653 | 662 | unsigned long irq_flags; |
| 654 | − int board; | |
| 655 | 663 | int ret; |
| 656 | 664 | |
| 657 | 665 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| @@ -663,13 +671,10 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) · 5 unmodified lines | ||
| 663 | 671 | return ret; |
| 664 | 672 | |
| 665 | 673 | board = das800_probe(dev); |
| 666 | − if (board < 0) { | |
| 667 | − dev_dbg(dev->class_dev, "unable to determine board type\n"); | |
| 674 | + if (!board) | |
| 668 | 675 | return -ENODEV; |
| 669 | − } | |
| 670 | − dev->board_ptr = das800_boards + board; | |
| 671 | − thisboard = dev->board_ptr; | |
| 672 | − dev->board_name = thisboard->name; | |
| 676 | + dev->board_ptr = board; | |
| 677 | + dev->board_name = board->name; | |
| 673 | 678 | |
| 674 | 679 | if (irq > 1 && irq <= 7) { |
| 675 | 680 | ret = request_irq(irq, das800_interrupt, 0, dev->board_name, |
| @@ -693,8 +698,8 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) · 17 unmodified lines | ||
| 693 | 698 | s->type = COMEDI_SUBD_AI; |
| 694 | 699 | s->subdev_flags = SDF_READABLE | SDF_GROUND; |
| 695 | 700 | s->n_chan = 8; |
| 696 | − s->maxdata = (1 << thisboard->resolution) - 1; | |
| 697 | − s->range_table = thisboard->ai_range; | |
| 701 | + s->maxdata = (1 << board->resolution) - 1; | |
| 702 | + s->range_table = board->ai_range; | |
| 698 | 703 | s->insn_read = das800_ai_insn_read; |
| 699 | 704 | if (dev->irq) { |
| 700 | 705 | s->subdev_flags |= SDF_CMD_READ; |
| @@ -400,7 +400,7 @@ static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, · 399 unmodified lines | ||
| 400 | 400 | static int dt3k_ai_cmdtest(struct comedi_device *dev, |
| 401 | 401 | struct comedi_subdevice *s, struct comedi_cmd *cmd) |
| 402 | 402 | { |
| 403 | − const struct dt3k_boardtype *this_board = dev->board_ptr; | |
| 403 | + const struct dt3k_boardtype *board = dev->board_ptr; | |
| 404 | 404 | int err = 0; |
| 405 | 405 | unsigned int arg; |
| 406 | 406 | |
| @@ -424,14 +424,14 @@ static int dt3k_ai_cmdtest(struct comedi_device *dev, · 17 unmodified lines | ||
| 424 | 424 | |
| 425 | 425 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 426 | 426 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 427 | − this_board->ai_speed); | |
| 427 | + board->ai_speed); | |
| 428 | 428 | err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, |
| 429 | 429 | 100 * 16 * 65535); |
| 430 | 430 | } |
| 431 | 431 | |
| 432 | 432 | if (cmd->convert_src == TRIG_TIMER) { |
| 433 | 433 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 434 | − this_board->ai_speed); | |
| 434 | + board->ai_speed); | |
| 435 | 435 | err |= comedi_check_trigger_arg_max(&cmd->convert_arg, |
| 436 | 436 | 50 * 16 * 65535); |
| 437 | 437 | } |
| @@ -635,17 +635,17 @@ static int dt3000_auto_attach(struct comedi_device *dev, · 197 unmodified lines | ||
| 635 | 635 | unsigned long context) |
| 636 | 636 | { |
| 637 | 637 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 638 | − const struct dt3k_boardtype *this_board = NULL; | |
| 638 | + const struct dt3k_boardtype *board = NULL; | |
| 639 | 639 | struct dt3k_private *devpriv; |
| 640 | 640 | struct comedi_subdevice *s; |
| 641 | 641 | int ret = 0; |
| 642 | 642 | |
| 643 | 643 | if (context < ARRAY_SIZE(dt3k_boardtypes)) |
| 644 | − this_board = &dt3k_boardtypes[context]; | |
| 645 | − if (!this_board) | |
| 644 | + board = &dt3k_boardtypes[context]; | |
| 645 | + if (!board) | |
| 646 | 646 | return -ENODEV; |
| 647 | − dev->board_ptr = this_board; | |
| 648 | − dev->board_name = this_board->name; | |
| 647 | + dev->board_ptr = board; | |
| 648 | + dev->board_name = board->name; | |
| 649 | 649 | |
| 650 | 650 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 651 | 651 | if (!devpriv) |
| @@ -674,9 +674,9 @@ static int dt3000_auto_attach(struct comedi_device *dev, · 22 unmodified lines | ||
| 674 | 674 | /* ai subdevice */ |
| 675 | 675 | s->type = COMEDI_SUBD_AI; |
| 676 | 676 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; |
| 677 | − s->n_chan = this_board->adchan; | |
| 677 | + s->n_chan = board->adchan; | |
| 678 | 678 | s->insn_read = dt3k_ai_insn; |
| 679 | − s->maxdata = (1 << this_board->adbits) - 1; | |
| 679 | + s->maxdata = (1 << board->adbits) - 1; | |
| 680 | 680 | s->range_table = &range_dt3000_ai; /* XXX */ |
| 681 | 681 | if (dev->irq) { |
| 682 | 682 | dev->read_subdev = s; |
| @@ -692,7 +692,7 @@ static int dt3000_auto_attach(struct comedi_device *dev, · 9 unmodified lines | ||
| 692 | 692 | s->type = COMEDI_SUBD_AO; |
| 693 | 693 | s->subdev_flags = SDF_WRITABLE; |
| 694 | 694 | s->n_chan = 2; |
| 695 | − s->maxdata = (1 << this_board->dabits) - 1; | |
| 695 | + s->maxdata = (1 << board->dabits) - 1; | |
| 696 | 696 | s->len_chanlist = 1; |
| 697 | 697 | s->range_table = &range_bipolar10; |
| 698 | 698 | s->insn_write = dt3k_ao_insn_write; |
| @@ -52,45 +52,45 @@ · 51 unmodified lines | ||
| 52 | 52 | * PCI BAR2 Register map (dev->mmio) |
| 53 | 53 | */ |
| 54 | 54 | #define FIRMWARE_REV_REG 0x00 |
| 55 | −#define FEATURES_REG_PRESENT_BIT (1 << 15) | |
| 55 | +#define FEATURES_REG_PRESENT_BIT BIT(15) | |
| 56 | 56 | #define BOARD_CONTROL_REG 0x04 |
| 57 | −#define BOARD_RESET_BIT (1 << 0) | |
| 58 | −#define TX_FIFO_RESET_BIT (1 << 1) | |
| 59 | −#define RX_FIFO_RESET_BIT (1 << 2) | |
| 60 | −#define TX_ENABLE_BIT (1 << 4) | |
| 61 | −#define RX_ENABLE_BIT (1 << 5) | |
| 62 | −#define DEMAND_DMA_DIRECTION_TX_BIT (1 << 6) /* ch 0 only */ | |
| 63 | −#define LINE_VALID_ON_STATUS_VALID_BIT (1 << 7) | |
| 64 | −#define START_TX_BIT (1 << 8) | |
| 65 | −#define CABLE_THROTTLE_ENABLE_BIT (1 << 9) | |
| 66 | −#define TEST_MODE_ENABLE_BIT (1 << 31) | |
| 57 | +#define BOARD_RESET_BIT BIT(0) | |
| 58 | +#define TX_FIFO_RESET_BIT BIT(1) | |
| 59 | +#define RX_FIFO_RESET_BIT BIT(2) | |
| 60 | +#define TX_ENABLE_BIT BIT(4) | |
| 61 | +#define RX_ENABLE_BIT BIT(5) | |
| 62 | +#define DEMAND_DMA_DIRECTION_TX_BIT BIT(6) /* ch 0 only */ | |
| 63 | +#define LINE_VALID_ON_STATUS_VALID_BIT BIT(7) | |
| 64 | +#define START_TX_BIT BIT(8) | |
| 65 | +#define CABLE_THROTTLE_ENABLE_BIT BIT(9) | |
| 66 | +#define TEST_MODE_ENABLE_BIT BIT(31) | |
| 67 | 67 | #define BOARD_STATUS_REG 0x08 |
| 68 | 68 | #define COMMAND_LINE_STATUS_MASK (0x7f << 0) |
| 69 | −#define TX_IN_PROGRESS_BIT (1 << 7) | |
| 70 | −#define TX_NOT_EMPTY_BIT (1 << 8) | |
| 71 | −#define TX_NOT_ALMOST_EMPTY_BIT (1 << 9) | |
| 72 | −#define TX_NOT_ALMOST_FULL_BIT (1 << 10) | |
| 73 | −#define TX_NOT_FULL_BIT (1 << 11) | |
| 74 | −#define RX_NOT_EMPTY_BIT (1 << 12) | |
| 75 | −#define RX_NOT_ALMOST_EMPTY_BIT (1 << 13) | |
| 76 | −#define RX_NOT_ALMOST_FULL_BIT (1 << 14) | |
| 77 | −#define RX_NOT_FULL_BIT (1 << 15) | |
| 78 | −#define BOARD_JUMPER0_INSTALLED_BIT (1 << 16) | |
| 79 | −#define BOARD_JUMPER1_INSTALLED_BIT (1 << 17) | |
| 80 | −#define TX_OVERRUN_BIT (1 << 21) | |
| 81 | −#define RX_UNDERRUN_BIT (1 << 22) | |
| 82 | −#define RX_OVERRUN_BIT (1 << 23) | |
| 69 | +#define TX_IN_PROGRESS_BIT BIT(7) | |
| 70 | +#define TX_NOT_EMPTY_BIT BIT(8) | |
| 71 | +#define TX_NOT_ALMOST_EMPTY_BIT BIT(9) | |
| 72 | +#define TX_NOT_ALMOST_FULL_BIT BIT(10) | |
| 73 | +#define TX_NOT_FULL_BIT BIT(11) | |
| 74 | +#define RX_NOT_EMPTY_BIT BIT(12) | |
| 75 | +#define RX_NOT_ALMOST_EMPTY_BIT BIT(13) | |
| 76 | +#define RX_NOT_ALMOST_FULL_BIT BIT(14) | |
| 77 | +#define RX_NOT_FULL_BIT BIT(15) | |
| 78 | +#define BOARD_JUMPER0_INSTALLED_BIT BIT(16) | |
| 79 | +#define BOARD_JUMPER1_INSTALLED_BIT BIT(17) | |
| 80 | +#define TX_OVERRUN_BIT BIT(21) | |
| 81 | +#define RX_UNDERRUN_BIT BIT(22) | |
| 82 | +#define RX_OVERRUN_BIT BIT(23) | |
| 83 | 83 | #define TX_PROG_ALMOST_REG 0x0c |
| 84 | 84 | #define RX_PROG_ALMOST_REG 0x10 |
| 85 | 85 | #define ALMOST_EMPTY_BITS(x) (((x) & 0xffff) << 0) |
| 86 | 86 | #define ALMOST_FULL_BITS(x) (((x) & 0xff) << 16) |
| 87 | 87 | #define FEATURES_REG 0x14 |
| 88 | −#define FIFO_SIZE_PRESENT_BIT (1 << 0) | |
| 89 | −#define FIFO_WORDS_PRESENT_BIT (1 << 1) | |
| 90 | −#define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT (1 << 2) | |
| 91 | −#define GPIO_SUPPORTED_BIT (1 << 3) | |
| 92 | −#define PLX_DMA_CH1_SUPPORTED_BIT (1 << 4) | |
| 93 | −#define OVERRUN_UNDERRUN_SUPPORTED_BIT (1 << 5) | |
| 88 | +#define FIFO_SIZE_PRESENT_BIT BIT(0) | |
| 89 | +#define FIFO_WORDS_PRESENT_BIT BIT(1) | |
| 90 | +#define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT BIT(2) | |
| 91 | +#define GPIO_SUPPORTED_BIT BIT(3) | |
| 92 | +#define PLX_DMA_CH1_SUPPORTED_BIT BIT(4) | |
| 93 | +#define OVERRUN_UNDERRUN_SUPPORTED_BIT BIT(5) | |
| 94 | 94 | #define FIFO_REG 0x18 |
| 95 | 95 | #define TX_STATUS_COUNT_REG 0x1c |
| 96 | 96 | #define TX_LINE_VALID_COUNT_REG 0x20, |
| @@ -98,16 +98,16 @@ · 1 unmodified line | ||
| 98 | 98 | #define RX_STATUS_COUNT_REG 0x28 |
| 99 | 99 | #define RX_LINE_COUNT_REG 0x2c |
| 100 | 100 | #define INTERRUPT_CONTROL_REG 0x30 |
| 101 | −#define FRAME_VALID_START_INTR (1 << 0) | |
| 102 | −#define FRAME_VALID_END_INTR (1 << 1) | |
| 103 | −#define TX_FIFO_EMPTY_INTR (1 << 8) | |
| 104 | −#define TX_FIFO_ALMOST_EMPTY_INTR (1 << 9) | |
| 105 | −#define TX_FIFO_ALMOST_FULL_INTR (1 << 10) | |
| 106 | −#define TX_FIFO_FULL_INTR (1 << 11) | |
| 107 | −#define RX_EMPTY_INTR (1 << 12) | |
| 108 | −#define RX_ALMOST_EMPTY_INTR (1 << 13) | |
| 109 | −#define RX_ALMOST_FULL_INTR (1 << 14) | |
| 110 | −#define RX_FULL_INTR (1 << 15) | |
| 101 | +#define FRAME_VALID_START_INTR BIT(0) | |
| 102 | +#define FRAME_VALID_END_INTR BIT(1) | |
| 103 | +#define TX_FIFO_EMPTY_INTR BIT(8) | |
| 104 | +#define TX_FIFO_ALMOST_EMPTY_INTR BIT(9) | |
| 105 | +#define TX_FIFO_ALMOST_FULL_INTR BIT(10) | |
| 106 | +#define TX_FIFO_FULL_INTR BIT(11) | |
| 107 | +#define RX_EMPTY_INTR BIT(12) | |
| 108 | +#define RX_ALMOST_EMPTY_INTR BIT(13) | |
| 109 | +#define RX_ALMOST_FULL_INTR BIT(14) | |
| 110 | +#define RX_FULL_INTR BIT(15) | |
| 111 | 111 | #define INTERRUPT_STATUS_REG 0x34 |
| 112 | 112 | #define TX_CLOCK_DIVIDER_REG 0x38 |
| 113 | 113 | #define TX_FIFO_SIZE_REG 0x40 |
| @@ -123,34 +123,15 @@ · 9 unmodified lines | ||
| 123 | 123 | #define NUM_DMA_BUFFERS 4 |
| 124 | 124 | #define NUM_DMA_DESCRIPTORS 256 |
| 125 | 125 | |
| 126 | −struct hpdi_board { | |
| 127 | − const char *name; | |
| 128 | − int device_id; | |
| 129 | − int subdevice_id; | |
| 130 | −}; | |
| 131 | − | |
| 132 | −static const struct hpdi_board hpdi_boards[] = { | |
| 133 | − { | |
| 134 | − .name = "pci-hpdi32", | |
| 135 | − .device_id = PCI_DEVICE_ID_PLX_9080, | |
| 136 | − .subdevice_id = 0x2400, | |
| 137 | − }, | |
| 138 | −#if 0 | |
| 139 | − { | |
| 140 | − .name = "pxi-hpdi32", | |
| 141 | − .device_id = 0x9656, | |
| 142 | − .subdevice_id = 0x2705, | |
| 143 | − }, | |
| 144 | −#endif | |
| 145 | −}; | |
| 146 | − | |
| 147 | 126 | struct hpdi_private { |
| 148 | 127 | void __iomem *plx9080_mmio; |
| 149 | − uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */ | |
| 128 | + uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */ | |
| 150 | 129 | /* physical addresses of dma buffers */ |
| 151 | 130 | dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; |
| 152 | − /* array of dma descriptors read by plx9080, allocated to get proper | |
| 153 | − * alignment */ | |
| 131 | + /* | |
| 132 | + * array of dma descriptors read by plx9080, allocated to get proper | |
| 133 | + * alignment | |
| 134 | + */ | |
| 154 | 135 | struct plx_dma_desc *dma_desc; |
| 155 | 136 | /* physical address of dma descriptor array */ |
| 156 | 137 | dma_addr_t dma_desc_phys_addr; |
| @@ -202,7 +183,7 @@ static void gsc_hpdi_drain_dma(struct comedi_device *dev, unsigned int channel) · 45 unmodified lines | ||
| 202 | 183 | |
| 203 | 184 | devpriv->dma_desc_index = idx; |
| 204 | 185 | } |
| 205 | − /* XXX check for buffer overrun somehow */ | |
| 186 | + /* XXX check for buffer overrun somehow */ | |
| 206 | 187 | } |
| 207 | 188 | |
| 208 | 189 | static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) |
| @@ -230,10 +211,11 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) · 21 unmodified lines | ||
| 230 | 211 | if (hpdi_intr_status) |
| 231 | 212 | writel(hpdi_intr_status, dev->mmio + INTERRUPT_STATUS_REG); |
| 232 | 213 | |
| 233 | − /* spin lock makes sure no one else changes plx dma control reg */ | |
| 214 | + /* spin lock makes sure no one else changes plx dma control reg */ | |
| 234 | 215 | spin_lock_irqsave(&dev->spinlock, flags); |
| 235 | 216 | dma0_status = readb(devpriv->plx9080_mmio + PLX_DMA0_CS_REG); |
| 236 | − if (plx_status & ICS_DMA0_A) { /* dma chan 0 interrupt */ | |
| 217 | + if (plx_status & ICS_DMA0_A) { | |
| 218 | + /* dma chan 0 interrupt */ | |
| 237 | 219 | writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, |
| 238 | 220 | devpriv->plx9080_mmio + PLX_DMA0_CS_REG); |
| 239 | 221 | |
| @@ -242,17 +224,19 @@ static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) · 2 unmodified lines | ||
| 242 | 224 | } |
| 243 | 225 | spin_unlock_irqrestore(&dev->spinlock, flags); |
| 244 | 226 | |
| 245 | − /* spin lock makes sure no one else changes plx dma control reg */ | |
| 227 | + /* spin lock makes sure no one else changes plx dma control reg */ | |
| 246 | 228 | spin_lock_irqsave(&dev->spinlock, flags); |
| 247 | 229 | dma1_status = readb(devpriv->plx9080_mmio + PLX_DMA1_CS_REG); |
| 248 | − if (plx_status & ICS_DMA1_A) { /* XXX *//* dma chan 1 interrupt */ | |
| 230 | + if (plx_status & ICS_DMA1_A) { | |
| 231 | + /* XXX */ /* dma chan 1 interrupt */ | |
| 249 | 232 | writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, |
| 250 | 233 | devpriv->plx9080_mmio + PLX_DMA1_CS_REG); |
| 251 | 234 | } |
| 252 | 235 | spin_unlock_irqrestore(&dev->spinlock, flags); |
| 253 | 236 | |
| 254 | − /* clear possible plx9080 interrupt sources */ | |
| 255 | − if (plx_status & ICS_LDIA) { /* clear local doorbell interrupt */ | |
| 237 | + /* clear possible plx9080 interrupt sources */ | |
| 238 | + if (plx_status & ICS_LDIA) { | |
| 239 | + /* clear local doorbell interrupt */ | |
| 256 | 240 | plx_bits = readl(devpriv->plx9080_mmio + PLX_DBR_OUT_REG); |
| 257 | 241 | writel(plx_bits, devpriv->plx9080_mmio + PLX_DBR_OUT_REG); |
| 258 | 242 | } |
| @@ -280,7 +264,7 @@ static void gsc_hpdi_abort_dma(struct comedi_device *dev, unsigned int channel) · 21 unmodified lines | ||
| 280 | 264 | struct hpdi_private *devpriv = dev->private; |
| 281 | 265 | unsigned long flags; |
| 282 | 266 | |
| 283 | − /* spinlock for plx dma control/status reg */ | |
| 267 | + /* spinlock for plx dma control/status reg */ | |
| 284 | 268 | spin_lock_irqsave(&dev->spinlock, flags); |
| 285 | 269 | |
| 286 | 270 | plx9080_abort_dma(devpriv->plx9080_mmio, channel); |
| @@ -536,7 +520,7 @@ static int gsc_hpdi_init(struct comedi_device *dev) · 249 unmodified lines | ||
| 536 | 520 | |
| 537 | 521 | /* wait 10usec after reset before accessing fifos */ |
| 538 | 522 | writel(BOARD_RESET_BIT, dev->mmio + BOARD_CONTROL_REG); |
| 539 | − udelay(10); | |
| 523 | + usleep_range(10, 1000); | |
| 540 | 524 | |
| 541 | 525 | writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32), |
| 542 | 526 | dev->mmio + RX_PROG_ALMOST_REG); |
| @@ -550,7 +534,7 @@ static int gsc_hpdi_init(struct comedi_device *dev) · 7 unmodified lines | ||
| 550 | 534 | |
| 551 | 535 | writel(0, dev->mmio + INTERRUPT_CONTROL_REG); |
| 552 | 536 | |
| 553 | − /* enable interrupts */ | |
| 537 | + /* enable interrupts */ | |
| 554 | 538 | plx_intcsr_bits = |
| 555 | 539 | ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE | |
| 556 | 540 | ICS_DMA0_E; |
| @@ -577,57 +561,42 @@ static void gsc_hpdi_init_plx9080(struct comedi_device *dev) · 20 unmodified lines | ||
| 577 | 561 | gsc_hpdi_abort_dma(dev, 0); |
| 578 | 562 | gsc_hpdi_abort_dma(dev, 1); |
| 579 | 563 | |
| 580 | − /* configure dma0 mode */ | |
| 564 | + /* configure dma0 mode */ | |
| 581 | 565 | bits = 0; |
| 582 | − /* enable ready input */ | |
| 566 | + /* enable ready input */ | |
| 583 | 567 | bits |= PLX_DMA_EN_READYIN_BIT; |
| 584 | − /* enable dma chaining */ | |
| 568 | + /* enable dma chaining */ | |
| 585 | 569 | bits |= PLX_EN_CHAIN_BIT; |
| 586 | − /* enable interrupt on dma done | |
| 587 | − * (probably don't need this, since chain never finishes) */ | |
| 570 | + /* | |
| 571 | + * enable interrupt on dma done | |
| 572 | + * (probably don't need this, since chain never finishes) | |
| 573 | + */ | |
| 588 | 574 | bits |= PLX_EN_DMA_DONE_INTR_BIT; |
| 589 | − /* don't increment local address during transfers | |
| 590 | − * (we are transferring from a fixed fifo register) */ | |
| 575 | + /* | |
| 576 | + * don't increment local address during transfers | |
| 577 | + * (we are transferring from a fixed fifo register) | |
| 578 | + */ | |
| 591 | 579 | bits |= PLX_LOCAL_ADDR_CONST_BIT; |
| 592 | − /* route dma interrupt to pci bus */ | |
| 580 | + /* route dma interrupt to pci bus */ | |
| 593 | 581 | bits |= PLX_DMA_INTR_PCI_BIT; |
| 594 | − /* enable demand mode */ | |
| 582 | + /* enable demand mode */ | |
| 595 | 583 | bits |= PLX_DEMAND_MODE_BIT; |
| 596 | − /* enable local burst mode */ | |
| 584 | + /* enable local burst mode */ | |
| 597 | 585 | bits |= PLX_DMA_LOCAL_BURST_EN_BIT; |
| 598 | 586 | bits |= PLX_LOCAL_BUS_32_WIDE_BITS; |
| 599 | 587 | writel(bits, plx_iobase + PLX_DMA0_MODE_REG); |
| 600 | 588 | } |
| 601 | 589 | |
| 602 | −static const struct hpdi_board *gsc_hpdi_find_board(struct pci_dev *pcidev) | |
| 603 | −{ | |
| 604 | − unsigned int i; | |
| 605 | − | |
| 606 | − for (i = 0; i < ARRAY_SIZE(hpdi_boards); i++) | |
| 607 | − if (pcidev->device == hpdi_boards[i].device_id && | |
| 608 | − pcidev->subsystem_device == hpdi_boards[i].subdevice_id) | |
| 609 | − return &hpdi_boards[i]; | |
| 610 | − return NULL; | |
| 611 | −} | |
| 612 | − | |
| 613 | 590 | static int gsc_hpdi_auto_attach(struct comedi_device *dev, |
| 614 | 591 | unsigned long context_unused) |
| 615 | 592 | { |
| 616 | 593 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 617 | − const struct hpdi_board *thisboard; | |
| 618 | 594 | struct hpdi_private *devpriv; |
| 619 | 595 | struct comedi_subdevice *s; |
| 620 | 596 | int i; |
| 621 | 597 | int retval; |
| 622 | 598 | |
| 623 | − thisboard = gsc_hpdi_find_board(pcidev); | |
| 624 | − if (!thisboard) { | |
| 625 | − dev_err(dev->class_dev, "gsc_hpdi: pci %s not supported\n", | |
| 626 | − pci_name(pcidev)); | |
| 627 | − return -EINVAL; | |
| 628 | − } | |
| 629 | − dev->board_ptr = thisboard; | |
| 630 | − dev->board_name = thisboard->name; | |
| 599 | + dev->board_name = "pci-hpdi32"; | |
| 631 | 600 | |
| 632 | 601 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 633 | 602 | if (!devpriv) |
| @@ -647,7 +616,7 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, · 13 unmodified lines | ||
| 647 | 616 | |
| 648 | 617 | gsc_hpdi_init_plx9080(dev); |
| 649 | 618 | |
| 650 | − /* get irq */ | |
| 619 | + /* get irq */ | |
| 651 | 620 | if (request_irq(pcidev->irq, gsc_hpdi_interrupt, IRQF_SHARED, |
| 652 | 621 | dev->board_name, dev)) { |
| 653 | 622 | dev_warn(dev->class_dev, |
| @@ -658,13 +627,13 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, · 4 unmodified lines | ||
| 658 | 627 | |
| 659 | 628 | dev_dbg(dev->class_dev, " irq %u\n", dev->irq); |
| 660 | 629 | |
| 661 | − /* allocate pci dma buffers */ | |
| 630 | + /* allocate pci dma buffers */ | |
| 662 | 631 | for (i = 0; i < NUM_DMA_BUFFERS; i++) { |
| 663 | 632 | devpriv->dio_buffer[i] = |
| 664 | 633 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, |
| 665 | 634 | &devpriv->dio_buffer_phys_addr[i]); |
| 666 | 635 | } |
| 667 | − /* allocate dma descriptors */ | |
| 636 | + /* allocate dma descriptors */ | |
| 668 | 637 | devpriv->dma_desc = pci_alloc_consistent(pcidev, |
| 669 | 638 | sizeof(struct plx_dma_desc) * |
| 670 | 639 | NUM_DMA_DESCRIPTORS, |
| @@ -733,8 +702,8 @@ static int gsc_hpdi_pci_probe(struct pci_dev *dev, · 62 unmodified lines | ||
| 733 | 702 | } |
| 734 | 703 | |
| 735 | 704 | static const struct pci_device_id gsc_hpdi_pci_table[] = { |
| 736 | − { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX, | |
| 737 | − 0x2400, 0, 0, 0}, | |
| 705 | + { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, | |
| 706 | + PCI_VENDOR_ID_PLX, 0x2400) }, | |
| 738 | 707 | { 0 } |
| 739 | 708 | }; |
| 740 | 709 | MODULE_DEVICE_TABLE(pci, gsc_hpdi_pci_table); |
| @@ -748,5 +717,5 @@ static struct pci_driver gsc_hpdi_pci_driver = { · 7 unmodified lines | ||
| 748 | 717 | module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver); |
| 749 | 718 | |
| 750 | 719 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 751 | −MODULE_DESCRIPTION("Comedi low-level driver"); | |
| 720 | +MODULE_DESCRIPTION("Comedi driver for General Standards PCI-HPDI32/PMC-HPDI32"); | |
| 752 | 721 | MODULE_LICENSE("GPL"); |
| @@ -453,7 +453,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, · 452 unmodified lines | ||
| 453 | 453 | struct comedi_subdevice *subdevice, |
| 454 | 454 | struct comedi_insn *insn, unsigned int *data) |
| 455 | 455 | { |
| 456 | − const struct me4000_board *thisboard = dev->board_ptr; | |
| 456 | + const struct me4000_board *board = dev->board_ptr; | |
| 457 | 457 | int chan = CR_CHAN(insn->chanspec); |
| 458 | 458 | int rang = CR_RANGE(insn->chanspec); |
| 459 | 459 | int aref = CR_AREF(insn->chanspec); |
| @@ -491,7 +491,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, · 31 unmodified lines | ||
| 491 | 491 | switch (aref) { |
| 492 | 492 | case AREF_GROUND: |
| 493 | 493 | case AREF_COMMON: |
| 494 | − if (chan >= thisboard->ai_nchan) { | |
| 494 | + if (chan >= board->ai_nchan) { | |
| 495 | 495 | dev_err(dev->class_dev, |
| 496 | 496 | "Analog input is not available\n"); |
| 497 | 497 | return -EINVAL; |
| @@ -506,7 +506,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, · 8 unmodified lines | ||
| 506 | 506 | return -EINVAL; |
| 507 | 507 | } |
| 508 | 508 | |
| 509 | − if (chan >= thisboard->ai_diff_nchan) { | |
| 509 | + if (chan >= board->ai_diff_nchan) { | |
| 510 | 510 | dev_err(dev->class_dev, |
| 511 | 511 | "Analog input is not available\n"); |
| 512 | 512 | return -EINVAL; |
| @@ -1252,17 +1252,17 @@ static int me4000_auto_attach(struct comedi_device *dev, · 739 unmodified lines | ||
| 1252 | 1252 | unsigned long context) |
| 1253 | 1253 | { |
| 1254 | 1254 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 1255 | − const struct me4000_board *thisboard = NULL; | |
| 1255 | + const struct me4000_board *board = NULL; | |
| 1256 | 1256 | struct me4000_info *info; |
| 1257 | 1257 | struct comedi_subdevice *s; |
| 1258 | 1258 | int result; |
| 1259 | 1259 | |
| 1260 | 1260 | if (context < ARRAY_SIZE(me4000_boards)) |
| 1261 | − thisboard = &me4000_boards[context]; | |
| 1262 | − if (!thisboard) | |
| 1261 | + board = &me4000_boards[context]; | |
| 1262 | + if (!board) | |
| 1263 | 1263 | return -ENODEV; |
| 1264 | − dev->board_ptr = thisboard; | |
| 1265 | − dev->board_name = thisboard->name; | |
| 1264 | + dev->board_ptr = board; | |
| 1265 | + dev->board_name = board->name; | |
| 1266 | 1266 | |
| 1267 | 1267 | info = comedi_alloc_devpriv(dev, sizeof(*info)); |
| 1268 | 1268 | if (!info) |
| @@ -1301,11 +1301,11 @@ static int me4000_auto_attach(struct comedi_device *dev, · 32 unmodified lines | ||
| 1301 | 1301 | |
| 1302 | 1302 | s = &dev->subdevices[0]; |
| 1303 | 1303 | |
| 1304 | − if (thisboard->ai_nchan) { | |
| 1304 | + if (board->ai_nchan) { | |
| 1305 | 1305 | s->type = COMEDI_SUBD_AI; |
| 1306 | 1306 | s->subdev_flags = |
| 1307 | 1307 | SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; |
| 1308 | − s->n_chan = thisboard->ai_nchan; | |
| 1308 | + s->n_chan = board->ai_nchan; | |
| 1309 | 1309 | s->maxdata = 0xFFFF; /* 16 bit ADC */ |
| 1310 | 1310 | s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; |
| 1311 | 1311 | s->range_table = &me4000_ai_range; |
| @@ -1328,10 +1328,10 @@ static int me4000_auto_attach(struct comedi_device *dev, · 16 unmodified lines | ||
| 1328 | 1328 | |
| 1329 | 1329 | s = &dev->subdevices[1]; |
| 1330 | 1330 | |
| 1331 | − if (thisboard->ao_nchan) { | |
| 1331 | + if (board->ao_nchan) { | |
| 1332 | 1332 | s->type = COMEDI_SUBD_AO; |
| 1333 | 1333 | s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND; |
| 1334 | − s->n_chan = thisboard->ao_nchan; | |
| 1334 | + s->n_chan = board->ao_nchan; | |
| 1335 | 1335 | s->maxdata = 0xFFFF; /* 16 bit DAC */ |
| 1336 | 1336 | s->range_table = &range_bipolar10; |
| 1337 | 1337 | s->insn_write = me4000_ao_insn_write; |
| @@ -1349,10 +1349,10 @@ static int me4000_auto_attach(struct comedi_device *dev, · 11 unmodified lines | ||
| 1349 | 1349 | |
| 1350 | 1350 | s = &dev->subdevices[2]; |
| 1351 | 1351 | |
| 1352 | − if (thisboard->dio_nchan) { | |
| 1352 | + if (board->dio_nchan) { | |
| 1353 | 1353 | s->type = COMEDI_SUBD_DIO; |
| 1354 | 1354 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; |
| 1355 | − s->n_chan = thisboard->dio_nchan; | |
| 1355 | + s->n_chan = board->dio_nchan; | |
| 1356 | 1356 | s->maxdata = 1; |
| 1357 | 1357 | s->range_table = &range_digital; |
| 1358 | 1358 | s->insn_bits = me4000_dio_insn_bits; |
| @@ -1373,7 +1373,7 @@ static int me4000_auto_attach(struct comedi_device *dev, · 14 unmodified lines | ||
| 1373 | 1373 | |
| 1374 | 1374 | /* Counter subdevice (8254) */ |
| 1375 | 1375 | s = &dev->subdevices[3]; |
| 1376 | − if (thisboard->has_counter) { | |
| 1376 | + if (board->has_counter) { | |
| 1377 | 1377 | unsigned long timer_base = pci_resource_start(pcidev, 3); |
| 1378 | 1378 | |
| 1379 | 1379 | if (!timer_base) |
| @@ -173,8 +173,7 @@ struct me_private_data { · 172 unmodified lines | ||
| 173 | 173 | |
| 174 | 174 | static inline void sleep(unsigned sec) |
| 175 | 175 | { |
| 176 | − __set_current_state(TASK_INTERRUPTIBLE); | |
| 177 | − schedule_timeout(sec * HZ); | |
| 176 | + schedule_timeout_interruptible(sec * HZ); | |
| 178 | 177 | } |
| 179 | 178 | |
| 180 | 179 | static int me_dio_insn_config(struct comedi_device *dev, |
| @@ -1,52 +1,51 @@ | ||
| 1 | 1 | /* |
| 2 | − comedi/drivers/mite.c | |
| 3 | − Hardware driver for NI Mite PCI interface chip | |
| 4 | − | |
| 5 | − COMEDI - Linux Control and Measurement Device Interface | |
| 6 | − Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> | |
| 7 | − | |
| 8 | − This program is free software; you can redistribute it and/or modify | |
| 9 | − it under the terms of the GNU General Public License as published by | |
| 10 | − the Free Software Foundation; either version 2 of the License, or | |
| 11 | − (at your option) any later version. | |
| 12 | − | |
| 13 | − This program is distributed in the hope that it will be useful, | |
| 14 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − GNU General Public License for more details. | |
| 17 | −*/ | |
| 2 | + * comedi/drivers/mite.c | |
| 3 | + * Hardware driver for NI Mite PCI interface chip | |
| 4 | + * | |
| 5 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 6 | + * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + */ | |
| 18 | 18 | |
| 19 | 19 | /* |
| 20 | − The PCI-MIO E series driver was originally written by | |
| 21 | − Tomasz Motylewski <...>, and ported to comedi by ds. | |
| 22 | − | |
| 23 | − References for specifications: | |
| 24 | − | |
| 25 | − 321747b.pdf Register Level Programmer Manual (obsolete) | |
| 26 | − 321747c.pdf Register Level Programmer Manual (new) | |
| 27 | − DAQ-STC reference manual | |
| 28 | − | |
| 29 | − Other possibly relevant info: | |
| 30 | − | |
| 31 | − 320517c.pdf User manual (obsolete) | |
| 32 | − 320517f.pdf User manual (new) | |
| 33 | − 320889a.pdf delete | |
| 34 | − 320906c.pdf maximum signal ratings | |
| 35 | − 321066a.pdf about 16x | |
| 36 | − 321791a.pdf discontinuation of at-mio-16e-10 rev. c | |
| 37 | − 321808a.pdf about at-mio-16e-10 rev P | |
| 38 | − 321837a.pdf discontinuation of at-mio-16de-10 rev d | |
| 39 | − 321838a.pdf about at-mio-16de-10 rev N | |
| 40 | − | |
| 41 | − ISSUES: | |
| 42 | − | |
| 43 | −*/ | |
| 44 | − | |
| 45 | −/* #define USE_KMALLOC */ | |
| 20 | + * The PCI-MIO E series driver was originally written by | |
| 21 | + * Tomasz Motylewski <...>, and ported to comedi by ds. | |
| 22 | + * | |
| 23 | + * References for specifications: | |
| 24 | + * | |
| 25 | + * 321747b.pdf Register Level Programmer Manual (obsolete) | |
| 26 | + * 321747c.pdf Register Level Programmer Manual (new) | |
| 27 | + * DAQ-STC reference manual | |
| 28 | + * | |
| 29 | + * Other possibly relevant info: | |
| 30 | + * | |
| 31 | + * 320517c.pdf User manual (obsolete) | |
| 32 | + * 320517f.pdf User manual (new) | |
| 33 | + * 320889a.pdf delete | |
| 34 | + * 320906c.pdf maximum signal ratings | |
| 35 | + * 321066a.pdf about 16x | |
| 36 | + * 321791a.pdf discontinuation of at-mio-16e-10 rev. c | |
| 37 | + * 321808a.pdf about at-mio-16e-10 rev P | |
| 38 | + * 321837a.pdf discontinuation of at-mio-16de-10 rev d | |
| 39 | + * 321838a.pdf about at-mio-16de-10 rev N | |
| 40 | + * | |
| 41 | + * ISSUES: | |
| 42 | + * | |
| 43 | + */ | |
| 46 | 44 | |
| 47 | 45 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 48 | 46 | |
| 49 | 47 | #include <linux/module.h> |
| 48 | +#include <linux/slab.h> | |
| 50 | 49 | |
| 51 | 50 | #include "../comedi_pci.h" |
| 52 | 51 | |
| @@ -132,7 +131,7 @@ int mite_setup2(struct comedi_device *dev, · 79 unmodified lines | ||
| 132 | 131 | mite->mite_io_addr + MITE_IODWBSR); |
| 133 | 132 | } |
| 134 | 133 | /* |
| 135 | − * make sure dma bursts work. I got this from running a bus analyzer | |
| 134 | + * Make sure dma bursts work. I got this from running a bus analyzer | |
| 136 | 135 | * on a pxi-6281 and a pxi-6713. 6713 powered up with register value |
| 137 | 136 | * of 0x61f and bursts worked. 6281 powered up with register value of |
| 138 | 137 | * 0x1f and bursts didn't work. The NI windows driver reads the |
| @@ -224,7 +223,8 @@ struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, · 85 unmodified lines | ||
| 224 | 223 | unsigned long flags; |
| 225 | 224 | struct mite_channel *channel = NULL; |
| 226 | 225 | |
| 227 | − /* spin lock so mite_release_channel can be called safely | |
| 226 | + /* | |
| 227 | + * spin lock so mite_release_channel can be called safely | |
| 228 | 228 | * from interrupts |
| 229 | 229 | */ |
| 230 | 230 | spin_lock_irqsave(&mite->lock, flags); |
| @@ -246,15 +246,15 @@ void mite_release_channel(struct mite_channel *mite_chan) · 15 unmodified lines | ||
| 246 | 246 | struct mite_struct *mite = mite_chan->mite; |
| 247 | 247 | unsigned long flags; |
| 248 | 248 | |
| 249 | − /* spin lock to prevent races with mite_request_channel */ | |
| 249 | + /* spin lock to prevent races with mite_request_channel */ | |
| 250 | 250 | spin_lock_irqsave(&mite->lock, flags); |
| 251 | 251 | if (mite->channel_allocated[mite_chan->channel]) { |
| 252 | 252 | mite_dma_disarm(mite_chan); |
| 253 | 253 | mite_dma_reset(mite_chan); |
| 254 | − /* | |
| 255 | − * disable all channel's interrupts (do it after disarm/reset so | |
| 256 | − * MITE_CHCR reg isn't changed while dma is still active!) | |
| 257 | − */ | |
| 254 | + /* | |
| 255 | + * disable all channel's interrupts (do it after disarm/reset so | |
| 256 | + * MITE_CHCR reg isn't changed while dma is still active!) | |
| 257 | + */ | |
| 258 | 258 | writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | |
| 259 | 259 | CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE | |
| 260 | 260 | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | |
| @@ -286,7 +286,7 @@ void mite_dma_arm(struct mite_channel *mite_chan) · 25 unmodified lines | ||
| 286 | 286 | writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); |
| 287 | 287 | mmiowb(); |
| 288 | 288 | spin_unlock_irqrestore(&mite->lock, flags); |
| 289 | −/* mite_dma_tcr(mite, channel); */ | |
| 289 | + /* mite_dma_tcr(mite, channel); */ | |
| 290 | 290 | } |
| 291 | 291 | EXPORT_SYMBOL_GPL(mite_dma_arm); |
| 292 | 292 | |
| @@ -529,8 +529,10 @@ int mite_sync_input_dma(struct mite_channel *mite_chan, · 236 unmodified lines | ||
| 529 | 529 | } |
| 530 | 530 | |
| 531 | 531 | count = nbytes - async->buf_write_count; |
| 532 | − /* it's possible count will be negative due to | |
| 533 | − * conservative value returned by mite_bytes_written_to_memory_lb */ | |
| 532 | + /* | |
| 533 | + * it's possible count will be negative due to conservative value | |
| 534 | + * returned by mite_bytes_written_to_memory_lb | |
| 535 | + */ | |
| 534 | 536 | if (count <= 0) |
| 535 | 537 | return 0; |
| 536 | 538 | |
| @@ -551,7 +553,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, · 14 unmodified lines | ||
| 551 | 553 | u32 nbytes_ub, nbytes_lb; |
| 552 | 554 | int count; |
| 553 | 555 | |
| 554 | − /* read alloc as much as we can */ | |
| 556 | + /* read alloc as much as we can */ | |
| 555 | 557 | comedi_buf_read_alloc(s, async->prealloc_bufsz); |
| 556 | 558 | nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan); |
| 557 | 559 | if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_lb - stop_count) > 0) |
| @@ -622,5 +624,5 @@ module_init(mite_module_init); · 64 unmodified lines | ||
| 622 | 624 | module_exit(mite_module_exit); |
| 623 | 625 | |
| 624 | 626 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 625 | −MODULE_DESCRIPTION("Comedi low-level driver"); | |
| 627 | +MODULE_DESCRIPTION("Comedi helper for NI Mite PCI interface chip"); | |
| 626 | 628 | MODULE_LICENSE("GPL"); |
| @@ -1,32 +1,35 @@ | ||
| 1 | 1 | /* |
| 2 | − module/mite.h | |
| 3 | − Hardware driver for NI Mite PCI interface chip | |
| 4 | − | |
| 5 | − COMEDI - Linux Control and Measurement Device Interface | |
| 6 | − Copyright (C) 1999 David A. Schleef <ds@schleef.org> | |
| 7 | − | |
| 8 | − This program is free software; you can redistribute it and/or modify | |
| 9 | − it under the terms of the GNU General Public License as published by | |
| 10 | − the Free Software Foundation; either version 2 of the License, or | |
| 11 | − (at your option) any later version. | |
| 12 | − | |
| 13 | − This program is distributed in the hope that it will be useful, | |
| 14 | − but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | − MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | − GNU General Public License for more details. | |
| 17 | −*/ | |
| 2 | + * module/mite.h | |
| 3 | + * Hardware driver for NI Mite PCI interface chip | |
| 4 | + * | |
| 5 | + * COMEDI - Linux Control and Measurement Device Interface | |
| 6 | + * Copyright (C) 1999 David A. Schleef <ds@schleef.org> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * This program is distributed in the hope that it will be useful, | |
| 14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | + * GNU General Public License for more details. | |
| 17 | + */ | |
| 18 | 18 | |
| 19 | 19 | #ifndef _MITE_H_ |
| 20 | 20 | #define _MITE_H_ |
| 21 | 21 | |
| 22 | +#include <linux/io.h> | |
| 22 | 23 | #include <linux/log2.h> |
| 23 | −#include <linux/slab.h> | |
| 24 | −#include "../comedi_pci.h" | |
| 25 | − | |
| 26 | −#define PCIMIO_COMPAT | |
| 24 | +#include <linux/spinlock.h> | |
| 27 | 25 | |
| 28 | 26 | #define MAX_MITE_DMA_CHANNELS 8 |
| 29 | 27 | |
| 28 | +struct comedi_device; | |
| 29 | +struct comedi_subdevice; | |
| 30 | +struct device; | |
| 31 | +struct pci_dev; | |
| 32 | + | |
| 30 | 33 | struct mite_dma_descriptor { |
| 31 | 34 | __le32 count; |
| 32 | 35 | __le32 addr; |
| @@ -74,16 +77,13 @@ static inline int mite_setup(struct comedi_device *dev, · 41 unmodified lines | ||
| 74 | 77 | void mite_detach(struct mite_struct *mite); |
| 75 | 78 | struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite); |
| 76 | 79 | void mite_free_ring(struct mite_dma_descriptor_ring *ring); |
| 77 | −struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, | |
| 78 | − struct | |
| 79 | − mite_dma_descriptor_ring | |
| 80 | − *ring, unsigned min_channel, | |
| 81 | − unsigned max_channel); | |
| 82 | −static inline struct mite_channel *mite_request_channel(struct mite_struct | |
| 83 | − *mite, | |
| 84 | − struct | |
| 85 | − mite_dma_descriptor_ring | |
| 86 | − *ring) | |
| 80 | +struct mite_channel * | |
| 81 | +mite_request_channel_in_range(struct mite_struct *mite, | |
| 82 | + struct mite_dma_descriptor_ring *ring, | |
| 83 | + unsigned min_channel, unsigned max_channel); | |
| 84 | +static inline struct mite_channel * | |
| 85 | +mite_request_channel(struct mite_struct *mite, | |
| 86 | + struct mite_dma_descriptor_ring *ring) | |
| 87 | 87 | { |
| 88 | 88 | return mite_request_channel_in_range(mite, ring, 0, |
| 89 | 89 | mite->num_channels - 1); |
| @@ -112,12 +112,14 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, · 22 unmodified lines | ||
| 112 | 112 | struct comedi_subdevice *s); |
| 113 | 113 | |
| 114 | 114 | enum mite_registers { |
| 115 | − /* The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be | |
| 116 | − written and read back. The bits 0x1f always read as 1. | |
| 117 | − The rest always read as zero. */ | |
| 115 | + /* | |
| 116 | + * The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be | |
| 117 | + * written and read back. The bits 0x1f always read as 1. | |
| 118 | + * The rest always read as zero. | |
| 119 | + */ | |
| 118 | 120 | MITE_UNKNOWN_DMA_BURST_REG = 0x28, |
| 119 | 121 | MITE_IODWBSR = 0xc0, /* IO Device Window Base Size Register */ |
| 120 | − MITE_IODWBSR_1 = 0xc4, /* IO Device Window Base Size Register 1 */ | |
| 122 | + MITE_IODWBSR_1 = 0xc4, /* IO Device Window Base Size Register 1 */ | |
| 121 | 123 | MITE_IODWCR_1 = 0xf4, |
| 122 | 124 | MITE_PCI_CONFIG_OFFSET = 0x300, |
| 123 | 125 | MITE_CSIGR = 0x460 /* chip signature */ |
| @@ -143,7 +145,7 @@ enum mite_registers { · 19 unmodified lines | ||
| 143 | 145 | #define MITE_FCR(x) (0x40 + MITE_CHAN(x)) /* fifo count */ |
| 144 | 146 | |
| 145 | 147 | enum MITE_IODWBSR_bits { |
| 146 | − WENAB = 0x80, /* window enable */ | |
| 148 | + WENAB = 0x80, /* window enable */ | |
| 147 | 149 | }; |
| 148 | 150 | |
| 149 | 151 | static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size) |
| @@ -166,27 +168,27 @@ static inline int mite_csigr_version(u32 csigr_bits) · 16 unmodified lines | ||
| 166 | 168 | }; |
| 167 | 169 | |
| 168 | 170 | static inline int mite_csigr_type(u32 csigr_bits) |
| 169 | −{ /* original mite = 0, minimite = 1 */ | |
| 171 | +{ /* original mite = 0, minimite = 1 */ | |
| 170 | 172 | return (csigr_bits >> 4) & 0xf; |
| 171 | 173 | }; |
| 172 | 174 | |
| 173 | 175 | static inline int mite_csigr_mmode(u32 csigr_bits) |
| 174 | −{ /* mite mode, minimite = 1 */ | |
| 176 | +{ /* mite mode, minimite = 1 */ | |
| 175 | 177 | return (csigr_bits >> 8) & 0x3; |
| 176 | 178 | }; |
| 177 | 179 | |
| 178 | 180 | static inline int mite_csigr_imode(u32 csigr_bits) |
| 179 | −{ /* cpu port interface mode, pci = 0x3 */ | |
| 181 | +{ /* cpu port interface mode, pci = 0x3 */ | |
| 180 | 182 | return (csigr_bits >> 12) & 0x3; |
| 181 | 183 | }; |
| 182 | 184 | |
| 183 | 185 | static inline int mite_csigr_dmac(u32 csigr_bits) |
| 184 | −{ /* number of dma channels */ | |
| 186 | +{ /* number of dma channels */ | |
| 185 | 187 | return (csigr_bits >> 16) & 0xf; |
| 186 | 188 | }; |
| 187 | 189 | |
| 188 | 190 | static inline int mite_csigr_wpdep(u32 csigr_bits) |
| 189 | −{ /* write post fifo depth */ | |
| 191 | +{ /* write post fifo depth */ | |
| 190 | 192 | unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7; |
| 191 | 193 | |
| 192 | 194 | return (wpdep_bits) ? (1 << (wpdep_bits - 1)) : 0; |
| @@ -198,7 +200,7 @@ static inline int mite_csigr_wins(u32 csigr_bits) · 5 unmodified lines | ||
| 198 | 200 | }; |
| 199 | 201 | |
| 200 | 202 | static inline int mite_csigr_iowins(u32 csigr_bits) |
| 201 | −{ /* number of io windows */ | |
| 203 | +{ /* number of io windows */ | |
| 202 | 204 | return (csigr_bits >> 29) & 0x7; |
| 203 | 205 | }; |
| 204 | 206 | |
| @@ -280,6 +282,7 @@ enum ConfigRegister_bits { · 75 unmodified lines | ||
| 280 | 282 | CR_PORTMXI = (3 << 6), |
| 281 | 283 | CR_AMDEVICE = (1 << 0), |
| 282 | 284 | }; |
| 285 | + | |
| 283 | 286 | static inline int CR_REQS(int source) |
| 284 | 287 | { |
| 285 | 288 | return (source & 0x7) << 16; |
| @@ -287,8 +290,7 @@ static inline int CR_REQS(int source) · 1 unmodified line | ||
| 287 | 290 | |
| 288 | 291 | static inline int CR_REQSDRQ(unsigned drq_line) |
| 289 | 292 | { |
| 290 | − /* This also works on m-series when | |
| 291 | − using channels (drq_line) 4 or 5. */ | |
| 293 | + /* This also works on m-series when using channels (drq_line) 4 or 5. */ | |
| 292 | 294 | return CR_REQS((drq_line & 0x3) | 0x4); |
| 293 | 295 | } |
| 294 | 296 | |
| @@ -172,18 +172,18 @@ static int ni_670x_auto_attach(struct comedi_device *dev, · 171 unmodified lines | ||
| 172 | 172 | unsigned long context) |
| 173 | 173 | { |
| 174 | 174 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 175 | − const struct ni_670x_board *thisboard = NULL; | |
| 175 | + const struct ni_670x_board *board = NULL; | |
| 176 | 176 | struct ni_670x_private *devpriv; |
| 177 | 177 | struct comedi_subdevice *s; |
| 178 | 178 | int ret; |
| 179 | 179 | int i; |
| 180 | 180 | |
| 181 | 181 | if (context < ARRAY_SIZE(ni_670x_boards)) |
| 182 | − thisboard = &ni_670x_boards[context]; | |
| 183 | − if (!thisboard) | |
| 182 | + board = &ni_670x_boards[context]; | |
| 183 | + if (!board) | |
| 184 | 184 | return -ENODEV; |
| 185 | − dev->board_ptr = thisboard; | |
| 186 | − dev->board_name = thisboard->name; | |
| 185 | + dev->board_ptr = board; | |
| 186 | + dev->board_name = board->name; | |
| 187 | 187 | |
| 188 | 188 | ret = comedi_pci_enable(dev); |
| 189 | 189 | if (ret) |
| @@ -209,7 +209,7 @@ static int ni_670x_auto_attach(struct comedi_device *dev, · 19 unmodified lines | ||
| 209 | 209 | /* analog output subdevice */ |
| 210 | 210 | s->type = COMEDI_SUBD_AO; |
| 211 | 211 | s->subdev_flags = SDF_WRITABLE; |
| 212 | − s->n_chan = thisboard->ao_chans; | |
| 212 | + s->n_chan = board->ao_chans; | |
| 213 | 213 | s->maxdata = 0xffff; |
| 214 | 214 | if (s->n_chan == 32) { |
| 215 | 215 | const struct comedi_lrange **range_table_list; |
| @@ -106,7 +106,7 @@ TRIG_WAKE_EOS · 105 unmodified lines | ||
| 106 | 106 | #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ |
| 107 | 107 | #define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ |
| 108 | 108 | #define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */ |
| 109 | −#define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */ | |
| 109 | +#define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */ | |
| 110 | 110 | #define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ |
| 111 | 111 | #define I8253_BASE_REG 0x14 |
| 112 | 112 | |
| @@ -264,7 +264,7 @@ static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s) · 151 unmodified lines | ||
| 264 | 264 | static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, |
| 265 | 265 | unsigned int flags) |
| 266 | 266 | { |
| 267 | − const struct a2150_board *thisboard = dev->board_ptr; | |
| 267 | + const struct a2150_board *board = dev->board_ptr; | |
| 268 | 268 | struct a2150_private *devpriv = dev->private; |
| 269 | 269 | int lub, glb, temp; |
| 270 | 270 | int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; |
| @@ -273,10 +273,10 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, · 2 unmodified lines | ||
| 273 | 273 | /* initialize greatest lower and least upper bounds */ |
| 274 | 274 | lub_divisor_shift = 3; |
| 275 | 275 | lub_index = 0; |
| 276 | − lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift); | |
| 276 | + lub = board->clock[lub_index] * (1 << lub_divisor_shift); | |
| 277 | 277 | glb_divisor_shift = 0; |
| 278 | − glb_index = thisboard->num_clocks - 1; | |
| 279 | − glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift); | |
| 278 | + glb_index = board->num_clocks - 1; | |
| 279 | + glb = board->clock[glb_index] * (1 << glb_divisor_shift); | |
| 280 | 280 | |
| 281 | 281 | /* make sure period is in available range */ |
| 282 | 282 | if (*period < glb) |
| @@ -287,9 +287,9 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, · 4 unmodified lines | ||
| 287 | 287 | /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ |
| 288 | 288 | for (i = 0; i < 4; i++) { |
| 289 | 289 | /* there are a maximum of 4 master clocks */ |
| 290 | − for (j = 0; j < thisboard->num_clocks; j++) { | |
| 290 | + for (j = 0; j < board->num_clocks; j++) { | |
| 291 | 291 | /* temp is the period in nanosec we are evaluating */ |
| 292 | − temp = thisboard->clock[j] * (1 << i); | |
| 292 | + temp = board->clock[j] * (1 << i); | |
| 293 | 293 | /* if it is the best match yet */ |
| 294 | 294 | if (temp < lub && temp >= *period) { |
| 295 | 295 | lub_divisor_shift = i; |
| @@ -413,7 +413,7 @@ static int a2150_ai_check_chanlist(struct comedi_device *dev, · 117 unmodified lines | ||
| 413 | 413 | static int a2150_ai_cmdtest(struct comedi_device *dev, |
| 414 | 414 | struct comedi_subdevice *s, struct comedi_cmd *cmd) |
| 415 | 415 | { |
| 416 | − const struct a2150_board *thisboard = dev->board_ptr; | |
| 416 | + const struct a2150_board *board = dev->board_ptr; | |
| 417 | 417 | int err = 0; |
| 418 | 418 | unsigned int arg; |
| 419 | 419 | |
| @@ -444,7 +444,7 @@ static int a2150_ai_cmdtest(struct comedi_device *dev, · 24 unmodified lines | ||
| 444 | 444 | |
| 445 | 445 | if (cmd->convert_src == TRIG_TIMER) { |
| 446 | 446 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 447 | − thisboard->ai_speed); | |
| 447 | + board->ai_speed); | |
| 448 | 448 | } |
| 449 | 449 | |
| 450 | 450 | err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); |
| @@ -687,17 +687,19 @@ static void a2150_free_dma(struct comedi_device *dev) · 236 unmodified lines | ||
| 687 | 687 | comedi_isadma_free(devpriv->dma); |
| 688 | 688 | } |
| 689 | 689 | |
| 690 | −/* probes board type, returns offset */ | |
| 691 | −static int a2150_probe(struct comedi_device *dev) | |
| 690 | +static const struct a2150_board *a2150_probe(struct comedi_device *dev) | |
| 692 | 691 | { |
| 693 | − int status = inw(dev->iobase + STATUS_REG); | |
| 692 | + int id = ID_BITS(inw(dev->iobase + STATUS_REG)); | |
| 694 | 693 | |
| 695 | − return ID_BITS(status); | |
| 694 | + if (id >= ARRAY_SIZE(a2150_boards)) | |
| 695 | + return NULL; | |
| 696 | + | |
| 697 | + return &a2150_boards[id]; | |
| 696 | 698 | } |
| 697 | 699 | |
| 698 | 700 | static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) |
| 699 | 701 | { |
| 700 | − const struct a2150_board *thisboard; | |
| 702 | + const struct a2150_board *board; | |
| 701 | 703 | struct a2150_private *devpriv; |
| 702 | 704 | struct comedi_subdevice *s; |
| 703 | 705 | static const int timeout = 2000; |
| @@ -712,13 +714,11 @@ static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) · 8 unmodified lines | ||
| 712 | 714 | if (ret) |
| 713 | 715 | return ret; |
| 714 | 716 | |
| 715 | − i = a2150_probe(dev); | |
| 716 | − if (i >= ARRAY_SIZE(a2150_boards)) | |
| 717 | + board = a2150_probe(dev); | |
| 718 | + if (!board) | |
| 717 | 719 | return -ENODEV; |
| 718 | − | |
| 719 | − dev->board_ptr = a2150_boards + i; | |
| 720 | − thisboard = dev->board_ptr; | |
| 721 | − dev->board_name = thisboard->name; | |
| 720 | + dev->board_ptr = board; | |
| 721 | + dev->board_name = board->name; | |
| 722 | 722 | |
| 723 | 723 | /* an IRQ and DMA are required to support async commands */ |
| 724 | 724 | a2150_alloc_irq_and_dma(dev, it); |
| @@ -274,14 +274,16 @@ static int ni_isapnp_find_board(struct pnp_dev **dev) · 273 unmodified lines | ||
| 274 | 274 | return 0; |
| 275 | 275 | } |
| 276 | 276 | |
| 277 | −static int ni_getboardtype(struct comedi_device *dev) | |
| 277 | +static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev) | |
| 278 | 278 | { |
| 279 | 279 | int device_id = ni_read_eeprom(dev, 511); |
| 280 | 280 | int i; |
| 281 | 281 | |
| 282 | 282 | for (i = 0; i < ARRAY_SIZE(ni_boards); i++) { |
| 283 | − if (ni_boards[i].device_id == device_id) | |
| 284 | − return i; | |
| 283 | + const struct ni_board_struct *board = &ni_boards[i]; | |
| 284 | + | |
| 285 | + if (board->device_id == device_id) | |
| 286 | + return board; | |
| 285 | 287 | } |
| 286 | 288 | if (device_id == 255) |
| 287 | 289 | dev_err(dev->class_dev, "can't find board\n"); |
| @@ -292,17 +294,16 @@ static int ni_getboardtype(struct comedi_device *dev) · 4 unmodified lines | ||
| 292 | 294 | dev_err(dev->class_dev, |
| 293 | 295 | "unknown device ID %d -- contact author\n", device_id); |
| 294 | 296 | |
| 295 | − return -1; | |
| 297 | + return NULL; | |
| 296 | 298 | } |
| 297 | 299 | |
| 298 | 300 | static int ni_atmio_attach(struct comedi_device *dev, |
| 299 | 301 | struct comedi_devconfig *it) |
| 300 | 302 | { |
| 301 | − const struct ni_board_struct *boardtype; | |
| 303 | + const struct ni_board_struct *board; | |
| 302 | 304 | struct pnp_dev *isapnp_dev; |
| 303 | 305 | int ret; |
| 304 | 306 | unsigned long iobase; |
| 305 | − int board; | |
| 306 | 307 | unsigned int irq; |
| 307 | 308 | |
| 308 | 309 | ret = ni_alloc_private(dev); |
| @@ -326,15 +327,11 @@ static int ni_atmio_attach(struct comedi_device *dev, · 17 unmodified lines | ||
| 326 | 327 | if (ret) |
| 327 | 328 | return ret; |
| 328 | 329 | |
| 329 | − /* get board type */ | |
| 330 | − | |
| 331 | − board = ni_getboardtype(dev); | |
| 332 | − if (board < 0) | |
| 333 | − return -EIO; | |
| 334 | − | |
| 335 | − dev->board_ptr = ni_boards + board; | |
| 336 | − boardtype = dev->board_ptr; | |
| 337 | − dev->board_name = boardtype->name; | |
| 330 | + board = ni_atmio_probe(dev); | |
| 331 | + if (!board) | |
| 332 | + return -ENODEV; | |
| 333 | + dev->board_ptr = board; | |
| 334 | + dev->board_name = board->name; | |
| 338 | 335 | |
| 339 | 336 | /* irq stuff */ |
| 340 | 337 | |
| @@ -60,7 +60,6 @@ · 59 unmodified lines | ||
| 60 | 60 | |
| 61 | 61 | /* A timeout count */ |
| 62 | 62 | #define NI_TIMEOUT 1000 |
| 63 | −static const unsigned old_RTSI_clock_channel = 7; | |
| 64 | 63 | |
| 65 | 64 | /* Note: this table must match the ai_gain_* definitions */ |
| 66 | 65 | static const short ni_gainlkup[][16] = { |
| @@ -308,262 +307,154 @@ static uint8_t ni_readb(struct comedi_device *dev, int reg) · 241 unmodified lines | ||
| 308 | 307 | * windowed STC registers to the m series register offsets. |
| 309 | 308 | */ |
| 310 | 309 | |
| 311 | −static void m_series_stc_writel(struct comedi_device *dev, | |
| 312 | − uint32_t data, int reg) | |
| 310 | +struct mio_regmap { | |
| 311 | + unsigned int mio_reg; | |
| 312 | + int size; | |
| 313 | +}; | |
| 314 | + | |
| 315 | +static const struct mio_regmap m_series_stc_write_regmap[] = { | |
| 316 | + [NISTC_INTA_ACK_REG] = { 0x104, 2 }, | |
| 317 | + [NISTC_INTB_ACK_REG] = { 0x106, 2 }, | |
| 318 | + [NISTC_AI_CMD2_REG] = { 0x108, 2 }, | |
| 319 | + [NISTC_AO_CMD2_REG] = { 0x10a, 2 }, | |
| 320 | + [NISTC_G0_CMD_REG] = { 0x10c, 2 }, | |
| 321 | + [NISTC_G1_CMD_REG] = { 0x10e, 2 }, | |
| 322 | + [NISTC_AI_CMD1_REG] = { 0x110, 2 }, | |
| 323 | + [NISTC_AO_CMD1_REG] = { 0x112, 2 }, | |
| 324 | + /* | |
| 325 | + * NISTC_DIO_OUT_REG maps to: | |
| 326 | + * { NI_M_DIO_REG, 4 } and { NI_M_SCXI_SER_DO_REG, 1 } | |
| 327 | + */ | |
| 328 | + [NISTC_DIO_OUT_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */ | |
| 329 | + [NISTC_DIO_CTRL_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */ | |
| 330 | + [NISTC_AI_MODE1_REG] = { 0x118, 2 }, | |
| 331 | + [NISTC_AI_MODE2_REG] = { 0x11a, 2 }, | |
| 332 | + [NISTC_AI_SI_LOADA_REG] = { 0x11c, 4 }, | |
| 333 | + [NISTC_AI_SI_LOADB_REG] = { 0x120, 4 }, | |
| 334 | + [NISTC_AI_SC_LOADA_REG] = { 0x124, 4 }, | |
| 335 | + [NISTC_AI_SC_LOADB_REG] = { 0x128, 4 }, | |
| 336 | + [NISTC_AI_SI2_LOADA_REG] = { 0x12c, 4 }, | |
| 337 | + [NISTC_AI_SI2_LOADB_REG] = { 0x130, 4 }, | |
| 338 | + [NISTC_G0_MODE_REG] = { 0x134, 2 }, | |
| 339 | + [NISTC_G1_MODE_REG] = { 0x136, 2 }, | |
| 340 | + [NISTC_G0_LOADA_REG] = { 0x138, 4 }, | |
| 341 | + [NISTC_G0_LOADB_REG] = { 0x13c, 4 }, | |
| 342 | + [NISTC_G1_LOADA_REG] = { 0x140, 4 }, | |
| 343 | + [NISTC_G1_LOADB_REG] = { 0x144, 4 }, | |
| 344 | + [NISTC_G0_INPUT_SEL_REG] = { 0x148, 2 }, | |
| 345 | + [NISTC_G1_INPUT_SEL_REG] = { 0x14a, 2 }, | |
| 346 | + [NISTC_AO_MODE1_REG] = { 0x14c, 2 }, | |
| 347 | + [NISTC_AO_MODE2_REG] = { 0x14e, 2 }, | |
| 348 | + [NISTC_AO_UI_LOADA_REG] = { 0x150, 4 }, | |
| 349 | + [NISTC_AO_UI_LOADB_REG] = { 0x154, 4 }, | |
| 350 | + [NISTC_AO_BC_LOADA_REG] = { 0x158, 4 }, | |
| 351 | + [NISTC_AO_BC_LOADB_REG] = { 0x15c, 4 }, | |
| 352 | + [NISTC_AO_UC_LOADA_REG] = { 0x160, 4 }, | |
| 353 | + [NISTC_AO_UC_LOADB_REG] = { 0x164, 4 }, | |
| 354 | + [NISTC_CLK_FOUT_REG] = { 0x170, 2 }, | |
| 355 | + [NISTC_IO_BIDIR_PIN_REG] = { 0x172, 2 }, | |
| 356 | + [NISTC_RTSI_TRIG_DIR_REG] = { 0x174, 2 }, | |
| 357 | + [NISTC_INT_CTRL_REG] = { 0x176, 2 }, | |
| 358 | + [NISTC_AI_OUT_CTRL_REG] = { 0x178, 2 }, | |
| 359 | + [NISTC_ATRIG_ETC_REG] = { 0x17a, 2 }, | |
| 360 | + [NISTC_AI_START_STOP_REG] = { 0x17c, 2 }, | |
| 361 | + [NISTC_AI_TRIG_SEL_REG] = { 0x17e, 2 }, | |
| 362 | + [NISTC_AI_DIV_LOADA_REG] = { 0x180, 4 }, | |
| 363 | + [NISTC_AO_START_SEL_REG] = { 0x184, 2 }, | |
| 364 | + [NISTC_AO_TRIG_SEL_REG] = { 0x186, 2 }, | |
| 365 | + [NISTC_G0_AUTOINC_REG] = { 0x188, 2 }, | |
| 366 | + [NISTC_G1_AUTOINC_REG] = { 0x18a, 2 }, | |
| 367 | + [NISTC_AO_MODE3_REG] = { 0x18c, 2 }, | |
| 368 | + [NISTC_RESET_REG] = { 0x190, 2 }, | |
| 369 | + [NISTC_INTA_ENA_REG] = { 0x192, 2 }, | |
| 370 | + [NISTC_INTA2_ENA_REG] = { 0, 0 }, /* E-Series only */ | |
| 371 | + [NISTC_INTB_ENA_REG] = { 0x196, 2 }, | |
| 372 | + [NISTC_INTB2_ENA_REG] = { 0, 0 }, /* E-Series only */ | |
| 373 | + [NISTC_AI_PERSONAL_REG] = { 0x19a, 2 }, | |
| 374 | + [NISTC_AO_PERSONAL_REG] = { 0x19c, 2 }, | |
| 375 | + [NISTC_RTSI_TRIGA_OUT_REG] = { 0x19e, 2 }, | |
| 376 | + [NISTC_RTSI_TRIGB_OUT_REG] = { 0x1a0, 2 }, | |
| 377 | + [NISTC_RTSI_BOARD_REG] = { 0, 0 }, /* Unknown */ | |
| 378 | + [NISTC_CFG_MEM_CLR_REG] = { 0x1a4, 2 }, | |
| 379 | + [NISTC_ADC_FIFO_CLR_REG] = { 0x1a6, 2 }, | |
| 380 | + [NISTC_DAC_FIFO_CLR_REG] = { 0x1a8, 2 }, | |
| 381 | + [NISTC_AO_OUT_CTRL_REG] = { 0x1ac, 2 }, | |
| 382 | + [NISTC_AI_MODE3_REG] = { 0x1ae, 2 }, | |
| 383 | +}; | |
| 384 | + | |
| 385 | +static void m_series_stc_write(struct comedi_device *dev, | |
| 386 | + unsigned int data, unsigned int reg) | |
| 313 | 387 | { |
| 314 | − unsigned offset; | |
| 388 | + const struct mio_regmap *regmap; | |
| 315 | 389 | |
| 316 | − switch (reg) { | |
| 317 | − case AI_SC_Load_A_Registers: | |
| 318 | − offset = M_Offset_AI_SC_Load_A; | |
| 319 | − break; | |
| 320 | − case AI_SI_Load_A_Registers: | |
| 321 | − offset = M_Offset_AI_SI_Load_A; | |
| 322 | − break; | |
| 323 | − case AO_BC_Load_A_Register: | |
| 324 | − offset = M_Offset_AO_BC_Load_A; | |
| 325 | − break; | |
| 326 | − case AO_UC_Load_A_Register: | |
| 327 | − offset = M_Offset_AO_UC_Load_A; | |
| 328 | − break; | |
| 329 | − case AO_UI_Load_A_Register: | |
| 330 | − offset = M_Offset_AO_UI_Load_A; | |
| 331 | − break; | |
| 332 | − case G_Load_A_Register(0): | |
| 333 | − offset = M_Offset_G0_Load_A; | |
| 334 | − break; | |
| 335 | − case G_Load_A_Register(1): | |
| 336 | − offset = M_Offset_G1_Load_A; | |
| 337 | − break; | |
| 338 | − case G_Load_B_Register(0): | |
| 339 | − offset = M_Offset_G0_Load_B; | |
| 340 | − break; | |
| 341 | − case G_Load_B_Register(1): | |
| 342 | − offset = M_Offset_G1_Load_B; | |
| 343 | − break; | |
| 344 | − default: | |
| 345 | − dev_warn(dev->class_dev, | |
| 346 | − "%s: bug! unhandled register=0x%x in switch\n", | |
| 390 | + if (reg < ARRAY_SIZE(m_series_stc_write_regmap)) { | |
| 391 | + regmap = &m_series_stc_write_regmap[reg]; | |
| 392 | + } else { | |
| 393 | + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", | |
| 347 | 394 | __func__, reg); |
| 348 | 395 | return; |
| 349 | 396 | } |
| 350 | − ni_writel(dev, data, offset); | |
| 351 | −} | |
| 352 | 397 | |
| 353 | −static void m_series_stc_writew(struct comedi_device *dev, | |
| 354 | − uint16_t data, int reg) | |
| 355 | −{ | |
| 356 | − unsigned offset; | |
| 357 | − | |
| 358 | − switch (reg) { | |
| 359 | − case ADC_FIFO_Clear: | |
| 360 | − offset = M_Offset_AI_FIFO_Clear; | |
| 361 | − break; | |
| 362 | − case AI_Command_1_Register: | |
| 363 | − offset = M_Offset_AI_Command_1; | |
| 364 | − break; | |
| 365 | − case AI_Command_2_Register: | |
| 366 | − offset = M_Offset_AI_Command_2; | |
| 367 | − break; | |
| 368 | − case AI_Mode_1_Register: | |
| 369 | − offset = M_Offset_AI_Mode_1; | |
| 370 | − break; | |
| 371 | − case AI_Mode_2_Register: | |
| 372 | − offset = M_Offset_AI_Mode_2; | |
| 373 | − break; | |
| 374 | − case AI_Mode_3_Register: | |
| 375 | − offset = M_Offset_AI_Mode_3; | |
| 376 | − break; | |
| 377 | − case AI_Output_Control_Register: | |
| 378 | − offset = M_Offset_AI_Output_Control; | |
| 379 | − break; | |
| 380 | − case AI_Personal_Register: | |
| 381 | − offset = M_Offset_AI_Personal; | |
| 382 | − break; | |
| 383 | − case AI_SI2_Load_A_Register: | |
| 384 | − /* this is a 32 bit register on m series boards */ | |
| 385 | − ni_writel(dev, data, M_Offset_AI_SI2_Load_A); | |
| 386 | − return; | |
| 387 | − case AI_SI2_Load_B_Register: | |
| 388 | − /* this is a 32 bit register on m series boards */ | |
| 389 | − ni_writel(dev, data, M_Offset_AI_SI2_Load_B); | |
| 390 | − return; | |
| 391 | − case AI_START_STOP_Select_Register: | |
| 392 | − offset = M_Offset_AI_START_STOP_Select; | |
| 393 | − break; | |
| 394 | − case AI_Trigger_Select_Register: | |
| 395 | − offset = M_Offset_AI_Trigger_Select; | |
| 396 | − break; | |
| 397 | − case Analog_Trigger_Etc_Register: | |
| 398 | − offset = M_Offset_Analog_Trigger_Etc; | |
| 399 | − break; | |
| 400 | − case AO_Command_1_Register: | |
| 401 | − offset = M_Offset_AO_Command_1; | |
| 402 | − break; | |
| 403 | − case AO_Command_2_Register: | |
| 404 | − offset = M_Offset_AO_Command_2; | |
| 405 | − break; | |
| 406 | − case AO_Mode_1_Register: | |
| 407 | − offset = M_Offset_AO_Mode_1; | |
| 408 | − break; | |
| 409 | − case AO_Mode_2_Register: | |
| 410 | − offset = M_Offset_AO_Mode_2; | |
| 411 | − break; | |
| 412 | − case AO_Mode_3_Register: | |
| 413 | − offset = M_Offset_AO_Mode_3; | |
| 414 | − break; | |
| 415 | − case AO_Output_Control_Register: | |
| 416 | − offset = M_Offset_AO_Output_Control; | |
| 417 | − break; | |
| 418 | − case AO_Personal_Register: | |
| 419 | − offset = M_Offset_AO_Personal; | |
| 420 | − break; | |
| 421 | − case AO_Start_Select_Register: | |
| 422 | − offset = M_Offset_AO_Start_Select; | |
| 423 | − break; | |
| 424 | − case AO_Trigger_Select_Register: | |
| 425 | − offset = M_Offset_AO_Trigger_Select; | |
| 426 | − break; | |
| 427 | − case Clock_and_FOUT_Register: | |
| 428 | − offset = M_Offset_Clock_and_FOUT; | |
| 429 | − break; | |
| 430 | − case Configuration_Memory_Clear: | |
| 431 | − offset = M_Offset_Configuration_Memory_Clear; | |
| 432 | − break; | |
| 433 | − case DAC_FIFO_Clear: | |
| 434 | − offset = M_Offset_AO_FIFO_Clear; | |
| 435 | − break; | |
| 436 | − case DIO_Control_Register: | |
| 437 | − dev_dbg(dev->class_dev, | |
| 438 | − "%s: FIXME: register 0x%x does not map cleanly on to m-series boards\n", | |
| 439 | − __func__, reg); | |
| 440 | − return; | |
| 441 | − case G_Autoincrement_Register(0): | |
| 442 | − offset = M_Offset_G0_Autoincrement; | |
| 443 | − break; | |
| 444 | − case G_Autoincrement_Register(1): | |
| 445 | − offset = M_Offset_G1_Autoincrement; | |
| 446 | − break; | |
| 447 | − case G_Command_Register(0): | |
| 448 | − offset = M_Offset_G0_Command; | |
| 449 | − break; | |
| 450 | − case G_Command_Register(1): | |
| 451 | − offset = M_Offset_G1_Command; | |
| 452 | − break; | |
| 453 | − case G_Input_Select_Register(0): | |
| 454 | − offset = M_Offset_G0_Input_Select; | |
| 455 | − break; | |
| 456 | − case G_Input_Select_Register(1): | |
| 457 | − offset = M_Offset_G1_Input_Select; | |
| 458 | − break; | |
| 459 | − case G_Mode_Register(0): | |
| 460 | − offset = M_Offset_G0_Mode; | |
| 461 | − break; | |
| 462 | − case G_Mode_Register(1): | |
| 463 | − offset = M_Offset_G1_Mode; | |
| 464 | − break; | |
| 465 | − case Interrupt_A_Ack_Register: | |
| 466 | − offset = M_Offset_Interrupt_A_Ack; | |
| 467 | − break; | |
| 468 | − case Interrupt_A_Enable_Register: | |
| 469 | − offset = M_Offset_Interrupt_A_Enable; | |
| 470 | − break; | |
| 471 | − case Interrupt_B_Ack_Register: | |
| 472 | − offset = M_Offset_Interrupt_B_Ack; | |
| 473 | − break; | |
| 474 | − case Interrupt_B_Enable_Register: | |
| 475 | − offset = M_Offset_Interrupt_B_Enable; | |
| 476 | − break; | |
| 477 | − case Interrupt_Control_Register: | |
| 478 | − offset = M_Offset_Interrupt_Control; | |
| 479 | − break; | |
| 480 | − case IO_Bidirection_Pin_Register: | |
| 481 | − offset = M_Offset_IO_Bidirection_Pin; | |
| 482 | − break; | |
| 483 | − case Joint_Reset_Register: | |
| 484 | − offset = M_Offset_Joint_Reset; | |
| 485 | − break; | |
| 486 | − case RTSI_Trig_A_Output_Register: | |
| 487 | − offset = M_Offset_RTSI_Trig_A_Output; | |
| 488 | − break; | |
| 489 | − case RTSI_Trig_B_Output_Register: | |
| 490 | − offset = M_Offset_RTSI_Trig_B_Output; | |
| 398 | + switch (regmap->size) { | |
| 399 | + case 4: | |
| 400 | + ni_writel(dev, data, regmap->mio_reg); | |
| 491 | 401 | break; |
| 492 | − case RTSI_Trig_Direction_Register: | |
| 493 | − offset = M_Offset_RTSI_Trig_Direction; | |
| 402 | + case 2: | |
| 403 | + ni_writew(dev, data, regmap->mio_reg); | |
| 494 | 404 | break; |
| 495 | − /* | |
| 496 | − * FIXME: DIO_Output_Register (16 bit reg) is replaced by | |
| 497 | − * M_Offset_Static_Digital_Output (32 bit) and | |
| 498 | − * M_Offset_SCXI_Serial_Data_Out (8 bit) | |
| 499 | − */ | |
| 500 | 405 | default: |
| 501 | − dev_warn(dev->class_dev, | |
| 502 | − "%s: bug! unhandled register=0x%x in switch\n", | |
| 406 | + dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n", | |
| 503 | 407 | __func__, reg); |
| 504 | − return; | |
| 408 | + break; | |
| 505 | 409 | } |
| 506 | − ni_writew(dev, data, offset); | |
| 507 | 410 | } |
| 508 | 411 | |
| 509 | −static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg) | |
| 412 | +static const struct mio_regmap m_series_stc_read_regmap[] = { | |
| 413 | + [NISTC_AI_STATUS1_REG] = { 0x104, 2 }, | |
| 414 | + [NISTC_AO_STATUS1_REG] = { 0x106, 2 }, | |
| 415 | + [NISTC_G01_STATUS_REG] = { 0x108, 2 }, | |
| 416 | + [NISTC_AI_STATUS2_REG] = { 0, 0 }, /* Unknown */ | |
| 417 | + [NISTC_AO_STATUS2_REG] = { 0x10c, 2 }, | |
| 418 | + [NISTC_DIO_IN_REG] = { 0, 0 }, /* Unknown */ | |
| 419 | + [NISTC_G0_HW_SAVE_REG] = { 0x110, 4 }, | |
| 420 | + [NISTC_G1_HW_SAVE_REG] = { 0x114, 4 }, | |
| 421 | + [NISTC_G0_SAVE_REG] = { 0x118, 4 }, | |
| 422 | + [NISTC_G1_SAVE_REG] = { 0x11c, 4 }, | |
| 423 | + [NISTC_AO_UI_SAVE_REG] = { 0x120, 4 }, | |
| 424 | + [NISTC_AO_BC_SAVE_REG] = { 0x124, 4 }, | |
| 425 | + [NISTC_AO_UC_SAVE_REG] = { 0x128, 4 }, | |
| 426 | + [NISTC_STATUS1_REG] = { 0x136, 2 }, | |
| 427 | + [NISTC_DIO_SERIAL_IN_REG] = { 0x009, 1 }, | |
| 428 | + [NISTC_STATUS2_REG] = { 0x13a, 2 }, | |
| 429 | + [NISTC_AI_SI_SAVE_REG] = { 0x180, 4 }, | |
| 430 | + [NISTC_AI_SC_SAVE_REG] = { 0x184, 4 }, | |
| 431 | +}; | |
| 432 | + | |
| 433 | +static unsigned int m_series_stc_read(struct comedi_device *dev, | |
| 434 | + unsigned int reg) | |
| 510 | 435 | { |
| 511 | − unsigned offset; | |
| 436 | + const struct mio_regmap *regmap; | |
| 512 | 437 | |
| 513 | − switch (reg) { | |
| 514 | − case G_HW_Save_Register(0): | |
| 515 | − offset = M_Offset_G0_HW_Save; | |
| 516 | − break; | |
| 517 | − case G_HW_Save_Register(1): | |
| 518 | − offset = M_Offset_G1_HW_Save; | |
| 519 | − break; | |
| 520 | − case G_Save_Register(0): | |
| 521 | − offset = M_Offset_G0_Save; | |
| 522 | − break; | |
| 523 | − case G_Save_Register(1): | |
| 524 | − offset = M_Offset_G1_Save; | |
| 525 | − break; | |
| 526 | − default: | |
| 527 | − dev_warn(dev->class_dev, | |
| 528 | − "%s: bug! unhandled register=0x%x in switch\n", | |
| 438 | + if (reg < ARRAY_SIZE(m_series_stc_read_regmap)) { | |
| 439 | + regmap = &m_series_stc_read_regmap[reg]; | |
| 440 | + } else { | |
| 441 | + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", | |
| 529 | 442 | __func__, reg); |
| 530 | 443 | return 0; |
| 531 | 444 | } |
| 532 | − return ni_readl(dev, offset); | |
| 533 | −} | |
| 534 | 445 | |
| 535 | −static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg) | |
| 536 | −{ | |
| 537 | − unsigned offset; | |
| 538 | − | |
| 539 | − switch (reg) { | |
| 540 | − case AI_Status_1_Register: | |
| 541 | − offset = M_Offset_AI_Status_1; | |
| 542 | − break; | |
| 543 | − case AO_Status_1_Register: | |
| 544 | − offset = M_Offset_AO_Status_1; | |
| 545 | − break; | |
| 546 | − case AO_Status_2_Register: | |
| 547 | − offset = M_Offset_AO_Status_2; | |
| 548 | − break; | |
| 549 | − case DIO_Serial_Input_Register: | |
| 550 | − return ni_readb(dev, M_Offset_SCXI_Serial_Data_In); | |
| 551 | − case Joint_Status_1_Register: | |
| 552 | − offset = M_Offset_Joint_Status_1; | |
| 553 | − break; | |
| 554 | − case Joint_Status_2_Register: | |
| 555 | − offset = M_Offset_Joint_Status_2; | |
| 556 | − break; | |
| 557 | − case G_Status_Register: | |
| 558 | − offset = M_Offset_G01_Status; | |
| 559 | − break; | |
| 446 | + switch (regmap->size) { | |
| 447 | + case 4: | |
| 448 | + return ni_readl(dev, regmap->mio_reg); | |
| 449 | + case 2: | |
| 450 | + return ni_readw(dev, regmap->mio_reg); | |
| 451 | + case 1: | |
| 452 | + return ni_readb(dev, regmap->mio_reg); | |
| 560 | 453 | default: |
| 561 | − dev_warn(dev->class_dev, | |
| 562 | − "%s: bug! unhandled register=0x%x in switch\n", | |
| 454 | + dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n", | |
| 563 | 455 | __func__, reg); |
| 564 | 456 | return 0; |
| 565 | 457 | } |
| 566 | − return ni_readw(dev, offset); | |
| 567 | 458 | } |
| 568 | 459 | |
| 569 | 460 | static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg) |
| @@ -572,14 +463,14 @@ static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg) · 2 unmodified lines | ||
| 572 | 463 | unsigned long flags; |
| 573 | 464 | |
| 574 | 465 | if (devpriv->is_m_series) { |
| 575 | − m_series_stc_writew(dev, data, reg); | |
| 466 | + m_series_stc_write(dev, data, reg); | |
| 576 | 467 | } else { |
| 577 | 468 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 578 | 469 | if (!devpriv->mite && reg < 8) { |
| 579 | 470 | ni_writew(dev, data, reg * 2); |
| 580 | 471 | } else { |
| 581 | − ni_writew(dev, reg, Window_Address); | |
| 582 | − ni_writew(dev, data, Window_Data); | |
| 472 | + ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG); | |
| 473 | + ni_writew(dev, data, NI_E_STC_WINDOW_DATA_REG); | |
| 583 | 474 | } |
| 584 | 475 | spin_unlock_irqrestore(&devpriv->window_lock, flags); |
| 585 | 476 | } |
| @@ -590,7 +481,7 @@ static void ni_stc_writel(struct comedi_device *dev, uint32_t data, int reg) · 4 unmodified lines | ||
| 590 | 481 | struct ni_private *devpriv = dev->private; |
| 591 | 482 | |
| 592 | 483 | if (devpriv->is_m_series) { |
| 593 | − m_series_stc_writel(dev, data, reg); | |
| 484 | + m_series_stc_write(dev, data, reg); | |
| 594 | 485 | } else { |
| 595 | 486 | ni_stc_writew(dev, data >> 16, reg); |
| 596 | 487 | ni_stc_writew(dev, data & 0xffff, reg + 1); |
| @@ -604,14 +495,14 @@ static uint16_t ni_stc_readw(struct comedi_device *dev, int reg) · 7 unmodified lines | ||
| 604 | 495 | uint16_t val; |
| 605 | 496 | |
| 606 | 497 | if (devpriv->is_m_series) { |
| 607 | − val = m_series_stc_readw(dev, reg); | |
| 498 | + val = m_series_stc_read(dev, reg); | |
| 608 | 499 | } else { |
| 609 | 500 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 610 | 501 | if (!devpriv->mite && reg < 8) { |
| 611 | 502 | val = ni_readw(dev, reg * 2); |
| 612 | 503 | } else { |
| 613 | − ni_writew(dev, reg, Window_Address); | |
| 614 | − val = ni_readw(dev, Window_Data); | |
| 504 | + ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG); | |
| 505 | + val = ni_readw(dev, NI_E_STC_WINDOW_DATA_REG); | |
| 615 | 506 | } |
| 616 | 507 | spin_unlock_irqrestore(&devpriv->window_lock, flags); |
| 617 | 508 | } |
| @@ -624,7 +515,7 @@ static uint32_t ni_stc_readl(struct comedi_device *dev, int reg) · 6 unmodified lines | ||
| 624 | 515 | uint32_t val; |
| 625 | 516 | |
| 626 | 517 | if (devpriv->is_m_series) { |
| 627 | − val = m_series_stc_readl(dev, reg); | |
| 518 | + val = m_series_stc_read(dev, reg); | |
| 628 | 519 | } else { |
| 629 | 520 | val = ni_stc_readw(dev, reg) << 16; |
| 630 | 521 | val |= ni_stc_readw(dev, reg + 1); |
| @@ -640,33 +531,30 @@ static inline void ni_set_bitfield(struct comedi_device *dev, int reg, · 9 unmodified lines | ||
| 640 | 531 | |
| 641 | 532 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); |
| 642 | 533 | switch (reg) { |
| 643 | − case Interrupt_A_Enable_Register: | |
| 534 | + case NISTC_INTA_ENA_REG: | |
| 644 | 535 | devpriv->int_a_enable_reg &= ~bit_mask; |
| 645 | 536 | devpriv->int_a_enable_reg |= bit_values & bit_mask; |
| 646 | − ni_stc_writew(dev, devpriv->int_a_enable_reg, | |
| 647 | − Interrupt_A_Enable_Register); | |
| 537 | + ni_stc_writew(dev, devpriv->int_a_enable_reg, reg); | |
| 648 | 538 | break; |
| 649 | − case Interrupt_B_Enable_Register: | |
| 539 | + case NISTC_INTB_ENA_REG: | |
| 650 | 540 | devpriv->int_b_enable_reg &= ~bit_mask; |
| 651 | 541 | devpriv->int_b_enable_reg |= bit_values & bit_mask; |
| 652 | − ni_stc_writew(dev, devpriv->int_b_enable_reg, | |
| 653 | − Interrupt_B_Enable_Register); | |
| 542 | + ni_stc_writew(dev, devpriv->int_b_enable_reg, reg); | |
| 654 | 543 | break; |
| 655 | − case IO_Bidirection_Pin_Register: | |
| 544 | + case NISTC_IO_BIDIR_PIN_REG: | |
| 656 | 545 | devpriv->io_bidirection_pin_reg &= ~bit_mask; |
| 657 | 546 | devpriv->io_bidirection_pin_reg |= bit_values & bit_mask; |
| 658 | − ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, | |
| 659 | − IO_Bidirection_Pin_Register); | |
| 547 | + ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, reg); | |
| 660 | 548 | break; |
| 661 | − case AI_AO_Select: | |
| 549 | + case NI_E_DMA_AI_AO_SEL_REG: | |
| 662 | 550 | devpriv->ai_ao_select_reg &= ~bit_mask; |
| 663 | 551 | devpriv->ai_ao_select_reg |= bit_values & bit_mask; |
| 664 | − ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select); | |
| 552 | + ni_writeb(dev, devpriv->ai_ao_select_reg, reg); | |
| 665 | 553 | break; |
| 666 | − case G0_G1_Select: | |
| 554 | + case NI_E_DMA_G0_G1_SEL_REG: | |
| 667 | 555 | devpriv->g0_g1_select_reg &= ~bit_mask; |
| 668 | 556 | devpriv->g0_g1_select_reg |= bit_values & bit_mask; |
| 669 | − ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select); | |
| 557 | + ni_writeb(dev, devpriv->g0_g1_select_reg, reg); | |
| 670 | 558 | break; |
| 671 | 559 | default: |
| 672 | 560 | dev_err(dev->class_dev, "called with invalid register %d\n", |
| @@ -679,48 +567,55 @@ static inline void ni_set_bitfield(struct comedi_device *dev, int reg, · 6 unmodified lines | ||
| 679 | 567 | |
| 680 | 568 | #ifdef PCIDMA |
| 681 | 569 | /* DMA channel setup */ |
| 570 | +static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel) | |
| 571 | +{ | |
| 572 | + if (channel < 4) | |
| 573 | + return 1 << channel; | |
| 574 | + if (channel == 4) | |
| 575 | + return 0x3; | |
| 576 | + if (channel == 5) | |
| 577 | + return 0x5; | |
| 578 | + BUG(); | |
| 579 | + return 0; | |
| 580 | +} | |
| 682 | 581 | |
| 683 | 582 | /* negative channel means no channel */ |
| 684 | 583 | static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel) |
| 685 | 584 | { |
| 686 | − unsigned bitfield; | |
| 585 | + unsigned bits = 0; | |
| 687 | 586 | |
| 688 | 587 | if (channel >= 0) |
| 689 | − bitfield = | |
| 690 | − (ni_stc_dma_channel_select_bitfield(channel) << | |
| 691 | − AI_DMA_Select_Shift) & AI_DMA_Select_Mask; | |
| 692 | − else | |
| 693 | − bitfield = 0; | |
| 694 | − ni_set_bitfield(dev, AI_AO_Select, AI_DMA_Select_Mask, bitfield); | |
| 588 | + bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 589 | + | |
| 590 | + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, | |
| 591 | + NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); | |
| 695 | 592 | } |
| 696 | 593 | |
| 697 | 594 | /* negative channel means no channel */ |
| 698 | 595 | static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel) |
| 699 | 596 | { |
| 700 | − unsigned bitfield; | |
| 597 | + unsigned bits = 0; | |
| 701 | 598 | |
| 702 | 599 | if (channel >= 0) |
| 703 | − bitfield = | |
| 704 | − (ni_stc_dma_channel_select_bitfield(channel) << | |
| 705 | − AO_DMA_Select_Shift) & AO_DMA_Select_Mask; | |
| 706 | − else | |
| 707 | − bitfield = 0; | |
| 708 | − ni_set_bitfield(dev, AI_AO_Select, AO_DMA_Select_Mask, bitfield); | |
| 600 | + bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 601 | + | |
| 602 | + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, | |
| 603 | + NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits)); | |
| 709 | 604 | } |
| 710 | 605 | |
| 711 | −/* negative mite_channel means no channel */ | |
| 606 | +/* negative channel means no channel */ | |
| 712 | 607 | static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, |
| 713 | 608 | unsigned gpct_index, |
| 714 | − int mite_channel) | |
| 609 | + int channel) | |
| 715 | 610 | { |
| 716 | − unsigned bitfield; | |
| 611 | + unsigned bits = 0; | |
| 717 | 612 | |
| 718 | − if (mite_channel >= 0) | |
| 719 | − bitfield = GPCT_DMA_Select_Bits(gpct_index, mite_channel); | |
| 720 | − else | |
| 721 | − bitfield = 0; | |
| 722 | − ni_set_bitfield(dev, G0_G1_Select, GPCT_DMA_Select_Mask(gpct_index), | |
| 723 | − bitfield); | |
| 613 | + if (channel >= 0) | |
| 614 | + bits = ni_stc_dma_channel_select_bitfield(channel); | |
| 615 | + | |
| 616 | + ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, | |
| 617 | + NI_E_DMA_G0_G1_SEL_MASK(gpct_index), | |
| 618 | + NI_E_DMA_G0_G1_SEL(gpct_index, bits)); | |
| 724 | 619 | } |
| 725 | 620 | |
| 726 | 621 | /* negative mite_channel means no channel */ |
| @@ -729,18 +624,21 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, · 2 unmodified lines | ||
| 729 | 624 | { |
| 730 | 625 | struct ni_private *devpriv = dev->private; |
| 731 | 626 | unsigned long flags; |
| 627 | + unsigned bits; | |
| 732 | 628 | |
| 733 | 629 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); |
| 734 | − devpriv->cdio_dma_select_reg &= ~CDO_DMA_Select_Mask; | |
| 630 | + devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; | |
| 735 | 631 | if (mite_channel >= 0) { |
| 736 | − /*XXX just guessing ni_stc_dma_channel_select_bitfield() returns the right bits, | |
| 737 | − under the assumption the cdio dma selection works just like ai/ao/gpct. | |
| 738 | − Definitely works for dma channels 0 and 1. */ | |
| 739 | − devpriv->cdio_dma_select_reg |= | |
| 740 | − (ni_stc_dma_channel_select_bitfield(mite_channel) << | |
| 741 | − CDO_DMA_Select_Shift) & CDO_DMA_Select_Mask; | |
| 742 | − } | |
| 743 | − ni_writeb(dev, devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select); | |
| 632 | + /* | |
| 633 | + * XXX just guessing ni_stc_dma_channel_select_bitfield() | |
| 634 | + * returns the right bits, under the assumption the cdio dma | |
| 635 | + * selection works just like ai/ao/gpct. | |
| 636 | + * Definitely works for dma channels 0 and 1. | |
| 637 | + */ | |
| 638 | + bits = ni_stc_dma_channel_select_bitfield(mite_channel); | |
| 639 | + devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits); | |
| 640 | + } | |
| 641 | + ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); | |
| 744 | 642 | mmiowb(); |
| 745 | 643 | spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); |
| 746 | 644 | } |
| @@ -795,7 +693,6 @@ static int ni_request_gpct_mite_channel(struct comedi_device *dev, · 48 unmodified lines | ||
| 795 | 693 | unsigned long flags; |
| 796 | 694 | struct mite_channel *mite_chan; |
| 797 | 695 | |
| 798 | − BUG_ON(gpct_index >= NUM_GPCT); | |
| 799 | 696 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 800 | 697 | BUG_ON(devpriv->counter_dev->counters[gpct_index].mite_chan); |
| 801 | 698 | mite_chan = |
| @@ -879,7 +776,6 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev, · 77 unmodified lines | ||
| 879 | 776 | struct ni_private *devpriv = dev->private; |
| 880 | 777 | unsigned long flags; |
| 881 | 778 | |
| 882 | − BUG_ON(gpct_index >= NUM_GPCT); | |
| 883 | 779 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 884 | 780 | if (devpriv->counter_dev->counters[gpct_index].mite_chan) { |
| 885 | 781 | struct mite_channel *mite_chan = |
| @@ -927,13 +823,13 @@ static void ni_e_series_enable_second_irq(struct comedi_device *dev, · 41 unmodified lines | ||
| 927 | 823 | * dma requests for their counters |
| 928 | 824 | */ |
| 929 | 825 | if (gpct_index == 0) { |
| 930 | − reg = Second_IRQ_A_Enable_Register; | |
| 826 | + reg = NISTC_INTA2_ENA_REG; | |
| 931 | 827 | if (enable) |
| 932 | − val = G0_Gate_Second_Irq_Enable; | |
| 828 | + val = NISTC_INTA_ENA_G0_GATE; | |
| 933 | 829 | } else { |
| 934 | − reg = Second_IRQ_B_Enable_Register; | |
| 830 | + reg = NISTC_INTB2_ENA_REG; | |
| 935 | 831 | if (enable) |
| 936 | − val = G1_Gate_Second_Irq_Enable; | |
| 832 | + val = NISTC_INTB_ENA_G1_GATE; | |
| 937 | 833 | } |
| 938 | 834 | ni_stc_writew(dev, val, reg); |
| 939 | 835 | } |
| @@ -947,30 +843,30 @@ static void ni_clear_ai_fifo(struct comedi_device *dev) · 7 unmodified lines | ||
| 947 | 843 | |
| 948 | 844 | if (devpriv->is_6143) { |
| 949 | 845 | /* Flush the 6143 data FIFO */ |
| 950 | − ni_writel(dev, 0x10, AIFIFO_Control_6143); | |
| 951 | − ni_writel(dev, 0x00, AIFIFO_Control_6143); | |
| 846 | + ni_writel(dev, 0x10, NI6143_AI_FIFO_CTRL_REG); | |
| 847 | + ni_writel(dev, 0x00, NI6143_AI_FIFO_CTRL_REG); | |
| 952 | 848 | /* Wait for complete */ |
| 953 | 849 | for (i = 0; i < timeout; i++) { |
| 954 | − if (!(ni_readl(dev, AIFIFO_Status_6143) & 0x10)) | |
| 850 | + if (!(ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x10)) | |
| 955 | 851 | break; |
| 956 | 852 | udelay(1); |
| 957 | 853 | } |
| 958 | 854 | if (i == timeout) |
| 959 | 855 | dev_err(dev->class_dev, "FIFO flush timeout\n"); |
| 960 | 856 | } else { |
| 961 | − ni_stc_writew(dev, 1, ADC_FIFO_Clear); | |
| 857 | + ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG); | |
| 962 | 858 | if (devpriv->is_625x) { |
| 963 | − ni_writeb(dev, 0, M_Offset_Static_AI_Control(0)); | |
| 964 | − ni_writeb(dev, 1, M_Offset_Static_AI_Control(0)); | |
| 859 | + ni_writeb(dev, 0, NI_M_STATIC_AI_CTRL_REG(0)); | |
| 860 | + ni_writeb(dev, 1, NI_M_STATIC_AI_CTRL_REG(0)); | |
| 965 | 861 | #if 0 |
| 966 | 862 | /* the NI example code does 3 convert pulses for 625x boards, |
| 967 | 863 | but that appears to be wrong in practice. */ |
| 968 | − ni_stc_writew(dev, AI_CONVERT_Pulse, | |
| 969 | − AI_Command_1_Register); | |
| 970 | − ni_stc_writew(dev, AI_CONVERT_Pulse, | |
| 971 | − AI_Command_1_Register); | |
| 972 | − ni_stc_writew(dev, AI_CONVERT_Pulse, | |
| 973 | − AI_Command_1_Register); | |
| 864 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, | |
| 865 | + NISTC_AI_CMD1_REG); | |
| 866 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, | |
| 867 | + NISTC_AI_CMD1_REG); | |
| 868 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, | |
| 869 | + NISTC_AI_CMD1_REG); | |
| 974 | 870 | #endif |
| 975 | 871 | } |
| 976 | 872 | } |
| @@ -983,8 +879,8 @@ static inline void ni_ao_win_outw(struct comedi_device *dev, uint16_t data, · 6 unmodified lines | ||
| 983 | 879 | unsigned long flags; |
| 984 | 880 | |
| 985 | 881 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 986 | − ni_writew(dev, addr, AO_Window_Address_611x); | |
| 987 | − ni_writew(dev, data, AO_Window_Data_611x); | |
| 882 | + ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); | |
| 883 | + ni_writew(dev, data, NI611X_AO_WINDOW_DATA_REG); | |
| 988 | 884 | spin_unlock_irqrestore(&devpriv->window_lock, flags); |
| 989 | 885 | } |
| 990 | 886 | |
| @@ -995,8 +891,8 @@ static inline void ni_ao_win_outl(struct comedi_device *dev, uint32_t data, · 4 unmodified lines | ||
| 995 | 891 | unsigned long flags; |
| 996 | 892 | |
| 997 | 893 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 998 | − ni_writew(dev, addr, AO_Window_Address_611x); | |
| 999 | − ni_writel(dev, data, AO_Window_Data_611x); | |
| 894 | + ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); | |
| 895 | + ni_writel(dev, data, NI611X_AO_WINDOW_DATA_REG); | |
| 1000 | 896 | spin_unlock_irqrestore(&devpriv->window_lock, flags); |
| 1001 | 897 | } |
| 1002 | 898 | |
| @@ -1007,8 +903,8 @@ static inline unsigned short ni_ao_win_inw(struct comedi_device *dev, int addr) · 4 unmodified lines | ||
| 1007 | 903 | unsigned short data; |
| 1008 | 904 | |
| 1009 | 905 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 1010 | − ni_writew(dev, addr, AO_Window_Address_611x); | |
| 1011 | − data = ni_readw(dev, AO_Window_Data_611x); | |
| 906 | + ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); | |
| 907 | + data = ni_readw(dev, NI611X_AO_WINDOW_DATA_REG); | |
| 1012 | 908 | spin_unlock_irqrestore(&devpriv->window_lock, flags); |
| 1013 | 909 | return data; |
| 1014 | 910 | } |
| @@ -1059,8 +955,8 @@ static int ni_ai_drain_dma(struct comedi_device *dev) · 44 unmodified lines | ||
| 1059 | 955 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 1060 | 956 | if (devpriv->ai_mite_chan) { |
| 1061 | 957 | for (i = 0; i < timeout; i++) { |
| 1062 | − if ((ni_stc_readw(dev, AI_Status_1_Register) & | |
| 1063 | − AI_FIFO_Empty_St) | |
| 958 | + if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & | |
| 959 | + NISTC_AI_STATUS1_FIFO_E) | |
| 1064 | 960 | && mite_bytes_in_transit(devpriv->ai_mite_chan) == |
| 1065 | 961 | 0) |
| 1066 | 962 | break; |
| @@ -1071,7 +967,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev) · 4 unmodified lines | ||
| 1071 | 967 | dev_err(dev->class_dev, |
| 1072 | 968 | "mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n", |
| 1073 | 969 | mite_bytes_in_transit(devpriv->ai_mite_chan), |
| 1074 | − ni_stc_readw(dev, AI_Status_1_Register)); | |
| 970 | + ni_stc_readw(dev, NISTC_AI_STATUS1_REG)); | |
| 1075 | 971 | retval = -1; |
| 1076 | 972 | } |
| 1077 | 973 | } |
| @@ -1103,8 +999,8 @@ static int ni_ao_wait_for_dma_load(struct comedi_device *dev) · 25 unmodified lines | ||
| 1103 | 999 | for (i = 0; i < timeout; i++) { |
| 1104 | 1000 | unsigned short b_status; |
| 1105 | 1001 | |
| 1106 | − b_status = ni_stc_readw(dev, AO_Status_1_Register); | |
| 1107 | − if (b_status & AO_FIFO_Half_Full_St) | |
| 1002 | + b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); | |
| 1003 | + if (b_status & NISTC_AO_STATUS1_FIFO_HF) | |
| 1108 | 1004 | break; |
| 1109 | 1005 | /* if we poll too often, the pci bus activity seems |
| 1110 | 1006 | to slow the dma transfer down */ |
| @@ -1139,9 +1035,9 @@ static void ni_ao_fifo_load(struct comedi_device *dev, · 28 unmodified lines | ||
| 1139 | 1035 | i++; |
| 1140 | 1036 | packed_data |= (d << 16) & 0xffff0000; |
| 1141 | 1037 | } |
| 1142 | − ni_writel(dev, packed_data, DAC_FIFO_Data_611x); | |
| 1038 | + ni_writel(dev, packed_data, NI611X_AO_FIFO_DATA_REG); | |
| 1143 | 1039 | } else { |
| 1144 | − ni_writew(dev, d, DAC_FIFO_Data); | |
| 1040 | + ni_writew(dev, d, NI_E_AO_FIFO_DATA_REG); | |
| 1145 | 1041 | } |
| 1146 | 1042 | } |
| 1147 | 1043 | } |
| @@ -1193,9 +1089,9 @@ static int ni_ao_prep_fifo(struct comedi_device *dev, · 45 unmodified lines | ||
| 1193 | 1089 | unsigned int nsamples; |
| 1194 | 1090 | |
| 1195 | 1091 | /* reset fifo */ |
| 1196 | − ni_stc_writew(dev, 1, DAC_FIFO_Clear); | |
| 1092 | + ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG); | |
| 1197 | 1093 | if (devpriv->is_6xxx) |
| 1198 | − ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); | |
| 1094 | + ni_ao_win_outl(dev, 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG); | |
| 1199 | 1095 | |
| 1200 | 1096 | /* load some data */ |
| 1201 | 1097 | nbytes = comedi_buf_read_n_available(s); |
| @@ -1222,7 +1118,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, · 20 unmodified lines | ||
| 1222 | 1118 | |
| 1223 | 1119 | if (devpriv->is_611x) { |
| 1224 | 1120 | for (i = 0; i < n / 2; i++) { |
| 1225 | − dl = ni_readl(dev, ADC_FIFO_Data_611x); | |
| 1121 | + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); | |
| 1226 | 1122 | /* This may get the hi/lo data in the wrong order */ |
| 1227 | 1123 | data = (dl >> 16) & 0xffff; |
| 1228 | 1124 | comedi_buf_write_samples(s, &data, 1); |
| @@ -1231,14 +1127,14 @@ static void ni_ai_fifo_read(struct comedi_device *dev, · 2 unmodified lines | ||
| 1231 | 1127 | } |
| 1232 | 1128 | /* Check if there's a single sample stuck in the FIFO */ |
| 1233 | 1129 | if (n % 2) { |
| 1234 | − dl = ni_readl(dev, ADC_FIFO_Data_611x); | |
| 1130 | + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); | |
| 1235 | 1131 | data = dl & 0xffff; |
| 1236 | 1132 | comedi_buf_write_samples(s, &data, 1); |
| 1237 | 1133 | } |
| 1238 | 1134 | } else if (devpriv->is_6143) { |
| 1239 | 1135 | /* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */ |
| 1240 | 1136 | for (i = 0; i < n / 2; i++) { |
| 1241 | − dl = ni_readl(dev, AIFIFO_Data_6143); | |
| 1137 | + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); | |
| 1242 | 1138 | |
| 1243 | 1139 | data = (dl >> 16) & 0xffff; |
| 1244 | 1140 | comedi_buf_write_samples(s, &data, 1); |
| @@ -1248,8 +1144,8 @@ static void ni_ai_fifo_read(struct comedi_device *dev, · 3 unmodified lines | ||
| 1248 | 1144 | if (n % 2) { |
| 1249 | 1145 | /* Assume there is a single sample stuck in the FIFO */ |
| 1250 | 1146 | /* Get stranded sample into FIFO */ |
| 1251 | − ni_writel(dev, 0x01, AIFIFO_Control_6143); | |
| 1252 | − dl = ni_readl(dev, AIFIFO_Data_6143); | |
| 1147 | + ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); | |
| 1148 | + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); | |
| 1253 | 1149 | data = (dl >> 16) & 0xffff; |
| 1254 | 1150 | comedi_buf_write_samples(s, &data, 1); |
| 1255 | 1151 | } |
| @@ -1263,7 +1159,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, · 7 unmodified lines | ||
| 1263 | 1159 | } |
| 1264 | 1160 | for (i = 0; i < n; i++) { |
| 1265 | 1161 | devpriv->ai_fifo_buffer[i] = |
| 1266 | − ni_readw(dev, ADC_FIFO_Data_Register); | |
| 1162 | + ni_readw(dev, NI_E_AI_FIFO_DATA_REG); | |
| 1267 | 1163 | } |
| 1268 | 1164 | comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, n); |
| 1269 | 1165 | } |
| @@ -1294,9 +1190,9 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) · 24 unmodified lines | ||
| 1294 | 1190 | int i; |
| 1295 | 1191 | |
| 1296 | 1192 | if (devpriv->is_611x) { |
| 1297 | − while ((ni_stc_readw(dev, AI_Status_1_Register) & | |
| 1298 | − AI_FIFO_Empty_St) == 0) { | |
| 1299 | − dl = ni_readl(dev, ADC_FIFO_Data_611x); | |
| 1193 | + while ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & | |
| 1194 | + NISTC_AI_STATUS1_FIFO_E) == 0) { | |
| 1195 | + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); | |
| 1300 | 1196 | |
| 1301 | 1197 | /* This may get the hi/lo data in the wrong order */ |
| 1302 | 1198 | data = dl >> 16; |
| @@ -1306,8 +1202,8 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) · 3 unmodified lines | ||
| 1306 | 1202 | } |
| 1307 | 1203 | } else if (devpriv->is_6143) { |
| 1308 | 1204 | i = 0; |
| 1309 | − while (ni_readl(dev, AIFIFO_Status_6143) & 0x04) { | |
| 1310 | − dl = ni_readl(dev, AIFIFO_Data_6143); | |
| 1205 | + while (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x04) { | |
| 1206 | + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); | |
| 1311 | 1207 | |
| 1312 | 1208 | /* This may get the hi/lo data in the wrong order */ |
| 1313 | 1209 | data = dl >> 16; |
| @@ -1317,29 +1213,29 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) · 3 unmodified lines | ||
| 1317 | 1213 | i += 2; |
| 1318 | 1214 | } |
| 1319 | 1215 | /* Check if stranded sample is present */ |
| 1320 | − if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { | |
| 1216 | + if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { | |
| 1321 | 1217 | /* Get stranded sample into FIFO */ |
| 1322 | − ni_writel(dev, 0x01, AIFIFO_Control_6143); | |
| 1323 | − dl = ni_readl(dev, AIFIFO_Data_6143); | |
| 1218 | + ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); | |
| 1219 | + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); | |
| 1324 | 1220 | data = (dl >> 16) & 0xffff; |
| 1325 | 1221 | comedi_buf_write_samples(s, &data, 1); |
| 1326 | 1222 | } |
| 1327 | 1223 | |
| 1328 | 1224 | } else { |
| 1329 | − fifo_empty = ni_stc_readw(dev, AI_Status_1_Register) & | |
| 1330 | − AI_FIFO_Empty_St; | |
| 1225 | + fifo_empty = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & | |
| 1226 | + NISTC_AI_STATUS1_FIFO_E; | |
| 1331 | 1227 | while (fifo_empty == 0) { |
| 1332 | 1228 | for (i = 0; |
| 1333 | 1229 | i < |
| 1334 | 1230 | sizeof(devpriv->ai_fifo_buffer) / |
| 1335 | 1231 | sizeof(devpriv->ai_fifo_buffer[0]); i++) { |
| 1336 | 1232 | fifo_empty = ni_stc_readw(dev, |
| 1337 | − AI_Status_1_Register) & | |
| 1338 | − AI_FIFO_Empty_St; | |
| 1233 | + NISTC_AI_STATUS1_REG) & | |
| 1234 | + NISTC_AI_STATUS1_FIFO_E; | |
| 1339 | 1235 | if (fifo_empty) |
| 1340 | 1236 | break; |
| 1341 | 1237 | devpriv->ai_fifo_buffer[i] = |
| 1342 | − ni_readw(dev, ADC_FIFO_Data_Register); | |
| 1238 | + ni_readw(dev, NI_E_AI_FIFO_DATA_REG); | |
| 1343 | 1239 | } |
| 1344 | 1240 | comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, i); |
| 1345 | 1241 | } |
| @@ -1357,8 +1253,8 @@ static void get_last_sample_611x(struct comedi_device *dev) · 11 unmodified lines | ||
| 1357 | 1253 | return; |
| 1358 | 1254 | |
| 1359 | 1255 | /* Check if there's a single sample stuck in the FIFO */ |
| 1360 | − if (ni_readb(dev, XXX_Status) & 0x80) { | |
| 1361 | − dl = ni_readl(dev, ADC_FIFO_Data_611x); | |
| 1256 | + if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { | |
| 1257 | + dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); | |
| 1362 | 1258 | data = dl & 0xffff; |
| 1363 | 1259 | comedi_buf_write_samples(s, &data, 1); |
| 1364 | 1260 | } |
| @@ -1375,10 +1271,10 @@ static void get_last_sample_6143(struct comedi_device *dev) · 10 unmodified lines | ||
| 1375 | 1271 | return; |
| 1376 | 1272 | |
| 1377 | 1273 | /* Check if there's a single sample stuck in the FIFO */ |
| 1378 | − if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { | |
| 1274 | + if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { | |
| 1379 | 1275 | /* Get stranded sample into FIFO */ |
| 1380 | − ni_writel(dev, 0x01, AIFIFO_Control_6143); | |
| 1381 | − dl = ni_readl(dev, AIFIFO_Data_6143); | |
| 1276 | + ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); | |
| 1277 | + dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); | |
| 1382 | 1278 | |
| 1383 | 1279 | /* This may get the hi/lo data in the wrong order */ |
| 1384 | 1280 | data = (dl >> 16) & 0xffff; |
| @@ -1420,8 +1316,8 @@ static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s) · 35 unmodified lines | ||
| 1420 | 1316 | s->async->events |= COMEDI_CB_EOS; |
| 1421 | 1317 | #endif |
| 1422 | 1318 | } |
| 1423 | − /* handle special case of single scan using AI_End_On_End_Of_Scan */ | |
| 1424 | − if ((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) | |
| 1319 | + /* handle special case of single scan */ | |
| 1320 | + if (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS) | |
| 1425 | 1321 | shutdown_ai_command(dev); |
| 1426 | 1322 | } |
| 1427 | 1323 | |
| @@ -1444,17 +1340,16 @@ static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status) · 16 unmodified lines | ||
| 1444 | 1340 | { |
| 1445 | 1341 | unsigned short ack = 0; |
| 1446 | 1342 | |
| 1447 | − if (a_status & AI_SC_TC_St) | |
| 1448 | − ack |= AI_SC_TC_Interrupt_Ack; | |
| 1449 | − if (a_status & AI_START1_St) | |
| 1450 | − ack |= AI_START1_Interrupt_Ack; | |
| 1451 | − if (a_status & AI_START_St) | |
| 1452 | − ack |= AI_START_Interrupt_Ack; | |
| 1453 | − if (a_status & AI_STOP_St) | |
| 1454 | − /* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */ | |
| 1455 | − ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack */; | |
| 1343 | + if (a_status & NISTC_AI_STATUS1_SC_TC) | |
| 1344 | + ack |= NISTC_INTA_ACK_AI_SC_TC; | |
| 1345 | + if (a_status & NISTC_AI_STATUS1_START1) | |
| 1346 | + ack |= NISTC_INTA_ACK_AI_START1; | |
| 1347 | + if (a_status & NISTC_AI_STATUS1_START) | |
| 1348 | + ack |= NISTC_INTA_ACK_AI_START; | |
| 1349 | + if (a_status & NISTC_AI_STATUS1_STOP) | |
| 1350 | + ack |= NISTC_INTA_ACK_AI_STOP; | |
| 1456 | 1351 | if (ack) |
| 1457 | − ni_stc_writew(dev, ack, Interrupt_A_Ack_Register); | |
| 1352 | + ni_stc_writew(dev, ack, NISTC_INTA_ACK_REG); | |
| 1458 | 1353 | } |
| 1459 | 1354 | |
| 1460 | 1355 | static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, |
| @@ -1483,8 +1378,8 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, · 22 unmodified lines | ||
| 1483 | 1378 | #endif |
| 1484 | 1379 | |
| 1485 | 1380 | /* test for all uncommon interrupt events at the same time */ |
| 1486 | − if (status & (AI_Overrun_St | AI_Overflow_St | AI_SC_TC_Error_St | | |
| 1487 | − AI_SC_TC_St | AI_START1_St)) { | |
| 1381 | + if (status & (NISTC_AI_STATUS1_ERR | | |
| 1382 | + NISTC_AI_STATUS1_SC_TC | NISTC_AI_STATUS1_START1)) { | |
| 1488 | 1383 | if (status == 0xffff) { |
| 1489 | 1384 | dev_err(dev->class_dev, "Card removed?\n"); |
| 1490 | 1385 | /* we probably aren't even running a command now, |
| @@ -1495,41 +1390,40 @@ static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, · 4 unmodified lines | ||
| 1495 | 1390 | } |
| 1496 | 1391 | return; |
| 1497 | 1392 | } |
| 1498 | − if (status & (AI_Overrun_St | AI_Overflow_St | | |
| 1499 | − AI_SC_TC_Error_St)) { | |
| 1393 | + if (status & NISTC_AI_STATUS1_ERR) { | |
| 1500 | 1394 | dev_err(dev->class_dev, "ai error a_status=%04x\n", |
| 1501 | 1395 | status); |
| 1502 | 1396 | |
| 1503 | 1397 | shutdown_ai_command(dev); |
| 1504 | 1398 | |
| 1505 | 1399 | s->async->events |= COMEDI_CB_ERROR; |
| 1506 | − if (status & (AI_Overrun_St | AI_Overflow_St)) | |
| 1400 | + if (status & NISTC_AI_STATUS1_OVER) | |
| 1507 | 1401 | s->async->events |= COMEDI_CB_OVERFLOW; |
| 1508 | 1402 | |
| 1509 | 1403 | comedi_handle_events(dev, s); |
| 1510 | 1404 | return; |
| 1511 | 1405 | } |
| 1512 | − if (status & AI_SC_TC_St) { | |
| 1406 | + if (status & NISTC_AI_STATUS1_SC_TC) { | |
| 1513 | 1407 | if (cmd->stop_src == TRIG_COUNT) |
| 1514 | 1408 | shutdown_ai_command(dev); |
| 1515 | 1409 | } |
| 1516 | 1410 | } |
| 1517 | 1411 | #ifndef PCIDMA |
| 1518 | − if (status & AI_FIFO_Half_Full_St) { | |
| 1412 | + if (status & NISTC_AI_STATUS1_FIFO_HF) { | |
| 1519 | 1413 | int i; |
| 1520 | 1414 | static const int timeout = 10; |
| 1521 | 1415 | /* pcmcia cards (at least 6036) seem to stop producing interrupts if we |
| 1522 | 1416 | *fail to get the fifo less than half full, so loop to be sure.*/ |
| 1523 | 1417 | for (i = 0; i < timeout; ++i) { |
| 1524 | 1418 | ni_handle_fifo_half_full(dev); |
| 1525 | − if ((ni_stc_readw(dev, AI_Status_1_Register) & | |
| 1526 | − AI_FIFO_Half_Full_St) == 0) | |
| 1419 | + if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & | |
| 1420 | + NISTC_AI_STATUS1_FIFO_HF) == 0) | |
| 1527 | 1421 | break; |
| 1528 | 1422 | } |
| 1529 | 1423 | } |
| 1530 | 1424 | #endif /* !PCIDMA */ |
| 1531 | 1425 | |
| 1532 | − if ((status & AI_STOP_St)) | |
| 1426 | + if (status & NISTC_AI_STATUS1_STOP) | |
| 1533 | 1427 | ni_handle_eos(dev, s); |
| 1534 | 1428 | |
| 1535 | 1429 | comedi_handle_events(dev, s); |
| @@ -1539,22 +1433,22 @@ static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status) · 3 unmodified lines | ||
| 1539 | 1433 | { |
| 1540 | 1434 | unsigned short ack = 0; |
| 1541 | 1435 | |
| 1542 | − if (b_status & AO_BC_TC_St) | |
| 1543 | − ack |= AO_BC_TC_Interrupt_Ack; | |
| 1544 | − if (b_status & AO_Overrun_St) | |
| 1545 | − ack |= AO_Error_Interrupt_Ack; | |
| 1546 | − if (b_status & AO_START_St) | |
| 1547 | − ack |= AO_START_Interrupt_Ack; | |
| 1548 | − if (b_status & AO_START1_St) | |
| 1549 | − ack |= AO_START1_Interrupt_Ack; | |
| 1550 | − if (b_status & AO_UC_TC_St) | |
| 1551 | − ack |= AO_UC_TC_Interrupt_Ack; | |
| 1552 | − if (b_status & AO_UI2_TC_St) | |
| 1553 | − ack |= AO_UI2_TC_Interrupt_Ack; | |
| 1554 | − if (b_status & AO_UPDATE_St) | |
| 1555 | − ack |= AO_UPDATE_Interrupt_Ack; | |
| 1436 | + if (b_status & NISTC_AO_STATUS1_BC_TC) | |
| 1437 | + ack |= NISTC_INTB_ACK_AO_BC_TC; | |
| 1438 | + if (b_status & NISTC_AO_STATUS1_OVERRUN) | |
| 1439 | + ack |= NISTC_INTB_ACK_AO_ERR; | |
| 1440 | + if (b_status & NISTC_AO_STATUS1_START) | |
| 1441 | + ack |= NISTC_INTB_ACK_AO_START; | |
| 1442 | + if (b_status & NISTC_AO_STATUS1_START1) | |
| 1443 | + ack |= NISTC_INTB_ACK_AO_START1; | |
| 1444 | + if (b_status & NISTC_AO_STATUS1_UC_TC) | |
| 1445 | + ack |= NISTC_INTB_ACK_AO_UC_TC; | |
| 1446 | + if (b_status & NISTC_AO_STATUS1_UI2_TC) | |
| 1447 | + ack |= NISTC_INTB_ACK_AO_UI2_TC; | |
| 1448 | + if (b_status & NISTC_AO_STATUS1_UPDATE) | |
| 1449 | + ack |= NISTC_INTB_ACK_AO_UPDATE; | |
| 1556 | 1450 | if (ack) |
| 1557 | − ni_stc_writew(dev, ack, Interrupt_B_Ack_Register); | |
| 1451 | + ni_stc_writew(dev, ack, NISTC_INTB_ACK_REG); | |
| 1558 | 1452 | } |
| 1559 | 1453 | |
| 1560 | 1454 | static void handle_b_interrupt(struct comedi_device *dev, |
| @@ -1583,26 +1477,26 @@ static void handle_b_interrupt(struct comedi_device *dev, · 22 unmodified lines | ||
| 1583 | 1477 | |
| 1584 | 1478 | if (b_status == 0xffff) |
| 1585 | 1479 | return; |
| 1586 | − if (b_status & AO_Overrun_St) { | |
| 1480 | + if (b_status & NISTC_AO_STATUS1_OVERRUN) { | |
| 1587 | 1481 | dev_err(dev->class_dev, |
| 1588 | 1482 | "AO FIFO underrun status=0x%04x status2=0x%04x\n", |
| 1589 | − b_status, ni_stc_readw(dev, AO_Status_2_Register)); | |
| 1483 | + b_status, ni_stc_readw(dev, NISTC_AO_STATUS2_REG)); | |
| 1590 | 1484 | s->async->events |= COMEDI_CB_OVERFLOW; |
| 1591 | 1485 | } |
| 1592 | 1486 | |
| 1593 | − if (b_status & AO_BC_TC_St) | |
| 1487 | + if (b_status & NISTC_AO_STATUS1_BC_TC) | |
| 1594 | 1488 | s->async->events |= COMEDI_CB_EOA; |
| 1595 | 1489 | |
| 1596 | 1490 | #ifndef PCIDMA |
| 1597 | − if (b_status & AO_FIFO_Request_St) { | |
| 1491 | + if (b_status & NISTC_AO_STATUS1_FIFO_REQ) { | |
| 1598 | 1492 | int ret; |
| 1599 | 1493 | |
| 1600 | 1494 | ret = ni_ao_fifo_half_empty(dev, s); |
| 1601 | 1495 | if (!ret) { |
| 1602 | 1496 | dev_err(dev->class_dev, "AO buffer underrun\n"); |
| 1603 | − ni_set_bits(dev, Interrupt_B_Enable_Register, | |
| 1604 | − AO_FIFO_Interrupt_Enable | | |
| 1605 | − AO_Error_Interrupt_Enable, 0); | |
| 1497 | + ni_set_bits(dev, NISTC_INTB_ENA_REG, | |
| 1498 | + NISTC_INTB_ENA_AO_FIFO | | |
| 1499 | + NISTC_INTB_ENA_AO_ERR, 0); | |
| 1606 | 1500 | s->async->events |= COMEDI_CB_OVERFLOW; |
| 1607 | 1501 | } |
| 1608 | 1502 | } |
| @@ -1718,101 +1612,65 @@ static int ni_ao_setup_MITE_dma(struct comedi_device *dev) · 109 unmodified lines | ||
| 1718 | 1612 | static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) |
| 1719 | 1613 | { |
| 1720 | 1614 | struct ni_private *devpriv = dev->private; |
| 1615 | + unsigned ai_personal; | |
| 1616 | + unsigned ai_out_ctrl; | |
| 1721 | 1617 | |
| 1722 | 1618 | ni_release_ai_mite_channel(dev); |
| 1723 | 1619 | /* ai configuration */ |
| 1724 | − ni_stc_writew(dev, AI_Configuration_Start | AI_Reset, | |
| 1725 | − Joint_Reset_Register); | |
| 1620 | + ni_stc_writew(dev, NISTC_RESET_AI_CFG_START | NISTC_RESET_AI, | |
| 1621 | + NISTC_RESET_REG); | |
| 1726 | 1622 | |
| 1727 | − ni_set_bits(dev, Interrupt_A_Enable_Register, | |
| 1728 | − AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable | | |
| 1729 | − AI_START2_Interrupt_Enable | AI_START_Interrupt_Enable | | |
| 1730 | − AI_STOP_Interrupt_Enable | AI_Error_Interrupt_Enable | | |
| 1731 | − AI_FIFO_Interrupt_Enable, 0); | |
| 1623 | + ni_set_bits(dev, NISTC_INTA_ENA_REG, NISTC_INTA_ENA_AI_MASK, 0); | |
| 1732 | 1624 | |
| 1733 | 1625 | ni_clear_ai_fifo(dev); |
| 1734 | 1626 | |
| 1735 | 1627 | if (!devpriv->is_6143) |
| 1736 | − ni_writeb(dev, 0, Misc_Command); | |
| 1737 | − | |
| 1738 | − ni_stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */ | |
| 1739 | − ni_stc_writew(dev, AI_Start_Stop | AI_Mode_1_Reserved | |
| 1740 | − /*| AI_Trigger_Once */, | |
| 1741 | − AI_Mode_1_Register); | |
| 1742 | − ni_stc_writew(dev, 0x0000, AI_Mode_2_Register); | |
| 1628 | + ni_writeb(dev, NI_E_MISC_CMD_EXT_ATRIG, NI_E_MISC_CMD_REG); | |
| 1629 | + | |
| 1630 | + ni_stc_writew(dev, NISTC_AI_CMD1_DISARM, NISTC_AI_CMD1_REG); | |
| 1631 | + ni_stc_writew(dev, NISTC_AI_MODE1_START_STOP | | |
| 1632 | + NISTC_AI_MODE1_RSVD | |
| 1633 | + /*| NISTC_AI_MODE1_TRIGGER_ONCE */, | |
| 1634 | + NISTC_AI_MODE1_REG); | |
| 1635 | + ni_stc_writew(dev, 0, NISTC_AI_MODE2_REG); | |
| 1743 | 1636 | /* generate FIFO interrupts on non-empty */ |
| 1744 | − ni_stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register); | |
| 1637 | + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, | |
| 1638 | + NISTC_AI_MODE3_REG); | |
| 1639 | + | |
| 1640 | + ai_personal = NISTC_AI_PERSONAL_SHIFTIN_PW | | |
| 1641 | + NISTC_AI_PERSONAL_SOC_POLARITY | | |
| 1642 | + NISTC_AI_PERSONAL_LOCALMUX_CLK_PW; | |
| 1643 | + ai_out_ctrl = NISTC_AI_OUT_CTRL_SCAN_IN_PROG_SEL(3) | | |
| 1644 | + NISTC_AI_OUT_CTRL_EXTMUX_CLK_SEL(0) | | |
| 1645 | + NISTC_AI_OUT_CTRL_LOCALMUX_CLK_SEL(2) | | |
| 1646 | + NISTC_AI_OUT_CTRL_SC_TC_SEL(3); | |
| 1745 | 1647 | if (devpriv->is_611x) { |
| 1746 | − ni_stc_writew(dev, | |
| 1747 | − AI_SHIFTIN_Pulse_Width | | |
| 1748 | − AI_SOC_Polarity | | |
| 1749 | − AI_LOCALMUX_CLK_Pulse_Width, | |
| 1750 | − AI_Personal_Register); | |
| 1751 | − ni_stc_writew(dev, | |
| 1752 | − AI_SCAN_IN_PROG_Output_Select(3) | | |
| 1753 | − AI_EXTMUX_CLK_Output_Select(0) | | |
| 1754 | − AI_LOCALMUX_CLK_Output_Select(2) | | |
| 1755 | − AI_SC_TC_Output_Select(3) | | |
| 1756 | − AI_CONVERT_Output_Select | |
| 1757 | − (AI_CONVERT_Output_Enable_High), | |
| 1758 | − AI_Output_Control_Register); | |
| 1648 | + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; | |
| 1759 | 1649 | } else if (devpriv->is_6143) { |
| 1760 | − ni_stc_writew(dev, AI_SHIFTIN_Pulse_Width | | |
| 1761 | − AI_SOC_Polarity | | |
| 1762 | − AI_LOCALMUX_CLK_Pulse_Width, | |
| 1763 | − AI_Personal_Register); | |
| 1764 | − ni_stc_writew(dev, | |
| 1765 | − AI_SCAN_IN_PROG_Output_Select(3) | | |
| 1766 | − AI_EXTMUX_CLK_Output_Select(0) | | |
| 1767 | − AI_LOCALMUX_CLK_Output_Select(2) | | |
| 1768 | − AI_SC_TC_Output_Select(3) | | |
| 1769 | − AI_CONVERT_Output_Select | |
| 1770 | − (AI_CONVERT_Output_Enable_Low), | |
| 1771 | − AI_Output_Control_Register); | |
| 1650 | + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; | |
| 1772 | 1651 | } else { |
| 1773 | − unsigned ai_output_control_bits; | |
| 1774 | − | |
| 1775 | − ni_stc_writew(dev, | |
| 1776 | − AI_SHIFTIN_Pulse_Width | | |
| 1777 | − AI_SOC_Polarity | | |
| 1778 | − AI_CONVERT_Pulse_Width | | |
| 1779 | − AI_LOCALMUX_CLK_Pulse_Width, | |
| 1780 | − AI_Personal_Register); | |
| 1781 | − ai_output_control_bits = | |
| 1782 | − AI_SCAN_IN_PROG_Output_Select(3) | | |
| 1783 | − AI_EXTMUX_CLK_Output_Select(0) | | |
| 1784 | − AI_LOCALMUX_CLK_Output_Select(2) | | |
| 1785 | − AI_SC_TC_Output_Select(3); | |
| 1652 | + ai_personal |= NISTC_AI_PERSONAL_CONVERT_PW; | |
| 1786 | 1653 | if (devpriv->is_622x) |
| 1787 | − ai_output_control_bits |= | |
| 1788 | − AI_CONVERT_Output_Select | |
| 1789 | − (AI_CONVERT_Output_Enable_High); | |
| 1654 | + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; | |
| 1790 | 1655 | else |
| 1791 | − ai_output_control_bits |= | |
| 1792 | − AI_CONVERT_Output_Select | |
| 1793 | − (AI_CONVERT_Output_Enable_Low); | |
| 1794 | − ni_stc_writew(dev, ai_output_control_bits, | |
| 1795 | − AI_Output_Control_Register); | |
| 1656 | + ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; | |
| 1796 | 1657 | } |
| 1658 | + ni_stc_writew(dev, ai_personal, NISTC_AI_PERSONAL_REG); | |
| 1659 | + ni_stc_writew(dev, ai_out_ctrl, NISTC_AI_OUT_CTRL_REG); | |
| 1660 | + | |
| 1797 | 1661 | /* the following registers should not be changed, because there |
| 1798 | 1662 | * are no backup registers in devpriv. If you want to change |
| 1799 | 1663 | * any of these, add a backup register and other appropriate code: |
| 1800 | − * AI_Mode_1_Register | |
| 1801 | − * AI_Mode_3_Register | |
| 1802 | − * AI_Personal_Register | |
| 1803 | − * AI_Output_Control_Register | |
| 1664 | + * NISTC_AI_MODE1_REG | |
| 1665 | + * NISTC_AI_MODE3_REG | |
| 1666 | + * NISTC_AI_PERSONAL_REG | |
| 1667 | + * NISTC_AI_OUT_CTRL_REG | |
| 1804 | 1668 | */ |
| 1805 | − ni_stc_writew(dev, | |
| 1806 | − AI_SC_TC_Error_Confirm | | |
| 1807 | − AI_START_Interrupt_Ack | | |
| 1808 | − AI_START2_Interrupt_Ack | | |
| 1809 | − AI_START1_Interrupt_Ack | | |
| 1810 | − AI_SC_TC_Interrupt_Ack | | |
| 1811 | − AI_Error_Interrupt_Ack | | |
| 1812 | − AI_STOP_Interrupt_Ack, | |
| 1813 | − Interrupt_A_Ack_Register); /* clear interrupts */ | |
| 1814 | − | |
| 1815 | − ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); | |
| 1669 | + | |
| 1670 | + /* clear interrupts */ | |
| 1671 | + ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); | |
| 1672 | + | |
| 1673 | + ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG); | |
| 1816 | 1674 | |
| 1817 | 1675 | return 0; |
| 1818 | 1676 | } |
| @@ -1839,11 +1697,11 @@ static void ni_prime_channelgain_list(struct comedi_device *dev) · 20 unmodified lines | ||
| 1839 | 1697 | { |
| 1840 | 1698 | int i; |
| 1841 | 1699 | |
| 1842 | − ni_stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register); | |
| 1700 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, NISTC_AI_CMD1_REG); | |
| 1843 | 1701 | for (i = 0; i < NI_TIMEOUT; ++i) { |
| 1844 | − if (!(ni_stc_readw(dev, AI_Status_1_Register) & | |
| 1845 | − AI_FIFO_Empty_St)) { | |
| 1846 | − ni_stc_writew(dev, 1, ADC_FIFO_Clear); | |
| 1702 | + if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & | |
| 1703 | + NISTC_AI_STATUS1_FIFO_E)) { | |
| 1704 | + ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG); | |
| 1847 | 1705 | return; |
| 1848 | 1706 | } |
| 1849 | 1707 | udelay(1); |
| @@ -1862,7 +1720,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, · 12 unmodified lines | ||
| 1862 | 1720 | unsigned int dither; |
| 1863 | 1721 | unsigned range_code; |
| 1864 | 1722 | |
| 1865 | − ni_stc_writew(dev, 1, Configuration_Memory_Clear); | |
| 1723 | + ni_stc_writew(dev, 1, NISTC_CFG_MEM_CLR_REG); | |
| 1866 | 1724 | |
| 1867 | 1725 | if ((list[0] & CR_ALT_SOURCE)) { |
| 1868 | 1726 | unsigned bypass_bits; |
| @@ -1871,22 +1729,17 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, · 2 unmodified lines | ||
| 1871 | 1729 | range = CR_RANGE(list[0]); |
| 1872 | 1730 | range_code = ni_gainlkup[board->gainlkup][range]; |
| 1873 | 1731 | dither = (list[0] & CR_ALT_FILTER) != 0; |
| 1874 | − bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit; | |
| 1875 | − bypass_bits |= chan; | |
| 1876 | − bypass_bits |= | |
| 1877 | − (devpriv->ai_calib_source) & | |
| 1878 | − (MSeries_AI_Bypass_Cal_Sel_Pos_Mask | | |
| 1879 | − MSeries_AI_Bypass_Cal_Sel_Neg_Mask | | |
| 1880 | − MSeries_AI_Bypass_Mode_Mux_Mask | | |
| 1881 | − MSeries_AO_Bypass_AO_Cal_Sel_Mask); | |
| 1882 | − bypass_bits |= MSeries_AI_Bypass_Gain_Bits(range_code); | |
| 1732 | + bypass_bits = NI_M_CFG_BYPASS_FIFO | | |
| 1733 | + NI_M_CFG_BYPASS_AI_CHAN(chan) | | |
| 1734 | + NI_M_CFG_BYPASS_AI_GAIN(range_code) | | |
| 1735 | + devpriv->ai_calib_source; | |
| 1883 | 1736 | if (dither) |
| 1884 | − bypass_bits |= MSeries_AI_Bypass_Dither_Bit; | |
| 1737 | + bypass_bits |= NI_M_CFG_BYPASS_AI_DITHER; | |
| 1885 | 1738 | /* don't use 2's complement encoding */ |
| 1886 | − bypass_bits |= MSeries_AI_Bypass_Polarity_Bit; | |
| 1887 | − ni_writel(dev, bypass_bits, M_Offset_AI_Config_FIFO_Bypass); | |
| 1739 | + bypass_bits |= NI_M_CFG_BYPASS_AI_POLARITY; | |
| 1740 | + ni_writel(dev, bypass_bits, NI_M_CFG_BYPASS_FIFO_REG); | |
| 1888 | 1741 | } else { |
| 1889 | − ni_writel(dev, 0, M_Offset_AI_Config_FIFO_Bypass); | |
| 1742 | + ni_writel(dev, 0, NI_M_CFG_BYPASS_FIFO_REG); | |
| 1890 | 1743 | } |
| 1891 | 1744 | for (i = 0; i < n_chan; i++) { |
| 1892 | 1745 | unsigned config_bits = 0; |
| @@ -1900,31 +1753,27 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, · 7 unmodified lines | ||
| 1900 | 1753 | devpriv->ai_offset[i] = 0; |
| 1901 | 1754 | switch (aref) { |
| 1902 | 1755 | case AREF_DIFF: |
| 1903 | − config_bits |= | |
| 1904 | − MSeries_AI_Config_Channel_Type_Differential_Bits; | |
| 1756 | + config_bits |= NI_M_AI_CFG_CHAN_TYPE_DIFF; | |
| 1905 | 1757 | break; |
| 1906 | 1758 | case AREF_COMMON: |
| 1907 | − config_bits |= | |
| 1908 | − MSeries_AI_Config_Channel_Type_Common_Ref_Bits; | |
| 1759 | + config_bits |= NI_M_AI_CFG_CHAN_TYPE_COMMON; | |
| 1909 | 1760 | break; |
| 1910 | 1761 | case AREF_GROUND: |
| 1911 | − config_bits |= | |
| 1912 | − MSeries_AI_Config_Channel_Type_Ground_Ref_Bits; | |
| 1762 | + config_bits |= NI_M_AI_CFG_CHAN_TYPE_GROUND; | |
| 1913 | 1763 | break; |
| 1914 | 1764 | case AREF_OTHER: |
| 1915 | 1765 | break; |
| 1916 | 1766 | } |
| 1917 | − config_bits |= MSeries_AI_Config_Channel_Bits(chan); | |
| 1918 | − config_bits |= | |
| 1919 | − MSeries_AI_Config_Bank_Bits(board->reg_type, chan); | |
| 1920 | − config_bits |= MSeries_AI_Config_Gain_Bits(range_code); | |
| 1767 | + config_bits |= NI_M_AI_CFG_CHAN_SEL(chan); | |
| 1768 | + config_bits |= NI_M_AI_CFG_BANK_SEL(chan); | |
| 1769 | + config_bits |= NI_M_AI_CFG_GAIN(range_code); | |
| 1921 | 1770 | if (i == n_chan - 1) |
| 1922 | − config_bits |= MSeries_AI_Config_Last_Channel_Bit; | |
| 1771 | + config_bits |= NI_M_AI_CFG_LAST_CHAN; | |
| 1923 | 1772 | if (dither) |
| 1924 | − config_bits |= MSeries_AI_Config_Dither_Bit; | |
| 1773 | + config_bits |= NI_M_AI_CFG_DITHER; | |
| 1925 | 1774 | /* don't use 2's complement encoding */ |
| 1926 | − config_bits |= MSeries_AI_Config_Polarity_Bit; | |
| 1927 | − ni_writew(dev, config_bits, M_Offset_AI_Config_FIFO_Data); | |
| 1775 | + config_bits |= NI_M_AI_CFG_POLARITY; | |
| 1776 | + ni_writew(dev, config_bits, NI_M_AI_CFG_FIFO_DATA_REG); | |
| 1928 | 1777 | } |
| 1929 | 1778 | ni_prime_channelgain_list(dev); |
| 1930 | 1779 | } |
| @@ -1986,7 +1835,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev, · 55 unmodified lines | ||
| 1986 | 1835 | devpriv->changain_state = 0; |
| 1987 | 1836 | } |
| 1988 | 1837 | |
| 1989 | − ni_stc_writew(dev, 1, Configuration_Memory_Clear); | |
| 1838 | + ni_stc_writew(dev, 1, NISTC_CFG_MEM_CLR_REG); | |
| 1990 | 1839 | |
| 1991 | 1840 | /* Set up Calibration mode if required */ |
| 1992 | 1841 | if (devpriv->is_6143) { |
| @@ -1994,20 +1843,20 @@ static void ni_load_channelgain_list(struct comedi_device *dev, · 1 unmodified line | ||
| 1994 | 1843 | && !devpriv->ai_calib_source_enabled) { |
| 1995 | 1844 | /* Strobe Relay enable bit */ |
| 1996 | 1845 | ni_writew(dev, devpriv->ai_calib_source | |
| 1997 | − Calibration_Channel_6143_RelayOn, | |
| 1998 | − Calibration_Channel_6143); | |
| 1846 | + NI6143_CALIB_CHAN_RELAY_ON, | |
| 1847 | + NI6143_CALIB_CHAN_REG); | |
| 1999 | 1848 | ni_writew(dev, devpriv->ai_calib_source, |
| 2000 | − Calibration_Channel_6143); | |
| 1849 | + NI6143_CALIB_CHAN_REG); | |
| 2001 | 1850 | devpriv->ai_calib_source_enabled = 1; |
| 2002 | 1851 | msleep_interruptible(100); /* Allow relays to change */ |
| 2003 | 1852 | } else if (!(list[0] & CR_ALT_SOURCE) |
| 2004 | 1853 | && devpriv->ai_calib_source_enabled) { |
| 2005 | 1854 | /* Strobe Relay disable bit */ |
| 2006 | 1855 | ni_writew(dev, devpriv->ai_calib_source | |
| 2007 | − Calibration_Channel_6143_RelayOff, | |
| 2008 | − Calibration_Channel_6143); | |
| 1856 | + NI6143_CALIB_CHAN_RELAY_OFF, | |
| 1857 | + NI6143_CALIB_CHAN_REG); | |
| 2009 | 1858 | ni_writew(dev, devpriv->ai_calib_source, |
| 2010 | − Calibration_Channel_6143); | |
| 1859 | + NI6143_CALIB_CHAN_REG); | |
| 2011 | 1860 | devpriv->ai_calib_source_enabled = 0; |
| 2012 | 1861 | msleep_interruptible(100); /* Allow relays to change */ |
| 2013 | 1862 | } |
| @@ -2033,7 +1882,7 @@ static void ni_load_channelgain_list(struct comedi_device *dev, · 19 unmodified lines | ||
| 2033 | 1882 | if ((list[i] & CR_ALT_SOURCE)) { |
| 2034 | 1883 | if (devpriv->is_611x) |
| 2035 | 1884 | ni_writew(dev, CR_CHAN(list[i]) & 0x0003, |
| 2036 | − Calibration_Channel_Select_611x); | |
| 1885 | + NI611X_CALIB_CHAN_SEL_REG); | |
| 2037 | 1886 | } else { |
| 2038 | 1887 | if (devpriv->is_611x) |
| 2039 | 1888 | aref = AREF_DIFF; |
| @@ -2041,30 +1890,31 @@ static void ni_load_channelgain_list(struct comedi_device *dev, · 1 unmodified line | ||
| 2041 | 1890 | aref = AREF_OTHER; |
| 2042 | 1891 | switch (aref) { |
| 2043 | 1892 | case AREF_DIFF: |
| 2044 | − hi |= AI_DIFFERENTIAL; | |
| 1893 | + hi |= NI_E_AI_CFG_HI_TYPE_DIFF; | |
| 2045 | 1894 | break; |
| 2046 | 1895 | case AREF_COMMON: |
| 2047 | − hi |= AI_COMMON; | |
| 1896 | + hi |= NI_E_AI_CFG_HI_TYPE_COMMON; | |
| 2048 | 1897 | break; |
| 2049 | 1898 | case AREF_GROUND: |
| 2050 | − hi |= AI_GROUND; | |
| 1899 | + hi |= NI_E_AI_CFG_HI_TYPE_GROUND; | |
| 2051 | 1900 | break; |
| 2052 | 1901 | case AREF_OTHER: |
| 2053 | 1902 | break; |
| 2054 | 1903 | } |
| 2055 | 1904 | } |
| 2056 | − hi |= AI_CONFIG_CHANNEL(chan); | |
| 1905 | + hi |= NI_E_AI_CFG_HI_CHAN(chan); | |
| 2057 | 1906 | |
| 2058 | − ni_writew(dev, hi, Configuration_Memory_High); | |
| 1907 | + ni_writew(dev, hi, NI_E_AI_CFG_HI_REG); | |
| 2059 | 1908 | |
| 2060 | 1909 | if (!devpriv->is_6143) { |
| 2061 | − lo = range; | |
| 1910 | + lo = NI_E_AI_CFG_LO_GAIN(range); | |
| 1911 | + | |
| 2062 | 1912 | if (i == n_chan - 1) |
| 2063 | − lo |= AI_LAST_CHANNEL; | |
| 1913 | + lo |= NI_E_AI_CFG_LO_LAST_CHAN; | |
| 2064 | 1914 | if (dither) |
| 2065 | − lo |= AI_DITHER; | |
| 1915 | + lo |= NI_E_AI_CFG_LO_DITHER; | |
| 2066 | 1916 | |
| 2067 | − ni_writew(dev, lo, Configuration_Memory_Low); | |
| 1917 | + ni_writew(dev, lo, NI_E_AI_CFG_LO_REG); | |
| 2068 | 1918 | } |
| 2069 | 1919 | } |
| 2070 | 1920 | |
| @@ -2092,25 +1942,27 @@ static int ni_ai_insn_read(struct comedi_device *dev, · 21 unmodified lines | ||
| 2092 | 1942 | signbits = devpriv->ai_offset[0]; |
| 2093 | 1943 | if (devpriv->is_611x) { |
| 2094 | 1944 | for (n = 0; n < num_adc_stages_611x; n++) { |
| 2095 | − ni_stc_writew(dev, AI_CONVERT_Pulse, | |
| 2096 | − AI_Command_1_Register); | |
| 1945 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, | |
| 1946 | + NISTC_AI_CMD1_REG); | |
| 2097 | 1947 | udelay(1); |
| 2098 | 1948 | } |
| 2099 | 1949 | for (n = 0; n < insn->n; n++) { |
| 2100 | − ni_stc_writew(dev, AI_CONVERT_Pulse, | |
| 2101 | − AI_Command_1_Register); | |
| 1950 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, | |
| 1951 | + NISTC_AI_CMD1_REG); | |
| 2102 | 1952 | /* The 611x has screwy 32-bit FIFOs. */ |
| 2103 | 1953 | d = 0; |
| 2104 | 1954 | for (i = 0; i < NI_TIMEOUT; i++) { |
| 2105 | − if (ni_readb(dev, XXX_Status) & 0x80) { | |
| 2106 | − d = ni_readl(dev, ADC_FIFO_Data_611x); | |
| 1955 | + if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { | |
| 1956 | + d = ni_readl(dev, | |
| 1957 | + NI611X_AI_FIFO_DATA_REG); | |
| 2107 | 1958 | d >>= 16; |
| 2108 | 1959 | d &= 0xffff; |
| 2109 | 1960 | break; |
| 2110 | 1961 | } |
| 2111 | − if (!(ni_stc_readw(dev, AI_Status_1_Register) & | |
| 2112 | − AI_FIFO_Empty_St)) { | |
| 2113 | − d = ni_readl(dev, ADC_FIFO_Data_611x); | |
| 1962 | + if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & | |
| 1963 | + NISTC_AI_STATUS1_FIFO_E)) { | |
| 1964 | + d = ni_readl(dev, | |
| 1965 | + NI611X_AI_FIFO_DATA_REG); | |
| 2114 | 1966 | d &= 0xffff; |
| 2115 | 1967 | break; |
| 2116 | 1968 | } |
| @@ -2124,17 +1976,19 @@ static int ni_ai_insn_read(struct comedi_device *dev, · 7 unmodified lines | ||
| 2124 | 1976 | } |
| 2125 | 1977 | } else if (devpriv->is_6143) { |
| 2126 | 1978 | for (n = 0; n < insn->n; n++) { |
| 2127 | − ni_stc_writew(dev, AI_CONVERT_Pulse, | |
| 2128 | − AI_Command_1_Register); | |
| 1979 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, | |
| 1980 | + NISTC_AI_CMD1_REG); | |
| 2129 | 1981 | |
| 2130 | 1982 | /* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */ |
| 2131 | 1983 | dl = 0; |
| 2132 | 1984 | for (i = 0; i < NI_TIMEOUT; i++) { |
| 2133 | − if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) { | |
| 1985 | + if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & | |
| 1986 | + 0x01) { | |
| 2134 | 1987 | /* Get stranded sample into FIFO */ |
| 2135 | 1988 | ni_writel(dev, 0x01, |
| 2136 | − AIFIFO_Control_6143); | |
| 2137 | − dl = ni_readl(dev, AIFIFO_Data_6143); | |
| 1989 | + NI6143_AI_FIFO_CTRL_REG); | |
| 1990 | + dl = ni_readl(dev, | |
| 1991 | + NI6143_AI_FIFO_DATA_REG); | |
| 2138 | 1992 | break; |
| 2139 | 1993 | } |
| 2140 | 1994 | } |
| @@ -2146,11 +2000,11 @@ static int ni_ai_insn_read(struct comedi_device *dev, · 5 unmodified lines | ||
| 2146 | 2000 | } |
| 2147 | 2001 | } else { |
| 2148 | 2002 | for (n = 0; n < insn->n; n++) { |
| 2149 | − ni_stc_writew(dev, AI_CONVERT_Pulse, | |
| 2150 | − AI_Command_1_Register); | |
| 2003 | + ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, | |
| 2004 | + NISTC_AI_CMD1_REG); | |
| 2151 | 2005 | for (i = 0; i < NI_TIMEOUT; i++) { |
| 2152 | − if (!(ni_stc_readw(dev, AI_Status_1_Register) & | |
| 2153 | − AI_FIFO_Empty_St)) | |
| 2006 | + if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & | |
| 2007 | + NISTC_AI_STATUS1_FIFO_E)) | |
| 2154 | 2008 | break; |
| 2155 | 2009 | } |
| 2156 | 2010 | if (i == NI_TIMEOUT) { |
| @@ -2158,11 +2012,11 @@ static int ni_ai_insn_read(struct comedi_device *dev, · 1 unmodified line | ||
| 2158 | 2012 | return -ETIME; |
| 2159 | 2013 | } |
| 2160 | 2014 | if (devpriv->is_m_series) { |
| 2161 | − dl = ni_readl(dev, M_Offset_AI_FIFO_Data); | |
| 2015 | + dl = ni_readl(dev, NI_M_AI_FIFO_DATA_REG); | |
| 2162 | 2016 | dl &= mask; |
| 2163 | 2017 | data[n] = dl; |
| 2164 | 2018 | } else { |
| 2165 | − d = ni_readw(dev, ADC_FIFO_Data_Register); | |
| 2019 | + d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG); | |
| 2166 | 2020 | d += signbits; /* subtle: needs to be short addition */ |
| 2167 | 2021 | data[n] = d; |
| 2168 | 2022 | } |
| @@ -2374,8 +2228,8 @@ static int ni_ai_inttrig(struct comedi_device *dev, · 205 unmodified lines | ||
| 2374 | 2228 | if (trig_num != cmd->start_arg) |
| 2375 | 2229 | return -EINVAL; |
| 2376 | 2230 | |
| 2377 | − ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, | |
| 2378 | − AI_Command_2_Register); | |
| 2231 | + ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | devpriv->ai_cmd2, | |
| 2232 | + NISTC_AI_CMD2_REG); | |
| 2379 | 2233 | s->async->inttrig = NULL; |
| 2380 | 2234 | |
| 2381 | 2235 | return 1; |
| @@ -2391,6 +2245,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 9 unmodified lines | ||
| 2391 | 2245 | int start_stop_select = 0; |
| 2392 | 2246 | unsigned int stop_count; |
| 2393 | 2247 | int interrupt_a_enable = 0; |
| 2248 | + unsigned ai_trig; | |
| 2394 | 2249 | |
| 2395 | 2250 | if (dev->irq == 0) { |
| 2396 | 2251 | dev_err(dev->class_dev, "cannot run command without an irq\n"); |
| @@ -2401,51 +2256,47 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 4 unmodified lines | ||
| 2401 | 2256 | ni_load_channelgain_list(dev, s, cmd->chanlist_len, cmd->chanlist); |
| 2402 | 2257 | |
| 2403 | 2258 | /* start configuration */ |
| 2404 | − ni_stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register); | |
| 2259 | + ni_stc_writew(dev, NISTC_RESET_AI_CFG_START, NISTC_RESET_REG); | |
| 2405 | 2260 | |
| 2406 | 2261 | /* disable analog triggering for now, since it |
| 2407 | 2262 | * interferes with the use of pfi0 */ |
| 2408 | − devpriv->an_trig_etc_reg &= ~Analog_Trigger_Enable; | |
| 2409 | − ni_stc_writew(dev, devpriv->an_trig_etc_reg, | |
| 2410 | − Analog_Trigger_Etc_Register); | |
| 2263 | + devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_ENA; | |
| 2264 | + ni_stc_writew(dev, devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG); | |
| 2411 | 2265 | |
| 2266 | + ai_trig = NISTC_AI_TRIG_START2_SEL(0) | NISTC_AI_TRIG_START1_SYNC; | |
| 2412 | 2267 | switch (cmd->start_src) { |
| 2413 | 2268 | case TRIG_INT: |
| 2414 | 2269 | case TRIG_NOW: |
| 2415 | − ni_stc_writew(dev, | |
| 2416 | − AI_START2_Select(0) | | |
| 2417 | − AI_START1_Sync | AI_START1_Edge | | |
| 2418 | − AI_START1_Select(0), | |
| 2419 | − AI_Trigger_Select_Register); | |
| 2270 | + ai_trig |= NISTC_AI_TRIG_START1_EDGE | | |
| 2271 | + NISTC_AI_TRIG_START1_SEL(0); | |
| 2420 | 2272 | break; |
| 2421 | 2273 | case TRIG_EXT: |
| 2422 | − { | |
| 2423 | − int chan = CR_CHAN(cmd->start_arg); | |
| 2424 | − unsigned int bits = AI_START2_Select(0) | | |
| 2425 | − AI_START1_Sync | AI_START1_Select(chan + 1); | |
| 2426 | − | |
| 2427 | − if (cmd->start_arg & CR_INVERT) | |
| 2428 | − bits |= AI_START1_Polarity; | |
| 2429 | − if (cmd->start_arg & CR_EDGE) | |
| 2430 | − bits |= AI_START1_Edge; | |
| 2431 | − ni_stc_writew(dev, bits, AI_Trigger_Select_Register); | |
| 2432 | − break; | |
| 2433 | − } | |
| 2274 | + ai_trig |= NISTC_AI_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + | |
| 2275 | + 1); | |
| 2276 | + | |
| 2277 | + if (cmd->start_arg & CR_INVERT) | |
| 2278 | + ai_trig |= NISTC_AI_TRIG_START1_POLARITY; | |
| 2279 | + if (cmd->start_arg & CR_EDGE) | |
| 2280 | + ai_trig |= NISTC_AI_TRIG_START1_EDGE; | |
| 2281 | + break; | |
| 2434 | 2282 | } |
| 2283 | + ni_stc_writew(dev, ai_trig, NISTC_AI_TRIG_SEL_REG); | |
| 2435 | 2284 | |
| 2436 | − mode2 &= ~AI_Pre_Trigger; | |
| 2437 | − mode2 &= ~AI_SC_Initial_Load_Source; | |
| 2438 | − mode2 &= ~AI_SC_Reload_Mode; | |
| 2439 | − ni_stc_writew(dev, mode2, AI_Mode_2_Register); | |
| 2285 | + mode2 &= ~NISTC_AI_MODE2_PRE_TRIGGER; | |
| 2286 | + mode2 &= ~NISTC_AI_MODE2_SC_INIT_LOAD_SRC; | |
| 2287 | + mode2 &= ~NISTC_AI_MODE2_SC_RELOAD_MODE; | |
| 2288 | + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); | |
| 2440 | 2289 | |
| 2441 | 2290 | if (cmd->chanlist_len == 1 || devpriv->is_611x || devpriv->is_6143) { |
| 2442 | − start_stop_select |= AI_STOP_Polarity; | |
| 2443 | − start_stop_select |= AI_STOP_Select(31); /* logic low */ | |
| 2444 | − start_stop_select |= AI_STOP_Sync; | |
| 2291 | + /* logic low */ | |
| 2292 | + start_stop_select |= NISTC_AI_STOP_POLARITY | | |
| 2293 | + NISTC_AI_STOP_SEL(31) | | |
| 2294 | + NISTC_AI_STOP_SYNC; | |
| 2445 | 2295 | } else { |
| 2446 | − start_stop_select |= AI_STOP_Select(19); /* ai configuration memory */ | |
| 2296 | + /* ai configuration memory */ | |
| 2297 | + start_stop_select |= NISTC_AI_STOP_SEL(19); | |
| 2447 | 2298 | } |
| 2448 | − ni_stc_writew(dev, start_stop_select, AI_START_STOP_Select_Register); | |
| 2299 | + ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); | |
| 2449 | 2300 | |
| 2450 | 2301 | devpriv->ai_cmd2 = 0; |
| 2451 | 2302 | switch (cmd->stop_src) { |
| @@ -2457,80 +2308,80 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 5 unmodified lines | ||
| 2457 | 2308 | stop_count += num_adc_stages_611x; |
| 2458 | 2309 | } |
| 2459 | 2310 | /* stage number of scans */ |
| 2460 | − ni_stc_writel(dev, stop_count, AI_SC_Load_A_Registers); | |
| 2311 | + ni_stc_writel(dev, stop_count, NISTC_AI_SC_LOADA_REG); | |
| 2461 | 2312 | |
| 2462 | − mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Trigger_Once; | |
| 2463 | − ni_stc_writew(dev, mode1, AI_Mode_1_Register); | |
| 2313 | + mode1 |= NISTC_AI_MODE1_START_STOP | | |
| 2314 | + NISTC_AI_MODE1_RSVD | | |
| 2315 | + NISTC_AI_MODE1_TRIGGER_ONCE; | |
| 2316 | + ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); | |
| 2464 | 2317 | /* load SC (Scan Count) */ |
| 2465 | − ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register); | |
| 2318 | + ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG); | |
| 2466 | 2319 | |
| 2467 | 2320 | if (stop_count == 0) { |
| 2468 | − devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan; | |
| 2469 | − interrupt_a_enable |= AI_STOP_Interrupt_Enable; | |
| 2321 | + devpriv->ai_cmd2 |= NISTC_AI_CMD2_END_ON_EOS; | |
| 2322 | + interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; | |
| 2470 | 2323 | /* this is required to get the last sample for chanlist_len > 1, not sure why */ |
| 2471 | 2324 | if (cmd->chanlist_len > 1) |
| 2472 | − start_stop_select |= | |
| 2473 | − AI_STOP_Polarity | AI_STOP_Edge; | |
| 2325 | + start_stop_select |= NISTC_AI_STOP_POLARITY | | |
| 2326 | + NISTC_AI_STOP_EDGE; | |
| 2474 | 2327 | } |
| 2475 | 2328 | break; |
| 2476 | 2329 | case TRIG_NONE: |
| 2477 | 2330 | /* stage number of scans */ |
| 2478 | − ni_stc_writel(dev, 0, AI_SC_Load_A_Registers); | |
| 2331 | + ni_stc_writel(dev, 0, NISTC_AI_SC_LOADA_REG); | |
| 2479 | 2332 | |
| 2480 | − mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Continuous; | |
| 2481 | − ni_stc_writew(dev, mode1, AI_Mode_1_Register); | |
| 2333 | + mode1 |= NISTC_AI_MODE1_START_STOP | | |
| 2334 | + NISTC_AI_MODE1_RSVD | | |
| 2335 | + NISTC_AI_MODE1_CONTINUOUS; | |
| 2336 | + ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); | |
| 2482 | 2337 | |
| 2483 | 2338 | /* load SC (Scan Count) */ |
| 2484 | − ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register); | |
| 2339 | + ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG); | |
| 2485 | 2340 | break; |
| 2486 | 2341 | } |
| 2487 | 2342 | |
| 2488 | 2343 | switch (cmd->scan_begin_src) { |
| 2489 | 2344 | case TRIG_TIMER: |
| 2490 | 2345 | /* |
| 2491 | − stop bits for non 611x boards | |
| 2492 | − AI_SI_Special_Trigger_Delay=0 | |
| 2493 | − AI_Pre_Trigger=0 | |
| 2494 | − AI_START_STOP_Select_Register: | |
| 2495 | − AI_START_Polarity=0 (?) rising edge | |
| 2496 | − AI_START_Edge=1 edge triggered | |
| 2497 | − AI_START_Sync=1 (?) | |
| 2498 | − AI_START_Select=0 SI_TC | |
| 2499 | − AI_STOP_Polarity=0 rising edge | |
| 2500 | − AI_STOP_Edge=0 level | |
| 2501 | − AI_STOP_Sync=1 | |
| 2502 | − AI_STOP_Select=19 external pin (configuration mem) | |
| 2346 | + * stop bits for non 611x boards | |
| 2347 | + * NISTC_AI_MODE3_SI_TRIG_DELAY=0 | |
| 2348 | + * NISTC_AI_MODE2_PRE_TRIGGER=0 | |
| 2349 | + * NISTC_AI_START_STOP_REG: | |
| 2350 | + * NISTC_AI_START_POLARITY=0 (?) rising edge | |
| 2351 | + * NISTC_AI_START_EDGE=1 edge triggered | |
| 2352 | + * NISTC_AI_START_SYNC=1 (?) | |
| 2353 | + * NISTC_AI_START_SEL=0 SI_TC | |
| 2354 | + * NISTC_AI_STOP_POLARITY=0 rising edge | |
| 2355 | + * NISTC_AI_STOP_EDGE=0 level | |
| 2356 | + * NISTC_AI_STOP_SYNC=1 | |
| 2357 | + * NISTC_AI_STOP_SEL=19 external pin (configuration mem) | |
| 2503 | 2358 | */ |
| 2504 | − start_stop_select |= AI_START_Edge | AI_START_Sync; | |
| 2505 | − ni_stc_writew(dev, start_stop_select, | |
| 2506 | − AI_START_STOP_Select_Register); | |
| 2359 | + start_stop_select |= NISTC_AI_START_EDGE | NISTC_AI_START_SYNC; | |
| 2360 | + ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); | |
| 2507 | 2361 | |
| 2508 | − mode2 |= AI_SI_Reload_Mode(0); | |
| 2509 | − /* AI_SI_Initial_Load_Source=A */ | |
| 2510 | − mode2 &= ~AI_SI_Initial_Load_Source; | |
| 2511 | − /* mode2 |= AI_SC_Reload_Mode; */ | |
| 2512 | − ni_stc_writew(dev, mode2, AI_Mode_2_Register); | |
| 2362 | + mode2 &= ~NISTC_AI_MODE2_SI_INIT_LOAD_SRC; /* A */ | |
| 2363 | + mode2 |= NISTC_AI_MODE2_SI_RELOAD_MODE(0); | |
| 2364 | + /* mode2 |= NISTC_AI_MODE2_SC_RELOAD_MODE; */ | |
| 2365 | + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); | |
| 2513 | 2366 | |
| 2514 | 2367 | /* load SI */ |
| 2515 | 2368 | timer = ni_ns_to_timer(dev, cmd->scan_begin_arg, |
| 2516 | 2369 | CMDF_ROUND_NEAREST); |
| 2517 | − ni_stc_writel(dev, timer, AI_SI_Load_A_Registers); | |
| 2518 | − ni_stc_writew(dev, AI_SI_Load, AI_Command_1_Register); | |
| 2370 | + ni_stc_writel(dev, timer, NISTC_AI_SI_LOADA_REG); | |
| 2371 | + ni_stc_writew(dev, NISTC_AI_CMD1_SI_LOAD, NISTC_AI_CMD1_REG); | |
| 2519 | 2372 | break; |
| 2520 | 2373 | case TRIG_EXT: |
| 2521 | 2374 | if (cmd->scan_begin_arg & CR_EDGE) |
| 2522 | − start_stop_select |= AI_START_Edge; | |
| 2523 | − /* AI_START_Polarity==1 is falling edge */ | |
| 2524 | − if (cmd->scan_begin_arg & CR_INVERT) | |
| 2525 | − start_stop_select |= AI_START_Polarity; | |
| 2375 | + start_stop_select |= NISTC_AI_START_EDGE; | |
| 2376 | + if (cmd->scan_begin_arg & CR_INVERT) /* falling edge */ | |
| 2377 | + start_stop_select |= NISTC_AI_START_POLARITY; | |
| 2526 | 2378 | if (cmd->scan_begin_src != cmd->convert_src || |
| 2527 | 2379 | (cmd->scan_begin_arg & ~CR_EDGE) != |
| 2528 | 2380 | (cmd->convert_arg & ~CR_EDGE)) |
| 2529 | − start_stop_select |= AI_START_Sync; | |
| 2381 | + start_stop_select |= NISTC_AI_START_SYNC; | |
| 2530 | 2382 | start_stop_select |= |
| 2531 | − AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg)); | |
| 2532 | − ni_stc_writew(dev, start_stop_select, | |
| 2533 | − AI_START_STOP_Select_Register); | |
| 2383 | + NISTC_AI_START_SEL(1 + CR_CHAN(cmd->scan_begin_arg)); | |
| 2384 | + ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); | |
| 2534 | 2385 | break; |
| 2535 | 2386 | } |
| 2536 | 2387 | |
| @@ -2543,46 +2394,43 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 6 unmodified lines | ||
| 2543 | 2394 | timer = ni_ns_to_timer(dev, cmd->convert_arg, |
| 2544 | 2395 | CMDF_ROUND_NEAREST); |
| 2545 | 2396 | /* 0,0 does not work */ |
| 2546 | − ni_stc_writew(dev, 1, AI_SI2_Load_A_Register); | |
| 2547 | − ni_stc_writew(dev, timer, AI_SI2_Load_B_Register); | |
| 2397 | + ni_stc_writew(dev, 1, NISTC_AI_SI2_LOADA_REG); | |
| 2398 | + ni_stc_writew(dev, timer, NISTC_AI_SI2_LOADB_REG); | |
| 2548 | 2399 | |
| 2549 | − /* AI_SI2_Reload_Mode = alternate */ | |
| 2550 | − /* AI_SI2_Initial_Load_Source = A */ | |
| 2551 | − mode2 &= ~AI_SI2_Initial_Load_Source; | |
| 2552 | − mode2 |= AI_SI2_Reload_Mode; | |
| 2553 | − ni_stc_writew(dev, mode2, AI_Mode_2_Register); | |
| 2400 | + mode2 &= ~NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* A */ | |
| 2401 | + mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ | |
| 2402 | + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); | |
| 2554 | 2403 | |
| 2555 | − /* AI_SI2_Load */ | |
| 2556 | − ni_stc_writew(dev, AI_SI2_Load, AI_Command_1_Register); | |
| 2404 | + ni_stc_writew(dev, NISTC_AI_CMD1_SI2_LOAD, NISTC_AI_CMD1_REG); | |
| 2557 | 2405 | |
| 2558 | − mode2 |= AI_SI2_Reload_Mode; /* alternate */ | |
| 2559 | − mode2 |= AI_SI2_Initial_Load_Source; /* B */ | |
| 2560 | − | |
| 2561 | − ni_stc_writew(dev, mode2, AI_Mode_2_Register); | |
| 2406 | + mode2 |= NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* B */ | |
| 2407 | + mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ | |
| 2408 | + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); | |
| 2562 | 2409 | break; |
| 2563 | 2410 | case TRIG_EXT: |
| 2564 | − mode1 |= AI_CONVERT_Source_Select(1 + cmd->convert_arg); | |
| 2411 | + mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg); | |
| 2565 | 2412 | if ((cmd->convert_arg & CR_INVERT) == 0) |
| 2566 | − mode1 |= AI_CONVERT_Source_Polarity; | |
| 2567 | − ni_stc_writew(dev, mode1, AI_Mode_1_Register); | |
| 2413 | + mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY; | |
| 2414 | + ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); | |
| 2568 | 2415 | |
| 2569 | − mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable; | |
| 2570 | − ni_stc_writew(dev, mode2, AI_Mode_2_Register); | |
| 2416 | + mode2 |= NISTC_AI_MODE2_SC_GATE_ENA | | |
| 2417 | + NISTC_AI_MODE2_START_STOP_GATE_ENA; | |
| 2418 | + ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); | |
| 2571 | 2419 | |
| 2572 | 2420 | break; |
| 2573 | 2421 | } |
| 2574 | 2422 | |
| 2575 | 2423 | if (dev->irq) { |
| 2576 | 2424 | /* interrupt on FIFO, errors, SC_TC */ |
| 2577 | − interrupt_a_enable |= AI_Error_Interrupt_Enable | | |
| 2578 | − AI_SC_TC_Interrupt_Enable; | |
| 2425 | + interrupt_a_enable |= NISTC_INTA_ENA_AI_ERR | | |
| 2426 | + NISTC_INTA_ENA_AI_SC_TC; | |
| 2579 | 2427 | |
| 2580 | 2428 | #ifndef PCIDMA |
| 2581 | − interrupt_a_enable |= AI_FIFO_Interrupt_Enable; | |
| 2429 | + interrupt_a_enable |= NISTC_INTA_ENA_AI_FIFO; | |
| 2582 | 2430 | #endif |
| 2583 | 2431 | |
| 2584 | − if (cmd->flags & CMDF_WAKE_EOS | |
| 2585 | − || (devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) { | |
| 2432 | + if ((cmd->flags & CMDF_WAKE_EOS) || | |
| 2433 | + (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS)) { | |
| 2586 | 2434 | /* wake on end-of-scan */ |
| 2587 | 2435 | devpriv->aimode = AIMODE_SCAN; |
| 2588 | 2436 | } else { |
| @@ -2593,66 +2441,60 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 4 unmodified lines | ||
| 2593 | 2441 | case AIMODE_HALF_FULL: |
| 2594 | 2442 | /*generate FIFO interrupts and DMA requests on half-full */ |
| 2595 | 2443 | #ifdef PCIDMA |
| 2596 | − ni_stc_writew(dev, AI_FIFO_Mode_HF_to_E, | |
| 2597 | − AI_Mode_3_Register); | |
| 2444 | + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF_E, | |
| 2445 | + NISTC_AI_MODE3_REG); | |
| 2598 | 2446 | #else |
| 2599 | − ni_stc_writew(dev, AI_FIFO_Mode_HF, | |
| 2600 | − AI_Mode_3_Register); | |
| 2447 | + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, | |
| 2448 | + NISTC_AI_MODE3_REG); | |
| 2601 | 2449 | #endif |
| 2602 | 2450 | break; |
| 2603 | 2451 | case AIMODE_SAMPLE: |
| 2604 | 2452 | /*generate FIFO interrupts on non-empty */ |
| 2605 | − ni_stc_writew(dev, AI_FIFO_Mode_NE, | |
| 2606 | − AI_Mode_3_Register); | |
| 2453 | + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, | |
| 2454 | + NISTC_AI_MODE3_REG); | |
| 2607 | 2455 | break; |
| 2608 | 2456 | case AIMODE_SCAN: |
| 2609 | 2457 | #ifdef PCIDMA |
| 2610 | − ni_stc_writew(dev, AI_FIFO_Mode_NE, | |
| 2611 | − AI_Mode_3_Register); | |
| 2458 | + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, | |
| 2459 | + NISTC_AI_MODE3_REG); | |
| 2612 | 2460 | #else |
| 2613 | − ni_stc_writew(dev, AI_FIFO_Mode_HF, | |
| 2614 | − AI_Mode_3_Register); | |
| 2461 | + ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, | |
| 2462 | + NISTC_AI_MODE3_REG); | |
| 2615 | 2463 | #endif |
| 2616 | − interrupt_a_enable |= AI_STOP_Interrupt_Enable; | |
| 2464 | + interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; | |
| 2617 | 2465 | break; |
| 2618 | 2466 | default: |
| 2619 | 2467 | break; |
| 2620 | 2468 | } |
| 2621 | 2469 | |
| 2622 | 2470 | /* clear interrupts */ |
| 2623 | − ni_stc_writew(dev, | |
| 2624 | − AI_Error_Interrupt_Ack | | |
| 2625 | − AI_STOP_Interrupt_Ack | | |
| 2626 | − AI_START_Interrupt_Ack | | |
| 2627 | − AI_START2_Interrupt_Ack | | |
| 2628 | − AI_START1_Interrupt_Ack | | |
| 2629 | − AI_SC_TC_Interrupt_Ack | | |
| 2630 | − AI_SC_TC_Error_Confirm, | |
| 2631 | − Interrupt_A_Ack_Register); | |
| 2632 | − | |
| 2633 | − ni_set_bits(dev, Interrupt_A_Enable_Register, | |
| 2634 | − interrupt_a_enable, 1); | |
| 2471 | + ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); | |
| 2472 | + | |
| 2473 | + ni_set_bits(dev, NISTC_INTA_ENA_REG, interrupt_a_enable, 1); | |
| 2635 | 2474 | } else { |
| 2636 | 2475 | /* interrupt on nothing */ |
| 2637 | − ni_set_bits(dev, Interrupt_A_Enable_Register, ~0, 0); | |
| 2476 | + ni_set_bits(dev, NISTC_INTA_ENA_REG, ~0, 0); | |
| 2638 | 2477 | |
| 2639 | 2478 | /* XXX start polling if necessary */ |
| 2640 | 2479 | } |
| 2641 | 2480 | |
| 2642 | 2481 | /* end configuration */ |
| 2643 | − ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register); | |
| 2482 | + ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG); | |
| 2644 | 2483 | |
| 2645 | 2484 | switch (cmd->scan_begin_src) { |
| 2646 | 2485 | case TRIG_TIMER: |
| 2647 | − ni_stc_writew(dev, | |
| 2648 | − AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, | |
| 2649 | − AI_Command_1_Register); | |
| 2486 | + ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | | |
| 2487 | + NISTC_AI_CMD1_SI_ARM | | |
| 2488 | + NISTC_AI_CMD1_DIV_ARM | | |
| 2489 | + NISTC_AI_CMD1_SC_ARM, | |
| 2490 | + NISTC_AI_CMD1_REG); | |
| 2650 | 2491 | break; |
| 2651 | 2492 | case TRIG_EXT: |
| 2652 | − /* XXX AI_SI_Arm? */ | |
| 2653 | − ni_stc_writew(dev, | |
| 2654 | − AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, | |
| 2655 | − AI_Command_1_Register); | |
| 2493 | + ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | | |
| 2494 | + NISTC_AI_CMD1_SI_ARM | /* XXX ? */ | |
| 2495 | + NISTC_AI_CMD1_DIV_ARM | | |
| 2496 | + NISTC_AI_CMD1_SC_ARM, | |
| 2497 | + NISTC_AI_CMD1_REG); | |
| 2656 | 2498 | break; |
| 2657 | 2499 | } |
| 2658 | 2500 | |
| @@ -2666,9 +2508,9 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 7 unmodified lines | ||
| 2666 | 2508 | #endif |
| 2667 | 2509 | |
| 2668 | 2510 | if (cmd->start_src == TRIG_NOW) { |
| 2669 | − /* AI_START1_Pulse */ | |
| 2670 | − ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, | |
| 2671 | − AI_Command_2_Register); | |
| 2511 | + ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | | |
| 2512 | + devpriv->ai_cmd2, | |
| 2513 | + NISTC_AI_CMD2_REG); | |
| 2672 | 2514 | s->async->inttrig = NULL; |
| 2673 | 2515 | } else if (cmd->start_src == TRIG_EXT) { |
| 2674 | 2516 | s->async->inttrig = NULL; |
| @@ -2691,12 +2533,8 @@ static int ni_ai_insn_config(struct comedi_device *dev, · 16 unmodified lines | ||
| 2691 | 2533 | switch (data[0]) { |
| 2692 | 2534 | case INSN_CONFIG_ALT_SOURCE: |
| 2693 | 2535 | if (devpriv->is_m_series) { |
| 2694 | − if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask | | |
| 2695 | − MSeries_AI_Bypass_Cal_Sel_Neg_Mask | | |
| 2696 | − MSeries_AI_Bypass_Mode_Mux_Mask | | |
| 2697 | − MSeries_AO_Bypass_AO_Cal_Sel_Mask)) { | |
| 2536 | + if (data[1] & ~NI_M_CFG_BYPASS_AI_CAL_MASK) | |
| 2698 | 2537 | return -EINVAL; |
| 2699 | − } | |
| 2700 | 2538 | devpriv->ai_calib_source = data[1]; |
| 2701 | 2539 | } else if (devpriv->is_6143) { |
| 2702 | 2540 | unsigned int calib_source; |
| @@ -2704,7 +2542,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, · 1 unmodified line | ||
| 2704 | 2542 | calib_source = data[1] & 0xf; |
| 2705 | 2543 | |
| 2706 | 2544 | devpriv->ai_calib_source = calib_source; |
| 2707 | − ni_writew(dev, calib_source, Calibration_Channel_6143); | |
| 2545 | + ni_writew(dev, calib_source, NI6143_CALIB_CHAN_REG); | |
| 2708 | 2546 | } else { |
| 2709 | 2547 | unsigned int calib_source; |
| 2710 | 2548 | unsigned int calib_source_adjust; |
| @@ -2717,7 +2555,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, · 6 unmodified lines | ||
| 2717 | 2555 | devpriv->ai_calib_source = calib_source; |
| 2718 | 2556 | if (devpriv->is_611x) { |
| 2719 | 2557 | ni_writeb(dev, calib_source_adjust, |
| 2720 | − Cal_Gain_Select_611x); | |
| 2558 | + NI611X_CAL_GAIN_SEL_REG); | |
| 2721 | 2559 | } |
| 2722 | 2560 | } |
| 2723 | 2561 | return 2; |
| @@ -2771,10 +2609,10 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, · 47 unmodified lines | ||
| 2771 | 2609 | |
| 2772 | 2610 | if (timed) { |
| 2773 | 2611 | for (i = 0; i < s->n_chan; ++i) { |
| 2774 | − devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit; | |
| 2612 | + devpriv->ao_conf[i] &= ~NI_M_AO_CFG_BANK_UPDATE_TIMED; | |
| 2775 | 2613 | ni_writeb(dev, devpriv->ao_conf[i], |
| 2776 | − M_Offset_AO_Config_Bank(i)); | |
| 2777 | − ni_writeb(dev, 0xf, M_Offset_AO_Waveform_Order(i)); | |
| 2614 | + NI_M_AO_CFG_BANK_REG(i)); | |
| 2615 | + ni_writeb(dev, 0xf, NI_M_AO_WAVEFORM_ORDER_REG(i)); | |
| 2778 | 2616 | } |
| 2779 | 2617 | } |
| 2780 | 2618 | for (i = 0; i < n_chans; i++) { |
| @@ -2787,24 +2625,22 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, · 6 unmodified lines | ||
| 2787 | 2625 | conf = 0; |
| 2788 | 2626 | switch (krange->max - krange->min) { |
| 2789 | 2627 | case 20000000: |
| 2790 | − conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; | |
| 2791 | − ni_writeb(dev, 0, | |
| 2792 | − M_Offset_AO_Reference_Attenuation(chan)); | |
| 2628 | + conf |= NI_M_AO_CFG_BANK_REF_INT_10V; | |
| 2629 | + ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan)); | |
| 2793 | 2630 | break; |
| 2794 | 2631 | case 10000000: |
| 2795 | − conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; | |
| 2796 | − ni_writeb(dev, 0, | |
| 2797 | − M_Offset_AO_Reference_Attenuation(chan)); | |
| 2632 | + conf |= NI_M_AO_CFG_BANK_REF_INT_5V; | |
| 2633 | + ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan)); | |
| 2798 | 2634 | break; |
| 2799 | 2635 | case 4000000: |
| 2800 | − conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; | |
| 2801 | − ni_writeb(dev, MSeries_Attenuate_x5_Bit, | |
| 2802 | − M_Offset_AO_Reference_Attenuation(chan)); | |
| 2636 | + conf |= NI_M_AO_CFG_BANK_REF_INT_10V; | |
| 2637 | + ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, | |
| 2638 | + NI_M_AO_REF_ATTENUATION_REG(chan)); | |
| 2803 | 2639 | break; |
| 2804 | 2640 | case 2000000: |
| 2805 | − conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; | |
| 2806 | − ni_writeb(dev, MSeries_Attenuate_x5_Bit, | |
| 2807 | − M_Offset_AO_Reference_Attenuation(chan)); | |
| 2641 | + conf |= NI_M_AO_CFG_BANK_REF_INT_5V; | |
| 2642 | + ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, | |
| 2643 | + NI_M_AO_REF_ATTENUATION_REG(chan)); | |
| 2808 | 2644 | break; |
| 2809 | 2645 | default: |
| 2810 | 2646 | dev_err(dev->class_dev, |
| @@ -2813,10 +2649,10 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, · 2 unmodified lines | ||
| 2813 | 2649 | } |
| 2814 | 2650 | switch (krange->max + krange->min) { |
| 2815 | 2651 | case 0: |
| 2816 | − conf |= MSeries_AO_DAC_Offset_0V_Bits; | |
| 2652 | + conf |= NI_M_AO_CFG_BANK_OFFSET_0V; | |
| 2817 | 2653 | break; |
| 2818 | 2654 | case 10000000: |
| 2819 | − conf |= MSeries_AO_DAC_Offset_5V_Bits; | |
| 2655 | + conf |= NI_M_AO_CFG_BANK_OFFSET_5V; | |
| 2820 | 2656 | break; |
| 2821 | 2657 | default: |
| 2822 | 2658 | dev_err(dev->class_dev, |
| @@ -2824,10 +2660,10 @@ static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, · 1 unmodified line | ||
| 2824 | 2660 | break; |
| 2825 | 2661 | } |
| 2826 | 2662 | if (timed) |
| 2827 | − conf |= MSeries_AO_Update_Timed_Bit; | |
| 2828 | − ni_writeb(dev, conf, M_Offset_AO_Config_Bank(chan)); | |
| 2663 | + conf |= NI_M_AO_CFG_BANK_UPDATE_TIMED; | |
| 2664 | + ni_writeb(dev, conf, NI_M_AO_CFG_BANK_REG(chan)); | |
| 2829 | 2665 | devpriv->ao_conf[chan] = conf; |
| 2830 | − ni_writeb(dev, i, M_Offset_AO_Waveform_Order(chan)); | |
| 2666 | + ni_writeb(dev, i, NI_M_AO_WAVEFORM_ORDER_REG(chan)); | |
| 2831 | 2667 | } |
| 2832 | 2668 | return invert; |
| 2833 | 2669 | } |
| @@ -2847,27 +2683,27 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, · 13 unmodified lines | ||
| 2847 | 2683 | for (i = 0; i < n_chans; i++) { |
| 2848 | 2684 | chan = CR_CHAN(chanspec[i]); |
| 2849 | 2685 | range = CR_RANGE(chanspec[i]); |
| 2850 | − conf = AO_Channel(chan); | |
| 2686 | + conf = NI_E_AO_DACSEL(chan); | |
| 2851 | 2687 | |
| 2852 | 2688 | if (comedi_range_is_bipolar(s, range)) { |
| 2853 | − conf |= AO_Bipolar; | |
| 2689 | + conf |= NI_E_AO_CFG_BIP; | |
| 2854 | 2690 | invert = (s->maxdata + 1) >> 1; |
| 2855 | 2691 | } else { |
| 2856 | 2692 | invert = 0; |
| 2857 | 2693 | } |
| 2858 | 2694 | if (comedi_range_is_external(s, range)) |
| 2859 | − conf |= AO_Ext_Ref; | |
| 2695 | + conf |= NI_E_AO_EXT_REF; | |
| 2860 | 2696 | |
| 2861 | 2697 | /* not all boards can deglitch, but this shouldn't hurt */ |
| 2862 | 2698 | if (chanspec[i] & CR_DEGLITCH) |
| 2863 | − conf |= AO_Deglitch; | |
| 2699 | + conf |= NI_E_AO_DEGLITCH; | |
| 2864 | 2700 | |
| 2865 | 2701 | /* analog reference */ |
| 2866 | 2702 | /* AREF_OTHER connects AO ground to AI ground, i think */ |
| 2867 | − conf |= (CR_AREF(chanspec[i]) == | |
| 2868 | − AREF_OTHER) ? AO_Ground_Ref : 0; | |
| 2703 | + if (CR_AREF(chanspec[i]) == AREF_OTHER) | |
| 2704 | + conf |= NI_E_AO_GROUND_REF; | |
| 2869 | 2705 | |
| 2870 | − ni_writew(dev, conf, AO_Configuration); | |
| 2706 | + ni_writew(dev, conf, NI_E_AO_CFG_REG); | |
| 2871 | 2707 | devpriv->ao_conf[chan] = conf; |
| 2872 | 2708 | } |
| 2873 | 2709 | return invert; |
| @@ -2899,13 +2735,13 @@ static int ni_ao_insn_write(struct comedi_device *dev, · 25 unmodified lines | ||
| 2899 | 2735 | int i; |
| 2900 | 2736 | |
| 2901 | 2737 | if (devpriv->is_6xxx) { |
| 2902 | − ni_ao_win_outw(dev, 1 << chan, AO_Immediate_671x); | |
| 2738 | + ni_ao_win_outw(dev, 1 << chan, NI671X_AO_IMMEDIATE_REG); | |
| 2903 | 2739 | |
| 2904 | − reg = DACx_Direct_Data_671x(chan); | |
| 2740 | + reg = NI671X_DAC_DIRECT_DATA_REG(chan); | |
| 2905 | 2741 | } else if (devpriv->is_m_series) { |
| 2906 | − reg = M_Offset_DAC_Direct_Data(chan); | |
| 2742 | + reg = NI_M_DAC_DIRECT_DATA_REG(chan); | |
| 2907 | 2743 | } else { |
| 2908 | − reg = (chan) ? DAC1_Direct_Data : DAC0_Direct_Data; | |
| 2744 | + reg = NI_E_DAC_DIRECT_DATA_REG(chan); | |
| 2909 | 2745 | } |
| 2910 | 2746 | |
| 2911 | 2747 | ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); |
| @@ -2995,13 +2831,13 @@ static int ni_ao_inttrig(struct comedi_device *dev, · 83 unmodified lines | ||
| 2995 | 2831 | multiple times) */ |
| 2996 | 2832 | s->async->inttrig = NULL; |
| 2997 | 2833 | |
| 2998 | − ni_set_bits(dev, Interrupt_B_Enable_Register, | |
| 2999 | − AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0); | |
| 3000 | − interrupt_b_bits = AO_Error_Interrupt_Enable; | |
| 2834 | + ni_set_bits(dev, NISTC_INTB_ENA_REG, | |
| 2835 | + NISTC_INTB_ENA_AO_FIFO | NISTC_INTB_ENA_AO_ERR, 0); | |
| 2836 | + interrupt_b_bits = NISTC_INTB_ENA_AO_ERR; | |
| 3001 | 2837 | #ifdef PCIDMA |
| 3002 | − ni_stc_writew(dev, 1, DAC_FIFO_Clear); | |
| 2838 | + ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG); | |
| 3003 | 2839 | if (devpriv->is_6xxx) |
| 3004 | − ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x); | |
| 2840 | + ni_ao_win_outl(dev, 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG); | |
| 3005 | 2841 | ret = ni_ao_setup_MITE_dma(dev); |
| 3006 | 2842 | if (ret) |
| 3007 | 2843 | return ret; |
| @@ -3013,17 +2849,17 @@ static int ni_ao_inttrig(struct comedi_device *dev, · 5 unmodified lines | ||
| 3013 | 2849 | if (ret == 0) |
| 3014 | 2850 | return -EPIPE; |
| 3015 | 2851 | |
| 3016 | − interrupt_b_bits |= AO_FIFO_Interrupt_Enable; | |
| 2852 | + interrupt_b_bits |= NISTC_INTB_ENA_AO_FIFO; | |
| 3017 | 2853 | #endif |
| 3018 | 2854 | |
| 3019 | − ni_stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE, | |
| 3020 | − AO_Mode_3_Register); | |
| 3021 | − ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); | |
| 2855 | + ni_stc_writew(dev, devpriv->ao_mode3 | NISTC_AO_MODE3_NOT_AN_UPDATE, | |
| 2856 | + NISTC_AO_MODE3_REG); | |
| 2857 | + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); | |
| 3022 | 2858 | /* wait for DACs to be loaded */ |
| 3023 | 2859 | for (i = 0; i < timeout; i++) { |
| 3024 | 2860 | udelay(1); |
| 3025 | − if ((ni_stc_readw(dev, Joint_Status_2_Register) & | |
| 3026 | − AO_TMRDACWRs_In_Progress_St) == 0) | |
| 2861 | + if ((ni_stc_readw(dev, NISTC_STATUS2_REG) & | |
| 2862 | + NISTC_STATUS2_AO_TMRDACWRS_IN_PROGRESS) == 0) | |
| 3027 | 2863 | break; |
| 3028 | 2864 | } |
| 3029 | 2865 | if (i == timeout) { |
| @@ -3035,17 +2871,20 @@ static int ni_ao_inttrig(struct comedi_device *dev, · 5 unmodified lines | ||
| 3035 | 2871 | * stc manual says we are need to clear error interrupt after |
| 3036 | 2872 | * AO_TMRDACWRs_In_Progress_St clears |
| 3037 | 2873 | */ |
| 3038 | − ni_stc_writew(dev, AO_Error_Interrupt_Ack, Interrupt_B_Ack_Register); | |
| 2874 | + ni_stc_writew(dev, NISTC_INTB_ACK_AO_ERR, NISTC_INTB_ACK_REG); | |
| 3039 | 2875 | |
| 3040 | − ni_set_bits(dev, Interrupt_B_Enable_Register, interrupt_b_bits, 1); | |
| 2876 | + ni_set_bits(dev, NISTC_INTB_ENA_REG, interrupt_b_bits, 1); | |
| 3041 | 2877 | |
| 3042 | − ni_stc_writew(dev, devpriv->ao_cmd1 | | |
| 3043 | − AO_UI_Arm | AO_UC_Arm | AO_BC_Arm | | |
| 3044 | − AO_DAC1_Update_Mode | AO_DAC0_Update_Mode, | |
| 3045 | − AO_Command_1_Register); | |
| 2878 | + ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM | | |
| 2879 | + NISTC_AO_CMD1_UC_ARM | | |
| 2880 | + NISTC_AO_CMD1_BC_ARM | | |
| 2881 | + NISTC_AO_CMD1_DAC1_UPDATE_MODE | | |
| 2882 | + NISTC_AO_CMD1_DAC0_UPDATE_MODE | | |
| 2883 | + devpriv->ao_cmd1, | |
| 2884 | + NISTC_AO_CMD1_REG); | |
| 3046 | 2885 | |
| 3047 | − ni_stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse, | |
| 3048 | − AO_Command_2_Register); | |
| 2886 | + ni_stc_writew(dev, NISTC_AO_CMD2_START1_PULSE | devpriv->ao_cmd2, | |
| 2887 | + NISTC_AO_CMD2_REG); | |
| 3049 | 2888 | |
| 3050 | 2889 | return 0; |
| 3051 | 2890 | } |
| @@ -3058,18 +2897,20 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 6 unmodified lines | ||
| 3058 | 2897 | int bits; |
| 3059 | 2898 | int i; |
| 3060 | 2899 | unsigned trigvar; |
| 2900 | + unsigned val; | |
| 3061 | 2901 | |
| 3062 | 2902 | if (dev->irq == 0) { |
| 3063 | 2903 | dev_err(dev->class_dev, "cannot run command without an irq\n"); |
| 3064 | 2904 | return -EIO; |
| 3065 | 2905 | } |
| 3066 | 2906 | |
| 3067 | − ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); | |
| 2907 | + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); | |
| 3068 | 2908 | |
| 3069 | − ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register); | |
| 2909 | + ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); | |
| 3070 | 2910 | |
| 3071 | 2911 | if (devpriv->is_6xxx) { |
| 3072 | − ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x); | |
| 2912 | + ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, | |
| 2913 | + NI611X_AO_MISC_REG); | |
| 3073 | 2914 | |
| 3074 | 2915 | bits = 0; |
| 3075 | 2916 | for (i = 0; i < cmd->chanlist_len; i++) { |
| @@ -3077,172 +2918,186 @@ static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 1 unmodified line | ||
| 3077 | 2918 | |
| 3078 | 2919 | chan = CR_CHAN(cmd->chanlist[i]); |
| 3079 | 2920 | bits |= 1 << chan; |
| 3080 | − ni_ao_win_outw(dev, chan, AO_Waveform_Generation_611x); | |
| 2921 | + ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG); | |
| 3081 | 2922 | } |
| 3082 | − ni_ao_win_outw(dev, bits, AO_Timed_611x); | |
| 2923 | + ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG); | |
| 3083 | 2924 | } |
| 3084 | 2925 | |
| 3085 | 2926 | ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); |
| 3086 | 2927 | |
| 3087 | 2928 | if (cmd->stop_src == TRIG_NONE) { |
| 3088 | − devpriv->ao_mode1 |= AO_Continuous; | |
| 3089 | − devpriv->ao_mode1 &= ~AO_Trigger_Once; | |
| 2929 | + devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS; | |
| 2930 | + devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE; | |
| 3090 | 2931 | } else { |
| 3091 | − devpriv->ao_mode1 &= ~AO_Continuous; | |
| 3092 | − devpriv->ao_mode1 |= AO_Trigger_Once; | |
| 2932 | + devpriv->ao_mode1 &= ~NISTC_AO_MODE1_CONTINUOUS; | |
| 2933 | + devpriv->ao_mode1 |= NISTC_AO_MODE1_TRIGGER_ONCE; | |
| 3093 | 2934 | } |
| 3094 | − ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); | |
| 2935 | + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); | |
| 2936 | + | |
| 2937 | + val = devpriv->ao_trigger_select; | |
| 3095 | 2938 | switch (cmd->start_src) { |
| 3096 | 2939 | case TRIG_INT: |
| 3097 | 2940 | case TRIG_NOW: |
| 3098 | − devpriv->ao_trigger_select &= | |
| 3099 | − ~(AO_START1_Polarity | AO_START1_Select(-1)); | |
| 3100 | − devpriv->ao_trigger_select |= AO_START1_Edge | AO_START1_Sync; | |
| 3101 | − ni_stc_writew(dev, devpriv->ao_trigger_select, | |
| 3102 | − AO_Trigger_Select_Register); | |
| 2941 | + val &= ~(NISTC_AO_TRIG_START1_POLARITY | | |
| 2942 | + NISTC_AO_TRIG_START1_SEL_MASK); | |
| 2943 | + val |= NISTC_AO_TRIG_START1_EDGE | | |
| 2944 | + NISTC_AO_TRIG_START1_SYNC; | |
| 3103 | 2945 | break; |
| 3104 | 2946 | case TRIG_EXT: |
| 3105 | − devpriv->ao_trigger_select = | |
| 3106 | − AO_START1_Select(CR_CHAN(cmd->start_arg) + 1); | |
| 3107 | − if (cmd->start_arg & CR_INVERT) | |
| 3108 | − devpriv->ao_trigger_select |= AO_START1_Polarity; /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ | |
| 3109 | − if (cmd->start_arg & CR_EDGE) | |
| 3110 | − devpriv->ao_trigger_select |= AO_START1_Edge; /* 0=edge detection disabled, 1=enabled */ | |
| 2947 | + val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1); | |
| 2948 | + if (cmd->start_arg & CR_INVERT) { | |
| 2949 | + /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ | |
| 2950 | + val |= NISTC_AO_TRIG_START1_POLARITY; | |
| 2951 | + } | |
| 2952 | + if (cmd->start_arg & CR_EDGE) { | |
| 2953 | + /* 0=edge detection disabled, 1=enabled */ | |
| 2954 | + val |= NISTC_AO_TRIG_START1_EDGE; | |
| 2955 | + } | |
| 3111 | 2956 | ni_stc_writew(dev, devpriv->ao_trigger_select, |
| 3112 | − AO_Trigger_Select_Register); | |
| 2957 | + NISTC_AO_TRIG_SEL_REG); | |
| 3113 | 2958 | break; |
| 3114 | 2959 | default: |
| 3115 | 2960 | BUG(); |
| 3116 | 2961 | break; |
| 3117 | 2962 | } |
| 3118 | − devpriv->ao_mode3 &= ~AO_Trigger_Length; | |
| 3119 | − ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); | |
| 2963 | + devpriv->ao_trigger_select = val; | |
| 2964 | + ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG); | |
| 2965 | + | |
| 2966 | + devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN; | |
| 2967 | + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); | |
| 3120 | 2968 | |
| 3121 | − ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); | |
| 3122 | − devpriv->ao_mode2 &= ~AO_BC_Initial_Load_Source; | |
| 3123 | − ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | |
| 2969 | + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); | |
| 2970 | + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC; | |
| 2971 | + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); | |
| 3124 | 2972 | if (cmd->stop_src == TRIG_NONE) |
| 3125 | − ni_stc_writel(dev, 0xffffff, AO_BC_Load_A_Register); | |
| 2973 | + ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG); | |
| 3126 | 2974 | else |
| 3127 | − ni_stc_writel(dev, 0, AO_BC_Load_A_Register); | |
| 3128 | − ni_stc_writew(dev, AO_BC_Load, AO_Command_1_Register); | |
| 3129 | − devpriv->ao_mode2 &= ~AO_UC_Initial_Load_Source; | |
| 3130 | − ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | |
| 2975 | + ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); | |
| 2976 | + ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG); | |
| 2977 | + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; | |
| 2978 | + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); | |
| 3131 | 2979 | switch (cmd->stop_src) { |
| 3132 | 2980 | case TRIG_COUNT: |
| 3133 | 2981 | if (devpriv->is_m_series) { |
| 3134 | 2982 | /* this is how the NI example code does it for m-series boards, verified correct with 6259 */ |
| 3135 | 2983 | ni_stc_writel(dev, cmd->stop_arg - 1, |
| 3136 | − AO_UC_Load_A_Register); | |
| 3137 | − ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | |
| 2984 | + NISTC_AO_UC_LOADA_REG); | |
| 2985 | + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, | |
| 2986 | + NISTC_AO_CMD1_REG); | |
| 3138 | 2987 | } else { |
| 3139 | 2988 | ni_stc_writel(dev, cmd->stop_arg, |
| 3140 | − AO_UC_Load_A_Register); | |
| 3141 | − ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | |
| 2989 | + NISTC_AO_UC_LOADA_REG); | |
| 2990 | + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, | |
| 2991 | + NISTC_AO_CMD1_REG); | |
| 3142 | 2992 | ni_stc_writel(dev, cmd->stop_arg - 1, |
| 3143 | − AO_UC_Load_A_Register); | |
| 2993 | + NISTC_AO_UC_LOADA_REG); | |
| 3144 | 2994 | } |
| 3145 | 2995 | break; |
| 3146 | 2996 | case TRIG_NONE: |
| 3147 | − ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); | |
| 3148 | − ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | |
| 3149 | − ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); | |
| 2997 | + ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); | |
| 2998 | + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); | |
| 2999 | + ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); | |
| 3150 | 3000 | break; |
| 3151 | 3001 | default: |
| 3152 | − ni_stc_writel(dev, 0, AO_UC_Load_A_Register); | |
| 3153 | − ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | |
| 3154 | − ni_stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register); | |
| 3002 | + ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG); | |
| 3003 | + ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); | |
| 3004 | + ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG); | |
| 3155 | 3005 | } |
| 3156 | 3006 | |
| 3157 | − devpriv->ao_mode1 &= | |
| 3158 | − ~(AO_UI_Source_Select(0x1f) | AO_UI_Source_Polarity | | |
| 3159 | − AO_UPDATE_Source_Select(0x1f) | AO_UPDATE_Source_Polarity); | |
| 3007 | + devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK | | |
| 3008 | + NISTC_AO_MODE1_UI_SRC_MASK | | |
| 3009 | + NISTC_AO_MODE1_UPDATE_SRC_POLARITY | | |
| 3010 | + NISTC_AO_MODE1_UI_SRC_POLARITY); | |
| 3160 | 3011 | switch (cmd->scan_begin_src) { |
| 3161 | 3012 | case TRIG_TIMER: |
| 3162 | − devpriv->ao_cmd2 &= ~AO_BC_Gate_Enable; | |
| 3013 | + devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; | |
| 3163 | 3014 | trigvar = |
| 3164 | 3015 | ni_ns_to_timer(dev, cmd->scan_begin_arg, |
| 3165 | 3016 | CMDF_ROUND_NEAREST); |
| 3166 | − ni_stc_writel(dev, 1, AO_UI_Load_A_Register); | |
| 3167 | − ni_stc_writew(dev, AO_UI_Load, AO_Command_1_Register); | |
| 3168 | − ni_stc_writel(dev, trigvar, AO_UI_Load_A_Register); | |
| 3017 | + ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); | |
| 3018 | + ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG); | |
| 3019 | + ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG); | |
| 3169 | 3020 | break; |
| 3170 | 3021 | case TRIG_EXT: |
| 3171 | 3022 | devpriv->ao_mode1 |= |
| 3172 | − AO_UPDATE_Source_Select(cmd->scan_begin_arg); | |
| 3023 | + NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg); | |
| 3173 | 3024 | if (cmd->scan_begin_arg & CR_INVERT) |
| 3174 | − devpriv->ao_mode1 |= AO_UPDATE_Source_Polarity; | |
| 3175 | − devpriv->ao_cmd2 |= AO_BC_Gate_Enable; | |
| 3025 | + devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY; | |
| 3026 | + devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; | |
| 3176 | 3027 | break; |
| 3177 | 3028 | default: |
| 3178 | 3029 | BUG(); |
| 3179 | 3030 | break; |
| 3180 | 3031 | } |
| 3181 | − ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); | |
| 3182 | − ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); | |
| 3183 | − devpriv->ao_mode2 &= | |
| 3184 | − ~(AO_UI_Reload_Mode(3) | AO_UI_Initial_Load_Source); | |
| 3185 | − ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | |
| 3032 | + ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); | |
| 3033 | + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); | |
| 3034 | + devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) | | |
| 3035 | + NISTC_AO_MODE2_UI_INIT_LOAD_SRC); | |
| 3036 | + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); | |
| 3186 | 3037 | |
| 3187 | 3038 | if (cmd->scan_end_arg > 1) { |
| 3188 | − devpriv->ao_mode1 |= AO_Multiple_Channels; | |
| 3039 | + devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN; | |
| 3189 | 3040 | ni_stc_writew(dev, |
| 3190 | − AO_Number_Of_Channels(cmd->scan_end_arg - 1) | | |
| 3191 | − AO_UPDATE_Output_Select(AO_Update_Output_High_Z), | |
| 3192 | − AO_Output_Control_Register); | |
| 3041 | + NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) | | |
| 3042 | + NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ, | |
| 3043 | + NISTC_AO_OUT_CTRL_REG); | |
| 3193 | 3044 | } else { |
| 3194 | 3045 | unsigned bits; |
| 3195 | 3046 | |
| 3196 | − devpriv->ao_mode1 &= ~AO_Multiple_Channels; | |
| 3197 | − bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z); | |
| 3047 | + devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN; | |
| 3048 | + bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; | |
| 3198 | 3049 | if (devpriv->is_m_series || devpriv->is_6xxx) { |
| 3199 | − bits |= AO_Number_Of_Channels(0); | |
| 3050 | + bits |= NISTC_AO_OUT_CTRL_CHANS(0); | |
| 3200 | 3051 | } else { |
| 3201 | 3052 | bits |= |
| 3202 | − AO_Number_Of_Channels(CR_CHAN(cmd->chanlist[0])); | |
| 3053 | + NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0])); | |
| 3203 | 3054 | } |
| 3204 | − ni_stc_writew(dev, bits, AO_Output_Control_Register); | |
| 3055 | + ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG); | |
| 3205 | 3056 | } |
| 3206 | − ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); | |
| 3057 | + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); | |
| 3207 | 3058 | |
| 3208 | − ni_stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode, | |
| 3209 | − AO_Command_1_Register); | |
| 3059 | + ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE | | |
| 3060 | + NISTC_AO_CMD1_DAC0_UPDATE_MODE, | |
| 3061 | + NISTC_AO_CMD1_REG); | |
| 3210 | 3062 | |
| 3211 | − devpriv->ao_mode3 |= AO_Stop_On_Overrun_Error; | |
| 3212 | − ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); | |
| 3063 | + devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; | |
| 3064 | + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); | |
| 3213 | 3065 | |
| 3214 | − devpriv->ao_mode2 &= ~AO_FIFO_Mode_Mask; | |
| 3066 | + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK; | |
| 3215 | 3067 | #ifdef PCIDMA |
| 3216 | − devpriv->ao_mode2 |= AO_FIFO_Mode_HF_to_F; | |
| 3068 | + devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F; | |
| 3217 | 3069 | #else |
| 3218 | − devpriv->ao_mode2 |= AO_FIFO_Mode_HF; | |
| 3070 | + devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF; | |
| 3219 | 3071 | #endif |
| 3220 | − devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable; | |
| 3221 | − ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | |
| 3072 | + devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA; | |
| 3073 | + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); | |
| 3222 | 3074 | |
| 3223 | − bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width | | |
| 3224 | − AO_TMRDACWR_Pulse_Width; | |
| 3075 | + bits = NISTC_AO_PERSONAL_BC_SRC_SEL | | |
| 3076 | + NISTC_AO_PERSONAL_UPDATE_PW | | |
| 3077 | + NISTC_AO_PERSONAL_TMRDACWR_PW; | |
| 3225 | 3078 | if (board->ao_fifo_depth) |
| 3226 | − bits |= AO_FIFO_Enable; | |
| 3079 | + bits |= NISTC_AO_PERSONAL_FIFO_ENA; | |
| 3227 | 3080 | else |
| 3228 | − bits |= AO_DMA_PIO_Control; | |
| 3081 | + bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL; | |
| 3229 | 3082 | #if 0 |
| 3230 | − /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281, | |
| 3231 | − verified with bus analyzer. */ | |
| 3083 | + /* | |
| 3084 | + * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit | |
| 3085 | + * for 6281, verified with bus analyzer. | |
| 3086 | + */ | |
| 3232 | 3087 | if (devpriv->is_m_series) |
| 3233 | − bits |= AO_Number_Of_DAC_Packages; | |
| 3088 | + bits |= NISTC_AO_PERSONAL_NUM_DAC; | |
| 3234 | 3089 | #endif |
| 3235 | − ni_stc_writew(dev, bits, AO_Personal_Register); | |
| 3090 | + ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG); | |
| 3236 | 3091 | /* enable sending of ao dma requests */ |
| 3237 | − ni_stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register); | |
| 3092 | + ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG); | |
| 3238 | 3093 | |
| 3239 | − ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); | |
| 3094 | + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); | |
| 3240 | 3095 | |
| 3241 | 3096 | if (cmd->stop_src == TRIG_COUNT) { |
| 3242 | − ni_stc_writew(dev, AO_BC_TC_Interrupt_Ack, | |
| 3243 | − Interrupt_B_Ack_Register); | |
| 3244 | − ni_set_bits(dev, Interrupt_B_Enable_Register, | |
| 3245 | − AO_BC_TC_Interrupt_Enable, 1); | |
| 3097 | + ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC, | |
| 3098 | + NISTC_INTB_ACK_REG); | |
| 3099 | + ni_set_bits(dev, NISTC_INTB_ENA_REG, | |
| 3100 | + NISTC_INTB_ENA_AO_BC_TC, 1); | |
| 3246 | 3101 | } |
| 3247 | 3102 | |
| 3248 | 3103 | s->async->inttrig = ni_ao_inttrig; |
| @@ -3339,41 +3194,44 @@ static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) · 90 unmodified lines | ||
| 3339 | 3194 | |
| 3340 | 3195 | ni_release_ao_mite_channel(dev); |
| 3341 | 3196 | |
| 3342 | − ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); | |
| 3343 | − ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register); | |
| 3344 | − ni_set_bits(dev, Interrupt_B_Enable_Register, ~0, 0); | |
| 3345 | − ni_stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register); | |
| 3346 | − ni_stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register); | |
| 3347 | − ni_stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width | | |
| 3348 | − AO_TMRDACWR_Pulse_Width, AO_Personal_Register); | |
| 3349 | − ni_stc_writew(dev, 0, AO_Output_Control_Register); | |
| 3350 | − ni_stc_writew(dev, 0, AO_Start_Select_Register); | |
| 3197 | + ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); | |
| 3198 | + ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); | |
| 3199 | + ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0); | |
| 3200 | + ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); | |
| 3201 | + ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); | |
| 3202 | + ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL | | |
| 3203 | + NISTC_AO_PERSONAL_UPDATE_PW | | |
| 3204 | + NISTC_AO_PERSONAL_TMRDACWR_PW, | |
| 3205 | + NISTC_AO_PERSONAL_REG); | |
| 3206 | + ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG); | |
| 3207 | + ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG); | |
| 3351 | 3208 | devpriv->ao_cmd1 = 0; |
| 3352 | − ni_stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register); | |
| 3209 | + ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG); | |
| 3353 | 3210 | devpriv->ao_cmd2 = 0; |
| 3354 | − ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); | |
| 3211 | + ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); | |
| 3355 | 3212 | devpriv->ao_mode1 = 0; |
| 3356 | − ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); | |
| 3213 | + ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); | |
| 3357 | 3214 | devpriv->ao_mode2 = 0; |
| 3358 | − ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | |
| 3215 | + ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); | |
| 3359 | 3216 | if (devpriv->is_m_series) |
| 3360 | − devpriv->ao_mode3 = AO_Last_Gate_Disable; | |
| 3217 | + devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE; | |
| 3361 | 3218 | else |
| 3362 | 3219 | devpriv->ao_mode3 = 0; |
| 3363 | − ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); | |
| 3220 | + ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); | |
| 3364 | 3221 | devpriv->ao_trigger_select = 0; |
| 3365 | 3222 | ni_stc_writew(dev, devpriv->ao_trigger_select, |
| 3366 | − AO_Trigger_Select_Register); | |
| 3223 | + NISTC_AO_TRIG_SEL_REG); | |
| 3367 | 3224 | if (devpriv->is_6xxx) { |
| 3368 | 3225 | unsigned immediate_bits = 0; |
| 3369 | 3226 | unsigned i; |
| 3370 | 3227 | |
| 3371 | 3228 | for (i = 0; i < s->n_chan; ++i) |
| 3372 | 3229 | immediate_bits |= 1 << i; |
| 3373 | − ni_ao_win_outw(dev, immediate_bits, AO_Immediate_671x); | |
| 3374 | − ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x); | |
| 3230 | + ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG); | |
| 3231 | + ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, | |
| 3232 | + NI611X_AO_MISC_REG); | |
| 3375 | 3233 | } |
| 3376 | − ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register); | |
| 3234 | + ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); | |
| 3377 | 3235 | |
| 3378 | 3236 | return 0; |
| 3379 | 3237 | } |
| @@ -3392,9 +3250,9 @@ static int ni_dio_insn_config(struct comedi_device *dev, · 12 unmodified lines | ||
| 3392 | 3250 | if (ret) |
| 3393 | 3251 | return ret; |
| 3394 | 3252 | |
| 3395 | − devpriv->dio_control &= ~DIO_Pins_Dir_Mask; | |
| 3396 | − devpriv->dio_control |= DIO_Pins_Dir(s->io_bits); | |
| 3397 | − ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | |
| 3253 | + devpriv->dio_control &= ~NISTC_DIO_CTRL_DIR_MASK; | |
| 3254 | + devpriv->dio_control |= NISTC_DIO_CTRL_DIR(s->io_bits); | |
| 3255 | + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); | |
| 3398 | 3256 | |
| 3399 | 3257 | return insn->n; |
| 3400 | 3258 | } |
| @@ -3407,16 +3265,17 @@ static int ni_dio_insn_bits(struct comedi_device *dev, · 6 unmodified lines | ||
| 3407 | 3265 | struct ni_private *devpriv = dev->private; |
| 3408 | 3266 | |
| 3409 | 3267 | /* Make sure we're not using the serial part of the dio */ |
| 3410 | − if ((data[0] & (DIO_SDIN | DIO_SDOUT)) && devpriv->serial_interval_ns) | |
| 3268 | + if ((data[0] & (NISTC_DIO_SDIN | NISTC_DIO_SDOUT)) && | |
| 3269 | + devpriv->serial_interval_ns) | |
| 3411 | 3270 | return -EBUSY; |
| 3412 | 3271 | |
| 3413 | 3272 | if (comedi_dio_update_state(s, data)) { |
| 3414 | − devpriv->dio_output &= ~DIO_Parallel_Data_Mask; | |
| 3415 | − devpriv->dio_output |= DIO_Parallel_Data_Out(s->state); | |
| 3416 | − ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); | |
| 3273 | + devpriv->dio_output &= ~NISTC_DIO_OUT_PARALLEL_MASK; | |
| 3274 | + devpriv->dio_output |= NISTC_DIO_OUT_PARALLEL(s->state); | |
| 3275 | + ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); | |
| 3417 | 3276 | } |
| 3418 | 3277 | |
| 3419 | − data[1] = ni_stc_readw(dev, DIO_Parallel_Input_Register); | |
| 3278 | + data[1] = ni_stc_readw(dev, NISTC_DIO_IN_REG); | |
| 3420 | 3279 | |
| 3421 | 3280 | return insn->n; |
| 3422 | 3281 | } |
| @@ -3432,7 +3291,7 @@ static int ni_m_series_dio_insn_config(struct comedi_device *dev, · 9 unmodified lines | ||
| 3432 | 3291 | if (ret) |
| 3433 | 3292 | return ret; |
| 3434 | 3293 | |
| 3435 | − ni_writel(dev, s->io_bits, M_Offset_DIO_Direction); | |
| 3294 | + ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG); | |
| 3436 | 3295 | |
| 3437 | 3296 | return insn->n; |
| 3438 | 3297 | } |
| @@ -3443,9 +3302,9 @@ static int ni_m_series_dio_insn_bits(struct comedi_device *dev, · 4 unmodified lines | ||
| 3443 | 3302 | unsigned int *data) |
| 3444 | 3303 | { |
| 3445 | 3304 | if (comedi_dio_update_state(s, data)) |
| 3446 | − ni_writel(dev, s->state, M_Offset_Static_Digital_Output); | |
| 3305 | + ni_writel(dev, s->state, NI_M_DIO_REG); | |
| 3447 | 3306 | |
| 3448 | − data[1] = ni_readl(dev, M_Offset_Static_Digital_Input); | |
| 3307 | + data[1] = ni_readl(dev, NI_M_DIO_REG); | |
| 3449 | 3308 | |
| 3450 | 3309 | return insn->n; |
| 3451 | 3310 | } |
| @@ -3491,7 +3350,7 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, · 39 unmodified lines | ||
| 3491 | 3350 | err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); |
| 3492 | 3351 | |
| 3493 | 3352 | tmp = cmd->scan_begin_arg; |
| 3494 | − tmp &= CR_PACK_FLAGS(CDO_Sample_Source_Select_Mask, 0, 0, CR_INVERT); | |
| 3353 | + tmp &= CR_PACK_FLAGS(NI_M_CDO_MODE_SAMPLE_SRC_MASK, 0, 0, CR_INVERT); | |
| 3495 | 3354 | if (tmp != cmd->scan_begin_arg) |
| 3496 | 3355 | err |= -EINVAL; |
| 3497 | 3356 | |
| @@ -3550,13 +3409,14 @@ static int ni_cdo_inttrig(struct comedi_device *dev, · 52 unmodified lines | ||
| 3550 | 3409 | if (retval < 0) |
| 3551 | 3410 | return retval; |
| 3552 | 3411 | #endif |
| 3553 | −/* | |
| 3554 | −* XXX not sure what interrupt C group does | |
| 3555 | −* ni_writeb(dev, Interrupt_Group_C_Enable_Bit, | |
| 3556 | −* M_Offset_Interrupt_C_Enable); wait for dma to fill output fifo | |
| 3557 | −*/ | |
| 3412 | + /* | |
| 3413 | + * XXX not sure what interrupt C group does | |
| 3414 | + * wait for dma to fill output fifo | |
| 3415 | + * ni_writeb(dev, NI_M_INTC_ENA, NI_M_INTC_ENA_REG); | |
| 3416 | + */ | |
| 3558 | 3417 | for (i = 0; i < timeout; ++i) { |
| 3559 | − if (ni_readl(dev, M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit) | |
| 3418 | + if (ni_readl(dev, NI_M_CDIO_STATUS_REG) & | |
| 3419 | + NI_M_CDIO_STATUS_CDO_FIFO_FULL) | |
| 3560 | 3420 | break; |
| 3561 | 3421 | udelay(10); |
| 3562 | 3422 | } |
| @@ -3565,36 +3425,30 @@ static int ni_cdo_inttrig(struct comedi_device *dev, · 2 unmodified lines | ||
| 3565 | 3425 | s->cancel(dev, s); |
| 3566 | 3426 | return -EIO; |
| 3567 | 3427 | } |
| 3568 | − ni_writel(dev, CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit | | |
| 3569 | − CDO_Empty_FIFO_Interrupt_Enable_Set_Bit, | |
| 3570 | − M_Offset_CDIO_Command); | |
| 3428 | + ni_writel(dev, NI_M_CDO_CMD_ARM | | |
| 3429 | + NI_M_CDO_CMD_ERR_INT_ENA_SET | | |
| 3430 | + NI_M_CDO_CMD_F_E_INT_ENA_SET, | |
| 3431 | + NI_M_CDIO_CMD_REG); | |
| 3571 | 3432 | return retval; |
| 3572 | 3433 | } |
| 3573 | 3434 | |
| 3574 | 3435 | static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
| 3575 | 3436 | { |
| 3576 | 3437 | const struct comedi_cmd *cmd = &s->async->cmd; |
| 3577 | − unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit; | |
| 3438 | + unsigned cdo_mode_bits; | |
| 3578 | 3439 | int retval; |
| 3579 | 3440 | |
| 3580 | − ni_writel(dev, CDO_Reset_Bit, M_Offset_CDIO_Command); | |
| 3581 | − switch (cmd->scan_begin_src) { | |
| 3582 | − case TRIG_EXT: | |
| 3583 | − cdo_mode_bits |= | |
| 3584 | − CR_CHAN(cmd->scan_begin_arg) & | |
| 3585 | − CDO_Sample_Source_Select_Mask; | |
| 3586 | − break; | |
| 3587 | − default: | |
| 3588 | − BUG(); | |
| 3589 | − break; | |
| 3590 | − } | |
| 3441 | + ni_writel(dev, NI_M_CDO_CMD_RESET, NI_M_CDIO_CMD_REG); | |
| 3442 | + cdo_mode_bits = NI_M_CDO_MODE_FIFO_MODE | | |
| 3443 | + NI_M_CDO_MODE_HALT_ON_ERROR | | |
| 3444 | + NI_M_CDO_MODE_SAMPLE_SRC(CR_CHAN(cmd->scan_begin_arg)); | |
| 3591 | 3445 | if (cmd->scan_begin_arg & CR_INVERT) |
| 3592 | − cdo_mode_bits |= CDO_Polarity_Bit; | |
| 3593 | − ni_writel(dev, cdo_mode_bits, M_Offset_CDO_Mode); | |
| 3446 | + cdo_mode_bits |= NI_M_CDO_MODE_POLARITY; | |
| 3447 | + ni_writel(dev, cdo_mode_bits, NI_M_CDO_MODE_REG); | |
| 3594 | 3448 | if (s->io_bits) { |
| 3595 | − ni_writel(dev, s->state, M_Offset_CDO_FIFO_Data); | |
| 3596 | − ni_writel(dev, CDO_SW_Update_Bit, M_Offset_CDIO_Command); | |
| 3597 | − ni_writel(dev, s->io_bits, M_Offset_CDO_Mask_Enable); | |
| 3449 | + ni_writel(dev, s->state, NI_M_CDO_FIFO_DATA_REG); | |
| 3450 | + ni_writel(dev, NI_M_CDO_CMD_SW_UPDATE, NI_M_CDIO_CMD_REG); | |
| 3451 | + ni_writel(dev, s->io_bits, NI_M_CDO_MASK_ENA_REG); | |
| 3598 | 3452 | } else { |
| 3599 | 3453 | dev_err(dev->class_dev, |
| 3600 | 3454 | "attempted to run digital output command with no lines configured as outputs\n"); |
| @@ -3611,15 +3465,16 @@ static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 10 unmodified lines | ||
| 3611 | 3465 | |
| 3612 | 3466 | static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) |
| 3613 | 3467 | { |
| 3614 | − ni_writel(dev, CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit | | |
| 3615 | − CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit | | |
| 3616 | − CDO_FIFO_Request_Interrupt_Enable_Clear_Bit, | |
| 3617 | − M_Offset_CDIO_Command); | |
| 3618 | −/* | |
| 3619 | −* XXX not sure what interrupt C group does ni_writeb(dev, 0, | |
| 3620 | −* M_Offset_Interrupt_C_Enable); | |
| 3621 | −*/ | |
| 3622 | − ni_writel(dev, 0, M_Offset_CDO_Mask_Enable); | |
| 3468 | + ni_writel(dev, NI_M_CDO_CMD_DISARM | | |
| 3469 | + NI_M_CDO_CMD_ERR_INT_ENA_CLR | | |
| 3470 | + NI_M_CDO_CMD_F_E_INT_ENA_CLR | | |
| 3471 | + NI_M_CDO_CMD_F_REQ_INT_ENA_CLR, | |
| 3472 | + NI_M_CDIO_CMD_REG); | |
| 3473 | + /* | |
| 3474 | + * XXX not sure what interrupt C group does | |
| 3475 | + * ni_writeb(dev, 0, NI_M_INTC_ENA_REG); | |
| 3476 | + */ | |
| 3477 | + ni_writel(dev, 0, NI_M_CDO_MASK_ENA_REG); | |
| 3623 | 3478 | ni_release_cdo_mite_channel(dev); |
| 3624 | 3479 | return 0; |
| 3625 | 3480 | } |
| @@ -3650,16 +3505,16 @@ static void handle_cdio_interrupt(struct comedi_device *dev) · 24 unmodified lines | ||
| 3650 | 3505 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
| 3651 | 3506 | #endif |
| 3652 | 3507 | |
| 3653 | − cdio_status = ni_readl(dev, M_Offset_CDIO_Status); | |
| 3654 | − if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) { | |
| 3508 | + cdio_status = ni_readl(dev, NI_M_CDIO_STATUS_REG); | |
| 3509 | + if (cdio_status & NI_M_CDIO_STATUS_CDO_ERROR) { | |
| 3655 | 3510 | /* XXX just guessing this is needed and does something useful */ |
| 3656 | − ni_writel(dev, CDO_Error_Interrupt_Confirm_Bit, | |
| 3657 | − M_Offset_CDIO_Command); | |
| 3511 | + ni_writel(dev, NI_M_CDO_CMD_ERR_INT_CONFIRM, | |
| 3512 | + NI_M_CDIO_CMD_REG); | |
| 3658 | 3513 | s->async->events |= COMEDI_CB_OVERFLOW; |
| 3659 | 3514 | } |
| 3660 | − if (cdio_status & CDO_FIFO_Empty_Bit) { | |
| 3661 | − ni_writel(dev, CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit, | |
| 3662 | − M_Offset_CDIO_Command); | |
| 3515 | + if (cdio_status & NI_M_CDIO_STATUS_CDO_FIFO_EMPTY) { | |
| 3516 | + ni_writel(dev, NI_M_CDO_CMD_F_E_INT_ENA_CLR, | |
| 3517 | + NI_M_CDIO_CMD_REG); | |
| 3663 | 3518 | /* s->async->events |= COMEDI_CB_EOA; */ |
| 3664 | 3519 | } |
| 3665 | 3520 | comedi_handle_events(dev, s); |
| @@ -3674,23 +3529,23 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, · 8 unmodified lines | ||
| 3674 | 3529 | unsigned int status1; |
| 3675 | 3530 | int err = 0, count = 20; |
| 3676 | 3531 | |
| 3677 | − devpriv->dio_output &= ~DIO_Serial_Data_Mask; | |
| 3678 | − devpriv->dio_output |= DIO_Serial_Data_Out(data_out); | |
| 3679 | − ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); | |
| 3532 | + devpriv->dio_output &= ~NISTC_DIO_OUT_SERIAL_MASK; | |
| 3533 | + devpriv->dio_output |= NISTC_DIO_OUT_SERIAL(data_out); | |
| 3534 | + ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); | |
| 3680 | 3535 | |
| 3681 | − status1 = ni_stc_readw(dev, Joint_Status_1_Register); | |
| 3682 | − if (status1 & DIO_Serial_IO_In_Progress_St) { | |
| 3536 | + status1 = ni_stc_readw(dev, NISTC_STATUS1_REG); | |
| 3537 | + if (status1 & NISTC_STATUS1_SERIO_IN_PROG) { | |
| 3683 | 3538 | err = -EBUSY; |
| 3684 | 3539 | goto Error; |
| 3685 | 3540 | } |
| 3686 | 3541 | |
| 3687 | − devpriv->dio_control |= DIO_HW_Serial_Start; | |
| 3688 | − ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | |
| 3689 | − devpriv->dio_control &= ~DIO_HW_Serial_Start; | |
| 3542 | + devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_START; | |
| 3543 | + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); | |
| 3544 | + devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_START; | |
| 3690 | 3545 | |
| 3691 | 3546 | /* Wait until STC says we're done, but don't loop infinitely. */ |
| 3692 | − while ((status1 = ni_stc_readw(dev, Joint_Status_1_Register)) & | |
| 3693 | − DIO_Serial_IO_In_Progress_St) { | |
| 3547 | + while ((status1 = ni_stc_readw(dev, NISTC_STATUS1_REG)) & | |
| 3548 | + NISTC_STATUS1_SERIO_IN_PROG) { | |
| 3694 | 3549 | /* Delay one bit per loop */ |
| 3695 | 3550 | udelay((devpriv->serial_interval_ns + 999) / 1000); |
| 3696 | 3551 | if (--count < 0) { |
| @@ -3701,15 +3556,17 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, · 4 unmodified lines | ||
| 3701 | 3556 | } |
| 3702 | 3557 | } |
| 3703 | 3558 | |
| 3704 | − /* Delay for last bit. This delay is absolutely necessary, because | |
| 3705 | − DIO_Serial_IO_In_Progress_St goes high one bit too early. */ | |
| 3559 | + /* | |
| 3560 | + * Delay for last bit. This delay is absolutely necessary, because | |
| 3561 | + * NISTC_STATUS1_SERIO_IN_PROG goes high one bit too early. | |
| 3562 | + */ | |
| 3706 | 3563 | udelay((devpriv->serial_interval_ns + 999) / 1000); |
| 3707 | 3564 | |
| 3708 | 3565 | if (data_in) |
| 3709 | − *data_in = ni_stc_readw(dev, DIO_Serial_Input_Register); | |
| 3566 | + *data_in = ni_stc_readw(dev, NISTC_DIO_SERIAL_IN_REG); | |
| 3710 | 3567 | |
| 3711 | 3568 | Error: |
| 3712 | − ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | |
| 3569 | + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); | |
| 3713 | 3570 | |
| 3714 | 3571 | return err; |
| 3715 | 3572 | } |
| @@ -3729,25 +3586,25 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, · 13 unmodified lines | ||
| 3729 | 3586 | /* Output current bit; note that we cannot touch s->state |
| 3730 | 3587 | because it is a per-subdevice field, and serial is |
| 3731 | 3588 | a separate subdevice from DIO. */ |
| 3732 | − devpriv->dio_output &= ~DIO_SDOUT; | |
| 3589 | + devpriv->dio_output &= ~NISTC_DIO_SDOUT; | |
| 3733 | 3590 | if (data_out & mask) |
| 3734 | − devpriv->dio_output |= DIO_SDOUT; | |
| 3735 | − ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); | |
| 3591 | + devpriv->dio_output |= NISTC_DIO_SDOUT; | |
| 3592 | + ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); | |
| 3736 | 3593 | |
| 3737 | 3594 | /* Assert SDCLK (active low, inverted), wait for half of |
| 3738 | 3595 | the delay, deassert SDCLK, and wait for the other half. */ |
| 3739 | − devpriv->dio_control |= DIO_Software_Serial_Control; | |
| 3740 | − ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | |
| 3596 | + devpriv->dio_control |= NISTC_DIO_SDCLK; | |
| 3597 | + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); | |
| 3741 | 3598 | |
| 3742 | 3599 | udelay((devpriv->serial_interval_ns + 999) / 2000); |
| 3743 | 3600 | |
| 3744 | − devpriv->dio_control &= ~DIO_Software_Serial_Control; | |
| 3745 | − ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | |
| 3601 | + devpriv->dio_control &= ~NISTC_DIO_SDCLK; | |
| 3602 | + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); | |
| 3746 | 3603 | |
| 3747 | 3604 | udelay((devpriv->serial_interval_ns + 999) / 2000); |
| 3748 | 3605 | |
| 3749 | 3606 | /* Input current bit */ |
| 3750 | − if (ni_stc_readw(dev, DIO_Parallel_Input_Register) & DIO_SDIN) | |
| 3607 | + if (ni_stc_readw(dev, NISTC_DIO_IN_REG) & NISTC_DIO_SDIN) | |
| 3751 | 3608 | input |= mask; |
| 3752 | 3609 | } |
| 3753 | 3610 | |
| @@ -3763,6 +3620,7 @@ static int ni_serial_insn_config(struct comedi_device *dev, · 9 unmodified lines | ||
| 3763 | 3620 | unsigned int *data) |
| 3764 | 3621 | { |
| 3765 | 3622 | struct ni_private *devpriv = dev->private; |
| 3623 | + unsigned clk_fout = devpriv->clock_and_fout; | |
| 3766 | 3624 | int err = insn->n; |
| 3767 | 3625 | unsigned char byte_out, byte_in = 0; |
| 3768 | 3626 | |
| @@ -3772,49 +3630,49 @@ static int ni_serial_insn_config(struct comedi_device *dev, · 3 unmodified lines | ||
| 3772 | 3630 | switch (data[0]) { |
| 3773 | 3631 | case INSN_CONFIG_SERIAL_CLOCK: |
| 3774 | 3632 | devpriv->serial_hw_mode = 1; |
| 3775 | − devpriv->dio_control |= DIO_HW_Serial_Enable; | |
| 3633 | + devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_ENA; | |
| 3776 | 3634 | |
| 3777 | 3635 | if (data[1] == SERIAL_DISABLED) { |
| 3778 | 3636 | devpriv->serial_hw_mode = 0; |
| 3779 | − devpriv->dio_control &= ~(DIO_HW_Serial_Enable | | |
| 3780 | − DIO_Software_Serial_Control); | |
| 3637 | + devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | | |
| 3638 | + NISTC_DIO_SDCLK); | |
| 3781 | 3639 | data[1] = SERIAL_DISABLED; |
| 3782 | 3640 | devpriv->serial_interval_ns = data[1]; |
| 3783 | 3641 | } else if (data[1] <= SERIAL_600NS) { |
| 3784 | 3642 | /* Warning: this clock speed is too fast to reliably |
| 3785 | 3643 | control SCXI. */ |
| 3786 | − devpriv->dio_control &= ~DIO_HW_Serial_Timebase; | |
| 3787 | − devpriv->clock_and_fout |= Slow_Internal_Timebase; | |
| 3788 | − devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2; | |
| 3644 | + devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; | |
| 3645 | + clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE; | |
| 3646 | + clk_fout &= ~NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; | |
| 3789 | 3647 | data[1] = SERIAL_600NS; |
| 3790 | 3648 | devpriv->serial_interval_ns = data[1]; |
| 3791 | 3649 | } else if (data[1] <= SERIAL_1_2US) { |
| 3792 | − devpriv->dio_control &= ~DIO_HW_Serial_Timebase; | |
| 3793 | − devpriv->clock_and_fout |= Slow_Internal_Timebase | | |
| 3794 | − DIO_Serial_Out_Divide_By_2; | |
| 3650 | + devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; | |
| 3651 | + clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | | |
| 3652 | + NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; | |
| 3795 | 3653 | data[1] = SERIAL_1_2US; |
| 3796 | 3654 | devpriv->serial_interval_ns = data[1]; |
| 3797 | 3655 | } else if (data[1] <= SERIAL_10US) { |
| 3798 | − devpriv->dio_control |= DIO_HW_Serial_Timebase; | |
| 3799 | − devpriv->clock_and_fout |= Slow_Internal_Timebase | | |
| 3800 | − DIO_Serial_Out_Divide_By_2; | |
| 3801 | − /* Note: DIO_Serial_Out_Divide_By_2 only affects | |
| 3656 | + devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_TIMEBASE; | |
| 3657 | + clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | | |
| 3658 | + NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; | |
| 3659 | + /* Note: NISTC_CLK_FOUT_DIO_SER_OUT_DIV2 only affects | |
| 3802 | 3660 | 600ns/1.2us. If you turn divide_by_2 off with the |
| 3803 | 3661 | slow clock, you will still get 10us, except then |
| 3804 | 3662 | all your delays are wrong. */ |
| 3805 | 3663 | data[1] = SERIAL_10US; |
| 3806 | 3664 | devpriv->serial_interval_ns = data[1]; |
| 3807 | 3665 | } else { |
| 3808 | − devpriv->dio_control &= ~(DIO_HW_Serial_Enable | | |
| 3809 | − DIO_Software_Serial_Control); | |
| 3666 | + devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | | |
| 3667 | + NISTC_DIO_SDCLK); | |
| 3810 | 3668 | devpriv->serial_hw_mode = 0; |
| 3811 | 3669 | data[1] = (data[1] / 1000) * 1000; |
| 3812 | 3670 | devpriv->serial_interval_ns = data[1]; |
| 3813 | 3671 | } |
| 3672 | + devpriv->clock_and_fout = clk_fout; | |
| 3814 | 3673 | |
| 3815 | − ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | |
| 3816 | − ni_stc_writew(dev, devpriv->clock_and_fout, | |
| 3817 | − Clock_and_FOUT_Register); | |
| 3674 | + ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); | |
| 3675 | + ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); | |
| 3818 | 3676 | return 1; |
| 3819 | 3677 | |
| 3820 | 3678 | case INSN_CONFIG_BIDIRECTIONAL_DATA: |
| @@ -3850,141 +3708,91 @@ static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) · 29 unmodified lines | ||
| 3850 | 3708 | int i; |
| 3851 | 3709 | |
| 3852 | 3710 | for (i = 0; i < s->n_chan; i++) { |
| 3853 | − ni_ao_win_outw(dev, AO_Channel(i) | 0x0, | |
| 3854 | − AO_Configuration_2_67xx); | |
| 3855 | − } | |
| 3856 | − ni_ao_win_outw(dev, 0x0, AO_Later_Single_Point_Updates); | |
| 3857 | −} | |
| 3711 | + ni_ao_win_outw(dev, NI_E_AO_DACSEL(i) | 0x0, | |
| 3712 | + NI67XX_AO_CFG2_REG); | |
| 3713 | + } | |
| 3714 | + ni_ao_win_outw(dev, 0x0, NI67XX_AO_SP_UPDATES_REG); | |
| 3715 | +} | |
| 3716 | + | |
| 3717 | +static const struct mio_regmap ni_gpct_to_stc_regmap[] = { | |
| 3718 | + [NITIO_G0_AUTO_INC] = { NISTC_G0_AUTOINC_REG, 2 }, | |
| 3719 | + [NITIO_G1_AUTO_INC] = { NISTC_G1_AUTOINC_REG, 2 }, | |
| 3720 | + [NITIO_G0_CMD] = { NISTC_G0_CMD_REG, 2 }, | |
| 3721 | + [NITIO_G1_CMD] = { NISTC_G1_CMD_REG, 2 }, | |
| 3722 | + [NITIO_G0_HW_SAVE] = { NISTC_G0_HW_SAVE_REG, 4 }, | |
| 3723 | + [NITIO_G1_HW_SAVE] = { NISTC_G1_HW_SAVE_REG, 4 }, | |
| 3724 | + [NITIO_G0_SW_SAVE] = { NISTC_G0_SAVE_REG, 4 }, | |
| 3725 | + [NITIO_G1_SW_SAVE] = { NISTC_G1_SAVE_REG, 4 }, | |
| 3726 | + [NITIO_G0_MODE] = { NISTC_G0_MODE_REG, 2 }, | |
| 3727 | + [NITIO_G1_MODE] = { NISTC_G1_MODE_REG, 2 }, | |
| 3728 | + [NITIO_G0_LOADA] = { NISTC_G0_LOADA_REG, 4 }, | |
| 3729 | + [NITIO_G1_LOADA] = { NISTC_G1_LOADA_REG, 4 }, | |
| 3730 | + [NITIO_G0_LOADB] = { NISTC_G0_LOADB_REG, 4 }, | |
| 3731 | + [NITIO_G1_LOADB] = { NISTC_G1_LOADB_REG, 4 }, | |
| 3732 | + [NITIO_G0_INPUT_SEL] = { NISTC_G0_INPUT_SEL_REG, 2 }, | |
| 3733 | + [NITIO_G1_INPUT_SEL] = { NISTC_G1_INPUT_SEL_REG, 2 }, | |
| 3734 | + [NITIO_G0_CNT_MODE] = { 0x1b0, 2 }, /* M-Series only */ | |
| 3735 | + [NITIO_G1_CNT_MODE] = { 0x1b2, 2 }, /* M-Series only */ | |
| 3736 | + [NITIO_G0_GATE2] = { 0x1b4, 2 }, /* M-Series only */ | |
| 3737 | + [NITIO_G1_GATE2] = { 0x1b6, 2 }, /* M-Series only */ | |
| 3738 | + [NITIO_G01_STATUS] = { NISTC_G01_STATUS_REG, 2 }, | |
| 3739 | + [NITIO_G01_RESET] = { NISTC_RESET_REG, 2 }, | |
| 3740 | + [NITIO_G01_STATUS1] = { NISTC_STATUS1_REG, 2 }, | |
| 3741 | + [NITIO_G01_STATUS2] = { NISTC_STATUS2_REG, 2 }, | |
| 3742 | + [NITIO_G0_DMA_CFG] = { 0x1b8, 2 }, /* M-Series only */ | |
| 3743 | + [NITIO_G1_DMA_CFG] = { 0x1ba, 2 }, /* M-Series only */ | |
| 3744 | + [NITIO_G0_DMA_STATUS] = { 0x1b8, 2 }, /* M-Series only */ | |
| 3745 | + [NITIO_G1_DMA_STATUS] = { 0x1ba, 2 }, /* M-Series only */ | |
| 3746 | + [NITIO_G0_ABZ] = { 0x1c0, 2 }, /* M-Series only */ | |
| 3747 | + [NITIO_G1_ABZ] = { 0x1c2, 2 }, /* M-Series only */ | |
| 3748 | + [NITIO_G0_INT_ACK] = { NISTC_INTA_ACK_REG, 2 }, | |
| 3749 | + [NITIO_G1_INT_ACK] = { NISTC_INTB_ACK_REG, 2 }, | |
| 3750 | + [NITIO_G0_STATUS] = { NISTC_AI_STATUS1_REG, 2 }, | |
| 3751 | + [NITIO_G1_STATUS] = { NISTC_AO_STATUS1_REG, 2 }, | |
| 3752 | + [NITIO_G0_INT_ENA] = { NISTC_INTA_ENA_REG, 2 }, | |
| 3753 | + [NITIO_G1_INT_ENA] = { NISTC_INTB_ENA_REG, 2 }, | |
| 3754 | +}; | |
| 3858 | 3755 | |
| 3859 | −static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg) | |
| 3756 | +static unsigned int ni_gpct_to_stc_register(struct comedi_device *dev, | |
| 3757 | + enum ni_gpct_register reg) | |
| 3860 | 3758 | { |
| 3861 | − unsigned stc_register; | |
| 3759 | + const struct mio_regmap *regmap; | |
| 3862 | 3760 | |
| 3863 | − switch (reg) { | |
| 3864 | − case NITIO_G0_AUTO_INC: | |
| 3865 | − stc_register = G_Autoincrement_Register(0); | |
| 3866 | − break; | |
| 3867 | − case NITIO_G1_AUTO_INC: | |
| 3868 | − stc_register = G_Autoincrement_Register(1); | |
| 3869 | − break; | |
| 3870 | − case NITIO_G0_CMD: | |
| 3871 | − stc_register = G_Command_Register(0); | |
| 3872 | − break; | |
| 3873 | − case NITIO_G1_CMD: | |
| 3874 | − stc_register = G_Command_Register(1); | |
| 3875 | − break; | |
| 3876 | − case NITIO_G0_HW_SAVE: | |
| 3877 | − stc_register = G_HW_Save_Register(0); | |
| 3878 | − break; | |
| 3879 | − case NITIO_G1_HW_SAVE: | |
| 3880 | − stc_register = G_HW_Save_Register(1); | |
| 3881 | − break; | |
| 3882 | − case NITIO_G0_SW_SAVE: | |
| 3883 | − stc_register = G_Save_Register(0); | |
| 3884 | − break; | |
| 3885 | − case NITIO_G1_SW_SAVE: | |
| 3886 | − stc_register = G_Save_Register(1); | |
| 3887 | − break; | |
| 3888 | − case NITIO_G0_MODE: | |
| 3889 | − stc_register = G_Mode_Register(0); | |
| 3890 | − break; | |
| 3891 | − case NITIO_G1_MODE: | |
| 3892 | − stc_register = G_Mode_Register(1); | |
| 3893 | − break; | |
| 3894 | − case NITIO_G0_LOADA: | |
| 3895 | − stc_register = G_Load_A_Register(0); | |
| 3896 | − break; | |
| 3897 | − case NITIO_G1_LOADA: | |
| 3898 | − stc_register = G_Load_A_Register(1); | |
| 3899 | − break; | |
| 3900 | − case NITIO_G0_LOADB: | |
| 3901 | − stc_register = G_Load_B_Register(0); | |
| 3902 | − break; | |
| 3903 | − case NITIO_G1_LOADB: | |
| 3904 | − stc_register = G_Load_B_Register(1); | |
| 3905 | − break; | |
| 3906 | − case NITIO_G0_INPUT_SEL: | |
| 3907 | − stc_register = G_Input_Select_Register(0); | |
| 3908 | − break; | |
| 3909 | − case NITIO_G1_INPUT_SEL: | |
| 3910 | − stc_register = G_Input_Select_Register(1); | |
| 3911 | − break; | |
| 3912 | − case NITIO_G01_STATUS: | |
| 3913 | − stc_register = G_Status_Register; | |
| 3914 | − break; | |
| 3915 | − case NITIO_G01_RESET: | |
| 3916 | − stc_register = Joint_Reset_Register; | |
| 3917 | − break; | |
| 3918 | − case NITIO_G01_STATUS1: | |
| 3919 | − stc_register = Joint_Status_1_Register; | |
| 3920 | − break; | |
| 3921 | − case NITIO_G01_STATUS2: | |
| 3922 | − stc_register = Joint_Status_2_Register; | |
| 3923 | − break; | |
| 3924 | − case NITIO_G0_INT_ACK: | |
| 3925 | − stc_register = Interrupt_A_Ack_Register; | |
| 3926 | − break; | |
| 3927 | − case NITIO_G1_INT_ACK: | |
| 3928 | − stc_register = Interrupt_B_Ack_Register; | |
| 3929 | − break; | |
| 3930 | − case NITIO_G0_STATUS: | |
| 3931 | − stc_register = AI_Status_1_Register; | |
| 3932 | − break; | |
| 3933 | − case NITIO_G1_STATUS: | |
| 3934 | − stc_register = AO_Status_1_Register; | |
| 3935 | − break; | |
| 3936 | − case NITIO_G0_INT_ENA: | |
| 3937 | − stc_register = Interrupt_A_Enable_Register; | |
| 3938 | − break; | |
| 3939 | − case NITIO_G1_INT_ENA: | |
| 3940 | − stc_register = Interrupt_B_Enable_Register; | |
| 3941 | − break; | |
| 3942 | − default: | |
| 3943 | − pr_err("%s: unhandled register 0x%x in switch.\n", | |
| 3944 | − __func__, reg); | |
| 3945 | − BUG(); | |
| 3761 | + if (reg < ARRAY_SIZE(ni_gpct_to_stc_regmap)) { | |
| 3762 | + regmap = &ni_gpct_to_stc_regmap[reg]; | |
| 3763 | + } else { | |
| 3764 | + dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", | |
| 3765 | + __func__, reg); | |
| 3946 | 3766 | return 0; |
| 3947 | 3767 | } |
| 3948 | − return stc_register; | |
| 3768 | + | |
| 3769 | + return regmap->mio_reg; | |
| 3949 | 3770 | } |
| 3950 | 3771 | |
| 3951 | 3772 | static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, |
| 3952 | 3773 | enum ni_gpct_register reg) |
| 3953 | 3774 | { |
| 3954 | 3775 | struct comedi_device *dev = counter->counter_dev->dev; |
| 3955 | − unsigned stc_register; | |
| 3956 | − /* bits in the join reset register which are relevant to counters */ | |
| 3957 | − static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset; | |
| 3776 | + unsigned int stc_register = ni_gpct_to_stc_register(dev, reg); | |
| 3958 | 3777 | static const unsigned gpct_interrupt_a_enable_mask = |
| 3959 | − G0_Gate_Interrupt_Enable | G0_TC_Interrupt_Enable; | |
| 3778 | + NISTC_INTA_ENA_G0_GATE | NISTC_INTA_ENA_G0_TC; | |
| 3960 | 3779 | static const unsigned gpct_interrupt_b_enable_mask = |
| 3961 | − G1_Gate_Interrupt_Enable | G1_TC_Interrupt_Enable; | |
| 3780 | + NISTC_INTB_ENA_G1_GATE | NISTC_INTB_ENA_G1_TC; | |
| 3781 | + | |
| 3782 | + if (stc_register == 0) | |
| 3783 | + return; | |
1042 more lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 2281 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 179 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 352 lines aren’t shown here.
This diff is large: its 204 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 212 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 162 lines aren’t shown here.
This diff is large: its 231 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 395 lines aren’t shown here.
This diff is large: its 178 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 474 lines aren’t shown here.
This diff is large: its 593 lines aren’t shown here.
This diff is large: its 382 lines aren’t shown here.
This diff is large: its 613 lines aren’t shown here.
This diff is large: its 989 lines aren’t shown here.
This diff is large: its 1229 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 1163 lines aren’t shown here.
This diff is large: its 2050 lines aren’t shown here.
This diff is large: its 815 lines aren’t shown here.
This diff is large: its 1256 lines aren’t shown here.
This diff is large: its 313 lines aren’t shown here.
This diff is large: its 501 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 434 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 134 lines aren’t shown here.
This diff is large: its 464 lines aren’t shown here.
This diff is large: its 929 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 634 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 469 lines aren’t shown here.
This diff is large: its 951 lines aren’t shown here.
This diff is large: its 843 lines aren’t shown here.
This diff is large: its 940 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 923 lines aren’t shown here.
This diff is large: its 723 lines aren’t shown here.
This diff is large: its 905 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 362 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 321 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 232 lines aren’t shown here.
This diff is large: its 729 lines aren’t shown here.
This diff is large: its 493 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 509 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 274 lines aren’t shown here.
This diff is large: its 629 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 610 lines aren’t shown here.
This diff is large: its 357 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 281 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 575 lines aren’t shown here.
This diff is large: its 214 lines aren’t shown here.
This diff is large: its 400 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 332 lines aren’t shown here.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 471 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 175 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 419 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 242 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 97 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 170 lines aren’t shown here.
This diff is large: its 304 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 555 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 294 lines aren’t shown here.
This diff is large: its 298 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 1129 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 343 lines aren’t shown here.
This diff is large: its 182 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 242 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 175 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 179 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 164 lines aren’t shown here.
This diff is large: its 277 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 900 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 290 lines aren’t shown here.
This diff is large: its 4 lines aren’t shown here.
This diff is large: its 175 lines aren’t shown here.
This diff is large: its 58 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 684 lines aren’t shown here.
This diff is large: its 455 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 250 lines aren’t shown here.
This diff is large: its 339 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 526 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 348 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 131 lines aren’t shown here.
This diff is large: its 682 lines aren’t shown here.
This diff is large: its 136 lines aren’t shown here.
This diff is large: its 464 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 300 lines aren’t shown here.
This diff is large: its 199 lines aren’t shown here.
This diff is large: its 245 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 324 lines aren’t shown here.
This diff is large: its 798 lines aren’t shown here.
This diff is large: its 544 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 392 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 192 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 7232 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 311 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 294 lines aren’t shown here.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 208 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 313 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 1580 lines aren’t shown here.
This diff is large: its 909 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 441 lines aren’t shown here.
This diff is large: its 729 lines aren’t shown here.
This diff is large: its 383 lines aren’t shown here.
This diff is large: its 1574 lines aren’t shown here.
This diff is large: its 185 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 186 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 323 lines aren’t shown here.
This diff is large: its 198 lines aren’t shown here.
This diff is large: its 162 lines aren’t shown here.
This diff is large: its 247 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 237 lines aren’t shown here.
This diff is large: its 1218 lines aren’t shown here.
This diff is large: its 255 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 202 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 123 lines aren’t shown here.
This diff is large: its 1705 lines aren’t shown here.
This diff is large: its 706 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 365 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 92 lines aren’t shown here.
This diff is large: its 85 lines aren’t shown here.
This diff is large: its 260 lines aren’t shown here.
This diff is large: its 194 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 165 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 87 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 504 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 385 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 94 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 578 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 451 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 377 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 314 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 675 lines aren’t shown here.
This diff is large: its 1340 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 428 lines aren’t shown here.
This diff is large: its 311 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
File renamed without changes.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 731 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 154 lines aren’t shown here.
This diff is large: its 397 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 300 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
File renamed without changes.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 1373 lines aren’t shown here.
This diff is large: its 323 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 138 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 1573 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 1395 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 415 lines aren’t shown here.
File renamed without changes.
File renamed without changes.
This diff is large: its 143 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
File renamed without changes.
This diff is large: its 1519 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 688 lines aren’t shown here.
This diff is large: its 2291 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 161 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 431 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 237 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 2141 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 128 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 208 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 341 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 347 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 45 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 2157 lines aren’t shown here.
This diff is large: its 198 lines aren’t shown here.
This diff is large: its 134 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 7964 lines aren’t shown here.
This diff is large: its 1282 lines aren’t shown here.
This diff is large: its 599 lines aren’t shown here.
This diff is large: its 2784 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 250 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 480 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 192 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 240 lines aren’t shown here.
This diff is large: its 191 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 1255 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 1407 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 135 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 3958 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 952 lines aren’t shown here.
This diff is large: its 255 lines aren’t shown here.
This diff is large: its 2333 lines aren’t shown here.
This diff is large: its 322 lines aren’t shown here.
This diff is large: its 618 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 970 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 329 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 849 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.