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 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_raw | 72 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_raw |
| 73 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_raw | 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 | KernelVersion: 2.6.35 | 76 | KernelVersion: 2.6.35 |
| 75 | Contact: linux-iio@vger.kernel.org | 77 | Contact: linux-iio@vger.kernel.org |
| 76 | Description: | 78 | Description: |
| @@ -81,6 +83,11 @@ Description: · 4 unmodified lines | |||
| 81 | unique to allow association with event codes. Units after | 83 | unique to allow association with event codes. Units after |
| 82 | application of scale and offset are millivolts. | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw | 91 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_raw |
| 85 | KernelVersion: 2.6.35 | 92 | KernelVersion: 2.6.35 |
| 86 | Contact: linux-iio@vger.kernel.org | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset | 253 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset |
| 247 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset | 254 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset |
| 248 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset | 260 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset |
| 250 | What: /sys/bus/iio/devices/iio:deviceX/in_current_offset | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset | 266 | What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset |
| 252 | What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset | 267 | What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset |
| 253 | What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset | 268 | What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset |
| @@ -273,14 +288,22 @@ Description: · 19 unmodified lines | |||
| 273 | to the _raw output. | 288 | to the _raw output. |
| 274 | 289 | ||
| 275 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_scale | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_scale | 293 | What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_scale |
| 277 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale | 297 | What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale |
| 279 | What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale | 298 | What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale |
| 280 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale | 299 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale |
| 281 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale | 300 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale |
| 282 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale | 301 | What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale |
| 283 | What: /sys/bus/iio/devices/iio:deviceX/in_current_scale | 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 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale | 307 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale |
| 285 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale | 308 | What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale |
| 286 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale | 309 | What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale |
| @@ -328,6 +351,10 @@ Description: · 41 unmodified lines | |||
| 328 | 351 | ||
| 329 | What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale | 352 | What /sys/bus/iio/devices/iio:deviceX/in_voltageY_calibscale |
| 330 | What /sys/bus/iio/devices/iio:deviceX/in_voltageY_supply_calibscale | 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 | What /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale | 358 | What /sys/bus/iio/devices/iio:deviceX/in_voltage_calibscale |
| 332 | What /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale | 359 | What /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibscale |
| 333 | What /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale | 360 | What /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibscale |
| @@ -420,6 +447,16 @@ Description: · 86 unmodified lines | |||
| 420 | to the underlying data channel, then this parameter | 447 | to the underlying data channel, then this parameter |
| 421 | gives the 3dB frequency of the filter in Hz. | 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 | What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw | 460 | What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_raw |
| 424 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_raw | 461 | What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_raw |
| 425 | KernelVersion: 2.6.37 | 462 | KernelVersion: 2.6.37 |
| @@ -880,6 +917,26 @@ Description: · 454 unmodified lines | |||
| 880 | met before an event is generated. If direction is not | 917 | met before an event is generated. If direction is not |
| 881 | specified then this period applies to both directions. | 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 | What: /sys/.../events/in_activity_still_thresh_rising_en | 940 | What: /sys/.../events/in_activity_still_thresh_rising_en |
| 884 | What: /sys/.../events/in_activity_still_thresh_falling_en | 941 | What: /sys/.../events/in_activity_still_thresh_falling_en |
| 885 | What: /sys/.../events/in_activity_walking_thresh_rising_en | 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 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en | 1073 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_en |
| 1017 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en | 1074 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_en |
| 1018 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY-voltageZ_en | 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 | What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en | 1080 | What: /sys/.../iio:deviceX/scan_elements/in_incli_x_en |
| 1020 | What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en | 1081 | What: /sys/.../iio:deviceX/scan_elements/in_incli_y_en |
| 1021 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_en | 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 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type | 1095 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_type |
| 1035 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_type | 1096 | What: /sys/.../iio:deviceX/scan_elements/in_voltage_type |
| 1036 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_type | 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 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type | 1102 | What: /sys/.../iio:deviceX/scan_elements/in_timestamp_type |
| 1038 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type | 1103 | What: /sys/.../iio:deviceX/scan_elements/in_pressureY_type |
| 1039 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_type | 1104 | What: /sys/.../iio:deviceX/scan_elements/in_pressure_type |
| @@ -1071,6 +1136,10 @@ Description: · 31 unmodified lines | |||
| 1071 | 1136 | ||
| 1072 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index | 1137 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_index |
| 1073 | What: /sys/.../iio:deviceX/scan_elements/in_voltageY_supply_index | 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 | What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index | 1143 | What: /sys/.../iio:deviceX/scan_elements/in_accel_x_index |
| 1075 | What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index | 1144 | What: /sys/.../iio:deviceX/scan_elements/in_accel_y_index |
| 1076 | What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index | 1145 | What: /sys/.../iio:deviceX/scan_elements/in_accel_z_index |
| @@ -1230,6 +1299,8 @@ Description: · 153 unmodified lines | |||
| 1230 | or without compensation from tilt sensors. | 1299 | or without compensation from tilt sensors. |
| 1231 | 1300 | ||
| 1232 | What: /sys/bus/iio/devices/iio:deviceX/in_currentX_raw | 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 | KernelVersion: 3.18 | 1304 | KernelVersion: 3.18 |
| 1234 | Contact: linux-iio@vger.kernel.org | 1305 | Contact: linux-iio@vger.kernel.org |
| 1235 | Description: | 1306 | Description: |
| @@ -1238,6 +1309,11 @@ Description: · 2 unmodified lines | |||
| 1238 | present, output should be considered as processed with the | 1309 | present, output should be considered as processed with the |
| 1239 | unit in milliamps. | 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 | What: /sys/.../iio:deviceX/in_energy_en | 1317 | What: /sys/.../iio:deviceX/in_energy_en |
| 1242 | What: /sys/.../iio:deviceX/in_distance_en | 1318 | What: /sys/.../iio:deviceX/in_distance_en |
| 1243 | What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en | 1319 | What: /sys/.../iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_en |
| @@ -1364,3 +1440,26 @@ Description: · 120 unmodified lines | |||
| 1364 | hwfifo_watermak_min but not equal to any of the values in this | 1440 | hwfifo_watermak_min but not equal to any of the values in this |
| 1365 | list, the driver will chose an appropriate value for the | 1441 | list, the driver will chose an appropriate value for the |
| 1366 | hardware fifo watermark level. | 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 | Required properties: | 3 | Required properties: |
| 4 | - compatible: Should be "ti,adc128s052" | 4 | - compatible: Should be "ti,adc128s052" or "ti,adc122s021" |
| 5 | - reg: spi chip select number for the device | 5 | - reg: spi chip select number for the device |
| 6 | - vref-supply: The regulator supply for ADC reference voltage | 6 | - vref-supply: The regulator supply for ADC reference voltage |
| 7 | 7 | ||
| @@ -11,6 +11,13 @@ Required properties: · 10 unmodified lines | |||
| 11 | - clock-names: Must contain "adc", matching entry in the clocks property. | 11 | - clock-names: Must contain "adc", matching entry in the clocks property. |
| 12 | - vref-supply: The regulator supply ADC reference voltage. | 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 | Example: | 21 | Example: |
| 15 | adc0: adc@4003b000 { | 22 | adc0: adc@4003b000 { |
| 16 | compatible = "fsl,vf610-adc"; | 23 | compatible = "fsl,vf610-adc"; |
| @@ -18,5 +25,7 @@ adc0: adc@4003b000 { · 1 unmodified line | |||
| 18 | interrupts = <0 53 0x04>; | 25 | interrupts = <0 53 0x04>; |
| 19 | clocks = <&clks VF610_CLK_ADC0>; | 26 | clocks = <&clks VF610_CLK_ADC0>; |
| 20 | clock-names = "adc"; | 27 | clock-names = "adc"; |
| 28 | fsl,adck-max-frequency = <30000000>, <40000000>, | ||
| 29 | <20000000>; | ||
| 21 | vref-supply = <®_vcc_3v3_mcu>; | 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 | - st,lsm330d-accel | 30 | - st,lsm330d-accel |
| 31 | - st,lsm330dl-accel | 31 | - st,lsm330dl-accel |
| 32 | - st,lsm330dlc-accel | 32 | - st,lsm330dlc-accel |
| 33 | - st,lis331dl-accel | ||
| 33 | - st,lis331dlh-accel | 34 | - st,lis331dlh-accel |
| 34 | - st,lsm303dl-accel | 35 | - st,lsm303dl-accel |
| 35 | - st,lsm303dlm-accel | 36 | - st,lsm303dlm-accel |
| @@ -45,6 +46,7 @@ Gyroscopes: · 9 unmodified lines | |||
| 45 | - st,lsm330-gyro | 46 | - st,lsm330-gyro |
| 46 | 47 | ||
| 47 | Magnetometers: | 48 | Magnetometers: |
| 49 | - st,lsm303dlh-magn | ||
| 48 | - st,lsm303dlhc-magn | 50 | - st,lsm303dlhc-magn |
| 49 | - st,lsm303dlm-magn | 51 | - st,lsm303dlm-magn |
| 50 | - st,lis3mdl-magn | 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 | hardware knob for adjusting the amount of "settling | 42 | hardware knob for adjusting the amount of "settling |
| 43 | time". | 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 | Example: | 66 | Example: |
| 46 | tscadc: tscadc@44e0d000 { | 67 | tscadc: tscadc@44e0d000 { |
| 47 | compatible = "ti,am3359-tscadc"; | 68 | compatible = "ti,am3359-tscadc"; |
| @@ -55,5 +76,8 @@ Example: · 7 unmodified lines | |||
| 55 | 76 | ||
| 56 | adc { | 77 | adc { |
| 57 | ti,adc-channels = <4 5 6 7>; | 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 | marvell Marvell Technology Group Ltd. | 123 | marvell Marvell Technology Group Ltd. |
| 124 | maxim Maxim Integrated Products | 124 | maxim Maxim Integrated Products |
| 125 | mediatek MediaTek Inc. | 125 | mediatek MediaTek Inc. |
| 126 | melexis Melexis N.V. | ||
| 126 | merrii Merrii Technology Co., Ltd. | 127 | merrii Merrii Technology Co., Ltd. |
| 127 | micrel Micrel Inc. | 128 | micrel Micrel Inc. |
| 128 | microchip Microchip Technology Inc. | 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 | the mask match with the values of the corresponding bits in the compare field, | 171 | the mask match with the values of the corresponding bits in the compare field, |
| 172 | the value of swap is written the specified offset. | 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 | Slave windows | 181 | Slave windows |
| 176 | ============= | 182 | ============= |
| @@ -9696,6 +9696,15 @@ M: Forest Bond <forest@alittletooquiet.net> · 9695 unmodified lines | |||
| 9696 | S: Odd Fixes | 9696 | S: Odd Fixes |
| 9697 | F: drivers/staging/vt665?/ | 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 | STAGING - XGI Z7,Z9,Z11 PCI DISPLAY DRIVER | 9708 | STAGING - XGI Z7,Z9,Z11 PCI DISPLAY DRIVER |
| 9700 | M: Arnaud Patard <arnaud.patard@rtp-net.org> | 9709 | M: Arnaud Patard <arnaud.patard@rtp-net.org> |
| 9701 | S: Odd Fixes | 9710 | S: Odd Fixes |
| @@ -98,7 +98,6 @@ obj-$(CONFIG_USB_GADGET) += usb/ · 97 unmodified lines | |||
| 98 | obj-$(CONFIG_SERIO) += input/serio/ | 98 | obj-$(CONFIG_SERIO) += input/serio/ |
| 99 | obj-$(CONFIG_GAMEPORT) += input/gameport/ | 99 | obj-$(CONFIG_GAMEPORT) += input/gameport/ |
| 100 | obj-$(CONFIG_INPUT) += input/ | 100 | obj-$(CONFIG_INPUT) += input/ |
| 101 | obj-$(CONFIG_I2O) += message/ | ||
| 102 | obj-$(CONFIG_RTC_LIB) += rtc/ | 101 | obj-$(CONFIG_RTC_LIB) += rtc/ |
| 103 | obj-y += i2c/ media/ | 102 | obj-y += i2c/ media/ |
| 104 | obj-$(CONFIG_PPS) += pps/ | 103 | obj-$(CONFIG_PPS) += pps/ |
| @@ -136,4 +136,25 @@ config MMA9553 · 135 unmodified lines | |||
| 136 | 136 | ||
| 137 | To compile this driver as a module, choose M here: the module | 137 | To compile this driver as a module, choose M here: the module |
| 138 | will be called mma9553. | 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 | endmenu | 160 | endmenu |
| @@ -14,6 +14,9 @@ obj-$(CONFIG_MMA9551_CORE) += mma9551_core.o · 13 unmodified lines | |||
| 14 | obj-$(CONFIG_MMA9551) += mma9551.o | 14 | obj-$(CONFIG_MMA9551) += mma9551.o |
| 15 | obj-$(CONFIG_MMA9553) += mma9553.o | 15 | obj-$(CONFIG_MMA9553) += mma9553.o |
| 16 | 16 | ||
| 17 | obj-$(CONFIG_STK8312) += stk8312.o | ||
| 18 | obj-$(CONFIG_STK8BA50) += stk8ba50.o | ||
| 19 | |||
| 17 | obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o | 20 | obj-$(CONFIG_IIO_SSP_SENSORS_COMMONS) += ssp_accel_sensor.o |
| 18 | 21 | ||
| 19 | obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o | 22 | obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o |
| @@ -196,7 +196,7 @@ struct bmc150_accel_data { · 195 unmodified lines | |||
| 196 | u32 slope_thres; | 196 | u32 slope_thres; |
| 197 | u32 range; | 197 | u32 range; |
| 198 | int ev_enable_state; | 198 | int ev_enable_state; |
| 199 | int64_t timestamp, old_timestamp; | 199 | int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */ |
| 200 | const struct bmc150_accel_chip_info *chip_info; | 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 | .write_event_value = bmc150_accel_write_event, | 1183 | .write_event_value = bmc150_accel_write_event, |
| 1184 | .write_event_config = bmc150_accel_write_event_config, | 1184 | .write_event_config = bmc150_accel_write_event_config, |
| 1185 | .read_event_config = bmc150_accel_read_event_config, | 1185 | .read_event_config = bmc150_accel_read_event_config, |
| 1186 | .validate_trigger = bmc150_accel_validate_trigger, | ||
| 1187 | .driver_module = THIS_MODULE, | 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 | mutex_unlock(&data->mutex); | 1221 | mutex_unlock(&data->mutex); |
| 1223 | 1222 | ||
| 1224 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 1223 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, |
| 1225 | data->timestamp); | 1224 | pf->timestamp); |
| 1226 | err_read: | 1225 | err_read: |
| 1227 | iio_trigger_notify_done(indio_dev->trig); | 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 | return ret; | 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 | static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev) | 1544 | static int bmc150_accel_buffer_postenable(struct iio_dev *indio_dev) |
| 1539 | { | 1545 | { |
| 1540 | struct bmc150_accel_data *data = iio_priv(indio_dev); | 1546 | struct bmc150_accel_data *data = iio_priv(indio_dev); |
| @@ -1591,9 +1597,18 @@ out: · 50 unmodified lines | |||
| 1591 | return 0; | 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 | static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = { | 1607 | static const struct iio_buffer_setup_ops bmc150_accel_buffer_ops = { |
| 1608 | .preenable = bmc150_accel_buffer_preenable, | ||
| 1595 | .postenable = bmc150_accel_buffer_postenable, | 1609 | .postenable = bmc150_accel_buffer_postenable, |
| 1596 | .predisable = bmc150_accel_buffer_predisable, | 1610 | .predisable = bmc150_accel_buffer_predisable, |
| 1611 | .postdisable = bmc150_accel_buffer_postdisable, | ||
| 1597 | }; | 1612 | }; |
| 1598 | 1613 | ||
| 1599 | static int bmc150_accel_probe(struct i2c_client *client, | 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 | indio_dev->modes = INDIO_DIRECT_MODE; | 1651 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 1637 | indio_dev->info = &bmc150_accel_info; | 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 | if (client->irq < 0) | 1663 | if (client->irq < 0) |
| 1640 | client->irq = bmc150_accel_gpio_probe(client, data); | 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 | BMC150_ACCEL_IRQ_NAME, | 1672 | BMC150_ACCEL_IRQ_NAME, |
| 1649 | indio_dev); | 1673 | indio_dev); |
| 1650 | if (ret) | 1674 | if (ret) |
| 1651 | return ret; | 1675 | goto err_buffer_cleanup; |
| 1652 | 1676 | ||
| 1653 | /* | 1677 | /* |
| 1654 | * Set latched mode interrupt. While certain interrupts are | 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 | BMC150_ACCEL_INT_MODE_LATCH_RESET); | 1685 | BMC150_ACCEL_INT_MODE_LATCH_RESET); |
| 1662 | if (ret < 0) { | 1686 | if (ret < 0) { |
| 1663 | dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n"); | 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 | bmc150_accel_interrupts_setup(indio_dev, data); | 1691 | bmc150_accel_interrupts_setup(indio_dev, data); |
| 1668 | 1692 | ||
| 1669 | ret = bmc150_accel_triggers_setup(indio_dev, data); | 1693 | ret = bmc150_accel_triggers_setup(indio_dev, data); |
| 1670 | if (ret) | 1694 | if (ret) |
| 1671 | return ret; | 1695 | goto err_buffer_cleanup; |
| 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 | } | ||
| 1682 | 1696 | ||
| 1683 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || | 1697 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) || |
| 1684 | i2c_check_functionality(client->adapter, | 1698 | i2c_check_functionality(client->adapter, |
| @@ -1692,7 +1706,7 @@ static int bmc150_accel_probe(struct i2c_client *client, · 7 unmodified lines | |||
| 1692 | ret = iio_device_register(indio_dev); | 1706 | ret = iio_device_register(indio_dev); |
| 1693 | if (ret < 0) { | 1707 | if (ret < 0) { |
| 1694 | dev_err(&client->dev, "Unable to register iio device\n"); | 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 | ret = pm_runtime_set_active(&client->dev); | 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 | err_iio_unregister: | 1723 | err_iio_unregister: |
| 1710 | iio_device_unregister(indio_dev); | 1724 | iio_device_unregister(indio_dev); |
| 1711 | err_buffer_cleanup: | ||
| 1712 | if (indio_dev->pollfunc) | ||
| 1713 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 1714 | err_trigger_unregister: | 1725 | err_trigger_unregister: |
| 1715 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); | 1726 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1727 | err_buffer_cleanup: | ||
| 1728 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 1716 | 1729 | ||
| 1717 | return ret; | 1730 | return ret; |
| 1718 | } | 1731 | } |
| @@ -1730,6 +1743,8 @@ static int bmc150_accel_remove(struct i2c_client *client) · 11 unmodified lines | |||
| 1730 | 1743 | ||
| 1731 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); | 1744 | bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1); |
| 1732 | 1745 | ||
| 1746 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 1747 | |||
| 1733 | mutex_lock(&data->mutex); | 1748 | mutex_lock(&data->mutex); |
| 1734 | bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_DEEP_SUSPEND, 0); | 1749 | bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_DEEP_SUSPEND, 0); |
| 1735 | mutex_unlock(&data->mutex); | 1750 | mutex_unlock(&data->mutex); |
| @@ -299,7 +299,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev) · 298 unmodified lines | |||
| 299 | struct iio_dev *indio_dev; | 299 | struct iio_dev *indio_dev; |
| 300 | struct accel_3d_state *accel_state; | 300 | struct accel_3d_state *accel_state; |
| 301 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 301 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 302 | struct iio_chan_spec *channels; | ||
| 303 | 302 | ||
| 304 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 303 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 305 | sizeof(struct accel_3d_state)); | 304 | sizeof(struct accel_3d_state)); |
| @@ -320,21 +319,21 @@ static int hid_accel_3d_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 320 | return ret; | 319 | return ret; |
| 321 | } | 320 | } |
| 322 | 321 | ||
| 323 | channels = kmemdup(accel_3d_channels, sizeof(accel_3d_channels), | 322 | indio_dev->channels = kmemdup(accel_3d_channels, |
| 324 | GFP_KERNEL); | 323 | sizeof(accel_3d_channels), GFP_KERNEL); |
| 325 | if (!channels) { | 324 | if (!indio_dev->channels) { |
| 326 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | 325 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 327 | return -ENOMEM; | 326 | return -ENOMEM; |
| 328 | } | 327 | } |
| 329 | 328 | ||
| 330 | ret = accel_3d_parse_report(pdev, hsdev, channels, | 329 | ret = accel_3d_parse_report(pdev, hsdev, |
| 331 | HID_USAGE_SENSOR_ACCEL_3D, accel_state); | 330 | (struct iio_chan_spec *)indio_dev->channels, |
| 331 | HID_USAGE_SENSOR_ACCEL_3D, accel_state); | ||
| 332 | if (ret) { | 332 | if (ret) { |
| 333 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 333 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 334 | goto error_free_dev_mem; | 334 | goto error_free_dev_mem; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | indio_dev->channels = channels; | ||
| 338 | indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels); | 337 | indio_dev->num_channels = ARRAY_SIZE(accel_3d_channels); |
| 339 | indio_dev->dev.parent = &pdev->dev; | 338 | indio_dev->dev.parent = &pdev->dev; |
| 340 | indio_dev->info = &accel_3d_info; | 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 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 404 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 406 | .name = "HID-SENSOR-200073", | 405 | .name = "HID-SENSOR-200073", |
| @@ -875,15 +875,18 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev, · 874 unmodified lines | |||
| 875 | return 0; | 875 | return 0; |
| 876 | } | 876 | } |
| 877 | 877 | ||
| 878 | static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev, | 878 | static int kxcjk1013_buffer_preenable(struct iio_dev *indio_dev) |
| 879 | struct iio_trigger *trig) | ||
| 880 | { | 879 | { |
| 881 | struct kxcjk1013_data *data = iio_priv(indio_dev); | 880 | struct kxcjk1013_data *data = iio_priv(indio_dev); |
| 882 | 881 | ||
| 883 | if (data->dready_trig != trig && data->motion_trig != trig) | 882 | return kxcjk1013_set_power_state(data, true); |
| 884 | return -EINVAL; | 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 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( | 892 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( |
| @@ -935,6 +938,13 @@ static const struct iio_chan_spec kxcjk1013_channels[] = { · 45 unmodified lines | |||
| 935 | IIO_CHAN_SOFT_TIMESTAMP(3), | 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 | static const struct iio_info kxcjk1013_info = { | 948 | static const struct iio_info kxcjk1013_info = { |
| 939 | .attrs = &kxcjk1013_attrs_group, | 949 | .attrs = &kxcjk1013_attrs_group, |
| 940 | .read_raw = kxcjk1013_read_raw, | 950 | .read_raw = kxcjk1013_read_raw, |
| @@ -943,7 +953,6 @@ static const struct iio_info kxcjk1013_info = { · 2 unmodified lines | |||
| 943 | .write_event_value = kxcjk1013_write_event, | 953 | .write_event_value = kxcjk1013_write_event, |
| 944 | .write_event_config = kxcjk1013_write_event_config, | 954 | .write_event_config = kxcjk1013_write_event_config, |
| 945 | .read_event_config = kxcjk1013_read_event_config, | 955 | .read_event_config = kxcjk1013_read_event_config, |
| 946 | .validate_trigger = kxcjk1013_validate_trigger, | ||
| 947 | .driver_module = THIS_MODULE, | 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 | id = acpi_match_device(dev->driver->acpi_match_table, dev); | 1156 | id = acpi_match_device(dev->driver->acpi_match_table, dev); |
| 1148 | if (!id) | 1157 | if (!id) |
| 1149 | return NULL; | 1158 | return NULL; |
| 1159 | |||
| 1150 | if (strcmp(id->id, "SMO8500") == 0) | 1160 | if (strcmp(id->id, "SMO8500") == 0) |
| 1151 | *is_smo8500_device = true; | 1161 | *is_smo8500_device = true; |
| 1162 | |||
| 1152 | *chipset = (enum kx_chipset)id->driver_data; | 1163 | *chipset = (enum kx_chipset)id->driver_data; |
| 1153 | 1164 | ||
| 1154 | return dev_name(dev); | 1165 | return dev_name(dev); |
| @@ -1163,6 +1174,7 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client, · 8 unmodified lines | |||
| 1163 | 1174 | ||
| 1164 | if (!client) | 1175 | if (!client) |
| 1165 | return -EINVAL; | 1176 | return -EINVAL; |
| 1177 | |||
| 1166 | if (data->is_smo8500_device) | 1178 | if (data->is_smo8500_device) |
| 1167 | return -ENOTSUPP; | 1179 | return -ENOTSUPP; |
| 1168 | 1180 | ||
| @@ -1276,16 +1288,15 @@ static int kxcjk1013_probe(struct i2c_client *client, · 107 unmodified lines | |||
| 1276 | data->motion_trig = NULL; | 1288 | data->motion_trig = NULL; |
| 1277 | goto err_trigger_unregister; | 1289 | goto err_trigger_unregister; |
| 1278 | } | 1290 | } |
| 1291 | } | ||
| 1279 | 1292 | ||
| 1280 | ret = iio_triggered_buffer_setup(indio_dev, | 1293 | ret = iio_triggered_buffer_setup(indio_dev, |
| 1281 | &iio_pollfunc_store_time, | 1294 | &iio_pollfunc_store_time, |
| 1282 | kxcjk1013_trigger_handler, | 1295 | kxcjk1013_trigger_handler, |
| 1283 | NULL); | 1296 | &kxcjk1013_buffer_setup_ops); |
| 1284 | if (ret < 0) { | 1297 | if (ret < 0) { |
| 1285 | dev_err(&client->dev, | 1298 | dev_err(&client->dev, "iio triggered buffer setup failed\n"); |
| 1286 | "iio triggered buffer setup failed\n"); | 1299 | goto err_trigger_unregister; |
| 1287 | goto err_trigger_unregister; | ||
| 1288 | } | ||
| 1289 | } | 1300 | } |
| 1290 | 1301 | ||
| 1291 | ret = iio_device_register(indio_dev); | 1302 | ret = iio_device_register(indio_dev); |
| @@ -1418,6 +1429,7 @@ static const struct dev_pm_ops kxcjk1013_pm_ops = { · 126 unmodified lines | |||
| 1418 | static const struct acpi_device_id kx_acpi_match[] = { | 1429 | static const struct acpi_device_id kx_acpi_match[] = { |
| 1419 | {"KXCJ1013", KXCJK1013}, | 1430 | {"KXCJ1013", KXCJK1013}, |
| 1420 | {"KXCJ1008", KXCJ91008}, | 1431 | {"KXCJ1008", KXCJ91008}, |
| 1432 | {"KXCJ9000", KXCJ91008}, | ||
| 1421 | {"KXTJ1009", KXTJ21009}, | 1433 | {"KXTJ1009", KXTJ21009}, |
| 1422 | {"SMO8500", KXCJ91008}, | 1434 | {"SMO8500", KXCJ91008}, |
| 1423 | { }, | 1435 | { }, |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | |||
| 9 | * | 9 | * |
| 10 | * 7-bit I2C slave address 0x1c/0x1d (pin selectable) | 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 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| @@ -18,20 +18,42 @@ · 2 unmodified lines | |||
| 18 | #include <linux/iio/sysfs.h> | 18 | #include <linux/iio/sysfs.h> |
| 19 | #include <linux/iio/trigger_consumer.h> | 19 | #include <linux/iio/trigger_consumer.h> |
| 20 | #include <linux/iio/buffer.h> | 20 | #include <linux/iio/buffer.h> |
| 21 | #include <linux/iio/trigger.h> | ||
| 22 | #include <linux/iio/trigger_consumer.h> | ||
| 21 | #include <linux/iio/triggered_buffer.h> | 23 | #include <linux/iio/triggered_buffer.h> |
| 24 | #include <linux/iio/events.h> | ||
| 22 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 23 | 26 | ||
| 24 | #define MMA8452_STATUS 0x00 | 27 | #define MMA8452_STATUS 0x00 |
| 25 | #define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */ | 28 | #define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */ |
| 26 | #define MMA8452_OUT_Y 0x03 | 29 | #define MMA8452_OUT_Y 0x03 |
| 27 | #define MMA8452_OUT_Z 0x05 | 30 | #define MMA8452_OUT_Z 0x05 |
| 31 | #define MMA8452_INT_SRC 0x0c | ||
| 28 | #define MMA8452_WHO_AM_I 0x0d | 32 | #define MMA8452_WHO_AM_I 0x0d |
| 29 | #define MMA8452_DATA_CFG 0x0e | 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 | #define MMA8452_OFF_X 0x2f | 47 | #define MMA8452_OFF_X 0x2f |
| 31 | #define MMA8452_OFF_Y 0x30 | 48 | #define MMA8452_OFF_Y 0x30 |
| 32 | #define MMA8452_OFF_Z 0x31 | 49 | #define MMA8452_OFF_Z 0x31 |
| 33 | #define MMA8452_CTRL_REG1 0x2a | 50 | #define MMA8452_CTRL_REG1 0x2a |
| 34 | #define MMA8452_CTRL_REG2 0x2b | 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 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) | 58 | #define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0)) |
| 37 | 59 | ||
| @@ -44,6 +66,10 @@ · 6 unmodified lines | |||
| 44 | #define MMA8452_DATA_CFG_FS_2G 0 | 66 | #define MMA8452_DATA_CFG_FS_2G 0 |
| 45 | #define MMA8452_DATA_CFG_FS_4G 1 | 67 | #define MMA8452_DATA_CFG_FS_4G 1 |
| 46 | #define MMA8452_DATA_CFG_FS_8G 2 | 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 | #define MMA8452_DEVICE_ID 0x2a | 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 | return -EINVAL; | 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 | static const int mma8452_samp_freq[8][2] = { | 141 | static const int mma8452_samp_freq[8][2] = { |
| 110 | {800, 0}, {400, 0}, {200, 0}, {100, 0}, {50, 0}, {12, 500000}, | 142 | {800, 0}, {400, 0}, {200, 0}, {100, 0}, {50, 0}, {12, 500000}, |
| 111 | {6, 250000}, {1, 560000} | 143 | {6, 250000}, {1, 560000} |
| @@ -121,6 +153,30 @@ static const int mma8452_scales[3][2] = { · 9 unmodified lines | |||
| 121 | {0, 9577}, {0, 19154}, {0, 38307} | 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 | static ssize_t mma8452_show_samp_freq_avail(struct device *dev, | 180 | static ssize_t mma8452_show_samp_freq_avail(struct device *dev, |
| 125 | struct device_attribute *attr, char *buf) | 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 | ARRAY_SIZE(mma8452_scales)); | 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 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail); | 206 | static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail); |
| 139 | static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, | 207 | static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO, |
| 140 | mma8452_show_scale_avail, NULL, 0); | 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 | static int mma8452_get_samp_freq_index(struct mma8452_data *data, | 212 | static int mma8452_get_samp_freq_index(struct mma8452_data *data, |
| 143 | int val, int val2) | 213 | int val, int val2) |
| @@ -153,6 +223,31 @@ static int mma8452_get_scale_index(struct mma8452_data *data, · 9 unmodified lines | |||
| 153 | ARRAY_SIZE(mma8452_scales), val, val2); | 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 | static int mma8452_read_raw(struct iio_dev *indio_dev, | 251 | static int mma8452_read_raw(struct iio_dev *indio_dev, |
| 157 | struct iio_chan_spec const *chan, | 252 | struct iio_chan_spec const *chan, |
| 158 | int *val, int *val2, long mask) | 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 | *val2 = mma8452_scales[i][1]; | 275 | *val2 = mma8452_scales[i][1]; |
| 181 | return IIO_VAL_INT_PLUS_MICRO; | 276 | return IIO_VAL_INT_PLUS_MICRO; |
| 182 | case IIO_CHAN_INFO_SAMP_FREQ: | 277 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 183 | i = (data->ctrl_reg1 & MMA8452_CTRL_DR_MASK) >> | 278 | i = mma8452_get_odr_index(data); |
| 184 | MMA8452_CTRL_DR_SHIFT; | ||
| 185 | *val = mma8452_samp_freq[i][0]; | 279 | *val = mma8452_samp_freq[i][0]; |
| 186 | *val2 = mma8452_samp_freq[i][1]; | 280 | *val2 = mma8452_samp_freq[i][1]; |
| 187 | return IIO_VAL_INT_PLUS_MICRO; | 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 | return ret; | 286 | return ret; |
| 193 | *val = sign_extend32(ret, 7); | 287 | *val = sign_extend32(ret, 7); |
| 194 | return IIO_VAL_INT; | 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 | return -EINVAL; | 300 | return -EINVAL; |
| 197 | } | 301 | } |
| @@ -233,12 +337,31 @@ fail: · 35 unmodified lines | |||
| 233 | return ret; | 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 | static int mma8452_write_raw(struct iio_dev *indio_dev, | 359 | static int mma8452_write_raw(struct iio_dev *indio_dev, |
| 237 | struct iio_chan_spec const *chan, | 360 | struct iio_chan_spec const *chan, |
| 238 | int val, int val2, long mask) | 361 | int val, int val2, long mask) |
| 239 | { | 362 | { |
| 240 | struct mma8452_data *data = iio_priv(indio_dev); | 363 | struct mma8452_data *data = iio_priv(indio_dev); |
| 241 | int i; | 364 | int i, ret; |
| 242 | 365 | ||
| 243 | if (iio_buffer_enabled(indio_dev)) | 366 | if (iio_buffer_enabled(indio_dev)) |
| 244 | return -EBUSY; | 367 | return -EBUSY; |
| @@ -266,11 +389,217 @@ static int mma8452_write_raw(struct iio_dev *indio_dev, · 21 unmodified lines | |||
| 266 | return -EINVAL; | 389 | return -EINVAL; |
| 267 | return mma8452_change_config(data, MMA8452_OFF_X + | 390 | return mma8452_change_config(data, MMA8452_OFF_X + |
| 268 | chan->scan_index, val); | 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 | default: | 504 | default: |
| 270 | return -EINVAL; | 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 | static irqreturn_t mma8452_trigger_handler(int irq, void *p) | 603 | static irqreturn_t mma8452_trigger_handler(int irq, void *p) |
| 275 | { | 604 | { |
| 276 | struct iio_poll_func *pf = p; | 605 | struct iio_poll_func *pf = p; |
| @@ -291,6 +620,55 @@ done: · 14 unmodified lines | |||
| 291 | return IRQ_HANDLED; | 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 | #define MMA8452_CHANNEL(axis, idx) { \ | 672 | #define MMA8452_CHANNEL(axis, idx) { \ |
| 295 | .type = IIO_ACCEL, \ | 673 | .type = IIO_ACCEL, \ |
| 296 | .modified = 1, \ | 674 | .modified = 1, \ |
| @@ -298,7 +676,8 @@ done: · 1 unmodified line | |||
| 298 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ | 676 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
| 299 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | 677 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ |
| 300 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \ | 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 | .scan_index = idx, \ | 681 | .scan_index = idx, \ |
| 303 | .scan_type = { \ | 682 | .scan_type = { \ |
| 304 | .sign = 's', \ | 683 | .sign = 's', \ |
| @@ -307,6 +686,8 @@ done: · 2 unmodified lines | |||
| 307 | .shift = 4, \ | 686 | .shift = 4, \ |
| 308 | .endianness = IIO_BE, \ | 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 | static const struct iio_chan_spec mma8452_channels[] = { | 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 | static struct attribute *mma8452_attributes[] = { | 700 | static struct attribute *mma8452_attributes[] = { |
| 320 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | 701 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
| 321 | &iio_dev_attr_in_accel_scale_available.dev_attr.attr, | 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 | NULL | 704 | NULL |
| 323 | }; | 705 | }; |
| 324 | 706 | ||
| @@ -330,11 +712,107 @@ static const struct iio_info mma8452_info = { · 5 unmodified lines | |||
| 330 | .attrs = &mma8452_group, | 712 | .attrs = &mma8452_group, |
| 331 | .read_raw = &mma8452_read_raw, | 713 | .read_raw = &mma8452_read_raw, |
| 332 | .write_raw = &mma8452_write_raw, | 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 | .driver_module = THIS_MODULE, | 721 | .driver_module = THIS_MODULE, |
| 334 | }; | 722 | }; |
| 335 | 723 | ||
| 336 | static const unsigned long mma8452_scan_masks[] = {0x7, 0}; | 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 | static int mma8452_probe(struct i2c_client *client, | 816 | static int mma8452_probe(struct i2c_client *client, |
| 339 | const struct i2c_device_id *id) | 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 | indio_dev->num_channels = ARRAY_SIZE(mma8452_channels); | 843 | indio_dev->num_channels = ARRAY_SIZE(mma8452_channels); |
| 366 | indio_dev->available_scan_masks = mma8452_scan_masks; | 844 | indio_dev->available_scan_masks = mma8452_scan_masks; |
| 367 | 845 | ||
| 368 | data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | | 846 | ret = mma8452_reset(client); |
| 369 | (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT); | ||
| 370 | ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1, | ||
| 371 | data->ctrl_reg1); | ||
| 372 | if (ret < 0) | 847 | if (ret < 0) |
| 373 | return ret; | 848 | return ret; |
| 374 | 849 | ||
| @@ -378,18 +853,77 @@ static int mma8452_probe(struct i2c_client *client, · 3 unmodified lines | |||
| 378 | if (ret < 0) | 853 | if (ret < 0) |
| 379 | return ret; | 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 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | 900 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
| 382 | mma8452_trigger_handler, NULL); | 901 | mma8452_trigger_handler, NULL); |
| 383 | if (ret < 0) | 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 | ret = iio_device_register(indio_dev); | 915 | ret = iio_device_register(indio_dev); |
| 387 | if (ret < 0) | 916 | if (ret < 0) |
| 388 | goto buffer_cleanup; | 917 | goto buffer_cleanup; |
| 918 | |||
| 389 | return 0; | 919 | return 0; |
| 390 | 920 | ||
| 391 | buffer_cleanup: | 921 | buffer_cleanup: |
| 392 | iio_triggered_buffer_cleanup(indio_dev); | 922 | iio_triggered_buffer_cleanup(indio_dev); |
| 923 | |||
| 924 | trigger_cleanup: | ||
| 925 | mma8452_trigger_cleanup(indio_dev); | ||
| 926 | |||
| 393 | return ret; | 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 | iio_device_unregister(indio_dev); | 934 | iio_device_unregister(indio_dev); |
| 401 | iio_triggered_buffer_cleanup(indio_dev); | 935 | iio_triggered_buffer_cleanup(indio_dev); |
| 936 | mma8452_trigger_cleanup(indio_dev); | ||
| 402 | mma8452_standby(iio_priv(indio_dev)); | 937 | mma8452_standby(iio_priv(indio_dev)); |
| 403 | 938 | ||
| 404 | return 0; | 939 | return 0; |
| @@ -374,7 +374,7 @@ EXPORT_SYMBOL(mma9551_read_status_word); · 373 unmodified lines | |||
| 374 | * @app_id: Application ID | 374 | * @app_id: Application ID |
| 375 | * @reg: Application register | 375 | * @reg: Application register |
| 376 | * @len: Length of array to read in bytes | 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 | * Read multiple configuration registers (word-sized registers). | 379 | * Read multiple configuration registers (word-sized registers). |
| 380 | * | 380 | * |
| @@ -414,7 +414,7 @@ EXPORT_SYMBOL(mma9551_read_config_words); · 33 unmodified lines | |||
| 414 | * @app_id: Application ID | 414 | * @app_id: Application ID |
| 415 | * @reg: Application register | 415 | * @reg: Application register |
| 416 | * @len: Length of array to read in bytes | 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 | * Read multiple status registers (word-sized registers). | 419 | * Read multiple status registers (word-sized registers). |
| 420 | * | 420 | * |
| @@ -454,7 +454,7 @@ EXPORT_SYMBOL(mma9551_read_status_words); · 33 unmodified lines | |||
| 454 | * @app_id: Application ID | 454 | * @app_id: Application ID |
| 455 | * @reg: Application register | 455 | * @reg: Application register |
| 456 | * @len: Length of array to write in bytes | 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 | * Write multiple configuration registers (word-sized registers). | 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 | int mma9551_app_reset(struct i2c_client *client, u32 app_mask) | 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 | MMA9551_RSC_RESET + | 804 | MMA9551_RSC_RESET + |
| 805 | MMA9551_RSC_OFFSET(app_mask), | 805 | MMA9551_RSC_OFFSET(app_mask), |
| 806 | MMA9551_RSC_VAL(app_mask)); | 806 | MMA9551_RSC_VAL(app_mask)); |
| @@ -22,7 +22,7 @@ · 21 unmodified lines | |||
| 22 | #define MMA9551_APPID_TILT 0x0B | 22 | #define MMA9551_APPID_TILT 0x0B |
| 23 | #define MMA9551_APPID_SLEEP_WAKE 0x12 | 23 | #define MMA9551_APPID_SLEEP_WAKE 0x12 |
| 24 | #define MMA9551_APPID_PEDOMETER 0x15 | 24 | #define MMA9551_APPID_PEDOMETER 0x15 |
| 25 | #define MMA9551_APPID_RCS 0x17 | 25 | #define MMA9551_APPID_RSC 0x17 |
| 26 | #define MMA9551_APPID_NONE 0xff | 26 | #define MMA9551_APPID_NONE 0xff |
| 27 | 27 | ||
| 28 | /* Reset/Suspend/Clear application app masks */ | 28 | /* Reset/Suspend/Clear application app masks */ |
| @@ -63,8 +63,8 @@ · 62 unmodified lines | |||
| 63 | #define MMA9553_MASK_STATUS_STEPCHG BIT(13) | 63 | #define MMA9553_MASK_STATUS_STEPCHG BIT(13) |
| 64 | #define MMA9553_MASK_STATUS_ACTCHG BIT(12) | 64 | #define MMA9553_MASK_STATUS_ACTCHG BIT(12) |
| 65 | #define MMA9553_MASK_STATUS_SUSP BIT(11) | 65 | #define MMA9553_MASK_STATUS_SUSP BIT(11) |
| 66 | #define MMA9553_MASK_STATUS_ACTIVITY (BIT(10) | BIT(9) | BIT(8)) | 66 | #define MMA9553_MASK_STATUS_ACTIVITY GENMASK(10, 8) |
| 67 | #define MMA9553_MASK_STATUS_VERSION 0x00FF | 67 | #define MMA9553_MASK_STATUS_VERSION GENMASK(7, 0) |
| 68 | 68 | ||
| 69 | #define MMA9553_REG_STEPCNT 0x02 | 69 | #define MMA9553_REG_STEPCNT 0x02 |
| 70 | #define MMA9553_REG_DISTANCE 0x04 | 70 | #define MMA9553_REG_DISTANCE 0x04 |
| @@ -76,14 +76,15 @@ · 5 unmodified lines | |||
| 76 | #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 | 76 | #define MMA9553_DEFAULT_GPIO_PIN mma9551_gpio6 |
| 77 | #define MMA9553_DEFAULT_GPIO_POLARITY 0 | 77 | #define MMA9553_DEFAULT_GPIO_POLARITY 0 |
| 78 | 78 | ||
| 79 | /* Bitnum used for gpio configuration = bit number in high status byte */ | 79 | /* Bitnum used for GPIO configuration = bit number in high status byte */ |
| 80 | #define STATUS_TO_BITNUM(bit) (ffs(bit) - 9) | 80 | #define MMA9553_STATUS_TO_BITNUM(bit) (ffs(bit) - 9) |
| 81 | #define MMA9553_MAX_BITNUM MMA9553_STATUS_TO_BITNUM(BIT(16)) | ||
| 81 | 82 | ||
| 82 | #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ | 83 | #define MMA9553_DEFAULT_SAMPLE_RATE 30 /* Hz */ |
| 83 | 84 | ||
| 84 | /* | 85 | /* |
| 85 | * The internal activity level must be stable for ACTTHD samples before | 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 | * level and is updated every time a step is detected or once a second | 88 | * level and is updated every time a step is detected or once a second |
| 88 | * if there are no steps. | 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 | * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. | 352 | * This bit is the logical OR of the SUSPCHG, STEPCHG, and ACTCHG flags. |
| 352 | */ | 353 | */ |
| 353 | if (activity_enabled && ev_step_detect->enabled) | 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 | else if (ev_step_detect->enabled) | 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 | else if (activity_enabled) | 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 | else /* Reset */ | 360 | else /* Reset */ |
| 360 | appid = MMA9551_APPID_NONE; | 361 | appid = MMA9551_APPID_NONE; |
| 361 | 362 | ||
| @@ -363,9 +364,12 @@ static int mma9553_conf_gpio(struct mma9553_data *data) · 1 unmodified line | |||
| 363 | return 0; | 364 | return 0; |
| 364 | 365 | ||
| 365 | /* Save initial values for activity and stepcnt */ | 366 | /* Save initial values for activity and stepcnt */ |
| 366 | if (activity_enabled || ev_step_detect->enabled) | 367 | if (activity_enabled || ev_step_detect->enabled) { |
| 367 | mma9553_read_activity_stepcnt(data, &data->activity, | 368 | ret = mma9553_read_activity_stepcnt(data, &data->activity, |
| 368 | &data->stepcnt); | 369 | &data->stepcnt); |
| 370 | if (ret < 0) | ||
| 371 | return ret; | ||
| 372 | } | ||
| 369 | 373 | ||
| 370 | ret = mma9551_gpio_config(data->client, | 374 | ret = mma9551_gpio_config(data->client, |
| 371 | MMA9553_DEFAULT_GPIO_PIN, | 375 | MMA9553_DEFAULT_GPIO_PIN, |
| @@ -396,13 +400,13 @@ static int mma9553_init(struct mma9553_data *data) · 24 unmodified lines | |||
| 396 | sizeof(data->conf), (u16 *) &data->conf); | 400 | sizeof(data->conf), (u16 *) &data->conf); |
| 397 | if (ret < 0) { | 401 | if (ret < 0) { |
| 398 | dev_err(&data->client->dev, | 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 | return ret; | 404 | return ret; |
| 401 | } | 405 | } |
| 402 | 406 | ||
| 403 | 407 | ||
| 404 | /* Reset gpio */ | 408 | /* Reset GPIO */ |
| 405 | data->gpio_bitnum = -1; | 409 | data->gpio_bitnum = MMA9553_MAX_BITNUM; |
| 406 | ret = mma9553_conf_gpio(data); | 410 | ret = mma9553_conf_gpio(data); |
| 407 | if (ret < 0) | 411 | if (ret < 0) |
| 408 | return ret; | 412 | return ret; |
| @@ -436,6 +440,32 @@ static int mma9553_init(struct mma9553_data *data) · 27 unmodified lines | |||
| 436 | return mma9551_set_device_state(data->client, true); | 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 | static int mma9553_read_raw(struct iio_dev *indio_dev, | 469 | static int mma9553_read_raw(struct iio_dev *indio_dev, |
| 440 | struct iio_chan_spec const *chan, | 470 | struct iio_chan_spec const *chan, |
| 441 | int *val, int *val2, long mask) | 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 | int ret; | 474 | int ret; |
| 445 | u16 tmp; | 475 | u16 tmp; |
| 446 | u8 activity; | 476 | u8 activity; |
| 447 | bool powered_on; | ||
| 448 | 477 | ||
| 449 | switch (mask) { | 478 | switch (mask) { |
| 450 | case IIO_CHAN_INFO_PROCESSED: | 479 | case IIO_CHAN_INFO_PROCESSED: |
| 451 | switch (chan->type) { | 480 | switch (chan->type) { |
| 452 | case IIO_STEPS: | 481 | case IIO_STEPS: |
| 453 | /* | 482 | ret = mma9553_read_status_word(data, |
| 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, | ||
| 469 | MMA9553_REG_STEPCNT, | 483 | MMA9553_REG_STEPCNT, |
| 470 | &tmp); | 484 | &tmp); |
| 471 | mutex_unlock(&data->mutex); | ||
| 472 | if (ret < 0) | 485 | if (ret < 0) |
| 473 | return ret; | 486 | return ret; |
| 474 | *val = tmp; | 487 | *val = tmp; |
| 475 | return IIO_VAL_INT; | 488 | return IIO_VAL_INT; |
| 476 | case IIO_DISTANCE: | 489 | case IIO_DISTANCE: |
| 477 | powered_on = | 490 | ret = mma9553_read_status_word(data, |
| 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, | ||
| 488 | MMA9553_REG_DISTANCE, | 491 | MMA9553_REG_DISTANCE, |
| 489 | &tmp); | 492 | &tmp); |
| 490 | mutex_unlock(&data->mutex); | ||
| 491 | if (ret < 0) | 493 | if (ret < 0) |
| 492 | return ret; | 494 | return ret; |
| 493 | *val = tmp; | 495 | *val = tmp; |
| 494 | return IIO_VAL_INT; | 496 | return IIO_VAL_INT; |
| 495 | case IIO_ACTIVITY: | 497 | case IIO_ACTIVITY: |
| 496 | powered_on = | 498 | ret = mma9553_read_status_word(data, |
| 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, | ||
| 507 | MMA9553_REG_STATUS, | 499 | MMA9553_REG_STATUS, |
| 508 | &tmp); | 500 | &tmp); |
| 509 | mutex_unlock(&data->mutex); | ||
| 510 | if (ret < 0) | 501 | if (ret < 0) |
| 511 | return ret; | 502 | return ret; |
| 512 | 503 | ||
| @@ -531,38 +522,17 @@ static int mma9553_read_raw(struct iio_dev *indio_dev, · 18 unmodified lines | |||
| 531 | case IIO_VELOCITY: /* m/h */ | 522 | case IIO_VELOCITY: /* m/h */ |
| 532 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) | 523 | if (chan->channel2 != IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z) |
| 533 | return -EINVAL; | 524 | return -EINVAL; |
| 534 | powered_on = | 525 | ret = mma9553_read_status_word(data, |
| 535 | mma9553_is_any_event_enabled(data, false, 0) || | 526 | MMA9553_REG_SPEED, |
| 536 | data->stepcnt_enabled; | 527 | &tmp); |
| 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); | ||
| 547 | if (ret < 0) | 528 | if (ret < 0) |
| 548 | return ret; | 529 | return ret; |
| 549 | *val = tmp; | 530 | *val = tmp; |
| 550 | return IIO_VAL_INT; | 531 | return IIO_VAL_INT; |
| 551 | case IIO_ENERGY: /* Cal or kcal */ | 532 | case IIO_ENERGY: /* Cal or kcal */ |
| 552 | powered_on = | 533 | ret = mma9553_read_status_word(data, |
| 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, | ||
| 563 | MMA9553_REG_CALORIES, | 534 | MMA9553_REG_CALORIES, |
| 564 | &tmp); | 535 | &tmp); |
| 565 | mutex_unlock(&data->mutex); | ||
| 566 | if (ret < 0) | 536 | if (ret < 0) |
| 567 | return ret; | 537 | return ret; |
| 568 | *val = tmp; | 538 | *val = tmp; |
| @@ -789,7 +759,7 @@ static int mma9553_write_event_config(struct iio_dev *indio_dev, · 220 unmodified lines | |||
| 789 | 759 | ||
| 790 | mutex_unlock(&data->mutex); | 760 | mutex_unlock(&data->mutex); |
| 791 | 761 | ||
| 792 | return ret; | 762 | return 0; |
| 793 | 763 | ||
| 794 | err_conf_gpio: | 764 | err_conf_gpio: |
| 795 | if (state) { | 765 | if (state) { |
| @@ -897,7 +867,7 @@ static int mma9553_get_calibgender_mode(struct iio_dev *indio_dev, · 101 unmodified lines | |||
| 897 | gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); | 867 | gender = mma9553_get_bits(data->conf.filter, MMA9553_MASK_CONF_MALE); |
| 898 | /* | 868 | /* |
| 899 | * HW expects 0 for female and 1 for male, | 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 | return !gender; | 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 | static const struct iio_enum mma9553_calibgender_enum = { | 919 | static const struct iio_enum mma9553_calibgender_enum = { |
| 950 | .items = calibgender_modes, | 920 | .items = mma9553_calibgender_modes, |
| 951 | .num_items = ARRAY_SIZE(calibgender_modes), | 921 | .num_items = ARRAY_SIZE(mma9553_calibgender_modes), |
| 952 | .get = mma9553_get_calibgender_mode, | 922 | .get = mma9553_get_calibgender_mode, |
| 953 | .set = mma9553_set_calibgender_mode, | 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 | dev = &client->dev; | 1081 | dev = &client->dev; |
| 1112 | 1082 | ||
| 1113 | /* data ready gpio interrupt pin */ | 1083 | /* data ready GPIO interrupt pin */ |
| 1114 | gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN); | 1084 | gpio = devm_gpiod_get_index(dev, MMA9553_GPIO_NAME, 0, GPIOD_IN); |
| 1115 | if (IS_ERR(gpio)) { | 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 | return PTR_ERR(gpio); | 1087 | return PTR_ERR(gpio); |
| 1118 | } | 1088 | } |
| 1119 | 1089 | ||
| 1120 | ret = gpiod_to_irq(gpio); | 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 | return ret; | 1094 | return ret; |
| 1125 | } | 1095 | } |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | |||
| 20 | #define LSM330D_ACCEL_DEV_NAME "lsm330d_accel" | 20 | #define LSM330D_ACCEL_DEV_NAME "lsm330d_accel" |
| 21 | #define LSM330DL_ACCEL_DEV_NAME "lsm330dl_accel" | 21 | #define LSM330DL_ACCEL_DEV_NAME "lsm330dl_accel" |
| 22 | #define LSM330DLC_ACCEL_DEV_NAME "lsm330dlc_accel" | 22 | #define LSM330DLC_ACCEL_DEV_NAME "lsm330dlc_accel" |
| 23 | #define LIS331DL_ACCEL_DEV_NAME "lis331dl_accel" | ||
| 23 | #define LIS331DLH_ACCEL_DEV_NAME "lis331dlh" | 24 | #define LIS331DLH_ACCEL_DEV_NAME "lis331dlh" |
| 24 | #define LSM303DL_ACCEL_DEV_NAME "lsm303dl_accel" | 25 | #define LSM303DL_ACCEL_DEV_NAME "lsm303dl_accel" |
| 25 | #define LSM303DLH_ACCEL_DEV_NAME "lsm303dlh_accel" | 26 | #define LSM303DLH_ACCEL_DEV_NAME "lsm303dlh_accel" |
| @@ -153,6 +153,44 @@ · 152 unmodified lines | |||
| 153 | #define ST_ACCEL_4_IG1_EN_MASK 0x08 | 153 | #define ST_ACCEL_4_IG1_EN_MASK 0x08 |
| 154 | #define ST_ACCEL_4_MULTIREAD_BIT true | 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 | static const struct iio_chan_spec st_accel_12bit_channels[] = { | 194 | static const struct iio_chan_spec st_accel_12bit_channels[] = { |
| 157 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, | 195 | ST_SENSORS_LSM_CHANNELS(IIO_ACCEL, |
| 158 | BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), | 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 | .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT, | 492 | .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT, |
| 455 | .bootime = 2, /* guess */ | 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 | static int st_accel_read_raw(struct iio_dev *indio_dev, | 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 | .compatible = "st,lsm330dlc-accel", | 48 | .compatible = "st,lsm330dlc-accel", |
| 49 | .data = LSM330DLC_ACCEL_DEV_NAME, | 49 | .data = LSM330DLC_ACCEL_DEV_NAME, |
| 50 | }, | 50 | }, |
| 51 | { | ||
| 52 | .compatible = "st,lis331dl-accel", | ||
| 53 | .data = LIS331DL_ACCEL_DEV_NAME, | ||
| 54 | }, | ||
| 51 | { | 55 | { |
| 52 | .compatible = "st,lis331dlh-accel", | 56 | .compatible = "st,lis331dlh-accel", |
| 53 | .data = LIS331DLH_ACCEL_DEV_NAME, | 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 | device. Depending on platform configuration, this general purpose ADC can | 135 | device. Depending on platform configuration, this general purpose ADC can |
| 136 | be used for sampling sensors such as thermal resistors. | 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 | config DA9150_GPADC | 145 | config DA9150_GPADC |
| 139 | tristate "Dialog DA9150 GPADC driver support" | 146 | tristate "Dialog DA9150 GPADC driver support" |
| 140 | depends on MFD_DA9150 | 147 | depends on MFD_DA9150 |
| @@ -285,11 +292,11 @@ config TI_ADC081C · 144 unmodified lines | |||
| 285 | called ti-adc081c. | 292 | called ti-adc081c. |
| 286 | 293 | ||
| 287 | config TI_ADC128S052 | 294 | config TI_ADC128S052 |
| 288 | tristate "Texas Instruments ADC128S052" | 295 | tristate "Texas Instruments ADC128S052/ADC122S021" |
| 289 | depends on SPI | 296 | depends on SPI |
| 290 | help | 297 | help |
| 291 | If you say yes here you get support for Texas Instruments ADC128S052 | 298 | If you say yes here you get support for Texas Instruments ADC128S052 |
| 292 | chip. | 299 | and ADC122S021 chips. |
| 293 | 300 | ||
| 294 | This driver can also be built as a module. If so, the module will be | 301 | This driver can also be built as a module. If so, the module will be |
| 295 | called ti-adc128s052. | 302 | called ti-adc128s052. |
| @@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o · 14 unmodified lines | |||
| 15 | obj-$(CONFIG_AD799X) += ad799x.o | 15 | obj-$(CONFIG_AD799X) += ad799x.o |
| 16 | obj-$(CONFIG_AT91_ADC) += at91_adc.o | 16 | obj-$(CONFIG_AT91_ADC) += at91_adc.o |
| 17 | obj-$(CONFIG_AXP288_ADC) += axp288_adc.o | 17 | obj-$(CONFIG_AXP288_ADC) += axp288_adc.o |
| 18 | obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o | ||
| 18 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o | 19 | obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o |
| 19 | obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o | 20 | obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o |
| 20 | obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o | 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 | return 0; | 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 | { .name = "axp288_adc" }, | 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 | * Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com> | 2 | * Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com> |
| 3 | * | 3 | * |
| 4 | * Driver for Texas Instruments' ADC128S052 ADC chip. | 4 | * Driver for Texas Instruments' ADC128S052 and ADC122S021 ADC chip. |
| 5 | * Datasheet can be found here: | 5 | * Datasheets can be found here: |
| 6 | * http://www.ti.com/lit/ds/symlink/adc128s052.pdf | 6 | * http://www.ti.com/lit/ds/symlink/adc128s052.pdf |
| 7 | * http://www.ti.com/lit/ds/symlink/adc122s021.pdf | ||
| 7 | * | 8 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
| @@ -16,6 +17,11 @@ · 6 unmodified lines | |||
| 16 | #include <linux/iio/iio.h> | 17 | #include <linux/iio/iio.h> |
| 17 | #include <linux/regulator/consumer.h> | 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 | struct adc128 { | 25 | struct adc128 { |
| 20 | struct spi_device *spi; | 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 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \ | 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 | ADC128_VOLTAGE_CHANNEL(0), | 102 | ADC128_VOLTAGE_CHANNEL(0), |
| 97 | ADC128_VOLTAGE_CHANNEL(1), | 103 | ADC128_VOLTAGE_CHANNEL(1), |
| 98 | ADC128_VOLTAGE_CHANNEL(2), | 104 | ADC128_VOLTAGE_CHANNEL(2), |
| @@ -103,6 +109,16 @@ static const struct iio_chan_spec adc128_channels[] = { · 4 unmodified lines | |||
| 103 | ADC128_VOLTAGE_CHANNEL(7), | 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 | static const struct iio_info adc128_info = { | 122 | static const struct iio_info adc128_info = { |
| 107 | .read_raw = adc128_read_raw, | 123 | .read_raw = adc128_read_raw, |
| 108 | .driver_module = THIS_MODULE, | 124 | .driver_module = THIS_MODULE, |
| @@ -112,6 +128,7 @@ static int adc128_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 112 | { | 128 | { |
| 113 | struct iio_dev *indio_dev; | 129 | struct iio_dev *indio_dev; |
| 114 | struct adc128 *adc; | 130 | struct adc128 *adc; |
| 131 | int config = spi_get_device_id(spi)->driver_data; | ||
| 115 | int ret; | 132 | int ret; |
| 116 | 133 | ||
| 117 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc)); | 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 | indio_dev->modes = INDIO_DIRECT_MODE; | 145 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 129 | indio_dev->info = &adc128_info; | 146 | indio_dev->info = &adc128_info; |
| 130 | 147 | ||
| 131 | indio_dev->channels = adc128_channels; | 148 | indio_dev->channels = adc128_config[config].channels; |
| 132 | indio_dev->num_channels = ARRAY_SIZE(adc128_channels); | 149 | indio_dev->num_channels = adc128_config[config].num_channels; |
| 133 | 150 | ||
| 134 | adc->reg = devm_regulator_get(&spi->dev, "vref"); | 151 | adc->reg = devm_regulator_get(&spi->dev, "vref"); |
| 135 | if (IS_ERR(adc->reg)) | 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 | static const struct spi_device_id adc128_id[] = { | 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 | MODULE_DEVICE_TABLE(spi, adc128_id); | 182 | MODULE_DEVICE_TABLE(spi, adc128_id); |
| @@ -37,6 +37,7 @@ struct tiadc_device { · 36 unmodified lines | |||
| 37 | u8 channel_step[8]; | 37 | u8 channel_step[8]; |
| 38 | int buffer_en_ch_steps; | 38 | int buffer_en_ch_steps; |
| 39 | u16 data[8]; | 39 | u16 data[8]; |
| 40 | u32 open_delay[8], sample_delay[8], step_avg[8]; | ||
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 42 | static unsigned int tiadc_readl(struct tiadc_device *adc, unsigned int reg) | 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 | static void tiadc_step_config(struct iio_dev *indio_dev) | 86 | static void tiadc_step_config(struct iio_dev *indio_dev) |
| 86 | { | 87 | { |
| 87 | struct tiadc_device *adc_dev = iio_priv(indio_dev); | 88 | struct tiadc_device *adc_dev = iio_priv(indio_dev); |
| 89 | struct device *dev = adc_dev->mfd_tscadc->dev; | ||
| 88 | unsigned int stepconfig; | 90 | unsigned int stepconfig; |
| 89 | int i, steps = 0; | 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 | * needs to be given to ADC to digitalize data. | 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 | for (i = 0; i < adc_dev->channels; i++) { | 104 | for (i = 0; i < adc_dev->channels; i++) { |
| 108 | int chan; | 105 | int chan; |
| 109 | 106 | ||
| 110 | chan = adc_dev->channel_line[i]; | 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 | tiadc_writel(adc_dev, REG_STEPCONFIG(steps), | 125 | tiadc_writel(adc_dev, REG_STEPCONFIG(steps), |
| 112 | stepconfig | STEPCONFIG_INP(chan)); | 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 | tiadc_writel(adc_dev, REG_STEPDELAY(steps), | 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 | adc_dev->channel_step[i] = steps; | 144 | adc_dev->channel_step[i] = steps; |
| 116 | steps++; | 145 | steps++; |
| 117 | } | 146 | } |
| @@ -395,16 +424,43 @@ static const struct iio_info tiadc_info = { · 277 unmodified lines | |||
| 395 | .driver_module = THIS_MODULE, | 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 | static int tiadc_probe(struct platform_device *pdev) | 458 | static int tiadc_probe(struct platform_device *pdev) |
| 399 | { | 459 | { |
| 400 | struct iio_dev *indio_dev; | 460 | struct iio_dev *indio_dev; |
| 401 | struct tiadc_device *adc_dev; | 461 | struct tiadc_device *adc_dev; |
| 402 | struct device_node *node = pdev->dev.of_node; | 462 | struct device_node *node = pdev->dev.of_node; |
| 403 | struct property *prop; | ||
| 404 | const __be32 *cur; | ||
| 405 | int err; | 463 | int err; |
| 406 | u32 val; | ||
| 407 | int channels = 0; | ||
| 408 | 464 | ||
| 409 | if (!node) { | 465 | if (!node) { |
| 410 | dev_err(&pdev->dev, "Could not find valid DT data.\n"); | 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 | adc_dev = iio_priv(indio_dev); | 476 | adc_dev = iio_priv(indio_dev); |
| 421 | 477 | ||
| 422 | adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); | 478 | adc_dev->mfd_tscadc = ti_tscadc_dev_get(pdev); |
| 423 | 479 | tiadc_parse_dt(pdev, adc_dev); | |
| 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; | ||
| 429 | 480 | ||
| 430 | indio_dev->dev.parent = &pdev->dev; | 481 | indio_dev->dev.parent = &pdev->dev; |
| 431 | indio_dev->name = dev_name(&pdev->dev); | 482 | indio_dev->name = dev_name(&pdev->dev); |
| @@ -235,7 +235,7 @@ static int twl4030battery_temperature(int raw_volt) · 234 unmodified lines | |||
| 235 | if (ret < 0) | 235 | if (ret < 0) |
| 236 | return ret; | 236 | return ret; |
| 237 | 237 | ||
| 238 | curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10; | 238 | curr = ((val & TWL4030_BCI_ITHSENS) + 1) * 10; |
| 239 | /* Getting and calculating the thermistor resistance in ohms */ | 239 | /* Getting and calculating the thermistor resistance in ohms */ |
| 240 | res = volt * 1000 / curr; | 240 | res = volt * 1000 / curr; |
| 241 | /* calculating temperature */ | 241 | /* calculating temperature */ |
| @@ -662,10 +662,8 @@ EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion); · 420 unmodified lines | |||
| 662 | * | 662 | * |
| 663 | * @madc: pointer to twl4030_madc_data struct | 663 | * @madc: pointer to twl4030_madc_data struct |
| 664 | * @chan: can be one of the two values: | 664 | * @chan: can be one of the two values: |
| 665 | * TWL4030_BCI_ITHEN | 665 | * 0 - Enables bias current for main battery type reading |
| 666 | * Enables bias current for main battery type reading | 666 | * 1 - Enables bias current for main battery temperature sensing |
| 667 | * TWL4030_BCI_TYPEN | ||
| 668 | * Enables bias current for main battery temperature sensing | ||
| 669 | * @on: enable or disable chan. | 667 | * @on: enable or disable chan. |
| 670 | * | 668 | * |
| 671 | * Function to enable or disable bias current for | 669 | * Function to enable or disable bias current for |
| @@ -118,15 +118,21 @@ enum average_sel { · 117 unmodified lines | |||
| 118 | VF610_ADC_SAMPLE_32, | 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 | struct vf610_adc_feature { | 127 | struct vf610_adc_feature { |
| 122 | enum clk_sel clk_sel; | 128 | enum clk_sel clk_sel; |
| 123 | enum vol_ref vol_ref; | 129 | enum vol_ref vol_ref; |
| 130 | enum conversion_mode_sel conv_mode; | ||
| 124 | 131 | ||
| 125 | int clk_div; | 132 | int clk_div; |
| 126 | int sample_rate; | 133 | int sample_rate; |
| 127 | int res_mode; | 134 | int res_mode; |
| 128 | 135 | ||
| 129 | bool lpm; | ||
| 130 | bool calibration; | 136 | bool calibration; |
| 131 | bool ovwren; | 137 | bool ovwren; |
| 132 | }; | 138 | }; |
| @@ -139,6 +145,8 @@ struct vf610_adc { · 6 unmodified lines | |||
| 139 | u32 vref_uv; | 145 | u32 vref_uv; |
| 140 | u32 value; | 146 | u32 value; |
| 141 | struct regulator *vref; | 147 | struct regulator *vref; |
| 148 | |||
| 149 | u32 max_adck_rate[3]; | ||
| 142 | struct vf610_adc_feature adc_feature; | 150 | struct vf610_adc_feature adc_feature; |
| 143 | 151 | ||
| 144 | u32 sample_freq_avail[5]; | 152 | u32 sample_freq_avail[5]; |
| @@ -148,46 +156,22 @@ struct vf610_adc { · 3 unmodified lines | |||
| 148 | 156 | ||
| 149 | static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; | 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 | static inline void vf610_adc_calculate_rates(struct vf610_adc *info) | 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 | unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk); | 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 | * Calculate ADC sample frequencies | 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 | adc_feature->res_mode = 12; | 204 | adc_feature->res_mode = 12; |
| 221 | adc_feature->sample_rate = 1; | 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 */ | 207 | adc_feature->conv_mode = VF610_ADC_CONV_LOW_POWER; |
| 225 | adc_feature->clk_div = 8; | ||
| 226 | 208 | ||
| 227 | vf610_adc_calculate_rates(info); | 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 | cfg_data = readl(info->regs + VF610_REG_ADC_CFG); | 286 | cfg_data = readl(info->regs + VF610_REG_ADC_CFG); |
| 305 | 287 | ||
| 306 | cfg_data &= ~VF610_ADC_ADLPC_EN; | 288 | cfg_data &= ~VF610_ADC_ADLPC_EN; |
| 307 | if (adc_feature->lpm) | 289 | if (adc_feature->conv_mode == VF610_ADC_CONV_LOW_POWER) |
| 308 | cfg_data |= VF610_ADC_ADLPC_EN; | 290 | cfg_data |= VF610_ADC_ADLPC_EN; |
| 309 | 291 | ||
| 310 | cfg_data &= ~VF610_ADC_ADHSC_EN; | 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 | writel(cfg_data, info->regs + VF610_REG_ADC_CFG); | 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 | vf610_adc_cfg_set(info); | 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 | static int vf610_adc_read_data(struct vf610_adc *info) | 471 | static int vf610_adc_read_data(struct vf610_adc *info) |
| 413 | { | 472 | { |
| 414 | int result; | 473 | int result; |
| @@ -651,6 +710,9 @@ static int vf610_adc_probe(struct platform_device *pdev) · 236 unmodified lines | |||
| 651 | 710 | ||
| 652 | info->vref_uv = regulator_get_voltage(info->vref); | 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 | platform_set_drvdata(pdev, indio_dev); | 716 | platform_set_drvdata(pdev, indio_dev); |
| 655 | 717 | ||
| 656 | init_completion(&info->completion); | 718 | init_completion(&info->completion); |
| @@ -33,6 +33,8 @@ static void iio_buffer_cb_release(struct iio_buffer *buffer) · 32 unmodified lines | |||
| 33 | static const struct iio_buffer_access_funcs iio_cb_access = { | 33 | static const struct iio_buffer_access_funcs iio_cb_access = { |
| 34 | .store_to = &iio_buffer_cb_store_to, | 34 | .store_to = &iio_buffer_cb_store_to, |
| 35 | .release = &iio_buffer_cb_release, | 35 | .release = &iio_buffer_cb_release, |
| 36 | |||
| 37 | .modes = INDIO_BUFFER_SOFTWARE | INDIO_BUFFER_TRIGGERED, | ||
| 36 | }; | 38 | }; |
| 37 | 39 | ||
| 38 | struct iio_cb_buffer *iio_channel_get_all_cb(struct device *dev, | 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 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 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 | switch (pdata->drdy_int_pin) { | 258 | switch (pdata->drdy_int_pin) { |
| 249 | case 1: | 259 | case 1: |
| 250 | if (sdata->sensor_settings->drdy_irq.mask_int1 == 0) { | 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 | if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2)) | 295 | if (!of_property_read_u32(np, "st,drdy-int-pin", &val) && (val <= 2)) |
| 286 | pdata->drdy_int_pin = (u8) val; | 296 | pdata->drdy_int_pin = (u8) val; |
| 287 | else | 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 | return pdata; | 300 | return pdata; |
| 291 | } | 301 | } |
| @@ -332,11 +342,13 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, · 40 unmodified lines | |||
| 332 | return err; | 342 | return err; |
| 333 | 343 | ||
| 334 | /* set BDU */ | 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 | sdata->sensor_settings->bdu.addr, | 347 | sdata->sensor_settings->bdu.addr, |
| 337 | sdata->sensor_settings->bdu.mask, true); | 348 | sdata->sensor_settings->bdu.mask, true); |
| 338 | if (err < 0) | 349 | if (err < 0) |
| 339 | return err; | 350 | return err; |
| 351 | } | ||
| 340 | 352 | ||
| 341 | err = st_sensors_set_axis_enable(indio_dev, ST_SENSORS_ENABLE_ALL_AXIS); | 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 | if (err < 0) | 431 | if (err < 0) |
| 420 | goto st_sensors_free_memory; | 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 | *data = (s16)get_unaligned_le16(outdata); | 437 | *data = (s16)get_unaligned_le16(outdata); |
| 424 | else if (byte_for_channel == 3) | 438 | else if (byte_for_channel == 3) |
| 425 | *data = (s32)st_sensors_get_unaligned_le24(outdata); | 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 | break; | 503 | break; |
| 490 | } | 504 | } |
| 491 | if (n == ARRAY_SIZE(sensor_settings[i].sensors_supported)) { | 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 | goto sensor_name_mismatch; | 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 | IRQF_TRIGGER_RISING, | 37 | IRQF_TRIGGER_RISING, |
| 38 | sdata->trig->name, | 38 | sdata->trig->name, |
| 39 | sdata->trig); | 39 | sdata->trig); |
| 40 | if (err) | 40 | if (err) { |
| 41 | dev_err(&indio_dev->dev, "failed to request trigger IRQ.\n"); | ||
| 41 | goto request_irq_error; | 42 | goto request_irq_error; |
| 43 | } | ||
| 42 | 44 | ||
| 43 | iio_trigger_set_drvdata(sdata->trig, indio_dev); | 45 | iio_trigger_set_drvdata(sdata->trig, indio_dev); |
| 44 | sdata->trig->ops = trigger_ops; | 46 | sdata->trig->ops = trigger_ops; |
| @@ -142,6 +142,16 @@ config AD7303 · 141 unmodified lines | |||
| 142 | To compile this driver as module choose M here: the module will be called | 142 | To compile this driver as module choose M here: the module will be called |
| 143 | ad7303. | 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 | config MAX517 | 155 | config MAX517 |
| 146 | tristate "Maxim MAX517/518/519/520/521 DAC driver" | 156 | tristate "Maxim MAX517/518/519/520/521 DAC driver" |
| 147 | depends on I2C | 157 | depends on I2C |
| @@ -16,6 +16,7 @@ obj-$(CONFIG_AD5764) += ad5764.o · 15 unmodified lines | |||
| 16 | obj-$(CONFIG_AD5791) += ad5791.o | 16 | obj-$(CONFIG_AD5791) += ad5791.o |
| 17 | obj-$(CONFIG_AD5686) += ad5686.o | 17 | obj-$(CONFIG_AD5686) += ad5686.o |
| 18 | obj-$(CONFIG_AD7303) += ad7303.o | 18 | obj-$(CONFIG_AD7303) += ad7303.o |
| 19 | obj-$(CONFIG_M62332) += m62332.o | ||
| 19 | obj-$(CONFIG_MAX517) += max517.o | 20 | obj-$(CONFIG_MAX517) += max517.o |
| 20 | obj-$(CONFIG_MAX5821) += max5821.o | 21 | obj-$(CONFIG_MAX5821) += max5821.o |
| 21 | obj-$(CONFIG_MCP4725) += mcp4725.o | 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 | int slope_thres; | 108 | int slope_thres; |
| 109 | bool dready_trigger_on; | 109 | bool dready_trigger_on; |
| 110 | bool motion_trigger_on; | 110 | bool motion_trigger_on; |
| 111 | int64_t timestamp; | ||
| 112 | }; | 111 | }; |
| 113 | 112 | ||
| 114 | enum bmg160_axis { | 113 | enum bmg160_axis { |
| @@ -738,17 +737,6 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev, · 623 unmodified lines | |||
| 738 | return 0; | 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 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000"); | 740 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("100 200 400 1000 2000"); |
| 753 | 741 | ||
| 754 | static IIO_CONST_ATTR(in_anglvel_scale_available, | 742 | static IIO_CONST_ATTR(in_anglvel_scale_available, |
| @@ -810,7 +798,6 @@ static const struct iio_info bmg160_info = { · 55 unmodified lines | |||
| 810 | .write_event_value = bmg160_write_event, | 798 | .write_event_value = bmg160_write_event, |
| 811 | .write_event_config = bmg160_write_event_config, | 799 | .write_event_config = bmg160_write_event_config, |
| 812 | .read_event_config = bmg160_read_event_config, | 800 | .read_event_config = bmg160_read_event_config, |
| 813 | .validate_trigger = bmg160_validate_trigger, | ||
| 814 | .driver_module = THIS_MODULE, | 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 | mutex_unlock(&data->mutex); | 822 | mutex_unlock(&data->mutex); |
| 836 | 823 | ||
| 837 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, | 824 | iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, |
| 838 | data->timestamp); | 825 | pf->timestamp); |
| 839 | err: | 826 | err: |
| 840 | iio_trigger_notify_done(indio_dev->trig); | 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 | IIO_MOD_X, | 925 | IIO_MOD_X, |
| 939 | IIO_EV_TYPE_ROC, | 926 | IIO_EV_TYPE_ROC, |
| 940 | dir), | 927 | dir), |
| 941 | data->timestamp); | 928 | iio_get_time_ns()); |
| 942 | if (ret & BMG160_ANY_MOTION_BIT_Y) | 929 | if (ret & BMG160_ANY_MOTION_BIT_Y) |
| 943 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, | 930 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, |
| 944 | 0, | 931 | 0, |
| 945 | IIO_MOD_Y, | 932 | IIO_MOD_Y, |
| 946 | IIO_EV_TYPE_ROC, | 933 | IIO_EV_TYPE_ROC, |
| 947 | dir), | 934 | dir), |
| 948 | data->timestamp); | 935 | iio_get_time_ns()); |
| 949 | if (ret & BMG160_ANY_MOTION_BIT_Z) | 936 | if (ret & BMG160_ANY_MOTION_BIT_Z) |
| 950 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, | 937 | iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ANGL_VEL, |
| 951 | 0, | 938 | 0, |
| 952 | IIO_MOD_Z, | 939 | IIO_MOD_Z, |
| 953 | IIO_EV_TYPE_ROC, | 940 | IIO_EV_TYPE_ROC, |
| 954 | dir), | 941 | dir), |
| 955 | data->timestamp); | 942 | iio_get_time_ns()); |
| 956 | 943 | ||
| 957 | ack_intr_status: | 944 | ack_intr_status: |
| 958 | if (!data->dready_trigger_on) { | 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 | struct iio_dev *indio_dev = private; | 960 | struct iio_dev *indio_dev = private; |
| 974 | struct bmg160_data *data = iio_priv(indio_dev); | 961 | struct bmg160_data *data = iio_priv(indio_dev); |
| 975 | 962 | ||
| 976 | data->timestamp = iio_get_time_ns(); | ||
| 977 | |||
| 978 | if (data->dready_trigger_on) | 963 | if (data->dready_trigger_on) |
| 979 | iio_trigger_poll(data->dready_trig); | 964 | iio_trigger_poll(data->dready_trig); |
| 980 | else if (data->motion_trigger_on) | 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 | static int bmg160_gpio_probe(struct i2c_client *client, | 996 | static int bmg160_gpio_probe(struct i2c_client *client, |
| 991 | struct bmg160_data *data) | 997 | struct bmg160_data *data) |
| 992 | 998 | ||
| @@ -1103,16 +1109,16 @@ static int bmg160_probe(struct i2c_client *client, · 110 unmodified lines | |||
| 1103 | data->motion_trig = NULL; | 1109 | data->motion_trig = NULL; |
| 1104 | goto err_trigger_unregister; | 1110 | goto err_trigger_unregister; |
| 1105 | } | 1111 | } |
| 1112 | } | ||
| 1106 | 1113 | ||
| 1107 | ret = iio_triggered_buffer_setup(indio_dev, | 1114 | ret = iio_triggered_buffer_setup(indio_dev, |
| 1108 | NULL, | 1115 | iio_pollfunc_store_time, |
| 1109 | bmg160_trigger_handler, | 1116 | bmg160_trigger_handler, |
| 1110 | NULL); | 1117 | &bmg160_buffer_setup_ops); |
| 1111 | if (ret < 0) { | 1118 | if (ret < 0) { |
| 1112 | dev_err(&client->dev, | 1119 | dev_err(&client->dev, |
| 1113 | "iio triggered buffer setup failed\n"); | 1120 | "iio triggered buffer setup failed\n"); |
| 1114 | goto err_trigger_unregister; | 1121 | goto err_trigger_unregister; |
| 1115 | } | ||
| 1116 | } | 1122 | } |
| 1117 | 1123 | ||
| 1118 | ret = iio_device_register(indio_dev); | 1124 | ret = iio_device_register(indio_dev); |
| @@ -1135,8 +1141,7 @@ static int bmg160_probe(struct i2c_client *client, · 16 unmodified lines | |||
| 1135 | err_iio_unregister: | 1141 | err_iio_unregister: |
| 1136 | iio_device_unregister(indio_dev); | 1142 | iio_device_unregister(indio_dev); |
| 1137 | err_buffer_cleanup: | 1143 | err_buffer_cleanup: |
| 1138 | if (data->dready_trig) | 1144 | iio_triggered_buffer_cleanup(indio_dev); |
| 1139 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 1140 | err_trigger_unregister: | 1145 | err_trigger_unregister: |
| 1141 | if (data->dready_trig) | 1146 | if (data->dready_trig) |
| 1142 | iio_trigger_unregister(data->dready_trig); | 1147 | iio_trigger_unregister(data->dready_trig); |
| @@ -1156,9 +1161,9 @@ static int bmg160_remove(struct i2c_client *client) · 13 unmodified lines | |||
| 1156 | pm_runtime_put_noidle(&client->dev); | 1161 | pm_runtime_put_noidle(&client->dev); |
| 1157 | 1162 | ||
| 1158 | iio_device_unregister(indio_dev); | 1163 | iio_device_unregister(indio_dev); |
| 1164 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 1159 | 1165 | ||
| 1160 | if (data->dready_trig) { | 1166 | if (data->dready_trig) { |
| 1161 | iio_triggered_buffer_cleanup(indio_dev); | ||
| 1162 | iio_trigger_unregister(data->dready_trig); | 1167 | iio_trigger_unregister(data->dready_trig); |
| 1163 | iio_trigger_unregister(data->motion_trig); | 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 | struct iio_dev *indio_dev; | 298 | struct iio_dev *indio_dev; |
| 299 | struct gyro_3d_state *gyro_state; | 299 | struct gyro_3d_state *gyro_state; |
| 300 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 300 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 301 | struct iio_chan_spec *channels; | ||
| 302 | 301 | ||
| 303 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state)); | 302 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state)); |
| 304 | if (!indio_dev) | 303 | if (!indio_dev) |
| @@ -317,21 +316,21 @@ static int hid_gyro_3d_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 317 | return ret; | 316 | return ret; |
| 318 | } | 317 | } |
| 319 | 318 | ||
| 320 | channels = kmemdup(gyro_3d_channels, sizeof(gyro_3d_channels), | 319 | indio_dev->channels = kmemdup(gyro_3d_channels, |
| 321 | GFP_KERNEL); | 320 | sizeof(gyro_3d_channels), GFP_KERNEL); |
| 322 | if (!channels) { | 321 | if (!indio_dev->channels) { |
| 323 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | 322 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 324 | return -ENOMEM; | 323 | return -ENOMEM; |
| 325 | } | 324 | } |
| 326 | 325 | ||
| 327 | ret = gyro_3d_parse_report(pdev, hsdev, channels, | 326 | ret = gyro_3d_parse_report(pdev, hsdev, |
| 328 | HID_USAGE_SENSOR_GYRO_3D, gyro_state); | 327 | (struct iio_chan_spec *)indio_dev->channels, |
| 328 | HID_USAGE_SENSOR_GYRO_3D, gyro_state); | ||
| 329 | if (ret) { | 329 | if (ret) { |
| 330 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 330 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 331 | goto error_free_dev_mem; | 331 | goto error_free_dev_mem; |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | indio_dev->channels = channels; | ||
| 335 | indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels); | 334 | indio_dev->num_channels = ARRAY_SIZE(gyro_3d_channels); |
| 336 | indio_dev->dev.parent = &pdev->dev; | 335 | indio_dev->dev.parent = &pdev->dev; |
| 337 | indio_dev->info = &gyro_3d_info; | 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 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 401 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 403 | .name = "HID-SENSOR-200076", | 402 | .name = "HID-SENSOR-200076", |
| @@ -5,7 +5,7 @@ menu "Humidity sensors" · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | config DHT11 | 6 | config DHT11 |
| 7 | tristate "DHT11 (and compatible sensors) driver" | 7 | tristate "DHT11 (and compatible sensors) driver" |
| 8 | depends on GPIOLIB | 8 | depends on GPIOLIB || COMPILE_TEST |
| 9 | help | 9 | help |
| 10 | This driver supports reading data via a single interrupt | 10 | This driver supports reading data via a single interrupt |
| 11 | generating GPIO line. Currently tested are DHT11 and DHT22. | 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 | /* Note NULL used as error indicator as it doesn't make sense. */ | 239 | /* Note NULL used as error indicator as it doesn't make sense. */ |
| 240 | static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, | 240 | static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks, |
| 241 | unsigned int masklength, | 241 | unsigned int masklength, |
| 242 | const unsigned long *mask) | 242 | const unsigned long *mask, |
| 243 | bool strict) | ||
| 243 | { | 244 | { |
| 244 | if (bitmap_empty(mask, masklength)) | 245 | if (bitmap_empty(mask, masklength)) |
| 245 | return NULL; | 246 | return NULL; |
| 246 | while (*av_masks) { | 247 | while (*av_masks) { |
| 247 | if (bitmap_subset(mask, av_masks, masklength)) | 248 | if (strict) { |
| 248 | return av_masks; | 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 | av_masks += BITS_TO_LONGS(masklength); | 255 | av_masks += BITS_TO_LONGS(masklength); |
| 250 | } | 256 | } |
| 251 | return NULL; | 257 | return NULL; |
| @@ -295,7 +301,7 @@ static int iio_scan_mask_set(struct iio_dev *indio_dev, · 43 unmodified lines | |||
| 295 | if (indio_dev->available_scan_masks) { | 301 | if (indio_dev->available_scan_masks) { |
| 296 | mask = iio_scan_mask_match(indio_dev->available_scan_masks, | 302 | mask = iio_scan_mask_match(indio_dev->available_scan_masks, |
| 297 | indio_dev->masklength, | 303 | indio_dev->masklength, |
| 298 | trialmask); | 304 | trialmask, false); |
| 299 | if (!mask) | 305 | if (!mask) |
| 300 | goto err_invalid_mask; | 306 | goto err_invalid_mask; |
| 301 | } | 307 | } |
| @@ -539,26 +545,13 @@ static void iio_buffer_deactivate(struct iio_buffer *buffer) · 237 unmodified lines | |||
| 539 | iio_buffer_put(buffer); | 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 | struct iio_buffer *buffer, *_buffer; | 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 | list_for_each_entry_safe(buffer, _buffer, | 552 | list_for_each_entry_safe(buffer, _buffer, |
| 553 | &indio_dev->buffer_list, buffer_list) | 553 | &indio_dev->buffer_list, buffer_list) |
| 554 | iio_buffer_deactivate(buffer); | 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 | static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev, | 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 | buffer->access->set_bytes_per_datum(buffer, bytes); | 568 | buffer->access->set_bytes_per_datum(buffer, bytes); |
| 576 | } | 569 | } |
| 577 | 570 | ||
| 578 | static int __iio_update_buffers(struct iio_dev *indio_dev, | 571 | static int iio_buffer_request_update(struct iio_dev *indio_dev, |
| 579 | struct iio_buffer *insert_buffer, | 572 | struct iio_buffer *buffer) |
| 580 | struct iio_buffer *remove_buffer) | ||
| 581 | { | 573 | { |
| 582 | int ret; | 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 */ | 576 | iio_buffer_update_bytes_per_datum(indio_dev, buffer); |
| 589 | if (!list_empty(&indio_dev->buffer_list)) { | 577 | if (buffer->access->request_update) { |
| 590 | if (indio_dev->setup_ops->predisable) { | 578 | ret = buffer->access->request_update(buffer); |
| 591 | ret = indio_dev->setup_ops->predisable(indio_dev); | 579 | if (ret) { |
| 592 | if (ret) | 580 | dev_dbg(&indio_dev->dev, |
| 593 | return ret; | 581 | "Buffer not started: buffer parameter update failed (%d)\n", |
| 594 | } | 582 | ret); |
| 595 | indio_dev->currentmode = INDIO_DIRECT_MODE; | 583 | return ret; |
| 596 | if (indio_dev->setup_ops->postdisable) { | ||
| 597 | ret = indio_dev->setup_ops->postdisable(indio_dev); | ||
| 598 | if (ret) | ||
| 599 | return ret; | ||
| 600 | } | 584 | } |
| 601 | } | 585 | } |
| 602 | /* Keep a copy of current setup to allow roll back */ | 586 | |
| 603 | old_mask = indio_dev->active_scan_mask; | 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 | if (!indio_dev->available_scan_masks) | 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 | if (insert_buffer) | 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 */ | 637 | /* Definitely possible for devices to support both of these. */ |
| 613 | if (list_empty(&indio_dev->buffer_list)) { | 638 | if ((modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { |
| 614 | indio_dev->currentmode = INDIO_DIRECT_MODE; | 639 | config->mode = INDIO_BUFFER_TRIGGERED; |
| 615 | if (indio_dev->available_scan_masks == NULL) | 640 | } else if (modes & INDIO_BUFFER_HARDWARE) { |
| 616 | kfree(old_mask); | 641 | /* |
| 617 | return 0; | 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 | /* What scan mask do we actually have? */ | 658 | /* What scan mask do we actually have? */ |
| 621 | compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), | 659 | compound_mask = kcalloc(BITS_TO_LONGS(indio_dev->masklength), |
| 622 | sizeof(long), GFP_KERNEL); | 660 | sizeof(long), GFP_KERNEL); |
| 623 | if (compound_mask == NULL) { | 661 | if (compound_mask == NULL) |
| 624 | if (indio_dev->available_scan_masks == NULL) | ||
| 625 | kfree(old_mask); | ||
| 626 | return -ENOMEM; | 662 | return -ENOMEM; |
| 627 | } | 663 | |
| 628 | indio_dev->scan_timestamp = 0; | 664 | scan_timestamp = false; |
| 629 | 665 | ||
| 630 | list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { | 666 | list_for_each_entry(buffer, &indio_dev->buffer_list, buffer_list) { |
| 667 | if (buffer == remove_buffer) | ||
| 668 | continue; | ||
| 631 | bitmap_or(compound_mask, compound_mask, buffer->scan_mask, | 669 | bitmap_or(compound_mask, compound_mask, buffer->scan_mask, |
| 632 | indio_dev->masklength); | 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 | if (indio_dev->available_scan_masks) { | 680 | if (indio_dev->available_scan_masks) { |
| 636 | indio_dev->active_scan_mask = | 681 | scan_mask = iio_scan_mask_match(indio_dev->available_scan_masks, |
| 637 | iio_scan_mask_match(indio_dev->available_scan_masks, | 682 | indio_dev->masklength, |
| 638 | indio_dev->masklength, | 683 | compound_mask, |
| 639 | compound_mask); | 684 | strict_scanmask); |
| 640 | if (indio_dev->active_scan_mask == NULL) { | 685 | kfree(compound_mask); |
| 641 | /* | 686 | if (scan_mask == NULL) |
| 642 | * Roll back. | 687 | return -EINVAL; |
| 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 | } | ||
| 656 | } else { | 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 | iio_update_demux(indio_dev); | 709 | iio_update_demux(indio_dev); |
| 661 | 710 | ||
| 662 | /* Wind up again */ | 711 | /* Wind up again */ |
| 663 | if (indio_dev->setup_ops->preenable) { | 712 | if (indio_dev->setup_ops->preenable) { |
| 664 | ret = indio_dev->setup_ops->preenable(indio_dev); | 713 | ret = indio_dev->setup_ops->preenable(indio_dev); |
| 665 | if (ret) { | 714 | if (ret) { |
| 666 | printk(KERN_ERR | 715 | dev_dbg(&indio_dev->dev, |
| 667 | "Buffer not started: buffer preenable failed (%d)\n", ret); | 716 | "Buffer not started: buffer preenable failed (%d)\n", ret); |
| 668 | goto error_remove_inserted; | 717 | goto err_undo_config; |
| 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 | } | ||
| 684 | } | 718 | } |
| 685 | } | 719 | } |
| 720 | |||
| 686 | if (indio_dev->info->update_scan_mode) { | 721 | if (indio_dev->info->update_scan_mode) { |
| 687 | ret = indio_dev->info | 722 | ret = indio_dev->info |
| 688 | ->update_scan_mode(indio_dev, | 723 | ->update_scan_mode(indio_dev, |
| 689 | indio_dev->active_scan_mask); | 724 | indio_dev->active_scan_mask); |
| 690 | if (ret < 0) { | 725 | if (ret < 0) { |
| 691 | printk(KERN_INFO "Buffer not started: update scan mode failed (%d)\n", ret); | 726 | dev_dbg(&indio_dev->dev, |
| 692 | goto error_run_postdisable; | 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. */ | 732 | |
| 696 | if ((indio_dev->modes & INDIO_BUFFER_TRIGGERED) && indio_dev->trig) { | 733 | indio_dev->currentmode = config->mode; |
| 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 | } | ||
| 709 | 734 | ||
| 710 | if (indio_dev->setup_ops->postenable) { | 735 | if (indio_dev->setup_ops->postenable) { |
| 711 | ret = indio_dev->setup_ops->postenable(indio_dev); | 736 | ret = indio_dev->setup_ops->postenable(indio_dev); |
| 712 | if (ret) { | 737 | if (ret) { |
| 713 | printk(KERN_INFO | 738 | dev_dbg(&indio_dev->dev, |
| 714 | "Buffer not started: postenable failed (%d)\n", ret); | 739 | "Buffer not started: postenable failed (%d)\n", ret); |
| 715 | indio_dev->currentmode = INDIO_DIRECT_MODE; | 740 | goto err_run_postdisable; |
| 716 | if (indio_dev->setup_ops->postdisable) | ||
| 717 | indio_dev->setup_ops->postdisable(indio_dev); | ||
| 718 | goto error_disable_all_buffers; | ||
| 719 | } | 741 | } |
| 720 | } | 742 | } |
| 721 | 743 | ||
| 722 | if (indio_dev->available_scan_masks) | 744 | return 0; |
| 723 | kfree(compound_mask); | ||
| 724 | else | ||
| 725 | kfree(old_mask); | ||
| 726 | |||
| 727 | return success; | ||
| 728 | 745 | ||
| 729 | error_disable_all_buffers: | 746 | err_run_postdisable: |
| 730 | indio_dev->currentmode = INDIO_DIRECT_MODE; | 747 | indio_dev->currentmode = INDIO_DIRECT_MODE; |
| 731 | error_run_postdisable: | ||
| 732 | if (indio_dev->setup_ops->postdisable) | 748 | if (indio_dev->setup_ops->postdisable) |
| 733 | indio_dev->setup_ops->postdisable(indio_dev); | 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 | if (insert_buffer) | 816 | if (insert_buffer) |
| 736 | iio_buffer_deactivate(insert_buffer); | 817 | iio_buffer_activate(indio_dev, insert_buffer); |
| 737 | indio_dev->active_scan_mask = old_mask; | 818 | |
| 738 | kfree(compound_mask); | 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 | return ret; | 842 | return ret; |
| 740 | } | 843 | } |
| 741 | 844 | ||
| @@ -777,6 +880,12 @@ out_unlock: · 35 unmodified lines | |||
| 777 | } | 880 | } |
| 778 | EXPORT_SYMBOL_GPL(iio_update_buffers); | 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 | static ssize_t iio_buffer_store_enable(struct device *dev, | 889 | static ssize_t iio_buffer_store_enable(struct device *dev, |
| 781 | struct device_attribute *attr, | 890 | struct device_attribute *attr, |
| 782 | const char *buf, | 891 | const char *buf, |
| @@ -806,8 +915,6 @@ static ssize_t iio_buffer_store_enable(struct device *dev, · 23 unmodified lines | |||
| 806 | ret = __iio_update_buffers(indio_dev, | 915 | ret = __iio_update_buffers(indio_dev, |
| 807 | NULL, indio_dev->buffer); | 916 | NULL, indio_dev->buffer); |
| 808 | 917 | ||
| 809 | if (ret < 0) | ||
| 810 | goto done; | ||
| 811 | done: | 918 | done: |
| 812 | mutex_unlock(&indio_dev->mlock); | 919 | mutex_unlock(&indio_dev->mlock); |
| 813 | return (ret < 0) ? ret : len; | 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 | int ret, i, attrn, attrcount, attrcount_orig = 0; | 993 | int ret, i, attrn, attrcount, attrcount_orig = 0; |
| 887 | const struct iio_chan_spec *channels; | 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 | if (!buffer) | 1005 | if (!buffer) |
| 890 | return 0; | 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 | if (channels[i].scan_index < 0) | 1045 | if (channels[i].scan_index < 0) |
| 930 | continue; | 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 | ret = iio_buffer_add_channel_sysfs(indio_dev, | 1048 | ret = iio_buffer_add_channel_sysfs(indio_dev, |
| 939 | &channels[i]); | 1049 | &channels[i]); |
| 940 | if (ret < 0) | 1050 | if (ret < 0) |
| @@ -101,6 +101,8 @@ static const char * const iio_modifier_names[] = { · 100 unmodified lines | |||
| 101 | [IIO_MOD_WALKING] = "walking", | 101 | [IIO_MOD_WALKING] = "walking", |
| 102 | [IIO_MOD_STILL] = "still", | 102 | [IIO_MOD_STILL] = "still", |
| 103 | [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)", | 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 | /* relies on pairs of these shared then separate */ | 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 | [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", | 119 | [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", |
| 118 | [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] | 120 | [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] |
| 119 | = "filter_low_pass_3db_frequency", | 121 | = "filter_low_pass_3db_frequency", |
| 122 | [IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY] | ||
| 123 | = "filter_high_pass_3db_frequency", | ||
| 120 | [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", | 124 | [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", |
| 121 | [IIO_CHAN_INFO_FREQUENCY] = "frequency", | 125 | [IIO_CHAN_INFO_FREQUENCY] = "frequency", |
| 122 | [IIO_CHAN_INFO_PHASE] = "phase", | 126 | [IIO_CHAN_INFO_PHASE] = "phase", |
| @@ -128,6 +132,8 @@ static const char * const iio_chan_info_postfix[] = { · 5 unmodified lines | |||
| 128 | [IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight", | 132 | [IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight", |
| 129 | [IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count", | 133 | [IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count", |
| 130 | [IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time", | 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 | [IIO_EV_INFO_VALUE] = "value", | 211 | [IIO_EV_INFO_VALUE] = "value", |
| 212 | [IIO_EV_INFO_HYSTERESIS] = "hysteresis", | 212 | [IIO_EV_INFO_HYSTERESIS] = "hysteresis", |
| 213 | [IIO_EV_INFO_PERIOD] = "period", | 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 | static enum iio_event_direction iio_ev_attr_dir(struct iio_dev_attr *attr) | 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 | .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, | 136 | .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, |
| 137 | .set_length = &iio_set_length_kfifo, | 137 | .set_length = &iio_set_length_kfifo, |
| 138 | .release = &iio_kfifo_buffer_release, | 138 | .release = &iio_kfifo_buffer_release, |
| 139 | |||
| 140 | .modes = INDIO_BUFFER_SOFTWARE | INDIO_BUFFER_TRIGGERED, | ||
| 139 | }; | 141 | }; |
| 140 | 142 | ||
| 141 | struct iio_buffer *iio_kfifo_allocate(void) | 143 | struct iio_buffer *iio_kfifo_allocate(void) |
| @@ -5,6 +5,19 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | menu "Light sensors" | 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 | config ADJD_S311 | 21 | config ADJD_S311 |
| 9 | tristate "ADJD-S311-CR999 digital color sensor" | 22 | tristate "ADJD-S311-CR999 digital color sensor" |
| 10 | select IIO_BUFFER | 23 | select IIO_BUFFER |
| @@ -37,6 +50,16 @@ config APDS9300 · 26 unmodified lines | |||
| 37 | To compile this driver as a module, choose M here: the | 50 | To compile this driver as a module, choose M here: the |
| 38 | module will be called apds9300. | 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 | config CM32181 | 63 | config CM32181 |
| 41 | depends on I2C | 64 | depends on I2C |
| 42 | tristate "CM32181 driver" | 65 | tristate "CM32181 driver" |
| @@ -169,11 +192,23 @@ config LTR501 · 126 unmodified lines | |||
| 169 | select IIO_TRIGGERED_BUFFER | 192 | select IIO_TRIGGERED_BUFFER |
| 170 | help | 193 | help |
| 171 | If you say yes here you get support for the Lite-On LTR-501ALS-01 | 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 | This driver can also be built as a module. If so, the module | 198 | This driver can also be built as a module. If so, the module |
| 175 | will be called ltr501. | 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 | config TCS3414 | 212 | config TCS3414 |
| 178 | tristate "TAOS TCS3414 digital color sensor" | 213 | tristate "TAOS TCS3414 digital color sensor" |
| 179 | depends on I2C | 214 | depends on I2C |
| @@ -3,9 +3,11 @@ · 2 unmodified lines | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | # When adding new entries keep the list in alphabetical order | 5 | # When adding new entries keep the list in alphabetical order |
| 6 | obj-$(CONFIG_ACPI_ALS) += acpi-als.o | ||
| 6 | obj-$(CONFIG_ADJD_S311) += adjd_s311.o | 7 | obj-$(CONFIG_ADJD_S311) += adjd_s311.o |
| 7 | obj-$(CONFIG_AL3320A) += al3320a.o | 8 | obj-$(CONFIG_AL3320A) += al3320a.o |
| 8 | obj-$(CONFIG_APDS9300) += apds9300.o | 9 | obj-$(CONFIG_APDS9300) += apds9300.o |
| 10 | obj-$(CONFIG_BH1750) += bh1750.o | ||
| 9 | obj-$(CONFIG_CM32181) += cm32181.o | 11 | obj-$(CONFIG_CM32181) += cm32181.o |
| 10 | obj-$(CONFIG_CM3232) += cm3232.o | 12 | obj-$(CONFIG_CM3232) += cm3232.o |
| 11 | obj-$(CONFIG_CM3323) += cm3323.o | 13 | obj-$(CONFIG_CM3323) += cm3323.o |
| @@ -18,6 +20,7 @@ obj-$(CONFIG_JSA1212) += jsa1212.o · 6 unmodified lines | |||
| 18 | obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o | 20 | obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o |
| 19 | obj-$(CONFIG_LTR501) += ltr501.o | 21 | obj-$(CONFIG_LTR501) += ltr501.o |
| 20 | obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o | 22 | obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o |
| 23 | obj-$(CONFIG_STK3310) += stk3310.o | ||
| 21 | obj-$(CONFIG_TCS3414) += tcs3414.o | 24 | obj-$(CONFIG_TCS3414) += tcs3414.o |
| 22 | obj-$(CONFIG_TCS3472) += tcs3472.o | 25 | obj-$(CONFIG_TCS3472) += tcs3472.o |
| 23 | obj-$(CONFIG_TSL4531) += tsl4531.o | 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 | struct iio_dev *indio_dev; | 263 | struct iio_dev *indio_dev; |
| 264 | struct als_state *als_state; | 264 | struct als_state *als_state; |
| 265 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 265 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 266 | struct iio_chan_spec *channels; | ||
| 267 | 266 | ||
| 268 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state)); | 267 | indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state)); |
| 269 | if (!indio_dev) | 268 | if (!indio_dev) |
| @@ -281,20 +280,21 @@ static int hid_als_probe(struct platform_device *pdev) · 11 unmodified lines | |||
| 281 | return ret; | 280 | return ret; |
| 282 | } | 281 | } |
| 283 | 282 | ||
| 284 | channels = kmemdup(als_channels, sizeof(als_channels), GFP_KERNEL); | 283 | indio_dev->channels = kmemdup(als_channels, |
| 285 | if (!channels) { | 284 | sizeof(als_channels), GFP_KERNEL); |
| 285 | if (!indio_dev->channels) { | ||
| 286 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | 286 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 287 | return -ENOMEM; | 287 | return -ENOMEM; |
| 288 | } | 288 | } |
| 289 | 289 | ||
| 290 | ret = als_parse_report(pdev, hsdev, channels, | 290 | ret = als_parse_report(pdev, hsdev, |
| 291 | HID_USAGE_SENSOR_ALS, als_state); | 291 | (struct iio_chan_spec *)indio_dev->channels, |
| 292 | HID_USAGE_SENSOR_ALS, als_state); | ||
| 292 | if (ret) { | 293 | if (ret) { |
| 293 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 294 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 294 | goto error_free_dev_mem; | 295 | goto error_free_dev_mem; |
| 295 | } | 296 | } |
| 296 | 297 | ||
| 297 | indio_dev->channels = channels; | ||
| 298 | indio_dev->num_channels = | 298 | indio_dev->num_channels = |
| 299 | ARRAY_SIZE(als_channels); | 299 | ARRAY_SIZE(als_channels); |
| 300 | indio_dev->dev.parent = &pdev->dev; | 300 | indio_dev->dev.parent = &pdev->dev; |
| @@ -361,7 +361,7 @@ static int hid_als_remove(struct platform_device *pdev) · 60 unmodified lines | |||
| 361 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 366 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 367 | .name = "HID-SENSOR-200041", | 367 | .name = "HID-SENSOR-200041", |
| @@ -350,7 +350,7 @@ static int hid_prox_remove(struct platform_device *pdev) · 349 unmodified lines | |||
| 350 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 355 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 356 | .name = "HID-SENSOR-200011", | 356 | .name = "HID-SENSOR-200011", |
| @@ -9,15 +9,18 @@ · 8 unmodified lines | |||
| 9 | * | 9 | * |
| 10 | * 7-bit I2C slave address 0x23 | 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 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
| 17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/regmap.h> | ||
| 20 | #include <linux/acpi.h> | ||
| 19 | 21 | ||
| 20 | #include <linux/iio/iio.h> | 22 | #include <linux/iio/iio.h> |
| 23 | #include <linux/iio/events.h> | ||
| 21 | #include <linux/iio/sysfs.h> | 24 | #include <linux/iio/sysfs.h> |
| 22 | #include <linux/iio/trigger_consumer.h> | 25 | #include <linux/iio/trigger_consumer.h> |
| 23 | #include <linux/iio/buffer.h> | 26 | #include <linux/iio/buffer.h> |
| @@ -27,12 +30,21 @@ · 3 unmodified lines | |||
| 27 | 30 | ||
| 28 | #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */ | 31 | #define LTR501_ALS_CONTR 0x80 /* ALS operation mode, SW reset */ |
| 29 | #define LTR501_PS_CONTR 0x81 /* PS operation mode */ | 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 | #define LTR501_PART_ID 0x86 | 35 | #define LTR501_PART_ID 0x86 |
| 31 | #define LTR501_MANUFAC_ID 0x87 | 36 | #define LTR501_MANUFAC_ID 0x87 |
| 32 | #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ | 37 | #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ |
| 33 | #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ | 38 | #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ |
| 34 | #define LTR501_ALS_PS_STATUS 0x8c | 39 | #define LTR501_ALS_PS_STATUS 0x8c |
| 35 | #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ | 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 | #define LTR501_ALS_CONTR_SW_RESET BIT(2) | 49 | #define LTR501_ALS_CONTR_SW_RESET BIT(2) |
| 38 | #define LTR501_CONTR_PS_GAIN_MASK (BIT(3) | BIT(2)) | 50 | #define LTR501_CONTR_PS_GAIN_MASK (BIT(3) | BIT(2)) |
| @@ -40,28 +52,288 @@ · 1 unmodified line | |||
| 40 | #define LTR501_CONTR_ALS_GAIN_MASK BIT(3) | 52 | #define LTR501_CONTR_ALS_GAIN_MASK BIT(3) |
| 41 | #define LTR501_CONTR_ACTIVE BIT(1) | 53 | #define LTR501_CONTR_ACTIVE BIT(1) |
| 42 | 54 | ||
| 55 | #define LTR501_STATUS_ALS_INTR BIT(3) | ||
| 43 | #define LTR501_STATUS_ALS_RDY BIT(2) | 56 | #define LTR501_STATUS_ALS_RDY BIT(2) |
| 57 | #define LTR501_STATUS_PS_INTR BIT(1) | ||
| 44 | #define LTR501_STATUS_PS_RDY BIT(0) | 58 | #define LTR501_STATUS_PS_RDY BIT(0) |
| 45 | 59 | ||
| 46 | #define LTR501_PS_DATA_MASK 0x7ff | 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 | struct ltr501_data { | 152 | struct ltr501_data { |
| 49 | struct i2c_client *client; | 153 | struct i2c_client *client; |
| 50 | struct mutex lock_als, lock_ps; | 154 | struct mutex lock_als, lock_ps; |
| 155 | struct ltr501_chip_info *chip_info; | ||
| 51 | u8 als_contr, ps_contr; | 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 | static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) | 327 | static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) |
| 55 | { | 328 | { |
| 56 | int tries = 100; | 329 | int tries = 100; |
| 57 | int ret; | 330 | int ret, status; |
| 58 | 331 | ||
| 59 | while (tries--) { | 332 | while (tries--) { |
| 60 | ret = i2c_smbus_read_byte_data(data->client, | 333 | ret = regmap_read(data->regmap, LTR501_ALS_PS_STATUS, &status); |
| 61 | LTR501_ALS_PS_STATUS); | ||
| 62 | if (ret < 0) | 334 | if (ret < 0) |
| 63 | return ret; | 335 | return ret; |
| 64 | if ((ret & drdy_mask) == drdy_mask) | 336 | if ((status & drdy_mask) == drdy_mask) |
| 65 | return 0; | 337 | return 0; |
| 66 | msleep(25); | 338 | msleep(25); |
| 67 | } | 339 | } |
| @@ -70,25 +342,221 @@ static int ltr501_drdy(struct ltr501_data *data, u8 drdy_mask) · 2 unmodified lines | |||
| 70 | return -EIO; | 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 | static int ltr501_read_als(struct ltr501_data *data, __le16 buf[2]) | 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 | if (ret < 0) | 402 | if (ret < 0) |
| 77 | return ret; | 403 | return ret; |
| 78 | /* always read both ALS channels in given order */ | 404 | /* always read both ALS channels in given order */ |
| 79 | return i2c_smbus_read_i2c_block_data(data->client, | 405 | return regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, |
| 80 | LTR501_ALS_DATA1, 2 * sizeof(__le16), (u8 *) buf); | 406 | buf, 2 * sizeof(__le16)); |
| 81 | } | 407 | } |
| 82 | 408 | ||
| 83 | static int ltr501_read_ps(struct ltr501_data *data) | 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 | if (ret < 0) | 414 | if (ret < 0) |
| 87 | return ret; | 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 | .type = IIO_INTENSITY, \ | 560 | .type = IIO_INTENSITY, \ |
| 93 | .modified = 1, \ | 561 | .modified = 1, \ |
| 94 | .address = (_addr), \ | 562 | .address = (_addr), \ |
| @@ -101,13 +569,27 @@ static int ltr501_read_ps(struct ltr501_data *data) · 6 unmodified lines | |||
| 101 | .realbits = 16, \ | 569 | .realbits = 16, \ |
| 102 | .storagebits = 16, \ | 570 | .storagebits = 16, \ |
| 103 | .endianness = IIO_CPU, \ | 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 | static const struct iio_chan_spec ltr501_channels[] = { | 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 | LTR501_INTENSITY_CHANNEL(1, LTR501_ALS_DATA1, IIO_MOD_LIGHT_IR, | 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 | .type = IIO_PROXIMITY, | 594 | .type = IIO_PROXIMITY, |
| 113 | .address = LTR501_PS_DATA, | 595 | .address = LTR501_PS_DATA, |
| @@ -120,23 +602,51 @@ static const struct iio_chan_spec ltr501_channels[] = { · 6 unmodified lines | |||
| 120 | .storagebits = 16, | 602 | .storagebits = 16, |
| 121 | .endianness = IIO_CPU, | 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 | IIO_CHAN_SOFT_TIMESTAMP(3), | 608 | IIO_CHAN_SOFT_TIMESTAMP(3), |
| 125 | }; | 609 | }; |
| 126 | 610 | ||
| 127 | static const int ltr501_ps_gain[4][2] = { | 611 | static const struct iio_chan_spec ltr301_channels[] = { |
| 128 | {1, 0}, {0, 250000}, {0, 125000}, {0, 62500} | 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 | static int ltr501_read_raw(struct iio_dev *indio_dev, | 624 | static int ltr501_read_raw(struct iio_dev *indio_dev, |
| 132 | struct iio_chan_spec const *chan, | 625 | struct iio_chan_spec const *chan, |
| 133 | int *val, int *val2, long mask) | 626 | int *val, int *val2, long mask) |
| 134 | { | 627 | { |
| 135 | struct ltr501_data *data = iio_priv(indio_dev); | 628 | struct ltr501_data *data = iio_priv(indio_dev); |
| 136 | __le16 buf[2]; | 629 | __le16 buf[2]; |
| 137 | int ret, i; | 630 | int ret, i; |
| 138 | 631 | ||
| 139 | switch (mask) { | 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 | case IIO_CHAN_INFO_RAW: | 650 | case IIO_CHAN_INFO_RAW: |
| 141 | if (iio_buffer_enabled(indio_dev)) | 651 | if (iio_buffer_enabled(indio_dev)) |
| 142 | return -EBUSY; | 652 | return -EBUSY; |
| @@ -149,7 +659,7 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, · 6 unmodified lines | |||
| 149 | if (ret < 0) | 659 | if (ret < 0) |
| 150 | return ret; | 660 | return ret; |
| 151 | *val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ? | 661 | *val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ? |
| 152 | buf[0] : buf[1]); | 662 | buf[0] : buf[1]); |
| 153 | return IIO_VAL_INT; | 663 | return IIO_VAL_INT; |
| 154 | case IIO_PROXIMITY: | 664 | case IIO_PROXIMITY: |
| 155 | mutex_lock(&data->lock_ps); | 665 | mutex_lock(&data->lock_ps); |
| @@ -165,45 +675,59 @@ static int ltr501_read_raw(struct iio_dev *indio_dev, · 9 unmodified lines | |||
| 165 | case IIO_CHAN_INFO_SCALE: | 675 | case IIO_CHAN_INFO_SCALE: |
| 166 | switch (chan->type) { | 676 | switch (chan->type) { |
| 167 | case IIO_INTENSITY: | 677 | case IIO_INTENSITY: |
| 168 | if (data->als_contr & LTR501_CONTR_ALS_GAIN_MASK) { | 678 | i = (data->als_contr & data->chip_info->als_gain_mask) |
| 169 | *val = 0; | 679 | >> data->chip_info->als_gain_shift; |
| 170 | *val2 = 5000; | 680 | *val = data->chip_info->als_gain[i].scale; |
| 171 | return IIO_VAL_INT_PLUS_MICRO; | 681 | *val2 = data->chip_info->als_gain[i].uscale; |
| 172 | } else { | 682 | return IIO_VAL_INT_PLUS_MICRO; |
| 173 | *val = 1; | ||
| 174 | *val2 = 0; | ||
| 175 | return IIO_VAL_INT; | ||
| 176 | } | ||
| 177 | case IIO_PROXIMITY: | 683 | case IIO_PROXIMITY: |
| 178 | i = (data->ps_contr & LTR501_CONTR_PS_GAIN_MASK) >> | 684 | i = (data->ps_contr & LTR501_CONTR_PS_GAIN_MASK) >> |
| 179 | LTR501_CONTR_PS_GAIN_SHIFT; | 685 | LTR501_CONTR_PS_GAIN_SHIFT; |
| 180 | *val = ltr501_ps_gain[i][0]; | 686 | *val = data->chip_info->ps_gain[i].scale; |
| 181 | *val2 = ltr501_ps_gain[i][1]; | 687 | *val2 = data->chip_info->ps_gain[i].uscale; |
| 182 | return IIO_VAL_INT_PLUS_MICRO; | 688 | return IIO_VAL_INT_PLUS_MICRO; |
| 183 | default: | 689 | default: |
| 184 | return -EINVAL; | 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 | return -EINVAL; | 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 | int i; | 715 | int i; |
| 193 | 716 | ||
| 194 | for (i = 0; i < ARRAY_SIZE(ltr501_ps_gain); i++) | 717 | for (i = 0; i < size; i++) |
| 195 | if (val == ltr501_ps_gain[i][0] && val2 == ltr501_ps_gain[i][1]) | 718 | if (val == gain[i].scale && val2 == gain[i].uscale) |
| 196 | return i; | 719 | return i; |
| 197 | 720 | ||
| 198 | return -1; | 721 | return -1; |
| 199 | } | 722 | } |
| 200 | 723 | ||
| 201 | static int ltr501_write_raw(struct iio_dev *indio_dev, | 724 | static int ltr501_write_raw(struct iio_dev *indio_dev, |
| 202 | struct iio_chan_spec const *chan, | 725 | struct iio_chan_spec const *chan, |
| 203 | int val, int val2, long mask) | 726 | int val, int val2, long mask) |
| 204 | { | 727 | { |
| 205 | struct ltr501_data *data = iio_priv(indio_dev); | 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 | if (iio_buffer_enabled(indio_dev)) | 732 | if (iio_buffer_enabled(indio_dev)) |
| 209 | return -EBUSY; | 733 | return -EBUSY; |
| @@ -212,35 +736,382 @@ static int ltr501_write_raw(struct iio_dev *indio_dev, · 2 unmodified lines | |||
| 212 | case IIO_CHAN_INFO_SCALE: | 736 | case IIO_CHAN_INFO_SCALE: |
| 213 | switch (chan->type) { | 737 | switch (chan->type) { |
| 214 | case IIO_INTENSITY: | 738 | case IIO_INTENSITY: |
| 215 | if (val == 0 && val2 == 5000) | 739 | i = ltr501_get_gain_index(info->als_gain, |
| 216 | data->als_contr |= LTR501_CONTR_ALS_GAIN_MASK; | 740 | info->als_gain_tbl_size, |
| 217 | else if (val == 1 && val2 == 0) | 741 | val, val2); |
| 218 | data->als_contr &= ~LTR501_CONTR_ALS_GAIN_MASK; | 742 | if (i < 0) |
| 219 | else | ||
| 220 | return -EINVAL; | 743 | return -EINVAL; |
| 221 | return i2c_smbus_write_byte_data(data->client, | 744 | |
| 222 | LTR501_ALS_CONTR, data->als_contr); | 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 | case IIO_PROXIMITY: | 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 | if (i < 0) | 754 | if (i < 0) |
| 226 | return -EINVAL; | 755 | return -EINVAL; |
| 227 | data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; | 756 | data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK; |
| 228 | data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; | 757 | data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT; |
| 229 | return i2c_smbus_write_byte_data(data->client, | 758 | |
| 230 | LTR501_PS_CONTR, data->ps_contr); | 759 | return regmap_write(data->regmap, LTR501_PS_CONTR, |
| 760 | data->ps_contr); | ||
| 231 | default: | 761 | default: |
| 232 | return -EINVAL; | 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 | return -EINVAL; | 880 | return -EINVAL; |
| 236 | } | 881 | } |
| 237 | 882 | ||
| 238 | static IIO_CONST_ATTR(in_proximity_scale_available, "1 0.25 0.125 0.0625"); | 883 | static int ltr501_write_thresh(struct iio_dev *indio_dev, |
| 239 | static IIO_CONST_ATTR(in_intensity_scale_available, "1 0.005"); | 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 | static struct attribute *ltr501_attributes[] = { | 1103 | static struct attribute *ltr501_attributes[] = { |
| 242 | &iio_const_attr_in_proximity_scale_available.dev_attr.attr, | 1104 | &iio_dev_attr_in_proximity_scale_available.dev_attr.attr, |
| 243 | &iio_const_attr_in_intensity_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 | NULL | 1115 | NULL |
| 245 | }; | 1116 | }; |
| 246 | 1117 | ||
| @@ -248,20 +1119,98 @@ static const struct attribute_group ltr501_attribute_group = { · 1 unmodified line | |||
| 248 | .attrs = ltr501_attributes, | 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 | static const struct iio_info ltr501_info = { | 1133 | static const struct iio_info ltr501_info = { |
| 252 | .read_raw = ltr501_read_raw, | 1134 | .read_raw = ltr501_read_raw, |
| 253 | .write_raw = ltr501_write_raw, | 1135 | .write_raw = ltr501_write_raw, |
| 254 | .attrs = <r501_attribute_group, | 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 | .driver_module = THIS_MODULE, | 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 | if (ret < 0) | 1210 | if (ret < 0) |
| 262 | return ret; | 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 | static irqreturn_t ltr501_trigger_handler(int irq, void *p) | 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 | __le16 als_buf[2]; | 1222 | __le16 als_buf[2]; |
| 274 | u8 mask = 0; | 1223 | u8 mask = 0; |
| 275 | int j = 0; | 1224 | int j = 0; |
| 276 | int ret; | 1225 | int ret, psdata; |
| 277 | 1226 | ||
| 278 | memset(buf, 0, sizeof(buf)); | 1227 | memset(buf, 0, sizeof(buf)); |
| 279 | 1228 | ||
| 280 | /* figure out which data needs to be ready */ | 1229 | /* figure out which data needs to be ready */ |
| 281 | if (test_bit(0, indio_dev->active_scan_mask) || | 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 | mask |= LTR501_STATUS_ALS_RDY; | 1232 | mask |= LTR501_STATUS_ALS_RDY; |
| 284 | if (test_bit(2, indio_dev->active_scan_mask)) | 1233 | if (test_bit(2, indio_dev->active_scan_mask)) |
| 285 | mask |= LTR501_STATUS_PS_RDY; | 1234 | mask |= LTR501_STATUS_PS_RDY; |
| @@ -289,8 +1238,8 @@ static irqreturn_t ltr501_trigger_handler(int irq, void *p) · 3 unmodified lines | |||
| 289 | goto done; | 1238 | goto done; |
| 290 | 1239 | ||
| 291 | if (mask & LTR501_STATUS_ALS_RDY) { | 1240 | if (mask & LTR501_STATUS_ALS_RDY) { |
| 292 | ret = i2c_smbus_read_i2c_block_data(data->client, | 1241 | ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1, |
| 293 | LTR501_ALS_DATA1, sizeof(als_buf), (u8 *) als_buf); | 1242 | (u8 *)als_buf, sizeof(als_buf)); |
| 294 | if (ret < 0) | 1243 | if (ret < 0) |
| 295 | return ret; | 1244 | return ret; |
| 296 | if (test_bit(0, indio_dev->active_scan_mask)) | 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 | if (mask & LTR501_STATUS_PS_RDY) { | 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 | if (ret < 0) | 1254 | if (ret < 0) |
| 305 | goto done; | 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, | 1259 | iio_push_to_buffers_with_timestamp(indio_dev, buf, iio_get_time_ns()); |
| 310 | iio_get_time_ns()); | ||
| 311 | 1260 | ||
| 312 | done: | 1261 | done: |
| 313 | iio_trigger_notify_done(indio_dev->trig); | 1262 | iio_trigger_notify_done(indio_dev->trig); |
| @@ -315,67 +1264,225 @@ done: · 1 unmodified line | |||
| 315 | return IRQ_HANDLED; | 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 | static int ltr501_init(struct ltr501_data *data) | 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 | if (ret < 0) | 1302 | if (ret < 0) |
| 324 | return ret; | 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 | if (ret < 0) | 1308 | if (ret < 0) |
| 329 | return ret; | 1309 | return ret; |
| 330 | data->ps_contr = ret | LTR501_CONTR_ACTIVE; | ||
| 331 | 1310 | ||
| 332 | return ltr501_write_contr(data->client, data->als_contr, | 1311 | data->ps_contr = status | LTR501_CONTR_ACTIVE; |
| 333 | data->ps_contr); | 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 | static int ltr501_powerdown(struct ltr501_data *data) | 1346 | static int ltr501_powerdown(struct ltr501_data *data) |
| 337 | { | 1347 | { |
| 338 | return ltr501_write_contr(data->client, | 1348 | return ltr501_write_contr(data, data->als_contr & |
| 339 | data->als_contr & ~LTR501_CONTR_ACTIVE, | 1349 | ~data->chip_info->als_mode_active, |
| 340 | data->ps_contr & ~LTR501_CONTR_ACTIVE); | 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 | static int ltr501_probe(struct i2c_client *client, | 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 | struct ltr501_data *data; | 1367 | struct ltr501_data *data; |
| 347 | struct iio_dev *indio_dev; | 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 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | 1373 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
| 351 | if (!indio_dev) | 1374 | if (!indio_dev) |
| 352 | return -ENOMEM; | 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 | data = iio_priv(indio_dev); | 1383 | data = iio_priv(indio_dev); |
| 355 | i2c_set_clientdata(client, indio_dev); | 1384 | i2c_set_clientdata(client, indio_dev); |
| 356 | data->client = client; | 1385 | data->client = client; |
| 1386 | data->regmap = regmap; | ||
| 357 | mutex_init(&data->lock_als); | 1387 | mutex_init(&data->lock_als); |
| 358 | mutex_init(&data->lock_ps); | 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 | if (ret < 0) | 1440 | if (ret < 0) |
| 362 | return ret; | 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 | return -ENODEV; | 1455 | return -ENODEV; |
| 365 | 1456 | ||
| 366 | indio_dev->dev.parent = &client->dev; | 1457 | indio_dev->dev.parent = &client->dev; |
| 367 | indio_dev->info = <r501_info; | 1458 | indio_dev->info = data->chip_info->info; |
| 368 | indio_dev->channels = ltr501_channels; | 1459 | indio_dev->channels = data->chip_info->channels; |
| 369 | indio_dev->num_channels = ARRAY_SIZE(ltr501_channels); | 1460 | indio_dev->num_channels = data->chip_info->no_channels; |
| 370 | indio_dev->name = LTR501_DRV_NAME; | 1461 | indio_dev->name = name; |
| 371 | indio_dev->modes = INDIO_DIRECT_MODE; | 1462 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 372 | 1463 | ||
| 373 | ret = ltr501_init(data); | 1464 | ret = ltr501_init(data); |
| 374 | if (ret < 0) | 1465 | if (ret < 0) |
| 375 | return ret; | 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 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | 1484 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
| 378 | ltr501_trigger_handler, NULL); | 1485 | ltr501_trigger_handler, NULL); |
| 379 | if (ret) | 1486 | if (ret) |
| 380 | goto powerdown_on_error; | 1487 | goto powerdown_on_error; |
| 381 | 1488 | ||
| @@ -407,24 +1514,34 @@ static int ltr501_remove(struct i2c_client *client) · 25 unmodified lines | |||
| 407 | static int ltr501_suspend(struct device *dev) | 1514 | static int ltr501_suspend(struct device *dev) |
| 408 | { | 1515 | { |
| 409 | struct ltr501_data *data = iio_priv(i2c_get_clientdata( | 1516 | struct ltr501_data *data = iio_priv(i2c_get_clientdata( |
| 410 | to_i2c_client(dev))); | 1517 | to_i2c_client(dev))); |
| 411 | return ltr501_powerdown(data); | 1518 | return ltr501_powerdown(data); |
| 412 | } | 1519 | } |
| 413 | 1520 | ||
| 414 | static int ltr501_resume(struct device *dev) | 1521 | static int ltr501_resume(struct device *dev) |
| 415 | { | 1522 | { |
| 416 | struct ltr501_data *data = iio_priv(i2c_get_clientdata( | 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 | data->ps_contr); | 1527 | data->ps_contr); |
| 421 | } | 1528 | } |
| 422 | #endif | 1529 | #endif |
| 423 | 1530 | ||
| 424 | static SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume); | 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 | static const struct i2c_device_id ltr501_id[] = { | 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 | MODULE_DEVICE_TABLE(i2c, ltr501_id); | 1547 | MODULE_DEVICE_TABLE(i2c, ltr501_id); |
| @@ -433,6 +1550,7 @@ static struct i2c_driver ltr501_driver = { · 2 unmodified lines | |||
| 433 | .driver = { | 1550 | .driver = { |
| 434 | .name = LTR501_DRV_NAME, | 1551 | .name = LTR501_DRV_NAME, |
| 435 | .pm = <r501_pm_ops, | 1552 | .pm = <r501_pm_ops, |
| 1553 | .acpi_match_table = ACPI_PTR(ltr_acpi_match), | ||
| 436 | .owner = THIS_MODULE, | 1554 | .owner = THIS_MODULE, |
| 437 | }, | 1555 | }, |
| 438 | .probe = ltr501_probe, | 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 | * convert between normalized values and HW values obtained using given | 240 | * convert between normalized values and HW values obtained using given |
| 241 | * timing and gain settings. | 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 | int shift = 0; | 245 | int shift = 0; |
| 246 | 246 | ||
| @@ -263,9 +263,9 @@ static int adc_shiftbits(u8 timing) · 16 unmodified lines | |||
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | /* Convert a HW ADC value to normalized scale. */ | 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 | static void tsl2563_wait_adc(struct tsl2563_chip *chip) | 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 | retry = tsl2563_adjust_gainlevel(chip, adc0); | 350 | retry = tsl2563_adjust_gainlevel(chip, adc0); |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | chip->data0 = normalize_adc(adc0, chip->gainlevel->gaintime); | 353 | chip->data0 = tsl2563_normalize_adc(adc0, chip->gainlevel->gaintime); |
| 354 | chip->data1 = normalize_adc(adc1, chip->gainlevel->gaintime); | 354 | chip->data1 = tsl2563_normalize_adc(adc1, chip->gainlevel->gaintime); |
| 355 | 355 | ||
| 356 | if (!chip->int_enabled) | 356 | if (!chip->int_enabled) |
| 357 | schedule_delayed_work(&chip->poweroff_work, 5 * HZ); | 357 | schedule_delayed_work(&chip->poweroff_work, 5 * HZ); |
| @@ -361,13 +361,13 @@ out: · 3 unmodified lines | |||
| 361 | return ret; | 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 | return (int) (((calib * CALIB_BASE_SYSFS) + | 366 | return (int) (((calib * CALIB_BASE_SYSFS) + |
| 367 | CALIB_FRAC_HALF) >> CALIB_FRAC_BITS); | 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 | return (((u32) value) << CALIB_FRAC_BITS) / CALIB_BASE_SYSFS; | 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 | /* Convert normalized, scaled ADC values to lux. */ | 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 | const struct tsl2563_lux_coeff *lp = lux_table; | 431 | const struct tsl2563_lux_coeff *lp = lux_table; |
| 432 | unsigned long ratio, lux, ch0 = adc0, ch1 = adc1; | 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 | /* Apply calibration coefficient to ADC count. */ | 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 | unsigned long scaled = adc; | 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 | if (mask != IIO_CHAN_INFO_CALIBSCALE) | 463 | if (mask != IIO_CHAN_INFO_CALIBSCALE) |
| 464 | return -EINVAL; | 464 | return -EINVAL; |
| 465 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) | 465 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) |
| 466 | chip->calib0 = calib_from_sysfs(val); | 466 | chip->calib0 = tsl2563_calib_from_sysfs(val); |
| 467 | else if (chan->channel2 == IIO_MOD_LIGHT_IR) | 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 | else | 469 | else |
| 470 | return -EINVAL; | 470 | return -EINVAL; |
| 471 | 471 | ||
| @@ -491,11 +491,11 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, · 19 unmodified lines | |||
| 491 | ret = tsl2563_get_adc(chip); | 491 | ret = tsl2563_get_adc(chip); |
| 492 | if (ret) | 492 | if (ret) |
| 493 | goto error_ret; | 493 | goto error_ret; |
| 494 | calib0 = calib_adc(chip->data0, chip->calib0) * | 494 | calib0 = tsl2563_calib_adc(chip->data0, chip->calib0) * |
| 495 | chip->cover_comp_gain; | 495 | chip->cover_comp_gain; |
| 496 | calib1 = calib_adc(chip->data1, chip->calib1) * | 496 | calib1 = tsl2563_calib_adc(chip->data1, chip->calib1) * |
| 497 | chip->cover_comp_gain; | 497 | chip->cover_comp_gain; |
| 498 | *val = adc_to_lux(calib0, calib1); | 498 | *val = tsl2563_adc_to_lux(calib0, calib1); |
| 499 | ret = IIO_VAL_INT; | 499 | ret = IIO_VAL_INT; |
| 500 | break; | 500 | break; |
| 501 | case IIO_INTENSITY: | 501 | case IIO_INTENSITY: |
| @@ -515,9 +515,9 @@ static int tsl2563_read_raw(struct iio_dev *indio_dev, · 13 unmodified lines | |||
| 515 | 515 | ||
| 516 | case IIO_CHAN_INFO_CALIBSCALE: | 516 | case IIO_CHAN_INFO_CALIBSCALE: |
| 517 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) | 517 | if (chan->channel2 == IIO_MOD_LIGHT_BOTH) |
| 518 | *val = calib_to_sysfs(chip->calib0); | 518 | *val = tsl2563_calib_to_sysfs(chip->calib0); |
| 519 | else | 519 | else |
| 520 | *val = calib_to_sysfs(chip->calib1); | 520 | *val = tsl2563_calib_to_sysfs(chip->calib1); |
| 521 | ret = IIO_VAL_INT; | 521 | ret = IIO_VAL_INT; |
| 522 | break; | 522 | break; |
| 523 | default: | 523 | default: |
| @@ -750,8 +750,8 @@ static int tsl2563_probe(struct i2c_client *client, · 226 unmodified lines | |||
| 750 | chip->high_thres = 0xffff; | 750 | chip->high_thres = 0xffff; |
| 751 | chip->gainlevel = tsl2563_gainlevel_table; | 751 | chip->gainlevel = tsl2563_gainlevel_table; |
| 752 | chip->intr = TSL2563_INT_PERSIST(4); | 752 | chip->intr = TSL2563_INT_PERSIST(4); |
| 753 | chip->calib0 = calib_from_sysfs(CALIB_BASE_SYSFS); | 753 | chip->calib0 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); |
| 754 | chip->calib1 = calib_from_sysfs(CALIB_BASE_SYSFS); | 754 | chip->calib1 = tsl2563_calib_from_sysfs(CALIB_BASE_SYSFS); |
| 755 | 755 | ||
| 756 | if (pdata) | 756 | if (pdata) |
| 757 | chip->cover_comp_gain = pdata->cover_comp_gain; | 757 | chip->cover_comp_gain = pdata->cover_comp_gain; |
| @@ -24,12 +24,12 @@ · 23 unmodified lines | |||
| 24 | 24 | ||
| 25 | #define TSL4531_DRV_NAME "tsl4531" | 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) | 29 | #define TSL4531_CONTROL (TSL4531_COMMAND | 0x00) |
| 30 | #define TSL4531_CONFIG (TCS3472_COMMAND | 0x01) | 30 | #define TSL4531_CONFIG (TSL4531_COMMAND | 0x01) |
| 31 | #define TSL4531_DATA (TCS3472_COMMAND | 0x04) | 31 | #define TSL4531_DATA (TSL4531_COMMAND | 0x04) |
| 32 | #define TSL4531_ID (TCS3472_COMMAND | 0x0a) | 32 | #define TSL4531_ID (TSL4531_COMMAND | 0x0a) |
| 33 | 33 | ||
| 34 | /* operating modes in control register */ | 34 | /* operating modes in control register */ |
| 35 | #define TSL4531_MODE_POWERDOWN 0x00 | 35 | #define TSL4531_MODE_POWERDOWN 0x00 |
| @@ -8,7 +8,7 @@ menu "Magnetometer sensors" · 7 unmodified lines | |||
| 8 | config AK8975 | 8 | config AK8975 |
| 9 | tristate "Asahi Kasei AK 3-Axis Magnetometer" | 9 | tristate "Asahi Kasei AK 3-Axis Magnetometer" |
| 10 | depends on I2C | 10 | depends on I2C |
| 11 | depends on GPIOLIB | 11 | depends on GPIOLIB || COMPILE_TEST |
| 12 | help | 12 | help |
| 13 | Say yes here to build support for Asahi Kasei AK8975, AK8963, | 13 | Say yes here to build support for Asahi Kasei AK8975, AK8963, |
| 14 | AK09911 or AK09912 3-Axis Magnetometer. | 14 | AK09911 or AK09912 3-Axis Magnetometer. |
| @@ -19,7 +19,7 @@ config AK8975 · 4 unmodified lines | |||
| 19 | config AK09911 | 19 | config AK09911 |
| 20 | tristate "Asahi Kasei AK09911 3-axis Compass" | 20 | tristate "Asahi Kasei AK09911 3-axis Compass" |
| 21 | depends on I2C | 21 | depends on I2C |
| 22 | depends on GPIOLIB | 22 | depends on GPIOLIB || COMPILE_TEST |
| 23 | select AK8975 | 23 | select AK8975 |
| 24 | help | 24 | help |
| 25 | Deprecated: AK09911 is now supported by AK8975 driver. | 25 | Deprecated: AK09911 is now supported by AK8975 driver. |
| @@ -47,6 +47,17 @@ config HID_SENSOR_MAGNETOMETER_3D · 21 unmodified lines | |||
| 47 | Say yes here to build support for the HID SENSOR | 47 | Say yes here to build support for the HID SENSOR |
| 48 | Magnetometer 3D. | 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 | config IIO_ST_MAGN_3AXIS | 61 | config IIO_ST_MAGN_3AXIS |
| 51 | tristate "STMicroelectronics magnetometers 3-Axis Driver" | 62 | tristate "STMicroelectronics magnetometers 3-Axis Driver" |
| 52 | depends on (I2C || SPI_MASTER) && SYSFS | 63 | depends on (I2C || SPI_MASTER) && SYSFS |
| @@ -76,4 +87,18 @@ config IIO_ST_MAGN_SPI_3AXIS · 23 unmodified lines | |||
| 76 | depends on IIO_ST_MAGN_3AXIS | 87 | depends on IIO_ST_MAGN_3AXIS |
| 77 | depends on IIO_ST_SENSORS_SPI | 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 | endmenu | 104 | endmenu |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | obj-$(CONFIG_AK8975) += ak8975.o | 6 | obj-$(CONFIG_AK8975) += ak8975.o |
| 7 | obj-$(CONFIG_MAG3110) += mag3110.o | 7 | obj-$(CONFIG_MAG3110) += mag3110.o |
| 8 | obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o | 8 | obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o |
| 9 | obj-$(CONFIG_MMC35240) += mmc35240.o | ||
| 9 | 10 | ||
| 10 | obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o | 11 | obj-$(CONFIG_IIO_ST_MAGN_3AXIS) += st_magn.o |
| 11 | st_magn-y := st_magn_core.o | 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 | obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o | 15 | obj-$(CONFIG_IIO_ST_MAGN_I2C_3AXIS) += st_magn_i2c.o |
| 15 | obj-$(CONFIG_IIO_ST_MAGN_SPI_3AXIS) += st_magn_spi.o | 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 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 515 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 516 | .name = "HID-SENSOR-200083", | 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 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 15 | #include <linux/iio/common/st_sensors.h> | 15 | #include <linux/iio/common/st_sensors.h> |
| 16 | 16 | ||
| 17 | #define LSM303DLH_MAGN_DEV_NAME "lsm303dlh_magn" | ||
| 17 | #define LSM303DLHC_MAGN_DEV_NAME "lsm303dlhc_magn" | 18 | #define LSM303DLHC_MAGN_DEV_NAME "lsm303dlhc_magn" |
| 18 | #define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn" | 19 | #define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn" |
| 19 | #define LIS3MDL_MAGN_DEV_NAME "lis3mdl" | 20 | #define LIS3MDL_MAGN_DEV_NAME "lis3mdl" |
| @@ -45,6 +45,46 @@ · 44 unmodified lines | |||
| 45 | #define ST_MAGN_FS_AVL_12000MG 12000 | 45 | #define ST_MAGN_FS_AVL_12000MG 12000 |
| 46 | #define ST_MAGN_FS_AVL_16000MG 16000 | 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 | /* CUSTOM VALUES FOR SENSOR 1 */ | 88 | /* CUSTOM VALUES FOR SENSOR 1 */ |
| 49 | #define ST_MAGN_1_WAI_EXP 0x3c | 89 | #define ST_MAGN_1_WAI_EXP 0x3c |
| 50 | #define ST_MAGN_1_ODR_ADDR 0x00 | 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 | static const struct st_sensor_settings st_magn_sensors_settings[] = { | 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 | .wai = ST_MAGN_1_WAI_EXP, | 270 | .wai = ST_MAGN_1_WAI_EXP, |
| 155 | .sensors_supported = { | 271 | .sensors_supported = { |
| @@ -20,6 +20,10 @@ · 19 unmodified lines | |||
| 20 | 20 | ||
| 21 | #ifdef CONFIG_OF | 21 | #ifdef CONFIG_OF |
| 22 | static const struct of_device_id st_magn_of_match[] = { | 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 | .compatible = "st,lsm303dlhc-magn", | 28 | .compatible = "st,lsm303dlhc-magn", |
| 25 | .data = LSM303DLHC_MAGN_DEV_NAME, | 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 | static const struct i2c_device_id st_magn_id_table[] = { | 77 | static const struct i2c_device_id st_magn_id_table[] = { |
| 78 | { LSM303DLH_MAGN_DEV_NAME }, | ||
| 74 | { LSM303DLHC_MAGN_DEV_NAME }, | 79 | { LSM303DLHC_MAGN_DEV_NAME }, |
| 75 | { LSM303DLM_MAGN_DEV_NAME }, | 80 | { LSM303DLM_MAGN_DEV_NAME }, |
| 76 | { LIS3MDL_MAGN_DEV_NAME }, | 81 | { LIS3MDL_MAGN_DEV_NAME }, |
| @@ -315,7 +315,6 @@ static int hid_incl_3d_probe(struct platform_device *pdev) · 314 unmodified lines | |||
| 315 | struct iio_dev *indio_dev; | 315 | struct iio_dev *indio_dev; |
| 316 | struct incl_3d_state *incl_state; | 316 | struct incl_3d_state *incl_state; |
| 317 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 317 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 318 | struct iio_chan_spec *channels; | ||
| 319 | 318 | ||
| 320 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 319 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 321 | sizeof(struct incl_3d_state)); | 320 | sizeof(struct incl_3d_state)); |
| @@ -336,21 +335,22 @@ static int hid_incl_3d_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 336 | return ret; | 335 | return ret; |
| 337 | } | 336 | } |
| 338 | 337 | ||
| 339 | channels = kmemdup(incl_3d_channels, sizeof(incl_3d_channels), | 338 | indio_dev->channels = kmemdup(incl_3d_channels, |
| 340 | GFP_KERNEL); | 339 | sizeof(incl_3d_channels), GFP_KERNEL); |
| 341 | if (!channels) { | 340 | if (!indio_dev->channels) { |
| 342 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | 341 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 343 | return -ENOMEM; | 342 | return -ENOMEM; |
| 344 | } | 343 | } |
| 345 | 344 | ||
| 346 | ret = incl_3d_parse_report(pdev, hsdev, channels, | 345 | ret = incl_3d_parse_report(pdev, hsdev, |
| 347 | HID_USAGE_SENSOR_INCLINOMETER_3D, incl_state); | 346 | (struct iio_chan_spec *)indio_dev->channels, |
| 347 | HID_USAGE_SENSOR_INCLINOMETER_3D, | ||
| 348 | incl_state); | ||
| 348 | if (ret) { | 349 | if (ret) { |
| 349 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 350 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 350 | goto error_free_dev_mem; | 351 | goto error_free_dev_mem; |
| 351 | } | 352 | } |
| 352 | 353 | ||
| 353 | indio_dev->channels = channels; | ||
| 354 | indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels); | 354 | indio_dev->num_channels = ARRAY_SIZE(incl_3d_channels); |
| 355 | indio_dev->dev.parent = &pdev->dev; | 355 | indio_dev->dev.parent = &pdev->dev; |
| 356 | indio_dev->info = &incl_3d_info; | 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 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 422 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 423 | .name = "HID-SENSOR-200086", | 423 | .name = "HID-SENSOR-200086", |
| @@ -222,7 +222,6 @@ static int hid_dev_rot_probe(struct platform_device *pdev) · 221 unmodified lines | |||
| 222 | struct iio_dev *indio_dev; | 222 | struct iio_dev *indio_dev; |
| 223 | struct dev_rot_state *rot_state; | 223 | struct dev_rot_state *rot_state; |
| 224 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 224 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 225 | struct iio_chan_spec *channels; | ||
| 226 | 225 | ||
| 227 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 226 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 228 | sizeof(struct dev_rot_state)); | 227 | sizeof(struct dev_rot_state)); |
| @@ -243,21 +242,23 @@ static int hid_dev_rot_probe(struct platform_device *pdev) · 14 unmodified lines | |||
| 243 | return ret; | 242 | return ret; |
| 244 | } | 243 | } |
| 245 | 244 | ||
| 246 | channels = devm_kmemdup(&pdev->dev, dev_rot_channels, | 245 | indio_dev->channels = devm_kmemdup(&pdev->dev, dev_rot_channels, |
| 247 | sizeof(dev_rot_channels), GFP_KERNEL); | 246 | sizeof(dev_rot_channels), |
| 248 | if (!channels) { | 247 | GFP_KERNEL); |
| 248 | if (!indio_dev->channels) { | ||
| 249 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | 249 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 250 | return -ENOMEM; | 250 | return -ENOMEM; |
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | ret = dev_rot_parse_report(pdev, hsdev, channels, | 253 | ret = dev_rot_parse_report(pdev, hsdev, |
| 254 | HID_USAGE_SENSOR_DEVICE_ORIENTATION, rot_state); | 254 | (struct iio_chan_spec *)indio_dev->channels, |
| 255 | HID_USAGE_SENSOR_DEVICE_ORIENTATION, | ||
| 256 | rot_state); | ||
| 255 | if (ret) { | 257 | if (ret) { |
| 256 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 258 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 257 | return ret; | 259 | return ret; |
| 258 | } | 260 | } |
| 259 | 261 | ||
| 260 | indio_dev->channels = channels; | ||
| 261 | indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); | 262 | indio_dev->num_channels = ARRAY_SIZE(dev_rot_channels); |
| 262 | indio_dev->dev.parent = &pdev->dev; | 263 | indio_dev->dev.parent = &pdev->dev; |
| 263 | indio_dev->info = &dev_rot_info; | 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 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 327 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 327 | .name = "HID-SENSOR-20008a", | 328 | .name = "HID-SENSOR-20008a", |
| @@ -260,7 +260,6 @@ static int hid_press_probe(struct platform_device *pdev) · 259 unmodified lines | |||
| 260 | struct iio_dev *indio_dev; | 260 | struct iio_dev *indio_dev; |
| 261 | struct press_state *press_state; | 261 | struct press_state *press_state; |
| 262 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; | 262 | struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data; |
| 263 | struct iio_chan_spec *channels; | ||
| 264 | 263 | ||
| 265 | indio_dev = devm_iio_device_alloc(&pdev->dev, | 264 | indio_dev = devm_iio_device_alloc(&pdev->dev, |
| 266 | sizeof(struct press_state)); | 265 | sizeof(struct press_state)); |
| @@ -280,20 +279,21 @@ static int hid_press_probe(struct platform_device *pdev) · 13 unmodified lines | |||
| 280 | return ret; | 279 | return ret; |
| 281 | } | 280 | } |
| 282 | 281 | ||
| 283 | channels = kmemdup(press_channels, sizeof(press_channels), GFP_KERNEL); | 282 | indio_dev->channels = kmemdup(press_channels, sizeof(press_channels), |
| 284 | if (!channels) { | 283 | GFP_KERNEL); |
| 284 | if (!indio_dev->channels) { | ||
| 285 | dev_err(&pdev->dev, "failed to duplicate channels\n"); | 285 | dev_err(&pdev->dev, "failed to duplicate channels\n"); |
| 286 | return -ENOMEM; | 286 | return -ENOMEM; |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | ret = press_parse_report(pdev, hsdev, channels, | 289 | ret = press_parse_report(pdev, hsdev, |
| 290 | HID_USAGE_SENSOR_PRESSURE, press_state); | 290 | (struct iio_chan_spec *)indio_dev->channels, |
| 291 | HID_USAGE_SENSOR_PRESSURE, press_state); | ||
| 291 | if (ret) { | 292 | if (ret) { |
| 292 | dev_err(&pdev->dev, "failed to setup attributes\n"); | 293 | dev_err(&pdev->dev, "failed to setup attributes\n"); |
| 293 | goto error_free_dev_mem; | 294 | goto error_free_dev_mem; |
| 294 | } | 295 | } |
| 295 | 296 | ||
| 296 | indio_dev->channels = channels; | ||
| 297 | indio_dev->num_channels = | 297 | indio_dev->num_channels = |
| 298 | ARRAY_SIZE(press_channels); | 298 | ARRAY_SIZE(press_channels); |
| 299 | indio_dev->dev.parent = &pdev->dev; | 299 | indio_dev->dev.parent = &pdev->dev; |
| @@ -360,7 +360,7 @@ static int hid_press_remove(struct platform_device *pdev) · 60 unmodified lines | |||
| 360 | return 0; | 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 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ | 365 | /* Format: HID-SENSOR-usage_id_in_hex_lowercase */ |
| 366 | .name = "HID-SENSOR-200031", | 366 | .name = "HID-SENSOR-200031", |
| @@ -18,6 +18,8 @@ · 17 unmodified lines | |||
| 18 | #include <linux/acpi.h> | 18 | #include <linux/acpi.h> |
| 19 | #include <linux/gpio/consumer.h> | 19 | #include <linux/gpio/consumer.h> |
| 20 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
| 21 | #include <linux/pm.h> | ||
| 22 | #include <linux/delay.h> | ||
| 21 | 23 | ||
| 22 | #include <linux/iio/iio.h> | 24 | #include <linux/iio/iio.h> |
| 23 | #include <linux/iio/buffer.h> | 25 | #include <linux/iio/buffer.h> |
| @@ -29,7 +31,9 @@ · 5 unmodified lines | |||
| 29 | 31 | ||
| 30 | #define SX9500_DRIVER_NAME "sx9500" | 32 | #define SX9500_DRIVER_NAME "sx9500" |
| 31 | #define SX9500_IRQ_NAME "sx9500_event" | 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 | /* Register definitions. */ | 38 | /* Register definitions. */ |
| 35 | #define SX9500_REG_IRQ_SRC 0x00 | 39 | #define SX9500_REG_IRQ_SRC 0x00 |
| @@ -73,6 +77,7 @@ · 37 unmodified lines | |||
| 73 | #define SX9500_CONVDONE_IRQ BIT(3) | 77 | #define SX9500_CONVDONE_IRQ BIT(3) |
| 74 | 78 | ||
| 75 | #define SX9500_PROXSTAT_SHIFT 4 | 79 | #define SX9500_PROXSTAT_SHIFT 4 |
| 80 | #define SX9500_COMPSTAT_MASK GENMASK(3, 0) | ||
| 76 | 81 | ||
| 77 | #define SX9500_NUM_CHANNELS 4 | 82 | #define SX9500_NUM_CHANNELS 4 |
| 78 | 83 | ||
| @@ -81,6 +86,7 @@ struct sx9500_data { · 2 unmodified lines | |||
| 81 | struct i2c_client *client; | 86 | struct i2c_client *client; |
| 82 | struct iio_trigger *trig; | 87 | struct iio_trigger *trig; |
| 83 | struct regmap *regmap; | 88 | struct regmap *regmap; |
| 89 | struct gpio_desc *gpiod_rst; | ||
| 84 | /* | 90 | /* |
| 85 | * Last reading of the proximity status for each channel. We | 91 | * Last reading of the proximity status for each channel. We |
| 86 | * only send an event to user space when this changes. | 92 | * only send an event to user space when this changes. |
| @@ -89,6 +95,11 @@ struct sx9500_data { · 2 unmodified lines | |||
| 89 | bool event_enabled[SX9500_NUM_CHANNELS]; | 95 | bool event_enabled[SX9500_NUM_CHANNELS]; |
| 90 | bool trigger_enabled; | 96 | bool trigger_enabled; |
| 91 | u16 *buffer; | 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 | static const struct iio_event_spec sx9500_events[] = { | 105 | static const struct iio_event_spec sx9500_events[] = { |
| @@ -139,6 +150,10 @@ static const struct { · 44 unmodified lines | |||
| 139 | {2, 500000}, | 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 | static const struct regmap_range sx9500_writable_reg_ranges[] = { | 157 | static const struct regmap_range sx9500_writable_reg_ranges[] = { |
| 143 | regmap_reg_range(SX9500_REG_IRQ_MSK, SX9500_REG_IRQ_MSK), | 158 | regmap_reg_range(SX9500_REG_IRQ_MSK, SX9500_REG_IRQ_MSK), |
| 144 | regmap_reg_range(SX9500_REG_PROX_CTRL0, SX9500_REG_PROX_CTRL8), | 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 | .volatile_table = &sx9500_volatile_regs, | 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 | const struct iio_chan_spec *chan, | 270 | const struct iio_chan_spec *chan, |
| 196 | int *val) | 271 | int *val) |
| 197 | { | 272 | { |
| @@ -211,6 +286,79 @@ static int sx9500_read_proximity(struct sx9500_data *data, · 13 unmodified lines | |||
| 211 | return IIO_VAL_INT; | 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 | static int sx9500_read_samp_freq(struct sx9500_data *data, | 362 | static int sx9500_read_samp_freq(struct sx9500_data *data, |
| 215 | int *val, int *val2) | 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 | int *val, int *val2, long mask) | 384 | int *val, int *val2, long mask) |
| 237 | { | 385 | { |
| 238 | struct sx9500_data *data = iio_priv(indio_dev); | 386 | struct sx9500_data *data = iio_priv(indio_dev); |
| 239 | int ret; | ||
| 240 | 387 | ||
| 241 | switch (chan->type) { | 388 | switch (chan->type) { |
| 242 | case IIO_PROXIMITY: | 389 | case IIO_PROXIMITY: |
| @@ -244,10 +391,7 @@ static int sx9500_read_raw(struct iio_dev *indio_dev, · 1 unmodified line | |||
| 244 | case IIO_CHAN_INFO_RAW: | 391 | case IIO_CHAN_INFO_RAW: |
| 245 | if (iio_buffer_enabled(indio_dev)) | 392 | if (iio_buffer_enabled(indio_dev)) |
| 246 | return -EBUSY; | 393 | return -EBUSY; |
| 247 | mutex_lock(&data->mutex); | 394 | return sx9500_read_proximity(data, chan, val); |
| 248 | ret = sx9500_read_proximity(data, chan, val); | ||
| 249 | mutex_unlock(&data->mutex); | ||
| 250 | return ret; | ||
| 251 | case IIO_CHAN_INFO_SAMP_FREQ: | 395 | case IIO_CHAN_INFO_SAMP_FREQ: |
| 252 | return sx9500_read_samp_freq(data, val, val2); | 396 | return sx9500_read_samp_freq(data, val, val2); |
| 253 | default: | 397 | default: |
| @@ -318,28 +462,16 @@ static irqreturn_t sx9500_irq_handler(int irq, void *private) · 64 unmodified lines | |||
| 318 | return IRQ_WAKE_THREAD; | 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 | int ret; | 467 | int ret; |
| 326 | unsigned int val, chan; | 468 | unsigned int val, chan; |
| 327 | 469 | struct sx9500_data *data = iio_priv(indio_dev); | |
| 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; | ||
| 338 | 470 | ||
| 339 | ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); | 471 | ret = regmap_read(data->regmap, SX9500_REG_STAT, &val); |
| 340 | if (ret < 0) { | 472 | if (ret < 0) { |
| 341 | dev_err(&data->client->dev, "i2c transfer error in irq\n"); | 473 | dev_err(&data->client->dev, "i2c transfer error in irq\n"); |
| 342 | goto out; | 474 | return; |
| 343 | } | 475 | } |
| 344 | 476 | ||
| 345 | val >>= SX9500_PROXSTAT_SHIFT; | 477 | val >>= SX9500_PROXSTAT_SHIFT; |
| @@ -354,15 +486,34 @@ static irqreturn_t sx9500_irq_thread_handler(int irq, void *private) · 8 unmodified lines | |||
| 354 | /* No change on this channel. */ | 486 | /* No change on this channel. */ |
| 355 | continue; | 487 | continue; |
| 356 | 488 | ||
| 357 | dir = new_prox ? IIO_EV_DIR_FALLING : | 489 | dir = new_prox ? IIO_EV_DIR_FALLING : IIO_EV_DIR_RISING; |
| 358 | IIO_EV_DIR_RISING; | 490 | ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, chan, |
| 359 | ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, | 491 | IIO_EV_TYPE_THRESH, dir); |
| 360 | chan, | ||
| 361 | IIO_EV_TYPE_THRESH, | ||
| 362 | dir); | ||
| 363 | iio_push_event(indio_dev, ev, iio_get_time_ns()); | 492 | iio_push_event(indio_dev, ev, iio_get_time_ns()); |
| 364 | data->prox_stat[chan] = new_prox; | 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 | out: | 518 | out: |
| 368 | mutex_unlock(&data->mutex); | 519 | mutex_unlock(&data->mutex); |
| @@ -391,9 +542,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev, · 22 unmodified lines | |||
| 391 | int state) | 542 | int state) |
| 392 | { | 543 | { |
| 393 | struct sx9500_data *data = iio_priv(indio_dev); | 544 | struct sx9500_data *data = iio_priv(indio_dev); |
| 394 | int ret, i; | 545 | int ret; |
| 395 | bool any_active = false; | ||
| 396 | unsigned int irqmask; | ||
| 397 | 546 | ||
| 398 | if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || | 547 | if (chan->type != IIO_PROXIMITY || type != IIO_EV_TYPE_THRESH || |
| 399 | dir != IIO_EV_DIR_EITHER) | 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 | mutex_lock(&data->mutex); | 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++) | 569 | data->event_enabled[chan->channel] = state; |
| 407 | if (data->event_enabled[i]) { | 570 | goto out_unlock; |
| 408 | any_active = true; | ||
| 409 | break; | ||
| 410 | } | ||
| 411 | 571 | ||
| 412 | irqmask = SX9500_CLOSE_IRQ | SX9500_FAR_IRQ; | 572 | out_undo_chan: |
| 413 | if (any_active) | 573 | if (state == 1) |
| 414 | ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, | 574 | sx9500_dec_chan_users(data, chan->channel); |
| 415 | irqmask, irqmask); | ||
| 416 | else | 575 | else |
| 417 | ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, | 576 | sx9500_inc_chan_users(data, chan->channel); |
| 418 | irqmask, 0); | 577 | out_unlock: |
| 419 | |||
| 420 | mutex_unlock(&data->mutex); | 578 | mutex_unlock(&data->mutex); |
| 421 | |||
| 422 | return ret; | 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 | mutex_lock(&data->mutex); | 627 | mutex_lock(&data->mutex); |
| 471 | 628 | ||
| 472 | ret = regmap_update_bits(data->regmap, SX9500_REG_IRQ_MSK, | 629 | if (state) |
| 473 | SX9500_CONVDONE_IRQ, | 630 | ret = sx9500_inc_data_rdy_users(data); |
| 474 | state ? SX9500_CONVDONE_IRQ : 0); | 631 | else |
| 475 | if (ret == 0) | 632 | ret = sx9500_dec_data_rdy_users(data); |
| 476 | data->trigger_enabled = state; | 633 | if (ret < 0) |
| 634 | goto out; | ||
| 635 | |||
| 636 | data->trigger_enabled = state; | ||
| 477 | 637 | ||
| 638 | out: | ||
| 478 | mutex_unlock(&data->mutex); | 639 | mutex_unlock(&data->mutex); |
| 479 | 640 | ||
| 480 | return ret; | 641 | return ret; |
| @@ -496,7 +657,7 @@ static irqreturn_t sx9500_trigger_handler(int irq, void *private) · 15 unmodified lines | |||
| 496 | 657 | ||
| 497 | for_each_set_bit(bit, indio_dev->active_scan_mask, | 658 | for_each_set_bit(bit, indio_dev->active_scan_mask, |
| 498 | indio_dev->masklength) { | 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 | &val); | 661 | &val); |
| 501 | if (ret < 0) | 662 | if (ret < 0) |
| 502 | goto out; | 663 | goto out; |
| @@ -515,6 +676,62 @@ out: · 12 unmodified lines | |||
| 515 | return IRQ_HANDLED; | 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 | struct sx9500_reg_default { | 735 | struct sx9500_reg_default { |
| 519 | u8 reg; | 736 | u8 reg; |
| 520 | u8 def; | 737 | u8 def; |
| @@ -570,17 +787,57 @@ static const struct sx9500_reg_default sx9500_default_regs[] = { · 49 unmodified lines | |||
| 570 | }, | 787 | }, |
| 571 | { | 788 | { |
| 572 | .reg = SX9500_REG_PROX_CTRL0, | 789 | .reg = SX9500_REG_PROX_CTRL0, |
| 573 | /* Scan period: 30ms, all sensors enabled. */ | 790 | /* Scan period: 30ms, all sensors disabled. */ |
| 574 | .def = 0x0f, | 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 | static int sx9500_init_device(struct iio_dev *indio_dev) | 828 | static int sx9500_init_device(struct iio_dev *indio_dev) |
| 579 | { | 829 | { |
| 580 | struct sx9500_data *data = iio_priv(indio_dev); | 830 | struct sx9500_data *data = iio_priv(indio_dev); |
| 581 | int ret, i; | 831 | int ret, i; |
| 582 | unsigned int val; | 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 | ret = regmap_write(data->regmap, SX9500_REG_IRQ_MSK, 0); | 841 | ret = regmap_write(data->regmap, SX9500_REG_IRQ_MSK, 0); |
| 585 | if (ret < 0) | 842 | if (ret < 0) |
| 586 | return ret; | 843 | return ret; |
| @@ -602,33 +859,34 @@ static int sx9500_init_device(struct iio_dev *indio_dev) · 15 unmodified lines | |||
| 602 | return ret; | 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, | 865 | static void sx9500_gpio_probe(struct i2c_client *client, |
| 609 | struct sx9500_data *data) | 866 | struct sx9500_data *data) |
| 610 | { | 867 | { |
| 611 | struct device *dev; | 868 | struct device *dev; |
| 612 | struct gpio_desc *gpio; | 869 | struct gpio_desc *gpio; |
| 613 | int ret; | ||
| 614 | 870 | ||
| 615 | if (!client) | 871 | if (!client) |
| 616 | return -EINVAL; | 872 | return; |
| 617 | 873 | ||
| 618 | dev = &client->dev; | 874 | dev = &client->dev; |
| 619 | 875 | ||
| 620 | /* data ready gpio interrupt pin */ | 876 | if (client->irq <= 0) { |
| 621 | gpio = devm_gpiod_get_index(dev, SX9500_GPIO_NAME, 0, GPIOD_IN); | 877 | gpio = devm_gpiod_get_index(dev, SX9500_GPIO_INT, 0, GPIOD_IN); |
| 622 | if (IS_ERR(gpio)) { | 878 | if (IS_ERR(gpio)) |
| 623 | dev_err(dev, "acpi gpio get index failed\n"); | 879 | dev_err(dev, "gpio get irq failed\n"); |
| 624 | return PTR_ERR(gpio); | 880 | else |
| 881 | client->irq = gpiod_to_irq(gpio); | ||
| 625 | } | 882 | } |
| 626 | 883 | ||
| 627 | ret = gpiod_to_irq(gpio); | 884 | data->gpiod_rst = devm_gpiod_get_index(dev, SX9500_GPIO_RESET, |
| 628 | 885 | 0, GPIOD_OUT_HIGH); | |
| 629 | dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret); | 886 | if (IS_ERR(data->gpiod_rst)) { |
| 630 | 887 | dev_warn(dev, "gpio get reset pin failed\n"); | |
| 631 | return ret; | 888 | data->gpiod_rst = NULL; |
| 889 | } | ||
| 632 | } | 890 | } |
| 633 | 891 | ||
| 634 | static int sx9500_probe(struct i2c_client *client, | 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 | data = iio_priv(indio_dev); | 903 | data = iio_priv(indio_dev); |
| 646 | data->client = client; | 904 | data->client = client; |
| 647 | mutex_init(&data->mutex); | 905 | mutex_init(&data->mutex); |
| 906 | init_completion(&data->completion); | ||
| 648 | data->trigger_enabled = false; | 907 | data->trigger_enabled = false; |
| 649 | 908 | ||
| 650 | data->regmap = devm_regmap_init_i2c(client, &sx9500_regmap_config); | 909 | data->regmap = devm_regmap_init_i2c(client, &sx9500_regmap_config); |
| 651 | if (IS_ERR(data->regmap)) | 910 | if (IS_ERR(data->regmap)) |
| 652 | return PTR_ERR(data->regmap); | 911 | return PTR_ERR(data->regmap); |
| 653 | 912 | ||
| 654 | sx9500_init_device(indio_dev); | ||
| 655 | |||
| 656 | indio_dev->dev.parent = &client->dev; | 913 | indio_dev->dev.parent = &client->dev; |
| 657 | indio_dev->name = SX9500_DRIVER_NAME; | 914 | indio_dev->name = SX9500_DRIVER_NAME; |
| 658 | indio_dev->channels = sx9500_channels; | 915 | indio_dev->channels = sx9500_channels; |
| @@ -661,10 +918,15 @@ static int sx9500_probe(struct i2c_client *client, · 2 unmodified lines | |||
| 661 | indio_dev->modes = INDIO_DIRECT_MODE; | 918 | indio_dev->modes = INDIO_DIRECT_MODE; |
| 662 | i2c_set_clientdata(client, indio_dev); | 919 | i2c_set_clientdata(client, indio_dev); |
| 663 | 920 | ||
| 664 | if (client->irq <= 0) | 921 | sx9500_gpio_probe(client, data); |
| 665 | client->irq = 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 | ret = devm_request_threaded_irq(&client->dev, client->irq, | 930 | ret = devm_request_threaded_irq(&client->dev, client->irq, |
| 669 | sx9500_irq_handler, sx9500_irq_thread_handler, | 931 | sx9500_irq_handler, sx9500_irq_thread_handler, |
| 670 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 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 | ret = iio_triggered_buffer_setup(indio_dev, NULL, | 951 | ret = iio_triggered_buffer_setup(indio_dev, NULL, |
| 690 | sx9500_trigger_handler, NULL); | 952 | sx9500_trigger_handler, |
| 953 | &sx9500_buffer_setup_ops); | ||
| 691 | if (ret < 0) | 954 | if (ret < 0) |
| 692 | goto out_trigger_unregister; | 955 | goto out_trigger_unregister; |
| 693 | 956 | ||
| @@ -720,6 +983,49 @@ static int sx9500_remove(struct i2c_client *client) · 26 unmodified lines | |||
| 720 | return 0; | 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 | static const struct acpi_device_id sx9500_acpi_match[] = { | 1029 | static const struct acpi_device_id sx9500_acpi_match[] = { |
| 724 | {"SSX9500", 0}, | 1030 | {"SSX9500", 0}, |
| 725 | { }, | 1031 | { }, |
| @@ -728,7 +1034,7 @@ MODULE_DEVICE_TABLE(acpi, sx9500_acpi_match); · 2 unmodified lines | |||
| 728 | 1034 | ||
| 729 | static const struct i2c_device_id sx9500_id[] = { | 1035 | static const struct i2c_device_id sx9500_id[] = { |
| 730 | {"sx9500", 0}, | 1036 | {"sx9500", 0}, |
| 731 | {} | 1037 | { }, |
| 732 | }; | 1038 | }; |
| 733 | MODULE_DEVICE_TABLE(i2c, sx9500_id); | 1039 | MODULE_DEVICE_TABLE(i2c, sx9500_id); |
| 734 | 1040 | ||
| @@ -736,6 +1042,7 @@ static struct i2c_driver sx9500_driver = { · 1 unmodified line | |||
| 736 | .driver = { | 1042 | .driver = { |
| 737 | .name = SX9500_DRIVER_NAME, | 1043 | .name = SX9500_DRIVER_NAME, |
| 738 | .acpi_match_table = ACPI_PTR(sx9500_acpi_match), | 1044 | .acpi_match_table = ACPI_PTR(sx9500_acpi_match), |
| 1045 | .pm = &sx9500_pm_ops, | ||
| 739 | }, | 1046 | }, |
| 740 | .probe = sx9500_probe, | 1047 | .probe = sx9500_probe, |
| 741 | .remove = sx9500_remove, | 1048 | .remove = sx9500_remove, |
| @@ -12,12 +12,24 @@ · 11 unmodified lines | |||
| 12 | * | 12 | * |
| 13 | * (7-bit I2C slave address 0x5a, 100KHz bus speed only!) | 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 | #include <linux/err.h> | 26 | #include <linux/err.h> |
| 19 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
| 20 | #include <linux/module.h> | 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 | #include <linux/iio/iio.h> | 34 | #include <linux/iio/iio.h> |
| 23 | 35 | ||
| @@ -51,10 +63,101 @@ · 27 unmodified lines | |||
| 51 | #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */ | 63 | #define MLX90614_TIMING_WAKEUP 34 /* time to hold SDA low for wake-up */ |
| 52 | #define MLX90614_TIMING_STARTUP 250 /* time before first data after wake-up */ | 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 | struct mlx90614_data { | 68 | struct mlx90614_data { |
| 55 | struct i2c_client *client; | 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 | static int mlx90614_read_raw(struct iio_dev *indio_dev, | 161 | static int mlx90614_read_raw(struct iio_dev *indio_dev, |
| 59 | struct iio_chan_spec const *channel, int *val, | 162 | struct iio_chan_spec const *channel, int *val, |
| 60 | int *val2, long mask) | 163 | int *val2, long mask) |
| @@ -85,9 +188,19 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, · 24 unmodified lines | |||
| 85 | return -EINVAL; | 188 | return -EINVAL; |
| 86 | } | 189 | } |
| 87 | 190 | ||
| 191 | ret = mlx90614_power_get(data, true); | ||
| 192 | if (ret < 0) | ||
| 193 | return ret; | ||
| 88 | ret = i2c_smbus_read_word_data(data->client, cmd); | 194 | ret = i2c_smbus_read_word_data(data->client, cmd); |
| 195 | mlx90614_power_put(data); | ||
| 196 | |||
| 89 | if (ret < 0) | 197 | if (ret < 0) |
| 90 | return ret; | 198 | return ret; |
| 199 | |||
| 200 | /* MSB is an error flag */ | ||
| 201 | if (ret & 0x8000) | ||
| 202 | return -EIO; | ||
| 203 | |||
| 91 | *val = ret; | 204 | *val = ret; |
| 92 | return IIO_VAL_INT; | 205 | return IIO_VAL_INT; |
| 93 | case IIO_CHAN_INFO_OFFSET: | 206 | case IIO_CHAN_INFO_OFFSET: |
| @@ -97,6 +210,63 @@ static int mlx90614_read_raw(struct iio_dev *indio_dev, · 3 unmodified lines | |||
| 97 | case IIO_CHAN_INFO_SCALE: | 210 | case IIO_CHAN_INFO_SCALE: |
| 98 | *val = 20; | 211 | *val = 20; |
| 99 | return IIO_VAL_INT; | 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 | default: | 270 | default: |
| 101 | return -EINVAL; | 271 | return -EINVAL; |
| 102 | } | 272 | } |
| @@ -115,7 +285,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { · 12 unmodified lines | |||
| 115 | .type = IIO_TEMP, | 285 | .type = IIO_TEMP, |
| 116 | .modified = 1, | 286 | .modified = 1, |
| 117 | .channel2 = IIO_MOD_TEMP_OBJECT, | 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 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 290 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
| 120 | BIT(IIO_CHAN_INFO_SCALE), | 291 | BIT(IIO_CHAN_INFO_SCALE), |
| 121 | }, | 292 | }, |
| @@ -125,7 +296,8 @@ static const struct iio_chan_spec mlx90614_channels[] = { · 3 unmodified lines | |||
| 125 | .modified = 1, | 296 | .modified = 1, |
| 126 | .channel = 1, | 297 | .channel = 1, |
| 127 | .channel2 = IIO_MOD_TEMP_OBJECT, | 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 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | | 301 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | |
| 130 | BIT(IIO_CHAN_INFO_SCALE), | 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 | static const struct iio_info mlx90614_info = { | 306 | static const struct iio_info mlx90614_info = { |
| 135 | .read_raw = mlx90614_read_raw, | 307 | .read_raw = mlx90614_read_raw, |
| 308 | .write_raw = mlx90614_write_raw, | ||
| 309 | .write_raw_get_fmt = mlx90614_write_raw_get_fmt, | ||
| 136 | .driver_module = THIS_MODULE, | 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 | /* Return 0 for single sensor, 1 for dual sensor, <0 on error. */ | 405 | /* Return 0 for single sensor, 1 for dual sensor, <0 on error. */ |
| 140 | static int mlx90614_probe_num_ir_sensors(struct i2c_client *client) | 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 | data = iio_priv(indio_dev); | 432 | data = iio_priv(indio_dev); |
| 167 | i2c_set_clientdata(client, indio_dev); | 433 | i2c_set_clientdata(client, indio_dev); |
| 168 | data->client = client; | 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 | indio_dev->dev.parent = &client->dev; | 440 | indio_dev->dev.parent = &client->dev; |
| 171 | indio_dev->name = id->name; | 441 | indio_dev->name = id->name; |
| @@ -188,12 +458,30 @@ static int mlx90614_probe(struct i2c_client *client, · 16 unmodified lines | |||
| 188 | return ret; | 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 | return iio_device_register(indio_dev); | 469 | return iio_device_register(indio_dev); |
| 192 | } | 470 | } |
| 193 | 471 | ||
| 194 | static int mlx90614_remove(struct i2c_client *client) | 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 | return 0; | 486 | return 0; |
| 199 | } | 487 | } |
| @@ -204,10 +492,67 @@ static const struct i2c_device_id mlx90614_id[] = { · 4 unmodified lines | |||
| 204 | }; | 492 | }; |
| 205 | MODULE_DEVICE_TABLE(i2c, mlx90614_id); | 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 | static struct i2c_driver mlx90614_driver = { | 551 | static struct i2c_driver mlx90614_driver = { |
| 208 | .driver = { | 552 | .driver = { |
| 209 | .name = "mlx90614", | 553 | .name = "mlx90614", |
| 210 | .owner = THIS_MODULE, | 554 | .owner = THIS_MODULE, |
| 555 | .pm = &mlx90614_pm_ops, | ||
| 211 | }, | 556 | }, |
| 212 | .probe = mlx90614_probe, | 557 | .probe = mlx90614_probe, |
| 213 | .remove = mlx90614_remove, | 558 | .remove = mlx90614_remove, |
| @@ -41,8 +41,8 @@ · 40 unmodified lines | |||
| 41 | #define TMP006_CONFIG_CR_MASK 0x0e00 | 41 | #define TMP006_CONFIG_CR_MASK 0x0e00 |
| 42 | #define TMP006_CONFIG_CR_SHIFT 9 | 42 | #define TMP006_CONFIG_CR_SHIFT 9 |
| 43 | 43 | ||
| 44 | #define MANUFACTURER_MAGIC 0x5449 | 44 | #define TMP006_MANUFACTURER_MAGIC 0x5449 |
| 45 | #define DEVICE_MAGIC 0x0067 | 45 | #define TMP006_DEVICE_MAGIC 0x0067 |
| 46 | 46 | ||
| 47 | struct tmp006_data { | 47 | struct tmp006_data { |
| 48 | struct i2c_client *client; | 48 | struct i2c_client *client; |
| @@ -191,7 +191,7 @@ static bool tmp006_check_identification(struct i2c_client *client) · 142 unmodified lines | |||
| 191 | if (did < 0) | 191 | if (did < 0) |
| 192 | return false; | 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 | static int tmp006_probe(struct i2c_client *client, | 197 | static int tmp006_probe(struct i2c_client *client, |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | |||
| 15 | ***************************************************************************/ | 15 | ***************************************************************************/ |
| 16 | 16 | ||
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/version.h> | ||
| 19 | #include <linux/stringify.h> | 18 | #include <linux/stringify.h> |
| 20 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 21 | #include <linux/kthread.h> | 20 | #include <linux/kthread.h> |
| @@ -158,8 +158,8 @@ static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) · 157 unmodified lines | |||
| 158 | struct goldfish_pipe_dev *dev = pipe->dev; | 158 | struct goldfish_pipe_dev *dev = pipe->dev; |
| 159 | 159 | ||
| 160 | spin_lock_irqsave(&dev->lock, flags); | 160 | spin_lock_irqsave(&dev->lock, flags); |
| 161 | gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL, | 161 | gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, |
| 162 | dev->base + PIPE_REG_CHANNEL_HIGH); | 162 | dev->base + PIPE_REG_CHANNEL_HIGH); |
| 163 | writel(cmd, dev->base + PIPE_REG_COMMAND); | 163 | writel(cmd, dev->base + PIPE_REG_COMMAND); |
| 164 | status = readl(dev->base + PIPE_REG_STATUS); | 164 | status = readl(dev->base + PIPE_REG_STATUS); |
| 165 | spin_unlock_irqrestore(&dev->lock, flags); | 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 | struct goldfish_pipe_dev *dev = pipe->dev; | 172 | struct goldfish_pipe_dev *dev = pipe->dev; |
| 173 | 173 | ||
| 174 | spin_lock_irqsave(&dev->lock, flags); | 174 | spin_lock_irqsave(&dev->lock, flags); |
| 175 | gf_write64((u64)(unsigned long)pipe, dev->base + PIPE_REG_CHANNEL, | 175 | gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, |
| 176 | dev->base + PIPE_REG_CHANNEL_HIGH); | 176 | dev->base + PIPE_REG_CHANNEL_HIGH); |
| 177 | writel(cmd, dev->base + PIPE_REG_COMMAND); | 177 | writel(cmd, dev->base + PIPE_REG_COMMAND); |
| 178 | spin_unlock_irqrestore(&dev->lock, flags); | 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 | spin_lock_irqsave(&dev->lock, irq_flags); | 327 | spin_lock_irqsave(&dev->lock, irq_flags); |
| 328 | if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, | 328 | if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, |
| 329 | address, avail, pipe, &status)) { | 329 | address, avail, pipe, &status)) { |
| 330 | gf_write64((u64)(unsigned long)pipe, | 330 | gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, |
| 331 | dev->base + PIPE_REG_CHANNEL, | 331 | dev->base + PIPE_REG_CHANNEL_HIGH); |
| 332 | dev->base + PIPE_REG_CHANNEL_HIGH); | ||
| 333 | writel(avail, dev->base + PIPE_REG_SIZE); | 332 | writel(avail, dev->base + PIPE_REG_SIZE); |
| 334 | gf_write64(address, dev->base + PIPE_REG_ADDRESS, | 333 | gf_write_ptr((void *)address, |
| 335 | dev->base + PIPE_REG_ADDRESS_HIGH); | 334 | dev->base + PIPE_REG_ADDRESS, |
| 335 | dev->base + PIPE_REG_ADDRESS_HIGH); | ||
| 336 | writel(CMD_WRITE_BUFFER + cmd_offset, | 336 | writel(CMD_WRITE_BUFFER + cmd_offset, |
| 337 | dev->base + PIPE_REG_COMMAND); | 337 | dev->base + PIPE_REG_COMMAND); |
| 338 | status = readl(dev->base + PIPE_REG_STATUS); | 338 | status = readl(dev->base + PIPE_REG_STATUS); |
| @@ -108,8 +108,8 @@ source "drivers/staging/clocking-wizard/Kconfig" · 107 unmodified lines | |||
| 108 | 108 | ||
| 109 | source "drivers/staging/fbtft/Kconfig" | 109 | source "drivers/staging/fbtft/Kconfig" |
| 110 | 110 | ||
| 111 | source "drivers/staging/i2o/Kconfig" | ||
| 112 | |||
| 113 | source "drivers/staging/fsl-mc/Kconfig" | 111 | source "drivers/staging/fsl-mc/Kconfig" |
| 114 | 112 | ||
| 113 | source "drivers/staging/wilc1000/Kconfig" | ||
| 114 | |||
| 115 | endif # STAGING | 115 | endif # STAGING |
| @@ -23,7 +23,7 @@ obj-$(CONFIG_VT6656) += vt6656/ · 22 unmodified lines | |||
| 23 | obj-$(CONFIG_VME_BUS) += vme/ | 23 | obj-$(CONFIG_VME_BUS) += vme/ |
| 24 | obj-$(CONFIG_IIO) += iio/ | 24 | obj-$(CONFIG_IIO) += iio/ |
| 25 | obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ | 25 | obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ |
| 26 | obj-$(CONFIG_FB_SM7XX) += sm750fb/ | 26 | obj-$(CONFIG_FB_SM750) += sm750fb/ |
| 27 | obj-$(CONFIG_FB_XGI) += xgifb/ | 27 | obj-$(CONFIG_FB_XGI) += xgifb/ |
| 28 | obj-$(CONFIG_USB_EMXX) += emxx_udc/ | 28 | obj-$(CONFIG_USB_EMXX) += emxx_udc/ |
| 29 | obj-$(CONFIG_FT1000) += ft1000/ | 29 | obj-$(CONFIG_FT1000) += ft1000/ |
| @@ -46,5 +46,5 @@ obj-$(CONFIG_CRYPTO_SKEIN) += skein/ · 16 unmodified lines | |||
| 46 | obj-$(CONFIG_UNISYSSPAR) += unisys/ | 46 | obj-$(CONFIG_UNISYSSPAR) += unisys/ |
| 47 | obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ | 47 | obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/ |
| 48 | obj-$(CONFIG_FB_TFT) += fbtft/ | 48 | obj-$(CONFIG_FB_TFT) += fbtft/ |
| 49 | obj-$(CONFIG_I2O) += i2o/ | ||
| 50 | obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/ | 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 | tristate "Android timed gpio driver" | 22 | tristate "Android timed gpio driver" |
| 23 | depends on GPIOLIB && ANDROID_TIMED_OUTPUT | 23 | depends on GPIOLIB && ANDROID_TIMED_OUTPUT |
| 24 | default n | 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 | config ANDROID_LOW_MEMORY_KILLER | 30 | config ANDROID_LOW_MEMORY_KILLER |
| 27 | bool "Android Low Memory Killer" | 31 | bool "Android Low Memory Killer" |
| 28 | ---help--- | 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 | config SYNC | 40 | config SYNC |
| 32 | bool "Synchronization framework" | 41 | bool "Synchronization framework" |
| @@ -1579,6 +1579,7 @@ struct ion_device *ion_device_create(long (*custom_ioctl) · 1578 unmodified lines | |||
| 1579 | ret = misc_register(&idev->dev); | 1579 | ret = misc_register(&idev->dev); |
| 1580 | if (ret) { | 1580 | if (ret) { |
| 1581 | pr_err("ion: failed to register misc device.\n"); | 1581 | pr_err("ion: failed to register misc device.\n"); |
| 1582 | kfree(idev); | ||
| 1582 | return ERR_PTR(ret); | 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 | chunk_heap->heap.ops = &chunk_heap_ops; | 173 | chunk_heap->heap.ops = &chunk_heap_ops; |
| 174 | chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; | 174 | chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK; |
| 175 | chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE; | 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 | heap_data->size, heap_data->align); | 177 | heap_data->size, heap_data->align); |
| 178 | 178 | ||
| 179 | return &chunk_heap->heap; | 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 | * struct ion_buffer - metadata for a particular buffer | 35 | * struct ion_buffer - metadata for a particular buffer |
| 36 | * @ref: refernce count | 36 | * @ref: reference count |
| 37 | * @node: node in the ion_device buffers tree | 37 | * @node: node in the ion_device buffers tree |
| 38 | * @dev: back pointer to the ion_device | 38 | * @dev: back pointer to the ion_device |
| 39 | * @heap: back pointer to the heap the buffer came from | 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 | * an ion_phys_addr_t (and someday a phys_addr_t) | 46 | * an ion_phys_addr_t (and someday a phys_addr_t) |
| 47 | * @lock: protects the buffers cnt fields | 47 | * @lock: protects the buffers cnt fields |
| 48 | * @kmap_cnt: number of times the buffer is mapped to the kernel | 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 | * @dmap_cnt: number of times the buffer is mapped for dma | 50 | * @dmap_cnt: number of times the buffer is mapped for dma |
| 51 | * @sg_table: the sg table for the buffer if dmap_cnt is not zero | 51 | * @sg_table: the sg table for the buffer if dmap_cnt is not zero |
| 52 | * @pages: flat array of pages in the buffer -- used by fault | 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 | * ion_heap_freelist_drain - drain the deferred free list | 267 | * ion_heap_freelist_drain - drain the deferred free list |
| 268 | * @heap: the heap | 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 | * Drains the indicated amount of memory from the deferred freelist immediately. | 271 | * Drains the indicated amount of memory from the deferred freelist immediately. |
| 272 | * Returns the total amount freed. The total freed may be higher depending | 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 | return 0; | 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 | static struct platform_driver ion_test_platform_driver = { | 276 | static struct platform_driver ion_test_platform_driver = { |
| 277 | .remove = ion_test_remove, | ||
| 265 | .driver = { | 278 | .driver = { |
| 266 | .name = "ion-test", | 279 | .name = "ion-test", |
| 267 | }, | 280 | }, |
| @@ -269,13 +282,18 @@ static struct platform_driver ion_test_platform_driver = { · 1 unmodified line | |||
| 269 | 282 | ||
| 270 | static int __init ion_test_init(void) | 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 | return platform_driver_probe(&ion_test_platform_driver, ion_test_probe); | 290 | return platform_driver_probe(&ion_test_platform_driver, ion_test_probe); |
| 274 | } | 291 | } |
| 275 | 292 | ||
| 276 | static void __exit ion_test_exit(void) | 293 | static void __exit ion_test_exit(void) |
| 277 | { | 294 | { |
| 278 | platform_driver_unregister(&ion_test_platform_driver); | 295 | platform_driver_unregister(&ion_test_platform_driver); |
| 296 | platform_device_unregister(ion_test_pdev); | ||
| 279 | } | 297 | } |
| 280 | 298 | ||
| 281 | module_init(ion_test_init); | 299 | module_init(ion_test_init); |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
| 18 | #include <linux/module.h> | ||
| 18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 20 | #include "../ion.h" | 21 | #include "../ion.h" |
| @@ -156,20 +156,27 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc) · 155 unmodified lines | |||
| 156 | p->pid, p->comm, oom_score_adj, tasksize); | 156 | p->pid, p->comm, oom_score_adj, tasksize); |
| 157 | } | 157 | } |
| 158 | if (selected) { | 158 | if (selected) { |
| 159 | lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n", | 159 | task_lock(selected); |
| 160 | selected->pid, selected->comm, | 160 | if (!selected->mm) { |
| 161 | selected_oom_score_adj, selected_tasksize); | 161 | /* Already exited, cannot do mark_tsk_oom_victim() */ |
| 162 | lowmem_deathpending_timeout = jiffies + HZ; | 162 | task_unlock(selected); |
| 163 | goto out; | ||
| 164 | } | ||
| 163 | /* | 165 | /* |
| 164 | * FIXME: lowmemorykiller shouldn't abuse global OOM killer | 166 | * FIXME: lowmemorykiller shouldn't abuse global OOM killer |
| 165 | * infrastructure. There is no real reason why the selected | 167 | * infrastructure. There is no real reason why the selected |
| 166 | * task should have access to the memory reserves. | 168 | * task should have access to the memory reserves. |
| 167 | */ | 169 | */ |
| 168 | mark_oom_victim(selected); | 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 | send_sig(SIGKILL, selected, 0); | 176 | send_sig(SIGKILL, selected, 0); |
| 170 | rem += selected_tasksize; | 177 | rem += selected_tasksize; |
| 171 | } | 178 | } |
| 172 | 179 | out: | |
| 173 | lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n", | 180 | lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n", |
| 174 | sc->nr_to_scan, sc->gfp_mask, rem); | 181 | sc->nr_to_scan, sc->gfp_mask, rem); |
| 175 | rcu_read_unlock(); | 182 | rcu_read_unlock(); |
| @@ -179,7 +179,7 @@ struct ion_custom_data { · 178 unmodified lines | |||
| 179 | * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory | 179 | * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory |
| 180 | * | 180 | * |
| 181 | * Deprecated in favor of using the dma_buf api's correctly (syncing | 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 | * If necessary should be used after touching a cached buffer from the cpu, | 183 | * If necessary should be used after touching a cached buffer from the cpu, |
| 184 | * this will make the buffer in memory coherent. | 184 | * this will make the buffer in memory coherent. |
| 185 | */ | 185 | */ |
| @@ -1,7 +1,6 @@ | |||
| 1 | config STAGING_BOARD | 1 | config STAGING_BOARD |
| 2 | bool "Staging Board Support" | 2 | bool "Staging Board Support" |
| 3 | depends on OF_ADDRESS | 3 | depends on OF_ADDRESS |
| 4 | depends on BROKEN | ||
| 5 | help | 4 | help |
| 6 | Select to enable per-board staging support code. | 5 | Select to enable per-board staging support code. |
| 7 | 6 | ||
| @@ -1,2 +1,3 @@ | |||
| 1 | obj-y := board.o | 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 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/irq.h> | ||
| 2 | #include <linux/device.h> | 15 | #include <linux/device.h> |
| 3 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 4 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 5 | #include <linux/of_address.h> | 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 | #include "board.h" | 23 | #include "board.h" |
| 7 | 24 | ||
| 25 | static struct device_node *irqc_node __initdata; | ||
| 26 | static unsigned int irqc_base __initdata; | ||
| 27 | |||
| 8 | static bool find_by_address(u64 base_address) | 28 | static bool find_by_address(u64 base_address) |
| 9 | { | 29 | { |
| 10 | struct device_node *dn = of_find_all_nodes(NULL); | 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 | return false; /* Nothing found */ | 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 | #ifndef __BOARD_H__ | 1 | #ifndef __BOARD_H__ |
| 2 | #define __BOARD_H__ | 2 | #define __BOARD_H__ |
| 3 | |||
| 3 | #include <linux/init.h> | 4 | #include <linux/init.h> |
| 4 | #include <linux/of.h> | 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 | bool board_staging_dt_node_available(const struct resource *resource, | 25 | bool board_staging_dt_node_available(const struct resource *resource, |
| 7 | unsigned int num_resources); | 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 | #define board_staging(str, fn) \ | 34 | #define board_staging(str, fn) \ |
| 10 | static int __init runtime_board_check(void) \ | 35 | static int __init runtime_board_check(void) \ |
| @@ -15,6 +40,6 @@ static int __init runtime_board_check(void) \ · 4 unmodified lines | |||
| 15 | return 0; \ | 40 | return 0; \ |
| 16 | } \ | 41 | } \ |
| 17 | \ | 42 | \ |
| 18 | late_initcall(runtime_board_check) | 43 | device_initcall(runtime_board_check) |
| 19 | 44 | ||
| 20 | #endif /* __BOARD_H__ */ | 45 | #endif /* __BOARD_H__ */ |
| @@ -4,16 +4,22 @@ · 3 unmodified lines | |||
| 4 | #include <linux/platform_device.h> | 4 | #include <linux/platform_device.h> |
| 5 | #include "board.h" | 5 | #include "board.h" |
| 6 | 6 | ||
| 7 | static const struct resource usbs1_res[] __initconst = { | 7 | static struct resource usbs1_res[] __initdata = { |
| 8 | DEFINE_RES_MEM(0xe2800000, 0x2000), | 8 | DEFINE_RES_MEM(0xe2800000, 0x2000), |
| 9 | DEFINE_RES_IRQ(159), | 9 | DEFINE_RES_IRQ(159), |
| 10 | }; | 10 | }; |
| 11 | 11 | ||
| 12 | static void __init kzm9d_init(void) | 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 | platform_device_register_simple("emxx_udc", -1, usbs1_res, | 20 | platform_device_register_simple("emxx_udc", -1, usbs1_res, |
| 16 | ARRAY_SIZE(usbs1_res)); | 21 | ARRAY_SIZE(usbs1_res)); |
| 22 | } | ||
| 17 | } | 23 | } |
| 18 | 24 | ||
| 19 | board_staging("renesas,kzm9d", kzm9d_init); | 25 | board_staging("renesas,kzm9d", kzm9d_init); |
| @@ -1247,16 +1247,22 @@ config COMEDI_8254 · 1246 unmodified lines | |||
| 1247 | tristate | 1247 | tristate |
| 1248 | 1248 | ||
| 1249 | config COMEDI_8255 | 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 | ---help--- | 1255 | ---help--- |
| 1252 | Enable generic 8255 support. | 1256 | Enable support for 8255 digital I/O as a standalone driver. |
| 1253 | 1257 | ||
| 1254 | You should enable compilation this driver if you plan to use a board | 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 | 1259 | that has an 8255 chip at a known I/O base address and there are no |
| 1256 | configure the 8255 subdevice automatically. | 1260 | other Comedi drivers for the board. |
| 1257 | 1261 | ||
| 1258 | Note that most PCI based 8255 boards use the 8255_pci driver as a | 1262 | Note that Comedi drivers for most multi-function boards incorporating |
| 1259 | wrapper around this driver. | 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 | To compile this driver as a module, choose M here: the module will be | 1267 | To compile this driver as a module, choose M here: the module will be |
| 1262 | called 8255. | 1268 | called 8255. |
| @@ -217,7 +217,7 @@ · 216 unmodified lines | |||
| 217 | #define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */ | 217 | #define SDF_RUNNING 0x08000000 /* subdevice is acquiring data */ |
| 218 | #define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */ | 218 | #define SDF_LSAMPL 0x10000000 /* subdevice uses 32-bit samples */ |
| 219 | #define SDF_PACKED 0x20000000 /* subdevice can do packed DIO */ | 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 | #define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */ | 221 | #define SDF_PWM_COUNTER SDF_MODE0 /* PWM can automatically switch off */ |
| 222 | #define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */ | 222 | #define SDF_PWM_HBRIDGE SDF_MODE1 /* PWM is signed (H-bridge) */ |
| 223 | 223 | ||
| @@ -43,6 +43,23 @@ · 42 unmodified lines | |||
| 43 | 43 | ||
| 44 | #include "comedi_internal.h" | 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 | * struct comedi_file - per-file private data for comedi device | 64 | * struct comedi_file - per-file private data for comedi device |
| 48 | * @dev: comedi_device struct | 65 | * @dev: comedi_device struct |
| @@ -679,8 +696,28 @@ static bool comedi_is_subdevice_idle(struct comedi_subdevice *s) · 630 unmodified lines | |||
| 679 | return !(runflags & COMEDI_SRF_BUSY_MASK); | 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 | * @s: comedi_subdevice struct | 721 | * @s: comedi_subdevice struct |
| 685 | * @size: size of the memory to allocate | 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 | s->private = kzalloc(size, GFP_KERNEL); | 729 | s->private = kzalloc(size, GFP_KERNEL); |
| 693 | if (s->private) | 730 | if (s->private) |
| 694 | s->runflags |= COMEDI_SRF_FREE_SPRIV; | 731 | comedi_set_spriv_auto_free(s); |
| 695 | return s->private; | 732 | return s->private; |
| 696 | } | 733 | } |
| 697 | EXPORT_SYMBOL_GPL(comedi_alloc_spriv); | 734 | EXPORT_SYMBOL_GPL(comedi_alloc_spriv); |
| @@ -1048,11 +1085,6 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, · 350 unmodified lines | |||
| 1048 | if (put_user(x, it.rangelist + i)) | 1085 | if (put_user(x, it.rangelist + i)) |
| 1049 | return -EFAULT; | 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 | return 0; | 1090 | return 0; |
| @@ -1725,7 +1757,7 @@ cleanup: · 666 unmodified lines | |||
| 1725 | 1757 | ||
| 1726 | /* | 1758 | /* |
| 1727 | * COMEDI_CMDTEST ioctl | 1759 | * COMEDI_CMDTEST ioctl |
| 1728 | * asynchronous aquisition command testing | 1760 | * asynchronous acquisition command testing |
| 1729 | * | 1761 | * |
| 1730 | * arg: | 1762 | * arg: |
| 1731 | * pointer to comedi_cmd structure | 1763 | * pointer to comedi_cmd structure |
| @@ -33,6 +33,7 @@ struct comedi_buf_map *comedi_buf_map_from_subdev_get( · 32 unmodified lines | |||
| 33 | struct comedi_subdevice *s); | 33 | struct comedi_subdevice *s); |
| 34 | unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s); | 34 | unsigned int comedi_buf_write_n_allocated(struct comedi_subdevice *s); |
| 35 | void comedi_device_cancel_all(struct comedi_device *dev); | 35 | void comedi_device_cancel_all(struct comedi_device *dev); |
| 36 | bool comedi_can_auto_free_spriv(struct comedi_subdevice *s); | ||
| 36 | 37 | ||
| 37 | extern unsigned int comedi_default_buf_size_kb; | 38 | extern unsigned int comedi_default_buf_size_kb; |
| 38 | extern unsigned int comedi_default_buf_maxsize_kb; | 39 | extern unsigned int comedi_default_buf_maxsize_kb; |
| @@ -227,12 +227,12 @@ struct comedi_async { · 226 unmodified lines | |||
| 227 | * @COMEDI_CB_ERROR_MASK: events that indicate an error has occurred | 227 | * @COMEDI_CB_ERROR_MASK: events that indicate an error has occurred |
| 228 | * @COMEDI_CB_CANCEL_MASK: events that will cancel an async command | 228 | * @COMEDI_CB_CANCEL_MASK: events that will cancel an async command |
| 229 | */ | 229 | */ |
| 230 | #define COMEDI_CB_EOS (1 << 0) | 230 | #define COMEDI_CB_EOS BIT(0) |
| 231 | #define COMEDI_CB_EOA (1 << 1) | 231 | #define COMEDI_CB_EOA BIT(1) |
| 232 | #define COMEDI_CB_BLOCK (1 << 2) | 232 | #define COMEDI_CB_BLOCK BIT(2) |
| 233 | #define COMEDI_CB_EOBUF (1 << 3) | 233 | #define COMEDI_CB_EOBUF BIT(3) |
| 234 | #define COMEDI_CB_ERROR (1 << 4) | 234 | #define COMEDI_CB_ERROR BIT(4) |
| 235 | #define COMEDI_CB_OVERFLOW (1 << 5) | 235 | #define COMEDI_CB_OVERFLOW BIT(5) |
| 236 | 236 | ||
| 237 | #define COMEDI_CB_ERROR_MASK (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW) | 237 | #define COMEDI_CB_ERROR_MASK (COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW) |
| 238 | #define COMEDI_CB_CANCEL_MASK (COMEDI_CB_EOA | COMEDI_CB_ERROR_MASK) | 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 | struct comedi_device *comedi_dev_get_from_minor(unsigned minor); | 303 | struct comedi_device *comedi_dev_get_from_minor(unsigned minor); |
| 304 | int comedi_dev_put(struct comedi_device *dev); | 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 | bool comedi_is_subdevice_running(struct comedi_subdevice *s); | 306 | bool comedi_is_subdevice_running(struct comedi_subdevice *s); |
| 324 | 307 | ||
| 325 | void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size); | 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 | int comedi_check_chanlist(struct comedi_subdevice *s, | 311 | int comedi_check_chanlist(struct comedi_subdevice *s, |
| 328 | int n, | 312 | int n, |
| @@ -125,7 +125,7 @@ static void comedi_device_detach_cleanup(struct comedi_device *dev) · 124 unmodified lines | |||
| 125 | if (dev->subdevices) { | 125 | if (dev->subdevices) { |
| 126 | for (i = 0; i < dev->n_subdevices; i++) { | 126 | for (i = 0; i < dev->n_subdevices; i++) { |
| 127 | s = &dev->subdevices[i]; | 127 | s = &dev->subdevices[i]; |
| 128 | if (s->runflags & COMEDI_SRF_FREE_SPRIV) | 128 | if (comedi_can_auto_free_spriv(s)) |
| 129 | kfree(s->private); | 129 | kfree(s->private); |
| 130 | comedi_free_subdevice_minor(s); | 130 | comedi_free_subdevice_minor(s); |
| 131 | if (s->async) { | 131 | if (s->async) { |
| @@ -53,221 +53,6 @@ · 52 unmodified lines | |||
| 53 | 53 | ||
| 54 | #include "8255.h" | 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 | static int dev_8255_attach(struct comedi_device *dev, | 56 | static int dev_8255_attach(struct comedi_device *dev, |
| 272 | struct comedi_devconfig *it) | 57 | struct comedi_devconfig *it) |
| 273 | { | 58 | { |
| @@ -306,8 +91,15 @@ static int dev_8255_attach(struct comedi_device *dev, · 32 unmodified lines | |||
| 306 | s->type = COMEDI_SUBD_UNUSED; | 91 | s->type = COMEDI_SUBD_UNUSED; |
| 307 | } else { | 92 | } else { |
| 308 | ret = subdev_8255_init(dev, s, NULL, iobase); | 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 | return ret; | 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 | static void dev_8255_detach(struct comedi_device *dev) | 109 | static void dev_8255_detach(struct comedi_device *dev) |
| 318 | { | 110 | { |
| 319 | struct comedi_subdevice *s; | 111 | struct comedi_subdevice *s; |
| 320 | struct subdev_8255_private *spriv; | ||
| 321 | int i; | 112 | int i; |
| 322 | 113 | ||
| 323 | for (i = 0; i < dev->n_subdevices; i++) { | 114 | for (i = 0; i < dev->n_subdevices; i++) { |
| 324 | s = &dev->subdevices[i]; | 115 | s = &dev->subdevices[i]; |
| 325 | if (s->type != COMEDI_SUBD_UNUSED) { | 116 | if (s->type != COMEDI_SUBD_UNUSED) { |
| 326 | spriv = s->private; | 117 | unsigned long regbase = subdev_8255_regbase(s); |
| 327 | release_region(spriv->regbase, I8255_SIZE); | 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 | module_comedi_driver(dev_8255_driver); | 130 | module_comedi_driver(dev_8255_driver); |
| 339 | 131 | ||
| 340 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | 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 | MODULE_LICENSE("GPL"); | 134 | MODULE_LICENSE("GPL"); |
| @@ -19,8 +19,6 @@ · 18 unmodified lines | |||
| 19 | #ifndef _8255_H | 19 | #ifndef _8255_H |
| 20 | #define _8255_H | 20 | #define _8255_H |
| 21 | 21 | ||
| 22 | #include "../comedidev.h" | ||
| 23 | |||
| 24 | #define I8255_SIZE 0x04 | 22 | #define I8255_SIZE 0x04 |
| 25 | 23 | ||
| 26 | #define I8255_DATA_A_REG 0x00 | 24 | #define I8255_DATA_A_REG 0x00 |
| @@ -35,14 +33,19 @@ · 8 unmodified lines | |||
| 35 | #define I8255_CTRL_A_MODE(x) ((x) << 5) | 33 | #define I8255_CTRL_A_MODE(x) ((x) << 5) |
| 36 | #define I8255_CTRL_CW (1 << 7) | 34 | #define I8255_CTRL_CW (1 << 7) |
| 37 | 35 | ||
| 38 | int subdev_8255_init(struct comedi_device *, struct comedi_subdevice *, | 36 | struct comedi_device; |
| 39 | int (*io)(struct comedi_device *, | 37 | struct comedi_subdevice; |
| 40 | int, int, int, unsigned long), | 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 | unsigned long regbase); | 42 | unsigned long regbase); |
| 42 | 43 | ||
| 43 | int subdev_8255_mm_init(struct comedi_device *, struct comedi_subdevice *, | 44 | int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s, |
| 44 | int (*io)(struct comedi_device *, | 45 | int (*io)(struct comedi_device *dev, int dir, int port, |
| 45 | int, int, int, unsigned long), | 46 | int data, unsigned long regbase), |
| 46 | unsigned long regbase); | 47 | unsigned long regbase); |
| 47 | 48 | ||
| 49 | unsigned long subdev_8255_regbase(struct comedi_subdevice *s); | ||
| 50 | |||
| 48 | #endif | 51 | #endif |
| @@ -139,7 +139,8 @@ obj-$(CONFIG_COMEDI_NI_TIOCMD) += ni_tiocmd.o · 138 unmodified lines | |||
| 139 | obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc_common.o | 139 | obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc_common.o |
| 140 | obj-$(CONFIG_COMEDI_NI_LABPC_ISADMA) += ni_labpc_isadma.o | 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 | obj-$(CONFIG_COMEDI_AMPLC_DIO200) += amplc_dio200_common.o | 144 | obj-$(CONFIG_COMEDI_AMPLC_DIO200) += amplc_dio200_common.o |
| 144 | obj-$(CONFIG_COMEDI_AMPLC_PC236) += amplc_pc236_common.o | 145 | obj-$(CONFIG_COMEDI_AMPLC_PC236) += amplc_pc236_common.o |
| 145 | obj-$(CONFIG_COMEDI_DAS08) += das08.o | 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 | static int apci1516_reset(struct comedi_device *dev) | 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 | struct apci1516_private *devpriv = dev->private; | 104 | struct apci1516_private *devpriv = dev->private; |
| 105 | 105 | ||
| 106 | if (!this_board->has_wdog) | 106 | if (!board->has_wdog) |
| 107 | return 0; | 107 | return 0; |
| 108 | 108 | ||
| 109 | outw(0x0, dev->iobase + APCI1516_DO_REG); | 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 | unsigned long context) | 117 | unsigned long context) |
| 118 | { | 118 | { |
| 119 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct apci1516_private *devpriv; | 121 | struct apci1516_private *devpriv; |
| 122 | struct comedi_subdevice *s; | 122 | struct comedi_subdevice *s; |
| 123 | int ret; | 123 | int ret; |
| 124 | 124 | ||
| 125 | if (context < ARRAY_SIZE(apci1516_boardtypes)) | 125 | if (context < ARRAY_SIZE(apci1516_boardtypes)) |
| 126 | this_board = &apci1516_boardtypes[context]; | 126 | board = &apci1516_boardtypes[context]; |
| 127 | if (!this_board) | 127 | if (!board) |
| 128 | return -ENODEV; | 128 | return -ENODEV; |
| 129 | dev->board_ptr = this_board; | 129 | dev->board_ptr = board; |
| 130 | dev->board_name = this_board->name; | 130 | dev->board_name = board->name; |
| 131 | 131 | ||
| 132 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 132 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 133 | if (!devpriv) | 133 | if (!devpriv) |
| @@ -146,10 +146,10 @@ static int apci1516_auto_attach(struct comedi_device *dev, · 12 unmodified lines | |||
| 146 | 146 | ||
| 147 | /* Initialize the digital input subdevice */ | 147 | /* Initialize the digital input subdevice */ |
| 148 | s = &dev->subdevices[0]; | 148 | s = &dev->subdevices[0]; |
| 149 | if (this_board->di_nchan) { | 149 | if (board->di_nchan) { |
| 150 | s->type = COMEDI_SUBD_DI; | 150 | s->type = COMEDI_SUBD_DI; |
| 151 | s->subdev_flags = SDF_READABLE; | 151 | s->subdev_flags = SDF_READABLE; |
| 152 | s->n_chan = this_board->di_nchan; | 152 | s->n_chan = board->di_nchan; |
| 153 | s->maxdata = 1; | 153 | s->maxdata = 1; |
| 154 | s->range_table = &range_digital; | 154 | s->range_table = &range_digital; |
| 155 | s->insn_bits = apci1516_di_insn_bits; | 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 | /* Initialize the digital output subdevice */ | 160 | /* Initialize the digital output subdevice */ |
| 161 | s = &dev->subdevices[1]; | 161 | s = &dev->subdevices[1]; |
| 162 | if (this_board->do_nchan) { | 162 | if (board->do_nchan) { |
| 163 | s->type = COMEDI_SUBD_DO; | 163 | s->type = COMEDI_SUBD_DO; |
| 164 | s->subdev_flags = SDF_WRITABLE; | 164 | s->subdev_flags = SDF_WRITABLE; |
| 165 | s->n_chan = this_board->do_nchan; | 165 | s->n_chan = board->do_nchan; |
| 166 | s->maxdata = 1; | 166 | s->maxdata = 1; |
| 167 | s->range_table = &range_digital; | 167 | s->range_table = &range_digital; |
| 168 | s->insn_bits = apci1516_do_insn_bits; | 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 | /* Initialize the watchdog subdevice */ | 173 | /* Initialize the watchdog subdevice */ |
| 174 | s = &dev->subdevices[2]; | 174 | s = &dev->subdevices[2]; |
| 175 | if (this_board->has_wdog) { | 175 | if (board->has_wdog) { |
| 176 | ret = addi_watchdog_init(s, devpriv->wdog_iobase); | 176 | ret = addi_watchdog_init(s, devpriv->wdog_iobase); |
| 177 | if (ret) | 177 | if (ret) |
| 178 | return ret; | 178 | return ret; |
| @@ -977,18 +977,18 @@ static int apci3120_auto_attach(struct comedi_device *dev, · 976 unmodified lines | |||
| 977 | unsigned long context) | 977 | unsigned long context) |
| 978 | { | 978 | { |
| 979 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct apci3120_private *devpriv; | 981 | struct apci3120_private *devpriv; |
| 982 | struct comedi_subdevice *s; | 982 | struct comedi_subdevice *s; |
| 983 | unsigned int status; | 983 | unsigned int status; |
| 984 | int ret; | 984 | int ret; |
| 985 | 985 | ||
| 986 | if (context < ARRAY_SIZE(apci3120_boardtypes)) | 986 | if (context < ARRAY_SIZE(apci3120_boardtypes)) |
| 987 | this_board = &apci3120_boardtypes[context]; | 987 | board = &apci3120_boardtypes[context]; |
| 988 | if (!this_board) | 988 | if (!board) |
| 989 | return -ENODEV; | 989 | return -ENODEV; |
| 990 | dev->board_ptr = this_board; | 990 | dev->board_ptr = board; |
| 991 | dev->board_name = this_board->name; | 991 | dev->board_name = board->name; |
| 992 | 992 | ||
| 993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 994 | if (!devpriv) | 994 | if (!devpriv) |
| @@ -1031,7 +1031,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, · 36 unmodified lines | |||
| 1031 | s->type = COMEDI_SUBD_AI; | 1031 | s->type = COMEDI_SUBD_AI; |
| 1032 | s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; | 1032 | s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; |
| 1033 | s->n_chan = 16; | 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 | s->range_table = &apci3120_ai_range; | 1035 | s->range_table = &apci3120_ai_range; |
| 1036 | s->insn_read = apci3120_ai_insn_read; | 1036 | s->insn_read = apci3120_ai_insn_read; |
| 1037 | if (dev->irq) { | 1037 | if (dev->irq) { |
| @@ -1045,7 +1045,7 @@ static int apci3120_auto_attach(struct comedi_device *dev, · 7 unmodified lines | |||
| 1045 | 1045 | ||
| 1046 | /* Analog Output subdevice */ | 1046 | /* Analog Output subdevice */ |
| 1047 | s = &dev->subdevices[1]; | 1047 | s = &dev->subdevices[1]; |
| 1048 | if (this_board->has_ao) { | 1048 | if (board->has_ao) { |
| 1049 | s->type = COMEDI_SUBD_AO; | 1049 | s->type = COMEDI_SUBD_AO; |
| 1050 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; | 1050 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; |
| 1051 | s->n_chan = 8; | 1051 | s->n_chan = 8; |
| @@ -1,7 +1,7 @@ | |||
| 1 | #ifndef _ADDI_WATCHDOG_H | 1 | #ifndef _ADDI_WATCHDOG_H |
| 2 | #define _ADDI_WATCHDOG_H | 2 | #define _ADDI_WATCHDOG_H |
| 3 | 3 | ||
| 4 | #include "../comedidev.h" | 4 | struct comedi_subdevice; |
| 5 | 5 | ||
| 6 | void addi_watchdog_reset(unsigned long iobase); | 6 | void addi_watchdog_reset(unsigned long iobase); |
| 7 | int addi_watchdog_init(struct comedi_subdevice *, unsigned long iobase); | 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 | s->insn_write = adv_pci1724_insn_write; | 180 | s->insn_write = adv_pci1724_insn_write; |
| 181 | s->private = (void *)PCI1724_DAC_CTRL_MODE_GAIN; | 181 | s->private = (void *)PCI1724_DAC_CTRL_MODE_GAIN; |
| 182 | 182 | ||
| 183 | ret = comedi_alloc_subdev_readback(s); | 183 | return comedi_alloc_subdev_readback(s); |
| 184 | if (ret) | ||
| 185 | return ret; | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | 184 | } |
| 189 | 185 | ||
| 190 | static struct comedi_driver adv_pci1724_driver = { | 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 | static int pci_dio_reset(struct comedi_device *dev) | 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 | case TYPE_PCI1730: | 738 | case TYPE_PCI1730: |
| 739 | outb(0, dev->iobase + PCI1730_DO); /* clear outputs */ | 739 | outb(0, dev->iobase + PCI1730_DO); /* clear outputs */ |
| 740 | outb(0, dev->iobase + PCI1730_DO + 1); | 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 | struct comedi_subdevice *s, | 887 | struct comedi_subdevice *s, |
| 888 | const struct diosubd_data *d) | 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 | s->type = COMEDI_SUBD_DI; | 892 | s->type = COMEDI_SUBD_DI; |
| 893 | s->subdev_flags = SDF_READABLE | d->specflags; | 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 | s->maxdata = 1; | 897 | s->maxdata = 1; |
| 898 | s->len_chanlist = d->chans; | 898 | s->len_chanlist = d->chans; |
| 899 | s->range_table = &range_digital; | 899 | s->range_table = &range_digital; |
| 900 | switch (this_board->io_access) { | 900 | switch (board->io_access) { |
| 901 | case IO_8b: | 901 | case IO_8b: |
| 902 | s->insn_bits = pci_dio_insn_bits_di_b; | 902 | s->insn_bits = pci_dio_insn_bits_di_b; |
| 903 | break; | 903 | break; |
| @@ -917,7 +917,7 @@ static int pci_dio_add_do(struct comedi_device *dev, · 13 unmodified lines | |||
| 917 | struct comedi_subdevice *s, | 917 | struct comedi_subdevice *s, |
| 918 | const struct diosubd_data *d) | 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 | s->type = COMEDI_SUBD_DO; | 922 | s->type = COMEDI_SUBD_DO; |
| 923 | s->subdev_flags = SDF_WRITABLE; | 923 | s->subdev_flags = SDF_WRITABLE; |
| @@ -928,7 +928,7 @@ static int pci_dio_add_do(struct comedi_device *dev, · 4 unmodified lines | |||
| 928 | s->len_chanlist = d->chans; | 928 | s->len_chanlist = d->chans; |
| 929 | s->range_table = &range_digital; | 929 | s->range_table = &range_digital; |
| 930 | s->state = 0; | 930 | s->state = 0; |
| 931 | switch (this_board->io_access) { | 931 | switch (board->io_access) { |
| 932 | case IO_8b: | 932 | case IO_8b: |
| 933 | s->insn_bits = pci_dio_insn_bits_do_b; | 933 | s->insn_bits = pci_dio_insn_bits_do_b; |
| 934 | break; | 934 | break; |
| @@ -978,17 +978,17 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 43 unmodified lines | |||
| 978 | unsigned long context) | 978 | unsigned long context) |
| 979 | { | 979 | { |
| 980 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct pci_dio_private *devpriv; | 982 | struct pci_dio_private *devpriv; |
| 983 | struct comedi_subdevice *s; | 983 | struct comedi_subdevice *s; |
| 984 | int ret, subdev, i, j; | 984 | int ret, subdev, i, j; |
| 985 | 985 | ||
| 986 | if (context < ARRAY_SIZE(boardtypes)) | 986 | if (context < ARRAY_SIZE(boardtypes)) |
| 987 | this_board = &boardtypes[context]; | 987 | board = &boardtypes[context]; |
| 988 | if (!this_board) | 988 | if (!board) |
| 989 | return -ENODEV; | 989 | return -ENODEV; |
| 990 | dev->board_ptr = this_board; | 990 | dev->board_ptr = board; |
| 991 | dev->board_name = this_board->name; | 991 | dev->board_name = board->name; |
| 992 | 992 | ||
| 993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 994 | if (!devpriv) | 994 | if (!devpriv) |
| @@ -997,50 +997,50 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 2 unmodified lines | |||
| 997 | ret = comedi_pci_enable(dev); | 997 | ret = comedi_pci_enable(dev); |
| 998 | if (ret) | 998 | if (ret) |
| 999 | return ret; | 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 | if (ret) | 1003 | if (ret) |
| 1004 | return ret; | 1004 | return ret; |
| 1005 | 1005 | ||
| 1006 | subdev = 0; | 1006 | subdev = 0; |
| 1007 | for (i = 0; i < MAX_DI_SUBDEVS; i++) | 1007 | for (i = 0; i < MAX_DI_SUBDEVS; i++) |
| 1008 | if (this_board->sdi[i].chans) { | 1008 | if (board->sdi[i].chans) { |
| 1009 | s = &dev->subdevices[subdev]; | 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 | subdev++; | 1011 | subdev++; |
| 1012 | } | 1012 | } |
| 1013 | 1013 | ||
| 1014 | for (i = 0; i < MAX_DO_SUBDEVS; i++) | 1014 | for (i = 0; i < MAX_DO_SUBDEVS; i++) |
| 1015 | if (this_board->sdo[i].chans) { | 1015 | if (board->sdo[i].chans) { |
| 1016 | s = &dev->subdevices[subdev]; | 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 | subdev++; | 1018 | subdev++; |
| 1019 | } | 1019 | } |
| 1020 | 1020 | ||
| 1021 | for (i = 0; i < MAX_DIO_SUBDEVG; i++) | 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 | s = &dev->subdevices[subdev]; | 1023 | s = &dev->subdevices[subdev]; |
| 1024 | ret = subdev_8255_init(dev, s, NULL, | 1024 | ret = subdev_8255_init(dev, s, NULL, |
| 1025 | this_board->sdio[i].addr + | 1025 | board->sdio[i].addr + |
| 1026 | j * I8255_SIZE); | 1026 | j * I8255_SIZE); |
| 1027 | if (ret) | 1027 | if (ret) |
| 1028 | return ret; | 1028 | return ret; |
| 1029 | subdev++; | 1029 | subdev++; |
| 1030 | } | 1030 | } |
| 1031 | 1031 | ||
| 1032 | if (this_board->boardid.chans) { | 1032 | if (board->boardid.chans) { |
| 1033 | s = &dev->subdevices[subdev]; | 1033 | s = &dev->subdevices[subdev]; |
| 1034 | s->type = COMEDI_SUBD_DI; | 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 | subdev++; | 1036 | subdev++; |
| 1037 | } | 1037 | } |
| 1038 | 1038 | ||
| 1039 | if (this_board->timer_regbase) { | 1039 | if (board->timer_regbase) { |
| 1040 | s = &dev->subdevices[subdev]; | 1040 | s = &dev->subdevices[subdev]; |
| 1041 | 1041 | ||
| 1042 | dev->pacer = comedi_8254_init(dev->iobase + | 1042 | dev->pacer = comedi_8254_init(dev->iobase + |
| 1043 | this_board->timer_regbase, | 1043 | board->timer_regbase, |
| 1044 | 0, I8254_IO8, 0); | 1044 | 0, I8254_IO8, 0); |
| 1045 | if (!dev->pacer) | 1045 | if (!dev->pacer) |
| 1046 | return -ENOMEM; | 1046 | return -ENOMEM; |
| @@ -1050,7 +1050,7 @@ static int pci_dio_auto_attach(struct comedi_device *dev, · 3 unmodified lines | |||
| 1050 | subdev++; | 1050 | subdev++; |
| 1051 | } | 1051 | } |
| 1052 | 1052 | ||
| 1053 | if (this_board->cardtype == TYPE_PCI1760) | 1053 | if (board->cardtype == TYPE_PCI1760) |
| 1054 | pci1760_attach(dev); | 1054 | pci1760_attach(dev); |
| 1055 | 1055 | ||
| 1056 | pci_dio_reset(dev); | 1056 | pci_dio_reset(dev); |
| @@ -1,23 +1,24 @@ | |||
| 1 | /* | 1 | /* |
| 2 | comedi/drivers/amplc_dio200.c | 2 | * comedi/drivers/amplc_dio200.c |
| 3 | 3 | * | |
| 4 | Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. | 4 | * Driver for Amplicon PC212E, PC214E, PC215E, PC218E, PC272E. |
| 5 | 5 | * | |
| 6 | Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | 6 | * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> |
| 7 | 7 | * | |
| 8 | COMEDI - Linux Control and Measurement Device Interface | 8 | * COMEDI - Linux Control and Measurement Device Interface |
| 9 | Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | 9 | * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> |
| 10 | 10 | * | |
| 11 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 13 | * the Free Software Foundation; either version 2 of the License, or |
| 14 | (at your option) any later version. | 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 | * Driver: amplc_dio200 | 23 | * Driver: amplc_dio200 |
| 23 | * Description: Amplicon 200 Series ISA Digital I/O | 24 | * Description: Amplicon 200 Series ISA Digital I/O |
| @@ -1,28 +1,32 @@ | |||
| 1 | /* | 1 | /* |
| 2 | comedi/drivers/amplc_dio.h | 2 | * comedi/drivers/amplc_dio.h |
| 3 | 3 | * | |
| 4 | Header for amplc_dio200.c, amplc_dio200_common.c and | 4 | * Header for amplc_dio200.c, amplc_dio200_common.c and |
| 5 | amplc_dio200_pci.c. | 5 | * amplc_dio200_pci.c. |
| 6 | 6 | * | |
| 7 | Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | 7 | * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> |
| 8 | 8 | * | |
| 9 | COMEDI - Linux Control and Measurement Device Interface | 9 | * COMEDI - Linux Control and Measurement Device Interface |
| 10 | Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | 10 | * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> |
| 11 | 11 | * | |
| 12 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 14 | * the Free Software Foundation; either version 2 of the License, or |
| 15 | (at your option) any later version. | 15 | * (at your option) any later version. |
| 16 | 16 | * | |
| 17 | This program is distributed in the hope that it will be useful, | 17 | * This program is distributed in the hope that it will be useful, |
| 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 20 | GNU General Public License for more details. | 20 | * GNU General Public License for more details. |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #ifndef AMPLC_DIO200_H_INCLUDED | 23 | #ifndef AMPLC_DIO200_H_INCLUDED |
| 24 | #define AMPLC_DIO200_H_INCLUDED | 24 | #define AMPLC_DIO200_H_INCLUDED |
| 25 | 25 | ||
| 26 | #include <linux/types.h> | ||
| 27 | |||
| 28 | struct comedi_device; | ||
| 29 | |||
| 26 | /* | 30 | /* |
| 27 | * Subdevice types. | 31 | * Subdevice types. |
| 28 | */ | 32 | */ |
| @@ -1,23 +1,23 @@ | |||
| 1 | /* | 1 | /* |
| 2 | comedi/drivers/amplc_dio200_common.c | 2 | * comedi/drivers/amplc_dio200_common.c |
| 3 | 3 | * | |
| 4 | Common support code for "amplc_dio200" and "amplc_dio200_pci". | 4 | * Common support code for "amplc_dio200" and "amplc_dio200_pci". |
| 5 | 5 | * | |
| 6 | Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> | 6 | * Copyright (C) 2005-2013 MEV Ltd. <http://www.mev.co.uk/> |
| 7 | 7 | * | |
| 8 | COMEDI - Linux Control and Measurement Device Interface | 8 | * COMEDI - Linux Control and Measurement Device Interface |
| 9 | Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> | 9 | * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> |
| 10 | 10 | * | |
| 11 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 13 | * the Free Software Foundation; either version 2 of the License, or |
| 14 | (at your option) any later version. | 14 | * (at your option) any later version. |
| 15 | 15 | * | |
| 16 | This program is distributed in the hope that it will be useful, | 16 | * This program is distributed in the hope that it will be useful, |
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 19 | GNU General Public License for more details. | 19 | * GNU General Public License for more details. |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| @@ -337,9 +337,10 @@ static int dio200_handle_read_intr(struct comedi_device *dev, · 313 unmodified lines | |||
| 337 | * interested in (just in case there's a race | 337 | * interested in (just in case there's a race |
| 338 | * condition). | 338 | * condition). |
| 339 | */ | 339 | */ |
| 340 | if (triggered & subpriv->enabled_isns) | 340 | if (triggered & subpriv->enabled_isns) { |
| 341 | /* Collect scan data. */ | 341 | /* Collect scan data. */ |
| 342 | dio200_read_scan_intr(dev, s, triggered); | 342 | dio200_read_scan_intr(dev, s, triggered); |
| 343 | } | ||
| 343 | } | 344 | } |
| 344 | } | 345 | } |
| 345 | spin_unlock_irqrestore(&subpriv->spinlock, flags); | 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 | regshift = 0; | 577 | regshift = 0; |
| 577 | } | 578 | } |
| 578 | 579 | ||
| 579 | if (dev->mmio) | 580 | if (dev->mmio) { |
| 580 | i8254 = comedi_8254_mm_init(dev->mmio + offset, | 581 | i8254 = comedi_8254_mm_init(dev->mmio + offset, |
| 581 | 0, I8254_IO8, regshift); | 582 | 0, I8254_IO8, regshift); |
| 582 | else | 583 | } else { |
| 583 | i8254 = comedi_8254_init(dev->iobase + offset, | 584 | i8254 = comedi_8254_init(dev->iobase + offset, |
| 584 | 0, I8254_IO8, regshift); | 585 | 0, I8254_IO8, regshift); |
| 586 | } | ||
| 585 | if (!i8254) | 587 | if (!i8254) |
| 586 | return -ENOMEM; | 588 | return -ENOMEM; |
| 587 | 589 | ||
| @@ -593,10 +595,10 @@ static int dio200_subdev_8254_init(struct comedi_device *dev, · 5 unmodified lines | |||
| 593 | * There could be multiple timers so this driver does not | 595 | * There could be multiple timers so this driver does not |
| 594 | * use dev->pacer to save the i8254 pointer. Instead, | 596 | * use dev->pacer to save the i8254 pointer. Instead, |
| 595 | * comedi_8254_subdevice_init() saved the i8254 pointer in | 597 | * comedi_8254_subdevice_init() saved the i8254 pointer in |
| 596 | * s->private. Set the runflag bit so that the core will | 598 | * s->private. Mark the subdevice as having private data |
| 597 | * automatically free it when the driver is detached. | 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 | /* Initialize channels. */ | 603 | /* Initialize channels. */ |
| 602 | if (board->has_clk_gat_sce) { | 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 | mask = comedi_dio_update_state(s, data); | 644 | mask = comedi_dio_update_state(s, data); |
| 643 | if (mask) { | 645 | if (mask) { |
| 644 | if (mask & 0xff) | 646 | if (mask & 0xff) { |
| 645 | dio200_write8(dev, subpriv->ofs + I8255_DATA_A_REG, | 647 | dio200_write8(dev, subpriv->ofs + I8255_DATA_A_REG, |
| 646 | s->state & 0xff); | 648 | s->state & 0xff); |
| 647 | if (mask & 0xff00) | 649 | } |
| 650 | if (mask & 0xff00) { | ||
| 648 | dio200_write8(dev, subpriv->ofs + I8255_DATA_B_REG, | 651 | dio200_write8(dev, subpriv->ofs + I8255_DATA_B_REG, |
| 649 | (s->state >> 8) & 0xff); | 652 | (s->state >> 8) & 0xff); |
| 650 | if (mask & 0xff0000) | 653 | } |
| 654 | if (mask & 0xff0000) { | ||
| 651 | dio200_write8(dev, subpriv->ofs + I8255_DATA_C_REG, | 655 | dio200_write8(dev, subpriv->ofs + I8255_DATA_C_REG, |
| 652 | (s->state >> 16) & 0xff); | 656 | (s->state >> 16) & 0xff); |
| 657 | } | ||
| 653 | } | 658 | } |
| 654 | 659 | ||
| 655 | val = dio200_read8(dev, subpriv->ofs + I8255_DATA_A_REG); | 660 | val = dio200_read8(dev, subpriv->ofs + I8255_DATA_A_REG); |
| @@ -1,22 +1,23 @@ | |||
| 1 | /* comedi/drivers/amplc_dio200_pci.c | 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 | * Driver: amplc_dio200_pci | 22 | * Driver: amplc_dio200_pci |
| 22 | * Description: Amplicon 200 Series PCI Digital I/O | 23 | * Description: Amplicon 200 Series PCI Digital I/O |
| @@ -28,14 +28,14 @@ · 27 unmodified lines | |||
| 28 | 28 | ||
| 29 | static void pc236_intr_update(struct comedi_device *dev, bool enable) | 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 | struct pc236_private *devpriv = dev->private; | 32 | struct pc236_private *devpriv = dev->private; |
| 33 | unsigned long flags; | 33 | unsigned long flags; |
| 34 | 34 | ||
| 35 | spin_lock_irqsave(&dev->spinlock, flags); | 35 | spin_lock_irqsave(&dev->spinlock, flags); |
| 36 | devpriv->enable_irq = enable; | 36 | devpriv->enable_irq = enable; |
| 37 | if (thisboard->intr_update_cb) | 37 | if (board->intr_update_cb) |
| 38 | thisboard->intr_update_cb(dev, enable); | 38 | board->intr_update_cb(dev, enable); |
| 39 | spin_unlock_irqrestore(&dev->spinlock, flags); | 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 | static bool pc236_intr_check(struct comedi_device *dev) | 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 | struct pc236_private *devpriv = dev->private; | 52 | struct pc236_private *devpriv = dev->private; |
| 53 | bool retval = false; | 53 | bool retval = false; |
| 54 | unsigned long flags; | 54 | unsigned long flags; |
| 55 | 55 | ||
| 56 | spin_lock_irqsave(&dev->spinlock, flags); | 56 | spin_lock_irqsave(&dev->spinlock, flags); |
| 57 | if (devpriv->enable_irq) { | 57 | if (devpriv->enable_irq) { |
| 58 | if (thisboard->intr_chk_clr_cb) | 58 | if (board->intr_chk_clr_cb) |
| 59 | retval = thisboard->intr_chk_clr_cb(dev); | 59 | retval = board->intr_chk_clr_cb(dev); |
| 60 | else | 60 | else |
| 61 | retval = true; | 61 | retval = true; |
| 62 | } | 62 | } |
| @@ -385,14 +385,14 @@ static void · 384 unmodified lines | |||
| 385 | pci224_ao_set_data(struct comedi_device *dev, int chan, int range, | 385 | pci224_ao_set_data(struct comedi_device *dev, int chan, int range, |
| 386 | unsigned int data) | 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 | struct pci224_private *devpriv = dev->private; | 389 | struct pci224_private *devpriv = dev->private; |
| 390 | unsigned short mangled; | 390 | unsigned short mangled; |
| 391 | 391 | ||
| 392 | /* Enable the channel. */ | 392 | /* Enable the channel. */ |
| 393 | outw(1 << chan, dev->iobase + PCI224_DACCEN); | 393 | outw(1 << chan, dev->iobase + PCI224_DACCEN); |
| 394 | /* Set range and reset FIFO. */ | 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 | PCI224_DACCON_POLAR_MASK | | 396 | PCI224_DACCON_POLAR_MASK | |
| 397 | PCI224_DACCON_VREF_MASK); | 397 | PCI224_DACCON_VREF_MASK); |
| 398 | outw(devpriv->daccon | PCI224_DACCON_FIFORESET, | 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 | * - bipolar: 16-bit 2's complement | 402 | * - bipolar: 16-bit 2's complement |
| 403 | * - unipolar: 16-bit unsigned | 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 | if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) == | 406 | if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) == |
| 407 | PCI224_DACCON_POLAR_BI) { | 407 | PCI224_DACCON_POLAR_BI) { |
| 408 | mangled ^= 0x8000; | 408 | mangled ^= 0x8000; |
| @@ -620,12 +620,12 @@ static int pci224_ao_check_chanlist(struct comedi_device *dev, · 211 unmodified lines | |||
| 620 | struct comedi_subdevice *s, | 620 | struct comedi_subdevice *s, |
| 621 | struct comedi_cmd *cmd) | 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 | unsigned int range_check_0; | 624 | unsigned int range_check_0; |
| 625 | unsigned int chan_mask = 0; | 625 | unsigned int chan_mask = 0; |
| 626 | int i; | 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 | for (i = 0; i < cmd->chanlist_len; i++) { | 629 | for (i = 0; i < cmd->chanlist_len; i++) { |
| 630 | unsigned int chan = CR_CHAN(cmd->chanlist[i]); | 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 | chan_mask |= 1 << chan; | 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 | range_check_0) { | 641 | range_check_0) { |
| 642 | dev_dbg(dev->class_dev, | 642 | dev_dbg(dev->class_dev, |
| 643 | "%s: entries in chanlist have incompatible ranges\n", | 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 | static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) | 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 | struct pci224_private *devpriv = dev->private; | 830 | struct pci224_private *devpriv = dev->private; |
| 831 | struct comedi_cmd *cmd = &s->async->cmd; | 831 | struct comedi_cmd *cmd = &s->async->cmd; |
| 832 | int range; | 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 | devpriv->daccon = | 870 | devpriv->daccon = |
| 871 | COMBINE(devpriv->daccon, | 871 | COMBINE(devpriv->daccon, |
| 872 | thisboard->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE | | 872 | board->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE | |
| 873 | PCI224_DACCON_FIFOINTR_NHALF, | 873 | PCI224_DACCON_FIFOINTR_NHALF, |
| 874 | PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK | | 874 | PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK | |
| 875 | PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK); | 875 | PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK); |
| @@ -911,7 +911,7 @@ static void · 35 unmodified lines | |||
| 911 | pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, | 911 | pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, |
| 912 | void *data, unsigned int num_bytes, unsigned int chan_index) | 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 | struct comedi_cmd *cmd = &s->async->cmd; | 915 | struct comedi_cmd *cmd = &s->async->cmd; |
| 916 | unsigned short *array = data; | 916 | unsigned short *array = data; |
| 917 | unsigned int length = num_bytes / sizeof(*array); | 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 | unsigned int i; | 920 | unsigned int i; |
| 921 | 921 | ||
| 922 | /* The hardware expects 16-bit numbers. */ | 922 | /* The hardware expects 16-bit numbers. */ |
| 923 | shift = 16 - thisboard->ao_bits; | 923 | shift = 16 - board->ao_bits; |
| 924 | /* Channels will be all bipolar or all unipolar. */ | 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 | PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) { | 926 | PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) { |
| 927 | /* Unipolar */ | 927 | /* Unipolar */ |
| 928 | offset = 0; | 928 | offset = 0; |
| @@ -988,21 +988,21 @@ static int · 59 unmodified lines | |||
| 988 | pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) | 988 | pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) |
| 989 | { | 989 | { |
| 990 | struct pci_dev *pci_dev = comedi_to_pci_dev(dev); | 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 | struct pci224_private *devpriv; | 992 | struct pci224_private *devpriv; |
| 993 | struct comedi_subdevice *s; | 993 | struct comedi_subdevice *s; |
| 994 | unsigned int irq; | 994 | unsigned int irq; |
| 995 | int ret; | 995 | int ret; |
| 996 | 996 | ||
| 997 | if (context_model < ARRAY_SIZE(pci224_boards)) | 997 | if (context_model < ARRAY_SIZE(pci224_boards)) |
| 998 | thisboard = &pci224_boards[context_model]; | 998 | board = &pci224_boards[context_model]; |
| 999 | if (!thisboard || !thisboard->name) { | 999 | if (!board || !board->name) { |
| 1000 | dev_err(dev->class_dev, | 1000 | dev_err(dev->class_dev, |
| 1001 | "amplc_pci224: BUG! cannot determine board type!\n"); | 1001 | "amplc_pci224: BUG! cannot determine board type!\n"); |
| 1002 | return -EINVAL; | 1002 | return -EINVAL; |
| 1003 | } | 1003 | } |
| 1004 | dev->board_ptr = thisboard; | 1004 | dev->board_ptr = board; |
| 1005 | dev->board_name = thisboard->name; | 1005 | dev->board_name = board->name; |
| 1006 | 1006 | ||
| 1007 | dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n", | 1007 | dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n", |
| 1008 | pci_name(pci_dev), dev->board_name); | 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 | /* Allocate buffer to hold values for AO channel scan. */ | 1024 | /* Allocate buffer to hold values for AO channel scan. */ |
| 1025 | devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) * | 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 | if (!devpriv->ao_scan_vals) | 1027 | if (!devpriv->ao_scan_vals) |
| 1028 | return -ENOMEM; | 1028 | return -ENOMEM; |
| 1029 | 1029 | ||
| 1030 | /* Allocate buffer to hold AO channel scan order. */ | 1030 | /* Allocate buffer to hold AO channel scan order. */ |
| 1031 | devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) * | 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 | if (!devpriv->ao_scan_order) | 1033 | if (!devpriv->ao_scan_order) |
| 1034 | return -ENOMEM; | 1034 | return -ENOMEM; |
| 1035 | 1035 | ||
| @@ -1059,9 +1059,9 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) · 23 unmodified lines | |||
| 1059 | /* Analog output subdevice. */ | 1059 | /* Analog output subdevice. */ |
| 1060 | s->type = COMEDI_SUBD_AO; | 1060 | s->type = COMEDI_SUBD_AO; |
| 1061 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; | 1061 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; |
| 1062 | s->n_chan = thisboard->ao_chans; | 1062 | s->n_chan = board->ao_chans; |
| 1063 | s->maxdata = (1 << thisboard->ao_bits) - 1; | 1063 | s->maxdata = (1 << board->ao_bits) - 1; |
| 1064 | s->range_table = thisboard->ao_range; | 1064 | s->range_table = board->ao_range; |
| 1065 | s->insn_write = pci224_ao_insn_write; | 1065 | s->insn_write = pci224_ao_insn_write; |
| 1066 | s->len_chanlist = s->n_chan; | 1066 | s->len_chanlist = s->n_chan; |
| 1067 | dev->write_subdev = s; | 1067 | dev->write_subdev = s; |
| @@ -528,7 +528,7 @@ static const struct comedi_lrange pci230_ao_range = { · 527 unmodified lines | |||
| 528 | 528 | ||
| 529 | static unsigned short pci230_ai_read(struct comedi_device *dev) | 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 | struct pci230_private *devpriv = dev->private; | 532 | struct pci230_private *devpriv = dev->private; |
| 533 | unsigned short data; | 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 | if (devpriv->ai_bipolar) | 544 | if (devpriv->ai_bipolar) |
| 545 | data ^= 0x8000; | 545 | data ^= 0x8000; |
| 546 | data >>= (16 - thisboard->ai_bits); | 546 | data >>= (16 - board->ai_bits); |
| 547 | return data; | 547 | return data; |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, | 550 | static unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, |
| 551 | unsigned short datum) | 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 | struct pci230_private *devpriv = dev->private; | 554 | struct pci230_private *devpriv = dev->private; |
| 555 | 555 | ||
| 556 | /* | 556 | /* |
| 557 | * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower | 557 | * PCI230 is 12 bit - stored in upper bits of 16 bit register (lower |
| 558 | * four bits reserved for expansion). PCI230+ is also 12 bit AO. | 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 | * If a bipolar range was specified, mangle it | 562 | * If a bipolar range was specified, mangle it |
| 563 | * (straight binary->twos complement). | 563 | * (straight binary->twos complement). |
| @@ -877,7 +877,7 @@ static int pci230_ao_check_chanlist(struct comedi_device *dev, · 313 unmodified lines | |||
| 877 | static int pci230_ao_cmdtest(struct comedi_device *dev, | 877 | static int pci230_ao_cmdtest(struct comedi_device *dev, |
| 878 | struct comedi_subdevice *s, struct comedi_cmd *cmd) | 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 | struct pci230_private *devpriv = dev->private; | 881 | struct pci230_private *devpriv = dev->private; |
| 882 | int err = 0; | 882 | int err = 0; |
| 883 | unsigned int tmp; | 883 | unsigned int tmp; |
| @@ -887,14 +887,14 @@ static int pci230_ao_cmdtest(struct comedi_device *dev, · 3 unmodified lines | |||
| 887 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT); | 887 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT); |
| 888 | 888 | ||
| 889 | tmp = TRIG_TIMER | TRIG_INT; | 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 | * For PCI230+ hardware version 2 onwards, allow external | 892 | * For PCI230+ hardware version 2 onwards, allow external |
| 893 | * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25). | 893 | * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25). |
| 894 | * | 894 | * |
| 895 | * FIXME: The permitted scan_begin_src values shouldn't depend | 895 | * FIXME: The permitted scan_begin_src values shouldn't depend |
| 896 | * on devpriv->hwver (the detected card's actual hardware | 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 | * (the static capabilities of the configured card). To fix | 898 | * (the static capabilities of the configured card). To fix |
| 899 | * it, a new card model, e.g. "pci230+2" would have to be | 899 | * it, a new card model, e.g. "pci230+2" would have to be |
| 900 | * defined with min_hwver set to 2. It doesn't seem worth it | 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 | static int pci230_ai_cmdtest(struct comedi_device *dev, | 1500 | static int pci230_ai_cmdtest(struct comedi_device *dev, |
| 1501 | struct comedi_subdevice *s, struct comedi_cmd *cmd) | 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 | struct pci230_private *devpriv = dev->private; | 1504 | struct pci230_private *devpriv = dev->private; |
| 1505 | int err = 0; | 1505 | int err = 0; |
| 1506 | unsigned int tmp; | 1506 | unsigned int tmp; |
| @@ -1510,7 +1510,7 @@ static int pci230_ai_cmdtest(struct comedi_device *dev, · 3 unmodified lines | |||
| 1510 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); | 1510 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); |
| 1511 | 1511 | ||
| 1512 | tmp = TRIG_FOLLOW | TRIG_TIMER | TRIG_INT; | 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 | * Unfortunately, we cannot trigger a scan off an external | 1515 | * Unfortunately, we cannot trigger a scan off an external |
| 1516 | * source on the PCI260 board, since it uses the PPIC0 (DIO) | 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 | struct comedi_cmd *cmd = &async->cmd; | 2011 | struct comedi_cmd *cmd = &async->cmd; |
| 2012 | unsigned int status_fifo; | 2012 | unsigned int status_fifo; |
| 2013 | unsigned int i; | 2013 | unsigned int i; |
| 2014 | unsigned int todo; | 2014 | unsigned int nsamples; |
| 2015 | unsigned int fifoamount; | 2015 | unsigned int fifoamount; |
| 2016 | unsigned short val; | 2016 | unsigned short val; |
| 2017 | 2017 | ||
| 2018 | /* Determine number of samples to read. */ | 2018 | /* Determine number of samples to read. */ |
| 2019 | todo = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); | 2019 | nsamples = comedi_nsamples_left(s, PCI230_ADC_FIFOLEVEL_HALFFULL); |
| 2020 | if (todo == 0) | 2020 | if (nsamples == 0) |
| 2021 | return; | 2021 | return; |
| 2022 | 2022 | ||
| 2023 | fifoamount = 0; | 2023 | fifoamount = 0; |
| 2024 | for (i = 0; i < todo; i++) { | 2024 | for (i = 0; i < nsamples; i++) { |
| 2025 | if (fifoamount == 0) { | 2025 | if (fifoamount == 0) { |
| 2026 | /* Read FIFO state. */ | 2026 | /* Read FIFO state. */ |
| 2027 | status_fifo = inw(devpriv->daqio + PCI230_ADCCON); | 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 | unsigned long context_unused) | 2364 | unsigned long context_unused) |
| 2365 | { | 2365 | { |
| 2366 | struct pci_dev *pci_dev = comedi_to_pci_dev(dev); | 2366 | struct pci_dev *pci_dev = comedi_to_pci_dev(dev); |
| 2367 | const struct pci230_board *thisboard; | 2367 | const struct pci230_board *board; |
| 2368 | struct pci230_private *devpriv; | 2368 | struct pci230_private *devpriv; |
| 2369 | struct comedi_subdevice *s; | 2369 | struct comedi_subdevice *s; |
| 2370 | int rc; | 2370 | int rc; |
| @@ -2381,14 +2381,14 @@ static int pci230_auto_attach(struct comedi_device *dev, · 10 unmodified lines | |||
| 2381 | spin_lock_init(&devpriv->ai_stop_spinlock); | 2381 | spin_lock_init(&devpriv->ai_stop_spinlock); |
| 2382 | spin_lock_init(&devpriv->ao_stop_spinlock); | 2382 | spin_lock_init(&devpriv->ao_stop_spinlock); |
| 2383 | 2383 | ||
| 2384 | dev->board_ptr = pci230_find_pci_board(pci_dev); | 2384 | board = pci230_find_pci_board(pci_dev); |
| 2385 | if (!dev->board_ptr) { | 2385 | if (!board) { |
| 2386 | dev_err(dev->class_dev, | 2386 | dev_err(dev->class_dev, |
| 2387 | "amplc_pci230: BUG! cannot determine board type!\n"); | 2387 | "amplc_pci230: BUG! cannot determine board type!\n"); |
| 2388 | return -EINVAL; | 2388 | return -EINVAL; |
| 2389 | } | 2389 | } |
| 2390 | thisboard = dev->board_ptr; | 2390 | dev->board_ptr = board; |
| 2391 | dev->board_name = thisboard->name; | 2391 | dev->board_name = board->name; |
| 2392 | 2392 | ||
| 2393 | rc = comedi_pci_enable(dev); | 2393 | rc = comedi_pci_enable(dev); |
| 2394 | if (rc) | 2394 | if (rc) |
| @@ -2414,15 +2414,15 @@ static int pci230_auto_attach(struct comedi_device *dev, · 19 unmodified lines | |||
| 2414 | unsigned short extfunc = 0; | 2414 | unsigned short extfunc = 0; |
| 2415 | 2415 | ||
| 2416 | devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER); | 2416 | devpriv->hwver = inw(devpriv->daqio + PCI230P_HWVER); |
| 2417 | if (devpriv->hwver < thisboard->min_hwver) { | 2417 | if (devpriv->hwver < board->min_hwver) { |
| 2418 | dev_err(dev->class_dev, | 2418 | dev_err(dev->class_dev, |
| 2419 | "%s - bad hardware version - got %u, need %u\n", | 2419 | "%s - bad hardware version - got %u, need %u\n", |
| 2420 | dev->board_name, devpriv->hwver, | 2420 | dev->board_name, devpriv->hwver, |
| 2421 | thisboard->min_hwver); | 2421 | board->min_hwver); |
| 2422 | return -EIO; | 2422 | return -EIO; |
| 2423 | } | 2423 | } |
| 2424 | if (devpriv->hwver > 0) { | 2424 | if (devpriv->hwver > 0) { |
| 2425 | if (!thisboard->have_dio) { | 2425 | if (!board->have_dio) { |
| 2426 | /* | 2426 | /* |
| 2427 | * No DIO ports. Route counters' external gates | 2427 | * No DIO ports. Route counters' external gates |
| 2428 | * to the EXTTRIG signal (PCI260+ pin 17). | 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 | extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG; | 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 | /* Enable DAC FIFO functionality. */ | 2436 | /* Enable DAC FIFO functionality. */ |
| 2437 | extfunc |= PCI230P2_EXTFUNC_DACFIFO; | 2437 | extfunc |= PCI230P2_EXTFUNC_DACFIFO; |
| 2438 | } | 2438 | } |
| @@ -2484,7 +2484,7 @@ static int pci230_auto_attach(struct comedi_device *dev, · 45 unmodified lines | |||
| 2484 | s->type = COMEDI_SUBD_AI; | 2484 | s->type = COMEDI_SUBD_AI; |
| 2485 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; | 2485 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; |
| 2486 | s->n_chan = 16; | 2486 | s->n_chan = 16; |
| 2487 | s->maxdata = (1 << thisboard->ai_bits) - 1; | 2487 | s->maxdata = (1 << board->ai_bits) - 1; |
| 2488 | s->range_table = &pci230_ai_range; | 2488 | s->range_table = &pci230_ai_range; |
| 2489 | s->insn_read = pci230_ai_insn_read; | 2489 | s->insn_read = pci230_ai_insn_read; |
| 2490 | s->len_chanlist = 256; /* but there are restrictions. */ | 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 | s = &dev->subdevices[1]; | 2499 | s = &dev->subdevices[1]; |
| 2500 | /* analog output subdevice */ | 2500 | /* analog output subdevice */ |
| 2501 | if (thisboard->ao_bits) { | 2501 | if (board->ao_bits) { |
| 2502 | s->type = COMEDI_SUBD_AO; | 2502 | s->type = COMEDI_SUBD_AO; |
| 2503 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND; | 2503 | s->subdev_flags = SDF_WRITABLE | SDF_GROUND; |
| 2504 | s->n_chan = 2; | 2504 | s->n_chan = 2; |
| 2505 | s->maxdata = (1 << thisboard->ao_bits) - 1; | 2505 | s->maxdata = (1 << board->ao_bits) - 1; |
| 2506 | s->range_table = &pci230_ao_range; | 2506 | s->range_table = &pci230_ao_range; |
| 2507 | s->insn_write = pci230_ao_insn_write; | 2507 | s->insn_write = pci230_ao_insn_write; |
| 2508 | s->len_chanlist = 2; | 2508 | s->len_chanlist = 2; |
| @@ -2523,7 +2523,7 @@ static int pci230_auto_attach(struct comedi_device *dev, · 14 unmodified lines | |||
| 2523 | 2523 | ||
| 2524 | s = &dev->subdevices[2]; | 2524 | s = &dev->subdevices[2]; |
| 2525 | /* digital i/o subdevice */ | 2525 | /* digital i/o subdevice */ |
| 2526 | if (thisboard->have_dio) { | 2526 | if (board->have_dio) { |
| 2527 | rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE); | 2527 | rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE); |
| 2528 | if (rc) | 2528 | if (rc) |
| 2529 | return rc; | 2529 | return rc; |
| @@ -705,9 +705,9 @@ static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, · 704 unmodified lines | |||
| 705 | static void cb_pcidas_trimpot_write(struct comedi_device *dev, | 705 | static void cb_pcidas_trimpot_write(struct comedi_device *dev, |
| 706 | unsigned int chan, unsigned int val) | 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 | case AD7376: | 711 | case AD7376: |
| 712 | trimpot_7376_write(dev, val); | 712 | trimpot_7376_write(dev, val); |
| 713 | break; | 713 | break; |
| @@ -770,7 +770,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, · 56 unmodified lines | |||
| 770 | struct comedi_subdevice *s, | 770 | struct comedi_subdevice *s, |
| 771 | struct comedi_cmd *cmd) | 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 | int err = 0; | 774 | int err = 0; |
| 775 | unsigned int arg; | 775 | unsigned int arg; |
| 776 | 776 | ||
| @@ -821,7 +821,7 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev, · 44 unmodified lines | |||
| 821 | ~(CR_EDGE | CR_INVERT)); | 821 | ~(CR_EDGE | CR_INVERT)); |
| 822 | err |= -EINVAL; | 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 | cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT); | 825 | cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT); |
| 826 | err |= -EINVAL; | 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 | if (cmd->scan_begin_src == TRIG_TIMER) { | 831 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 832 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, | 832 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 833 | thisboard->ai_speed * | 833 | board->ai_speed * |
| 834 | cmd->chanlist_len); | 834 | cmd->chanlist_len); |
| 835 | } | 835 | } |
| 836 | 836 | ||
| 837 | if (cmd->convert_src == TRIG_TIMER) { | 837 | if (cmd->convert_src == TRIG_TIMER) { |
| 838 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, | 838 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 839 | thisboard->ai_speed); | 839 | board->ai_speed); |
| 840 | } | 840 | } |
| 841 | 841 | ||
| 842 | err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, | 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 | static int cb_pcidas_ai_cmd(struct comedi_device *dev, | 879 | static int cb_pcidas_ai_cmd(struct comedi_device *dev, |
| 880 | struct comedi_subdevice *s) | 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 | struct cb_pcidas_private *devpriv = dev->private; | 883 | struct cb_pcidas_private *devpriv = dev->private; |
| 884 | struct comedi_async *async = s->async; | 884 | struct comedi_async *async = s->async; |
| 885 | struct comedi_cmd *cmd = &async->cmd; | 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 | bits |= SW_TRIGGER; | 945 | bits |= SW_TRIGGER; |
| 946 | } else { /* TRIG_EXT */ | 946 | } else { /* TRIG_EXT */ |
| 947 | bits |= EXT_TRIGGER | TGEN | XTRCL; | 947 | bits |= EXT_TRIGGER | TGEN | XTRCL; |
| 948 | if (thisboard->is_1602) { | 948 | if (board->is_1602) { |
| 949 | if (cmd->start_arg & CR_INVERT) | 949 | if (cmd->start_arg & CR_INVERT) |
| 950 | bits |= TGPOL; | 950 | bits |= TGPOL; |
| 951 | if (cmd->start_arg & CR_EDGE) | 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 | struct comedi_subdevice *s, | 982 | struct comedi_subdevice *s, |
| 983 | struct comedi_cmd *cmd) | 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 | struct cb_pcidas_private *devpriv = dev->private; | 986 | struct cb_pcidas_private *devpriv = dev->private; |
| 987 | int err = 0; | 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 | if (cmd->scan_begin_src == TRIG_TIMER) { | 1015 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 1016 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, | 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 | err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, | 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 | struct comedi_subdevice *s, | 1090 | struct comedi_subdevice *s, |
| 1091 | unsigned int trig_num) | 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 | struct cb_pcidas_private *devpriv = dev->private; | 1094 | struct cb_pcidas_private *devpriv = dev->private; |
| 1095 | struct comedi_async *async = s->async; | 1095 | struct comedi_async *async = s->async; |
| 1096 | struct comedi_cmd *cmd = &async->cmd; | 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 | if (trig_num != cmd->start_arg) | 1099 | if (trig_num != cmd->start_arg) |
| 1100 | return -EINVAL; | 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 | /* enable dac half-full and empty interrupts */ | 1104 | /* enable dac half-full and empty interrupts */ |
| 1105 | spin_lock_irqsave(&dev->spinlock, flags); | 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 | static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) | 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 | struct cb_pcidas_private *devpriv = dev->private; | 1201 | struct cb_pcidas_private *devpriv = dev->private; |
| 1202 | struct comedi_subdevice *s = dev->write_subdev; | 1202 | struct comedi_subdevice *s = dev->write_subdev; |
| 1203 | struct comedi_async *async = s->async; | 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 | } else if (status & DAHFI) { | 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 | /* clear half-full interrupt latch */ | 1225 | /* clear half-full interrupt latch */ |
| 1226 | spin_lock_irqsave(&dev->spinlock, flags); | 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 | static irqreturn_t cb_pcidas_interrupt(int irq, void *d) | 1235 | static irqreturn_t cb_pcidas_interrupt(int irq, void *d) |
| 1236 | { | 1236 | { |
| 1237 | struct comedi_device *dev = (struct comedi_device *)d; | 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 | struct cb_pcidas_private *devpriv = dev->private; | 1239 | struct cb_pcidas_private *devpriv = dev->private; |
| 1240 | struct comedi_subdevice *s = dev->read_subdev; | 1240 | struct comedi_subdevice *s = dev->read_subdev; |
| 1241 | struct comedi_async *async; | 1241 | struct comedi_async *async; |
| 1242 | struct comedi_cmd *cmd; | 1242 | struct comedi_cmd *cmd; |
| 1243 | int status, s5933_status; | 1243 | int status, s5933_status; |
| 1244 | int half_fifo = thisboard->fifo_size / 2; | 1244 | int half_fifo = board->fifo_size / 2; |
| 1245 | unsigned int num_samples, i; | 1245 | unsigned int num_samples, i; |
| 1246 | static const int timeout = 10000; | 1246 | static const int timeout = 10000; |
| 1247 | unsigned long flags; | 1247 | unsigned long flags; |
| @@ -1338,18 +1338,18 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 90 unmodified lines | |||
| 1338 | unsigned long context) | 1338 | unsigned long context) |
| 1339 | { | 1339 | { |
| 1340 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct cb_pcidas_private *devpriv; | 1342 | struct cb_pcidas_private *devpriv; |
| 1343 | struct comedi_subdevice *s; | 1343 | struct comedi_subdevice *s; |
| 1344 | int i; | 1344 | int i; |
| 1345 | int ret; | 1345 | int ret; |
| 1346 | 1346 | ||
| 1347 | if (context < ARRAY_SIZE(cb_pcidas_boards)) | 1347 | if (context < ARRAY_SIZE(cb_pcidas_boards)) |
| 1348 | thisboard = &cb_pcidas_boards[context]; | 1348 | board = &cb_pcidas_boards[context]; |
| 1349 | if (!thisboard) | 1349 | if (!board) |
| 1350 | return -ENODEV; | 1350 | return -ENODEV; |
| 1351 | dev->board_ptr = thisboard; | 1351 | dev->board_ptr = board; |
| 1352 | dev->board_name = thisboard->name; | 1352 | dev->board_name = board->name; |
| 1353 | 1353 | ||
| 1354 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 1354 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 1355 | if (!devpriv) | 1355 | if (!devpriv) |
| @@ -1363,7 +1363,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 7 unmodified lines | |||
| 1363 | devpriv->control_status = pci_resource_start(pcidev, 1); | 1363 | devpriv->control_status = pci_resource_start(pcidev, 1); |
| 1364 | devpriv->adc_fifo = pci_resource_start(pcidev, 2); | 1364 | devpriv->adc_fifo = pci_resource_start(pcidev, 2); |
| 1365 | dev->iobase = pci_resource_start(pcidev, 3); | 1365 | dev->iobase = pci_resource_start(pcidev, 3); |
| 1366 | if (thisboard->ao_nchan) | 1366 | if (board->ao_nchan) |
| 1367 | devpriv->ao_registers = pci_resource_start(pcidev, 4); | 1367 | devpriv->ao_registers = pci_resource_start(pcidev, 4); |
| 1368 | 1368 | ||
| 1369 | /* disable and clear interrupts on amcc s5933 */ | 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 | s->type = COMEDI_SUBD_AI; | 1400 | s->type = COMEDI_SUBD_AI; |
| 1401 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; | 1401 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; |
| 1402 | /* WARNING: Number of inputs in differential mode is ignored */ | 1402 | /* WARNING: Number of inputs in differential mode is ignored */ |
| 1403 | s->n_chan = thisboard->ai_nchan; | 1403 | s->n_chan = board->ai_nchan; |
| 1404 | s->len_chanlist = thisboard->ai_nchan; | 1404 | s->len_chanlist = board->ai_nchan; |
| 1405 | s->maxdata = (1 << thisboard->ai_bits) - 1; | 1405 | s->maxdata = (1 << board->ai_bits) - 1; |
| 1406 | s->range_table = thisboard->ranges; | 1406 | s->range_table = board->ranges; |
| 1407 | s->insn_read = cb_pcidas_ai_rinsn; | 1407 | s->insn_read = cb_pcidas_ai_rinsn; |
| 1408 | s->insn_config = ai_config_insn; | 1408 | s->insn_config = ai_config_insn; |
| 1409 | s->do_cmd = cb_pcidas_ai_cmd; | 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 | /* analog output subdevice */ | 1413 | /* analog output subdevice */ |
| 1414 | s = &dev->subdevices[1]; | 1414 | s = &dev->subdevices[1]; |
| 1415 | if (thisboard->ao_nchan) { | 1415 | if (board->ao_nchan) { |
| 1416 | s->type = COMEDI_SUBD_AO; | 1416 | s->type = COMEDI_SUBD_AO; |
| 1417 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND; | 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 | * analog out resolution is the same as | 1420 | * analog out resolution is the same as |
| 1421 | * analog input resolution, so use ai_bits | 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 | s->range_table = &cb_pcidas_ao_ranges; | 1424 | s->range_table = &cb_pcidas_ao_ranges; |
| 1425 | /* default to no fifo (*insn_write) */ | 1425 | /* default to no fifo (*insn_write) */ |
| 1426 | s->insn_write = cb_pcidas_ao_nofifo_winsn; | 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 | if (ret) | 1429 | if (ret) |
| 1430 | return ret; | 1430 | return ret; |
| 1431 | 1431 | ||
| 1432 | if (thisboard->has_ao_fifo) { | 1432 | if (board->has_ao_fifo) { |
| 1433 | dev->write_subdev = s; | 1433 | dev->write_subdev = s; |
| 1434 | s->subdev_flags |= SDF_CMD_WRITE; | 1434 | s->subdev_flags |= SDF_CMD_WRITE; |
| 1435 | /* use fifo (*insn_write) instead */ | 1435 | /* use fifo (*insn_write) instead */ |
| @@ -1477,7 +1477,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 41 unmodified lines | |||
| 1477 | s = &dev->subdevices[5]; | 1477 | s = &dev->subdevices[5]; |
| 1478 | s->type = COMEDI_SUBD_CALIB; | 1478 | s->type = COMEDI_SUBD_CALIB; |
| 1479 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; | 1479 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 1480 | if (thisboard->trimpot == AD7376) { | 1480 | if (board->trimpot == AD7376) { |
| 1481 | s->n_chan = NUM_CHANNELS_7376; | 1481 | s->n_chan = NUM_CHANNELS_7376; |
| 1482 | s->maxdata = 0x7f; | 1482 | s->maxdata = 0x7f; |
| 1483 | } else { | 1483 | } else { |
| @@ -1497,7 +1497,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, · 13 unmodified lines | |||
| 1497 | 1497 | ||
| 1498 | /* dac08 caldac */ | 1498 | /* dac08 caldac */ |
| 1499 | s = &dev->subdevices[6]; | 1499 | s = &dev->subdevices[6]; |
| 1500 | if (thisboard->has_dac08) { | 1500 | if (board->has_dac08) { |
| 1501 | s->type = COMEDI_SUBD_CALIB; | 1501 | s->type = COMEDI_SUBD_CALIB; |
| 1502 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; | 1502 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 1503 | s->n_chan = NUM_CHANNELS_DAC08; | 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 | enum read_only_registers { | 157 | enum read_only_registers { |
| 158 | /* hardware status register, | 158 | /* |
| 159 | * reading this apparently clears pending interrupts as well */ | 159 | * hardware status register, |
| 160 | * reading this apparently clears pending interrupts as well | ||
| 161 | */ | ||
| 160 | HW_STATUS_REG = 0x0, | 162 | HW_STATUS_REG = 0x0, |
| 161 | PIPE1_READ_REG = 0x4, | 163 | PIPE1_READ_REG = 0x4, |
| 162 | ADC_READ_PNTR_REG = 0x8, | 164 | ADC_READ_PNTR_REG = 0x8, |
| @@ -243,7 +245,8 @@ enum adc_control0_contents { · 80 unmodified lines | |||
| 243 | ADC_SOFT_GATE_BITS = 0x1, /* software gate */ | 245 | ADC_SOFT_GATE_BITS = 0x1, /* software gate */ |
| 244 | ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ | 246 | ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ |
| 245 | ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ | 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 | ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ | 250 | ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ |
| 248 | ADC_START_TRIG_SOFT_BITS = 0x10, | 251 | ADC_START_TRIG_SOFT_BITS = 0x10, |
| 249 | ADC_START_TRIG_EXT_BITS = 0x20, | 252 | ADC_START_TRIG_EXT_BITS = 0x20, |
| @@ -300,7 +303,8 @@ enum calibration_contents { · 50 unmodified lines | |||
| 300 | CAL_GAIN_BIT = 0x800, | 303 | CAL_GAIN_BIT = 0x800, |
| 301 | }; | 304 | }; |
| 302 | 305 | ||
| 303 | /* calibration sources for 6025 are: | 306 | /* |
| 307 | * calibration sources for 6025 are: | ||
| 304 | * 0 : ground | 308 | * 0 : ground |
| 305 | * 1 : 10V | 309 | * 1 : 10V |
| 306 | * 2 : 5V | 310 | * 2 : 5V |
| @@ -660,8 +664,10 @@ static const struct hw_fifo_info ai_fifo_60xx = { · 353 unmodified lines | |||
| 660 | .fifo_size_reg_mask = 0x7f, | 664 | .fifo_size_reg_mask = 0x7f, |
| 661 | }; | 665 | }; |
| 662 | 666 | ||
| 663 | /* maximum number of dma transfers we will chain together into a ring | 667 | /* |
| 664 | * (and the maximum number of dma buffers we maintain) */ | 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 | #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE) | 671 | #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE) |
| 666 | #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) | 672 | #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) |
| 667 | #define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) | 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 | static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, | 1106 | static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, |
| 1101 | int use_differential) | 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) || | 1111 | if ((board->layout == LAYOUT_64XX && !use_differential) || |
| 1106 | (thisboard->layout == LAYOUT_60XX && use_differential)) | 1112 | (board->layout == LAYOUT_60XX && use_differential)) |
| 1107 | return ADC_SE_DIFF_BIT; | 1113 | return ADC_SE_DIFF_BIT; |
| 1108 | 1114 | ||
| 1109 | return 0; | 1115 | return 0; |
| @@ -1176,17 +1182,17 @@ struct pcidas64_private { · 66 unmodified lines | |||
| 1176 | static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, | 1182 | static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, |
| 1177 | unsigned int range_index) | 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 | static unsigned int hw_revision(const struct comedi_device *dev, | 1190 | static unsigned int hw_revision(const struct comedi_device *dev, |
| 1185 | uint16_t hw_status_bits) | 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 | return (hw_status_bits >> 13) & 0x7; | 1196 | return (hw_status_bits >> 13) & 0x7; |
| 1191 | 1197 | ||
| 1192 | return (hw_status_bits >> 12) & 0xf; | 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 | uint16_t *bits, unsigned int channel, | 1202 | uint16_t *bits, unsigned int channel, |
| 1197 | unsigned int range) | 1203 | unsigned int range) |
| 1198 | { | 1204 | { |
| 1199 | const struct pcidas64_board *thisboard = dev->board_ptr; | 1205 | const struct pcidas64_board *board = dev->board_ptr; |
| 1200 | unsigned int code = thisboard->ao_range_code[range]; | 1206 | unsigned int code = board->ao_range_code[range]; |
| 1201 | 1207 | ||
| 1202 | if (channel > 1) | 1208 | if (channel > 1) |
| 1203 | dev_err(dev->class_dev, "bug! bad channel?\n"); | 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 | static void enable_ai_interrupts(struct comedi_device *dev, | 1259 | static void enable_ai_interrupts(struct comedi_device *dev, |
| 1254 | const struct comedi_cmd *cmd) | 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 | struct pcidas64_private *devpriv = dev->private; | 1263 | struct pcidas64_private *devpriv = dev->private; |
| 1258 | uint32_t bits; | 1264 | uint32_t bits; |
| 1259 | unsigned long flags; | 1265 | unsigned long flags; |
| 1260 | 1266 | ||
| 1261 | bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT | | 1267 | bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT | |
| 1262 | EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT; | 1268 | EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT; |
| 1263 | /* Use pio transfer and interrupt on end of conversion | 1269 | /* |
| 1264 | * if CMDF_WAKE_EOS flag is set. */ | 1270 | * Use pio transfer and interrupt on end of conversion |
| 1271 | * if CMDF_WAKE_EOS flag is set. | ||
| 1272 | */ | ||
| 1265 | if (cmd->flags & CMDF_WAKE_EOS) { | 1273 | if (cmd->flags & CMDF_WAKE_EOS) { |
| 1266 | /* 4020 doesn't support pio transfers except for fifo dregs */ | 1274 | /* 4020 doesn't support pio transfers except for fifo dregs */ |
| 1267 | if (thisboard->layout != LAYOUT_4020) | 1275 | if (board->layout != LAYOUT_4020) |
| 1268 | bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; | 1276 | bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; |
| 1269 | } | 1277 | } |
| 1270 | spin_lock_irqsave(&dev->spinlock, flags); | 1278 | spin_lock_irqsave(&dev->spinlock, flags); |
| @@ -1277,7 +1285,7 @@ static void enable_ai_interrupts(struct comedi_device *dev, · 6 unmodified lines | |||
| 1277 | /* initialize plx9080 chip */ | 1285 | /* initialize plx9080 chip */ |
| 1278 | static void init_plx9080(struct comedi_device *dev) | 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 | struct pcidas64_private *devpriv = dev->private; | 1289 | struct pcidas64_private *devpriv = dev->private; |
| 1282 | uint32_t bits; | 1290 | uint32_t bits; |
| 1283 | void __iomem *plx_iobase = devpriv->plx9080_iobase; | 1291 | void __iomem *plx_iobase = devpriv->plx9080_iobase; |
| @@ -1318,12 +1326,12 @@ static void init_plx9080(struct comedi_device *dev) · 34 unmodified lines | |||
| 1318 | /* enable local burst mode */ | 1326 | /* enable local burst mode */ |
| 1319 | bits |= PLX_DMA_LOCAL_BURST_EN_BIT; | 1327 | bits |= PLX_DMA_LOCAL_BURST_EN_BIT; |
| 1320 | /* 4020 uses 32 bit dma */ | 1328 | /* 4020 uses 32 bit dma */ |
| 1321 | if (thisboard->layout == LAYOUT_4020) | 1329 | if (board->layout == LAYOUT_4020) |
| 1322 | bits |= PLX_LOCAL_BUS_32_WIDE_BITS; | 1330 | bits |= PLX_LOCAL_BUS_32_WIDE_BITS; |
| 1323 | else /* localspace0 bus is 16 bits wide */ | 1331 | else /* localspace0 bus is 16 bits wide */ |
| 1324 | bits |= PLX_LOCAL_BUS_16_WIDE_BITS; | 1332 | bits |= PLX_LOCAL_BUS_16_WIDE_BITS; |
| 1325 | writel(bits, plx_iobase + PLX_DMA1_MODE_REG); | 1333 | writel(bits, plx_iobase + PLX_DMA1_MODE_REG); |
| 1326 | if (ao_cmd_is_supported(thisboard)) | 1334 | if (ao_cmd_is_supported(board)) |
| 1327 | writel(bits, plx_iobase + PLX_DMA0_MODE_REG); | 1335 | writel(bits, plx_iobase + PLX_DMA0_MODE_REG); |
| 1328 | 1336 | ||
| 1329 | /* enable interrupts on plx 9080 */ | 1337 | /* enable interrupts on plx 9080 */ |
| @@ -1355,10 +1363,10 @@ static void disable_ai_pacing(struct comedi_device *dev) · 25 unmodified lines | |||
| 1355 | static int set_ai_fifo_segment_length(struct comedi_device *dev, | 1363 | static int set_ai_fifo_segment_length(struct comedi_device *dev, |
| 1356 | unsigned int num_entries) | 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 | struct pcidas64_private *devpriv = dev->private; | 1367 | struct pcidas64_private *devpriv = dev->private; |
| 1360 | static const int increment_size = 0x100; | 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 | unsigned int num_increments; | 1370 | unsigned int num_increments; |
| 1363 | uint16_t bits; | 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 | return devpriv->ai_fifo_segment_length; | 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 | static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) | 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 | unsigned int num_fifo_entries; | 1398 | unsigned int num_fifo_entries; |
| 1389 | int retval; | 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 | num_fifo_entries = num_samples / fifo->sample_packing_ratio; | 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 | /* query length of fifo */ | 1415 | /* query length of fifo */ |
| 1406 | static unsigned int ai_fifo_size(struct comedi_device *dev) | 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 | struct pcidas64_private *devpriv = dev->private; | 1419 | struct pcidas64_private *devpriv = dev->private; |
| 1410 | 1420 | ||
| 1411 | return devpriv->ai_fifo_segment_length * | 1421 | return devpriv->ai_fifo_segment_length * |
| 1412 | thisboard->ai_fifo->num_segments * | 1422 | board->ai_fifo->num_segments * |
| 1413 | thisboard->ai_fifo->sample_packing_ratio; | 1423 | board->ai_fifo->sample_packing_ratio; |
| 1414 | } | 1424 | } |
| 1415 | 1425 | ||
| 1416 | static void init_stc_registers(struct comedi_device *dev) | 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 | struct pcidas64_private *devpriv = dev->private; | 1429 | struct pcidas64_private *devpriv = dev->private; |
| 1420 | uint16_t bits; | 1430 | uint16_t bits; |
| 1421 | unsigned long flags; | 1431 | unsigned long flags; |
| 1422 | 1432 | ||
| 1423 | spin_lock_irqsave(&dev->spinlock, flags); | 1433 | spin_lock_irqsave(&dev->spinlock, flags); |
| 1424 | 1434 | ||
| 1425 | /* bit should be set for 6025, | 1435 | /* |
| 1426 | * although docs say boards with <= 16 chans should be cleared XXX */ | 1436 | * bit should be set for 6025, |
| 1437 | * although docs say boards with <= 16 chans should be cleared XXX | ||
| 1438 | */ | ||
| 1427 | if (1) | 1439 | if (1) |
| 1428 | devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT; | 1440 | devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT; |
| 1429 | writew(devpriv->adc_control1_bits, | 1441 | writew(devpriv->adc_control1_bits, |
| @@ -1433,7 +1445,7 @@ static void init_stc_registers(struct comedi_device *dev) · 3 unmodified lines | |||
| 1433 | writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); | 1445 | writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); |
| 1434 | 1446 | ||
| 1435 | bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; | 1447 | bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; |
| 1436 | if (thisboard->layout == LAYOUT_4020) | 1448 | if (board->layout == LAYOUT_4020) |
| 1437 | bits |= INTERNAL_CLOCK_4020_BITS; | 1449 | bits |= INTERNAL_CLOCK_4020_BITS; |
| 1438 | devpriv->hw_config_bits |= bits; | 1450 | devpriv->hw_config_bits |= bits; |
| 1439 | writew(devpriv->hw_config_bits, | 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 | /* set fifos to maximum size */ | 1459 | /* set fifos to maximum size */ |
| 1448 | devpriv->fifo_size_bits |= DAC_FIFO_BITS; | 1460 | devpriv->fifo_size_bits |= DAC_FIFO_BITS; |
| 1449 | set_ai_fifo_segment_length(dev, | 1461 | set_ai_fifo_segment_length(dev, board->ai_fifo->max_segment_length); |
| 1450 | thisboard->ai_fifo->max_segment_length); | ||
| 1451 | 1462 | ||
| 1452 | devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT; | 1463 | devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT; |
| 1453 | devpriv->intr_enable_bits = | 1464 | devpriv->intr_enable_bits = |
| @@ -1461,13 +1472,13 @@ static void init_stc_registers(struct comedi_device *dev) · 7 unmodified lines | |||
| 1461 | 1472 | ||
| 1462 | static int alloc_and_init_dma_members(struct comedi_device *dev) | 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 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 1476 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 1466 | struct pcidas64_private *devpriv = dev->private; | 1477 | struct pcidas64_private *devpriv = dev->private; |
| 1467 | int i; | 1478 | int i; |
| 1468 | 1479 | ||
| 1469 | /* allocate pci dma buffers */ | 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 | devpriv->ai_buffer[i] = | 1482 | devpriv->ai_buffer[i] = |
| 1472 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, | 1483 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, |
| 1473 | &devpriv->ai_buffer_bus_addr[i]); | 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 | return -ENOMEM; | 1486 | return -ENOMEM; |
| 1476 | } | 1487 | } |
| 1477 | for (i = 0; i < AO_DMA_RING_COUNT; i++) { | 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 | devpriv->ao_buffer[i] = | 1490 | devpriv->ao_buffer[i] = |
| 1480 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, | 1491 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, |
| 1481 | &devpriv-> | 1492 | &devpriv-> |
| @@ -1487,12 +1498,12 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) · 5 unmodified lines | |||
| 1487 | /* allocate dma descriptors */ | 1498 | /* allocate dma descriptors */ |
| 1488 | devpriv->ai_dma_desc = | 1499 | devpriv->ai_dma_desc = |
| 1489 | pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * | 1500 | pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * |
| 1490 | ai_dma_ring_count(thisboard), | 1501 | ai_dma_ring_count(board), |
| 1491 | &devpriv->ai_dma_desc_bus_addr); | 1502 | &devpriv->ai_dma_desc_bus_addr); |
| 1492 | if (!devpriv->ai_dma_desc) | 1503 | if (!devpriv->ai_dma_desc) |
| 1493 | return -ENOMEM; | 1504 | return -ENOMEM; |
| 1494 | 1505 | ||
| 1495 | if (ao_cmd_is_supported(thisboard)) { | 1506 | if (ao_cmd_is_supported(board)) { |
| 1496 | devpriv->ao_dma_desc = | 1507 | devpriv->ao_dma_desc = |
| 1497 | pci_alloc_consistent(pcidev, | 1508 | pci_alloc_consistent(pcidev, |
| 1498 | sizeof(struct plx_dma_desc) * | 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 | return -ENOMEM; | 1513 | return -ENOMEM; |
| 1503 | } | 1514 | } |
| 1504 | /* initialize dma descriptors */ | 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 | devpriv->ai_dma_desc[i].pci_start_addr = | 1517 | devpriv->ai_dma_desc[i].pci_start_addr = |
| 1507 | cpu_to_le32(devpriv->ai_buffer_bus_addr[i]); | 1518 | cpu_to_le32(devpriv->ai_buffer_bus_addr[i]); |
| 1508 | if (thisboard->layout == LAYOUT_4020) | 1519 | if (board->layout == LAYOUT_4020) |
| 1509 | devpriv->ai_dma_desc[i].local_start_addr = | 1520 | devpriv->ai_dma_desc[i].local_start_addr = |
| 1510 | cpu_to_le32(devpriv->local1_iobase + | 1521 | cpu_to_le32(devpriv->local1_iobase + |
| 1511 | ADC_FIFO_REG); | 1522 | ADC_FIFO_REG); |
| @@ -1516,12 +1527,12 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) · 4 unmodified lines | |||
| 1516 | devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(0); | 1527 | devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(0); |
| 1517 | devpriv->ai_dma_desc[i].next = | 1528 | devpriv->ai_dma_desc[i].next = |
| 1518 | cpu_to_le32((devpriv->ai_dma_desc_bus_addr + | 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 | sizeof(devpriv->ai_dma_desc[0])) | | 1531 | sizeof(devpriv->ai_dma_desc[0])) | |
| 1521 | PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | | 1532 | PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | |
| 1522 | PLX_XFER_LOCAL_TO_PCI); | 1533 | PLX_XFER_LOCAL_TO_PCI); |
| 1523 | } | 1534 | } |
| 1524 | if (ao_cmd_is_supported(thisboard)) { | 1535 | if (ao_cmd_is_supported(board)) { |
| 1525 | for (i = 0; i < AO_DMA_RING_COUNT; i++) { | 1536 | for (i = 0; i < AO_DMA_RING_COUNT; i++) { |
| 1526 | devpriv->ao_dma_desc[i].pci_start_addr = | 1537 | devpriv->ao_dma_desc[i].pci_start_addr = |
| 1527 | cpu_to_le32(devpriv->ao_buffer_bus_addr[i]); | 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 | static void cb_pcidas64_free_dma(struct comedi_device *dev) | 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 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 1557 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 1547 | struct pcidas64_private *devpriv = dev->private; | 1558 | struct pcidas64_private *devpriv = dev->private; |
| 1548 | int i; | 1559 | int i; |
| @@ -1551,7 +1562,7 @@ static void cb_pcidas64_free_dma(struct comedi_device *dev) · 2 unmodified lines | |||
| 1551 | return; | 1562 | return; |
| 1552 | 1563 | ||
| 1553 | /* free pci dma buffers */ | 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 | if (devpriv->ai_buffer[i]) | 1566 | if (devpriv->ai_buffer[i]) |
| 1556 | pci_free_consistent(pcidev, | 1567 | pci_free_consistent(pcidev, |
| 1557 | DMA_BUFFER_SIZE, | 1568 | DMA_BUFFER_SIZE, |
| @@ -1569,7 +1580,7 @@ static void cb_pcidas64_free_dma(struct comedi_device *dev) · 11 unmodified lines | |||
| 1569 | if (devpriv->ai_dma_desc) | 1580 | if (devpriv->ai_dma_desc) |
| 1570 | pci_free_consistent(pcidev, | 1581 | pci_free_consistent(pcidev, |
| 1571 | sizeof(struct plx_dma_desc) * | 1582 | sizeof(struct plx_dma_desc) * |
| 1572 | ai_dma_ring_count(thisboard), | 1583 | ai_dma_ring_count(board), |
| 1573 | devpriv->ai_dma_desc, | 1584 | devpriv->ai_dma_desc, |
| 1574 | devpriv->ai_dma_desc_bus_addr); | 1585 | devpriv->ai_dma_desc_bus_addr); |
| 1575 | if (devpriv->ao_dma_desc) | 1586 | if (devpriv->ao_dma_desc) |
| @@ -1588,7 +1599,9 @@ static inline void warn_external_queue(struct comedi_device *dev) · 12 unmodified lines | |||
| 1588 | "Use internal AI channel queue (channels must be consecutive and use same range/aref)\n"); | 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 | static const int i2c_high_udelay = 1000; | 1605 | static const int i2c_high_udelay = 1000; |
| 1593 | static const int i2c_low_udelay = 10; | 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 | uint8_t bitstream; | 1697 | uint8_t bitstream; |
| 1685 | static const int read_bit = 0x1; | 1698 | static const int read_bit = 0x1; |
| 1686 | 1699 | ||
| 1687 | /* XXX need mutex to prevent simultaneous attempts to access | 1700 | /* |
| 1688 | * eeprom and i2c bus */ | 1701 | * XXX need mutex to prevent simultaneous attempts to access |
| 1702 | * eeprom and i2c bus | ||
| 1703 | */ | ||
| 1689 | 1704 | ||
| 1690 | /* make sure we dont send anything to eeprom */ | 1705 | /* make sure we dont send anything to eeprom */ |
| 1691 | devpriv->plx_control_bits &= ~CTL_EE_CS; | 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 | struct comedi_insn *insn, | 1735 | struct comedi_insn *insn, |
| 1721 | unsigned long context) | 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 | struct pcidas64_private *devpriv = dev->private; | 1739 | struct pcidas64_private *devpriv = dev->private; |
| 1725 | unsigned int status; | 1740 | unsigned int status; |
| 1726 | 1741 | ||
| 1727 | status = readw(devpriv->main_iobase + HW_STATUS_REG); | 1742 | status = readw(devpriv->main_iobase + HW_STATUS_REG); |
| 1728 | if (thisboard->layout == LAYOUT_4020) { | 1743 | if (board->layout == LAYOUT_4020) { |
| 1729 | status = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG); | 1744 | status = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG); |
| 1730 | if (status) | 1745 | if (status) |
| 1731 | return 0; | 1746 | return 0; |
| @@ -1739,7 +1754,7 @@ static int cb_pcidas64_ai_eoc(struct comedi_device *dev, · 7 unmodified lines | |||
| 1739 | static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, | 1754 | static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, |
| 1740 | struct comedi_insn *insn, unsigned int *data) | 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 | struct pcidas64_private *devpriv = dev->private; | 1758 | struct pcidas64_private *devpriv = dev->private; |
| 1744 | unsigned int bits = 0, n; | 1759 | unsigned int bits = 0, n; |
| 1745 | unsigned int channel, range, aref; | 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 | devpriv->main_iobase + ADC_CONTROL1_REG); | 1778 | devpriv->main_iobase + ADC_CONTROL1_REG); |
| 1764 | spin_unlock_irqrestore(&dev->spinlock, flags); | 1779 | spin_unlock_irqrestore(&dev->spinlock, flags); |
| 1765 | 1780 | ||
| 1766 | if (thisboard->layout != LAYOUT_4020) { | 1781 | if (board->layout != LAYOUT_4020) { |
| 1767 | /* use internal queue */ | 1782 | /* use internal queue */ |
| 1768 | devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; | 1783 | devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; |
| 1769 | writew(devpriv->hw_config_bits, | 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 | if (insn->chanspec & CR_ALT_SOURCE) { | 1788 | if (insn->chanspec & CR_ALT_SOURCE) { |
| 1774 | unsigned int cal_en_bit; | 1789 | unsigned int cal_en_bit; |
| 1775 | 1790 | ||
| 1776 | if (thisboard->layout == LAYOUT_60XX) | 1791 | if (board->layout == LAYOUT_60XX) |
| 1777 | cal_en_bit = CAL_EN_60XX_BIT; | 1792 | cal_en_bit = CAL_EN_60XX_BIT; |
| 1778 | else | 1793 | else |
| 1779 | cal_en_bit = CAL_EN_64XX_BIT; | 1794 | cal_en_bit = CAL_EN_64XX_BIT; |
| 1780 | /* select internal reference source to connect | 1795 | /* |
| 1781 | * to channel 0 */ | 1796 | * select internal reference source to connect |
| 1797 | * to channel 0 | ||
| 1798 | */ | ||
| 1782 | writew(cal_en_bit | | 1799 | writew(cal_en_bit | |
| 1783 | adc_src_bits(devpriv->calibration_source), | 1800 | adc_src_bits(devpriv->calibration_source), |
| 1784 | devpriv->main_iobase + CALIBRATION_REG); | 1801 | devpriv->main_iobase + CALIBRATION_REG); |
| 1785 | } else { | 1802 | } else { |
| 1786 | /* make sure internal calibration source | 1803 | /* |
| 1787 | * is turned off */ | 1804 | * make sure internal calibration source |
| 1805 | * is turned off | ||
| 1806 | */ | ||
| 1788 | writew(0, devpriv->main_iobase + CALIBRATION_REG); | 1807 | writew(0, devpriv->main_iobase + CALIBRATION_REG); |
| 1789 | } | 1808 | } |
| 1790 | /* load internal queue */ | 1809 | /* load internal queue */ |
| @@ -1816,8 +1835,10 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 25 unmodified lines | |||
| 1816 | devpriv->i2c_cal_range_bits |= attenuate_bit(channel); | 1835 | devpriv->i2c_cal_range_bits |= attenuate_bit(channel); |
| 1817 | else | 1836 | else |
| 1818 | devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel); | 1837 | devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel); |
| 1819 | /* update calibration/range i2c register only if necessary, | 1838 | /* |
| 1820 | * as it is very slow */ | 1839 | * update calibration/range i2c register only if necessary, |
| 1840 | * as it is very slow | ||
| 1841 | */ | ||
| 1821 | if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { | 1842 | if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { |
| 1822 | uint8_t i2c_data = devpriv->i2c_cal_range_bits; | 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 | sizeof(i2c_data)); | 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 | * before writing to convert register. | 1851 | * before writing to convert register. |
| 1830 | * Using somewhat arbitrary setting of 4 master clock ticks | 1852 | * Using somewhat arbitrary setting of 4 master clock ticks |
| 1831 | * = 0.1 usec */ | 1853 | * = 0.1 usec |
| 1854 | */ | ||
| 1832 | writew(0, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); | 1855 | writew(0, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); |
| 1833 | writew(2, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); | 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 | if (ret) | 1869 | if (ret) |
| 1847 | return ret; | 1870 | return ret; |
| 1848 | 1871 | ||
| 1849 | if (thisboard->layout == LAYOUT_4020) | 1872 | if (board->layout == LAYOUT_4020) |
| 1850 | data[n] = readl(dev->mmio + ADC_FIFO_REG) & 0xffff; | 1873 | data[n] = readl(dev->mmio + ADC_FIFO_REG) & 0xffff; |
| 1851 | else | 1874 | else |
| 1852 | data[n] = readw(devpriv->main_iobase + PIPE1_READ_REG); | 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 | static int ai_config_calibration_source(struct comedi_device *dev, | 1881 | static int ai_config_calibration_source(struct comedi_device *dev, |
| 1859 | unsigned int *data) | 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 | struct pcidas64_private *devpriv = dev->private; | 1885 | struct pcidas64_private *devpriv = dev->private; |
| 1863 | unsigned int source = data[1]; | 1886 | unsigned int source = data[1]; |
| 1864 | int num_calibration_sources; | 1887 | int num_calibration_sources; |
| 1865 | 1888 | ||
| 1866 | if (thisboard->layout == LAYOUT_60XX) | 1889 | if (board->layout == LAYOUT_60XX) |
| 1867 | num_calibration_sources = 16; | 1890 | num_calibration_sources = 16; |
| 1868 | else | 1891 | else |
| 1869 | num_calibration_sources = 8; | 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 | static int ai_config_block_size(struct comedi_device *dev, unsigned int *data) | 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 | int fifo_size; | 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 | unsigned int block_size, requested_block_size; | 1909 | unsigned int block_size, requested_block_size; |
| 1887 | int retval; | 1910 | int retval; |
| 1888 | 1911 | ||
| @@ -1933,9 +1956,9 @@ static int ai_config_master_clock_4020(struct comedi_device *dev, · 44 unmodified lines | |||
| 1933 | /* XXX could add support for 60xx series */ | 1956 | /* XXX could add support for 60xx series */ |
| 1934 | static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data) | 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 | case LAYOUT_4020: | 1962 | case LAYOUT_4020: |
| 1940 | return ai_config_master_clock_4020(dev, data); | 1963 | return ai_config_master_clock_4020(dev, data); |
| 1941 | default: | 1964 | default: |
| @@ -1963,9 +1986,11 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, · 21 unmodified lines | |||
| 1963 | return -EINVAL; | 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 | * take into account possible minimum/maximum divisor values. Used | 1991 | * take into account possible minimum/maximum divisor values. Used |
| 1968 | * by other timing checking functions. */ | 1992 | * by other timing checking functions. |
| 1993 | */ | ||
| 1969 | static unsigned int get_divisor(unsigned int ns, unsigned int flags) | 1994 | static unsigned int get_divisor(unsigned int ns, unsigned int flags) |
| 1970 | { | 1995 | { |
| 1971 | unsigned int divisor; | 1996 | unsigned int divisor; |
| @@ -1985,13 +2010,15 @@ static unsigned int get_divisor(unsigned int ns, unsigned int flags) · 13 unmodified lines | |||
| 1985 | return divisor; | 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 | * sets cmd members appropriately. | 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 | static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) | 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 | unsigned long long convert_divisor = 0; | 2022 | unsigned long long convert_divisor = 0; |
| 1996 | unsigned int scan_divisor; | 2023 | unsigned int scan_divisor; |
| 1997 | static const int min_convert_divisor = 3; | 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 | unsigned long long max_scan_divisor, min_scan_divisor; | 2028 | unsigned long long max_scan_divisor, min_scan_divisor; |
| 2002 | 2029 | ||
| 2003 | if (cmd->convert_src == TRIG_TIMER) { | 2030 | if (cmd->convert_src == TRIG_TIMER) { |
| 2004 | if (thisboard->layout == LAYOUT_4020) { | 2031 | if (board->layout == LAYOUT_4020) { |
| 2005 | cmd->convert_arg = 0; | 2032 | cmd->convert_arg = 0; |
| 2006 | } else { | 2033 | } else { |
| 2007 | convert_divisor = get_divisor(cmd->convert_arg, | 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 | static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, | 2105 | static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, |
| 2079 | struct comedi_cmd *cmd) | 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 | int err = 0; | 2109 | int err = 0; |
| 2083 | unsigned int tmp_arg, tmp_arg2; | 2110 | unsigned int tmp_arg, tmp_arg2; |
| 2084 | unsigned int triggers; | 2111 | unsigned int triggers; |
| @@ -2088,14 +2115,14 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, · 3 unmodified lines | |||
| 2088 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); | 2115 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); |
| 2089 | 2116 | ||
| 2090 | triggers = TRIG_TIMER; | 2117 | triggers = TRIG_TIMER; |
| 2091 | if (thisboard->layout == LAYOUT_4020) | 2118 | if (board->layout == LAYOUT_4020) |
| 2092 | triggers |= TRIG_OTHER; | 2119 | triggers |= TRIG_OTHER; |
| 2093 | else | 2120 | else |
| 2094 | triggers |= TRIG_FOLLOW; | 2121 | triggers |= TRIG_FOLLOW; |
| 2095 | err |= comedi_check_trigger_src(&cmd->scan_begin_src, triggers); | 2122 | err |= comedi_check_trigger_src(&cmd->scan_begin_src, triggers); |
| 2096 | 2123 | ||
| 2097 | triggers = TRIG_TIMER; | 2124 | triggers = TRIG_TIMER; |
| 2098 | if (thisboard->layout == LAYOUT_4020) | 2125 | if (board->layout == LAYOUT_4020) |
| 2099 | triggers |= TRIG_NOW; | 2126 | triggers |= TRIG_NOW; |
| 2100 | else | 2127 | else |
| 2101 | triggers |= TRIG_EXT; | 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 | if (cmd->convert_src == TRIG_TIMER) { | 2166 | if (cmd->convert_src == TRIG_TIMER) { |
| 2140 | if (thisboard->layout == LAYOUT_4020) { | 2167 | if (board->layout == LAYOUT_4020) { |
| 2141 | err |= comedi_check_trigger_arg_is(&cmd->convert_arg, | 2168 | err |= comedi_check_trigger_arg_is(&cmd->convert_arg, |
| 2142 | 0); | 2169 | 0); |
| 2143 | } else { | 2170 | } else { |
| 2144 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, | 2171 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 2145 | thisboard-> | 2172 | board->ai_speed); |
| 2146 | ai_speed); | ||
| 2147 | /* | 2173 | /* |
| 2148 | * if scans are timed faster than conversion rate | 2174 | * if scans are timed faster than conversion rate |
| 2149 | * allows | 2175 | * allows |
| @@ -2231,12 +2257,12 @@ static void setup_sample_counters(struct comedi_device *dev, · 81 unmodified lines | |||
| 2231 | 2257 | ||
| 2232 | static inline unsigned int dma_transfer_size(struct comedi_device *dev) | 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 | struct pcidas64_private *devpriv = dev->private; | 2261 | struct pcidas64_private *devpriv = dev->private; |
| 2236 | unsigned int num_samples; | 2262 | unsigned int num_samples; |
| 2237 | 2263 | ||
| 2238 | num_samples = devpriv->ai_fifo_segment_length * | 2264 | num_samples = devpriv->ai_fifo_segment_length * |
| 2239 | thisboard->ai_fifo->sample_packing_ratio; | 2265 | board->ai_fifo->sample_packing_ratio; |
| 2240 | if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t)) | 2266 | if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t)) |
| 2241 | num_samples = DMA_BUFFER_SIZE / sizeof(uint16_t); | 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 | static void select_master_clock(struct comedi_device *dev, | 2344 | static void select_master_clock(struct comedi_device *dev, |
| 2319 | const struct comedi_cmd *cmd) | 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 | case LAYOUT_4020: | 2350 | case LAYOUT_4020: |
| 2325 | select_master_clock_4020(dev, cmd); | 2351 | select_master_clock_4020(dev, cmd); |
| 2326 | break; | 2352 | break; |
| @@ -2350,7 +2376,7 @@ static inline void dma_start_sync(struct comedi_device *dev, · 23 unmodified lines | |||
| 2350 | 2376 | ||
| 2351 | static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) | 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 | struct pcidas64_private *devpriv = dev->private; | 2380 | struct pcidas64_private *devpriv = dev->private; |
| 2355 | uint32_t convert_counter = 0, scan_counter = 0; | 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 | select_master_clock(dev, cmd); | 2385 | select_master_clock(dev, cmd); |
| 2360 | 2386 | ||
| 2361 | if (thisboard->layout == LAYOUT_4020) { | 2387 | if (board->layout == LAYOUT_4020) { |
| 2362 | convert_counter = ai_convert_counter_4020(dev, cmd); | 2388 | convert_counter = ai_convert_counter_4020(dev, cmd); |
| 2363 | } else { | 2389 | } else { |
| 2364 | convert_counter = ai_convert_counter_6xxx(dev, cmd); | 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 | static int setup_channel_queue(struct comedi_device *dev, | 2425 | static int setup_channel_queue(struct comedi_device *dev, |
| 2400 | const struct comedi_cmd *cmd) | 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 | struct pcidas64_private *devpriv = dev->private; | 2429 | struct pcidas64_private *devpriv = dev->private; |
| 2404 | unsigned short bits; | 2430 | unsigned short bits; |
| 2405 | int i; | 2431 | int i; |
| 2406 | 2432 | ||
| 2407 | if (thisboard->layout != LAYOUT_4020) { | 2433 | if (board->layout != LAYOUT_4020) { |
| 2408 | if (use_internal_queue_6xxx(cmd)) { | 2434 | if (use_internal_queue_6xxx(cmd)) { |
| 2409 | devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; | 2435 | devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; |
| 2410 | writew(devpriv->hw_config_bits, | 2436 | writew(devpriv->hw_config_bits, |
| @@ -2468,8 +2494,10 @@ static int setup_channel_queue(struct comedi_device *dev, · 57 unmodified lines | |||
| 2468 | devpriv->main_iobase + | 2494 | devpriv->main_iobase + |
| 2469 | ADC_QUEUE_FIFO_REG); | 2495 | ADC_QUEUE_FIFO_REG); |
| 2470 | } | 2496 | } |
| 2471 | /* doing a queue clear is not specified in board docs, | 2497 | /* |
| 2472 | * but required for reliable operation */ | 2498 | * doing a queue clear is not specified in board docs, |
| 2499 | * but required for reliable operation | ||
| 2500 | */ | ||
| 2473 | writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); | 2501 | writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); |
| 2474 | /* prime queue holding register */ | 2502 | /* prime queue holding register */ |
| 2475 | writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); | 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 | devpriv->i2c_cal_range_bits &= | 2520 | devpriv->i2c_cal_range_bits &= |
| 2493 | ~attenuate_bit(channel); | 2521 | ~attenuate_bit(channel); |
| 2494 | } | 2522 | } |
| 2495 | /* update calibration/range i2c register only if necessary, | 2523 | /* |
| 2496 | * as it is very slow */ | 2524 | * update calibration/range i2c register only if necessary, |
| 2525 | * as it is very slow | ||
| 2526 | */ | ||
| 2497 | if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { | 2527 | if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { |
| 2498 | uint8_t i2c_data = devpriv->i2c_cal_range_bits; | 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 | struct pcidas64_private *devpriv = dev->private; | 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 | * are supposedly unused during chained dma, | 2545 | * are supposedly unused during chained dma, |
| 2515 | * but I have found that left over values from last operation | 2546 | * but I have found that left over values from last operation |
| 2516 | * occasionally cause problems with transfer of first dma | 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 | if (dma_channel) { | 2550 | if (dma_channel) { |
| 2519 | writel(0, | 2551 | writel(0, |
| 2520 | devpriv->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG); | 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 | static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) | 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 | struct pcidas64_private *devpriv = dev->private; | 2572 | struct pcidas64_private *devpriv = dev->private; |
| 2541 | struct comedi_async *async = s->async; | 2573 | struct comedi_async *async = s->async; |
| 2542 | struct comedi_cmd *cmd = &async->cmd; | 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 | /* set mode, allow conversions through software gate */ | 2597 | /* set mode, allow conversions through software gate */ |
| 2566 | devpriv->adc_control1_bits |= ADC_SW_GATE_BIT; | 2598 | devpriv->adc_control1_bits |= ADC_SW_GATE_BIT; |
| 2567 | devpriv->adc_control1_bits &= ~ADC_DITHER_BIT; | 2599 | devpriv->adc_control1_bits &= ~ADC_DITHER_BIT; |
| 2568 | if (thisboard->layout != LAYOUT_4020) { | 2600 | if (board->layout != LAYOUT_4020) { |
| 2569 | devpriv->adc_control1_bits &= ~ADC_MODE_MASK; | 2601 | devpriv->adc_control1_bits &= ~ADC_MODE_MASK; |
| 2570 | if (cmd->convert_src == TRIG_EXT) | 2602 | if (cmd->convert_src == TRIG_EXT) |
| 2571 | /* good old mode 13 */ | 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 | writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); | 2627 | writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); |
| 2596 | 2628 | ||
| 2597 | if ((cmd->flags & CMDF_WAKE_EOS) == 0 || | 2629 | if ((cmd->flags & CMDF_WAKE_EOS) == 0 || |
| 2598 | thisboard->layout == LAYOUT_4020) { | 2630 | board->layout == LAYOUT_4020) { |
| 2599 | devpriv->ai_dma_index = 0; | 2631 | devpriv->ai_dma_index = 0; |
| 2600 | 2632 | ||
| 2601 | /* set dma transfer size */ | 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 | devpriv->ai_dma_desc[i].transfer_size = | 2635 | devpriv->ai_dma_desc[i].transfer_size = |
| 2604 | cpu_to_le32(dma_transfer_size(dev) * | 2636 | cpu_to_le32(dma_transfer_size(dev) * |
| 2605 | sizeof(uint16_t)); | 2637 | sizeof(uint16_t)); |
| @@ -2614,7 +2646,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 8 unmodified lines | |||
| 2614 | dma_start_sync(dev, 1); | 2646 | dma_start_sync(dev, 1); |
| 2615 | } | 2647 | } |
| 2616 | 2648 | ||
| 2617 | if (thisboard->layout == LAYOUT_4020) { | 2649 | if (board->layout == LAYOUT_4020) { |
| 2618 | /* set source for external triggers */ | 2650 | /* set source for external triggers */ |
| 2619 | bits = 0; | 2651 | bits = 0; |
| 2620 | if (cmd->start_src == TRIG_EXT && CR_CHAN(cmd->start_arg)) | 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 | 0x7fff; | 2701 | 0x7fff; |
| 2670 | write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & | 2702 | write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & |
| 2671 | 0x7fff; | 2703 | 0x7fff; |
| 2672 | /* Get most significant bits (grey code). | 2704 | /* |
| 2705 | * Get most significant bits (grey code). | ||
| 2673 | * Different boards use different code so use a scheme | 2706 | * Different boards use different code so use a scheme |
| 2674 | * that doesn't depend on encoding. This read must | 2707 | * that doesn't depend on encoding. This read must |
| 2675 | * occur after reading least significant 15 bits to avoid race | 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 | prepost_bits = readw(devpriv->main_iobase + PREPOST_REG); | 2711 | prepost_bits = readw(devpriv->main_iobase + PREPOST_REG); |
| 2678 | 2712 | ||
| 2679 | /* if read and write pointers are not on the same fifo segment, | 2713 | /* |
| 2680 | * read to the end of the read segment */ | 2714 | * if read and write pointers are not on the same fifo segment, |
| 2715 | * read to the end of the read segment | ||
| 2716 | */ | ||
| 2681 | read_segment = adc_upper_read_ptr_code(prepost_bits); | 2717 | read_segment = adc_upper_read_ptr_code(prepost_bits); |
| 2682 | write_segment = adc_upper_write_ptr_code(prepost_bits); | 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 | } while (read_segment != write_segment); | 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 | * pointers. The pci-4020 hardware only supports dma transfers (it only | 2747 | * pointers. The pci-4020 hardware only supports dma transfers (it only |
| 2711 | * supports the use of pio for draining the last remaining points from the | 2748 | * supports the use of pio for draining the last remaining points from the |
| 2712 | * fifo when a data acquisition operation has completed). | 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 | /* empty fifo */ | 2781 | /* empty fifo */ |
| 2745 | static void pio_drain_ai_fifo(struct comedi_device *dev) | 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 | pio_drain_ai_fifo_32(dev); | 2787 | pio_drain_ai_fifo_32(dev); |
| 2751 | else | 2788 | else |
| 2752 | pio_drain_ai_fifo_16(dev); | 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 | static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) | 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 | struct pcidas64_private *devpriv = dev->private; | 2795 | struct pcidas64_private *devpriv = dev->private; |
| 2759 | struct comedi_subdevice *s = dev->read_subdev; | 2796 | struct comedi_subdevice *s = dev->read_subdev; |
| 2760 | uint32_t next_transfer_addr; | 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 | devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] || | 2812 | devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] || |
| 2776 | next_transfer_addr >= | 2813 | next_transfer_addr >= |
| 2777 | devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] + | 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 | /* transfer data from dma buffer to comedi buffer */ | 2816 | /* transfer data from dma buffer to comedi buffer */ |
| 2780 | num_samples = comedi_nsamples_left(s, dma_transfer_size(dev)); | 2817 | num_samples = comedi_nsamples_left(s, dma_transfer_size(dev)); |
| 2781 | comedi_buf_write_samples(s, | 2818 | comedi_buf_write_samples(s, |
| 2782 | devpriv->ai_buffer[devpriv->ai_dma_index], | 2819 | devpriv->ai_buffer[devpriv->ai_dma_index], |
| 2783 | num_samples); | 2820 | num_samples); |
| 2784 | devpriv->ai_dma_index = (devpriv->ai_dma_index + 1) % | 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 | 2824 | /* |
| 2788 | * (use end-of-chain bit to mark last unused buffer) */ | 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 | static void handle_ai_interrupt(struct comedi_device *dev, | 2830 | static void handle_ai_interrupt(struct comedi_device *dev, |
| 2792 | unsigned short status, | 2831 | unsigned short status, |
| 2793 | unsigned int plx_status) | 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 | struct pcidas64_private *devpriv = dev->private; | 2835 | struct pcidas64_private *devpriv = dev->private; |
| 2797 | struct comedi_subdevice *s = dev->read_subdev; | 2836 | struct comedi_subdevice *s = dev->read_subdev; |
| 2798 | struct comedi_async *async = s->async; | 2837 | struct comedi_async *async = s->async; |
| @@ -2821,7 +2860,7 @@ static void handle_ai_interrupt(struct comedi_device *dev, · 22 unmodified lines | |||
| 2821 | if ((status & ADC_DONE_BIT) || | 2860 | if ((status & ADC_DONE_BIT) || |
| 2822 | ((cmd->flags & CMDF_WAKE_EOS) && | 2861 | ((cmd->flags & CMDF_WAKE_EOS) && |
| 2823 | (status & ADC_INTR_PENDING_BIT) && | 2862 | (status & ADC_INTR_PENDING_BIT) && |
| 2824 | (thisboard->layout != LAYOUT_4020))) { | 2863 | (board->layout != LAYOUT_4020))) { |
| 2825 | spin_lock_irqsave(&dev->spinlock, flags); | 2864 | spin_lock_irqsave(&dev->spinlock, flags); |
| 2826 | if (devpriv->ai_cmd_running) { | 2865 | if (devpriv->ai_cmd_running) { |
| 2827 | spin_unlock_irqrestore(&dev->spinlock, flags); | 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 | next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next); | 2972 | next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next); |
| 2934 | next_bits |= PLX_END_OF_CHAIN_BIT; | 2973 | next_bits |= PLX_END_OF_CHAIN_BIT; |
| 2935 | devpriv->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits); | 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 | 2975 | /* |
| 2937 | * for the last buffer */ | 2976 | * clear end of chain bit on previous buffer now that we have set it |
| 2977 | * for the last buffer | ||
| 2978 | */ | ||
| 2938 | next_bits = le32_to_cpu(devpriv->ao_dma_desc[prev_buffer_index].next); | 2979 | next_bits = le32_to_cpu(devpriv->ao_dma_desc[prev_buffer_index].next); |
| 2939 | next_bits &= ~PLX_END_OF_CHAIN_BIT; | 2980 | next_bits &= ~PLX_END_OF_CHAIN_BIT; |
| 2940 | devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits); | 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 | plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG); | 3068 | plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG); |
| 3028 | status = readw(devpriv->main_iobase + HW_STATUS_REG); | 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 | * cause a NULL dereference if we continue through the | 3073 | * cause a NULL dereference if we continue through the |
| 3032 | * interrupt handler */ | 3074 | * interrupt handler |
| 3075 | */ | ||
| 3033 | if (!dev->attached) | 3076 | if (!dev->attached) |
| 3034 | return IRQ_HANDLED; | 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 | static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, | 3111 | static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, |
| 3069 | struct comedi_insn *insn, unsigned int *data) | 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 | struct pcidas64_private *devpriv = dev->private; | 3115 | struct pcidas64_private *devpriv = dev->private; |
| 3073 | int chan = CR_CHAN(insn->chanspec); | 3116 | int chan = CR_CHAN(insn->chanspec); |
| 3074 | int range = CR_RANGE(insn->chanspec); | 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 | devpriv->main_iobase + DAC_CONTROL1_REG); | 3125 | devpriv->main_iobase + DAC_CONTROL1_REG); |
| 3083 | 3126 | ||
| 3084 | /* write to channel */ | 3127 | /* write to channel */ |
| 3085 | if (thisboard->layout == LAYOUT_4020) { | 3128 | if (board->layout == LAYOUT_4020) { |
| 3086 | writew(data[0] & 0xff, | 3129 | writew(data[0] & 0xff, |
| 3087 | devpriv->main_iobase + dac_lsb_4020_reg(chan)); | 3130 | devpriv->main_iobase + dac_lsb_4020_reg(chan)); |
| 3088 | writew((data[0] >> 8) & 0xf, | 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 | unsigned int nbytes; | 3232 | unsigned int nbytes; |
| 3190 | int i; | 3233 | int i; |
| 3191 | 3234 | ||
| 3192 | /* clear queue pointer too, since external queue has | 3235 | /* |
| 3193 | * weird interactions with ao fifo */ | 3236 | * clear queue pointer too, since external queue has |
| 3237 | * weird interactions with ao fifo | ||
| 3238 | */ | ||
| 3194 | writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); | 3239 | writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); |
| 3195 | writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG); | 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 | struct comedi_subdevice *s, | 3268 | struct comedi_subdevice *s, |
| 3224 | struct comedi_cmd *cmd) | 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 | if (s->busy) | 3273 | if (s->busy) |
| 3229 | return 0; | 3274 | return 0; |
| 3230 | if (thisboard->layout == LAYOUT_4020) | 3275 | if (board->layout == LAYOUT_4020) |
| 3231 | return 0; | 3276 | return 0; |
| 3232 | else if (use_internal_queue_6xxx(cmd)) | 3277 | else if (use_internal_queue_6xxx(cmd)) |
| 3233 | return 0; | 3278 | return 0; |
| @@ -3306,7 +3351,7 @@ static int cb_pcidas64_ao_check_chanlist(struct comedi_device *dev, · 72 unmodified lines | |||
| 3306 | static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, | 3351 | static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, |
| 3307 | struct comedi_cmd *cmd) | 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 | int err = 0; | 3355 | int err = 0; |
| 3311 | unsigned int tmp_arg; | 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 | if (cmd->scan_begin_src == TRIG_TIMER) { | 3390 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 3346 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, | 3391 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 3347 | thisboard->ao_scan_speed); | 3392 | board->ao_scan_speed); |
| 3348 | if (get_ao_divisor(cmd->scan_begin_arg, cmd->flags) > | 3393 | if (get_ao_divisor(cmd->scan_begin_arg, cmd->flags) > |
| 3349 | max_counter_value) { | 3394 | max_counter_value) { |
| 3350 | cmd->scan_begin_arg = (max_counter_value + 2) * | 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 | return insn->n; | 3504 | return insn->n; |
| 3460 | } | 3505 | } |
| 3461 | 3506 | ||
| 3462 | /* pci-6025 8800 caldac: | 3507 | /* |
| 3508 | * pci-6025 8800 caldac: | ||
| 3463 | * address 0 == dac channel 0 offset | 3509 | * address 0 == dac channel 0 offset |
| 3464 | * address 1 == dac channel 0 gain | 3510 | * address 1 == dac channel 0 gain |
| 3465 | * address 2 == dac channel 1 offset | 3511 | * address 2 == dac channel 1 offset |
| @@ -3469,7 +3515,8 @@ static int dio_60xx_wbits(struct comedi_device *dev, · 3 unmodified lines | |||
| 3469 | * address 6 == coarse adc gain | 3515 | * address 6 == coarse adc gain |
| 3470 | * address 7 == fine adc gain | 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 | * address 0 == dac channel 0 fine gain | 3520 | * address 0 == dac channel 0 fine gain |
| 3474 | * address 1 == dac channel 0 coarse gain | 3521 | * address 1 == dac channel 0 coarse gain |
| 3475 | * address 2 == dac channel 0 coarse offset | 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 | * address 5 == dac channel 1 coarse gain | 3525 | * address 5 == dac channel 1 coarse gain |
| 3479 | * address 6 == dac channel 0 fine offset | 3526 | * address 6 == dac channel 0 fine offset |
| 3480 | * address 7 == dac channel 1 fine offset | 3527 | * address 7 == dac channel 1 fine offset |
| 3481 | */ | 3528 | */ |
| 3482 | 3529 | ||
| 3483 | static int caldac_8800_write(struct comedi_device *dev, unsigned int address, | 3530 | static int caldac_8800_write(struct comedi_device *dev, unsigned int address, |
| 3484 | uint8_t value) | 3531 | uint8_t value) |
| @@ -3575,9 +3622,9 @@ static int caldac_i2c_write(struct comedi_device *dev, · 90 unmodified lines | |||
| 3575 | static void caldac_write(struct comedi_device *dev, unsigned int channel, | 3622 | static void caldac_write(struct comedi_device *dev, unsigned int channel, |
| 3576 | unsigned int value) | 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 | case LAYOUT_60XX: | 3628 | case LAYOUT_60XX: |
| 3582 | case LAYOUT_64XX: | 3629 | case LAYOUT_64XX: |
| 3583 | caldac_8800_write(dev, channel, value); | 3630 | caldac_8800_write(dev, channel, value); |
| @@ -3738,11 +3785,12 @@ static int eeprom_read_insn(struct comedi_device *dev, · 154 unmodified lines | |||
| 3738 | return 1; | 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 | static int setup_subdevices(struct comedi_device *dev) | 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 | struct pcidas64_private *devpriv = dev->private; | 3794 | struct pcidas64_private *devpriv = dev->private; |
| 3747 | struct comedi_subdevice *s; | 3795 | struct comedi_subdevice *s; |
| 3748 | int i; | 3796 | int i; |
| @@ -3757,24 +3805,26 @@ static int setup_subdevices(struct comedi_device *dev) · 8 unmodified lines | |||
| 3757 | dev->read_subdev = s; | 3805 | dev->read_subdev = s; |
| 3758 | s->type = COMEDI_SUBD_AI; | 3806 | s->type = COMEDI_SUBD_AI; |
| 3759 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ; | 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 | s->subdev_flags |= SDF_COMMON | SDF_DIFF; | 3809 | s->subdev_flags |= SDF_COMMON | SDF_DIFF; |
| 3762 | else if (thisboard->layout == LAYOUT_64XX) | 3810 | else if (board->layout == LAYOUT_64XX) |
| 3763 | s->subdev_flags |= SDF_DIFF; | 3811 | s->subdev_flags |= SDF_DIFF; |
| 3764 | /* XXX Number of inputs in differential mode is ignored */ | 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 | s->len_chanlist = 0x2000; | 3814 | s->len_chanlist = 0x2000; |
| 3767 | s->maxdata = (1 << thisboard->ai_bits) - 1; | 3815 | s->maxdata = (1 << board->ai_bits) - 1; |
| 3768 | s->range_table = thisboard->ai_range_table; | 3816 | s->range_table = board->ai_range_table; |
| 3769 | s->insn_read = ai_rinsn; | 3817 | s->insn_read = ai_rinsn; |
| 3770 | s->insn_config = ai_config_insn; | 3818 | s->insn_config = ai_config_insn; |
| 3771 | s->do_cmd = ai_cmd; | 3819 | s->do_cmd = ai_cmd; |
| 3772 | s->do_cmdtest = ai_cmdtest; | 3820 | s->do_cmdtest = ai_cmdtest; |
| 3773 | s->cancel = ai_cancel; | 3821 | s->cancel = ai_cancel; |
| 3774 | if (thisboard->layout == LAYOUT_4020) { | 3822 | if (board->layout == LAYOUT_4020) { |
| 3775 | uint8_t data; | 3823 | uint8_t data; |
| 3776 | /* set adc to read from inputs | 3824 | /* |
| 3777 | * (not internal calibration sources) */ | 3825 | * set adc to read from inputs |
| 3826 | * (not internal calibration sources) | ||
| 3827 | */ | ||
| 3778 | devpriv->i2c_cal_range_bits = adc_src_4020_bits(4); | 3828 | devpriv->i2c_cal_range_bits = adc_src_4020_bits(4); |
| 3779 | /* set channels to +-5 volt input ranges */ | 3829 | /* set channels to +-5 volt input ranges */ |
| 3780 | for (i = 0; i < s->n_chan; i++) | 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 | /* analog output subdevice */ | 3836 | /* analog output subdevice */ |
| 3787 | s = &dev->subdevices[1]; | 3837 | s = &dev->subdevices[1]; |
| 3788 | if (thisboard->ao_nchan) { | 3838 | if (board->ao_nchan) { |
| 3789 | s->type = COMEDI_SUBD_AO; | 3839 | s->type = COMEDI_SUBD_AO; |
| 3790 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | | 3840 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | |
| 3791 | SDF_GROUND | SDF_CMD_WRITE; | 3841 | SDF_GROUND | SDF_CMD_WRITE; |
| 3792 | s->n_chan = thisboard->ao_nchan; | 3842 | s->n_chan = board->ao_nchan; |
| 3793 | s->maxdata = (1 << thisboard->ao_bits) - 1; | 3843 | s->maxdata = (1 << board->ao_bits) - 1; |
| 3794 | s->range_table = thisboard->ao_range_table; | 3844 | s->range_table = board->ao_range_table; |
| 3795 | s->insn_write = ao_winsn; | 3845 | s->insn_write = ao_winsn; |
| 3796 | 3846 | ||
| 3797 | ret = comedi_alloc_subdev_readback(s); | 3847 | ret = comedi_alloc_subdev_readback(s); |
| 3798 | if (ret) | 3848 | if (ret) |
| 3799 | return ret; | 3849 | return ret; |
| 3800 | 3850 | ||
| 3801 | if (ao_cmd_is_supported(thisboard)) { | 3851 | if (ao_cmd_is_supported(board)) { |
| 3802 | dev->write_subdev = s; | 3852 | dev->write_subdev = s; |
| 3803 | s->do_cmdtest = ao_cmdtest; | 3853 | s->do_cmdtest = ao_cmdtest; |
| 3804 | s->do_cmd = ao_cmd; | 3854 | s->do_cmd = ao_cmd; |
| 3805 | s->len_chanlist = thisboard->ao_nchan; | 3855 | s->len_chanlist = board->ao_nchan; |
| 3806 | s->cancel = ao_cancel; | 3856 | s->cancel = ao_cancel; |
| 3807 | } | 3857 | } |
| 3808 | } else { | 3858 | } else { |
| @@ -3811,7 +3861,7 @@ static int setup_subdevices(struct comedi_device *dev) · 2 unmodified lines | |||
| 3811 | 3861 | ||
| 3812 | /* digital input */ | 3862 | /* digital input */ |
| 3813 | s = &dev->subdevices[2]; | 3863 | s = &dev->subdevices[2]; |
| 3814 | if (thisboard->layout == LAYOUT_64XX) { | 3864 | if (board->layout == LAYOUT_64XX) { |
| 3815 | s->type = COMEDI_SUBD_DI; | 3865 | s->type = COMEDI_SUBD_DI; |
| 3816 | s->subdev_flags = SDF_READABLE; | 3866 | s->subdev_flags = SDF_READABLE; |
| 3817 | s->n_chan = 4; | 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 | /* digital output */ | 3875 | /* digital output */ |
| 3826 | if (thisboard->layout == LAYOUT_64XX) { | 3876 | if (board->layout == LAYOUT_64XX) { |
| 3827 | s = &dev->subdevices[3]; | 3877 | s = &dev->subdevices[3]; |
| 3828 | s->type = COMEDI_SUBD_DO; | 3878 | s->type = COMEDI_SUBD_DO; |
| 3829 | s->subdev_flags = SDF_WRITABLE; | 3879 | s->subdev_flags = SDF_WRITABLE; |
| @@ -3837,8 +3887,8 @@ static int setup_subdevices(struct comedi_device *dev) · 7 unmodified lines | |||
| 3837 | 3887 | ||
| 3838 | /* 8255 */ | 3888 | /* 8255 */ |
| 3839 | s = &dev->subdevices[4]; | 3889 | s = &dev->subdevices[4]; |
| 3840 | if (thisboard->has_8255) { | 3890 | if (board->has_8255) { |
| 3841 | if (thisboard->layout == LAYOUT_4020) { | 3891 | if (board->layout == LAYOUT_4020) { |
| 3842 | ret = subdev_8255_init(dev, s, dio_callback_4020, | 3892 | ret = subdev_8255_init(dev, s, dio_callback_4020, |
| 3843 | I8255_4020_REG); | 3893 | I8255_4020_REG); |
| 3844 | } else { | 3894 | } else { |
| @@ -3853,7 +3903,7 @@ static int setup_subdevices(struct comedi_device *dev) · 8 unmodified lines | |||
| 3853 | 3903 | ||
| 3854 | /* 8 channel dio for 60xx */ | 3904 | /* 8 channel dio for 60xx */ |
| 3855 | s = &dev->subdevices[5]; | 3905 | s = &dev->subdevices[5]; |
| 3856 | if (thisboard->layout == LAYOUT_60XX) { | 3906 | if (board->layout == LAYOUT_60XX) { |
| 3857 | s->type = COMEDI_SUBD_DIO; | 3907 | s->type = COMEDI_SUBD_DIO; |
| 3858 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; | 3908 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; |
| 3859 | s->n_chan = 8; | 3909 | s->n_chan = 8; |
| @@ -3870,7 +3920,7 @@ static int setup_subdevices(struct comedi_device *dev) · 10 unmodified lines | |||
| 3870 | s->type = COMEDI_SUBD_CALIB; | 3920 | s->type = COMEDI_SUBD_CALIB; |
| 3871 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; | 3921 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 3872 | s->n_chan = 8; | 3922 | s->n_chan = 8; |
| 3873 | if (thisboard->layout == LAYOUT_4020) | 3923 | if (board->layout == LAYOUT_4020) |
| 3874 | s->maxdata = 0xfff; | 3924 | s->maxdata = 0xfff; |
| 3875 | else | 3925 | else |
| 3876 | s->maxdata = 0xff; | 3926 | s->maxdata = 0xff; |
| @@ -3887,7 +3937,7 @@ static int setup_subdevices(struct comedi_device *dev) · 10 unmodified lines | |||
| 3887 | 3937 | ||
| 3888 | /* 2 channel ad8402 potentiometer */ | 3938 | /* 2 channel ad8402 potentiometer */ |
| 3889 | s = &dev->subdevices[7]; | 3939 | s = &dev->subdevices[7]; |
| 3890 | if (thisboard->layout == LAYOUT_64XX) { | 3940 | if (board->layout == LAYOUT_64XX) { |
| 3891 | s->type = COMEDI_SUBD_CALIB; | 3941 | s->type = COMEDI_SUBD_CALIB; |
| 3892 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; | 3942 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
| 3893 | s->n_chan = 2; | 3943 | s->n_chan = 2; |
| @@ -3929,16 +3979,16 @@ static int auto_attach(struct comedi_device *dev, · 35 unmodified lines | |||
| 3929 | unsigned long context) | 3979 | unsigned long context) |
| 3930 | { | 3980 | { |
| 3931 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct pcidas64_private *devpriv; | 3983 | struct pcidas64_private *devpriv; |
| 3934 | uint32_t local_range, local_decode; | 3984 | uint32_t local_range, local_decode; |
| 3935 | int retval; | 3985 | int retval; |
| 3936 | 3986 | ||
| 3937 | if (context < ARRAY_SIZE(pcidas64_boards)) | 3987 | if (context < ARRAY_SIZE(pcidas64_boards)) |
| 3938 | thisboard = &pcidas64_boards[context]; | 3988 | board = &pcidas64_boards[context]; |
| 3939 | if (!thisboard) | 3989 | if (!board) |
| 3940 | return -ENODEV; | 3990 | return -ENODEV; |
| 3941 | dev->board_ptr = thisboard; | 3991 | dev->board_ptr = board; |
| 3942 | 3992 | ||
| 3943 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 3993 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 3944 | if (!devpriv) | 3994 | if (!devpriv) |
| @@ -3950,7 +4000,7 @@ static int auto_attach(struct comedi_device *dev, · 5 unmodified lines | |||
| 3950 | pci_set_master(pcidev); | 4000 | pci_set_master(pcidev); |
| 3951 | 4001 | ||
| 3952 | /* Initialize dev->board_name */ | 4002 | /* Initialize dev->board_name */ |
| 3953 | dev->board_name = thisboard->name; | 4003 | dev->board_name = board->name; |
| 3954 | 4004 | ||
| 3955 | devpriv->main_phys_iobase = pci_resource_start(pcidev, 2); | 4005 | devpriv->main_phys_iobase = pci_resource_start(pcidev, 2); |
| 3956 | devpriv->dio_counter_phys_iobase = pci_resource_start(pcidev, 3); | 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 | unsigned long context) | 335 | unsigned long context) |
| 336 | { | 336 | { |
| 337 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct cb_pcidda_private *devpriv; | 339 | struct cb_pcidda_private *devpriv; |
| 340 | struct comedi_subdevice *s; | 340 | struct comedi_subdevice *s; |
| 341 | int i; | 341 | int i; |
| 342 | int ret; | 342 | int ret; |
| 343 | 343 | ||
| 344 | if (context < ARRAY_SIZE(cb_pcidda_boards)) | 344 | if (context < ARRAY_SIZE(cb_pcidda_boards)) |
| 345 | thisboard = &cb_pcidda_boards[context]; | 345 | board = &cb_pcidda_boards[context]; |
| 346 | if (!thisboard) | 346 | if (!board) |
| 347 | return -ENODEV; | 347 | return -ENODEV; |
| 348 | dev->board_ptr = thisboard; | 348 | dev->board_ptr = board; |
| 349 | dev->board_name = thisboard->name; | 349 | dev->board_name = board->name; |
| 350 | 350 | ||
| 351 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 351 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 352 | if (!devpriv) | 352 | if (!devpriv) |
| @@ -366,8 +366,8 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev, · 13 unmodified lines | |||
| 366 | /* analog output subdevice */ | 366 | /* analog output subdevice */ |
| 367 | s->type = COMEDI_SUBD_AO; | 367 | s->type = COMEDI_SUBD_AO; |
| 368 | s->subdev_flags = SDF_WRITABLE; | 368 | s->subdev_flags = SDF_WRITABLE; |
| 369 | s->n_chan = thisboard->ao_chans; | 369 | s->n_chan = board->ao_chans; |
| 370 | s->maxdata = (1 << thisboard->ao_bits) - 1; | 370 | s->maxdata = (1 << board->ao_bits) - 1; |
| 371 | s->range_table = &cb_pcidda_ranges; | 371 | s->range_table = &cb_pcidda_ranges; |
| 372 | s->insn_write = cb_pcidda_ao_insn_write; | 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 | devpriv->eeprom_data[i] = cb_pcidda_read_eeprom(dev, i); | 384 | devpriv->eeprom_data[i] = cb_pcidda_read_eeprom(dev, i); |
| 385 | 385 | ||
| 386 | /* set calibrations dacs */ | 386 | /* set calibrations dacs */ |
| 387 | for (i = 0; i < thisboard->ao_chans; i++) | 387 | for (i = 0; i < board->ao_chans; i++) |
| 388 | cb_pcidda_calibrate(dev, i, devpriv->ao_range[i]); | 388 | cb_pcidda_calibrate(dev, i, devpriv->ao_range[i]); |
| 389 | 389 | ||
| 390 | return 0; | 390 | return 0; |
| @@ -243,7 +243,7 @@ static int cb_pcimdas_ao_insn_write(struct comedi_device *dev, · 242 unmodified lines | |||
| 243 | return insn->n; | 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 | struct comedi_subdevice *s, | 247 | struct comedi_subdevice *s, |
| 248 | struct comedi_insn *insn, | 248 | struct comedi_insn *insn, |
| 249 | unsigned int *data) | 249 | unsigned int *data) |
| @@ -258,7 +258,7 @@ static int cb_pcimdas_di_insn_read(struct comedi_device *dev, · 8 unmodified lines | |||
| 258 | return insn->n; | 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 | struct comedi_subdevice *s, | 262 | struct comedi_subdevice *s, |
| 263 | struct comedi_insn *insn, | 263 | struct comedi_insn *insn, |
| 264 | unsigned int *data) | 264 | unsigned int *data) |
| @@ -424,7 +424,7 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, · 159 unmodified lines | |||
| 424 | s->n_chan = 4; | 424 | s->n_chan = 4; |
| 425 | s->maxdata = 1; | 425 | s->maxdata = 1; |
| 426 | s->range_table = &range_digital; | 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 | /* Digital Output subdevice (main connector) */ | 429 | /* Digital Output subdevice (main connector) */ |
| 430 | s = &dev->subdevices[4]; | 430 | s = &dev->subdevices[4]; |
| @@ -433,7 +433,7 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, · 2 unmodified lines | |||
| 433 | s->n_chan = 4; | 433 | s->n_chan = 4; |
| 434 | s->maxdata = 1; | 434 | s->maxdata = 1; |
| 435 | s->range_table = &range_digital; | 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 | /* Counter subdevice (8254) */ | 438 | /* Counter subdevice (8254) */ |
| 439 | s = &dev->subdevices[5]; | 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 | s = &dev->subdevices[1]; | 165 | s = &dev->subdevices[1]; |
| 166 | /* digital i/o subdevice */ | 166 | /* digital i/o subdevice */ |
| 167 | ret = subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); | 167 | return subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); |
| 168 | if (ret) | ||
| 169 | return ret; | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | 168 | } |
| 173 | 169 | ||
| 174 | static struct comedi_driver cb_pcimdda_driver = { | 170 | static struct comedi_driver cb_pcimdda_driver = { |
| @@ -20,6 +20,12 @@ · 19 unmodified lines | |||
| 20 | #ifndef _COMEDI_8254_H | 20 | #ifndef _COMEDI_8254_H |
| 21 | #define _COMEDI_8254_H | 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 | * Common oscillator base values in nanoseconds | 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 | b_chans = bdev->nchans - base_chan; | 101 | b_chans = bdev->nchans - base_chan; |
| 102 | if (b_chans > n_left) | 102 | if (b_chans > n_left) |
| 103 | b_chans = n_left; | 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 | b_write_mask = (write_mask >> n_done) & b_mask; | 106 | b_write_mask = (write_mask >> n_done) & b_mask; |
| 106 | b_data_bits = (data_bits >> n_done) & b_mask; | 107 | b_data_bits = (data_bits >> n_done) & b_mask; |
| 107 | /* Read/Write the new digital lines. */ | 108 | /* Read/Write the new digital lines. */ |
| @@ -16,6 +16,10 @@ · 15 unmodified lines | |||
| 16 | #ifndef _COMEDI_ISADMA_H | 16 | #ifndef _COMEDI_ISADMA_H |
| 17 | #define _COMEDI_ISADMA_H | 17 | #define _COMEDI_ISADMA_H |
| 18 | 18 | ||
| 19 | #include <linux/types.h> | ||
| 20 | |||
| 21 | struct comedi_device; | ||
| 22 | |||
| 19 | /* | 23 | /* |
| 20 | * These are used to avoid issues when <asm/dma.h> and the DMA_MODE_ | 24 | * These are used to avoid issues when <asm/dma.h> and the DMA_MODE_ |
| 21 | * defines are not available. | 25 | * defines are not available. |
| @@ -1,105 +1,105 @@ | |||
| 1 | /* | 1 | /* |
| 2 | comedi/drivers/daqboard2000.c | 2 | * comedi/drivers/daqboard2000.c |
| 3 | hardware driver for IOtech DAQboard/2000 | 3 | * hardware driver for IOtech DAQboard/2000 |
| 4 | 4 | * | |
| 5 | COMEDI - Linux Control and Measurement Device Interface | 5 | * COMEDI - Linux Control and Measurement Device Interface |
| 6 | Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> | 6 | * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> |
| 7 | 7 | * | |
| 8 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | (at your option) any later version. | 11 | * (at your option) any later version. |
| 12 | 12 | * | |
| 13 | This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | /* | 18 | /* |
| 19 | Driver: daqboard2000 | 19 | * Driver: daqboard2000 |
| 20 | Description: IOTech DAQBoard/2000 | 20 | * Description: IOTech DAQBoard/2000 |
| 21 | Author: Anders Blomdell <anders.blomdell@control.lth.se> | 21 | * Author: Anders Blomdell <anders.blomdell@control.lth.se> |
| 22 | Status: works | 22 | * Status: works |
| 23 | Updated: Mon, 14 Apr 2008 15:28:52 +0100 | 23 | * Updated: Mon, 14 Apr 2008 15:28:52 +0100 |
| 24 | Devices: [IOTech] DAQBoard/2000 (daqboard2000) | 24 | * Devices: [IOTech] DAQBoard/2000 (daqboard2000) |
| 25 | 25 | * | |
| 26 | Much of the functionality of this driver was determined from reading | 26 | * Much of the functionality of this driver was determined from reading |
| 27 | the source code for the Windows driver. | 27 | * the source code for the Windows driver. |
| 28 | 28 | * | |
| 29 | The FPGA on the board requires fimware, which is available from | 29 | * The FPGA on the board requires fimware, which is available from |
| 30 | http://www.comedi.org in the comedi_nonfree_firmware tarball. | 30 | * http://www.comedi.org in the comedi_nonfree_firmware tarball. |
| 31 | 31 | * | |
| 32 | Configuration options: not applicable, uses PCI auto config | 32 | * Configuration options: not applicable, uses PCI auto config |
| 33 | */ | 33 | */ |
| 34 | /* | 34 | /* |
| 35 | This card was obviously never intended to leave the Windows world, | 35 | * This card was obviously never intended to leave the Windows world, |
| 36 | since it lacked all kind of hardware documentation (except for cable | 36 | * since it lacked all kind of hardware documentation (except for cable |
| 37 | pinouts, plug and pray has something to catch up with yet). | 37 | * pinouts, plug and pray has something to catch up with yet). |
| 38 | 38 | * | |
| 39 | With some help from our swedish distributor, we got the Windows sourcecode | 39 | * With some help from our swedish distributor, we got the Windows sourcecode |
| 40 | for the card, and here are the findings so far. | 40 | * for the card, and here are the findings so far. |
| 41 | 41 | * | |
| 42 | 1. A good document that describes the PCI interface chip is 9080db-106.pdf | 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 | 43 | * available from http://www.plxtech.com/products/io/pci9080 |
| 44 | 44 | * | |
| 45 | 2. The initialization done so far is: | 45 | * 2. The initialization done so far is: |
| 46 | a. program the FPGA (windows code sans a lot of error messages) | 46 | * a. program the FPGA (windows code sans a lot of error messages) |
| 47 | b. | 47 | * b. |
| 48 | 48 | * | |
| 49 | 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled, | 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 | 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 | 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. | 52 | * gives me no clues. I'll keep it simple so far. |
| 53 | 53 | * | |
| 54 | 4. Analog in. | 54 | * 4. Analog in. |
| 55 | Each channel in the scanlist seems to be controlled by four | 55 | * Each channel in the scanlist seems to be controlled by four |
| 56 | control words: | 56 | * control words: |
| 57 | 57 | * | |
| 58 | Word0: | 58 | * Word0: |
| 59 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 59 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 60 | ! | | | ! | | | ! | | | ! | | | ! | 60 | * ! | | | ! | | | ! | | | ! | | | ! |
| 61 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 61 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 62 | 62 | * | |
| 63 | Word1: | 63 | * Word1: |
| 64 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 64 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 65 | ! | | | ! | | | ! | | | ! | | | ! | 65 | * ! | | | ! | | | ! | | | ! | | | ! |
| 66 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 66 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 67 | | | | | | | | | 67 | * | | | | | | | |
| 68 | +------+------+ | | | | +-- Digital input (??) | 68 | * +------+------+ | | | | +-- Digital input (??) |
| 69 | | | | | +---- 10 us settling time | 69 | * | | | | +---- 10 us settling time |
| 70 | | | | +------ Suspend acquisition (last to scan) | 70 | * | | | +------ Suspend acquisition (last to scan) |
| 71 | | | +-------- Simultaneous sample and hold | 71 | * | | +-------- Simultaneous sample and hold |
| 72 | | +---------- Signed data format | 72 | * | +---------- Signed data format |
| 73 | +------------------------- Correction offset low | 73 | * +------------------------- Correction offset low |
| 74 | 74 | * | |
| 75 | Word2: | 75 | * Word2: |
| 76 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 76 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 77 | ! | | | ! | | | ! | | | ! | | | ! | 77 | * ! | | | ! | | | ! | | | ! | | | ! |
| 78 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 78 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 79 | | | | | | | | | | | | 79 | * | | | | | | | | | | |
| 80 | +-----+ +--+--+ +++ +++ +--+--+ | 80 | * +-----+ +--+--+ +++ +++ +--+--+ |
| 81 | | | | | +----- Expansion channel | 81 | * | | | | +----- Expansion channel |
| 82 | | | | +----------- Expansion gain | 82 | * | | | +----------- Expansion gain |
| 83 | | | +--------------- Channel (low) | 83 | * | | +--------------- Channel (low) |
| 84 | | +--------------------- Correction offset high | 84 | * | +--------------------- Correction offset high |
| 85 | +----------------------------- Correction gain low | 85 | * +----------------------------- Correction gain low |
| 86 | Word3: | 86 | * Word3: |
| 87 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 87 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 88 | ! | | | ! | | | ! | | | ! | | | ! | 88 | * ! | | | ! | | | ! | | | ! | | | ! |
| 89 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 89 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 90 | | | | | | | | | | | 90 | * | | | | | | | | | |
| 91 | +------+------+ | | +-+-+ | | +-- Low bank enable | 91 | * +------+------+ | | +-+-+ | | +-- Low bank enable |
| 92 | | | | | | +---- High bank enable | 92 | * | | | | | +---- High bank enable |
| 93 | | | | | +------ Hi/low select | 93 | * | | | | +------ Hi/low select |
| 94 | | | | +---------- Gain (1,?,2,4,8,16,32,64) | 94 | * | | | +---------- Gain (1,?,2,4,8,16,32,64) |
| 95 | | | +-------------- differential/single ended | 95 | * | | +-------------- differential/single ended |
| 96 | | +---------------- Unipolar | 96 | * | +---------------- Unipolar |
| 97 | +------------------------- Correction gain high | 97 | * +------------------------- Correction gain high |
| 98 | 98 | * | |
| 99 | 999. The card seems to have an incredible amount of capabilities, but | 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 | 100 | * trying to reverse engineer them from the Windows source is beyond my |
| 101 | patience. | 101 | * patience. |
| 102 | 102 | * | |
| 103 | */ | 103 | */ |
| 104 | 104 | ||
| 105 | #include <linux/module.h> | 105 | #include <linux/module.h> |
| @@ -1,21 +1,21 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * comedi/drivers/das08.c | 2 | * comedi/drivers/das08.c |
| 3 | * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) | 3 | * comedi module for common DAS08 support (used by ISA/PCI/PCMCIA drivers) |
| 4 | * | 4 | * |
| 5 | * COMEDI - Linux Control and Measurement Device Interface | 5 | * COMEDI - Linux Control and Measurement Device Interface |
| 6 | * Copyright (C) 2000 David A. Schleef <ds@schleef.org> | 6 | * Copyright (C) 2000 David A. Schleef <ds@schleef.org> |
| 7 | * Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net> | 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> | 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 | 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 | 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 | 12 | * the Free Software Foundation; either version 2 of the License, or |
| 13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
| 14 | * | 14 | * |
| 15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| @@ -27,85 +27,74 @@ · 5 unmodified lines | |||
| 27 | #include "das08.h" | 27 | #include "das08.h" |
| 28 | 28 | ||
| 29 | /* | 29 | /* |
| 30 | cio-das08.pdf | 30 | * Data format of DAS08_AI_LSB_REG and DAS08_AI_MSB_REG depends on |
| 31 | 31 | * 'ai_encoding' member of board structure: | |
| 32 | "isa-das08" | 32 | * |
| 33 | 33 | * das08_encode12 : DATA[11..4] = MSB[7..0], DATA[3..0] = LSB[7..4]. | |
| 34 | 0 a/d bits 0-3 start 8 bit | 34 | * das08_pcm_encode12 : DATA[11..8] = MSB[3..0], DATA[7..9] = LSB[7..0]. |
| 35 | 1 a/d bits 4-11 start 12 bit | 35 | * das08_encode16 : SIGN = MSB[7], MAGNITUDE[14..8] = MSB[6..0], |
| 36 | 2 eoc, ip1-3, irq, mux op1-4, inte, mux | 36 | * MAGNITUDE[7..0] = LSB[7..0]. |
| 37 | 3 unused unused | 37 | * SIGN==0 for negative input, SIGN==1 for positive input. |
| 38 | 4567 8254 | 38 | * Note: when read a second time after conversion |
| 39 | 89ab 8255 | 39 | * complete, MSB[7] is an "over-range" bit. |
| 40 | 40 | */ | |
| 41 | requires hard-wiring for async ai | 41 | #define DAS08_AI_LSB_REG 0x00 /* (R) AI least significant bits */ |
| 42 | 42 | #define DAS08_AI_MSB_REG 0x01 /* (R) AI most significant bits */ | |
| 43 | */ | 43 | #define DAS08_AI_TRIG_REG 0x01 /* (W) AI software trigger */ |
| 44 | 44 | #define DAS08_STATUS_REG 0x02 /* (R) status */ | |
| 45 | #define DAS08_LSB 0 | 45 | #define DAS08_STATUS_AI_BUSY BIT(7) /* AI conversion in progress */ |
| 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 | |||
| 59 | /* | 46 | /* |
| 60 | cio-das08jr.pdf | 47 | * The IRQ status bit is set to 1 by a rising edge on the external interrupt |
| 61 | 48 | * input (which may be jumpered to the pacer output). It is cleared by | |
| 62 | "das08/jr-ao" | 49 | * setting the INTE control bit to 0. Not present on "JR" boards. |
| 63 | 50 | */ | |
| 64 | 0 a/d bits 0-3 unused | 51 | #define DAS08_STATUS_IRQ BIT(3) /* latched interrupt input */ |
| 65 | 1 a/d bits 4-11 start 12 bit | 52 | /* digital inputs (not "JR" boards) */ |
| 66 | 2 eoc, mux mux | 53 | #define DAS08_STATUS_DI(x) (((x) & 0x70) >> 4) |
| 67 | 3 di do | 54 | #define DAS08_CONTROL_REG 0x02 /* (W) control */ |
| 68 | 4 unused ao0_lsb | 55 | /* |
| 69 | 5 unused ao0_msb | 56 | * Note: The AI multiplexor channel can also be read from status register using |
| 70 | 6 unused ao1_lsb | 57 | * the same mask. |
| 71 | 7 unused ao1_msb | 58 | */ |
| 72 | 59 | #define DAS08_CONTROL_MUX_MASK 0x7 /* multiplexor channel mask */ | |
| 73 | */ | 60 | #define DAS08_CONTROL_MUX(x) ((x) & DAS08_CONTROL_MUX_MASK) /* mux channel */ |
| 74 | 61 | #define DAS08_CONTROL_INTE BIT(3) /* interrupt enable (not "JR" boards) */ | |
| 75 | #define DAS08JR_DIO 3 | 62 | #define DAS08_CONTROL_DO_MASK 0xf0 /* digital outputs mask (not "JR") */ |
| 76 | #define DAS08JR_AO_LSB(x) ((x) ? 6 : 4) | 63 | /* digital outputs (not "JR" boards) */ |
| 77 | #define DAS08JR_AO_MSB(x) ((x) ? 7 : 5) | 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 | 90 | * (R) update analog outputs ("AOx" boards set for simultaneous output) |
| 81 | 91 | * (any of the analog output registers could be used for this) | |
| 82 | "das08-aoh" | 92 | */ |
| 83 | "das08-aol" | 93 | #define DAS08AOX_AO_UPDATE_REG 0x08 |
| 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 | ||
| 105 | 94 | ||
| 106 | /* gainlist same as _pgx_ below */ | 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 | 9, { | 98 | 9, { |
| 110 | BIP_RANGE(10), | 99 | BIP_RANGE(10), |
| 111 | BIP_RANGE(5), | 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 | 12, { | 112 | 12, { |
| 124 | BIP_RANGE(10), | 113 | BIP_RANGE(10), |
| 125 | BIP_RANGE(5), | 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 | 9, { | 129 | 9, { |
| 141 | BIP_RANGE(10), | 130 | BIP_RANGE(10), |
| 142 | BIP_RANGE(5), | 131 | BIP_RANGE(5), |
| @@ -148,42 +137,28 @@ static const struct comedi_lrange range_das08_pgm = { · 5 unmodified lines | |||
| 148 | UNI_RANGE(0.1), | 137 | UNI_RANGE(0.1), |
| 149 | UNI_RANGE(0.01) | 138 | UNI_RANGE(0.01) |
| 150 | } | 139 | } |
| 151 | }; /* | 140 | }; |
| 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 | */ | ||
| 166 | 141 | ||
| 167 | static const struct comedi_lrange *const das08_ai_lranges[] = { | 142 | static const struct comedi_lrange *const das08_ai_lranges[] = { |
| 168 | &range_unknown, | 143 | [das08_pg_none] = &range_unknown, |
| 169 | &range_bipolar5, | 144 | [das08_bipolar5] = &range_bipolar5, |
| 170 | &range_das08_pgh, | 145 | [das08_pgh] = &das08_pgh_ai_range, |
| 171 | &range_das08_pgl, | 146 | [das08_pgl] = &das08_pgl_ai_range, |
| 172 | &range_das08_pgm, | 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 | 8, 0, 10, 2, 12, 4, 14, 6, 1, 3, 5, 7 | 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 }; | 153 | static const int das08_pgl_ai_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 }; | 154 | static const int das08_pgm_ai_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 }; |
| 180 | 155 | ||
| 181 | static const int *const das08_gainlists[] = { | 156 | static const int *const das08_ai_gainlists[] = { |
| 182 | NULL, | 157 | [das08_pg_none] = NULL, |
| 183 | NULL, | 158 | [das08_bipolar5] = NULL, |
| 184 | das08_pgh_gainlist, | 159 | [das08_pgh] = das08_pgh_ai_gainlist, |
| 185 | das08_pgl_gainlist, | 160 | [das08_pgl] = das08_pgl_ai_gainlist, |
| 186 | das08_pgm_gainlist, | 161 | [das08_pgm] = das08_pgm_ai_gainlist, |
| 187 | }; | 162 | }; |
| 188 | 163 | ||
| 189 | static int das08_ai_eoc(struct comedi_device *dev, | 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 | unsigned int status; | 169 | unsigned int status; |
| 195 | 170 | ||
| 196 | status = inb(dev->iobase + DAS08_STATUS); | 171 | status = inb(dev->iobase + DAS08_STATUS_REG); |
| 197 | if ((status & DAS08_EOC) == 0) | 172 | if ((status & DAS08_STATUS_AI_BUSY) == 0) |
| 198 | return 0; | 173 | return 0; |
| 199 | return -EBUSY; | 174 | return -EBUSY; |
| 200 | } | 175 | } |
| 201 | 176 | ||
| 202 | static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, | 177 | static int das08_ai_insn_read(struct comedi_device *dev, |
| 203 | struct comedi_insn *insn, unsigned int *data) | 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 | struct das08_private_struct *devpriv = dev->private; | 182 | struct das08_private_struct *devpriv = dev->private; |
| 207 | int n; | 183 | int n; |
| 208 | int chan; | 184 | int chan; |
| @@ -214,49 +190,64 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 5 unmodified lines | |||
| 214 | range = CR_RANGE(insn->chanspec); | 190 | range = CR_RANGE(insn->chanspec); |
| 215 | 191 | ||
| 216 | /* clear crap */ | 192 | /* clear crap */ |
| 217 | inb(dev->iobase + DAS08_LSB); | 193 | inb(dev->iobase + DAS08_AI_LSB_REG); |
| 218 | inb(dev->iobase + DAS08_MSB); | 194 | inb(dev->iobase + DAS08_AI_MSB_REG); |
| 219 | 195 | ||
| 220 | /* set multiplexer */ | 196 | /* set multiplexer */ |
| 221 | /* lock to prevent race with digital output */ | 197 | /* lock to prevent race with digital output */ |
| 222 | spin_lock(&dev->spinlock); | 198 | spin_lock(&dev->spinlock); |
| 223 | devpriv->do_mux_bits &= ~DAS08_MUX_MASK; | 199 | devpriv->do_mux_bits &= ~DAS08_CONTROL_MUX_MASK; |
| 224 | devpriv->do_mux_bits |= DAS08_MUX(chan); | 200 | devpriv->do_mux_bits |= DAS08_CONTROL_MUX(chan); |
| 225 | outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); | 201 | outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL_REG); |
| 226 | spin_unlock(&dev->spinlock); | 202 | spin_unlock(&dev->spinlock); |
| 227 | 203 | ||
| 228 | if (s->range_table->length > 1) { | 204 | if (devpriv->pg_gainlist) { |
| 229 | /* set gain/range */ | 205 | /* set gain/range */ |
| 230 | range = CR_RANGE(insn->chanspec); | 206 | range = CR_RANGE(insn->chanspec); |
| 231 | outb(devpriv->pg_gainlist[range], | 207 | outb(devpriv->pg_gainlist[range], |
| 232 | dev->iobase + DAS08AO_GAIN_CONTROL); | 208 | dev->iobase + DAS08_GAIN_REG); |
| 233 | } | 209 | } |
| 234 | 210 | ||
| 235 | for (n = 0; n < insn->n; n++) { | 211 | for (n = 0; n < insn->n; n++) { |
| 236 | /* clear over-range bits for 16-bit boards */ | 212 | /* clear over-range bits for 16-bit boards */ |
| 237 | if (thisboard->ai_nbits == 16) | 213 | if (board->ai_nbits == 16) |
| 238 | if (inb(dev->iobase + DAS08_MSB) & 0x80) | 214 | if (inb(dev->iobase + DAS08_AI_MSB_REG) & 0x80) |
| 239 | dev_info(dev->class_dev, "over-range\n"); | 215 | dev_info(dev->class_dev, "over-range\n"); |
| 240 | 216 | ||
| 241 | /* trigger conversion */ | 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 | ret = comedi_timeout(dev, s, insn, das08_ai_eoc, 0); | 220 | ret = comedi_timeout(dev, s, insn, das08_ai_eoc, 0); |
| 245 | if (ret) | 221 | if (ret) |
| 246 | return ret; | 222 | return ret; |
| 247 | 223 | ||
| 248 | msb = inb(dev->iobase + DAS08_MSB); | 224 | msb = inb(dev->iobase + DAS08_AI_MSB_REG); |
| 249 | lsb = inb(dev->iobase + DAS08_LSB); | 225 | lsb = inb(dev->iobase + DAS08_AI_LSB_REG); |
| 250 | if (thisboard->ai_encoding == das08_encode12) { | 226 | if (board->ai_encoding == das08_encode12) { |
| 251 | data[n] = (lsb >> 4) | (msb << 4); | 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 | data[n] = (msb << 8) + lsb; | 229 | data[n] = (msb << 8) + lsb; |
| 254 | } else if (thisboard->ai_encoding == das08_encode16) { | 230 | } else if (board->ai_encoding == das08_encode16) { |
| 255 | /* FPOS 16-bit boards are sign-magnitude */ | 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 | if (msb & 0x80) | 247 | if (msb & 0x80) |
| 257 | data[n] = (1 << 15) | lsb | ((msb & 0x7f) << 8); | 248 | data[n] = (1 << 15) + magnitude; |
| 258 | else | 249 | else |
| 259 | data[n] = (1 << 15) - (lsb | (msb & 0x7f) << 8); | 250 | data[n] = (1 << 15) - magnitude; |
| 260 | } else { | 251 | } else { |
| 261 | dev_err(dev->class_dev, "bug! unknown ai encoding\n"); | 252 | dev_err(dev->class_dev, "bug! unknown ai encoding\n"); |
| 262 | return -1; | 253 | return -1; |
| @@ -266,28 +257,28 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, · 3 unmodified lines | |||
| 266 | return n; | 257 | return n; |
| 267 | } | 258 | } |
| 268 | 259 | ||
| 269 | static int das08_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, | 260 | static int das08_di_insn_bits(struct comedi_device *dev, |
| 270 | struct comedi_insn *insn, unsigned int *data) | 261 | struct comedi_subdevice *s, |
| 262 | struct comedi_insn *insn, unsigned int *data) | ||
| 271 | { | 263 | { |
| 272 | data[0] = 0; | 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 | return insn->n; | 267 | return insn->n; |
| 276 | } | 268 | } |
| 277 | 269 | ||
| 278 | static int das08_do_wbits(struct comedi_device *dev, | 270 | static int das08_do_insn_bits(struct comedi_device *dev, |
| 279 | struct comedi_subdevice *s, | 271 | struct comedi_subdevice *s, |
| 280 | struct comedi_insn *insn, | 272 | struct comedi_insn *insn, unsigned int *data) |
| 281 | unsigned int *data) | ||
| 282 | { | 273 | { |
| 283 | struct das08_private_struct *devpriv = dev->private; | 274 | struct das08_private_struct *devpriv = dev->private; |
| 284 | 275 | ||
| 285 | if (comedi_dio_update_state(s, data)) { | 276 | if (comedi_dio_update_state(s, data)) { |
| 286 | /* prevent race with setting of analog input mux */ | 277 | /* prevent race with setting of analog input mux */ |
| 287 | spin_lock(&dev->spinlock); | 278 | spin_lock(&dev->spinlock); |
| 288 | devpriv->do_mux_bits &= ~DAS08_DO_MASK; | 279 | devpriv->do_mux_bits &= ~DAS08_CONTROL_DO_MASK; |
| 289 | devpriv->do_mux_bits |= DAS08_OP(s->state); | 280 | devpriv->do_mux_bits |= DAS08_CONTROL_DO(s->state); |
| 290 | outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL); | 281 | outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL_REG); |
| 291 | spin_unlock(&dev->spinlock); | 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 | return insn->n; | 287 | return insn->n; |
| 297 | } | 288 | } |
| 298 | 289 | ||
| 299 | static int das08jr_di_rbits(struct comedi_device *dev, | 290 | static int das08jr_di_insn_bits(struct comedi_device *dev, |
| 300 | struct comedi_subdevice *s, | 291 | struct comedi_subdevice *s, |
| 301 | struct comedi_insn *insn, unsigned int *data) | 292 | struct comedi_insn *insn, unsigned int *data) |
| 302 | { | 293 | { |
| 303 | data[0] = 0; | 294 | data[0] = 0; |
| 304 | data[1] = inb(dev->iobase + DAS08JR_DIO); | 295 | data[1] = inb(dev->iobase + DAS08JR_DI_REG); |
| 305 | 296 | ||
| 306 | return insn->n; | 297 | return insn->n; |
| 307 | } | 298 | } |
| 308 | 299 | ||
| 309 | static int das08jr_do_wbits(struct comedi_device *dev, | 300 | static int das08jr_do_insn_bits(struct comedi_device *dev, |
| 310 | struct comedi_subdevice *s, | 301 | struct comedi_subdevice *s, |
| 311 | struct comedi_insn *insn, | 302 | struct comedi_insn *insn, unsigned int *data) |
| 312 | unsigned int *data) | ||
| 313 | { | 303 | { |
| 314 | if (comedi_dio_update_state(s, data)) | 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 | data[1] = s->state; | 307 | data[1] = s->state; |
| 318 | 308 | ||
| @@ -322,22 +312,22 @@ static int das08jr_do_wbits(struct comedi_device *dev, · 3 unmodified lines | |||
| 322 | static void das08_ao_set_data(struct comedi_device *dev, | 312 | static void das08_ao_set_data(struct comedi_device *dev, |
| 323 | unsigned int chan, unsigned int data) | 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 | unsigned char lsb; | 316 | unsigned char lsb; |
| 327 | unsigned char msb; | 317 | unsigned char msb; |
| 328 | 318 | ||
| 329 | lsb = data & 0xff; | 319 | lsb = data & 0xff; |
| 330 | msb = (data >> 8) & 0xff; | 320 | msb = (data >> 8) & 0xff; |
| 331 | if (thisboard->is_jr) { | 321 | if (board->is_jr) { |
| 332 | outb(lsb, dev->iobase + DAS08JR_AO_LSB(chan)); | 322 | outb(lsb, dev->iobase + DAS08JR_AO_LSB_REG(chan)); |
| 333 | outb(msb, dev->iobase + DAS08JR_AO_MSB(chan)); | 323 | outb(msb, dev->iobase + DAS08JR_AO_MSB_REG(chan)); |
| 334 | /* load DACs */ | 324 | /* load DACs */ |
| 335 | inb(dev->iobase + DAS08JR_DIO); | 325 | inb(dev->iobase + DAS08JR_AO_UPDATE_REG); |
| 336 | } else { | 326 | } else { |
| 337 | outb(lsb, dev->iobase + DAS08AO_AO_LSB(chan)); | 327 | outb(lsb, dev->iobase + DAS08AOX_AO_LSB_REG(chan)); |
| 338 | outb(msb, dev->iobase + DAS08AO_AO_MSB(chan)); | 328 | outb(msb, dev->iobase + DAS08AOX_AO_MSB_REG(chan)); |
| 339 | /* load DACs */ | 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 | int das08_common_attach(struct comedi_device *dev, unsigned long iobase) | 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 | struct das08_private_struct *devpriv = dev->private; | 355 | struct das08_private_struct *devpriv = dev->private; |
| 366 | struct comedi_subdevice *s; | 356 | struct comedi_subdevice *s; |
| 367 | int ret; | 357 | int ret; |
| @@ -369,7 +359,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) · 1 unmodified line | |||
| 369 | 359 | ||
| 370 | dev->iobase = iobase; | 360 | dev->iobase = iobase; |
| 371 | 361 | ||
| 372 | dev->board_name = thisboard->name; | 362 | dev->board_name = board->name; |
| 373 | 363 | ||
| 374 | ret = comedi_alloc_subdevices(dev, 6); | 364 | ret = comedi_alloc_subdevices(dev, 6); |
| 375 | if (ret) | 365 | if (ret) |
| @@ -377,30 +367,31 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) · 1 unmodified line | |||
| 377 | 367 | ||
| 378 | s = &dev->subdevices[0]; | 368 | s = &dev->subdevices[0]; |
| 379 | /* ai */ | 369 | /* ai */ |
| 380 | if (thisboard->ai_nbits) { | 370 | if (board->ai_nbits) { |
| 381 | s->type = COMEDI_SUBD_AI; | 371 | s->type = COMEDI_SUBD_AI; |
| 382 | /* XXX some boards actually have differential | 372 | /* |
| 373 | * XXX some boards actually have differential | ||
| 383 | * inputs instead of single ended. | 374 | * inputs instead of single ended. |
| 384 | * The driver does nothing with arefs though, | 375 | * The driver does nothing with arefs though, |
| 385 | * so it's no big deal. | 376 | * so it's no big deal. |
| 386 | */ | 377 | */ |
| 387 | s->subdev_flags = SDF_READABLE | SDF_GROUND; | 378 | s->subdev_flags = SDF_READABLE | SDF_GROUND; |
| 388 | s->n_chan = 8; | 379 | s->n_chan = 8; |
| 389 | s->maxdata = (1 << thisboard->ai_nbits) - 1; | 380 | s->maxdata = (1 << board->ai_nbits) - 1; |
| 390 | s->range_table = das08_ai_lranges[thisboard->ai_pg]; | 381 | s->range_table = das08_ai_lranges[board->ai_pg]; |
| 391 | s->insn_read = das08_ai_rinsn; | 382 | s->insn_read = das08_ai_insn_read; |
| 392 | devpriv->pg_gainlist = das08_gainlists[thisboard->ai_pg]; | 383 | devpriv->pg_gainlist = das08_ai_gainlists[board->ai_pg]; |
| 393 | } else { | 384 | } else { |
| 394 | s->type = COMEDI_SUBD_UNUSED; | 385 | s->type = COMEDI_SUBD_UNUSED; |
| 395 | } | 386 | } |
| 396 | 387 | ||
| 397 | s = &dev->subdevices[1]; | 388 | s = &dev->subdevices[1]; |
| 398 | /* ao */ | 389 | /* ao */ |
| 399 | if (thisboard->ao_nbits) { | 390 | if (board->ao_nbits) { |
| 400 | s->type = COMEDI_SUBD_AO; | 391 | s->type = COMEDI_SUBD_AO; |
| 401 | s->subdev_flags = SDF_WRITABLE; | 392 | s->subdev_flags = SDF_WRITABLE; |
| 402 | s->n_chan = 2; | 393 | s->n_chan = 2; |
| 403 | s->maxdata = (1 << thisboard->ao_nbits) - 1; | 394 | s->maxdata = (1 << board->ao_nbits) - 1; |
| 404 | s->range_table = &range_bipolar5; | 395 | s->range_table = &range_bipolar5; |
| 405 | s->insn_write = das08_ao_insn_write; | 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 | s = &dev->subdevices[2]; | 411 | s = &dev->subdevices[2]; |
| 421 | /* di */ | 412 | /* di */ |
| 422 | if (thisboard->di_nchan) { | 413 | if (board->di_nchan) { |
| 423 | s->type = COMEDI_SUBD_DI; | 414 | s->type = COMEDI_SUBD_DI; |
| 424 | s->subdev_flags = SDF_READABLE; | 415 | s->subdev_flags = SDF_READABLE; |
| 425 | s->n_chan = thisboard->di_nchan; | 416 | s->n_chan = board->di_nchan; |
| 426 | s->maxdata = 1; | 417 | s->maxdata = 1; |
| 427 | s->range_table = &range_digital; | 418 | s->range_table = &range_digital; |
| 428 | s->insn_bits = | 419 | s->insn_bits = board->is_jr ? das08jr_di_insn_bits : |
| 429 | thisboard->is_jr ? das08jr_di_rbits : das08_di_rbits; | 420 | das08_di_insn_bits; |
| 430 | } else { | 421 | } else { |
| 431 | s->type = COMEDI_SUBD_UNUSED; | 422 | s->type = COMEDI_SUBD_UNUSED; |
| 432 | } | 423 | } |
| 433 | 424 | ||
| 434 | s = &dev->subdevices[3]; | 425 | s = &dev->subdevices[3]; |
| 435 | /* do */ | 426 | /* do */ |
| 436 | if (thisboard->do_nchan) { | 427 | if (board->do_nchan) { |
| 437 | s->type = COMEDI_SUBD_DO; | 428 | s->type = COMEDI_SUBD_DO; |
| 438 | s->subdev_flags = SDF_WRITABLE; | 429 | s->subdev_flags = SDF_WRITABLE; |
| 439 | s->n_chan = thisboard->do_nchan; | 430 | s->n_chan = board->do_nchan; |
| 440 | s->maxdata = 1; | 431 | s->maxdata = 1; |
| 441 | s->range_table = &range_digital; | 432 | s->range_table = &range_digital; |
| 442 | s->insn_bits = | 433 | s->insn_bits = board->is_jr ? das08jr_do_insn_bits : |
| 443 | thisboard->is_jr ? das08jr_do_wbits : das08_do_wbits; | 434 | das08_do_insn_bits; |
| 444 | } else { | 435 | } else { |
| 445 | s->type = COMEDI_SUBD_UNUSED; | 436 | s->type = COMEDI_SUBD_UNUSED; |
| 446 | } | 437 | } |
| 447 | 438 | ||
| 448 | s = &dev->subdevices[4]; | 439 | s = &dev->subdevices[4]; |
| 449 | /* 8255 */ | 440 | /* 8255 */ |
| 450 | if (thisboard->i8255_offset != 0) { | 441 | if (board->i8255_offset != 0) { |
| 451 | ret = subdev_8255_init(dev, s, NULL, thisboard->i8255_offset); | 442 | ret = subdev_8255_init(dev, s, NULL, board->i8255_offset); |
| 452 | if (ret) | 443 | if (ret) |
| 453 | return ret; | 444 | return ret; |
| 454 | } else { | 445 | } else { |
| @@ -457,9 +448,8 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase) · 2 unmodified lines | |||
| 457 | 448 | ||
| 458 | /* Counter subdevice (8254) */ | 449 | /* Counter subdevice (8254) */ |
| 459 | s = &dev->subdevices[5]; | 450 | s = &dev->subdevices[5]; |
| 460 | if (thisboard->i8254_offset) { | 451 | if (board->i8254_offset) { |
| 461 | dev->pacer = comedi_8254_init(dev->iobase + | 452 | dev->pacer = comedi_8254_init(dev->iobase + board->i8254_offset, |
| 462 | thisboard->i8254_offset, | ||
| 463 | 0, I8254_IO8, 0); | 453 | 0, I8254_IO8, 0); |
| 464 | if (!dev->pacer) | 454 | if (!dev->pacer) |
| 465 | return -ENOMEM; | 455 | return -ENOMEM; |
| @@ -485,5 +475,5 @@ static void __exit das08_exit(void) · 19 unmodified lines | |||
| 485 | module_exit(das08_exit); | 475 | module_exit(das08_exit); |
| 486 | 476 | ||
| 487 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | 477 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 488 | MODULE_DESCRIPTION("Comedi low-level driver"); | 478 | MODULE_DESCRIPTION("Comedi common DAS08 support module"); |
| 489 | MODULE_LICENSE("GPL"); | 479 | MODULE_LICENSE("GPL"); |
| @@ -1,28 +1,33 @@ | |||
| 1 | /* | 1 | /* |
| 2 | das08.h | 2 | * das08.h |
| 3 | 3 | * | |
| 4 | Header for das08.c and das08_cs.c | 4 | * Header for common DAS08 support (used by ISA/PCI/PCMCIA drivers) |
| 5 | 5 | * | |
| 6 | Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> | 6 | * Copyright (C) 2003 Frank Mori Hess <fmhess@users.sourceforge.net> |
| 7 | 7 | * | |
| 8 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | (at your option) any later version. | 11 | * (at your option) any later version. |
| 12 | 12 | * | |
| 13 | This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #ifndef _DAS08_H | 19 | #ifndef _DAS08_H |
| 20 | #define _DAS08_H | 20 | #define _DAS08_H |
| 21 | 21 | ||
| 22 | #include <linux/types.h> | ||
| 23 | |||
| 24 | struct comedi_device; | ||
| 25 | |||
| 22 | /* different ways ai data is encoded in first two registers */ | 26 | /* different ways ai data is encoded in first two registers */ |
| 23 | enum das08_ai_encoding { das08_encode12, das08_encode16, das08_pcm_encode12 }; | 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, | 28 | /* types of ai range table used by different boards */ |
| 25 | das08_pgm | 29 | enum das08_lrange { |
| 30 | das08_pg_none, das08_bipolar5, das08_pgh, das08_pgl, das08_pgm | ||
| 26 | }; | 31 | }; |
| 27 | 32 | ||
| 28 | struct das08_board_struct { | 33 | struct das08_board_struct { |
| @@ -36,13 +41,12 @@ struct das08_board_struct { · 7 unmodified lines | |||
| 36 | unsigned int do_nchan; | 41 | unsigned int do_nchan; |
| 37 | unsigned int i8255_offset; | 42 | unsigned int i8255_offset; |
| 38 | unsigned int i8254_offset; | 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 | struct das08_private_struct { | 47 | struct das08_private_struct { |
| 43 | unsigned int do_mux_bits; /* bits for do/mux register on boards | 48 | /* bits for do/mux register on boards without separate do register */ |
| 44 | * without separate do register | 49 | unsigned int do_mux_bits; |
| 45 | */ | ||
| 46 | const unsigned int *pg_gainlist; | 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 | static int das08_isa_attach(struct comedi_device *dev, | 168 | static int das08_isa_attach(struct comedi_device *dev, |
| 169 | struct comedi_devconfig *it) | 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 | struct das08_private_struct *devpriv; | 172 | struct das08_private_struct *devpriv; |
| 173 | int ret; | 173 | int ret; |
| 174 | 174 | ||
| @@ -176,7 +176,7 @@ static int das08_isa_attach(struct comedi_device *dev, · 1 unmodified line | |||
| 176 | if (!devpriv) | 176 | if (!devpriv) |
| 177 | return -ENOMEM; | 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 | if (ret) | 180 | if (ret) |
| 181 | return ret; | 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 | (2) - the list must have an even number of entries. | 46 | (2) - the list must have an even number of entries. |
| 47 | 47 | ||
| 48 | Options: | 48 | Options: |
| 49 | [0] - base io address | 49 | [0] - base io address |
| 50 | [1] - irq (optional, but you probably want it) | 50 | [1] - irq (optional, but you probably want it) |
| 51 | 51 | ||
| 52 | irq can be omitted, although the cmd interface will not work without it. | 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 | static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, | 444 | static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev, |
| 445 | uint16_t sample) | 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 | return sample; | 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 | struct comedi_subdevice *s, | 725 | struct comedi_subdevice *s, |
| 726 | struct comedi_cmd *cmd) | 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 | int err = 0; | 729 | int err = 0; |
| 730 | unsigned int arg; | 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 | if (cmd->convert_src == TRIG_TIMER) { | 766 | if (cmd->convert_src == TRIG_TIMER) { |
| 767 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, | 767 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 768 | thisboard->ai_speed); | 768 | board->ai_speed); |
| 769 | } | 769 | } |
| 770 | 770 | ||
| 771 | err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); | 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 | struct comedi_subdevice *s, | 1048 | struct comedi_subdevice *s, |
| 1049 | struct comedi_insn *insn, unsigned int *data) | 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 | int i, n; | 1052 | int i, n; |
| 1053 | int chan, range, aref, chan_range; | 1053 | int chan, range, aref, chan_range; |
| 1054 | int timeout = 1000; | 1054 | int timeout = 1000; |
| @@ -1098,7 +1098,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, · 43 unmodified lines | |||
| 1098 | dpnt = inw(dev->iobase + DAS1800_FIFO); | 1098 | dpnt = inw(dev->iobase + DAS1800_FIFO); |
| 1099 | /* shift data to offset binary for bipolar ranges */ | 1099 | /* shift data to offset binary for bipolar ranges */ |
| 1100 | if ((conv_flags & UB) == 0) | 1100 | if ((conv_flags & UB) == 0) |
| 1101 | dpnt += 1 << (thisboard->resolution - 1); | 1101 | dpnt += 1 << (board->resolution - 1); |
| 1102 | data[n] = dpnt; | 1102 | data[n] = dpnt; |
| 1103 | } | 1103 | } |
| 1104 | exit: | 1104 | exit: |
| @@ -1112,16 +1112,16 @@ static int das1800_ao_winsn(struct comedi_device *dev, · 7 unmodified lines | |||
| 1112 | struct comedi_subdevice *s, | 1112 | struct comedi_subdevice *s, |
| 1113 | struct comedi_insn *insn, unsigned int *data) | 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 | struct das1800_private *devpriv = dev->private; | 1116 | struct das1800_private *devpriv = dev->private; |
| 1117 | int chan = CR_CHAN(insn->chanspec); | 1117 | int chan = CR_CHAN(insn->chanspec); |
| 1118 | /* int range = CR_RANGE(insn->chanspec); */ | 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 | unsigned short output; | 1120 | unsigned short output; |
| 1121 | unsigned long irq_flags; | 1121 | unsigned long irq_flags; |
| 1122 | 1122 | ||
| 1123 | /* card expects two's complement data */ | 1123 | /* card expects two's complement data */ |
| 1124 | output = data[0] - (1 << (thisboard->resolution - 1)); | 1124 | output = data[0] - (1 << (board->resolution - 1)); |
| 1125 | /* if the write is to the 'update' channel, we need to remember its value */ | 1125 | /* if the write is to the 'update' channel, we need to remember its value */ |
| 1126 | if (chan == update_chan) | 1126 | if (chan == update_chan) |
| 1127 | devpriv->ao_update_bits = output; | 1127 | devpriv->ao_update_bits = output; |
| @@ -1216,72 +1216,76 @@ static void das1800_free_dma(struct comedi_device *dev) · 88 unmodified lines | |||
| 1216 | comedi_isadma_free(devpriv->dma); | 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 | const struct das1800_board *board = dev->board_ptr; | 1221 | const struct das1800_board *board = dev->board_ptr; |
| 1222 | int index; | 1222 | int index = board ? board - das1800_boards : -EINVAL; |
| 1223 | int id; | 1223 | int id; |
| 1224 | 1224 | ||
| 1225 | /* calc the offset to the boardinfo that was found by the core */ | 1225 | /* |
| 1226 | index = board - das1800_boards; | 1226 | * The dev->board_ptr will be set by comedi_device_attach() if the |
| 1227 | 1227 | * board name provided by the user matches a board->name in this | |
| 1228 | /* verify that the board id matches the boardinfo */ | 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 | id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; | 1235 | id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; |
| 1230 | switch (id) { | 1236 | switch (id) { |
| 1231 | case 0x3: | 1237 | case 0x3: |
| 1232 | if (index == das1801st_da || index == das1802st_da || | 1238 | if (index == das1801st_da || index == das1802st_da || |
| 1233 | index == das1701st_da || index == das1702st_da) | 1239 | index == das1701st_da || index == das1702st_da) |
| 1234 | return index; | 1240 | return board; |
| 1235 | index = das1801st; | 1241 | index = das1801st; |
| 1236 | break; | 1242 | break; |
| 1237 | case 0x4: | 1243 | case 0x4: |
| 1238 | if (index == das1802hr_da || index == das1702hr_da) | 1244 | if (index == das1802hr_da || index == das1702hr_da) |
| 1239 | return index; | 1245 | return board; |
| 1240 | index = das1802hr; | 1246 | index = das1802hr; |
| 1241 | break; | 1247 | break; |
| 1242 | case 0x5: | 1248 | case 0x5: |
| 1243 | if (index == das1801ao || index == das1802ao || | 1249 | if (index == das1801ao || index == das1802ao || |
| 1244 | index == das1701ao || index == das1702ao) | 1250 | index == das1701ao || index == das1702ao) |
| 1245 | return index; | 1251 | return board; |
| 1246 | index = das1801ao; | 1252 | index = das1801ao; |
| 1247 | break; | 1253 | break; |
| 1248 | case 0x6: | 1254 | case 0x6: |
| 1249 | if (index == das1802hr || index == das1702hr) | 1255 | if (index == das1802hr || index == das1702hr) |
| 1250 | return index; | 1256 | return board; |
| 1251 | index = das1802hr; | 1257 | index = das1802hr; |
| 1252 | break; | 1258 | break; |
| 1253 | case 0x7: | 1259 | case 0x7: |
| 1254 | if (index == das1801st || index == das1802st || | 1260 | if (index == das1801st || index == das1802st || |
| 1255 | index == das1701st || index == das1702st) | 1261 | index == das1701st || index == das1702st) |
| 1256 | return index; | 1262 | return board; |
| 1257 | index = das1801st; | 1263 | index = das1801st; |
| 1258 | break; | 1264 | break; |
| 1259 | case 0x8: | 1265 | case 0x8: |
| 1260 | if (index == das1801hc || index == das1802hc) | 1266 | if (index == das1801hc || index == das1802hc) |
| 1261 | return index; | 1267 | return board; |
| 1262 | index = das1801hc; | 1268 | index = das1801hc; |
| 1263 | break; | ||
| 1264 | default: | 1269 | default: |
| 1265 | dev_err(dev->class_dev, | 1270 | dev_err(dev->class_dev, |
| 1266 | "Board model: probe returned 0x%x (unknown, please report)\n", | 1271 | "Board model: probe returned 0x%x (unknown, please report)\n", |
| 1267 | id); | 1272 | id); |
| 1268 | break; | 1273 | return NULL; |
| 1269 | } | 1274 | } |
| 1270 | dev_err(dev->class_dev, | 1275 | dev_err(dev->class_dev, |
| 1271 | "Board model (probed, not recommended): %s series\n", | 1276 | "Board model (probed, not recommended): %s series\n", |
| 1272 | das1800_boards[index].name); | 1277 | das1800_boards[index].name); |
| 1273 | 1278 | ||
| 1274 | return index; | 1279 | return &das1800_boards[index]; |
| 1275 | } | 1280 | } |
| 1276 | 1281 | ||
| 1277 | static int das1800_attach(struct comedi_device *dev, | 1282 | static int das1800_attach(struct comedi_device *dev, |
| 1278 | struct comedi_devconfig *it) | 1283 | struct comedi_devconfig *it) |
| 1279 | { | 1284 | { |
| 1280 | const struct das1800_board *thisboard; | 1285 | const struct das1800_board *board; |
| 1281 | struct das1800_private *devpriv; | 1286 | struct das1800_private *devpriv; |
| 1282 | struct comedi_subdevice *s; | 1287 | struct comedi_subdevice *s; |
| 1283 | unsigned int irq = it->options[1]; | 1288 | unsigned int irq = it->options[1]; |
| 1284 | int board; | ||
| 1285 | int ret; | 1289 | int ret; |
| 1286 | 1290 | ||
| 1287 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 1291 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| @@ -1293,17 +1297,15 @@ static int das1800_attach(struct comedi_device *dev, · 5 unmodified lines | |||
| 1293 | return ret; | 1297 | return ret; |
| 1294 | 1298 | ||
| 1295 | board = das1800_probe(dev); | 1299 | board = das1800_probe(dev); |
| 1296 | if (board < 0) { | 1300 | if (!board) { |
| 1297 | dev_err(dev->class_dev, "unable to determine board type\n"); | 1301 | dev_err(dev->class_dev, "unable to determine board type\n"); |
| 1298 | return -ENODEV; | 1302 | return -ENODEV; |
| 1299 | } | 1303 | } |
| 1300 | 1304 | dev->board_ptr = board; | |
| 1301 | dev->board_ptr = das1800_boards + board; | 1305 | dev->board_name = board->name; |
| 1302 | thisboard = dev->board_ptr; | ||
| 1303 | dev->board_name = thisboard->name; | ||
| 1304 | 1306 | ||
| 1305 | /* if it is an 'ao' board with fancy analog out then we need extra io ports */ | 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 | unsigned long iobase2 = dev->iobase + IOBASE2; | 1309 | unsigned long iobase2 = dev->iobase + IOBASE2; |
| 1308 | 1310 | ||
| 1309 | ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE); | 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 | s = &dev->subdevices[0]; | 1365 | s = &dev->subdevices[0]; |
| 1364 | s->type = COMEDI_SUBD_AI; | 1366 | s->type = COMEDI_SUBD_AI; |
| 1365 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; | 1367 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; |
| 1366 | if (thisboard->common) | 1368 | if (board->common) |
| 1367 | s->subdev_flags |= SDF_COMMON; | 1369 | s->subdev_flags |= SDF_COMMON; |
| 1368 | s->n_chan = thisboard->qram_len; | 1370 | s->n_chan = board->qram_len; |
| 1369 | s->maxdata = (1 << thisboard->resolution) - 1; | 1371 | s->maxdata = (1 << board->resolution) - 1; |
| 1370 | s->range_table = thisboard->range_ai; | 1372 | s->range_table = board->range_ai; |
| 1371 | s->insn_read = das1800_ai_rinsn; | 1373 | s->insn_read = das1800_ai_rinsn; |
| 1372 | if (dev->irq) { | 1374 | if (dev->irq) { |
| 1373 | dev->read_subdev = s; | 1375 | dev->read_subdev = s; |
| @@ -1381,11 +1383,11 @@ static int das1800_attach(struct comedi_device *dev, · 7 unmodified lines | |||
| 1381 | 1383 | ||
| 1382 | /* analog out */ | 1384 | /* analog out */ |
| 1383 | s = &dev->subdevices[1]; | 1385 | s = &dev->subdevices[1]; |
| 1384 | if (thisboard->ao_ability == 1) { | 1386 | if (board->ao_ability == 1) { |
| 1385 | s->type = COMEDI_SUBD_AO; | 1387 | s->type = COMEDI_SUBD_AO; |
| 1386 | s->subdev_flags = SDF_WRITABLE; | 1388 | s->subdev_flags = SDF_WRITABLE; |
| 1387 | s->n_chan = thisboard->ao_n_chan; | 1389 | s->n_chan = board->ao_n_chan; |
| 1388 | s->maxdata = (1 << thisboard->resolution) - 1; | 1390 | s->maxdata = (1 << board->resolution) - 1; |
| 1389 | s->range_table = &range_bipolar10; | 1391 | s->range_table = &range_bipolar10; |
| 1390 | s->insn_write = das1800_ao_winsn; | 1392 | s->insn_write = das1800_ao_winsn; |
| 1391 | } else { | 1393 | } else { |
| @@ -1405,7 +1407,7 @@ static int das1800_attach(struct comedi_device *dev, · 13 unmodified lines | |||
| 1405 | s = &dev->subdevices[3]; | 1407 | s = &dev->subdevices[3]; |
| 1406 | s->type = COMEDI_SUBD_DO; | 1408 | s->type = COMEDI_SUBD_DO; |
| 1407 | s->subdev_flags = SDF_WRITABLE; | 1409 | s->subdev_flags = SDF_WRITABLE; |
| 1408 | s->n_chan = thisboard->do_n_chan; | 1410 | s->n_chan = board->do_n_chan; |
| 1409 | s->maxdata = 1; | 1411 | s->maxdata = 1; |
| 1410 | s->range_table = &range_digital; | 1412 | s->range_table = &range_digital; |
| 1411 | s->insn_bits = das1800_do_wbits; | 1413 | s->insn_bits = das1800_do_wbits; |
| @@ -1416,9 +1418,9 @@ static int das1800_attach(struct comedi_device *dev, · 4 unmodified lines | |||
| 1416 | outb(0, dev->iobase + DAS1800_DIGITAL); | 1418 | outb(0, dev->iobase + DAS1800_DIGITAL); |
| 1417 | 1419 | ||
| 1418 | /* initialize analog out channels */ | 1420 | /* initialize analog out channels */ |
| 1419 | if (thisboard->ao_ability == 1) { | 1421 | if (board->ao_ability == 1) { |
| 1420 | /* select 'update' dac channel for baseAddress + 0x0 */ | 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 | dev->iobase + DAS1800_SELECT); | 1424 | dev->iobase + DAS1800_SELECT); |
| 1423 | outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); | 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 | static void das800_enable(struct comedi_device *dev) | 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 | struct das800_private *devpriv = dev->private; | 244 | struct das800_private *devpriv = dev->private; |
| 245 | unsigned long irq_flags; | 245 | unsigned long irq_flags; |
| 246 | 246 | ||
| 247 | spin_lock_irqsave(&dev->spinlock, irq_flags); | 247 | spin_lock_irqsave(&dev->spinlock, irq_flags); |
| 248 | /* enable fifo-half full interrupts for cio-das802/16 */ | 248 | /* enable fifo-half full interrupts for cio-das802/16 */ |
| 249 | if (thisboard->resolution == 16) | 249 | if (board->resolution == 16) |
| 250 | outb(CIO_ENHF, dev->iobase + DAS800_GAIN); | 250 | outb(CIO_ENHF, dev->iobase + DAS800_GAIN); |
| 251 | /* enable hardware triggering */ | 251 | /* enable hardware triggering */ |
| 252 | das800_ind_write(dev, CONV_HCEN, CONV_CONTROL); | 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 | struct comedi_subdevice *s, | 303 | struct comedi_subdevice *s, |
| 304 | struct comedi_cmd *cmd) | 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 | int err = 0; | 307 | int err = 0; |
| 308 | 308 | ||
| 309 | /* Step 1 : check if triggers are trivially valid */ | 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 | if (cmd->convert_src == TRIG_TIMER) { | 336 | if (cmd->convert_src == TRIG_TIMER) { |
| 337 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, | 337 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 338 | thisboard->ai_speed); | 338 | board->ai_speed); |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); | 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 | static int das800_ai_do_cmd(struct comedi_device *dev, | 375 | static int das800_ai_do_cmd(struct comedi_device *dev, |
| 376 | struct comedi_subdevice *s) | 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 | struct comedi_async *async = s->async; | 379 | struct comedi_async *async = s->async; |
| 380 | struct comedi_cmd *cmd = &async->cmd; | 380 | struct comedi_cmd *cmd = &async->cmd; |
| 381 | unsigned int gain = CR_RANGE(cmd->chanlist[0]); | 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 | spin_unlock_irqrestore(&dev->spinlock, irq_flags); | 393 | spin_unlock_irqrestore(&dev->spinlock, irq_flags); |
| 394 | 394 | ||
| 395 | /* set gain */ | 395 | /* set gain */ |
| 396 | if (thisboard->resolution == 12 && gain > 0) | 396 | if (board->resolution == 12 && gain > 0) |
| 397 | gain += 0x7; | 397 | gain += 0x7; |
| 398 | gain &= 0xf; | 398 | gain &= 0xf; |
| 399 | outb(gain, dev->iobase + DAS800_GAIN); | 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 | return insn->n; | 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; | 609 | const struct das800_board *board = dev->board_ptr; |
| 610 | int board = thisboard ? thisboard - das800_boards : -EINVAL; | 610 | int index = board ? board - das800_boards : -EINVAL; |
| 611 | int id_bits; | 611 | int id_bits; |
| 612 | unsigned long irq_flags; | 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 | spin_lock_irqsave(&dev->spinlock, irq_flags); | 624 | spin_lock_irqsave(&dev->spinlock, irq_flags); |
| 615 | id_bits = das800_ind_read(dev, ID) & 0x3; | 625 | id_bits = das800_ind_read(dev, ID) & 0x3; |
| 616 | spin_unlock_irqrestore(&dev->spinlock, irq_flags); | 626 | spin_unlock_irqrestore(&dev->spinlock, irq_flags); |
| 617 | 627 | ||
| 618 | switch (id_bits) { | 628 | switch (id_bits) { |
| 619 | case 0x0: | 629 | case 0x0: |
| 620 | if (board == BOARD_DAS800 || board == BOARD_CIODAS800) | 630 | if (index == BOARD_DAS800 || index == BOARD_CIODAS800) |
| 621 | break; | 631 | return board; |
| 622 | dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n"); | 632 | index = BOARD_DAS800; |
| 623 | board = BOARD_DAS800; | ||
| 624 | break; | 633 | break; |
| 625 | case 0x2: | 634 | case 0x2: |
| 626 | if (board == BOARD_DAS801 || board == BOARD_CIODAS801) | 635 | if (index == BOARD_DAS801 || index == BOARD_CIODAS801) |
| 627 | break; | 636 | return board; |
| 628 | dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n"); | 637 | index = BOARD_DAS801; |
| 629 | board = BOARD_DAS801; | ||
| 630 | break; | 638 | break; |
| 631 | case 0x3: | 639 | case 0x3: |
| 632 | if (board == BOARD_DAS802 || board == BOARD_CIODAS802 || | 640 | if (index == BOARD_DAS802 || index == BOARD_CIODAS802 || |
| 633 | board == BOARD_CIODAS80216) | 641 | index == BOARD_CIODAS80216) |
| 634 | break; | 642 | return board; |
| 635 | dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n"); | 643 | index = BOARD_DAS802; |
| 636 | board = BOARD_DAS802; | ||
| 637 | break; | 644 | break; |
| 638 | default: | 645 | default: |
| 639 | dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n", | 646 | dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n", |
| 640 | id_bits); | 647 | id_bits); |
| 641 | board = -EINVAL; | 648 | return NULL; |
| 642 | break; | ||
| 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 | static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) | 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 | struct das800_private *devpriv; | 659 | struct das800_private *devpriv; |
| 651 | struct comedi_subdevice *s; | 660 | struct comedi_subdevice *s; |
| 652 | unsigned int irq = it->options[1]; | 661 | unsigned int irq = it->options[1]; |
| 653 | unsigned long irq_flags; | 662 | unsigned long irq_flags; |
| 654 | int board; | ||
| 655 | int ret; | 663 | int ret; |
| 656 | 664 | ||
| 657 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 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 | return ret; | 671 | return ret; |
| 664 | 672 | ||
| 665 | board = das800_probe(dev); | 673 | board = das800_probe(dev); |
| 666 | if (board < 0) { | 674 | if (!board) |
| 667 | dev_dbg(dev->class_dev, "unable to determine board type\n"); | ||
| 668 | return -ENODEV; | 675 | return -ENODEV; |
| 669 | } | 676 | dev->board_ptr = board; |
| 670 | dev->board_ptr = das800_boards + board; | 677 | dev->board_name = board->name; |
| 671 | thisboard = dev->board_ptr; | ||
| 672 | dev->board_name = thisboard->name; | ||
| 673 | 678 | ||
| 674 | if (irq > 1 && irq <= 7) { | 679 | if (irq > 1 && irq <= 7) { |
| 675 | ret = request_irq(irq, das800_interrupt, 0, dev->board_name, | 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 | s->type = COMEDI_SUBD_AI; | 698 | s->type = COMEDI_SUBD_AI; |
| 694 | s->subdev_flags = SDF_READABLE | SDF_GROUND; | 699 | s->subdev_flags = SDF_READABLE | SDF_GROUND; |
| 695 | s->n_chan = 8; | 700 | s->n_chan = 8; |
| 696 | s->maxdata = (1 << thisboard->resolution) - 1; | 701 | s->maxdata = (1 << board->resolution) - 1; |
| 697 | s->range_table = thisboard->ai_range; | 702 | s->range_table = board->ai_range; |
| 698 | s->insn_read = das800_ai_insn_read; | 703 | s->insn_read = das800_ai_insn_read; |
| 699 | if (dev->irq) { | 704 | if (dev->irq) { |
| 700 | s->subdev_flags |= SDF_CMD_READ; | 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 | static int dt3k_ai_cmdtest(struct comedi_device *dev, | 400 | static int dt3k_ai_cmdtest(struct comedi_device *dev, |
| 401 | struct comedi_subdevice *s, struct comedi_cmd *cmd) | 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 | int err = 0; | 404 | int err = 0; |
| 405 | unsigned int arg; | 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 | if (cmd->scan_begin_src == TRIG_TIMER) { | 425 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 426 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, | 426 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 427 | this_board->ai_speed); | 427 | board->ai_speed); |
| 428 | err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, | 428 | err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg, |
| 429 | 100 * 16 * 65535); | 429 | 100 * 16 * 65535); |
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | if (cmd->convert_src == TRIG_TIMER) { | 432 | if (cmd->convert_src == TRIG_TIMER) { |
| 433 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, | 433 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 434 | this_board->ai_speed); | 434 | board->ai_speed); |
| 435 | err |= comedi_check_trigger_arg_max(&cmd->convert_arg, | 435 | err |= comedi_check_trigger_arg_max(&cmd->convert_arg, |
| 436 | 50 * 16 * 65535); | 436 | 50 * 16 * 65535); |
| 437 | } | 437 | } |
| @@ -635,17 +635,17 @@ static int dt3000_auto_attach(struct comedi_device *dev, · 197 unmodified lines | |||
| 635 | unsigned long context) | 635 | unsigned long context) |
| 636 | { | 636 | { |
| 637 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct dt3k_private *devpriv; | 639 | struct dt3k_private *devpriv; |
| 640 | struct comedi_subdevice *s; | 640 | struct comedi_subdevice *s; |
| 641 | int ret = 0; | 641 | int ret = 0; |
| 642 | 642 | ||
| 643 | if (context < ARRAY_SIZE(dt3k_boardtypes)) | 643 | if (context < ARRAY_SIZE(dt3k_boardtypes)) |
| 644 | this_board = &dt3k_boardtypes[context]; | 644 | board = &dt3k_boardtypes[context]; |
| 645 | if (!this_board) | 645 | if (!board) |
| 646 | return -ENODEV; | 646 | return -ENODEV; |
| 647 | dev->board_ptr = this_board; | 647 | dev->board_ptr = board; |
| 648 | dev->board_name = this_board->name; | 648 | dev->board_name = board->name; |
| 649 | 649 | ||
| 650 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 650 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 651 | if (!devpriv) | 651 | if (!devpriv) |
| @@ -674,9 +674,9 @@ static int dt3000_auto_attach(struct comedi_device *dev, · 22 unmodified lines | |||
| 674 | /* ai subdevice */ | 674 | /* ai subdevice */ |
| 675 | s->type = COMEDI_SUBD_AI; | 675 | s->type = COMEDI_SUBD_AI; |
| 676 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; | 676 | s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; |
| 677 | s->n_chan = this_board->adchan; | 677 | s->n_chan = board->adchan; |
| 678 | s->insn_read = dt3k_ai_insn; | 678 | s->insn_read = dt3k_ai_insn; |
| 679 | s->maxdata = (1 << this_board->adbits) - 1; | 679 | s->maxdata = (1 << board->adbits) - 1; |
| 680 | s->range_table = &range_dt3000_ai; /* XXX */ | 680 | s->range_table = &range_dt3000_ai; /* XXX */ |
| 681 | if (dev->irq) { | 681 | if (dev->irq) { |
| 682 | dev->read_subdev = s; | 682 | dev->read_subdev = s; |
| @@ -692,7 +692,7 @@ static int dt3000_auto_attach(struct comedi_device *dev, · 9 unmodified lines | |||
| 692 | s->type = COMEDI_SUBD_AO; | 692 | s->type = COMEDI_SUBD_AO; |
| 693 | s->subdev_flags = SDF_WRITABLE; | 693 | s->subdev_flags = SDF_WRITABLE; |
| 694 | s->n_chan = 2; | 694 | s->n_chan = 2; |
| 695 | s->maxdata = (1 << this_board->dabits) - 1; | 695 | s->maxdata = (1 << board->dabits) - 1; |
| 696 | s->len_chanlist = 1; | 696 | s->len_chanlist = 1; |
| 697 | s->range_table = &range_bipolar10; | 697 | s->range_table = &range_bipolar10; |
| 698 | s->insn_write = dt3k_ao_insn_write; | 698 | s->insn_write = dt3k_ao_insn_write; |
| @@ -52,45 +52,45 @@ · 51 unmodified lines | |||
| 52 | * PCI BAR2 Register map (dev->mmio) | 52 | * PCI BAR2 Register map (dev->mmio) |
| 53 | */ | 53 | */ |
| 54 | #define FIRMWARE_REV_REG 0x00 | 54 | #define FIRMWARE_REV_REG 0x00 |
| 55 | #define FEATURES_REG_PRESENT_BIT (1 << 15) | 55 | #define FEATURES_REG_PRESENT_BIT BIT(15) |
| 56 | #define BOARD_CONTROL_REG 0x04 | 56 | #define BOARD_CONTROL_REG 0x04 |
| 57 | #define BOARD_RESET_BIT (1 << 0) | 57 | #define BOARD_RESET_BIT BIT(0) |
| 58 | #define TX_FIFO_RESET_BIT (1 << 1) | 58 | #define TX_FIFO_RESET_BIT BIT(1) |
| 59 | #define RX_FIFO_RESET_BIT (1 << 2) | 59 | #define RX_FIFO_RESET_BIT BIT(2) |
| 60 | #define TX_ENABLE_BIT (1 << 4) | 60 | #define TX_ENABLE_BIT BIT(4) |
| 61 | #define RX_ENABLE_BIT (1 << 5) | 61 | #define RX_ENABLE_BIT BIT(5) |
| 62 | #define DEMAND_DMA_DIRECTION_TX_BIT (1 << 6) /* ch 0 only */ | 62 | #define DEMAND_DMA_DIRECTION_TX_BIT BIT(6) /* ch 0 only */ |
| 63 | #define LINE_VALID_ON_STATUS_VALID_BIT (1 << 7) | 63 | #define LINE_VALID_ON_STATUS_VALID_BIT BIT(7) |
| 64 | #define START_TX_BIT (1 << 8) | 64 | #define START_TX_BIT BIT(8) |
| 65 | #define CABLE_THROTTLE_ENABLE_BIT (1 << 9) | 65 | #define CABLE_THROTTLE_ENABLE_BIT BIT(9) |
| 66 | #define TEST_MODE_ENABLE_BIT (1 << 31) | 66 | #define TEST_MODE_ENABLE_BIT BIT(31) |
| 67 | #define BOARD_STATUS_REG 0x08 | 67 | #define BOARD_STATUS_REG 0x08 |
| 68 | #define COMMAND_LINE_STATUS_MASK (0x7f << 0) | 68 | #define COMMAND_LINE_STATUS_MASK (0x7f << 0) |
| 69 | #define TX_IN_PROGRESS_BIT (1 << 7) | 69 | #define TX_IN_PROGRESS_BIT BIT(7) |
| 70 | #define TX_NOT_EMPTY_BIT (1 << 8) | 70 | #define TX_NOT_EMPTY_BIT BIT(8) |
| 71 | #define TX_NOT_ALMOST_EMPTY_BIT (1 << 9) | 71 | #define TX_NOT_ALMOST_EMPTY_BIT BIT(9) |
| 72 | #define TX_NOT_ALMOST_FULL_BIT (1 << 10) | 72 | #define TX_NOT_ALMOST_FULL_BIT BIT(10) |
| 73 | #define TX_NOT_FULL_BIT (1 << 11) | 73 | #define TX_NOT_FULL_BIT BIT(11) |
| 74 | #define RX_NOT_EMPTY_BIT (1 << 12) | 74 | #define RX_NOT_EMPTY_BIT BIT(12) |
| 75 | #define RX_NOT_ALMOST_EMPTY_BIT (1 << 13) | 75 | #define RX_NOT_ALMOST_EMPTY_BIT BIT(13) |
| 76 | #define RX_NOT_ALMOST_FULL_BIT (1 << 14) | 76 | #define RX_NOT_ALMOST_FULL_BIT BIT(14) |
| 77 | #define RX_NOT_FULL_BIT (1 << 15) | 77 | #define RX_NOT_FULL_BIT BIT(15) |
| 78 | #define BOARD_JUMPER0_INSTALLED_BIT (1 << 16) | 78 | #define BOARD_JUMPER0_INSTALLED_BIT BIT(16) |
| 79 | #define BOARD_JUMPER1_INSTALLED_BIT (1 << 17) | 79 | #define BOARD_JUMPER1_INSTALLED_BIT BIT(17) |
| 80 | #define TX_OVERRUN_BIT (1 << 21) | 80 | #define TX_OVERRUN_BIT BIT(21) |
| 81 | #define RX_UNDERRUN_BIT (1 << 22) | 81 | #define RX_UNDERRUN_BIT BIT(22) |
| 82 | #define RX_OVERRUN_BIT (1 << 23) | 82 | #define RX_OVERRUN_BIT BIT(23) |
| 83 | #define TX_PROG_ALMOST_REG 0x0c | 83 | #define TX_PROG_ALMOST_REG 0x0c |
| 84 | #define RX_PROG_ALMOST_REG 0x10 | 84 | #define RX_PROG_ALMOST_REG 0x10 |
| 85 | #define ALMOST_EMPTY_BITS(x) (((x) & 0xffff) << 0) | 85 | #define ALMOST_EMPTY_BITS(x) (((x) & 0xffff) << 0) |
| 86 | #define ALMOST_FULL_BITS(x) (((x) & 0xff) << 16) | 86 | #define ALMOST_FULL_BITS(x) (((x) & 0xff) << 16) |
| 87 | #define FEATURES_REG 0x14 | 87 | #define FEATURES_REG 0x14 |
| 88 | #define FIFO_SIZE_PRESENT_BIT (1 << 0) | 88 | #define FIFO_SIZE_PRESENT_BIT BIT(0) |
| 89 | #define FIFO_WORDS_PRESENT_BIT (1 << 1) | 89 | #define FIFO_WORDS_PRESENT_BIT BIT(1) |
| 90 | #define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT (1 << 2) | 90 | #define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT BIT(2) |
| 91 | #define GPIO_SUPPORTED_BIT (1 << 3) | 91 | #define GPIO_SUPPORTED_BIT BIT(3) |
| 92 | #define PLX_DMA_CH1_SUPPORTED_BIT (1 << 4) | 92 | #define PLX_DMA_CH1_SUPPORTED_BIT BIT(4) |
| 93 | #define OVERRUN_UNDERRUN_SUPPORTED_BIT (1 << 5) | 93 | #define OVERRUN_UNDERRUN_SUPPORTED_BIT BIT(5) |
| 94 | #define FIFO_REG 0x18 | 94 | #define FIFO_REG 0x18 |
| 95 | #define TX_STATUS_COUNT_REG 0x1c | 95 | #define TX_STATUS_COUNT_REG 0x1c |
| 96 | #define TX_LINE_VALID_COUNT_REG 0x20, | 96 | #define TX_LINE_VALID_COUNT_REG 0x20, |
| @@ -98,16 +98,16 @@ · 1 unmodified line | |||
| 98 | #define RX_STATUS_COUNT_REG 0x28 | 98 | #define RX_STATUS_COUNT_REG 0x28 |
| 99 | #define RX_LINE_COUNT_REG 0x2c | 99 | #define RX_LINE_COUNT_REG 0x2c |
| 100 | #define INTERRUPT_CONTROL_REG 0x30 | 100 | #define INTERRUPT_CONTROL_REG 0x30 |
| 101 | #define FRAME_VALID_START_INTR (1 << 0) | 101 | #define FRAME_VALID_START_INTR BIT(0) |
| 102 | #define FRAME_VALID_END_INTR (1 << 1) | 102 | #define FRAME_VALID_END_INTR BIT(1) |
| 103 | #define TX_FIFO_EMPTY_INTR (1 << 8) | 103 | #define TX_FIFO_EMPTY_INTR BIT(8) |
| 104 | #define TX_FIFO_ALMOST_EMPTY_INTR (1 << 9) | 104 | #define TX_FIFO_ALMOST_EMPTY_INTR BIT(9) |
| 105 | #define TX_FIFO_ALMOST_FULL_INTR (1 << 10) | 105 | #define TX_FIFO_ALMOST_FULL_INTR BIT(10) |
| 106 | #define TX_FIFO_FULL_INTR (1 << 11) | 106 | #define TX_FIFO_FULL_INTR BIT(11) |
| 107 | #define RX_EMPTY_INTR (1 << 12) | 107 | #define RX_EMPTY_INTR BIT(12) |
| 108 | #define RX_ALMOST_EMPTY_INTR (1 << 13) | 108 | #define RX_ALMOST_EMPTY_INTR BIT(13) |
| 109 | #define RX_ALMOST_FULL_INTR (1 << 14) | 109 | #define RX_ALMOST_FULL_INTR BIT(14) |
| 110 | #define RX_FULL_INTR (1 << 15) | 110 | #define RX_FULL_INTR BIT(15) |
| 111 | #define INTERRUPT_STATUS_REG 0x34 | 111 | #define INTERRUPT_STATUS_REG 0x34 |
| 112 | #define TX_CLOCK_DIVIDER_REG 0x38 | 112 | #define TX_CLOCK_DIVIDER_REG 0x38 |
| 113 | #define TX_FIFO_SIZE_REG 0x40 | 113 | #define TX_FIFO_SIZE_REG 0x40 |
| @@ -123,34 +123,15 @@ · 9 unmodified lines | |||
| 123 | #define NUM_DMA_BUFFERS 4 | 123 | #define NUM_DMA_BUFFERS 4 |
| 124 | #define NUM_DMA_DESCRIPTORS 256 | 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 | struct hpdi_private { | 126 | struct hpdi_private { |
| 148 | void __iomem *plx9080_mmio; | 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 | /* physical addresses of dma buffers */ | 129 | /* physical addresses of dma buffers */ |
| 151 | dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; | 130 | dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS]; |
| 152 | /* array of dma descriptors read by plx9080, allocated to get proper | 131 | /* |
| 153 | * alignment */ | 132 | * array of dma descriptors read by plx9080, allocated to get proper |
| 133 | * alignment | ||
| 134 | */ | ||
| 154 | struct plx_dma_desc *dma_desc; | 135 | struct plx_dma_desc *dma_desc; |
| 155 | /* physical address of dma descriptor array */ | 136 | /* physical address of dma descriptor array */ |
| 156 | dma_addr_t dma_desc_phys_addr; | 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 | devpriv->dma_desc_index = idx; | 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 | static irqreturn_t gsc_hpdi_interrupt(int irq, void *d) | 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 | if (hpdi_intr_status) | 211 | if (hpdi_intr_status) |
| 231 | writel(hpdi_intr_status, dev->mmio + INTERRUPT_STATUS_REG); | 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 | spin_lock_irqsave(&dev->spinlock, flags); | 215 | spin_lock_irqsave(&dev->spinlock, flags); |
| 235 | dma0_status = readb(devpriv->plx9080_mmio + PLX_DMA0_CS_REG); | 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 | writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, | 219 | writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, |
| 238 | devpriv->plx9080_mmio + PLX_DMA0_CS_REG); | 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 | spin_unlock_irqrestore(&dev->spinlock, flags); | 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 | spin_lock_irqsave(&dev->spinlock, flags); | 228 | spin_lock_irqsave(&dev->spinlock, flags); |
| 247 | dma1_status = readb(devpriv->plx9080_mmio + PLX_DMA1_CS_REG); | 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 | writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, | 232 | writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, |
| 250 | devpriv->plx9080_mmio + PLX_DMA1_CS_REG); | 233 | devpriv->plx9080_mmio + PLX_DMA1_CS_REG); |
| 251 | } | 234 | } |
| 252 | spin_unlock_irqrestore(&dev->spinlock, flags); | 235 | spin_unlock_irqrestore(&dev->spinlock, flags); |
| 253 | 236 | ||
| 254 | /* clear possible plx9080 interrupt sources */ | 237 | /* clear possible plx9080 interrupt sources */ |
| 255 | if (plx_status & ICS_LDIA) { /* clear local doorbell interrupt */ | 238 | if (plx_status & ICS_LDIA) { |
| 239 | /* clear local doorbell interrupt */ | ||
| 256 | plx_bits = readl(devpriv->plx9080_mmio + PLX_DBR_OUT_REG); | 240 | plx_bits = readl(devpriv->plx9080_mmio + PLX_DBR_OUT_REG); |
| 257 | writel(plx_bits, devpriv->plx9080_mmio + PLX_DBR_OUT_REG); | 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 | struct hpdi_private *devpriv = dev->private; | 264 | struct hpdi_private *devpriv = dev->private; |
| 281 | unsigned long flags; | 265 | unsigned long flags; |
| 282 | 266 | ||
| 283 | /* spinlock for plx dma control/status reg */ | 267 | /* spinlock for plx dma control/status reg */ |
| 284 | spin_lock_irqsave(&dev->spinlock, flags); | 268 | spin_lock_irqsave(&dev->spinlock, flags); |
| 285 | 269 | ||
| 286 | plx9080_abort_dma(devpriv->plx9080_mmio, channel); | 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 | /* wait 10usec after reset before accessing fifos */ | 521 | /* wait 10usec after reset before accessing fifos */ |
| 538 | writel(BOARD_RESET_BIT, dev->mmio + BOARD_CONTROL_REG); | 522 | writel(BOARD_RESET_BIT, dev->mmio + BOARD_CONTROL_REG); |
| 539 | udelay(10); | 523 | usleep_range(10, 1000); |
| 540 | 524 | ||
| 541 | writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32), | 525 | writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32), |
| 542 | dev->mmio + RX_PROG_ALMOST_REG); | 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 | writel(0, dev->mmio + INTERRUPT_CONTROL_REG); | 535 | writel(0, dev->mmio + INTERRUPT_CONTROL_REG); |
| 552 | 536 | ||
| 553 | /* enable interrupts */ | 537 | /* enable interrupts */ |
| 554 | plx_intcsr_bits = | 538 | plx_intcsr_bits = |
| 555 | ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE | | 539 | ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE | |
| 556 | ICS_DMA0_E; | 540 | ICS_DMA0_E; |
| @@ -577,57 +561,42 @@ static void gsc_hpdi_init_plx9080(struct comedi_device *dev) · 20 unmodified lines | |||
| 577 | gsc_hpdi_abort_dma(dev, 0); | 561 | gsc_hpdi_abort_dma(dev, 0); |
| 578 | gsc_hpdi_abort_dma(dev, 1); | 562 | gsc_hpdi_abort_dma(dev, 1); |
| 579 | 563 | ||
| 580 | /* configure dma0 mode */ | 564 | /* configure dma0 mode */ |
| 581 | bits = 0; | 565 | bits = 0; |
| 582 | /* enable ready input */ | 566 | /* enable ready input */ |
| 583 | bits |= PLX_DMA_EN_READYIN_BIT; | 567 | bits |= PLX_DMA_EN_READYIN_BIT; |
| 584 | /* enable dma chaining */ | 568 | /* enable dma chaining */ |
| 585 | bits |= PLX_EN_CHAIN_BIT; | 569 | bits |= PLX_EN_CHAIN_BIT; |
| 586 | /* enable interrupt on dma done | 570 | /* |
| 587 | * (probably don't need this, since chain never finishes) */ | 571 | * enable interrupt on dma done |
| 572 | * (probably don't need this, since chain never finishes) | ||
| 573 | */ | ||
| 588 | bits |= PLX_EN_DMA_DONE_INTR_BIT; | 574 | bits |= PLX_EN_DMA_DONE_INTR_BIT; |
| 589 | /* don't increment local address during transfers | 575 | /* |
| 590 | * (we are transferring from a fixed fifo register) */ | 576 | * don't increment local address during transfers |
| 577 | * (we are transferring from a fixed fifo register) | ||
| 578 | */ | ||
| 591 | bits |= PLX_LOCAL_ADDR_CONST_BIT; | 579 | bits |= PLX_LOCAL_ADDR_CONST_BIT; |
| 592 | /* route dma interrupt to pci bus */ | 580 | /* route dma interrupt to pci bus */ |
| 593 | bits |= PLX_DMA_INTR_PCI_BIT; | 581 | bits |= PLX_DMA_INTR_PCI_BIT; |
| 594 | /* enable demand mode */ | 582 | /* enable demand mode */ |
| 595 | bits |= PLX_DEMAND_MODE_BIT; | 583 | bits |= PLX_DEMAND_MODE_BIT; |
| 596 | /* enable local burst mode */ | 584 | /* enable local burst mode */ |
| 597 | bits |= PLX_DMA_LOCAL_BURST_EN_BIT; | 585 | bits |= PLX_DMA_LOCAL_BURST_EN_BIT; |
| 598 | bits |= PLX_LOCAL_BUS_32_WIDE_BITS; | 586 | bits |= PLX_LOCAL_BUS_32_WIDE_BITS; |
| 599 | writel(bits, plx_iobase + PLX_DMA0_MODE_REG); | 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 | static int gsc_hpdi_auto_attach(struct comedi_device *dev, | 590 | static int gsc_hpdi_auto_attach(struct comedi_device *dev, |
| 614 | unsigned long context_unused) | 591 | unsigned long context_unused) |
| 615 | { | 592 | { |
| 616 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 593 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
| 617 | const struct hpdi_board *thisboard; | ||
| 618 | struct hpdi_private *devpriv; | 594 | struct hpdi_private *devpriv; |
| 619 | struct comedi_subdevice *s; | 595 | struct comedi_subdevice *s; |
| 620 | int i; | 596 | int i; |
| 621 | int retval; | 597 | int retval; |
| 622 | 598 | ||
| 623 | thisboard = gsc_hpdi_find_board(pcidev); | 599 | dev->board_name = "pci-hpdi32"; |
| 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; | ||
| 631 | 600 | ||
| 632 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); | 601 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
| 633 | if (!devpriv) | 602 | if (!devpriv) |
| @@ -647,7 +616,7 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev, · 13 unmodified lines | |||
| 647 | 616 | ||
| 648 | gsc_hpdi_init_plx9080(dev); | 617 | gsc_hpdi_init_plx9080(dev); |
| 649 | 618 | ||
| 650 | /* get irq */ | 619 | /* get irq */ |
| 651 | if (request_irq(pcidev->irq, gsc_hpdi_interrupt, IRQF_SHARED, | 620 | if (request_irq(pcidev->irq, gsc_hpdi_interrupt, IRQF_SHARED, |
| 652 | dev->board_name, dev)) { | 621 | dev->board_name, dev)) { |
| 653 | dev_warn(dev->class_dev, | 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 | dev_dbg(dev->class_dev, " irq %u\n", dev->irq); | 628 | dev_dbg(dev->class_dev, " irq %u\n", dev->irq); |
| 660 | 629 | ||
| 661 | /* allocate pci dma buffers */ | 630 | /* allocate pci dma buffers */ |
| 662 | for (i = 0; i < NUM_DMA_BUFFERS; i++) { | 631 | for (i = 0; i < NUM_DMA_BUFFERS; i++) { |
| 663 | devpriv->dio_buffer[i] = | 632 | devpriv->dio_buffer[i] = |
| 664 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, | 633 | pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, |
| 665 | &devpriv->dio_buffer_phys_addr[i]); | 634 | &devpriv->dio_buffer_phys_addr[i]); |
| 666 | } | 635 | } |
| 667 | /* allocate dma descriptors */ | 636 | /* allocate dma descriptors */ |
| 668 | devpriv->dma_desc = pci_alloc_consistent(pcidev, | 637 | devpriv->dma_desc = pci_alloc_consistent(pcidev, |
| 669 | sizeof(struct plx_dma_desc) * | 638 | sizeof(struct plx_dma_desc) * |
| 670 | NUM_DMA_DESCRIPTORS, | 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 | static const struct pci_device_id gsc_hpdi_pci_table[] = { | 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, | 705 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, |
| 737 | 0x2400, 0, 0, 0}, | 706 | PCI_VENDOR_ID_PLX, 0x2400) }, |
| 738 | { 0 } | 707 | { 0 } |
| 739 | }; | 708 | }; |
| 740 | MODULE_DEVICE_TABLE(pci, gsc_hpdi_pci_table); | 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 | module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver); | 717 | module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver); |
| 749 | 718 | ||
| 750 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | 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 | MODULE_LICENSE("GPL"); | 721 | MODULE_LICENSE("GPL"); |
| @@ -453,7 +453,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, · 452 unmodified lines | |||
| 453 | struct comedi_subdevice *subdevice, | 453 | struct comedi_subdevice *subdevice, |
| 454 | struct comedi_insn *insn, unsigned int *data) | 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 | int chan = CR_CHAN(insn->chanspec); | 457 | int chan = CR_CHAN(insn->chanspec); |
| 458 | int rang = CR_RANGE(insn->chanspec); | 458 | int rang = CR_RANGE(insn->chanspec); |
| 459 | int aref = CR_AREF(insn->chanspec); | 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 | switch (aref) { | 491 | switch (aref) { |
| 492 | case AREF_GROUND: | 492 | case AREF_GROUND: |
| 493 | case AREF_COMMON: | 493 | case AREF_COMMON: |
| 494 | if (chan >= thisboard->ai_nchan) { | 494 | if (chan >= board->ai_nchan) { |
| 495 | dev_err(dev->class_dev, | 495 | dev_err(dev->class_dev, |
| 496 | "Analog input is not available\n"); | 496 | "Analog input is not available\n"); |
| 497 | return -EINVAL; | 497 | return -EINVAL; |
| @@ -506,7 +506,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, · 8 unmodified lines | |||
| 506 | return -EINVAL; | 506 | return -EINVAL; |
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | if (chan >= thisboard->ai_diff_nchan) { | 509 | if (chan >= board->ai_diff_nchan) { |
| 510 | dev_err(dev->class_dev, | 510 | dev_err(dev->class_dev, |
| 511 | "Analog input is not available\n"); | 511 | "Analog input is not available\n"); |
| 512 | return -EINVAL; | 512 | return -EINVAL; |
| @@ -1252,17 +1252,17 @@ static int me4000_auto_attach(struct comedi_device *dev, · 739 unmodified lines | |||
| 1252 | unsigned long context) | 1252 | unsigned long context) |
| 1253 | { | 1253 | { |
| 1254 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct me4000_info *info; | 1256 | struct me4000_info *info; |
| 1257 | struct comedi_subdevice *s; | 1257 | struct comedi_subdevice *s; |
| 1258 | int result; | 1258 | int result; |
| 1259 | 1259 | ||
| 1260 | if (context < ARRAY_SIZE(me4000_boards)) | 1260 | if (context < ARRAY_SIZE(me4000_boards)) |
| 1261 | thisboard = &me4000_boards[context]; | 1261 | board = &me4000_boards[context]; |
| 1262 | if (!thisboard) | 1262 | if (!board) |
| 1263 | return -ENODEV; | 1263 | return -ENODEV; |
| 1264 | dev->board_ptr = thisboard; | 1264 | dev->board_ptr = board; |
| 1265 | dev->board_name = thisboard->name; | 1265 | dev->board_name = board->name; |
| 1266 | 1266 | ||
| 1267 | info = comedi_alloc_devpriv(dev, sizeof(*info)); | 1267 | info = comedi_alloc_devpriv(dev, sizeof(*info)); |
| 1268 | if (!info) | 1268 | if (!info) |
| @@ -1301,11 +1301,11 @@ static int me4000_auto_attach(struct comedi_device *dev, · 32 unmodified lines | |||
| 1301 | 1301 | ||
| 1302 | s = &dev->subdevices[0]; | 1302 | s = &dev->subdevices[0]; |
| 1303 | 1303 | ||
| 1304 | if (thisboard->ai_nchan) { | 1304 | if (board->ai_nchan) { |
| 1305 | s->type = COMEDI_SUBD_AI; | 1305 | s->type = COMEDI_SUBD_AI; |
| 1306 | s->subdev_flags = | 1306 | s->subdev_flags = |
| 1307 | SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; | 1307 | SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; |
| 1308 | s->n_chan = thisboard->ai_nchan; | 1308 | s->n_chan = board->ai_nchan; |
| 1309 | s->maxdata = 0xFFFF; /* 16 bit ADC */ | 1309 | s->maxdata = 0xFFFF; /* 16 bit ADC */ |
| 1310 | s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; | 1310 | s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT; |
| 1311 | s->range_table = &me4000_ai_range; | 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 | s = &dev->subdevices[1]; | 1329 | s = &dev->subdevices[1]; |
| 1330 | 1330 | ||
| 1331 | if (thisboard->ao_nchan) { | 1331 | if (board->ao_nchan) { |
| 1332 | s->type = COMEDI_SUBD_AO; | 1332 | s->type = COMEDI_SUBD_AO; |
| 1333 | s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND; | 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 | s->maxdata = 0xFFFF; /* 16 bit DAC */ | 1335 | s->maxdata = 0xFFFF; /* 16 bit DAC */ |
| 1336 | s->range_table = &range_bipolar10; | 1336 | s->range_table = &range_bipolar10; |
| 1337 | s->insn_write = me4000_ao_insn_write; | 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 | s = &dev->subdevices[2]; | 1350 | s = &dev->subdevices[2]; |
| 1351 | 1351 | ||
| 1352 | if (thisboard->dio_nchan) { | 1352 | if (board->dio_nchan) { |
| 1353 | s->type = COMEDI_SUBD_DIO; | 1353 | s->type = COMEDI_SUBD_DIO; |
| 1354 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | 1354 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; |
| 1355 | s->n_chan = thisboard->dio_nchan; | 1355 | s->n_chan = board->dio_nchan; |
| 1356 | s->maxdata = 1; | 1356 | s->maxdata = 1; |
| 1357 | s->range_table = &range_digital; | 1357 | s->range_table = &range_digital; |
| 1358 | s->insn_bits = me4000_dio_insn_bits; | 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 | /* Counter subdevice (8254) */ | 1374 | /* Counter subdevice (8254) */ |
| 1375 | s = &dev->subdevices[3]; | 1375 | s = &dev->subdevices[3]; |
| 1376 | if (thisboard->has_counter) { | 1376 | if (board->has_counter) { |
| 1377 | unsigned long timer_base = pci_resource_start(pcidev, 3); | 1377 | unsigned long timer_base = pci_resource_start(pcidev, 3); |
| 1378 | 1378 | ||
| 1379 | if (!timer_base) | 1379 | if (!timer_base) |
| @@ -173,8 +173,7 @@ struct me_private_data { · 172 unmodified lines | |||
| 173 | 173 | ||
| 174 | static inline void sleep(unsigned sec) | 174 | static inline void sleep(unsigned sec) |
| 175 | { | 175 | { |
| 176 | __set_current_state(TASK_INTERRUPTIBLE); | 176 | schedule_timeout_interruptible(sec * HZ); |
| 177 | schedule_timeout(sec * HZ); | ||
| 178 | } | 177 | } |
| 179 | 178 | ||
| 180 | static int me_dio_insn_config(struct comedi_device *dev, | 179 | static int me_dio_insn_config(struct comedi_device *dev, |
| @@ -1,52 +1,51 @@ | |||
| 1 | /* | 1 | /* |
| 2 | comedi/drivers/mite.c | 2 | * comedi/drivers/mite.c |
| 3 | Hardware driver for NI Mite PCI interface chip | 3 | * Hardware driver for NI Mite PCI interface chip |
| 4 | 4 | * | |
| 5 | COMEDI - Linux Control and Measurement Device Interface | 5 | * COMEDI - Linux Control and Measurement Device Interface |
| 6 | Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> | 6 | * Copyright (C) 1997-2002 David A. Schleef <ds@schleef.org> |
| 7 | 7 | * | |
| 8 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | (at your option) any later version. | 11 | * (at your option) any later version. |
| 12 | 12 | * | |
| 13 | This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | The PCI-MIO E series driver was originally written by | 20 | * The PCI-MIO E series driver was originally written by |
| 21 | Tomasz Motylewski <...>, and ported to comedi by ds. | 21 | * Tomasz Motylewski <...>, and ported to comedi by ds. |
| 22 | 22 | * | |
| 23 | References for specifications: | 23 | * References for specifications: |
| 24 | 24 | * | |
| 25 | 321747b.pdf Register Level Programmer Manual (obsolete) | 25 | * 321747b.pdf Register Level Programmer Manual (obsolete) |
| 26 | 321747c.pdf Register Level Programmer Manual (new) | 26 | * 321747c.pdf Register Level Programmer Manual (new) |
| 27 | DAQ-STC reference manual | 27 | * DAQ-STC reference manual |
| 28 | 28 | * | |
| 29 | Other possibly relevant info: | 29 | * Other possibly relevant info: |
| 30 | 30 | * | |
| 31 | 320517c.pdf User manual (obsolete) | 31 | * 320517c.pdf User manual (obsolete) |
| 32 | 320517f.pdf User manual (new) | 32 | * 320517f.pdf User manual (new) |
| 33 | 320889a.pdf delete | 33 | * 320889a.pdf delete |
| 34 | 320906c.pdf maximum signal ratings | 34 | * 320906c.pdf maximum signal ratings |
| 35 | 321066a.pdf about 16x | 35 | * 321066a.pdf about 16x |
| 36 | 321791a.pdf discontinuation of at-mio-16e-10 rev. c | 36 | * 321791a.pdf discontinuation of at-mio-16e-10 rev. c |
| 37 | 321808a.pdf about at-mio-16e-10 rev P | 37 | * 321808a.pdf about at-mio-16e-10 rev P |
| 38 | 321837a.pdf discontinuation of at-mio-16de-10 rev d | 38 | * 321837a.pdf discontinuation of at-mio-16de-10 rev d |
| 39 | 321838a.pdf about at-mio-16de-10 rev N | 39 | * 321838a.pdf about at-mio-16de-10 rev N |
| 40 | 40 | * | |
| 41 | ISSUES: | 41 | * ISSUES: |
| 42 | 42 | * | |
| 43 | */ | 43 | */ |
| 44 | |||
| 45 | /* #define USE_KMALLOC */ | ||
| 46 | 44 | ||
| 47 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 45 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 48 | 46 | ||
| 49 | #include <linux/module.h> | 47 | #include <linux/module.h> |
| 48 | #include <linux/slab.h> | ||
| 50 | 49 | ||
| 51 | #include "../comedi_pci.h" | 50 | #include "../comedi_pci.h" |
| 52 | 51 | ||
| @@ -132,7 +131,7 @@ int mite_setup2(struct comedi_device *dev, · 79 unmodified lines | |||
| 132 | mite->mite_io_addr + MITE_IODWBSR); | 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 | * on a pxi-6281 and a pxi-6713. 6713 powered up with register value | 135 | * on a pxi-6281 and a pxi-6713. 6713 powered up with register value |
| 137 | * of 0x61f and bursts worked. 6281 powered up with register value of | 136 | * of 0x61f and bursts worked. 6281 powered up with register value of |
| 138 | * 0x1f and bursts didn't work. The NI windows driver reads the | 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 | unsigned long flags; | 223 | unsigned long flags; |
| 225 | struct mite_channel *channel = NULL; | 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 | * from interrupts | 228 | * from interrupts |
| 229 | */ | 229 | */ |
| 230 | spin_lock_irqsave(&mite->lock, flags); | 230 | spin_lock_irqsave(&mite->lock, flags); |
| @@ -246,15 +246,15 @@ void mite_release_channel(struct mite_channel *mite_chan) · 15 unmodified lines | |||
| 246 | struct mite_struct *mite = mite_chan->mite; | 246 | struct mite_struct *mite = mite_chan->mite; |
| 247 | unsigned long flags; | 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 | spin_lock_irqsave(&mite->lock, flags); | 250 | spin_lock_irqsave(&mite->lock, flags); |
| 251 | if (mite->channel_allocated[mite_chan->channel]) { | 251 | if (mite->channel_allocated[mite_chan->channel]) { |
| 252 | mite_dma_disarm(mite_chan); | 252 | mite_dma_disarm(mite_chan); |
| 253 | mite_dma_reset(mite_chan); | 253 | mite_dma_reset(mite_chan); |
| 254 | /* | 254 | /* |
| 255 | * disable all channel's interrupts (do it after disarm/reset so | 255 | * disable all channel's interrupts (do it after disarm/reset so |
| 256 | * MITE_CHCR reg isn't changed while dma is still active!) | 256 | * MITE_CHCR reg isn't changed while dma is still active!) |
| 257 | */ | 257 | */ |
| 258 | writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | | 258 | writel(CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | |
| 259 | CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE | | 259 | CHCR_CLR_SAR_IE | CHCR_CLR_DONE_IE | |
| 260 | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | | 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 | writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); | 286 | writel(chor, mite->mite_io_addr + MITE_CHOR(mite_chan->channel)); |
| 287 | mmiowb(); | 287 | mmiowb(); |
| 288 | spin_unlock_irqrestore(&mite->lock, flags); | 288 | spin_unlock_irqrestore(&mite->lock, flags); |
| 289 | /* mite_dma_tcr(mite, channel); */ | 289 | /* mite_dma_tcr(mite, channel); */ |
| 290 | } | 290 | } |
| 291 | EXPORT_SYMBOL_GPL(mite_dma_arm); | 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 | count = nbytes - async->buf_write_count; | 531 | count = nbytes - async->buf_write_count; |
| 532 | /* it's possible count will be negative due to | 532 | /* |
| 533 | * conservative value returned by mite_bytes_written_to_memory_lb */ | 533 | * it's possible count will be negative due to conservative value |
| 534 | * returned by mite_bytes_written_to_memory_lb | ||
| 535 | */ | ||
| 534 | if (count <= 0) | 536 | if (count <= 0) |
| 535 | return 0; | 537 | return 0; |
| 536 | 538 | ||
| @@ -551,7 +553,7 @@ int mite_sync_output_dma(struct mite_channel *mite_chan, · 14 unmodified lines | |||
| 551 | u32 nbytes_ub, nbytes_lb; | 553 | u32 nbytes_ub, nbytes_lb; |
| 552 | int count; | 554 | int count; |
| 553 | 555 | ||
| 554 | /* read alloc as much as we can */ | 556 | /* read alloc as much as we can */ |
| 555 | comedi_buf_read_alloc(s, async->prealloc_bufsz); | 557 | comedi_buf_read_alloc(s, async->prealloc_bufsz); |
| 556 | nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan); | 558 | nbytes_lb = mite_bytes_read_from_memory_lb(mite_chan); |
| 557 | if (cmd->stop_src == TRIG_COUNT && (int)(nbytes_lb - stop_count) > 0) | 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 | module_exit(mite_module_exit); | 624 | module_exit(mite_module_exit); |
| 623 | 625 | ||
| 624 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | 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 | MODULE_LICENSE("GPL"); | 628 | MODULE_LICENSE("GPL"); |
| @@ -1,32 +1,35 @@ | |||
| 1 | /* | 1 | /* |
| 2 | module/mite.h | 2 | * module/mite.h |
| 3 | Hardware driver for NI Mite PCI interface chip | 3 | * Hardware driver for NI Mite PCI interface chip |
| 4 | 4 | * | |
| 5 | COMEDI - Linux Control and Measurement Device Interface | 5 | * COMEDI - Linux Control and Measurement Device Interface |
| 6 | Copyright (C) 1999 David A. Schleef <ds@schleef.org> | 6 | * Copyright (C) 1999 David A. Schleef <ds@schleef.org> |
| 7 | 7 | * | |
| 8 | This program is free software; you can redistribute it and/or modify | 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 | 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 | 10 | * the Free Software Foundation; either version 2 of the License, or |
| 11 | (at your option) any later version. | 11 | * (at your option) any later version. |
| 12 | 12 | * | |
| 13 | This program is distributed in the hope that it will be useful, | 13 | * This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #ifndef _MITE_H_ | 19 | #ifndef _MITE_H_ |
| 20 | #define _MITE_H_ | 20 | #define _MITE_H_ |
| 21 | 21 | ||
| 22 | #include <linux/io.h> | ||
| 22 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
| 23 | #include <linux/slab.h> | 24 | #include <linux/spinlock.h> |
| 24 | #include "../comedi_pci.h" | ||
| 25 | |||
| 26 | #define PCIMIO_COMPAT | ||
| 27 | 25 | ||
| 28 | #define MAX_MITE_DMA_CHANNELS 8 | 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 | struct mite_dma_descriptor { | 33 | struct mite_dma_descriptor { |
| 31 | __le32 count; | 34 | __le32 count; |
| 32 | __le32 addr; | 35 | __le32 addr; |
| @@ -74,16 +77,13 @@ static inline int mite_setup(struct comedi_device *dev, · 41 unmodified lines | |||
| 74 | void mite_detach(struct mite_struct *mite); | 77 | void mite_detach(struct mite_struct *mite); |
| 75 | struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite); | 78 | struct mite_dma_descriptor_ring *mite_alloc_ring(struct mite_struct *mite); |
| 76 | void mite_free_ring(struct mite_dma_descriptor_ring *ring); | 79 | void mite_free_ring(struct mite_dma_descriptor_ring *ring); |
| 77 | struct mite_channel *mite_request_channel_in_range(struct mite_struct *mite, | 80 | struct mite_channel * |
| 78 | struct | 81 | mite_request_channel_in_range(struct mite_struct *mite, |
| 79 | mite_dma_descriptor_ring | 82 | struct mite_dma_descriptor_ring *ring, |
| 80 | *ring, unsigned min_channel, | 83 | unsigned min_channel, unsigned max_channel); |
| 81 | unsigned max_channel); | 84 | static inline struct mite_channel * |
| 82 | static inline struct mite_channel *mite_request_channel(struct mite_struct | 85 | mite_request_channel(struct mite_struct *mite, |
| 83 | *mite, | 86 | struct mite_dma_descriptor_ring *ring) |
| 84 | struct | ||
| 85 | mite_dma_descriptor_ring | ||
| 86 | *ring) | ||
| 87 | { | 87 | { |
| 88 | return mite_request_channel_in_range(mite, ring, 0, | 88 | return mite_request_channel_in_range(mite, ring, 0, |
| 89 | mite->num_channels - 1); | 89 | mite->num_channels - 1); |
| @@ -112,12 +112,14 @@ int mite_buf_change(struct mite_dma_descriptor_ring *ring, · 22 unmodified lines | |||
| 112 | struct comedi_subdevice *s); | 112 | struct comedi_subdevice *s); |
| 113 | 113 | ||
| 114 | enum mite_registers { | 114 | enum mite_registers { |
| 115 | /* The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be | 115 | /* |
| 116 | written and read back. The bits 0x1f always read as 1. | 116 | * The bits 0x90180700 in MITE_UNKNOWN_DMA_BURST_REG can be |
| 117 | The rest always read as zero. */ | 117 | * written and read back. The bits 0x1f always read as 1. |
| 118 | * The rest always read as zero. | ||
| 119 | */ | ||
| 118 | MITE_UNKNOWN_DMA_BURST_REG = 0x28, | 120 | MITE_UNKNOWN_DMA_BURST_REG = 0x28, |
| 119 | MITE_IODWBSR = 0xc0, /* IO Device Window Base Size Register */ | 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 | MITE_IODWCR_1 = 0xf4, | 123 | MITE_IODWCR_1 = 0xf4, |
| 122 | MITE_PCI_CONFIG_OFFSET = 0x300, | 124 | MITE_PCI_CONFIG_OFFSET = 0x300, |
| 123 | MITE_CSIGR = 0x460 /* chip signature */ | 125 | MITE_CSIGR = 0x460 /* chip signature */ |
| @@ -143,7 +145,7 @@ enum mite_registers { · 19 unmodified lines | |||
| 143 | #define MITE_FCR(x) (0x40 + MITE_CHAN(x)) /* fifo count */ | 145 | #define MITE_FCR(x) (0x40 + MITE_CHAN(x)) /* fifo count */ |
| 144 | 146 | ||
| 145 | enum MITE_IODWBSR_bits { | 147 | enum MITE_IODWBSR_bits { |
| 146 | WENAB = 0x80, /* window enable */ | 148 | WENAB = 0x80, /* window enable */ |
| 147 | }; | 149 | }; |
| 148 | 150 | ||
| 149 | static inline unsigned MITE_IODWBSR_1_WSIZE_bits(unsigned size) | 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 | static inline int mite_csigr_type(u32 csigr_bits) | 170 | static inline int mite_csigr_type(u32 csigr_bits) |
| 169 | { /* original mite = 0, minimite = 1 */ | 171 | { /* original mite = 0, minimite = 1 */ |
| 170 | return (csigr_bits >> 4) & 0xf; | 172 | return (csigr_bits >> 4) & 0xf; |
| 171 | }; | 173 | }; |
| 172 | 174 | ||
| 173 | static inline int mite_csigr_mmode(u32 csigr_bits) | 175 | static inline int mite_csigr_mmode(u32 csigr_bits) |
| 174 | { /* mite mode, minimite = 1 */ | 176 | { /* mite mode, minimite = 1 */ |
| 175 | return (csigr_bits >> 8) & 0x3; | 177 | return (csigr_bits >> 8) & 0x3; |
| 176 | }; | 178 | }; |
| 177 | 179 | ||
| 178 | static inline int mite_csigr_imode(u32 csigr_bits) | 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 | return (csigr_bits >> 12) & 0x3; | 182 | return (csigr_bits >> 12) & 0x3; |
| 181 | }; | 183 | }; |
| 182 | 184 | ||
| 183 | static inline int mite_csigr_dmac(u32 csigr_bits) | 185 | static inline int mite_csigr_dmac(u32 csigr_bits) |
| 184 | { /* number of dma channels */ | 186 | { /* number of dma channels */ |
| 185 | return (csigr_bits >> 16) & 0xf; | 187 | return (csigr_bits >> 16) & 0xf; |
| 186 | }; | 188 | }; |
| 187 | 189 | ||
| 188 | static inline int mite_csigr_wpdep(u32 csigr_bits) | 190 | static inline int mite_csigr_wpdep(u32 csigr_bits) |
| 189 | { /* write post fifo depth */ | 191 | { /* write post fifo depth */ |
| 190 | unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7; | 192 | unsigned int wpdep_bits = (csigr_bits >> 20) & 0x7; |
| 191 | 193 | ||
| 192 | return (wpdep_bits) ? (1 << (wpdep_bits - 1)) : 0; | 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 | static inline int mite_csigr_iowins(u32 csigr_bits) | 202 | static inline int mite_csigr_iowins(u32 csigr_bits) |
| 201 | { /* number of io windows */ | 203 | { /* number of io windows */ |
| 202 | return (csigr_bits >> 29) & 0x7; | 204 | return (csigr_bits >> 29) & 0x7; |
| 203 | }; | 205 | }; |
| 204 | 206 | ||
| @@ -280,6 +282,7 @@ enum ConfigRegister_bits { · 75 unmodified lines | |||
| 280 | CR_PORTMXI = (3 << 6), | 282 | CR_PORTMXI = (3 << 6), |
| 281 | CR_AMDEVICE = (1 << 0), | 283 | CR_AMDEVICE = (1 << 0), |
| 282 | }; | 284 | }; |
| 285 | |||
| 283 | static inline int CR_REQS(int source) | 286 | static inline int CR_REQS(int source) |
| 284 | { | 287 | { |
| 285 | return (source & 0x7) << 16; | 288 | return (source & 0x7) << 16; |
| @@ -287,8 +290,7 @@ static inline int CR_REQS(int source) · 1 unmodified line | |||
| 287 | 290 | ||
| 288 | static inline int CR_REQSDRQ(unsigned drq_line) | 291 | static inline int CR_REQSDRQ(unsigned drq_line) |
| 289 | { | 292 | { |
| 290 | /* This also works on m-series when | 293 | /* This also works on m-series when using channels (drq_line) 4 or 5. */ |
| 291 | using channels (drq_line) 4 or 5. */ | ||
| 292 | return CR_REQS((drq_line & 0x3) | 0x4); | 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 | unsigned long context) | 172 | unsigned long context) |
| 173 | { | 173 | { |
| 174 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); | 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 | struct ni_670x_private *devpriv; | 176 | struct ni_670x_private *devpriv; |
| 177 | struct comedi_subdevice *s; | 177 | struct comedi_subdevice *s; |
| 178 | int ret; | 178 | int ret; |
| 179 | int i; | 179 | int i; |
| 180 | 180 | ||
| 181 | if (context < ARRAY_SIZE(ni_670x_boards)) | 181 | if (context < ARRAY_SIZE(ni_670x_boards)) |
| 182 | thisboard = &ni_670x_boards[context]; | 182 | board = &ni_670x_boards[context]; |
| 183 | if (!thisboard) | 183 | if (!board) |
| 184 | return -ENODEV; | 184 | return -ENODEV; |
| 185 | dev->board_ptr = thisboard; | 185 | dev->board_ptr = board; |
| 186 | dev->board_name = thisboard->name; | 186 | dev->board_name = board->name; |
| 187 | 187 | ||
| 188 | ret = comedi_pci_enable(dev); | 188 | ret = comedi_pci_enable(dev); |
| 189 | if (ret) | 189 | if (ret) |
| @@ -209,7 +209,7 @@ static int ni_670x_auto_attach(struct comedi_device *dev, · 19 unmodified lines | |||
| 209 | /* analog output subdevice */ | 209 | /* analog output subdevice */ |
| 210 | s->type = COMEDI_SUBD_AO; | 210 | s->type = COMEDI_SUBD_AO; |
| 211 | s->subdev_flags = SDF_WRITABLE; | 211 | s->subdev_flags = SDF_WRITABLE; |
| 212 | s->n_chan = thisboard->ao_chans; | 212 | s->n_chan = board->ao_chans; |
| 213 | s->maxdata = 0xffff; | 213 | s->maxdata = 0xffff; |
| 214 | if (s->n_chan == 32) { | 214 | if (s->n_chan == 32) { |
| 215 | const struct comedi_lrange **range_table_list; | 215 | const struct comedi_lrange **range_table_list; |
| @@ -106,7 +106,7 @@ TRIG_WAKE_EOS · 105 unmodified lines | |||
| 106 | #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ | 106 | #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */ |
| 107 | #define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ | 107 | #define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */ |
| 108 | #define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */ | 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 | #define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ | 110 | #define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */ |
| 111 | #define I8253_BASE_REG 0x14 | 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 | static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, | 264 | static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, |
| 265 | unsigned int flags) | 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 | struct a2150_private *devpriv = dev->private; | 268 | struct a2150_private *devpriv = dev->private; |
| 269 | int lub, glb, temp; | 269 | int lub, glb, temp; |
| 270 | int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index; | 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 | /* initialize greatest lower and least upper bounds */ | 273 | /* initialize greatest lower and least upper bounds */ |
| 274 | lub_divisor_shift = 3; | 274 | lub_divisor_shift = 3; |
| 275 | lub_index = 0; | 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 | glb_divisor_shift = 0; | 277 | glb_divisor_shift = 0; |
| 278 | glb_index = thisboard->num_clocks - 1; | 278 | glb_index = board->num_clocks - 1; |
| 279 | glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift); | 279 | glb = board->clock[glb_index] * (1 << glb_divisor_shift); |
| 280 | 280 | ||
| 281 | /* make sure period is in available range */ | 281 | /* make sure period is in available range */ |
| 282 | if (*period < glb) | 282 | if (*period < glb) |
| @@ -287,9 +287,9 @@ static int a2150_get_timing(struct comedi_device *dev, unsigned int *period, · 4 unmodified lines | |||
| 287 | /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ | 287 | /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */ |
| 288 | for (i = 0; i < 4; i++) { | 288 | for (i = 0; i < 4; i++) { |
| 289 | /* there are a maximum of 4 master clocks */ | 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 | /* temp is the period in nanosec we are evaluating */ | 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 | /* if it is the best match yet */ | 293 | /* if it is the best match yet */ |
| 294 | if (temp < lub && temp >= *period) { | 294 | if (temp < lub && temp >= *period) { |
| 295 | lub_divisor_shift = i; | 295 | lub_divisor_shift = i; |
| @@ -413,7 +413,7 @@ static int a2150_ai_check_chanlist(struct comedi_device *dev, · 117 unmodified lines | |||
| 413 | static int a2150_ai_cmdtest(struct comedi_device *dev, | 413 | static int a2150_ai_cmdtest(struct comedi_device *dev, |
| 414 | struct comedi_subdevice *s, struct comedi_cmd *cmd) | 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 | int err = 0; | 417 | int err = 0; |
| 418 | unsigned int arg; | 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 | if (cmd->convert_src == TRIG_TIMER) { | 445 | if (cmd->convert_src == TRIG_TIMER) { |
| 446 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, | 446 | err |= comedi_check_trigger_arg_min(&cmd->convert_arg, |
| 447 | thisboard->ai_speed); | 447 | board->ai_speed); |
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); | 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 | comedi_isadma_free(devpriv->dma); | 687 | comedi_isadma_free(devpriv->dma); |
| 688 | } | 688 | } |
| 689 | 689 | ||
| 690 | /* probes board type, returns offset */ | 690 | static const struct a2150_board *a2150_probe(struct comedi_device *dev) |
| 691 | static int 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 | static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it) | 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 | struct a2150_private *devpriv; | 703 | struct a2150_private *devpriv; |
| 702 | struct comedi_subdevice *s; | 704 | struct comedi_subdevice *s; |
| 703 | static const int timeout = 2000; | 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 | if (ret) | 714 | if (ret) |
| 713 | return ret; | 715 | return ret; |
| 714 | 716 | ||
| 715 | i = a2150_probe(dev); | 717 | board = a2150_probe(dev); |
| 716 | if (i >= ARRAY_SIZE(a2150_boards)) | 718 | if (!board) |
| 717 | return -ENODEV; | 719 | return -ENODEV; |
| 718 | 720 | dev->board_ptr = board; | |
| 719 | dev->board_ptr = a2150_boards + i; | 721 | dev->board_name = board->name; |
| 720 | thisboard = dev->board_ptr; | ||
| 721 | dev->board_name = thisboard->name; | ||
| 722 | 722 | ||
| 723 | /* an IRQ and DMA are required to support async commands */ | 723 | /* an IRQ and DMA are required to support async commands */ |
| 724 | a2150_alloc_irq_and_dma(dev, it); | 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 | return 0; | 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 | int device_id = ni_read_eeprom(dev, 511); | 279 | int device_id = ni_read_eeprom(dev, 511); |
| 280 | int i; | 280 | int i; |
| 281 | 281 | ||
| 282 | for (i = 0; i < ARRAY_SIZE(ni_boards); i++) { | 282 | for (i = 0; i < ARRAY_SIZE(ni_boards); i++) { |
| 283 | if (ni_boards[i].device_id == device_id) | 283 | const struct ni_board_struct *board = &ni_boards[i]; |
| 284 | return i; | 284 | |
| 285 | if (board->device_id == device_id) | ||
| 286 | return board; | ||
| 285 | } | 287 | } |
| 286 | if (device_id == 255) | 288 | if (device_id == 255) |
| 287 | dev_err(dev->class_dev, "can't find board\n"); | 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 | dev_err(dev->class_dev, | 294 | dev_err(dev->class_dev, |
| 293 | "unknown device ID %d -- contact author\n", device_id); | 295 | "unknown device ID %d -- contact author\n", device_id); |
| 294 | 296 | ||
| 295 | return -1; | 297 | return NULL; |
| 296 | } | 298 | } |
| 297 | 299 | ||
| 298 | static int ni_atmio_attach(struct comedi_device *dev, | 300 | static int ni_atmio_attach(struct comedi_device *dev, |
| 299 | struct comedi_devconfig *it) | 301 | struct comedi_devconfig *it) |
| 300 | { | 302 | { |
| 301 | const struct ni_board_struct *boardtype; | 303 | const struct ni_board_struct *board; |
| 302 | struct pnp_dev *isapnp_dev; | 304 | struct pnp_dev *isapnp_dev; |
| 303 | int ret; | 305 | int ret; |
| 304 | unsigned long iobase; | 306 | unsigned long iobase; |
| 305 | int board; | ||
| 306 | unsigned int irq; | 307 | unsigned int irq; |
| 307 | 308 | ||
| 308 | ret = ni_alloc_private(dev); | 309 | ret = ni_alloc_private(dev); |
| @@ -326,15 +327,11 @@ static int ni_atmio_attach(struct comedi_device *dev, · 17 unmodified lines | |||
| 326 | if (ret) | 327 | if (ret) |
| 327 | return ret; | 328 | return ret; |
| 328 | 329 | ||
| 329 | /* get board type */ | 330 | board = ni_atmio_probe(dev); |
| 330 | 331 | if (!board) | |
| 331 | board = ni_getboardtype(dev); | 332 | return -ENODEV; |
| 332 | if (board < 0) | 333 | dev->board_ptr = board; |
| 333 | return -EIO; | 334 | dev->board_name = board->name; |
| 334 | |||
| 335 | dev->board_ptr = ni_boards + board; | ||
| 336 | boardtype = dev->board_ptr; | ||
| 337 | dev->board_name = boardtype->name; | ||
| 338 | 335 | ||
| 339 | /* irq stuff */ | 336 | /* irq stuff */ |
| 340 | 337 | ||
| @@ -60,7 +60,6 @@ · 59 unmodified lines | |||
| 60 | 60 | ||
| 61 | /* A timeout count */ | 61 | /* A timeout count */ |
| 62 | #define NI_TIMEOUT 1000 | 62 | #define NI_TIMEOUT 1000 |
| 63 | static const unsigned old_RTSI_clock_channel = 7; | ||
| 64 | 63 | ||
| 65 | /* Note: this table must match the ai_gain_* definitions */ | 64 | /* Note: this table must match the ai_gain_* definitions */ |
| 66 | static const short ni_gainlkup[][16] = { | 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 | * windowed STC registers to the m series register offsets. | 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, | 310 | struct mio_regmap { |
| 312 | uint32_t data, int reg) | 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) { | 390 | if (reg < ARRAY_SIZE(m_series_stc_write_regmap)) { |
| 317 | case AI_SC_Load_A_Registers: | 391 | regmap = &m_series_stc_write_regmap[reg]; |
| 318 | offset = M_Offset_AI_SC_Load_A; | 392 | } else { |
| 319 | break; | 393 | dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", |
| 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", | ||
| 347 | __func__, reg); | 394 | __func__, reg); |
| 348 | return; | 395 | return; |
| 349 | } | 396 | } |
| 350 | ni_writel(dev, data, offset); | ||
| 351 | } | ||
| 352 | 397 | ||
| 353 | static void m_series_stc_writew(struct comedi_device *dev, | 398 | switch (regmap->size) { |
| 354 | uint16_t data, int reg) | 399 | case 4: |
| 355 | { | 400 | ni_writel(dev, data, regmap->mio_reg); |
| 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; | ||
| 491 | break; | 401 | break; |
| 492 | case RTSI_Trig_Direction_Register: | 402 | case 2: |
| 493 | offset = M_Offset_RTSI_Trig_Direction; | 403 | ni_writew(dev, data, regmap->mio_reg); |
| 494 | break; | 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 | default: | 405 | default: |
| 501 | dev_warn(dev->class_dev, | 406 | dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n", |
| 502 | "%s: bug! unhandled register=0x%x in switch\n", | ||
| 503 | __func__, reg); | 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) { | 438 | if (reg < ARRAY_SIZE(m_series_stc_read_regmap)) { |
| 514 | case G_HW_Save_Register(0): | 439 | regmap = &m_series_stc_read_regmap[reg]; |
| 515 | offset = M_Offset_G0_HW_Save; | 440 | } else { |
| 516 | break; | 441 | dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", |
| 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", | ||
| 529 | __func__, reg); | 442 | __func__, reg); |
| 530 | return 0; | 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) | 446 | switch (regmap->size) { |
| 536 | { | 447 | case 4: |
| 537 | unsigned offset; | 448 | return ni_readl(dev, regmap->mio_reg); |
| 538 | 449 | case 2: | |
| 539 | switch (reg) { | 450 | return ni_readw(dev, regmap->mio_reg); |
| 540 | case AI_Status_1_Register: | 451 | case 1: |
| 541 | offset = M_Offset_AI_Status_1; | 452 | return ni_readb(dev, regmap->mio_reg); |
| 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; | ||
| 560 | default: | 453 | default: |
| 561 | dev_warn(dev->class_dev, | 454 | dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n", |
| 562 | "%s: bug! unhandled register=0x%x in switch\n", | ||
| 563 | __func__, reg); | 455 | __func__, reg); |
| 564 | return 0; | 456 | return 0; |
| 565 | } | 457 | } |
| 566 | return ni_readw(dev, offset); | ||
| 567 | } | 458 | } |
| 568 | 459 | ||
| 569 | static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg) | 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 | unsigned long flags; | 463 | unsigned long flags; |
| 573 | 464 | ||
| 574 | if (devpriv->is_m_series) { | 465 | if (devpriv->is_m_series) { |
| 575 | m_series_stc_writew(dev, data, reg); | 466 | m_series_stc_write(dev, data, reg); |
| 576 | } else { | 467 | } else { |
| 577 | spin_lock_irqsave(&devpriv->window_lock, flags); | 468 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 578 | if (!devpriv->mite && reg < 8) { | 469 | if (!devpriv->mite && reg < 8) { |
| 579 | ni_writew(dev, data, reg * 2); | 470 | ni_writew(dev, data, reg * 2); |
| 580 | } else { | 471 | } else { |
| 581 | ni_writew(dev, reg, Window_Address); | 472 | ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG); |
| 582 | ni_writew(dev, data, Window_Data); | 473 | ni_writew(dev, data, NI_E_STC_WINDOW_DATA_REG); |
| 583 | } | 474 | } |
| 584 | spin_unlock_irqrestore(&devpriv->window_lock, flags); | 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 | struct ni_private *devpriv = dev->private; | 481 | struct ni_private *devpriv = dev->private; |
| 591 | 482 | ||
| 592 | if (devpriv->is_m_series) { | 483 | if (devpriv->is_m_series) { |
| 593 | m_series_stc_writel(dev, data, reg); | 484 | m_series_stc_write(dev, data, reg); |
| 594 | } else { | 485 | } else { |
| 595 | ni_stc_writew(dev, data >> 16, reg); | 486 | ni_stc_writew(dev, data >> 16, reg); |
| 596 | ni_stc_writew(dev, data & 0xffff, reg + 1); | 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 | uint16_t val; | 495 | uint16_t val; |
| 605 | 496 | ||
| 606 | if (devpriv->is_m_series) { | 497 | if (devpriv->is_m_series) { |
| 607 | val = m_series_stc_readw(dev, reg); | 498 | val = m_series_stc_read(dev, reg); |
| 608 | } else { | 499 | } else { |
| 609 | spin_lock_irqsave(&devpriv->window_lock, flags); | 500 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 610 | if (!devpriv->mite && reg < 8) { | 501 | if (!devpriv->mite && reg < 8) { |
| 611 | val = ni_readw(dev, reg * 2); | 502 | val = ni_readw(dev, reg * 2); |
| 612 | } else { | 503 | } else { |
| 613 | ni_writew(dev, reg, Window_Address); | 504 | ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG); |
| 614 | val = ni_readw(dev, Window_Data); | 505 | val = ni_readw(dev, NI_E_STC_WINDOW_DATA_REG); |
| 615 | } | 506 | } |
| 616 | spin_unlock_irqrestore(&devpriv->window_lock, flags); | 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 | uint32_t val; | 515 | uint32_t val; |
| 625 | 516 | ||
| 626 | if (devpriv->is_m_series) { | 517 | if (devpriv->is_m_series) { |
| 627 | val = m_series_stc_readl(dev, reg); | 518 | val = m_series_stc_read(dev, reg); |
| 628 | } else { | 519 | } else { |
| 629 | val = ni_stc_readw(dev, reg) << 16; | 520 | val = ni_stc_readw(dev, reg) << 16; |
| 630 | val |= ni_stc_readw(dev, reg + 1); | 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 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); | 532 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); |
| 642 | switch (reg) { | 533 | switch (reg) { |
| 643 | case Interrupt_A_Enable_Register: | 534 | case NISTC_INTA_ENA_REG: |
| 644 | devpriv->int_a_enable_reg &= ~bit_mask; | 535 | devpriv->int_a_enable_reg &= ~bit_mask; |
| 645 | devpriv->int_a_enable_reg |= bit_values & bit_mask; | 536 | devpriv->int_a_enable_reg |= bit_values & bit_mask; |
| 646 | ni_stc_writew(dev, devpriv->int_a_enable_reg, | 537 | ni_stc_writew(dev, devpriv->int_a_enable_reg, reg); |
| 647 | Interrupt_A_Enable_Register); | ||
| 648 | break; | 538 | break; |
| 649 | case Interrupt_B_Enable_Register: | 539 | case NISTC_INTB_ENA_REG: |
| 650 | devpriv->int_b_enable_reg &= ~bit_mask; | 540 | devpriv->int_b_enable_reg &= ~bit_mask; |
| 651 | devpriv->int_b_enable_reg |= bit_values & bit_mask; | 541 | devpriv->int_b_enable_reg |= bit_values & bit_mask; |
| 652 | ni_stc_writew(dev, devpriv->int_b_enable_reg, | 542 | ni_stc_writew(dev, devpriv->int_b_enable_reg, reg); |
| 653 | Interrupt_B_Enable_Register); | ||
| 654 | break; | 543 | break; |
| 655 | case IO_Bidirection_Pin_Register: | 544 | case NISTC_IO_BIDIR_PIN_REG: |
| 656 | devpriv->io_bidirection_pin_reg &= ~bit_mask; | 545 | devpriv->io_bidirection_pin_reg &= ~bit_mask; |
| 657 | devpriv->io_bidirection_pin_reg |= bit_values & bit_mask; | 546 | devpriv->io_bidirection_pin_reg |= bit_values & bit_mask; |
| 658 | ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, | 547 | ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, reg); |
| 659 | IO_Bidirection_Pin_Register); | ||
| 660 | break; | 548 | break; |
| 661 | case AI_AO_Select: | 549 | case NI_E_DMA_AI_AO_SEL_REG: |
| 662 | devpriv->ai_ao_select_reg &= ~bit_mask; | 550 | devpriv->ai_ao_select_reg &= ~bit_mask; |
| 663 | devpriv->ai_ao_select_reg |= bit_values & bit_mask; | 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 | break; | 553 | break; |
| 666 | case G0_G1_Select: | 554 | case NI_E_DMA_G0_G1_SEL_REG: |
| 667 | devpriv->g0_g1_select_reg &= ~bit_mask; | 555 | devpriv->g0_g1_select_reg &= ~bit_mask; |
| 668 | devpriv->g0_g1_select_reg |= bit_values & bit_mask; | 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 | break; | 558 | break; |
| 671 | default: | 559 | default: |
| 672 | dev_err(dev->class_dev, "called with invalid register %d\n", | 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 | #ifdef PCIDMA | 568 | #ifdef PCIDMA |
| 681 | /* DMA channel setup */ | 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 | /* negative channel means no channel */ | 582 | /* negative channel means no channel */ |
| 684 | static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel) | 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 | if (channel >= 0) | 587 | if (channel >= 0) |
| 689 | bitfield = | 588 | bits = ni_stc_dma_channel_select_bitfield(channel); |
| 690 | (ni_stc_dma_channel_select_bitfield(channel) << | 589 | |
| 691 | AI_DMA_Select_Shift) & AI_DMA_Select_Mask; | 590 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
| 692 | else | 591 | NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); |
| 693 | bitfield = 0; | ||
| 694 | ni_set_bitfield(dev, AI_AO_Select, AI_DMA_Select_Mask, bitfield); | ||
| 695 | } | 592 | } |
| 696 | 593 | ||
| 697 | /* negative channel means no channel */ | 594 | /* negative channel means no channel */ |
| 698 | static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel) | 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 | if (channel >= 0) | 599 | if (channel >= 0) |
| 703 | bitfield = | 600 | bits = ni_stc_dma_channel_select_bitfield(channel); |
| 704 | (ni_stc_dma_channel_select_bitfield(channel) << | 601 | |
| 705 | AO_DMA_Select_Shift) & AO_DMA_Select_Mask; | 602 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
| 706 | else | 603 | NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits)); |
| 707 | bitfield = 0; | ||
| 708 | ni_set_bitfield(dev, AI_AO_Select, AO_DMA_Select_Mask, bitfield); | ||
| 709 | } | 604 | } |
| 710 | 605 | ||
| 711 | /* negative mite_channel means no channel */ | 606 | /* negative channel means no channel */ |
| 712 | static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, | 607 | static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, |
| 713 | unsigned gpct_index, | 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) | 613 | if (channel >= 0) |
| 719 | bitfield = GPCT_DMA_Select_Bits(gpct_index, mite_channel); | 614 | bits = ni_stc_dma_channel_select_bitfield(channel); |
| 720 | else | 615 | |
| 721 | bitfield = 0; | 616 | ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, |
| 722 | ni_set_bitfield(dev, G0_G1_Select, GPCT_DMA_Select_Mask(gpct_index), | 617 | NI_E_DMA_G0_G1_SEL_MASK(gpct_index), |
| 723 | bitfield); | 618 | NI_E_DMA_G0_G1_SEL(gpct_index, bits)); |
| 724 | } | 619 | } |
| 725 | 620 | ||
| 726 | /* negative mite_channel means no channel */ | 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 | struct ni_private *devpriv = dev->private; | 625 | struct ni_private *devpriv = dev->private; |
| 731 | unsigned long flags; | 626 | unsigned long flags; |
| 627 | unsigned bits; | ||
| 732 | 628 | ||
| 733 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); | 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 | if (mite_channel >= 0) { | 631 | if (mite_channel >= 0) { |
| 736 | /*XXX just guessing ni_stc_dma_channel_select_bitfield() returns the right bits, | 632 | /* |
| 737 | under the assumption the cdio dma selection works just like ai/ao/gpct. | 633 | * XXX just guessing ni_stc_dma_channel_select_bitfield() |
| 738 | Definitely works for dma channels 0 and 1. */ | 634 | * returns the right bits, under the assumption the cdio dma |
| 739 | devpriv->cdio_dma_select_reg |= | 635 | * selection works just like ai/ao/gpct. |
| 740 | (ni_stc_dma_channel_select_bitfield(mite_channel) << | 636 | * Definitely works for dma channels 0 and 1. |
| 741 | CDO_DMA_Select_Shift) & CDO_DMA_Select_Mask; | 637 | */ |
| 742 | } | 638 | bits = ni_stc_dma_channel_select_bitfield(mite_channel); |
| 743 | ni_writeb(dev, devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select); | 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 | mmiowb(); | 642 | mmiowb(); |
| 745 | spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); | 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 | unsigned long flags; | 693 | unsigned long flags; |
| 796 | struct mite_channel *mite_chan; | 694 | struct mite_channel *mite_chan; |
| 797 | 695 | ||
| 798 | BUG_ON(gpct_index >= NUM_GPCT); | ||
| 799 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); | 696 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 800 | BUG_ON(devpriv->counter_dev->counters[gpct_index].mite_chan); | 697 | BUG_ON(devpriv->counter_dev->counters[gpct_index].mite_chan); |
| 801 | mite_chan = | 698 | mite_chan = |
| @@ -879,7 +776,6 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev, · 77 unmodified lines | |||
| 879 | struct ni_private *devpriv = dev->private; | 776 | struct ni_private *devpriv = dev->private; |
| 880 | unsigned long flags; | 777 | unsigned long flags; |
| 881 | 778 | ||
| 882 | BUG_ON(gpct_index >= NUM_GPCT); | ||
| 883 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); | 779 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 884 | if (devpriv->counter_dev->counters[gpct_index].mite_chan) { | 780 | if (devpriv->counter_dev->counters[gpct_index].mite_chan) { |
| 885 | struct mite_channel *mite_chan = | 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 | * dma requests for their counters | 823 | * dma requests for their counters |
| 928 | */ | 824 | */ |
| 929 | if (gpct_index == 0) { | 825 | if (gpct_index == 0) { |
| 930 | reg = Second_IRQ_A_Enable_Register; | 826 | reg = NISTC_INTA2_ENA_REG; |
| 931 | if (enable) | 827 | if (enable) |
| 932 | val = G0_Gate_Second_Irq_Enable; | 828 | val = NISTC_INTA_ENA_G0_GATE; |
| 933 | } else { | 829 | } else { |
| 934 | reg = Second_IRQ_B_Enable_Register; | 830 | reg = NISTC_INTB2_ENA_REG; |
| 935 | if (enable) | 831 | if (enable) |
| 936 | val = G1_Gate_Second_Irq_Enable; | 832 | val = NISTC_INTB_ENA_G1_GATE; |
| 937 | } | 833 | } |
| 938 | ni_stc_writew(dev, val, reg); | 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 | if (devpriv->is_6143) { | 844 | if (devpriv->is_6143) { |
| 949 | /* Flush the 6143 data FIFO */ | 845 | /* Flush the 6143 data FIFO */ |
| 950 | ni_writel(dev, 0x10, AIFIFO_Control_6143); | 846 | ni_writel(dev, 0x10, NI6143_AI_FIFO_CTRL_REG); |
| 951 | ni_writel(dev, 0x00, AIFIFO_Control_6143); | 847 | ni_writel(dev, 0x00, NI6143_AI_FIFO_CTRL_REG); |
| 952 | /* Wait for complete */ | 848 | /* Wait for complete */ |
| 953 | for (i = 0; i < timeout; i++) { | 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 | break; | 851 | break; |
| 956 | udelay(1); | 852 | udelay(1); |
| 957 | } | 853 | } |
| 958 | if (i == timeout) | 854 | if (i == timeout) |
| 959 | dev_err(dev->class_dev, "FIFO flush timeout\n"); | 855 | dev_err(dev->class_dev, "FIFO flush timeout\n"); |
| 960 | } else { | 856 | } else { |
| 961 | ni_stc_writew(dev, 1, ADC_FIFO_Clear); | 857 | ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG); |
| 962 | if (devpriv->is_625x) { | 858 | if (devpriv->is_625x) { |
| 963 | ni_writeb(dev, 0, M_Offset_Static_AI_Control(0)); | 859 | ni_writeb(dev, 0, NI_M_STATIC_AI_CTRL_REG(0)); |
| 964 | ni_writeb(dev, 1, M_Offset_Static_AI_Control(0)); | 860 | ni_writeb(dev, 1, NI_M_STATIC_AI_CTRL_REG(0)); |
| 965 | #if 0 | 861 | #if 0 |
| 966 | /* the NI example code does 3 convert pulses for 625x boards, | 862 | /* the NI example code does 3 convert pulses for 625x boards, |
| 967 | but that appears to be wrong in practice. */ | 863 | but that appears to be wrong in practice. */ |
| 968 | ni_stc_writew(dev, AI_CONVERT_Pulse, | 864 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
| 969 | AI_Command_1_Register); | 865 | NISTC_AI_CMD1_REG); |
| 970 | ni_stc_writew(dev, AI_CONVERT_Pulse, | 866 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
| 971 | AI_Command_1_Register); | 867 | NISTC_AI_CMD1_REG); |
| 972 | ni_stc_writew(dev, AI_CONVERT_Pulse, | 868 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
| 973 | AI_Command_1_Register); | 869 | NISTC_AI_CMD1_REG); |
| 974 | #endif | 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 | unsigned long flags; | 879 | unsigned long flags; |
| 984 | 880 | ||
| 985 | spin_lock_irqsave(&devpriv->window_lock, flags); | 881 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 986 | ni_writew(dev, addr, AO_Window_Address_611x); | 882 | ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); |
| 987 | ni_writew(dev, data, AO_Window_Data_611x); | 883 | ni_writew(dev, data, NI611X_AO_WINDOW_DATA_REG); |
| 988 | spin_unlock_irqrestore(&devpriv->window_lock, flags); | 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 | unsigned long flags; | 891 | unsigned long flags; |
| 996 | 892 | ||
| 997 | spin_lock_irqsave(&devpriv->window_lock, flags); | 893 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 998 | ni_writew(dev, addr, AO_Window_Address_611x); | 894 | ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); |
| 999 | ni_writel(dev, data, AO_Window_Data_611x); | 895 | ni_writel(dev, data, NI611X_AO_WINDOW_DATA_REG); |
| 1000 | spin_unlock_irqrestore(&devpriv->window_lock, flags); | 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 | unsigned short data; | 903 | unsigned short data; |
| 1008 | 904 | ||
| 1009 | spin_lock_irqsave(&devpriv->window_lock, flags); | 905 | spin_lock_irqsave(&devpriv->window_lock, flags); |
| 1010 | ni_writew(dev, addr, AO_Window_Address_611x); | 906 | ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG); |
| 1011 | data = ni_readw(dev, AO_Window_Data_611x); | 907 | data = ni_readw(dev, NI611X_AO_WINDOW_DATA_REG); |
| 1012 | spin_unlock_irqrestore(&devpriv->window_lock, flags); | 908 | spin_unlock_irqrestore(&devpriv->window_lock, flags); |
| 1013 | return data; | 909 | return data; |
| 1014 | } | 910 | } |
| @@ -1059,8 +955,8 @@ static int ni_ai_drain_dma(struct comedi_device *dev) · 44 unmodified lines | |||
| 1059 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); | 955 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 1060 | if (devpriv->ai_mite_chan) { | 956 | if (devpriv->ai_mite_chan) { |
| 1061 | for (i = 0; i < timeout; i++) { | 957 | for (i = 0; i < timeout; i++) { |
| 1062 | if ((ni_stc_readw(dev, AI_Status_1_Register) & | 958 | if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
| 1063 | AI_FIFO_Empty_St) | 959 | NISTC_AI_STATUS1_FIFO_E) |
| 1064 | && mite_bytes_in_transit(devpriv->ai_mite_chan) == | 960 | && mite_bytes_in_transit(devpriv->ai_mite_chan) == |
| 1065 | 0) | 961 | 0) |
| 1066 | break; | 962 | break; |
| @@ -1071,7 +967,7 @@ static int ni_ai_drain_dma(struct comedi_device *dev) · 4 unmodified lines | |||
| 1071 | dev_err(dev->class_dev, | 967 | dev_err(dev->class_dev, |
| 1072 | "mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n", | 968 | "mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n", |
| 1073 | mite_bytes_in_transit(devpriv->ai_mite_chan), | 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 | retval = -1; | 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 | for (i = 0; i < timeout; i++) { | 999 | for (i = 0; i < timeout; i++) { |
| 1104 | unsigned short b_status; | 1000 | unsigned short b_status; |
| 1105 | 1001 | ||
| 1106 | b_status = ni_stc_readw(dev, AO_Status_1_Register); | 1002 | b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); |
| 1107 | if (b_status & AO_FIFO_Half_Full_St) | 1003 | if (b_status & NISTC_AO_STATUS1_FIFO_HF) |
| 1108 | break; | 1004 | break; |
| 1109 | /* if we poll too often, the pci bus activity seems | 1005 | /* if we poll too often, the pci bus activity seems |
| 1110 | to slow the dma transfer down */ | 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 | i++; | 1035 | i++; |
| 1140 | packed_data |= (d << 16) & 0xffff0000; | 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 | } else { | 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 | unsigned int nsamples; | 1089 | unsigned int nsamples; |
| 1194 | 1090 | ||
| 1195 | /* reset fifo */ | 1091 | /* reset fifo */ |
| 1196 | ni_stc_writew(dev, 1, DAC_FIFO_Clear); | 1092 | ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG); |
| 1197 | if (devpriv->is_6xxx) | 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 | /* load some data */ | 1096 | /* load some data */ |
| 1201 | nbytes = comedi_buf_read_n_available(s); | 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 | if (devpriv->is_611x) { | 1119 | if (devpriv->is_611x) { |
| 1224 | for (i = 0; i < n / 2; i++) { | 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 | /* This may get the hi/lo data in the wrong order */ | 1122 | /* This may get the hi/lo data in the wrong order */ |
| 1227 | data = (dl >> 16) & 0xffff; | 1123 | data = (dl >> 16) & 0xffff; |
| 1228 | comedi_buf_write_samples(s, &data, 1); | 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 | /* Check if there's a single sample stuck in the FIFO */ | 1128 | /* Check if there's a single sample stuck in the FIFO */ |
| 1233 | if (n % 2) { | 1129 | if (n % 2) { |
| 1234 | dl = ni_readl(dev, ADC_FIFO_Data_611x); | 1130 | dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); |
| 1235 | data = dl & 0xffff; | 1131 | data = dl & 0xffff; |
| 1236 | comedi_buf_write_samples(s, &data, 1); | 1132 | comedi_buf_write_samples(s, &data, 1); |
| 1237 | } | 1133 | } |
| 1238 | } else if (devpriv->is_6143) { | 1134 | } else if (devpriv->is_6143) { |
| 1239 | /* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */ | 1135 | /* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */ |
| 1240 | for (i = 0; i < n / 2; i++) { | 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 | data = (dl >> 16) & 0xffff; | 1139 | data = (dl >> 16) & 0xffff; |
| 1244 | comedi_buf_write_samples(s, &data, 1); | 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 | if (n % 2) { | 1144 | if (n % 2) { |
| 1249 | /* Assume there is a single sample stuck in the FIFO */ | 1145 | /* Assume there is a single sample stuck in the FIFO */ |
| 1250 | /* Get stranded sample into FIFO */ | 1146 | /* Get stranded sample into FIFO */ |
| 1251 | ni_writel(dev, 0x01, AIFIFO_Control_6143); | 1147 | ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); |
| 1252 | dl = ni_readl(dev, AIFIFO_Data_6143); | 1148 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
| 1253 | data = (dl >> 16) & 0xffff; | 1149 | data = (dl >> 16) & 0xffff; |
| 1254 | comedi_buf_write_samples(s, &data, 1); | 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 | for (i = 0; i < n; i++) { | 1160 | for (i = 0; i < n; i++) { |
| 1265 | devpriv->ai_fifo_buffer[i] = | 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 | comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, n); | 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 | int i; | 1190 | int i; |
| 1295 | 1191 | ||
| 1296 | if (devpriv->is_611x) { | 1192 | if (devpriv->is_611x) { |
| 1297 | while ((ni_stc_readw(dev, AI_Status_1_Register) & | 1193 | while ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
| 1298 | AI_FIFO_Empty_St) == 0) { | 1194 | NISTC_AI_STATUS1_FIFO_E) == 0) { |
| 1299 | dl = ni_readl(dev, ADC_FIFO_Data_611x); | 1195 | dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); |
| 1300 | 1196 | ||
| 1301 | /* This may get the hi/lo data in the wrong order */ | 1197 | /* This may get the hi/lo data in the wrong order */ |
| 1302 | data = dl >> 16; | 1198 | data = dl >> 16; |
| @@ -1306,8 +1202,8 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) · 3 unmodified lines | |||
| 1306 | } | 1202 | } |
| 1307 | } else if (devpriv->is_6143) { | 1203 | } else if (devpriv->is_6143) { |
| 1308 | i = 0; | 1204 | i = 0; |
| 1309 | while (ni_readl(dev, AIFIFO_Status_6143) & 0x04) { | 1205 | while (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x04) { |
| 1310 | dl = ni_readl(dev, AIFIFO_Data_6143); | 1206 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
| 1311 | 1207 | ||
| 1312 | /* This may get the hi/lo data in the wrong order */ | 1208 | /* This may get the hi/lo data in the wrong order */ |
| 1313 | data = dl >> 16; | 1209 | data = dl >> 16; |
| @@ -1317,29 +1213,29 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) · 3 unmodified lines | |||
| 1317 | i += 2; | 1213 | i += 2; |
| 1318 | } | 1214 | } |
| 1319 | /* Check if stranded sample is present */ | 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 | /* Get stranded sample into FIFO */ | 1217 | /* Get stranded sample into FIFO */ |
| 1322 | ni_writel(dev, 0x01, AIFIFO_Control_6143); | 1218 | ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); |
| 1323 | dl = ni_readl(dev, AIFIFO_Data_6143); | 1219 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
| 1324 | data = (dl >> 16) & 0xffff; | 1220 | data = (dl >> 16) & 0xffff; |
| 1325 | comedi_buf_write_samples(s, &data, 1); | 1221 | comedi_buf_write_samples(s, &data, 1); |
| 1326 | } | 1222 | } |
| 1327 | 1223 | ||
| 1328 | } else { | 1224 | } else { |
| 1329 | fifo_empty = ni_stc_readw(dev, AI_Status_1_Register) & | 1225 | fifo_empty = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
| 1330 | AI_FIFO_Empty_St; | 1226 | NISTC_AI_STATUS1_FIFO_E; |
| 1331 | while (fifo_empty == 0) { | 1227 | while (fifo_empty == 0) { |
| 1332 | for (i = 0; | 1228 | for (i = 0; |
| 1333 | i < | 1229 | i < |
| 1334 | sizeof(devpriv->ai_fifo_buffer) / | 1230 | sizeof(devpriv->ai_fifo_buffer) / |
| 1335 | sizeof(devpriv->ai_fifo_buffer[0]); i++) { | 1231 | sizeof(devpriv->ai_fifo_buffer[0]); i++) { |
| 1336 | fifo_empty = ni_stc_readw(dev, | 1232 | fifo_empty = ni_stc_readw(dev, |
| 1337 | AI_Status_1_Register) & | 1233 | NISTC_AI_STATUS1_REG) & |
| 1338 | AI_FIFO_Empty_St; | 1234 | NISTC_AI_STATUS1_FIFO_E; |
| 1339 | if (fifo_empty) | 1235 | if (fifo_empty) |
| 1340 | break; | 1236 | break; |
| 1341 | devpriv->ai_fifo_buffer[i] = | 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 | comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, i); | 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 | return; | 1253 | return; |
| 1358 | 1254 | ||
| 1359 | /* Check if there's a single sample stuck in the FIFO */ | 1255 | /* Check if there's a single sample stuck in the FIFO */ |
| 1360 | if (ni_readb(dev, XXX_Status) & 0x80) { | 1256 | if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { |
| 1361 | dl = ni_readl(dev, ADC_FIFO_Data_611x); | 1257 | dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); |
| 1362 | data = dl & 0xffff; | 1258 | data = dl & 0xffff; |
| 1363 | comedi_buf_write_samples(s, &data, 1); | 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 | return; | 1271 | return; |
| 1376 | 1272 | ||
| 1377 | /* Check if there's a single sample stuck in the FIFO */ | 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 | /* Get stranded sample into FIFO */ | 1275 | /* Get stranded sample into FIFO */ |
| 1380 | ni_writel(dev, 0x01, AIFIFO_Control_6143); | 1276 | ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG); |
| 1381 | dl = ni_readl(dev, AIFIFO_Data_6143); | 1277 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
| 1382 | 1278 | ||
| 1383 | /* This may get the hi/lo data in the wrong order */ | 1279 | /* This may get the hi/lo data in the wrong order */ |
| 1384 | data = (dl >> 16) & 0xffff; | 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 | s->async->events |= COMEDI_CB_EOS; | 1316 | s->async->events |= COMEDI_CB_EOS; |
| 1421 | #endif | 1317 | #endif |
| 1422 | } | 1318 | } |
| 1423 | /* handle special case of single scan using AI_End_On_End_Of_Scan */ | 1319 | /* handle special case of single scan */ |
| 1424 | if ((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) | 1320 | if (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS) |
| 1425 | shutdown_ai_command(dev); | 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 | unsigned short ack = 0; | 1341 | unsigned short ack = 0; |
| 1446 | 1342 | ||
| 1447 | if (a_status & AI_SC_TC_St) | 1343 | if (a_status & NISTC_AI_STATUS1_SC_TC) |
| 1448 | ack |= AI_SC_TC_Interrupt_Ack; | 1344 | ack |= NISTC_INTA_ACK_AI_SC_TC; |
| 1449 | if (a_status & AI_START1_St) | 1345 | if (a_status & NISTC_AI_STATUS1_START1) |
| 1450 | ack |= AI_START1_Interrupt_Ack; | 1346 | ack |= NISTC_INTA_ACK_AI_START1; |
| 1451 | if (a_status & AI_START_St) | 1347 | if (a_status & NISTC_AI_STATUS1_START) |
| 1452 | ack |= AI_START_Interrupt_Ack; | 1348 | ack |= NISTC_INTA_ACK_AI_START; |
| 1453 | if (a_status & AI_STOP_St) | 1349 | if (a_status & NISTC_AI_STATUS1_STOP) |
| 1454 | /* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */ | 1350 | ack |= NISTC_INTA_ACK_AI_STOP; |
| 1455 | ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack */; | ||
| 1456 | if (ack) | 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 | static void handle_a_interrupt(struct comedi_device *dev, unsigned short status, | 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 | #endif | 1378 | #endif |
| 1484 | 1379 | ||
| 1485 | /* test for all uncommon interrupt events at the same time */ | 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 | | 1381 | if (status & (NISTC_AI_STATUS1_ERR | |
| 1487 | AI_SC_TC_St | AI_START1_St)) { | 1382 | NISTC_AI_STATUS1_SC_TC | NISTC_AI_STATUS1_START1)) { |
| 1488 | if (status == 0xffff) { | 1383 | if (status == 0xffff) { |
| 1489 | dev_err(dev->class_dev, "Card removed?\n"); | 1384 | dev_err(dev->class_dev, "Card removed?\n"); |
| 1490 | /* we probably aren't even running a command now, | 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 | return; | 1391 | return; |
| 1497 | } | 1392 | } |
| 1498 | if (status & (AI_Overrun_St | AI_Overflow_St | | 1393 | if (status & NISTC_AI_STATUS1_ERR) { |
| 1499 | AI_SC_TC_Error_St)) { | ||
| 1500 | dev_err(dev->class_dev, "ai error a_status=%04x\n", | 1394 | dev_err(dev->class_dev, "ai error a_status=%04x\n", |
| 1501 | status); | 1395 | status); |
| 1502 | 1396 | ||
| 1503 | shutdown_ai_command(dev); | 1397 | shutdown_ai_command(dev); |
| 1504 | 1398 | ||
| 1505 | s->async->events |= COMEDI_CB_ERROR; | 1399 | s->async->events |= COMEDI_CB_ERROR; |
| 1506 | if (status & (AI_Overrun_St | AI_Overflow_St)) | 1400 | if (status & NISTC_AI_STATUS1_OVER) |
| 1507 | s->async->events |= COMEDI_CB_OVERFLOW; | 1401 | s->async->events |= COMEDI_CB_OVERFLOW; |
| 1508 | 1402 | ||
| 1509 | comedi_handle_events(dev, s); | 1403 | comedi_handle_events(dev, s); |
| 1510 | return; | 1404 | return; |
| 1511 | } | 1405 | } |
| 1512 | if (status & AI_SC_TC_St) { | 1406 | if (status & NISTC_AI_STATUS1_SC_TC) { |
| 1513 | if (cmd->stop_src == TRIG_COUNT) | 1407 | if (cmd->stop_src == TRIG_COUNT) |
| 1514 | shutdown_ai_command(dev); | 1408 | shutdown_ai_command(dev); |
| 1515 | } | 1409 | } |
| 1516 | } | 1410 | } |
| 1517 | #ifndef PCIDMA | 1411 | #ifndef PCIDMA |
| 1518 | if (status & AI_FIFO_Half_Full_St) { | 1412 | if (status & NISTC_AI_STATUS1_FIFO_HF) { |
| 1519 | int i; | 1413 | int i; |
| 1520 | static const int timeout = 10; | 1414 | static const int timeout = 10; |
| 1521 | /* pcmcia cards (at least 6036) seem to stop producing interrupts if we | 1415 | /* pcmcia cards (at least 6036) seem to stop producing interrupts if we |
| 1522 | *fail to get the fifo less than half full, so loop to be sure.*/ | 1416 | *fail to get the fifo less than half full, so loop to be sure.*/ |
| 1523 | for (i = 0; i < timeout; ++i) { | 1417 | for (i = 0; i < timeout; ++i) { |
| 1524 | ni_handle_fifo_half_full(dev); | 1418 | ni_handle_fifo_half_full(dev); |
| 1525 | if ((ni_stc_readw(dev, AI_Status_1_Register) & | 1419 | if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
| 1526 | AI_FIFO_Half_Full_St) == 0) | 1420 | NISTC_AI_STATUS1_FIFO_HF) == 0) |
| 1527 | break; | 1421 | break; |
| 1528 | } | 1422 | } |
| 1529 | } | 1423 | } |
| 1530 | #endif /* !PCIDMA */ | 1424 | #endif /* !PCIDMA */ |
| 1531 | 1425 | ||
| 1532 | if ((status & AI_STOP_St)) | 1426 | if (status & NISTC_AI_STATUS1_STOP) |
| 1533 | ni_handle_eos(dev, s); | 1427 | ni_handle_eos(dev, s); |
| 1534 | 1428 | ||
| 1535 | comedi_handle_events(dev, s); | 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 | unsigned short ack = 0; | 1434 | unsigned short ack = 0; |
| 1541 | 1435 | ||
| 1542 | if (b_status & AO_BC_TC_St) | 1436 | if (b_status & NISTC_AO_STATUS1_BC_TC) |
| 1543 | ack |= AO_BC_TC_Interrupt_Ack; | 1437 | ack |= NISTC_INTB_ACK_AO_BC_TC; |
| 1544 | if (b_status & AO_Overrun_St) | 1438 | if (b_status & NISTC_AO_STATUS1_OVERRUN) |
| 1545 | ack |= AO_Error_Interrupt_Ack; | 1439 | ack |= NISTC_INTB_ACK_AO_ERR; |
| 1546 | if (b_status & AO_START_St) | 1440 | if (b_status & NISTC_AO_STATUS1_START) |
| 1547 | ack |= AO_START_Interrupt_Ack; | 1441 | ack |= NISTC_INTB_ACK_AO_START; |
| 1548 | if (b_status & AO_START1_St) | 1442 | if (b_status & NISTC_AO_STATUS1_START1) |
| 1549 | ack |= AO_START1_Interrupt_Ack; | 1443 | ack |= NISTC_INTB_ACK_AO_START1; |
| 1550 | if (b_status & AO_UC_TC_St) | 1444 | if (b_status & NISTC_AO_STATUS1_UC_TC) |
| 1551 | ack |= AO_UC_TC_Interrupt_Ack; | 1445 | ack |= NISTC_INTB_ACK_AO_UC_TC; |
| 1552 | if (b_status & AO_UI2_TC_St) | 1446 | if (b_status & NISTC_AO_STATUS1_UI2_TC) |
| 1553 | ack |= AO_UI2_TC_Interrupt_Ack; | 1447 | ack |= NISTC_INTB_ACK_AO_UI2_TC; |
| 1554 | if (b_status & AO_UPDATE_St) | 1448 | if (b_status & NISTC_AO_STATUS1_UPDATE) |
| 1555 | ack |= AO_UPDATE_Interrupt_Ack; | 1449 | ack |= NISTC_INTB_ACK_AO_UPDATE; |
| 1556 | if (ack) | 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 | static void handle_b_interrupt(struct comedi_device *dev, | 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 | if (b_status == 0xffff) | 1478 | if (b_status == 0xffff) |
| 1585 | return; | 1479 | return; |
| 1586 | if (b_status & AO_Overrun_St) { | 1480 | if (b_status & NISTC_AO_STATUS1_OVERRUN) { |
| 1587 | dev_err(dev->class_dev, | 1481 | dev_err(dev->class_dev, |
| 1588 | "AO FIFO underrun status=0x%04x status2=0x%04x\n", | 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 | s->async->events |= COMEDI_CB_OVERFLOW; | 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 | s->async->events |= COMEDI_CB_EOA; | 1488 | s->async->events |= COMEDI_CB_EOA; |
| 1595 | 1489 | ||
| 1596 | #ifndef PCIDMA | 1490 | #ifndef PCIDMA |
| 1597 | if (b_status & AO_FIFO_Request_St) { | 1491 | if (b_status & NISTC_AO_STATUS1_FIFO_REQ) { |
| 1598 | int ret; | 1492 | int ret; |
| 1599 | 1493 | ||
| 1600 | ret = ni_ao_fifo_half_empty(dev, s); | 1494 | ret = ni_ao_fifo_half_empty(dev, s); |
| 1601 | if (!ret) { | 1495 | if (!ret) { |
| 1602 | dev_err(dev->class_dev, "AO buffer underrun\n"); | 1496 | dev_err(dev->class_dev, "AO buffer underrun\n"); |
| 1603 | ni_set_bits(dev, Interrupt_B_Enable_Register, | 1497 | ni_set_bits(dev, NISTC_INTB_ENA_REG, |
| 1604 | AO_FIFO_Interrupt_Enable | | 1498 | NISTC_INTB_ENA_AO_FIFO | |
| 1605 | AO_Error_Interrupt_Enable, 0); | 1499 | NISTC_INTB_ENA_AO_ERR, 0); |
| 1606 | s->async->events |= COMEDI_CB_OVERFLOW; | 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 | static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) | 1612 | static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) |
| 1719 | { | 1613 | { |
| 1720 | struct ni_private *devpriv = dev->private; | 1614 | struct ni_private *devpriv = dev->private; |
| 1615 | unsigned ai_personal; | ||
| 1616 | unsigned ai_out_ctrl; | ||
| 1721 | 1617 | ||
| 1722 | ni_release_ai_mite_channel(dev); | 1618 | ni_release_ai_mite_channel(dev); |
| 1723 | /* ai configuration */ | 1619 | /* ai configuration */ |
| 1724 | ni_stc_writew(dev, AI_Configuration_Start | AI_Reset, | 1620 | ni_stc_writew(dev, NISTC_RESET_AI_CFG_START | NISTC_RESET_AI, |
| 1725 | Joint_Reset_Register); | 1621 | NISTC_RESET_REG); |
| 1726 | 1622 | ||
| 1727 | ni_set_bits(dev, Interrupt_A_Enable_Register, | 1623 | ni_set_bits(dev, NISTC_INTA_ENA_REG, NISTC_INTA_ENA_AI_MASK, 0); |
| 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); | ||
| 1732 | 1624 | ||
| 1733 | ni_clear_ai_fifo(dev); | 1625 | ni_clear_ai_fifo(dev); |
| 1734 | 1626 | ||
| 1735 | if (!devpriv->is_6143) | 1627 | if (!devpriv->is_6143) |
| 1736 | ni_writeb(dev, 0, Misc_Command); | 1628 | ni_writeb(dev, NI_E_MISC_CMD_EXT_ATRIG, NI_E_MISC_CMD_REG); |
| 1737 | 1629 | ||
| 1738 | ni_stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */ | 1630 | ni_stc_writew(dev, NISTC_AI_CMD1_DISARM, NISTC_AI_CMD1_REG); |
| 1739 | ni_stc_writew(dev, AI_Start_Stop | AI_Mode_1_Reserved | 1631 | ni_stc_writew(dev, NISTC_AI_MODE1_START_STOP | |
| 1740 | /*| AI_Trigger_Once */, | 1632 | NISTC_AI_MODE1_RSVD |
| 1741 | AI_Mode_1_Register); | 1633 | /*| NISTC_AI_MODE1_TRIGGER_ONCE */, |
| 1742 | ni_stc_writew(dev, 0x0000, AI_Mode_2_Register); | 1634 | NISTC_AI_MODE1_REG); |
| 1635 | ni_stc_writew(dev, 0, NISTC_AI_MODE2_REG); | ||
| 1743 | /* generate FIFO interrupts on non-empty */ | 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 | if (devpriv->is_611x) { | 1647 | if (devpriv->is_611x) { |
| 1746 | ni_stc_writew(dev, | 1648 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; |
| 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); | ||
| 1759 | } else if (devpriv->is_6143) { | 1649 | } else if (devpriv->is_6143) { |
| 1760 | ni_stc_writew(dev, AI_SHIFTIN_Pulse_Width | | 1650 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; |
| 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); | ||
| 1772 | } else { | 1651 | } else { |
| 1773 | unsigned ai_output_control_bits; | 1652 | ai_personal |= NISTC_AI_PERSONAL_CONVERT_PW; |
| 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); | ||
| 1786 | if (devpriv->is_622x) | 1653 | if (devpriv->is_622x) |
| 1787 | ai_output_control_bits |= | 1654 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; |
| 1788 | AI_CONVERT_Output_Select | ||
| 1789 | (AI_CONVERT_Output_Enable_High); | ||
| 1790 | else | 1655 | else |
| 1791 | ai_output_control_bits |= | 1656 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; |
| 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); | ||
| 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 | /* the following registers should not be changed, because there | 1661 | /* the following registers should not be changed, because there |
| 1798 | * are no backup registers in devpriv. If you want to change | 1662 | * are no backup registers in devpriv. If you want to change |
| 1799 | * any of these, add a backup register and other appropriate code: | 1663 | * any of these, add a backup register and other appropriate code: |
| 1800 | * AI_Mode_1_Register | 1664 | * NISTC_AI_MODE1_REG |
| 1801 | * AI_Mode_3_Register | 1665 | * NISTC_AI_MODE3_REG |
| 1802 | * AI_Personal_Register | 1666 | * NISTC_AI_PERSONAL_REG |
| 1803 | * AI_Output_Control_Register | 1667 | * NISTC_AI_OUT_CTRL_REG |
| 1804 | */ | 1668 | */ |
| 1805 | ni_stc_writew(dev, | 1669 | |
| 1806 | AI_SC_TC_Error_Confirm | | 1670 | /* clear interrupts */ |
| 1807 | AI_START_Interrupt_Ack | | 1671 | ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); |
| 1808 | AI_START2_Interrupt_Ack | | 1672 | |
| 1809 | AI_START1_Interrupt_Ack | | 1673 | ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG); |
| 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); | ||
| 1816 | 1674 | ||
| 1817 | return 0; | 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 | int i; | 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 | for (i = 0; i < NI_TIMEOUT; ++i) { | 1701 | for (i = 0; i < NI_TIMEOUT; ++i) { |
| 1844 | if (!(ni_stc_readw(dev, AI_Status_1_Register) & | 1702 | if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
| 1845 | AI_FIFO_Empty_St)) { | 1703 | NISTC_AI_STATUS1_FIFO_E)) { |
| 1846 | ni_stc_writew(dev, 1, ADC_FIFO_Clear); | 1704 | ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG); |
| 1847 | return; | 1705 | return; |
| 1848 | } | 1706 | } |
| 1849 | udelay(1); | 1707 | udelay(1); |
| @@ -1862,7 +1720,7 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, · 12 unmodified lines | |||
| 1862 | unsigned int dither; | 1720 | unsigned int dither; |
| 1863 | unsigned range_code; | 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 | if ((list[0] & CR_ALT_SOURCE)) { | 1725 | if ((list[0] & CR_ALT_SOURCE)) { |
| 1868 | unsigned bypass_bits; | 1726 | unsigned bypass_bits; |
| @@ -1871,22 +1729,17 @@ static void ni_m_series_load_channelgain_list(struct comedi_device *dev, · 2 unmodified lines | |||
| 1871 | range = CR_RANGE(list[0]); | 1729 | range = CR_RANGE(list[0]); |
| 1872 | range_code = ni_gainlkup[board->gainlkup][range]; | 1730 | range_code = ni_gainlkup[board->gainlkup][range]; |
| 1873 | dither = (list[0] & CR_ALT_FILTER) != 0; | 1731 | dither = (list[0] & CR_ALT_FILTER) != 0; |
| 1874 | bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit; | 1732 | bypass_bits = NI_M_CFG_BYPASS_FIFO | |
| 1875 | bypass_bits |= chan; | 1733 | NI_M_CFG_BYPASS_AI_CHAN(chan) | |
| 1876 | bypass_bits |= | 1734 | NI_M_CFG_BYPASS_AI_GAIN(range_code) | |
| 1877 | (devpriv->ai_calib_source) & | 1735 | 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); | ||
| 1883 | if (dither) | 1736 | if (dither) |
| 1884 | bypass_bits |= MSeries_AI_Bypass_Dither_Bit; | 1737 | bypass_bits |= NI_M_CFG_BYPASS_AI_DITHER; |
| 1885 | /* don't use 2's complement encoding */ | 1738 | /* don't use 2's complement encoding */ |
| 1886 | bypass_bits |= MSeries_AI_Bypass_Polarity_Bit; | 1739 | bypass_bits |= NI_M_CFG_BYPASS_AI_POLARITY; |
| 1887 | ni_writel(dev, bypass_bits, M_Offset_AI_Config_FIFO_Bypass); | 1740 | ni_writel(dev, bypass_bits, NI_M_CFG_BYPASS_FIFO_REG); |
| 1888 | } else { | 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 | for (i = 0; i < n_chan; i++) { | 1744 | for (i = 0; i < n_chan; i++) { |
| 1892 | unsigned config_bits = 0; | 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 | devpriv->ai_offset[i] = 0; | 1753 | devpriv->ai_offset[i] = 0; |
| 1901 | switch (aref) { | 1754 | switch (aref) { |
| 1902 | case AREF_DIFF: | 1755 | case AREF_DIFF: |
| 1903 | config_bits |= | 1756 | config_bits |= NI_M_AI_CFG_CHAN_TYPE_DIFF; |
| 1904 | MSeries_AI_Config_Channel_Type_Differential_Bits; | ||
| 1905 | break; | 1757 | break; |
| 1906 | case AREF_COMMON: | 1758 | case AREF_COMMON: |
| 1907 | config_bits |= | 1759 | config_bits |= NI_M_AI_CFG_CHAN_TYPE_COMMON; |
| 1908 | MSeries_AI_Config_Channel_Type_Common_Ref_Bits; | ||
| 1909 | break; | 1760 | break; |
| 1910 | case AREF_GROUND: | 1761 | case AREF_GROUND: |
| 1911 | config_bits |= | 1762 | config_bits |= NI_M_AI_CFG_CHAN_TYPE_GROUND; |
| 1912 | MSeries_AI_Config_Channel_Type_Ground_Ref_Bits; | ||
| 1913 | break; | 1763 | break; |
| 1914 | case AREF_OTHER: | 1764 | case AREF_OTHER: |
| 1915 | break; | 1765 | break; |
| 1916 | } | 1766 | } |
| 1917 | config_bits |= MSeries_AI_Config_Channel_Bits(chan); | 1767 | config_bits |= NI_M_AI_CFG_CHAN_SEL(chan); |
| 1918 | config_bits |= | 1768 | config_bits |= NI_M_AI_CFG_BANK_SEL(chan); |
| 1919 | MSeries_AI_Config_Bank_Bits(board->reg_type, chan); | 1769 | config_bits |= NI_M_AI_CFG_GAIN(range_code); |
| 1920 | config_bits |= MSeries_AI_Config_Gain_Bits(range_code); | ||
| 1921 | if (i == n_chan - 1) | 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 | if (dither) | 1772 | if (dither) |
| 1924 | config_bits |= MSeries_AI_Config_Dither_Bit; | 1773 | config_bits |= NI_M_AI_CFG_DITHER; |
| 1925 | /* don't use 2's complement encoding */ | 1774 | /* don't use 2's complement encoding */ |
| 1926 | config_bits |= MSeries_AI_Config_Polarity_Bit; | 1775 | config_bits |= NI_M_AI_CFG_POLARITY; |
| 1927 | ni_writew(dev, config_bits, M_Offset_AI_Config_FIFO_Data); | 1776 | ni_writew(dev, config_bits, NI_M_AI_CFG_FIFO_DATA_REG); |
| 1928 | } | 1777 | } |
| 1929 | ni_prime_channelgain_list(dev); | 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 | devpriv->changain_state = 0; | 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 | /* Set up Calibration mode if required */ | 1840 | /* Set up Calibration mode if required */ |
| 1992 | if (devpriv->is_6143) { | 1841 | if (devpriv->is_6143) { |
| @@ -1994,20 +1843,20 @@ static void ni_load_channelgain_list(struct comedi_device *dev, · 1 unmodified line | |||
| 1994 | && !devpriv->ai_calib_source_enabled) { | 1843 | && !devpriv->ai_calib_source_enabled) { |
| 1995 | /* Strobe Relay enable bit */ | 1844 | /* Strobe Relay enable bit */ |
| 1996 | ni_writew(dev, devpriv->ai_calib_source | | 1845 | ni_writew(dev, devpriv->ai_calib_source | |
| 1997 | Calibration_Channel_6143_RelayOn, | 1846 | NI6143_CALIB_CHAN_RELAY_ON, |
| 1998 | Calibration_Channel_6143); | 1847 | NI6143_CALIB_CHAN_REG); |
| 1999 | ni_writew(dev, devpriv->ai_calib_source, | 1848 | ni_writew(dev, devpriv->ai_calib_source, |
| 2000 | Calibration_Channel_6143); | 1849 | NI6143_CALIB_CHAN_REG); |
| 2001 | devpriv->ai_calib_source_enabled = 1; | 1850 | devpriv->ai_calib_source_enabled = 1; |
| 2002 | msleep_interruptible(100); /* Allow relays to change */ | 1851 | msleep_interruptible(100); /* Allow relays to change */ |
| 2003 | } else if (!(list[0] & CR_ALT_SOURCE) | 1852 | } else if (!(list[0] & CR_ALT_SOURCE) |
| 2004 | && devpriv->ai_calib_source_enabled) { | 1853 | && devpriv->ai_calib_source_enabled) { |
| 2005 | /* Strobe Relay disable bit */ | 1854 | /* Strobe Relay disable bit */ |
| 2006 | ni_writew(dev, devpriv->ai_calib_source | | 1855 | ni_writew(dev, devpriv->ai_calib_source | |
| 2007 | Calibration_Channel_6143_RelayOff, | 1856 | NI6143_CALIB_CHAN_RELAY_OFF, |
| 2008 | Calibration_Channel_6143); | 1857 | NI6143_CALIB_CHAN_REG); |
| 2009 | ni_writew(dev, devpriv->ai_calib_source, | 1858 | ni_writew(dev, devpriv->ai_calib_source, |
| 2010 | Calibration_Channel_6143); | 1859 | NI6143_CALIB_CHAN_REG); |
| 2011 | devpriv->ai_calib_source_enabled = 0; | 1860 | devpriv->ai_calib_source_enabled = 0; |
| 2012 | msleep_interruptible(100); /* Allow relays to change */ | 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 | if ((list[i] & CR_ALT_SOURCE)) { | 1882 | if ((list[i] & CR_ALT_SOURCE)) { |
| 2034 | if (devpriv->is_611x) | 1883 | if (devpriv->is_611x) |
| 2035 | ni_writew(dev, CR_CHAN(list[i]) & 0x0003, | 1884 | ni_writew(dev, CR_CHAN(list[i]) & 0x0003, |
| 2036 | Calibration_Channel_Select_611x); | 1885 | NI611X_CALIB_CHAN_SEL_REG); |
| 2037 | } else { | 1886 | } else { |
| 2038 | if (devpriv->is_611x) | 1887 | if (devpriv->is_611x) |
| 2039 | aref = AREF_DIFF; | 1888 | aref = AREF_DIFF; |
| @@ -2041,30 +1890,31 @@ static void ni_load_channelgain_list(struct comedi_device *dev, · 1 unmodified line | |||
| 2041 | aref = AREF_OTHER; | 1890 | aref = AREF_OTHER; |
| 2042 | switch (aref) { | 1891 | switch (aref) { |
| 2043 | case AREF_DIFF: | 1892 | case AREF_DIFF: |
| 2044 | hi |= AI_DIFFERENTIAL; | 1893 | hi |= NI_E_AI_CFG_HI_TYPE_DIFF; |
| 2045 | break; | 1894 | break; |
| 2046 | case AREF_COMMON: | 1895 | case AREF_COMMON: |
| 2047 | hi |= AI_COMMON; | 1896 | hi |= NI_E_AI_CFG_HI_TYPE_COMMON; |
| 2048 | break; | 1897 | break; |
| 2049 | case AREF_GROUND: | 1898 | case AREF_GROUND: |
| 2050 | hi |= AI_GROUND; | 1899 | hi |= NI_E_AI_CFG_HI_TYPE_GROUND; |
| 2051 | break; | 1900 | break; |
| 2052 | case AREF_OTHER: | 1901 | case AREF_OTHER: |
| 2053 | break; | 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 | if (!devpriv->is_6143) { | 1909 | if (!devpriv->is_6143) { |
| 2061 | lo = range; | 1910 | lo = NI_E_AI_CFG_LO_GAIN(range); |
| 1911 | |||
| 2062 | if (i == n_chan - 1) | 1912 | if (i == n_chan - 1) |
| 2063 | lo |= AI_LAST_CHANNEL; | 1913 | lo |= NI_E_AI_CFG_LO_LAST_CHAN; |
| 2064 | if (dither) | 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 | signbits = devpriv->ai_offset[0]; | 1942 | signbits = devpriv->ai_offset[0]; |
| 2093 | if (devpriv->is_611x) { | 1943 | if (devpriv->is_611x) { |
| 2094 | for (n = 0; n < num_adc_stages_611x; n++) { | 1944 | for (n = 0; n < num_adc_stages_611x; n++) { |
| 2095 | ni_stc_writew(dev, AI_CONVERT_Pulse, | 1945 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
| 2096 | AI_Command_1_Register); | 1946 | NISTC_AI_CMD1_REG); |
| 2097 | udelay(1); | 1947 | udelay(1); |
| 2098 | } | 1948 | } |
| 2099 | for (n = 0; n < insn->n; n++) { | 1949 | for (n = 0; n < insn->n; n++) { |
| 2100 | ni_stc_writew(dev, AI_CONVERT_Pulse, | 1950 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
| 2101 | AI_Command_1_Register); | 1951 | NISTC_AI_CMD1_REG); |
| 2102 | /* The 611x has screwy 32-bit FIFOs. */ | 1952 | /* The 611x has screwy 32-bit FIFOs. */ |
| 2103 | d = 0; | 1953 | d = 0; |
| 2104 | for (i = 0; i < NI_TIMEOUT; i++) { | 1954 | for (i = 0; i < NI_TIMEOUT; i++) { |
| 2105 | if (ni_readb(dev, XXX_Status) & 0x80) { | 1955 | if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { |
| 2106 | d = ni_readl(dev, ADC_FIFO_Data_611x); | 1956 | d = ni_readl(dev, |
| 1957 | NI611X_AI_FIFO_DATA_REG); | ||
| 2107 | d >>= 16; | 1958 | d >>= 16; |
| 2108 | d &= 0xffff; | 1959 | d &= 0xffff; |
| 2109 | break; | 1960 | break; |
| 2110 | } | 1961 | } |
| 2111 | if (!(ni_stc_readw(dev, AI_Status_1_Register) & | 1962 | if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
| 2112 | AI_FIFO_Empty_St)) { | 1963 | NISTC_AI_STATUS1_FIFO_E)) { |
| 2113 | d = ni_readl(dev, ADC_FIFO_Data_611x); | 1964 | d = ni_readl(dev, |
| 1965 | NI611X_AI_FIFO_DATA_REG); | ||
| 2114 | d &= 0xffff; | 1966 | d &= 0xffff; |
| 2115 | break; | 1967 | break; |
| 2116 | } | 1968 | } |
| @@ -2124,17 +1976,19 @@ static int ni_ai_insn_read(struct comedi_device *dev, · 7 unmodified lines | |||
| 2124 | } | 1976 | } |
| 2125 | } else if (devpriv->is_6143) { | 1977 | } else if (devpriv->is_6143) { |
| 2126 | for (n = 0; n < insn->n; n++) { | 1978 | for (n = 0; n < insn->n; n++) { |
| 2127 | ni_stc_writew(dev, AI_CONVERT_Pulse, | 1979 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
| 2128 | AI_Command_1_Register); | 1980 | NISTC_AI_CMD1_REG); |
| 2129 | 1981 | ||
| 2130 | /* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */ | 1982 | /* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */ |
| 2131 | dl = 0; | 1983 | dl = 0; |
| 2132 | for (i = 0; i < NI_TIMEOUT; i++) { | 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 | /* Get stranded sample into FIFO */ | 1987 | /* Get stranded sample into FIFO */ |
| 2135 | ni_writel(dev, 0x01, | 1988 | ni_writel(dev, 0x01, |
| 2136 | AIFIFO_Control_6143); | 1989 | NI6143_AI_FIFO_CTRL_REG); |
| 2137 | dl = ni_readl(dev, AIFIFO_Data_6143); | 1990 | dl = ni_readl(dev, |
| 1991 | NI6143_AI_FIFO_DATA_REG); | ||
| 2138 | break; | 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 | } else { | 2001 | } else { |
| 2148 | for (n = 0; n < insn->n; n++) { | 2002 | for (n = 0; n < insn->n; n++) { |
| 2149 | ni_stc_writew(dev, AI_CONVERT_Pulse, | 2003 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
| 2150 | AI_Command_1_Register); | 2004 | NISTC_AI_CMD1_REG); |
| 2151 | for (i = 0; i < NI_TIMEOUT; i++) { | 2005 | for (i = 0; i < NI_TIMEOUT; i++) { |
| 2152 | if (!(ni_stc_readw(dev, AI_Status_1_Register) & | 2006 | if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
| 2153 | AI_FIFO_Empty_St)) | 2007 | NISTC_AI_STATUS1_FIFO_E)) |
| 2154 | break; | 2008 | break; |
| 2155 | } | 2009 | } |
| 2156 | if (i == NI_TIMEOUT) { | 2010 | if (i == NI_TIMEOUT) { |
| @@ -2158,11 +2012,11 @@ static int ni_ai_insn_read(struct comedi_device *dev, · 1 unmodified line | |||
| 2158 | return -ETIME; | 2012 | return -ETIME; |
| 2159 | } | 2013 | } |
| 2160 | if (devpriv->is_m_series) { | 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 | dl &= mask; | 2016 | dl &= mask; |
| 2163 | data[n] = dl; | 2017 | data[n] = dl; |
| 2164 | } else { | 2018 | } else { |
| 2165 | d = ni_readw(dev, ADC_FIFO_Data_Register); | 2019 | d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG); |
| 2166 | d += signbits; /* subtle: needs to be short addition */ | 2020 | d += signbits; /* subtle: needs to be short addition */ |
| 2167 | data[n] = d; | 2021 | data[n] = d; |
| 2168 | } | 2022 | } |
| @@ -2374,8 +2228,8 @@ static int ni_ai_inttrig(struct comedi_device *dev, · 205 unmodified lines | |||
| 2374 | if (trig_num != cmd->start_arg) | 2228 | if (trig_num != cmd->start_arg) |
| 2375 | return -EINVAL; | 2229 | return -EINVAL; |
| 2376 | 2230 | ||
| 2377 | ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, | 2231 | ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | devpriv->ai_cmd2, |
| 2378 | AI_Command_2_Register); | 2232 | NISTC_AI_CMD2_REG); |
| 2379 | s->async->inttrig = NULL; | 2233 | s->async->inttrig = NULL; |
| 2380 | 2234 | ||
| 2381 | return 1; | 2235 | return 1; |
| @@ -2391,6 +2245,7 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 9 unmodified lines | |||
| 2391 | int start_stop_select = 0; | 2245 | int start_stop_select = 0; |
| 2392 | unsigned int stop_count; | 2246 | unsigned int stop_count; |
| 2393 | int interrupt_a_enable = 0; | 2247 | int interrupt_a_enable = 0; |
| 2248 | unsigned ai_trig; | ||
| 2394 | 2249 | ||
| 2395 | if (dev->irq == 0) { | 2250 | if (dev->irq == 0) { |
| 2396 | dev_err(dev->class_dev, "cannot run command without an irq\n"); | 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 | ni_load_channelgain_list(dev, s, cmd->chanlist_len, cmd->chanlist); | 2256 | ni_load_channelgain_list(dev, s, cmd->chanlist_len, cmd->chanlist); |
| 2402 | 2257 | ||
| 2403 | /* start configuration */ | 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 | /* disable analog triggering for now, since it | 2261 | /* disable analog triggering for now, since it |
| 2407 | * interferes with the use of pfi0 */ | 2262 | * interferes with the use of pfi0 */ |
| 2408 | devpriv->an_trig_etc_reg &= ~Analog_Trigger_Enable; | 2263 | devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_ENA; |
| 2409 | ni_stc_writew(dev, devpriv->an_trig_etc_reg, | 2264 | ni_stc_writew(dev, devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG); |
| 2410 | Analog_Trigger_Etc_Register); | ||
| 2411 | 2265 | ||
| 2266 | ai_trig = NISTC_AI_TRIG_START2_SEL(0) | NISTC_AI_TRIG_START1_SYNC; | ||
| 2412 | switch (cmd->start_src) { | 2267 | switch (cmd->start_src) { |
| 2413 | case TRIG_INT: | 2268 | case TRIG_INT: |
| 2414 | case TRIG_NOW: | 2269 | case TRIG_NOW: |
| 2415 | ni_stc_writew(dev, | 2270 | ai_trig |= NISTC_AI_TRIG_START1_EDGE | |
| 2416 | AI_START2_Select(0) | | 2271 | NISTC_AI_TRIG_START1_SEL(0); |
| 2417 | AI_START1_Sync | AI_START1_Edge | | ||
| 2418 | AI_START1_Select(0), | ||
| 2419 | AI_Trigger_Select_Register); | ||
| 2420 | break; | 2272 | break; |
| 2421 | case TRIG_EXT: | 2273 | case TRIG_EXT: |
| 2422 | { | 2274 | ai_trig |= NISTC_AI_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + |
| 2423 | int chan = CR_CHAN(cmd->start_arg); | 2275 | 1); |
| 2424 | unsigned int bits = AI_START2_Select(0) | | 2276 | |
| 2425 | AI_START1_Sync | AI_START1_Select(chan + 1); | 2277 | if (cmd->start_arg & CR_INVERT) |
| 2426 | 2278 | ai_trig |= NISTC_AI_TRIG_START1_POLARITY; | |
| 2427 | if (cmd->start_arg & CR_INVERT) | 2279 | if (cmd->start_arg & CR_EDGE) |
| 2428 | bits |= AI_START1_Polarity; | 2280 | ai_trig |= NISTC_AI_TRIG_START1_EDGE; |
| 2429 | if (cmd->start_arg & CR_EDGE) | 2281 | break; |
| 2430 | bits |= AI_START1_Edge; | ||
| 2431 | ni_stc_writew(dev, bits, AI_Trigger_Select_Register); | ||
| 2432 | break; | ||
| 2433 | } | ||
| 2434 | } | 2282 | } |
| 2283 | ni_stc_writew(dev, ai_trig, NISTC_AI_TRIG_SEL_REG); | ||
| 2435 | 2284 | ||
| 2436 | mode2 &= ~AI_Pre_Trigger; | 2285 | mode2 &= ~NISTC_AI_MODE2_PRE_TRIGGER; |
| 2437 | mode2 &= ~AI_SC_Initial_Load_Source; | 2286 | mode2 &= ~NISTC_AI_MODE2_SC_INIT_LOAD_SRC; |
| 2438 | mode2 &= ~AI_SC_Reload_Mode; | 2287 | mode2 &= ~NISTC_AI_MODE2_SC_RELOAD_MODE; |
| 2439 | ni_stc_writew(dev, mode2, AI_Mode_2_Register); | 2288 | ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); |
| 2440 | 2289 | ||
| 2441 | if (cmd->chanlist_len == 1 || devpriv->is_611x || devpriv->is_6143) { | 2290 | if (cmd->chanlist_len == 1 || devpriv->is_611x || devpriv->is_6143) { |
| 2442 | start_stop_select |= AI_STOP_Polarity; | 2291 | /* logic low */ |
| 2443 | start_stop_select |= AI_STOP_Select(31); /* logic low */ | 2292 | start_stop_select |= NISTC_AI_STOP_POLARITY | |
| 2444 | start_stop_select |= AI_STOP_Sync; | 2293 | NISTC_AI_STOP_SEL(31) | |
| 2294 | NISTC_AI_STOP_SYNC; | ||
| 2445 | } else { | 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 | devpriv->ai_cmd2 = 0; | 2301 | devpriv->ai_cmd2 = 0; |
| 2451 | switch (cmd->stop_src) { | 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 | stop_count += num_adc_stages_611x; | 2308 | stop_count += num_adc_stages_611x; |
| 2458 | } | 2309 | } |
| 2459 | /* stage number of scans */ | 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; | 2313 | mode1 |= NISTC_AI_MODE1_START_STOP | |
| 2463 | ni_stc_writew(dev, mode1, AI_Mode_1_Register); | 2314 | NISTC_AI_MODE1_RSVD | |
| 2315 | NISTC_AI_MODE1_TRIGGER_ONCE; | ||
| 2316 | ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); | ||
| 2464 | /* load SC (Scan Count) */ | 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 | if (stop_count == 0) { | 2320 | if (stop_count == 0) { |
| 2468 | devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan; | 2321 | devpriv->ai_cmd2 |= NISTC_AI_CMD2_END_ON_EOS; |
| 2469 | interrupt_a_enable |= AI_STOP_Interrupt_Enable; | 2322 | interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; |
| 2470 | /* this is required to get the last sample for chanlist_len > 1, not sure why */ | 2323 | /* this is required to get the last sample for chanlist_len > 1, not sure why */ |
| 2471 | if (cmd->chanlist_len > 1) | 2324 | if (cmd->chanlist_len > 1) |
| 2472 | start_stop_select |= | 2325 | start_stop_select |= NISTC_AI_STOP_POLARITY | |
| 2473 | AI_STOP_Polarity | AI_STOP_Edge; | 2326 | NISTC_AI_STOP_EDGE; |
| 2474 | } | 2327 | } |
| 2475 | break; | 2328 | break; |
| 2476 | case TRIG_NONE: | 2329 | case TRIG_NONE: |
| 2477 | /* stage number of scans */ | 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; | 2333 | mode1 |= NISTC_AI_MODE1_START_STOP | |
| 2481 | ni_stc_writew(dev, mode1, AI_Mode_1_Register); | 2334 | NISTC_AI_MODE1_RSVD | |
| 2335 | NISTC_AI_MODE1_CONTINUOUS; | ||
| 2336 | ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); | ||
| 2482 | 2337 | ||
| 2483 | /* load SC (Scan Count) */ | 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 | break; | 2340 | break; |
| 2486 | } | 2341 | } |
| 2487 | 2342 | ||
| 2488 | switch (cmd->scan_begin_src) { | 2343 | switch (cmd->scan_begin_src) { |
| 2489 | case TRIG_TIMER: | 2344 | case TRIG_TIMER: |
| 2490 | /* | 2345 | /* |
| 2491 | stop bits for non 611x boards | 2346 | * stop bits for non 611x boards |
| 2492 | AI_SI_Special_Trigger_Delay=0 | 2347 | * NISTC_AI_MODE3_SI_TRIG_DELAY=0 |
| 2493 | AI_Pre_Trigger=0 | 2348 | * NISTC_AI_MODE2_PRE_TRIGGER=0 |
| 2494 | AI_START_STOP_Select_Register: | 2349 | * NISTC_AI_START_STOP_REG: |
| 2495 | AI_START_Polarity=0 (?) rising edge | 2350 | * NISTC_AI_START_POLARITY=0 (?) rising edge |
| 2496 | AI_START_Edge=1 edge triggered | 2351 | * NISTC_AI_START_EDGE=1 edge triggered |
| 2497 | AI_START_Sync=1 (?) | 2352 | * NISTC_AI_START_SYNC=1 (?) |
| 2498 | AI_START_Select=0 SI_TC | 2353 | * NISTC_AI_START_SEL=0 SI_TC |
| 2499 | AI_STOP_Polarity=0 rising edge | 2354 | * NISTC_AI_STOP_POLARITY=0 rising edge |
| 2500 | AI_STOP_Edge=0 level | 2355 | * NISTC_AI_STOP_EDGE=0 level |
| 2501 | AI_STOP_Sync=1 | 2356 | * NISTC_AI_STOP_SYNC=1 |
| 2502 | AI_STOP_Select=19 external pin (configuration mem) | 2357 | * NISTC_AI_STOP_SEL=19 external pin (configuration mem) |
| 2503 | */ | 2358 | */ |
| 2504 | start_stop_select |= AI_START_Edge | AI_START_Sync; | 2359 | start_stop_select |= NISTC_AI_START_EDGE | NISTC_AI_START_SYNC; |
| 2505 | ni_stc_writew(dev, start_stop_select, | 2360 | ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); |
| 2506 | AI_START_STOP_Select_Register); | ||
| 2507 | 2361 | ||
| 2508 | mode2 |= AI_SI_Reload_Mode(0); | 2362 | mode2 &= ~NISTC_AI_MODE2_SI_INIT_LOAD_SRC; /* A */ |
| 2509 | /* AI_SI_Initial_Load_Source=A */ | 2363 | mode2 |= NISTC_AI_MODE2_SI_RELOAD_MODE(0); |
| 2510 | mode2 &= ~AI_SI_Initial_Load_Source; | 2364 | /* mode2 |= NISTC_AI_MODE2_SC_RELOAD_MODE; */ |
| 2511 | /* mode2 |= AI_SC_Reload_Mode; */ | 2365 | ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); |
| 2512 | ni_stc_writew(dev, mode2, AI_Mode_2_Register); | ||
| 2513 | 2366 | ||
| 2514 | /* load SI */ | 2367 | /* load SI */ |
| 2515 | timer = ni_ns_to_timer(dev, cmd->scan_begin_arg, | 2368 | timer = ni_ns_to_timer(dev, cmd->scan_begin_arg, |
| 2516 | CMDF_ROUND_NEAREST); | 2369 | CMDF_ROUND_NEAREST); |
| 2517 | ni_stc_writel(dev, timer, AI_SI_Load_A_Registers); | 2370 | ni_stc_writel(dev, timer, NISTC_AI_SI_LOADA_REG); |
| 2518 | ni_stc_writew(dev, AI_SI_Load, AI_Command_1_Register); | 2371 | ni_stc_writew(dev, NISTC_AI_CMD1_SI_LOAD, NISTC_AI_CMD1_REG); |
| 2519 | break; | 2372 | break; |
| 2520 | case TRIG_EXT: | 2373 | case TRIG_EXT: |
| 2521 | if (cmd->scan_begin_arg & CR_EDGE) | 2374 | if (cmd->scan_begin_arg & CR_EDGE) |
| 2522 | start_stop_select |= AI_START_Edge; | 2375 | start_stop_select |= NISTC_AI_START_EDGE; |
| 2523 | /* AI_START_Polarity==1 is falling edge */ | 2376 | if (cmd->scan_begin_arg & CR_INVERT) /* falling edge */ |
| 2524 | if (cmd->scan_begin_arg & CR_INVERT) | 2377 | start_stop_select |= NISTC_AI_START_POLARITY; |
| 2525 | start_stop_select |= AI_START_Polarity; | ||
| 2526 | if (cmd->scan_begin_src != cmd->convert_src || | 2378 | if (cmd->scan_begin_src != cmd->convert_src || |
| 2527 | (cmd->scan_begin_arg & ~CR_EDGE) != | 2379 | (cmd->scan_begin_arg & ~CR_EDGE) != |
| 2528 | (cmd->convert_arg & ~CR_EDGE)) | 2380 | (cmd->convert_arg & ~CR_EDGE)) |
| 2529 | start_stop_select |= AI_START_Sync; | 2381 | start_stop_select |= NISTC_AI_START_SYNC; |
| 2530 | start_stop_select |= | 2382 | start_stop_select |= |
| 2531 | AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg)); | 2383 | NISTC_AI_START_SEL(1 + CR_CHAN(cmd->scan_begin_arg)); |
| 2532 | ni_stc_writew(dev, start_stop_select, | 2384 | ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG); |
| 2533 | AI_START_STOP_Select_Register); | ||
| 2534 | break; | 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 | timer = ni_ns_to_timer(dev, cmd->convert_arg, | 2394 | timer = ni_ns_to_timer(dev, cmd->convert_arg, |
| 2544 | CMDF_ROUND_NEAREST); | 2395 | CMDF_ROUND_NEAREST); |
| 2545 | /* 0,0 does not work */ | 2396 | /* 0,0 does not work */ |
| 2546 | ni_stc_writew(dev, 1, AI_SI2_Load_A_Register); | 2397 | ni_stc_writew(dev, 1, NISTC_AI_SI2_LOADA_REG); |
| 2547 | ni_stc_writew(dev, timer, AI_SI2_Load_B_Register); | 2398 | ni_stc_writew(dev, timer, NISTC_AI_SI2_LOADB_REG); |
| 2548 | 2399 | ||
| 2549 | /* AI_SI2_Reload_Mode = alternate */ | 2400 | mode2 &= ~NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* A */ |
| 2550 | /* AI_SI2_Initial_Load_Source = A */ | 2401 | mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ |
| 2551 | mode2 &= ~AI_SI2_Initial_Load_Source; | 2402 | ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); |
| 2552 | mode2 |= AI_SI2_Reload_Mode; | ||
| 2553 | ni_stc_writew(dev, mode2, AI_Mode_2_Register); | ||
| 2554 | 2403 | ||
| 2555 | /* AI_SI2_Load */ | 2404 | ni_stc_writew(dev, NISTC_AI_CMD1_SI2_LOAD, NISTC_AI_CMD1_REG); |
| 2556 | ni_stc_writew(dev, AI_SI2_Load, AI_Command_1_Register); | ||
| 2557 | 2405 | ||
| 2558 | mode2 |= AI_SI2_Reload_Mode; /* alternate */ | 2406 | mode2 |= NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* B */ |
| 2559 | mode2 |= AI_SI2_Initial_Load_Source; /* B */ | 2407 | mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ |
| 2560 | 2408 | ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); | |
| 2561 | ni_stc_writew(dev, mode2, AI_Mode_2_Register); | ||
| 2562 | break; | 2409 | break; |
| 2563 | case TRIG_EXT: | 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 | if ((cmd->convert_arg & CR_INVERT) == 0) | 2412 | if ((cmd->convert_arg & CR_INVERT) == 0) |
| 2566 | mode1 |= AI_CONVERT_Source_Polarity; | 2413 | mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY; |
| 2567 | ni_stc_writew(dev, mode1, AI_Mode_1_Register); | 2414 | ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG); |
| 2568 | 2415 | ||
| 2569 | mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable; | 2416 | mode2 |= NISTC_AI_MODE2_SC_GATE_ENA | |
| 2570 | ni_stc_writew(dev, mode2, AI_Mode_2_Register); | 2417 | NISTC_AI_MODE2_START_STOP_GATE_ENA; |
| 2418 | ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG); | ||
| 2571 | 2419 | ||
| 2572 | break; | 2420 | break; |
| 2573 | } | 2421 | } |
| 2574 | 2422 | ||
| 2575 | if (dev->irq) { | 2423 | if (dev->irq) { |
| 2576 | /* interrupt on FIFO, errors, SC_TC */ | 2424 | /* interrupt on FIFO, errors, SC_TC */ |
| 2577 | interrupt_a_enable |= AI_Error_Interrupt_Enable | | 2425 | interrupt_a_enable |= NISTC_INTA_ENA_AI_ERR | |
| 2578 | AI_SC_TC_Interrupt_Enable; | 2426 | NISTC_INTA_ENA_AI_SC_TC; |
| 2579 | 2427 | ||
| 2580 | #ifndef PCIDMA | 2428 | #ifndef PCIDMA |
| 2581 | interrupt_a_enable |= AI_FIFO_Interrupt_Enable; | 2429 | interrupt_a_enable |= NISTC_INTA_ENA_AI_FIFO; |
| 2582 | #endif | 2430 | #endif |
| 2583 | 2431 | ||
| 2584 | if (cmd->flags & CMDF_WAKE_EOS | 2432 | if ((cmd->flags & CMDF_WAKE_EOS) || |
| 2585 | || (devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) { | 2433 | (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS)) { |
| 2586 | /* wake on end-of-scan */ | 2434 | /* wake on end-of-scan */ |
| 2587 | devpriv->aimode = AIMODE_SCAN; | 2435 | devpriv->aimode = AIMODE_SCAN; |
| 2588 | } else { | 2436 | } else { |
| @@ -2593,66 +2441,60 @@ static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) · 4 unmodified lines | |||
| 2593 | case AIMODE_HALF_FULL: | 2441 | case AIMODE_HALF_FULL: |
| 2594 | /*generate FIFO interrupts and DMA requests on half-full */ | 2442 | /*generate FIFO interrupts and DMA requests on half-full */ |
| 2595 | #ifdef PCIDMA | 2443 | #ifdef PCIDMA |
| 2596 | ni_stc_writew(dev, AI_FIFO_Mode_HF_to_E, | 2444 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF_E, |
| 2597 | AI_Mode_3_Register); | 2445 | NISTC_AI_MODE3_REG); |
| 2598 | #else | 2446 | #else |
| 2599 | ni_stc_writew(dev, AI_FIFO_Mode_HF, | 2447 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, |
| 2600 | AI_Mode_3_Register); | 2448 | NISTC_AI_MODE3_REG); |
| 2601 | #endif | 2449 | #endif |
| 2602 | break; | 2450 | break; |
| 2603 | case AIMODE_SAMPLE: | 2451 | case AIMODE_SAMPLE: |
| 2604 | /*generate FIFO interrupts on non-empty */ | 2452 | /*generate FIFO interrupts on non-empty */ |
| 2605 | ni_stc_writew(dev, AI_FIFO_Mode_NE, | 2453 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, |
| 2606 | AI_Mode_3_Register); | 2454 | NISTC_AI_MODE3_REG); |
| 2607 | break; | 2455 | break; |
| 2608 | case AIMODE_SCAN: | 2456 | case AIMODE_SCAN: |
| 2609 | #ifdef PCIDMA | 2457 | #ifdef PCIDMA |
| 2610 | ni_stc_writew(dev, AI_FIFO_Mode_NE, | 2458 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, |
| 2611 | AI_Mode_3_Register); | 2459 | NISTC_AI_MODE3_REG); |
| 2612 | #else | 2460 | #else |
| 2613 | ni_stc_writew(dev, AI_FIFO_Mode_HF, | 2461 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, |
| 2614 | AI_Mode_3_Register); | 2462 | NISTC_AI_MODE3_REG); |
| 2615 | #endif | 2463 | #endif |
| 2616 | interrupt_a_enable |= AI_STOP_Interrupt_Enable; | 2464 | interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; |
| 2617 | break; | 2465 | break; |
| 2618 | default: | 2466 | default: |
| 2619 | break; | 2467 | break; |
| 2620 | } | 2468 | } |
| 2621 | 2469 | ||
| 2622 | /* clear interrupts */ | 2470 | /* clear interrupts */ |
| 2623 | ni_stc_writew(dev, | 2471 | ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); |
| 2624 | AI_Error_Interrupt_Ack | | 2472 | |
| 2625 | AI_STOP_Interrupt_Ack | | 2473 | ni_set_bits(dev, NISTC_INTA_ENA_REG, interrupt_a_enable, 1); |
| 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); | ||
| 2635 | } else { | 2474 | } else { |
| 2636 | /* interrupt on nothing */ | 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 | /* XXX start polling if necessary */ | 2478 | /* XXX start polling if necessary */ |
| 2640 | } | 2479 | } |
| 2641 | 2480 | ||
| 2642 | /* end configuration */ | 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 | switch (cmd->scan_begin_src) { | 2484 | switch (cmd->scan_begin_src) { |
| 2646 | case TRIG_TIMER: | 2485 | case TRIG_TIMER: |
| 2647 | ni_stc_writew(dev, | 2486 | ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | |
| 2648 | AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, | 2487 | NISTC_AI_CMD1_SI_ARM | |
| 2649 | AI_Command_1_Register); | 2488 | NISTC_AI_CMD1_DIV_ARM | |
| 2489 | NISTC_AI_CMD1_SC_ARM, | ||
| 2490 | NISTC_AI_CMD1_REG); | ||
| 2650 | break; | 2491 | break; |
| 2651 | case TRIG_EXT: | 2492 | case TRIG_EXT: |
| 2652 | /* XXX AI_SI_Arm? */ | 2493 | ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | |
| 2653 | ni_stc_writew(dev, | 2494 | NISTC_AI_CMD1_SI_ARM | /* XXX ? */ |
| 2654 | AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm, | 2495 | NISTC_AI_CMD1_DIV_ARM | |
| 2655 | AI_Command_1_Register); | 2496 | NISTC_AI_CMD1_SC_ARM, |
| 2497 | NISTC_AI_CMD1_REG); | ||
| 2656 | break; | 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 | #endif | 2508 | #endif |
| 2667 | 2509 | ||
| 2668 | if (cmd->start_src == TRIG_NOW) { | 2510 | if (cmd->start_src == TRIG_NOW) { |
| 2669 | /* AI_START1_Pulse */ | 2511 | ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | |
| 2670 | ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2, | 2512 | devpriv->ai_cmd2, |
| 2671 | AI_Command_2_Register); | 2513 | NISTC_AI_CMD2_REG); |
| 2672 | s->async->inttrig = NULL; | 2514 | s->async->inttrig = NULL; |
| 2673 | } else if (cmd->start_src == TRIG_EXT) { | 2515 | } else if (cmd->start_src == TRIG_EXT) { |
| 2674 | s->async->inttrig = NULL; | 2516 | s->async->inttrig = NULL; |
| @@ -2691,12 +2533,8 @@ static int ni_ai_insn_config(struct comedi_device *dev, · 16 unmodified lines | |||
| 2691 | switch (data[0]) { | 2533 | switch (data[0]) { |
| 2692 | case INSN_CONFIG_ALT_SOURCE: | 2534 | case INSN_CONFIG_ALT_SOURCE: |
| 2693 | if (devpriv->is_m_series) { | 2535 | if (devpriv->is_m_series) { |
| 2694 | if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask | | 2536 | if (data[1] & ~NI_M_CFG_BYPASS_AI_CAL_MASK) |
| 2695 | MSeries_AI_Bypass_Cal_Sel_Neg_Mask | | ||
| 2696 | MSeries_AI_Bypass_Mode_Mux_Mask | | ||
| 2697 | MSeries_AO_Bypass_AO_Cal_Sel_Mask)) { | ||
| 2698 | return -EINVAL; | 2537 | return -EINVAL; |
| 2699 | } | ||
| 2700 | devpriv->ai_calib_source = data[1]; | 2538 | devpriv->ai_calib_source = data[1]; |
| 2701 | } else if (devpriv->is_6143) { | 2539 | } else if (devpriv->is_6143) { |
| 2702 | unsigned int calib_source; | 2540 | unsigned int calib_source; |
| @@ -2704,7 +2542,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, · 1 unmodified line | |||
| 2704 | calib_source = data[1] & 0xf; | 2542 | calib_source = data[1] & 0xf; |
| 2705 | 2543 | ||
| 2706 | devpriv->ai_calib_source = calib_source; | 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 | } else { | 2546 | } else { |
| 2709 | unsigned int calib_source; | 2547 | unsigned int calib_source; |
| 2710 | unsigned int calib_source_adjust; | 2548 | unsigned int calib_source_adjust; |
| @@ -2717,7 +2555,7 @@ static int ni_ai_insn_config(struct comedi_device *dev, · 6 unmodified lines | |||
| 2717 | devpriv->ai_calib_source = calib_source; | 2555 | devpriv->ai_calib_source = calib_source; |
| 2718 | if (devpriv->is_611x) { | 2556 | if (devpriv->is_611x) { |
| 2719 | ni_writeb(dev, calib_source_adjust, | 2557 | ni_writeb(dev, calib_source_adjust, |
| 2720 | Cal_Gain_Select_611x); | 2558 | NI611X_CAL_GAIN_SEL_REG); |
| 2721 | } | 2559 | } |
| 2722 | } | 2560 | } |
| 2723 | return 2; | 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 | if (timed) { | 2610 | if (timed) { |
| 2773 | for (i = 0; i < s->n_chan; ++i) { | 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 | ni_writeb(dev, devpriv->ao_conf[i], | 2613 | ni_writeb(dev, devpriv->ao_conf[i], |
| 2776 | M_Offset_AO_Config_Bank(i)); | 2614 | NI_M_AO_CFG_BANK_REG(i)); |
| 2777 | ni_writeb(dev, 0xf, M_Offset_AO_Waveform_Order(i)); | 2615 | ni_writeb(dev, 0xf, NI_M_AO_WAVEFORM_ORDER_REG(i)); |
| 2778 | } | 2616 | } |
| 2779 | } | 2617 | } |
| 2780 | for (i = 0; i < n_chans; i++) { | 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 | conf = 0; | 2625 | conf = 0; |
| 2788 | switch (krange->max - krange->min) { | 2626 | switch (krange->max - krange->min) { |
| 2789 | case 20000000: | 2627 | case 20000000: |
| 2790 | conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; | 2628 | conf |= NI_M_AO_CFG_BANK_REF_INT_10V; |
| 2791 | ni_writeb(dev, 0, | 2629 | ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan)); |
| 2792 | M_Offset_AO_Reference_Attenuation(chan)); | ||
| 2793 | break; | 2630 | break; |
| 2794 | case 10000000: | 2631 | case 10000000: |
| 2795 | conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; | 2632 | conf |= NI_M_AO_CFG_BANK_REF_INT_5V; |
| 2796 | ni_writeb(dev, 0, | 2633 | ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan)); |
| 2797 | M_Offset_AO_Reference_Attenuation(chan)); | ||
| 2798 | break; | 2634 | break; |
| 2799 | case 4000000: | 2635 | case 4000000: |
| 2800 | conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits; | 2636 | conf |= NI_M_AO_CFG_BANK_REF_INT_10V; |
| 2801 | ni_writeb(dev, MSeries_Attenuate_x5_Bit, | 2637 | ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, |
| 2802 | M_Offset_AO_Reference_Attenuation(chan)); | 2638 | NI_M_AO_REF_ATTENUATION_REG(chan)); |
| 2803 | break; | 2639 | break; |
| 2804 | case 2000000: | 2640 | case 2000000: |
| 2805 | conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits; | 2641 | conf |= NI_M_AO_CFG_BANK_REF_INT_5V; |
| 2806 | ni_writeb(dev, MSeries_Attenuate_x5_Bit, | 2642 | ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, |
| 2807 | M_Offset_AO_Reference_Attenuation(chan)); | 2643 | NI_M_AO_REF_ATTENUATION_REG(chan)); |
| 2808 | break; | 2644 | break; |
| 2809 | default: | 2645 | default: |
| 2810 | dev_err(dev->class_dev, | 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 | switch (krange->max + krange->min) { | 2650 | switch (krange->max + krange->min) { |
| 2815 | case 0: | 2651 | case 0: |
| 2816 | conf |= MSeries_AO_DAC_Offset_0V_Bits; | 2652 | conf |= NI_M_AO_CFG_BANK_OFFSET_0V; |
| 2817 | break; | 2653 | break; |
| 2818 | case 10000000: | 2654 | case 10000000: |
| 2819 | conf |= MSeries_AO_DAC_Offset_5V_Bits; | 2655 | conf |= NI_M_AO_CFG_BANK_OFFSET_5V; |
| 2820 | break; | 2656 | break; |
| 2821 | default: | 2657 | default: |
| 2822 | dev_err(dev->class_dev, | 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 | break; | 2660 | break; |
| 2825 | } | 2661 | } |
| 2826 | if (timed) | 2662 | if (timed) |
| 2827 | conf |= MSeries_AO_Update_Timed_Bit; | 2663 | conf |= NI_M_AO_CFG_BANK_UPDATE_TIMED; |
| 2828 | ni_writeb(dev, conf, M_Offset_AO_Config_Bank(chan)); | 2664 | ni_writeb(dev, conf, NI_M_AO_CFG_BANK_REG(chan)); |
| 2829 | devpriv->ao_conf[chan] = conf; | 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 | return invert; | 2668 | return invert; |
| 2833 | } | 2669 | } |
| @@ -2847,27 +2683,27 @@ static int ni_old_ao_config_chanlist(struct comedi_device *dev, · 13 unmodified lines | |||
| 2847 | for (i = 0; i < n_chans; i++) { | 2683 | for (i = 0; i < n_chans; i++) { |
| 2848 | chan = CR_CHAN(chanspec[i]); | 2684 | chan = CR_CHAN(chanspec[i]); |
| 2849 | range = CR_RANGE(chanspec[i]); | 2685 | range = CR_RANGE(chanspec[i]); |
| 2850 | conf = AO_Channel(chan); | 2686 | conf = NI_E_AO_DACSEL(chan); |
| 2851 | 2687 | ||
| 2852 | if (comedi_range_is_bipolar(s, range)) { | 2688 | if (comedi_range_is_bipolar(s, range)) { |
| 2853 | conf |= AO_Bipolar; | 2689 | conf |= NI_E_AO_CFG_BIP; |
| 2854 | invert = (s->maxdata + 1) >> 1; | 2690 | invert = (s->maxdata + 1) >> 1; |
| 2855 | } else { | 2691 | } else { |
| 2856 | invert = 0; | 2692 | invert = 0; |
| 2857 | } | 2693 | } |
| 2858 | if (comedi_range_is_external(s, range)) | 2694 | if (comedi_range_is_external(s, range)) |
| 2859 | conf |= AO_Ext_Ref; | 2695 | conf |= NI_E_AO_EXT_REF; |
| 2860 | 2696 | ||
| 2861 | /* not all boards can deglitch, but this shouldn't hurt */ | 2697 | /* not all boards can deglitch, but this shouldn't hurt */ |
| 2862 | if (chanspec[i] & CR_DEGLITCH) | 2698 | if (chanspec[i] & CR_DEGLITCH) |
| 2863 | conf |= AO_Deglitch; | 2699 | conf |= NI_E_AO_DEGLITCH; |
| 2864 | 2700 | ||
| 2865 | /* analog reference */ | 2701 | /* analog reference */ |
| 2866 | /* AREF_OTHER connects AO ground to AI ground, i think */ | 2702 | /* AREF_OTHER connects AO ground to AI ground, i think */ |
| 2867 | conf |= (CR_AREF(chanspec[i]) == | 2703 | if (CR_AREF(chanspec[i]) == AREF_OTHER) |
| 2868 | AREF_OTHER) ? AO_Ground_Ref : 0; | 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 | devpriv->ao_conf[chan] = conf; | 2707 | devpriv->ao_conf[chan] = conf; |
| 2872 | } | 2708 | } |
| 2873 | return invert; | 2709 | return invert; |
| @@ -2899,13 +2735,13 @@ static int ni_ao_insn_write(struct comedi_device *dev, · 25 unmodified lines | |||
| 2899 | int i; | 2735 | int i; |
| 2900 | 2736 | ||
| 2901 | if (devpriv->is_6xxx) { | 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 | } else if (devpriv->is_m_series) { | 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 | } else { | 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 | ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); | 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 | multiple times) */ | 2831 | multiple times) */ |
| 2996 | s->async->inttrig = NULL; | 2832 | s->async->inttrig = NULL; |
| 2997 | 2833 | ||
| 2998 | ni_set_bits(dev, Interrupt_B_Enable_Register, | 2834 | ni_set_bits(dev, NISTC_INTB_ENA_REG, |
| 2999 | AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0); | 2835 | NISTC_INTB_ENA_AO_FIFO | NISTC_INTB_ENA_AO_ERR, 0); |
| 3000 | interrupt_b_bits = AO_Error_Interrupt_Enable; | 2836 | interrupt_b_bits = NISTC_INTB_ENA_AO_ERR; |
| 3001 | #ifdef PCIDMA | 2837 | #ifdef PCIDMA |
| 3002 | ni_stc_writew(dev, 1, DAC_FIFO_Clear); | 2838 | ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG); |
| 3003 | if (devpriv->is_6xxx) | 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 | ret = ni_ao_setup_MITE_dma(dev); | 2841 | ret = ni_ao_setup_MITE_dma(dev); |
| 3006 | if (ret) | 2842 | if (ret) |
| 3007 | return ret; | 2843 | return ret; |
| @@ -3013,17 +2849,17 @@ static int ni_ao_inttrig(struct comedi_device *dev, · 5 unmodified lines | |||
| 3013 | if (ret == 0) | 2849 | if (ret == 0) |
| 3014 | return -EPIPE; | 2850 | return -EPIPE; |
| 3015 | 2851 | ||
| 3016 | interrupt_b_bits |= AO_FIFO_Interrupt_Enable; | 2852 | interrupt_b_bits |= NISTC_INTB_ENA_AO_FIFO; |
| 3017 | #endif | 2853 | #endif |
| 3018 | 2854 | ||
| 3019 | ni_stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE, | 2855 | ni_stc_writew(dev, devpriv->ao_mode3 | NISTC_AO_MODE3_NOT_AN_UPDATE, |
| 3020 | AO_Mode_3_Register); | 2856 | NISTC_AO_MODE3_REG); |
| 3021 | ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); | 2857 | ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG); |
| 3022 | /* wait for DACs to be loaded */ | 2858 | /* wait for DACs to be loaded */ |
| 3023 | for (i = 0; i < timeout; i++) { | 2859 | for (i = 0; i < timeout; i++) { |
| 3024 | udelay(1); | 2860 | udelay(1); |
| 3025 | if ((ni_stc_readw(dev, Joint_Status_2_Register) & | 2861 | if ((ni_stc_readw(dev, NISTC_STATUS2_REG) & |
| 3026 | AO_TMRDACWRs_In_Progress_St) == 0) | 2862 | NISTC_STATUS2_AO_TMRDACWRS_IN_PROGRESS) == 0) |
| 3027 | break; | 2863 | break; |
| 3028 | } | 2864 | } |
| 3029 | if (i == timeout) { | 2865 | if (i == timeout) { |
| @@ -3035,17 +2871,20 @@ static int ni_ao_inttrig(struct comedi_device *dev, · 5 unmodified lines | |||
| 3035 | * stc manual says we are need to clear error interrupt after | 2871 | * stc manual says we are need to clear error interrupt after |
| 3036 | * AO_TMRDACWRs_In_Progress_St clears | 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 | | 2878 | ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM | |
| 3043 | AO_UI_Arm | AO_UC_Arm | AO_BC_Arm | | 2879 | NISTC_AO_CMD1_UC_ARM | |
| 3044 | AO_DAC1_Update_Mode | AO_DAC0_Update_Mode, | 2880 | NISTC_AO_CMD1_BC_ARM | |
| 3045 | AO_Command_1_Register); | 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, | 2886 | ni_stc_writew(dev, NISTC_AO_CMD2_START1_PULSE | devpriv->ao_cmd2, |
| 3048 | AO_Command_2_Register); | 2887 | NISTC_AO_CMD2_REG); |
| 3049 | 2888 | ||
| 3050 | return 0; | 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 | int bits; | 2897 | int bits; |
| 3059 | int i; | 2898 | int i; |
| 3060 | unsigned trigvar; | 2899 | unsigned trigvar; |
| 2900 | unsigned val; | ||
| 3061 | 2901 | ||
| 3062 | if (dev->irq == 0) { | 2902 | if (dev->irq == 0) { |
| 3063 | dev_err(dev->class_dev, "cannot run command without an irq\n"); | 2903 | dev_err(dev->class_dev, "cannot run command without an irq\n"); |
| 3064 | return -EIO; | 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 | if (devpriv->is_6xxx) { | 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 | bits = 0; | 2915 | bits = 0; |
| 3075 | for (i = 0; i < cmd->chanlist_len; i++) { | 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 | chan = CR_CHAN(cmd->chanlist[i]); | 2919 | chan = CR_CHAN(cmd->chanlist[i]); |
| 3079 | bits |= 1 << chan; | 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 | ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); | 2926 | ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1); |
| 3086 | 2927 | ||
| 3087 | if (cmd->stop_src == TRIG_NONE) { | 2928 | if (cmd->stop_src == TRIG_NONE) { |
| 3088 | devpriv->ao_mode1 |= AO_Continuous; | 2929 | devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS; |
| 3089 | devpriv->ao_mode1 &= ~AO_Trigger_Once; | 2930 | devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE; |
| 3090 | } else { | 2931 | } else { |
| 3091 | devpriv->ao_mode1 &= ~AO_Continuous; | 2932 | devpriv->ao_mode1 &= ~NISTC_AO_MODE1_CONTINUOUS; |
| 3092 | devpriv->ao_mode1 |= AO_Trigger_Once; | 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 | switch (cmd->start_src) { | 2938 | switch (cmd->start_src) { |
| 3096 | case TRIG_INT: | 2939 | case TRIG_INT: |
| 3097 | case TRIG_NOW: | 2940 | case TRIG_NOW: |
| 3098 | devpriv->ao_trigger_select &= | 2941 | val &= ~(NISTC_AO_TRIG_START1_POLARITY | |
| 3099 | ~(AO_START1_Polarity | AO_START1_Select(-1)); | 2942 | NISTC_AO_TRIG_START1_SEL_MASK); |
| 3100 | devpriv->ao_trigger_select |= AO_START1_Edge | AO_START1_Sync; | 2943 | val |= NISTC_AO_TRIG_START1_EDGE | |
| 3101 | ni_stc_writew(dev, devpriv->ao_trigger_select, | 2944 | NISTC_AO_TRIG_START1_SYNC; |
| 3102 | AO_Trigger_Select_Register); | ||
| 3103 | break; | 2945 | break; |
| 3104 | case TRIG_EXT: | 2946 | case TRIG_EXT: |
| 3105 | devpriv->ao_trigger_select = | 2947 | val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1); |
| 3106 | AO_START1_Select(CR_CHAN(cmd->start_arg) + 1); | 2948 | if (cmd->start_arg & CR_INVERT) { |
| 3107 | if (cmd->start_arg & CR_INVERT) | 2949 | /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ |
| 3108 | devpriv->ao_trigger_select |= AO_START1_Polarity; /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ | 2950 | val |= NISTC_AO_TRIG_START1_POLARITY; |
| 3109 | if (cmd->start_arg & CR_EDGE) | 2951 | } |
| 3110 | devpriv->ao_trigger_select |= AO_START1_Edge; /* 0=edge detection disabled, 1=enabled */ | 2952 | if (cmd->start_arg & CR_EDGE) { |
| 2953 | /* 0=edge detection disabled, 1=enabled */ | ||
| 2954 | val |= NISTC_AO_TRIG_START1_EDGE; | ||
| 2955 | } | ||
| 3111 | ni_stc_writew(dev, devpriv->ao_trigger_select, | 2956 | ni_stc_writew(dev, devpriv->ao_trigger_select, |
| 3112 | AO_Trigger_Select_Register); | 2957 | NISTC_AO_TRIG_SEL_REG); |
| 3113 | break; | 2958 | break; |
| 3114 | default: | 2959 | default: |
| 3115 | BUG(); | 2960 | BUG(); |
| 3116 | break; | 2961 | break; |
| 3117 | } | 2962 | } |
| 3118 | devpriv->ao_mode3 &= ~AO_Trigger_Length; | 2963 | devpriv->ao_trigger_select = val; |
| 3119 | ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); | 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); | 2969 | ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); |
| 3122 | devpriv->ao_mode2 &= ~AO_BC_Initial_Load_Source; | 2970 | devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC; |
| 3123 | ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | 2971 | ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
| 3124 | if (cmd->stop_src == TRIG_NONE) | 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 | else | 2974 | else |
| 3127 | ni_stc_writel(dev, 0, AO_BC_Load_A_Register); | 2975 | ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG); |
| 3128 | ni_stc_writew(dev, AO_BC_Load, AO_Command_1_Register); | 2976 | ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG); |
| 3129 | devpriv->ao_mode2 &= ~AO_UC_Initial_Load_Source; | 2977 | devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; |
| 3130 | ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | 2978 | ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
| 3131 | switch (cmd->stop_src) { | 2979 | switch (cmd->stop_src) { |
| 3132 | case TRIG_COUNT: | 2980 | case TRIG_COUNT: |
| 3133 | if (devpriv->is_m_series) { | 2981 | if (devpriv->is_m_series) { |
| 3134 | /* this is how the NI example code does it for m-series boards, verified correct with 6259 */ | 2982 | /* this is how the NI example code does it for m-series boards, verified correct with 6259 */ |
| 3135 | ni_stc_writel(dev, cmd->stop_arg - 1, | 2983 | ni_stc_writel(dev, cmd->stop_arg - 1, |
| 3136 | AO_UC_Load_A_Register); | 2984 | NISTC_AO_UC_LOADA_REG); |
| 3137 | ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | 2985 | ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, |
| 2986 | NISTC_AO_CMD1_REG); | ||
| 3138 | } else { | 2987 | } else { |
| 3139 | ni_stc_writel(dev, cmd->stop_arg, | 2988 | ni_stc_writel(dev, cmd->stop_arg, |
| 3140 | AO_UC_Load_A_Register); | 2989 | NISTC_AO_UC_LOADA_REG); |
| 3141 | ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | 2990 | ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, |
| 2991 | NISTC_AO_CMD1_REG); | ||
| 3142 | ni_stc_writel(dev, cmd->stop_arg - 1, | 2992 | ni_stc_writel(dev, cmd->stop_arg - 1, |
| 3143 | AO_UC_Load_A_Register); | 2993 | NISTC_AO_UC_LOADA_REG); |
| 3144 | } | 2994 | } |
| 3145 | break; | 2995 | break; |
| 3146 | case TRIG_NONE: | 2996 | case TRIG_NONE: |
| 3147 | ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); | 2997 | ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); |
| 3148 | ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | 2998 | ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); |
| 3149 | ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register); | 2999 | ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG); |
| 3150 | break; | 3000 | break; |
| 3151 | default: | 3001 | default: |
| 3152 | ni_stc_writel(dev, 0, AO_UC_Load_A_Register); | 3002 | ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG); |
| 3153 | ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register); | 3003 | ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG); |
| 3154 | ni_stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register); | 3004 | ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG); |
| 3155 | } | 3005 | } |
| 3156 | 3006 | ||
| 3157 | devpriv->ao_mode1 &= | 3007 | devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK | |
| 3158 | ~(AO_UI_Source_Select(0x1f) | AO_UI_Source_Polarity | | 3008 | NISTC_AO_MODE1_UI_SRC_MASK | |
| 3159 | AO_UPDATE_Source_Select(0x1f) | AO_UPDATE_Source_Polarity); | 3009 | NISTC_AO_MODE1_UPDATE_SRC_POLARITY | |
| 3010 | NISTC_AO_MODE1_UI_SRC_POLARITY); | ||
| 3160 | switch (cmd->scan_begin_src) { | 3011 | switch (cmd->scan_begin_src) { |
| 3161 | case TRIG_TIMER: | 3012 | case TRIG_TIMER: |
| 3162 | devpriv->ao_cmd2 &= ~AO_BC_Gate_Enable; | 3013 | devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; |
| 3163 | trigvar = | 3014 | trigvar = |
| 3164 | ni_ns_to_timer(dev, cmd->scan_begin_arg, | 3015 | ni_ns_to_timer(dev, cmd->scan_begin_arg, |
| 3165 | CMDF_ROUND_NEAREST); | 3016 | CMDF_ROUND_NEAREST); |
| 3166 | ni_stc_writel(dev, 1, AO_UI_Load_A_Register); | 3017 | ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG); |
| 3167 | ni_stc_writew(dev, AO_UI_Load, AO_Command_1_Register); | 3018 | ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG); |
| 3168 | ni_stc_writel(dev, trigvar, AO_UI_Load_A_Register); | 3019 | ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG); |
| 3169 | break; | 3020 | break; |
| 3170 | case TRIG_EXT: | 3021 | case TRIG_EXT: |
| 3171 | devpriv->ao_mode1 |= | 3022 | devpriv->ao_mode1 |= |
| 3172 | AO_UPDATE_Source_Select(cmd->scan_begin_arg); | 3023 | NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg); |
| 3173 | if (cmd->scan_begin_arg & CR_INVERT) | 3024 | if (cmd->scan_begin_arg & CR_INVERT) |
| 3174 | devpriv->ao_mode1 |= AO_UPDATE_Source_Polarity; | 3025 | devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY; |
| 3175 | devpriv->ao_cmd2 |= AO_BC_Gate_Enable; | 3026 | devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; |
| 3176 | break; | 3027 | break; |
| 3177 | default: | 3028 | default: |
| 3178 | BUG(); | 3029 | BUG(); |
| 3179 | break; | 3030 | break; |
| 3180 | } | 3031 | } |
| 3181 | ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register); | 3032 | ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG); |
| 3182 | ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register); | 3033 | ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG); |
| 3183 | devpriv->ao_mode2 &= | 3034 | devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) | |
| 3184 | ~(AO_UI_Reload_Mode(3) | AO_UI_Initial_Load_Source); | 3035 | NISTC_AO_MODE2_UI_INIT_LOAD_SRC); |
| 3185 | ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | 3036 | ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
| 3186 | 3037 | ||
| 3187 | if (cmd->scan_end_arg > 1) { | 3038 | if (cmd->scan_end_arg > 1) { |
| 3188 | devpriv->ao_mode1 |= AO_Multiple_Channels; | 3039 | devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN; |
| 3189 | ni_stc_writew(dev, | 3040 | ni_stc_writew(dev, |
| 3190 | AO_Number_Of_Channels(cmd->scan_end_arg - 1) | | 3041 | NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) | |
| 3191 | AO_UPDATE_Output_Select(AO_Update_Output_High_Z), | 3042 | NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ, |
| 3192 | AO_Output_Control_Register); | 3043 | NISTC_AO_OUT_CTRL_REG); |
| 3193 | } else { | 3044 | } else { |
| 3194 | unsigned bits; | 3045 | unsigned bits; |
| 3195 | 3046 | ||
| 3196 | devpriv->ao_mode1 &= ~AO_Multiple_Channels; | 3047 | devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN; |
| 3197 | bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z); | 3048 | bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; |
| 3198 | if (devpriv->is_m_series || devpriv->is_6xxx) { | 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 | } else { | 3051 | } else { |
| 3201 | bits |= | 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, | 3059 | ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE | |
| 3209 | AO_Command_1_Register); | 3060 | NISTC_AO_CMD1_DAC0_UPDATE_MODE, |
| 3061 | NISTC_AO_CMD1_REG); | ||
| 3210 | 3062 | ||
| 3211 | devpriv->ao_mode3 |= AO_Stop_On_Overrun_Error; | 3063 | devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; |
| 3212 | ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register); | 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 | #ifdef PCIDMA | 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 | #else | 3069 | #else |
| 3218 | devpriv->ao_mode2 |= AO_FIFO_Mode_HF; | 3070 | devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF; |
| 3219 | #endif | 3071 | #endif |
| 3220 | devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable; | 3072 | devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA; |
| 3221 | ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register); | 3073 | ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
| 3222 | 3074 | ||
| 3223 | bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width | | 3075 | bits = NISTC_AO_PERSONAL_BC_SRC_SEL | |
| 3224 | AO_TMRDACWR_Pulse_Width; | 3076 | NISTC_AO_PERSONAL_UPDATE_PW | |
| 3077 | NISTC_AO_PERSONAL_TMRDACWR_PW; | ||
| 3225 | if (board->ao_fifo_depth) | 3078 | if (board->ao_fifo_depth) |
| 3226 | bits |= AO_FIFO_Enable; | 3079 | bits |= NISTC_AO_PERSONAL_FIFO_ENA; |
| 3227 | else | 3080 | else |
| 3228 | bits |= AO_DMA_PIO_Control; | 3081 | bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL; |
| 3229 | #if 0 | 3082 | #if 0 |
| 3230 | /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281, | 3083 | /* |
| 3231 | verified with bus analyzer. */ | 3084 | * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit |
| 3085 | * for 6281, verified with bus analyzer. | ||
| 3086 | */ | ||
| 3232 | if (devpriv->is_m_series) | 3087 | if (devpriv->is_m_series) |
| 3233 | bits |= AO_Number_Of_DAC_Packages; | 3088 | bits |= NISTC_AO_PERSONAL_NUM_DAC; |
| 3234 | #endif | 3089 | #endif |
| 3235 | ni_stc_writew(dev, bits, AO_Personal_Register); | 3090 | ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG); |
| 3236 | /* enable sending of ao dma requests */ | 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 | if (cmd->stop_src == TRIG_COUNT) { | 3096 | if (cmd->stop_src == TRIG_COUNT) { |
| 3242 | ni_stc_writew(dev, AO_BC_TC_Interrupt_Ack, | 3097 | ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC, |
| 3243 | Interrupt_B_Ack_Register); | 3098 | NISTC_INTB_ACK_REG); |
| 3244 | ni_set_bits(dev, Interrupt_B_Enable_Register, | 3099 | ni_set_bits(dev, NISTC_INTB_ENA_REG, |
| 3245 | AO_BC_TC_Interrupt_Enable, 1); | 3100 | NISTC_INTB_ENA_AO_BC_TC, 1); |
| 3246 | } | 3101 | } |
| 3247 | 3102 | ||
| 3248 | s->async->inttrig = ni_ao_inttrig; | 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 | ni_release_ao_mite_channel(dev); | 3195 | ni_release_ao_mite_channel(dev); |
| 3341 | 3196 | ||
| 3342 | ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register); | 3197 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
| 3343 | ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register); | 3198 | ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); |
| 3344 | ni_set_bits(dev, Interrupt_B_Enable_Register, ~0, 0); | 3199 | ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0); |
| 3345 | ni_stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register); | 3200 | ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); |
| 3346 | ni_stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register); | 3201 | ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); |
| 3347 | ni_stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width | | 3202 | ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL | |
| 3348 | AO_TMRDACWR_Pulse_Width, AO_Personal_Register); | 3203 | NISTC_AO_PERSONAL_UPDATE_PW | |
| 3349 | ni_stc_writew(dev, 0, AO_Output_Control_Register); | 3204 | NISTC_AO_PERSONAL_TMRDACWR_PW, |
| 3350 | ni_stc_writew(dev, 0, AO_Start_Select_Register); | 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 | devpriv->ao_cmd1 = 0; | 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 | devpriv->ao_cmd2 = 0; | 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 | devpriv->ao_mode1 = 0; | 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 | devpriv->ao_mode2 = 0; | 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 | if (devpriv->is_m_series) | 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 | else | 3218 | else |
| 3362 | devpriv->ao_mode3 = 0; | 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 | devpriv->ao_trigger_select = 0; | 3221 | devpriv->ao_trigger_select = 0; |
| 3365 | ni_stc_writew(dev, devpriv->ao_trigger_select, | 3222 | ni_stc_writew(dev, devpriv->ao_trigger_select, |
| 3366 | AO_Trigger_Select_Register); | 3223 | NISTC_AO_TRIG_SEL_REG); |
| 3367 | if (devpriv->is_6xxx) { | 3224 | if (devpriv->is_6xxx) { |
| 3368 | unsigned immediate_bits = 0; | 3225 | unsigned immediate_bits = 0; |
| 3369 | unsigned i; | 3226 | unsigned i; |
| 3370 | 3227 | ||
| 3371 | for (i = 0; i < s->n_chan; ++i) | 3228 | for (i = 0; i < s->n_chan; ++i) |
| 3372 | immediate_bits |= 1 << i; | 3229 | immediate_bits |= 1 << i; |
| 3373 | ni_ao_win_outw(dev, immediate_bits, AO_Immediate_671x); | 3230 | ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG); |
| 3374 | ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x); | 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 | return 0; | 3236 | return 0; |
| 3379 | } | 3237 | } |
| @@ -3392,9 +3250,9 @@ static int ni_dio_insn_config(struct comedi_device *dev, · 12 unmodified lines | |||
| 3392 | if (ret) | 3250 | if (ret) |
| 3393 | return ret; | 3251 | return ret; |
| 3394 | 3252 | ||
| 3395 | devpriv->dio_control &= ~DIO_Pins_Dir_Mask; | 3253 | devpriv->dio_control &= ~NISTC_DIO_CTRL_DIR_MASK; |
| 3396 | devpriv->dio_control |= DIO_Pins_Dir(s->io_bits); | 3254 | devpriv->dio_control |= NISTC_DIO_CTRL_DIR(s->io_bits); |
| 3397 | ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | 3255 | ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); |
| 3398 | 3256 | ||
| 3399 | return insn->n; | 3257 | return insn->n; |
| 3400 | } | 3258 | } |
| @@ -3407,16 +3265,17 @@ static int ni_dio_insn_bits(struct comedi_device *dev, · 6 unmodified lines | |||
| 3407 | struct ni_private *devpriv = dev->private; | 3265 | struct ni_private *devpriv = dev->private; |
| 3408 | 3266 | ||
| 3409 | /* Make sure we're not using the serial part of the dio */ | 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 | return -EBUSY; | 3270 | return -EBUSY; |
| 3412 | 3271 | ||
| 3413 | if (comedi_dio_update_state(s, data)) { | 3272 | if (comedi_dio_update_state(s, data)) { |
| 3414 | devpriv->dio_output &= ~DIO_Parallel_Data_Mask; | 3273 | devpriv->dio_output &= ~NISTC_DIO_OUT_PARALLEL_MASK; |
| 3415 | devpriv->dio_output |= DIO_Parallel_Data_Out(s->state); | 3274 | devpriv->dio_output |= NISTC_DIO_OUT_PARALLEL(s->state); |
| 3416 | ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); | 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 | return insn->n; | 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 | if (ret) | 3291 | if (ret) |
| 3433 | return ret; | 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 | return insn->n; | 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 | unsigned int *data) | 3302 | unsigned int *data) |
| 3444 | { | 3303 | { |
| 3445 | if (comedi_dio_update_state(s, data)) | 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 | return insn->n; | 3309 | return insn->n; |
| 3451 | } | 3310 | } |
| @@ -3491,7 +3350,7 @@ static int ni_cdio_cmdtest(struct comedi_device *dev, · 39 unmodified lines | |||
| 3491 | err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); | 3350 | err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); |
| 3492 | 3351 | ||
| 3493 | tmp = cmd->scan_begin_arg; | 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 | if (tmp != cmd->scan_begin_arg) | 3354 | if (tmp != cmd->scan_begin_arg) |
| 3496 | err |= -EINVAL; | 3355 | err |= -EINVAL; |
| 3497 | 3356 | ||
| @@ -3550,13 +3409,14 @@ static int ni_cdo_inttrig(struct comedi_device *dev, · 52 unmodified lines | |||
| 3550 | if (retval < 0) | 3409 | if (retval < 0) |
| 3551 | return retval; | 3410 | return retval; |
| 3552 | #endif | 3411 | #endif |
| 3553 | /* | 3412 | /* |
| 3554 | * XXX not sure what interrupt C group does | 3413 | * XXX not sure what interrupt C group does |
| 3555 | * ni_writeb(dev, Interrupt_Group_C_Enable_Bit, | 3414 | * wait for dma to fill output fifo |
| 3556 | * M_Offset_Interrupt_C_Enable); wait for dma to fill output fifo | 3415 | * ni_writeb(dev, NI_M_INTC_ENA, NI_M_INTC_ENA_REG); |
| 3557 | */ | 3416 | */ |
| 3558 | for (i = 0; i < timeout; ++i) { | 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 | break; | 3420 | break; |
| 3561 | udelay(10); | 3421 | udelay(10); |
| 3562 | } | 3422 | } |
| @@ -3565,36 +3425,30 @@ static int ni_cdo_inttrig(struct comedi_device *dev, · 2 unmodified lines | |||
| 3565 | s->cancel(dev, s); | 3425 | s->cancel(dev, s); |
| 3566 | return -EIO; | 3426 | return -EIO; |
| 3567 | } | 3427 | } |
| 3568 | ni_writel(dev, CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit | | 3428 | ni_writel(dev, NI_M_CDO_CMD_ARM | |
| 3569 | CDO_Empty_FIFO_Interrupt_Enable_Set_Bit, | 3429 | NI_M_CDO_CMD_ERR_INT_ENA_SET | |
| 3570 | M_Offset_CDIO_Command); | 3430 | NI_M_CDO_CMD_F_E_INT_ENA_SET, |
| 3431 | NI_M_CDIO_CMD_REG); | ||
| 3571 | return retval; | 3432 | return retval; |
| 3572 | } | 3433 | } |
| 3573 | 3434 | ||
| 3574 | static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) | 3435 | static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
| 3575 | { | 3436 | { |
| 3576 | const struct comedi_cmd *cmd = &s->async->cmd; | 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 | int retval; | 3439 | int retval; |
| 3579 | 3440 | ||
| 3580 | ni_writel(dev, CDO_Reset_Bit, M_Offset_CDIO_Command); | 3441 | ni_writel(dev, NI_M_CDO_CMD_RESET, NI_M_CDIO_CMD_REG); |
| 3581 | switch (cmd->scan_begin_src) { | 3442 | cdo_mode_bits = NI_M_CDO_MODE_FIFO_MODE | |
| 3582 | case TRIG_EXT: | 3443 | NI_M_CDO_MODE_HALT_ON_ERROR | |
| 3583 | cdo_mode_bits |= | 3444 | NI_M_CDO_MODE_SAMPLE_SRC(CR_CHAN(cmd->scan_begin_arg)); |
| 3584 | CR_CHAN(cmd->scan_begin_arg) & | ||
| 3585 | CDO_Sample_Source_Select_Mask; | ||
| 3586 | break; | ||
| 3587 | default: | ||
| 3588 | BUG(); | ||
| 3589 | break; | ||
| 3590 | } | ||
| 3591 | if (cmd->scan_begin_arg & CR_INVERT) | 3445 | if (cmd->scan_begin_arg & CR_INVERT) |
| 3592 | cdo_mode_bits |= CDO_Polarity_Bit; | 3446 | cdo_mode_bits |= NI_M_CDO_MODE_POLARITY; |
| 3593 | ni_writel(dev, cdo_mode_bits, M_Offset_CDO_Mode); | 3447 | ni_writel(dev, cdo_mode_bits, NI_M_CDO_MODE_REG); |
| 3594 | if (s->io_bits) { | 3448 | if (s->io_bits) { |
| 3595 | ni_writel(dev, s->state, M_Offset_CDO_FIFO_Data); | 3449 | ni_writel(dev, s->state, NI_M_CDO_FIFO_DATA_REG); |
| 3596 | ni_writel(dev, CDO_SW_Update_Bit, M_Offset_CDIO_Command); | 3450 | ni_writel(dev, NI_M_CDO_CMD_SW_UPDATE, NI_M_CDIO_CMD_REG); |
| 3597 | ni_writel(dev, s->io_bits, M_Offset_CDO_Mask_Enable); | 3451 | ni_writel(dev, s->io_bits, NI_M_CDO_MASK_ENA_REG); |
| 3598 | } else { | 3452 | } else { |
| 3599 | dev_err(dev->class_dev, | 3453 | dev_err(dev->class_dev, |
| 3600 | "attempted to run digital output command with no lines configured as outputs\n"); | 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 | static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) | 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 | | 3468 | ni_writel(dev, NI_M_CDO_CMD_DISARM | |
| 3615 | CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit | | 3469 | NI_M_CDO_CMD_ERR_INT_ENA_CLR | |
| 3616 | CDO_FIFO_Request_Interrupt_Enable_Clear_Bit, | 3470 | NI_M_CDO_CMD_F_E_INT_ENA_CLR | |
| 3617 | M_Offset_CDIO_Command); | 3471 | NI_M_CDO_CMD_F_REQ_INT_ENA_CLR, |
| 3618 | /* | 3472 | NI_M_CDIO_CMD_REG); |
| 3619 | * XXX not sure what interrupt C group does ni_writeb(dev, 0, | 3473 | /* |
| 3620 | * M_Offset_Interrupt_C_Enable); | 3474 | * XXX not sure what interrupt C group does |
| 3621 | */ | 3475 | * ni_writeb(dev, 0, NI_M_INTC_ENA_REG); |
| 3622 | ni_writel(dev, 0, M_Offset_CDO_Mask_Enable); | 3476 | */ |
| 3477 | ni_writel(dev, 0, NI_M_CDO_MASK_ENA_REG); | ||
| 3623 | ni_release_cdo_mite_channel(dev); | 3478 | ni_release_cdo_mite_channel(dev); |
| 3624 | return 0; | 3479 | return 0; |
| 3625 | } | 3480 | } |
| @@ -3650,16 +3505,16 @@ static void handle_cdio_interrupt(struct comedi_device *dev) · 24 unmodified lines | |||
| 3650 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); | 3505 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
| 3651 | #endif | 3506 | #endif |
| 3652 | 3507 | ||
| 3653 | cdio_status = ni_readl(dev, M_Offset_CDIO_Status); | 3508 | cdio_status = ni_readl(dev, NI_M_CDIO_STATUS_REG); |
| 3654 | if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) { | 3509 | if (cdio_status & NI_M_CDIO_STATUS_CDO_ERROR) { |
| 3655 | /* XXX just guessing this is needed and does something useful */ | 3510 | /* XXX just guessing this is needed and does something useful */ |
| 3656 | ni_writel(dev, CDO_Error_Interrupt_Confirm_Bit, | 3511 | ni_writel(dev, NI_M_CDO_CMD_ERR_INT_CONFIRM, |
| 3657 | M_Offset_CDIO_Command); | 3512 | NI_M_CDIO_CMD_REG); |
| 3658 | s->async->events |= COMEDI_CB_OVERFLOW; | 3513 | s->async->events |= COMEDI_CB_OVERFLOW; |
| 3659 | } | 3514 | } |
| 3660 | if (cdio_status & CDO_FIFO_Empty_Bit) { | 3515 | if (cdio_status & NI_M_CDIO_STATUS_CDO_FIFO_EMPTY) { |
| 3661 | ni_writel(dev, CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit, | 3516 | ni_writel(dev, NI_M_CDO_CMD_F_E_INT_ENA_CLR, |
| 3662 | M_Offset_CDIO_Command); | 3517 | NI_M_CDIO_CMD_REG); |
| 3663 | /* s->async->events |= COMEDI_CB_EOA; */ | 3518 | /* s->async->events |= COMEDI_CB_EOA; */ |
| 3664 | } | 3519 | } |
| 3665 | comedi_handle_events(dev, s); | 3520 | comedi_handle_events(dev, s); |
| @@ -3674,23 +3529,23 @@ static int ni_serial_hw_readwrite8(struct comedi_device *dev, · 8 unmodified lines | |||
| 3674 | unsigned int status1; | 3529 | unsigned int status1; |
| 3675 | int err = 0, count = 20; | 3530 | int err = 0, count = 20; |
| 3676 | 3531 | ||
| 3677 | devpriv->dio_output &= ~DIO_Serial_Data_Mask; | 3532 | devpriv->dio_output &= ~NISTC_DIO_OUT_SERIAL_MASK; |
| 3678 | devpriv->dio_output |= DIO_Serial_Data_Out(data_out); | 3533 | devpriv->dio_output |= NISTC_DIO_OUT_SERIAL(data_out); |
| 3679 | ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); | 3534 | ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); |
| 3680 | 3535 | ||
| 3681 | status1 = ni_stc_readw(dev, Joint_Status_1_Register); | 3536 | status1 = ni_stc_readw(dev, NISTC_STATUS1_REG); |
| 3682 | if (status1 & DIO_Serial_IO_In_Progress_St) { | 3537 | if (status1 & NISTC_STATUS1_SERIO_IN_PROG) { |
| 3683 | err = -EBUSY; | 3538 | err = -EBUSY; |
| 3684 | goto Error; | 3539 | goto Error; |
| 3685 | } | 3540 | } |
| 3686 | 3541 | ||
| 3687 | devpriv->dio_control |= DIO_HW_Serial_Start; | 3542 | devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_START; |
| 3688 | ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | 3543 | ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); |
| 3689 | devpriv->dio_control &= ~DIO_HW_Serial_Start; | 3544 | devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_START; |
| 3690 | 3545 | ||
| 3691 | /* Wait until STC says we're done, but don't loop infinitely. */ | 3546 | /* Wait until STC says we're done, but don't loop infinitely. */ |
| 3692 | while ((status1 = ni_stc_readw(dev, Joint_Status_1_Register)) & | 3547 | while ((status1 = ni_stc_readw(dev, NISTC_STATUS1_REG)) & |
| 3693 | DIO_Serial_IO_In_Progress_St) { | 3548 | NISTC_STATUS1_SERIO_IN_PROG) { |
| 3694 | /* Delay one bit per loop */ | 3549 | /* Delay one bit per loop */ |
| 3695 | udelay((devpriv->serial_interval_ns + 999) / 1000); | 3550 | udelay((devpriv->serial_interval_ns + 999) / 1000); |
| 3696 | if (--count < 0) { | 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 | 3559 | /* |
| 3705 | DIO_Serial_IO_In_Progress_St goes high one bit too early. */ | 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 | udelay((devpriv->serial_interval_ns + 999) / 1000); | 3563 | udelay((devpriv->serial_interval_ns + 999) / 1000); |
| 3707 | 3564 | ||
| 3708 | if (data_in) | 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 | Error: | 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 | return err; | 3571 | return err; |
| 3715 | } | 3572 | } |
| @@ -3729,25 +3586,25 @@ static int ni_serial_sw_readwrite8(struct comedi_device *dev, · 13 unmodified lines | |||
| 3729 | /* Output current bit; note that we cannot touch s->state | 3586 | /* Output current bit; note that we cannot touch s->state |
| 3730 | because it is a per-subdevice field, and serial is | 3587 | because it is a per-subdevice field, and serial is |
| 3731 | a separate subdevice from DIO. */ | 3588 | a separate subdevice from DIO. */ |
| 3732 | devpriv->dio_output &= ~DIO_SDOUT; | 3589 | devpriv->dio_output &= ~NISTC_DIO_SDOUT; |
| 3733 | if (data_out & mask) | 3590 | if (data_out & mask) |
| 3734 | devpriv->dio_output |= DIO_SDOUT; | 3591 | devpriv->dio_output |= NISTC_DIO_SDOUT; |
| 3735 | ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register); | 3592 | ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG); |
| 3736 | 3593 | ||
| 3737 | /* Assert SDCLK (active low, inverted), wait for half of | 3594 | /* Assert SDCLK (active low, inverted), wait for half of |
| 3738 | the delay, deassert SDCLK, and wait for the other half. */ | 3595 | the delay, deassert SDCLK, and wait for the other half. */ |
| 3739 | devpriv->dio_control |= DIO_Software_Serial_Control; | 3596 | devpriv->dio_control |= NISTC_DIO_SDCLK; |
| 3740 | ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | 3597 | ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); |
| 3741 | 3598 | ||
| 3742 | udelay((devpriv->serial_interval_ns + 999) / 2000); | 3599 | udelay((devpriv->serial_interval_ns + 999) / 2000); |
| 3743 | 3600 | ||
| 3744 | devpriv->dio_control &= ~DIO_Software_Serial_Control; | 3601 | devpriv->dio_control &= ~NISTC_DIO_SDCLK; |
| 3745 | ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register); | 3602 | ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); |
| 3746 | 3603 | ||
| 3747 | udelay((devpriv->serial_interval_ns + 999) / 2000); | 3604 | udelay((devpriv->serial_interval_ns + 999) / 2000); |
| 3748 | 3605 | ||
| 3749 | /* Input current bit */ | 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 | input |= mask; | 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 | unsigned int *data) | 3620 | unsigned int *data) |
| 3764 | { | 3621 | { |
| 3765 | struct ni_private *devpriv = dev->private; | 3622 | struct ni_private *devpriv = dev->private; |
| 3623 | unsigned clk_fout = devpriv->clock_and_fout; | ||
| 3766 | int err = insn->n; | 3624 | int err = insn->n; |
| 3767 | unsigned char byte_out, byte_in = 0; | 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 | switch (data[0]) { | 3630 | switch (data[0]) { |
| 3773 | case INSN_CONFIG_SERIAL_CLOCK: | 3631 | case INSN_CONFIG_SERIAL_CLOCK: |
| 3774 | devpriv->serial_hw_mode = 1; | 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 | if (data[1] == SERIAL_DISABLED) { | 3635 | if (data[1] == SERIAL_DISABLED) { |
| 3778 | devpriv->serial_hw_mode = 0; | 3636 | devpriv->serial_hw_mode = 0; |
| 3779 | devpriv->dio_control &= ~(DIO_HW_Serial_Enable | | 3637 | devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | |
| 3780 | DIO_Software_Serial_Control); | 3638 | NISTC_DIO_SDCLK); |
| 3781 | data[1] = SERIAL_DISABLED; | 3639 | data[1] = SERIAL_DISABLED; |
| 3782 | devpriv->serial_interval_ns = data[1]; | 3640 | devpriv->serial_interval_ns = data[1]; |
| 3783 | } else if (data[1] <= SERIAL_600NS) { | 3641 | } else if (data[1] <= SERIAL_600NS) { |
| 3784 | /* Warning: this clock speed is too fast to reliably | 3642 | /* Warning: this clock speed is too fast to reliably |
| 3785 | control SCXI. */ | 3643 | control SCXI. */ |
| 3786 | devpriv->dio_control &= ~DIO_HW_Serial_Timebase; | 3644 | devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; |
| 3787 | devpriv->clock_and_fout |= Slow_Internal_Timebase; | 3645 | clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE; |
| 3788 | devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2; | 3646 | clk_fout &= ~NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; |
| 3789 | data[1] = SERIAL_600NS; | 3647 | data[1] = SERIAL_600NS; |
| 3790 | devpriv->serial_interval_ns = data[1]; | 3648 | devpriv->serial_interval_ns = data[1]; |
| 3791 | } else if (data[1] <= SERIAL_1_2US) { | 3649 | } else if (data[1] <= SERIAL_1_2US) { |
| 3792 | devpriv->dio_control &= ~DIO_HW_Serial_Timebase; | 3650 | devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; |
| 3793 | devpriv->clock_and_fout |= Slow_Internal_Timebase | | 3651 | clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | |
| 3794 | DIO_Serial_Out_Divide_By_2; | 3652 | NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; |
| 3795 | data[1] = SERIAL_1_2US; | 3653 | data[1] = SERIAL_1_2US; |
| 3796 | devpriv->serial_interval_ns = data[1]; | 3654 | devpriv->serial_interval_ns = data[1]; |
| 3797 | } else if (data[1] <= SERIAL_10US) { | 3655 | } else if (data[1] <= SERIAL_10US) { |
| 3798 | devpriv->dio_control |= DIO_HW_Serial_Timebase; | 3656 | devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_TIMEBASE; |
| 3799 | devpriv->clock_and_fout |= Slow_Internal_Timebase | | 3657 | clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | |
| 3800 | DIO_Serial_Out_Divide_By_2; | 3658 | NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; |
| 3801 | /* Note: DIO_Serial_Out_Divide_By_2 only affects | 3659 | /* Note: NISTC_CLK_FOUT_DIO_SER_OUT_DIV2 only affects |
| 3802 | 600ns/1.2us. If you turn divide_by_2 off with the | 3660 | 600ns/1.2us. If you turn divide_by_2 off with the |
| 3803 | slow clock, you will still get 10us, except then | 3661 | slow clock, you will still get 10us, except then |
| 3804 | all your delays are wrong. */ | 3662 | all your delays are wrong. */ |
| 3805 | data[1] = SERIAL_10US; | 3663 | data[1] = SERIAL_10US; |
| 3806 | devpriv->serial_interval_ns = data[1]; | 3664 | devpriv->serial_interval_ns = data[1]; |
| 3807 | } else { | 3665 | } else { |
| 3808 | devpriv->dio_control &= ~(DIO_HW_Serial_Enable | | 3666 | devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | |
| 3809 | DIO_Software_Serial_Control); | 3667 | NISTC_DIO_SDCLK); |
| 3810 | devpriv->serial_hw_mode = 0; | 3668 | devpriv->serial_hw_mode = 0; |
| 3811 | data[1] = (data[1] / 1000) * 1000; | 3669 | data[1] = (data[1] / 1000) * 1000; |
| 3812 | devpriv->serial_interval_ns = data[1]; | 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); | 3674 | ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG); |
| 3816 | ni_stc_writew(dev, devpriv->clock_and_fout, | 3675 | ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); |
| 3817 | Clock_and_FOUT_Register); | ||
| 3818 | return 1; | 3676 | return 1; |
| 3819 | 3677 | ||
| 3820 | case INSN_CONFIG_BIDIRECTIONAL_DATA: | 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 | int i; | 3708 | int i; |
| 3851 | 3709 | ||
| 3852 | for (i = 0; i < s->n_chan; i++) { | 3710 | for (i = 0; i < s->n_chan; i++) { |
| 3853 | ni_ao_win_outw(dev, AO_Channel(i) | 0x0, | 3711 | ni_ao_win_outw(dev, NI_E_AO_DACSEL(i) | 0x0, |
| 3854 | AO_Configuration_2_67xx); | 3712 | NI67XX_AO_CFG2_REG); |
| 3855 | } | 3713 | } |
| 3856 | ni_ao_win_outw(dev, 0x0, AO_Later_Single_Point_Updates); | 3714 | ni_ao_win_outw(dev, 0x0, NI67XX_AO_SP_UPDATES_REG); |
| 3857 | } | 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) { | 3761 | if (reg < ARRAY_SIZE(ni_gpct_to_stc_regmap)) { |
| 3864 | case NITIO_G0_AUTO_INC: | 3762 | regmap = &ni_gpct_to_stc_regmap[reg]; |
| 3865 | stc_register = G_Autoincrement_Register(0); | 3763 | } else { |
| 3866 | break; | 3764 | dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n", |
| 3867 | case NITIO_G1_AUTO_INC: | 3765 | __func__, reg); |
| 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(); | ||
| 3946 | return 0; | 3766 | return 0; |
| 3947 | } | 3767 | } |
| 3948 | return stc_register; | 3768 | |
| 3769 | return regmap->mio_reg; | ||
| 3949 | } | 3770 | } |
| 3950 | 3771 | ||
| 3951 | static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, | 3772 | static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, |
| 3952 | enum ni_gpct_register reg) | 3773 | enum ni_gpct_register reg) |
| 3953 | { | 3774 | { |
| 3954 | struct comedi_device *dev = counter->counter_dev->dev; | 3775 | struct comedi_device *dev = counter->counter_dev->dev; |
| 3955 | unsigned stc_register; | 3776 | unsigned int stc_register = ni_gpct_to_stc_register(dev, reg); |
| 3956 | /* bits in the join reset register which are relevant to counters */ | ||
| 3957 | static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset; | ||
| 3958 | static const unsigned gpct_interrupt_a_enable_mask = | 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 | static const unsigned gpct_interrupt_b_enable_mask = | 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.