David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 1 | /* |
| 2 | comedi/drivers/ni_pcidio.c |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 3 | driver for National Instruments PCI-DIO-32HS |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 4 | |
| 5 | COMEDI - Linux Control and Measurement Device Interface |
| 6 | Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org> |
| 7 | |
| 8 | This program is free software; you can redistribute it and/or modify |
| 9 | it under the terms of the GNU General Public License as published by |
| 10 | the Free Software Foundation; either version 2 of the License, or |
| 11 | (at your option) any later version. |
| 12 | |
| 13 | This program is distributed in the hope that it will be useful, |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | GNU General Public License for more details. |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 17 | */ |
| 18 | /* |
| 19 | Driver: ni_pcidio |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 20 | Description: National Instruments PCI-DIO32HS, PCI-6533 |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 21 | Author: ds |
| 22 | Status: works |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 23 | Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio) |
| 24 | [National Instruments] PXI-6533, PCI-6533 (pxi-6533) |
| 25 | [National Instruments] PCI-6534 (pci-6534) |
Ian Abbott | 22494ed | 2012-01-09 15:47:33 +0000 | [diff] [blame] | 26 | Updated: Mon, 09 Jan 2012 14:27:23 +0000 |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 27 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 28 | The DIO32HS board appears as one subdevice, with 32 channels. |
| 29 | Each channel is individually I/O configurable. The channel order |
| 30 | is 0=A0, 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only |
| 31 | supports simple digital I/O; no handshaking is supported. |
| 32 | |
| 33 | DMA mostly works for the PCI-DIO32HS, but only in timed input mode. |
| 34 | |
Ian Abbott | 22494ed | 2012-01-09 15:47:33 +0000 | [diff] [blame] | 35 | The PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting |
| 36 | scan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting |
| 37 | scan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the |
| 38 | trailing edge. |
| 39 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 40 | This driver could be easily modified to support AT-MIO32HS and |
| 41 | AT-MIO96. |
| 42 | |
| 43 | The PCI-6534 requires a firmware upload after power-up to work, the |
| 44 | firmware data and instructions for loading it with comedi_config |
| 45 | it are contained in the |
| 46 | comedi_nonfree_firmware tarball available from http://www.comedi.org |
| 47 | */ |
| 48 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 49 | #define USE_DMA |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 50 | |
H Hartley Sweeten | ce157f8 | 2013-06-24 17:04:43 -0700 | [diff] [blame] | 51 | #include <linux/module.h> |
H Hartley Sweeten | 33782dd | 2013-01-30 15:22:21 -0700 | [diff] [blame] | 52 | #include <linux/delay.h> |
Greg Kroah-Hartman | 25436dc | 2009-04-27 15:14:34 -0700 | [diff] [blame] | 53 | #include <linux/interrupt.h> |
Greg Kroah-Hartman | 4377a02 | 2009-10-12 14:58:16 -0700 | [diff] [blame] | 54 | #include <linux/sched.h> |
H Hartley Sweeten | 33782dd | 2013-01-30 15:22:21 -0700 | [diff] [blame] | 55 | |
Ian Abbott | 2a5f650 | 2015-03-10 16:11:11 +0000 | [diff] [blame] | 56 | #include "../comedi_pci.h" |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 57 | |
| 58 | #include "mite.h" |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 59 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 60 | /* defines for the PCI-DIO-32HS */ |
| 61 | |
| 62 | #define Window_Address 4 /* W */ |
| 63 | #define Interrupt_And_Window_Status 4 /* R */ |
| 64 | #define IntStatus1 (1<<0) |
| 65 | #define IntStatus2 (1<<1) |
| 66 | #define WindowAddressStatus_mask 0x7c |
| 67 | |
| 68 | #define Master_DMA_And_Interrupt_Control 5 /* W */ |
| 69 | #define InterruptLine(x) ((x)&3) |
| 70 | #define OpenInt (1<<2) |
| 71 | #define Group_Status 5 /* R */ |
| 72 | #define DataLeft (1<<0) |
| 73 | #define Req (1<<2) |
| 74 | #define StopTrig (1<<3) |
| 75 | |
| 76 | #define Group_1_Flags 6 /* R */ |
| 77 | #define Group_2_Flags 7 /* R */ |
| 78 | #define TransferReady (1<<0) |
| 79 | #define CountExpired (1<<1) |
| 80 | #define Waited (1<<5) |
| 81 | #define PrimaryTC (1<<6) |
| 82 | #define SecondaryTC (1<<7) |
Bill Pemberton | 56e9e16 | 2009-04-23 15:54:52 -0400 | [diff] [blame] | 83 | /* #define SerialRose */ |
| 84 | /* #define ReqRose */ |
| 85 | /* #define Paused */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 86 | |
| 87 | #define Group_1_First_Clear 6 /* W */ |
| 88 | #define Group_2_First_Clear 7 /* W */ |
| 89 | #define ClearWaited (1<<3) |
| 90 | #define ClearPrimaryTC (1<<4) |
| 91 | #define ClearSecondaryTC (1<<5) |
| 92 | #define DMAReset (1<<6) |
| 93 | #define FIFOReset (1<<7) |
| 94 | #define ClearAll 0xf8 |
| 95 | |
| 96 | #define Group_1_FIFO 8 /* W */ |
| 97 | #define Group_2_FIFO 12 /* W */ |
| 98 | |
| 99 | #define Transfer_Count 20 |
| 100 | #define Chip_ID_D 24 |
| 101 | #define Chip_ID_I 25 |
| 102 | #define Chip_ID_O 26 |
| 103 | #define Chip_Version 27 |
| 104 | #define Port_IO(x) (28+(x)) |
| 105 | #define Port_Pin_Directions(x) (32+(x)) |
| 106 | #define Port_Pin_Mask(x) (36+(x)) |
| 107 | #define Port_Pin_Polarities(x) (40+(x)) |
| 108 | |
| 109 | #define Master_Clock_Routing 45 |
| 110 | #define RTSIClocking(x) (((x)&3)<<4) |
| 111 | |
| 112 | #define Group_1_Second_Clear 46 /* W */ |
| 113 | #define Group_2_Second_Clear 47 /* W */ |
| 114 | #define ClearExpired (1<<0) |
| 115 | |
| 116 | #define Port_Pattern(x) (48+(x)) |
| 117 | |
| 118 | #define Data_Path 64 |
| 119 | #define FIFOEnableA (1<<0) |
| 120 | #define FIFOEnableB (1<<1) |
| 121 | #define FIFOEnableC (1<<2) |
| 122 | #define FIFOEnableD (1<<3) |
| 123 | #define Funneling(x) (((x)&3)<<4) |
| 124 | #define GroupDirection (1<<7) |
| 125 | |
| 126 | #define Protocol_Register_1 65 |
| 127 | #define OpMode Protocol_Register_1 |
| 128 | #define RunMode(x) ((x)&7) |
| 129 | #define Numbered (1<<3) |
| 130 | |
| 131 | #define Protocol_Register_2 66 |
| 132 | #define ClockReg Protocol_Register_2 |
| 133 | #define ClockLine(x) (((x)&3)<<5) |
| 134 | #define InvertStopTrig (1<<7) |
| 135 | #define DataLatching(x) (((x)&3)<<5) |
| 136 | |
| 137 | #define Protocol_Register_3 67 |
| 138 | #define Sequence Protocol_Register_3 |
| 139 | |
| 140 | #define Protocol_Register_14 68 /* 16 bit */ |
| 141 | #define ClockSpeed Protocol_Register_14 |
| 142 | |
| 143 | #define Protocol_Register_4 70 |
| 144 | #define ReqReg Protocol_Register_4 |
| 145 | #define ReqConditioning(x) (((x)&7)<<3) |
| 146 | |
| 147 | #define Protocol_Register_5 71 |
| 148 | #define BlockMode Protocol_Register_5 |
| 149 | |
| 150 | #define FIFO_Control 72 |
| 151 | #define ReadyLevel(x) ((x)&7) |
| 152 | |
| 153 | #define Protocol_Register_6 73 |
| 154 | #define LinePolarities Protocol_Register_6 |
| 155 | #define InvertAck (1<<0) |
| 156 | #define InvertReq (1<<1) |
| 157 | #define InvertClock (1<<2) |
| 158 | #define InvertSerial (1<<3) |
| 159 | #define OpenAck (1<<4) |
| 160 | #define OpenClock (1<<5) |
| 161 | |
| 162 | #define Protocol_Register_7 74 |
| 163 | #define AckSer Protocol_Register_7 |
| 164 | #define AckLine(x) (((x)&3)<<2) |
| 165 | #define ExchangePins (1<<7) |
| 166 | |
| 167 | #define Interrupt_Control 75 |
| 168 | /* bits same as flags */ |
| 169 | |
| 170 | #define DMA_Line_Control_Group1 76 |
| 171 | #define DMA_Line_Control_Group2 108 |
Bill Pemberton | 56e9e16 | 2009-04-23 15:54:52 -0400 | [diff] [blame] | 172 | /* channel zero is none */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 173 | static inline unsigned primary_DMAChannel_bits(unsigned channel) |
| 174 | { |
| 175 | return channel & 0x3; |
| 176 | } |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 177 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 178 | static inline unsigned secondary_DMAChannel_bits(unsigned channel) |
| 179 | { |
| 180 | return (channel << 2) & 0xc; |
| 181 | } |
| 182 | |
| 183 | #define Transfer_Size_Control 77 |
| 184 | #define TransferWidth(x) ((x)&3) |
| 185 | #define TransferLength(x) (((x)&3)<<3) |
| 186 | #define RequireRLevel (1<<5) |
| 187 | |
| 188 | #define Protocol_Register_15 79 |
| 189 | #define DAQOptions Protocol_Register_15 |
| 190 | #define StartSource(x) ((x)&0x3) |
| 191 | #define InvertStart (1<<2) |
| 192 | #define StopSource(x) (((x)&0x3)<<3) |
| 193 | #define ReqStart (1<<6) |
| 194 | #define PreStart (1<<7) |
| 195 | |
| 196 | #define Pattern_Detection 81 |
| 197 | #define DetectionMethod (1<<0) |
| 198 | #define InvertMatch (1<<1) |
| 199 | #define IE_Pattern_Detection (1<<2) |
| 200 | |
| 201 | #define Protocol_Register_9 82 |
| 202 | #define ReqDelay Protocol_Register_9 |
| 203 | |
| 204 | #define Protocol_Register_10 83 |
| 205 | #define ReqNotDelay Protocol_Register_10 |
| 206 | |
| 207 | #define Protocol_Register_11 84 |
| 208 | #define AckDelay Protocol_Register_11 |
| 209 | |
| 210 | #define Protocol_Register_12 85 |
| 211 | #define AckNotDelay Protocol_Register_12 |
| 212 | |
| 213 | #define Protocol_Register_13 86 |
| 214 | #define Data1Delay Protocol_Register_13 |
| 215 | |
| 216 | #define Protocol_Register_8 88 /* 32 bit */ |
| 217 | #define StartDelay Protocol_Register_8 |
| 218 | |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 219 | /* Firmware files for PCI-6524 */ |
| 220 | #define FW_PCI_6534_MAIN "ni6534a.bin" |
| 221 | #define FW_PCI_6534_SCARAB_DI "niscrb01.bin" |
| 222 | #define FW_PCI_6534_SCARAB_DO "niscrb02.bin" |
| 223 | MODULE_FIRMWARE(FW_PCI_6534_MAIN); |
| 224 | MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI); |
| 225 | MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO); |
| 226 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 227 | enum pci_6534_firmware_registers { /* 16 bit */ |
| 228 | Firmware_Control_Register = 0x100, |
| 229 | Firmware_Status_Register = 0x104, |
| 230 | Firmware_Data_Register = 0x108, |
| 231 | Firmware_Mask_Register = 0x10c, |
| 232 | Firmware_Debug_Register = 0x110, |
| 233 | }; |
| 234 | /* main fpga registers (32 bit)*/ |
| 235 | enum pci_6534_fpga_registers { |
| 236 | FPGA_Control1_Register = 0x200, |
| 237 | FPGA_Control2_Register = 0x204, |
| 238 | FPGA_Irq_Mask_Register = 0x208, |
| 239 | FPGA_Status_Register = 0x20c, |
| 240 | FPGA_Signature_Register = 0x210, |
| 241 | FPGA_SCALS_Counter_Register = 0x280, /*write-clear */ |
| 242 | FPGA_SCAMS_Counter_Register = 0x284, /*write-clear */ |
| 243 | FPGA_SCBLS_Counter_Register = 0x288, /*write-clear */ |
| 244 | FPGA_SCBMS_Counter_Register = 0x28c, /*write-clear */ |
| 245 | FPGA_Temp_Control_Register = 0x2a0, |
| 246 | FPGA_DAR_Register = 0x2a8, |
| 247 | FPGA_ELC_Read_Register = 0x2b8, |
| 248 | FPGA_ELC_Write_Register = 0x2bc, |
| 249 | }; |
| 250 | enum FPGA_Control_Bits { |
| 251 | FPGA_Enable_Bit = 0x8000, |
| 252 | }; |
| 253 | |
| 254 | #define TIMER_BASE 50 /* nanoseconds */ |
| 255 | |
| 256 | #ifdef USE_DMA |
| 257 | #define IntEn (CountExpired|Waited|PrimaryTC|SecondaryTC) |
| 258 | #else |
| 259 | #define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC) |
| 260 | #endif |
| 261 | |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 262 | enum nidio_boardid { |
| 263 | BOARD_PCIDIO_32HS, |
| 264 | BOARD_PXI6533, |
| 265 | BOARD_PCI6534, |
| 266 | }; |
| 267 | |
Bill Pemberton | a7195f3 | 2009-03-16 22:16:39 -0400 | [diff] [blame] | 268 | struct nidio_board { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 269 | const char *name; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 270 | unsigned int uses_firmware:1; |
Bill Pemberton | a7195f3 | 2009-03-16 22:16:39 -0400 | [diff] [blame] | 271 | }; |
| 272 | |
| 273 | static const struct nidio_board nidio_boards[] = { |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 274 | [BOARD_PCIDIO_32HS] = { |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 275 | .name = "pci-dio-32hs", |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 276 | }, |
| 277 | [BOARD_PXI6533] = { |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 278 | .name = "pxi-6533", |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 279 | }, |
| 280 | [BOARD_PCI6534] = { |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 281 | .name = "pci-6534", |
| 282 | .uses_firmware = 1, |
| 283 | }, |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 284 | }; |
| 285 | |
Bill Pemberton | 2e93aa5 | 2009-03-19 17:59:44 -0400 | [diff] [blame] | 286 | struct nidio96_private { |
H Hartley Sweeten | 1a8da31 | 2016-05-02 10:11:34 -0700 | [diff] [blame] | 287 | struct mite *mite; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 288 | int boardtype; |
| 289 | int dio; |
| 290 | unsigned short OpModeBits; |
| 291 | struct mite_channel *di_mite_chan; |
H Hartley Sweeten | 19d9212 | 2016-05-02 10:11:36 -0700 | [diff] [blame] | 292 | struct mite_ring *di_mite_ring; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 293 | spinlock_t mite_channel_lock; |
Bill Pemberton | 2e93aa5 | 2009-03-19 17:59:44 -0400 | [diff] [blame] | 294 | }; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 295 | |
Bill Pemberton | da91b26 | 2009-04-09 16:07:03 -0400 | [diff] [blame] | 296 | static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 297 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 298 | struct nidio96_private *devpriv = dev->private; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 299 | unsigned long flags; |
| 300 | |
Greg Kroah-Hartman | 5f74ea1 | 2009-04-27 14:44:31 -0700 | [diff] [blame] | 301 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 302 | BUG_ON(devpriv->di_mite_chan); |
| 303 | devpriv->di_mite_chan = |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 304 | mite_request_channel_in_range(devpriv->mite, |
| 305 | devpriv->di_mite_ring, 1, 2); |
H Hartley Sweeten | 4ce82de | 2015-03-04 12:15:37 -0700 | [diff] [blame] | 306 | if (!devpriv->di_mite_chan) { |
Greg Kroah-Hartman | 5f74ea1 | 2009-04-27 14:44:31 -0700 | [diff] [blame] | 307 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
H Hartley Sweeten | 74e9607 | 2014-07-17 11:57:32 -0700 | [diff] [blame] | 308 | dev_err(dev->class_dev, "failed to reserve mite dma channel\n"); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 309 | return -EBUSY; |
| 310 | } |
Ian Abbott | e3794b5 | 2012-01-09 15:47:31 +0000 | [diff] [blame] | 311 | devpriv->di_mite_chan->dir = COMEDI_INPUT; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 312 | writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 313 | secondary_DMAChannel_bits(devpriv->di_mite_chan->channel), |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 314 | dev->mmio + DMA_Line_Control_Group1); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 315 | mmiowb(); |
Greg Kroah-Hartman | 5f74ea1 | 2009-04-27 14:44:31 -0700 | [diff] [blame] | 316 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 317 | return 0; |
| 318 | } |
| 319 | |
Bill Pemberton | da91b26 | 2009-04-09 16:07:03 -0400 | [diff] [blame] | 320 | static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 321 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 322 | struct nidio96_private *devpriv = dev->private; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 323 | unsigned long flags; |
| 324 | |
Greg Kroah-Hartman | 5f74ea1 | 2009-04-27 14:44:31 -0700 | [diff] [blame] | 325 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 326 | if (devpriv->di_mite_chan) { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 327 | mite_release_channel(devpriv->di_mite_chan); |
| 328 | devpriv->di_mite_chan = NULL; |
| 329 | writeb(primary_DMAChannel_bits(0) | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 330 | secondary_DMAChannel_bits(0), |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 331 | dev->mmio + DMA_Line_Control_Group1); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 332 | mmiowb(); |
| 333 | } |
Greg Kroah-Hartman | 5f74ea1 | 2009-04-27 14:44:31 -0700 | [diff] [blame] | 334 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 335 | } |
| 336 | |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 337 | static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s) |
| 338 | { |
| 339 | struct nidio96_private *devpriv = dev->private; |
| 340 | int retval; |
| 341 | unsigned long flags; |
| 342 | |
| 343 | retval = ni_pcidio_request_di_mite_channel(dev); |
| 344 | if (retval) |
| 345 | return retval; |
| 346 | |
| 347 | /* write alloc the entire buffer */ |
| 348 | comedi_buf_write_alloc(s, s->async->prealloc_bufsz); |
| 349 | |
| 350 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
| 351 | if (devpriv->di_mite_chan) { |
| 352 | mite_prep_dma(devpriv->di_mite_chan, 32, 32); |
| 353 | mite_dma_arm(devpriv->di_mite_chan); |
H Hartley Sweeten | 6ac986d0 | 2015-03-05 13:21:18 -0700 | [diff] [blame] | 354 | } else { |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 355 | retval = -EIO; |
H Hartley Sweeten | 6ac986d0 | 2015-03-05 13:21:18 -0700 | [diff] [blame] | 356 | } |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 357 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
| 358 | |
| 359 | return retval; |
| 360 | } |
| 361 | |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 362 | static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s) |
| 363 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 364 | struct nidio96_private *devpriv = dev->private; |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 365 | unsigned long irq_flags; |
| 366 | int count; |
| 367 | |
| 368 | spin_lock_irqsave(&dev->spinlock, irq_flags); |
| 369 | spin_lock(&devpriv->mite_channel_lock); |
| 370 | if (devpriv->di_mite_chan) |
H Hartley Sweeten | 51d4300 | 2016-04-20 10:36:39 -0700 | [diff] [blame] | 371 | mite_sync_dma(devpriv->di_mite_chan, s); |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 372 | spin_unlock(&devpriv->mite_channel_lock); |
H Hartley Sweeten | f4f3f7c | 2014-06-20 10:58:28 -0700 | [diff] [blame] | 373 | count = comedi_buf_n_bytes_ready(s); |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 374 | spin_unlock_irqrestore(&dev->spinlock, irq_flags); |
| 375 | return count; |
| 376 | } |
| 377 | |
Jiri Slaby | 70265d2 | 2009-03-26 09:34:06 +0100 | [diff] [blame] | 378 | static irqreturn_t nidio_interrupt(int irq, void *d) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 379 | { |
Bill Pemberton | 71b5f4f | 2009-03-16 22:05:08 -0400 | [diff] [blame] | 380 | struct comedi_device *dev = d; |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 381 | struct nidio96_private *devpriv = dev->private; |
H Hartley Sweeten | 7a68ef9 | 2013-12-05 13:43:49 -0700 | [diff] [blame] | 382 | struct comedi_subdevice *s = dev->read_subdev; |
Bill Pemberton | d163679 | 2009-03-16 22:05:20 -0400 | [diff] [blame] | 383 | struct comedi_async *async = s->async; |
H Hartley Sweeten | dbe81a9 | 2014-10-22 15:37:12 -0700 | [diff] [blame] | 384 | unsigned int auxdata; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 385 | int flags; |
| 386 | int status; |
| 387 | int work = 0; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 388 | |
Bill Pemberton | 56e9e16 | 2009-04-23 15:54:52 -0400 | [diff] [blame] | 389 | /* interrupcions parasites */ |
Ian Abbott | a7401cd | 2013-03-15 13:15:33 +0000 | [diff] [blame] | 390 | if (!dev->attached) { |
Bill Pemberton | 56e9e16 | 2009-04-23 15:54:52 -0400 | [diff] [blame] | 391 | /* assume it's from another card */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 392 | return IRQ_NONE; |
| 393 | } |
| 394 | |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 395 | /* Lock to avoid race with comedi_poll */ |
| 396 | spin_lock(&dev->spinlock); |
| 397 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 398 | status = readb(dev->mmio + Interrupt_And_Window_Status); |
| 399 | flags = readb(dev->mmio + Group_1_Flags); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 400 | |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 401 | spin_lock(&devpriv->mite_channel_lock); |
H Hartley Sweeten | 4d88096 | 2016-04-20 10:36:37 -0700 | [diff] [blame] | 402 | if (devpriv->di_mite_chan) { |
H Hartley Sweeten | f7d005c | 2016-04-21 12:04:44 -0700 | [diff] [blame] | 403 | mite_ack_linkc(devpriv->di_mite_chan, s, false); |
| 404 | /* XXX need to byteswap sync'ed dma */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 405 | } |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 406 | spin_unlock(&devpriv->mite_channel_lock); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 407 | |
| 408 | while (status & DataLeft) { |
| 409 | work++; |
| 410 | if (work > 20) { |
H Hartley Sweeten | 20dad98 | 2013-11-26 10:21:14 -0700 | [diff] [blame] | 411 | dev_dbg(dev->class_dev, "too much work in interrupt\n"); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 412 | writeb(0x00, |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 413 | dev->mmio + Master_DMA_And_Interrupt_Control); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 414 | break; |
| 415 | } |
| 416 | |
| 417 | flags &= IntEn; |
| 418 | |
| 419 | if (flags & TransferReady) { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 420 | while (flags & TransferReady) { |
| 421 | work++; |
| 422 | if (work > 100) { |
H Hartley Sweeten | 20dad98 | 2013-11-26 10:21:14 -0700 | [diff] [blame] | 423 | dev_dbg(dev->class_dev, |
| 424 | "too much work in interrupt\n"); |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 425 | writeb(0x00, dev->mmio + |
Benjamin Adolphi | 2d2facd | 2010-02-06 16:17:06 +0100 | [diff] [blame] | 426 | Master_DMA_And_Interrupt_Control |
| 427 | ); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 428 | goto out; |
| 429 | } |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 430 | auxdata = readl(dev->mmio + Group_1_FIFO); |
H Hartley Sweeten | dbe81a9 | 2014-10-22 15:37:12 -0700 | [diff] [blame] | 431 | comedi_buf_write_samples(s, &auxdata, 1); |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 432 | flags = readb(dev->mmio + Group_1_Flags); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 433 | } |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 434 | } |
| 435 | |
| 436 | if (flags & CountExpired) { |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 437 | writeb(ClearExpired, dev->mmio + Group_1_Second_Clear); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 438 | async->events |= COMEDI_CB_EOA; |
| 439 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 440 | writeb(0x00, dev->mmio + OpMode); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 441 | break; |
| 442 | } else if (flags & Waited) { |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 443 | writeb(ClearWaited, dev->mmio + Group_1_First_Clear); |
H Hartley Sweeten | 3e6cb74 | 2015-01-20 12:06:02 -0700 | [diff] [blame] | 444 | async->events |= COMEDI_CB_ERROR; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 445 | break; |
| 446 | } else if (flags & PrimaryTC) { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 447 | writeb(ClearPrimaryTC, |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 448 | dev->mmio + Group_1_First_Clear); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 449 | async->events |= COMEDI_CB_EOA; |
| 450 | } else if (flags & SecondaryTC) { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 451 | writeb(ClearSecondaryTC, |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 452 | dev->mmio + Group_1_First_Clear); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 453 | async->events |= COMEDI_CB_EOA; |
| 454 | } |
H Hartley Sweeten | 20dad98 | 2013-11-26 10:21:14 -0700 | [diff] [blame] | 455 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 456 | flags = readb(dev->mmio + Group_1_Flags); |
| 457 | status = readb(dev->mmio + Interrupt_And_Window_Status); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 458 | } |
| 459 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 460 | out: |
H Hartley Sweeten | bd5ebdf | 2014-09-18 11:11:31 -0700 | [diff] [blame] | 461 | comedi_handle_events(dev, s); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 462 | #if 0 |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 463 | if (!tag) |
| 464 | writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 465 | #endif |
Ian Abbott | 02f69d6 | 2012-01-09 18:35:53 +0000 | [diff] [blame] | 466 | |
| 467 | spin_unlock(&dev->spinlock); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 468 | return IRQ_HANDLED; |
| 469 | } |
| 470 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 471 | static int ni_pcidio_insn_config(struct comedi_device *dev, |
| 472 | struct comedi_subdevice *s, |
H Hartley Sweeten | ddf62f2 | 2013-08-06 09:32:33 -0700 | [diff] [blame] | 473 | struct comedi_insn *insn, |
| 474 | unsigned int *data) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 475 | { |
H Hartley Sweeten | ddf62f2 | 2013-08-06 09:32:33 -0700 | [diff] [blame] | 476 | int ret; |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 477 | |
H Hartley Sweeten | ddf62f2 | 2013-08-06 09:32:33 -0700 | [diff] [blame] | 478 | ret = comedi_dio_insn_config(dev, s, insn, data, 0); |
| 479 | if (ret) |
| 480 | return ret; |
| 481 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 482 | writel(s->io_bits, dev->mmio + Port_Pin_Directions(0)); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 483 | |
H Hartley Sweeten | ddf62f2 | 2013-08-06 09:32:33 -0700 | [diff] [blame] | 484 | return insn->n; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 485 | } |
| 486 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 487 | static int ni_pcidio_insn_bits(struct comedi_device *dev, |
| 488 | struct comedi_subdevice *s, |
H Hartley Sweeten | 97f4289 | 2013-08-30 11:05:58 -0700 | [diff] [blame] | 489 | struct comedi_insn *insn, |
| 490 | unsigned int *data) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 491 | { |
H Hartley Sweeten | 97f4289 | 2013-08-30 11:05:58 -0700 | [diff] [blame] | 492 | if (comedi_dio_update_state(s, data)) |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 493 | writel(s->state, dev->mmio + Port_IO(0)); |
H Hartley Sweeten | 97f4289 | 2013-08-30 11:05:58 -0700 | [diff] [blame] | 494 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 495 | data[1] = readl(dev->mmio + Port_IO(0)); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 496 | |
H Hartley Sweeten | a2714e3 | 2012-06-18 13:16:35 -0700 | [diff] [blame] | 497 | return insn->n; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 498 | } |
| 499 | |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 500 | static int ni_pcidio_ns_to_timer(int *nanosec, unsigned int flags) |
| 501 | { |
| 502 | int divider, base; |
| 503 | |
| 504 | base = TIMER_BASE; |
| 505 | |
Ian Abbott | b302b8b | 2014-09-03 13:45:58 +0100 | [diff] [blame] | 506 | switch (flags & CMDF_ROUND_MASK) { |
| 507 | case CMDF_ROUND_NEAREST: |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 508 | default: |
Amitoj Kaur Chawla | 2ead7b3 | 2016-02-19 20:57:15 +0530 | [diff] [blame] | 509 | divider = DIV_ROUND_CLOSEST(*nanosec, base); |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 510 | break; |
Ian Abbott | b302b8b | 2014-09-03 13:45:58 +0100 | [diff] [blame] | 511 | case CMDF_ROUND_DOWN: |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 512 | divider = (*nanosec) / base; |
| 513 | break; |
Ian Abbott | b302b8b | 2014-09-03 13:45:58 +0100 | [diff] [blame] | 514 | case CMDF_ROUND_UP: |
Bhaktipriya Shridhar | b44483e | 2016-03-10 00:34:44 +0530 | [diff] [blame] | 515 | divider = DIV_ROUND_UP(*nanosec, base); |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 516 | break; |
| 517 | } |
| 518 | |
| 519 | *nanosec = base * divider; |
| 520 | return divider; |
| 521 | } |
| 522 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 523 | static int ni_pcidio_cmdtest(struct comedi_device *dev, |
| 524 | struct comedi_subdevice *s, struct comedi_cmd *cmd) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 525 | { |
| 526 | int err = 0; |
H Hartley Sweeten | 370936b | 2014-05-27 10:12:52 -0700 | [diff] [blame] | 527 | unsigned int arg; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 528 | |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 529 | /* Step 1 : check if triggers are trivially valid */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 530 | |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 531 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); |
| 532 | err |= comedi_check_trigger_src(&cmd->scan_begin_src, |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 533 | TRIG_TIMER | TRIG_EXT); |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 534 | err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); |
| 535 | err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); |
| 536 | err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 537 | |
| 538 | if (err) |
| 539 | return 1; |
| 540 | |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 541 | /* Step 2a : make sure trigger sources are unique */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 542 | |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 543 | err |= comedi_check_trigger_is_unique(cmd->start_src); |
| 544 | err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); |
| 545 | err |= comedi_check_trigger_is_unique(cmd->stop_src); |
H Hartley Sweeten | 27020ff | 2012-09-26 14:11:10 -0700 | [diff] [blame] | 546 | |
| 547 | /* Step 2b : and mutually compatible */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 548 | |
| 549 | if (err) |
| 550 | return 2; |
| 551 | |
H Hartley Sweeten | 616a14d | 2012-11-13 17:57:10 -0700 | [diff] [blame] | 552 | /* Step 3: check if arguments are trivially valid */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 553 | |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 554 | err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); |
H Hartley Sweeten | 616a14d | 2012-11-13 17:57:10 -0700 | [diff] [blame] | 555 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 556 | #define MAX_SPEED (TIMER_BASE) /* in nanoseconds */ |
| 557 | |
| 558 | if (cmd->scan_begin_src == TRIG_TIMER) { |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 559 | err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, |
| 560 | MAX_SPEED); |
Lucas De Marchi | 25985ed | 2011-03-30 22:57:33 -0300 | [diff] [blame] | 561 | /* no minimum speed */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 562 | } else { |
| 563 | /* TRIG_EXT */ |
| 564 | /* should be level/edge, hi/lo specification here */ |
Ian Abbott | 22494ed | 2012-01-09 15:47:33 +0000 | [diff] [blame] | 565 | if ((cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) != 0) { |
| 566 | cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT); |
H Hartley Sweeten | 616a14d | 2012-11-13 17:57:10 -0700 | [diff] [blame] | 567 | err |= -EINVAL; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 568 | } |
| 569 | } |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 570 | |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 571 | err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); |
| 572 | err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, |
| 573 | cmd->chanlist_len); |
H Hartley Sweeten | 616a14d | 2012-11-13 17:57:10 -0700 | [diff] [blame] | 574 | |
H Hartley Sweeten | 7be7f9c | 2014-09-09 16:15:51 -0700 | [diff] [blame] | 575 | if (cmd->stop_src == TRIG_COUNT) |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 576 | err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); |
H Hartley Sweeten | 7be7f9c | 2014-09-09 16:15:51 -0700 | [diff] [blame] | 577 | else /* TRIG_NONE */ |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 578 | err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 579 | |
| 580 | if (err) |
| 581 | return 3; |
| 582 | |
| 583 | /* step 4: fix up any arguments */ |
| 584 | |
| 585 | if (cmd->scan_begin_src == TRIG_TIMER) { |
H Hartley Sweeten | 370936b | 2014-05-27 10:12:52 -0700 | [diff] [blame] | 586 | arg = cmd->scan_begin_arg; |
H Hartley Sweeten | a207c12 | 2014-07-18 17:01:16 -0700 | [diff] [blame] | 587 | ni_pcidio_ns_to_timer(&arg, cmd->flags); |
Ian Abbott | 21ebbb1 | 2015-03-27 19:14:25 +0000 | [diff] [blame] | 588 | err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 589 | } |
| 590 | |
| 591 | if (err) |
| 592 | return 4; |
| 593 | |
| 594 | return 0; |
| 595 | } |
| 596 | |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 597 | static int ni_pcidio_inttrig(struct comedi_device *dev, |
| 598 | struct comedi_subdevice *s, |
| 599 | unsigned int trig_num) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 600 | { |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 601 | struct nidio96_private *devpriv = dev->private; |
| 602 | struct comedi_cmd *cmd = &s->async->cmd; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 603 | |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 604 | if (trig_num != cmd->start_arg) |
| 605 | return -EINVAL; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 606 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 607 | writeb(devpriv->OpModeBits, dev->mmio + OpMode); |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 608 | s->async->inttrig = NULL; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 609 | |
H Hartley Sweeten | 5d6e229 | 2014-07-18 17:01:18 -0700 | [diff] [blame] | 610 | return 1; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 611 | } |
| 612 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 613 | static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 614 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 615 | struct nidio96_private *devpriv = dev->private; |
Bill Pemberton | ea6d0d4 | 2009-03-16 22:05:47 -0400 | [diff] [blame] | 616 | struct comedi_cmd *cmd = &s->async->cmd; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 617 | |
| 618 | /* XXX configure ports for input */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 619 | writel(0x0000, dev->mmio + Port_Pin_Directions(0)); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 620 | |
| 621 | if (1) { |
| 622 | /* enable fifos A B C D */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 623 | writeb(0x0f, dev->mmio + Data_Path); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 624 | |
| 625 | /* set transfer width a 32 bits */ |
| 626 | writeb(TransferWidth(0) | TransferLength(0), |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 627 | dev->mmio + Transfer_Size_Control); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 628 | } else { |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 629 | writeb(0x03, dev->mmio + Data_Path); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 630 | writeb(TransferWidth(3) | TransferLength(0), |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 631 | dev->mmio + Transfer_Size_Control); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 632 | } |
| 633 | |
| 634 | /* protocol configuration */ |
| 635 | if (cmd->scan_begin_src == TRIG_TIMER) { |
| 636 | /* page 4-5, "input with internal REQs" */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 637 | writeb(0, dev->mmio + OpMode); |
| 638 | writeb(0x00, dev->mmio + ClockReg); |
| 639 | writeb(1, dev->mmio + Sequence); |
| 640 | writeb(0x04, dev->mmio + ReqReg); |
| 641 | writeb(4, dev->mmio + BlockMode); |
| 642 | writeb(3, dev->mmio + LinePolarities); |
| 643 | writeb(0xc0, dev->mmio + AckSer); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 644 | writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg, |
Ian Abbott | b302b8b | 2014-09-03 13:45:58 +0100 | [diff] [blame] | 645 | CMDF_ROUND_NEAREST), |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 646 | dev->mmio + StartDelay); |
| 647 | writeb(1, dev->mmio + ReqDelay); |
| 648 | writeb(1, dev->mmio + ReqNotDelay); |
| 649 | writeb(1, dev->mmio + AckDelay); |
| 650 | writeb(0x0b, dev->mmio + AckNotDelay); |
| 651 | writeb(0x01, dev->mmio + Data1Delay); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 652 | /* manual, page 4-5: ClockSpeed comment is incorrectly listed |
| 653 | * on DAQOptions */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 654 | writew(0, dev->mmio + ClockSpeed); |
| 655 | writeb(0, dev->mmio + DAQOptions); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 656 | } else { |
| 657 | /* TRIG_EXT */ |
| 658 | /* page 4-5, "input with external REQs" */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 659 | writeb(0, dev->mmio + OpMode); |
| 660 | writeb(0x00, dev->mmio + ClockReg); |
| 661 | writeb(0, dev->mmio + Sequence); |
| 662 | writeb(0x00, dev->mmio + ReqReg); |
| 663 | writeb(4, dev->mmio + BlockMode); |
| 664 | if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */ |
| 665 | writeb(0, dev->mmio + LinePolarities); |
| 666 | else /* Trailing Edge */ |
| 667 | writeb(2, dev->mmio + LinePolarities); |
| 668 | writeb(0x00, dev->mmio + AckSer); |
| 669 | writel(1, dev->mmio + StartDelay); |
| 670 | writeb(1, dev->mmio + ReqDelay); |
| 671 | writeb(1, dev->mmio + ReqNotDelay); |
| 672 | writeb(1, dev->mmio + AckDelay); |
| 673 | writeb(0x0C, dev->mmio + AckNotDelay); |
| 674 | writeb(0x10, dev->mmio + Data1Delay); |
| 675 | writew(0, dev->mmio + ClockSpeed); |
| 676 | writeb(0x60, dev->mmio + DAQOptions); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 677 | } |
| 678 | |
| 679 | if (cmd->stop_src == TRIG_COUNT) { |
| 680 | writel(cmd->stop_arg, |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 681 | dev->mmio + Transfer_Count); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 682 | } else { |
| 683 | /* XXX */ |
| 684 | } |
| 685 | |
| 686 | #ifdef USE_DMA |
| 687 | writeb(ClearPrimaryTC | ClearSecondaryTC, |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 688 | dev->mmio + Group_1_First_Clear); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 689 | |
| 690 | { |
| 691 | int retval = setup_mite_dma(dev, s); |
H Hartley Sweeten | fd28703 | 2014-07-16 11:02:07 -0700 | [diff] [blame] | 692 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 693 | if (retval) |
| 694 | return retval; |
| 695 | } |
| 696 | #else |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 697 | writeb(0x00, dev->mmio + DMA_Line_Control_Group1); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 698 | #endif |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 699 | writeb(0x00, dev->mmio + DMA_Line_Control_Group2); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 700 | |
| 701 | /* clear and enable interrupts */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 702 | writeb(0xff, dev->mmio + Group_1_First_Clear); |
| 703 | /* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 704 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 705 | writeb(IntEn, dev->mmio + Interrupt_Control); |
| 706 | writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 707 | |
| 708 | if (cmd->stop_src == TRIG_NONE) { |
| 709 | devpriv->OpModeBits = DataLatching(0) | RunMode(7); |
Bill Pemberton | 56e9e16 | 2009-04-23 15:54:52 -0400 | [diff] [blame] | 710 | } else { /* TRIG_TIMER */ |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 711 | devpriv->OpModeBits = Numbered | RunMode(7); |
| 712 | } |
| 713 | if (cmd->start_src == TRIG_NOW) { |
| 714 | /* start */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 715 | writeb(devpriv->OpModeBits, dev->mmio + OpMode); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 716 | s->async->inttrig = NULL; |
| 717 | } else { |
| 718 | /* TRIG_INT */ |
| 719 | s->async->inttrig = ni_pcidio_inttrig; |
| 720 | } |
| 721 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 722 | return 0; |
| 723 | } |
| 724 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 725 | static int ni_pcidio_cancel(struct comedi_device *dev, |
| 726 | struct comedi_subdevice *s) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 727 | { |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 728 | writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 729 | ni_pcidio_release_di_mite_channel(dev); |
| 730 | |
| 731 | return 0; |
| 732 | } |
| 733 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 734 | static int ni_pcidio_change(struct comedi_device *dev, |
H Hartley Sweeten | d546b89 | 2014-07-21 11:48:32 -0700 | [diff] [blame] | 735 | struct comedi_subdevice *s) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 736 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 737 | struct nidio96_private *devpriv = dev->private; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 738 | int ret; |
| 739 | |
Ian Abbott | b74e635 | 2014-05-06 13:12:15 +0100 | [diff] [blame] | 740 | ret = mite_buf_change(devpriv->di_mite_ring, s); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 741 | if (ret < 0) |
| 742 | return ret; |
| 743 | |
| 744 | memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz); |
| 745 | |
| 746 | return 0; |
| 747 | } |
| 748 | |
H Hartley Sweeten | d569541 | 2013-05-17 11:18:01 -0700 | [diff] [blame] | 749 | static int pci_6534_load_fpga(struct comedi_device *dev, |
| 750 | const u8 *data, size_t data_len, |
| 751 | unsigned long context) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 752 | { |
| 753 | static const int timeout = 1000; |
H Hartley Sweeten | d569541 | 2013-05-17 11:18:01 -0700 | [diff] [blame] | 754 | int fpga_index = context; |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 755 | int i; |
| 756 | size_t j; |
| 757 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 758 | writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register); |
| 759 | writew(0xc0 | fpga_index, dev->mmio + Firmware_Control_Register); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 760 | for (i = 0; |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 761 | (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 && |
| 762 | i < timeout; ++i) { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 763 | udelay(1); |
| 764 | } |
| 765 | if (i == timeout) { |
Ian Abbott | 6b26ecf | 2012-09-14 17:34:15 +0100 | [diff] [blame] | 766 | dev_warn(dev->class_dev, |
| 767 | "ni_pcidio: failed to load fpga %i, waiting for status 0x2\n", |
| 768 | fpga_index); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 769 | return -EIO; |
| 770 | } |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 771 | writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 772 | for (i = 0; |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 773 | readw(dev->mmio + Firmware_Status_Register) != 0x3 && |
| 774 | i < timeout; ++i) { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 775 | udelay(1); |
| 776 | } |
| 777 | if (i == timeout) { |
Ian Abbott | 6b26ecf | 2012-09-14 17:34:15 +0100 | [diff] [blame] | 778 | dev_warn(dev->class_dev, |
| 779 | "ni_pcidio: failed to load fpga %i, waiting for status 0x3\n", |
| 780 | fpga_index); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 781 | return -EIO; |
| 782 | } |
| 783 | for (j = 0; j + 1 < data_len;) { |
| 784 | unsigned int value = data[j++]; |
H Hartley Sweeten | fd28703 | 2014-07-16 11:02:07 -0700 | [diff] [blame] | 785 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 786 | value |= data[j++] << 8; |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 787 | writew(value, dev->mmio + Firmware_Data_Register); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 788 | for (i = 0; |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 789 | (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 790 | && i < timeout; ++i) { |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 791 | udelay(1); |
| 792 | } |
| 793 | if (i == timeout) { |
Ian Abbott | 6b26ecf | 2012-09-14 17:34:15 +0100 | [diff] [blame] | 794 | dev_warn(dev->class_dev, |
| 795 | "ni_pcidio: failed to load word into fpga %i\n", |
| 796 | fpga_index); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 797 | return -EIO; |
| 798 | } |
| 799 | if (need_resched()) |
| 800 | schedule(); |
| 801 | } |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 802 | writew(0x0, dev->mmio + Firmware_Control_Register); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 803 | return 0; |
| 804 | } |
| 805 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 806 | static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 807 | { |
H Hartley Sweeten | d569541 | 2013-05-17 11:18:01 -0700 | [diff] [blame] | 808 | return pci_6534_load_fpga(dev, NULL, 0, fpga_index); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 809 | } |
| 810 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 811 | static int pci_6534_reset_fpgas(struct comedi_device *dev) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 812 | { |
| 813 | int ret; |
| 814 | int i; |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 815 | |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 816 | writew(0x0, dev->mmio + Firmware_Control_Register); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 817 | for (i = 0; i < 3; ++i) { |
| 818 | ret = pci_6534_reset_fpga(dev, i); |
| 819 | if (ret < 0) |
| 820 | break; |
| 821 | } |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 822 | writew(0x0, dev->mmio + Firmware_Mask_Register); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 823 | return ret; |
| 824 | } |
| 825 | |
Mithlesh Thukral | 0a85b6f | 2009-06-08 21:04:41 +0530 | [diff] [blame] | 826 | static void pci_6534_init_main_fpga(struct comedi_device *dev) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 827 | { |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 828 | writel(0, dev->mmio + FPGA_Control1_Register); |
| 829 | writel(0, dev->mmio + FPGA_Control2_Register); |
| 830 | writel(0, dev->mmio + FPGA_SCALS_Counter_Register); |
| 831 | writel(0, dev->mmio + FPGA_SCAMS_Counter_Register); |
| 832 | writel(0, dev->mmio + FPGA_SCBLS_Counter_Register); |
| 833 | writel(0, dev->mmio + FPGA_SCBMS_Counter_Register); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 834 | } |
| 835 | |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 836 | static int pci_6534_upload_firmware(struct comedi_device *dev) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 837 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 838 | struct nidio96_private *devpriv = dev->private; |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 839 | static const char *const fw_file[3] = { |
| 840 | FW_PCI_6534_SCARAB_DI, /* loaded into scarab A for DI */ |
| 841 | FW_PCI_6534_SCARAB_DO, /* loaded into scarab B for DO */ |
| 842 | FW_PCI_6534_MAIN, /* loaded into main FPGA */ |
| 843 | }; |
H Hartley Sweeten | d569541 | 2013-05-17 11:18:01 -0700 | [diff] [blame] | 844 | int ret; |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 845 | int n; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 846 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 847 | ret = pci_6534_reset_fpgas(dev); |
| 848 | if (ret < 0) |
| 849 | return ret; |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 850 | /* load main FPGA first, then the two scarabs */ |
| 851 | for (n = 2; n >= 0; n--) { |
H Hartley Sweeten | d569541 | 2013-05-17 11:18:01 -0700 | [diff] [blame] | 852 | ret = comedi_load_firmware(dev, &devpriv->mite->pcidev->dev, |
| 853 | fw_file[n], |
| 854 | pci_6534_load_fpga, n); |
| 855 | if (ret == 0 && n == 2) |
| 856 | pci_6534_init_main_fpga(dev); |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 857 | if (ret < 0) |
| 858 | break; |
| 859 | } |
| 860 | return ret; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 861 | } |
| 862 | |
H Hartley Sweeten | de1e27a | 2013-12-05 13:43:48 -0700 | [diff] [blame] | 863 | static void nidio_reset_board(struct comedi_device *dev) |
| 864 | { |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 865 | writel(0, dev->mmio + Port_IO(0)); |
| 866 | writel(0, dev->mmio + Port_Pin_Directions(0)); |
| 867 | writel(0, dev->mmio + Port_Pin_Mask(0)); |
H Hartley Sweeten | de1e27a | 2013-12-05 13:43:48 -0700 | [diff] [blame] | 868 | |
| 869 | /* disable interrupts on board */ |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 870 | writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control); |
H Hartley Sweeten | de1e27a | 2013-12-05 13:43:48 -0700 | [diff] [blame] | 871 | } |
| 872 | |
Bill Pemberton | a690b7e | 2012-11-19 13:21:58 -0500 | [diff] [blame] | 873 | static int nidio_auto_attach(struct comedi_device *dev, |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 874 | unsigned long context) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 875 | { |
Ian Abbott | 750af5e | 2012-10-30 13:30:04 +0000 | [diff] [blame] | 876 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 877 | const struct nidio_board *board = NULL; |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 878 | struct nidio96_private *devpriv; |
Bill Pemberton | 34c4392 | 2009-03-16 22:05:14 -0400 | [diff] [blame] | 879 | struct comedi_subdevice *s; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 880 | int ret; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 881 | unsigned int irq; |
| 882 | |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 883 | if (context < ARRAY_SIZE(nidio_boards)) |
| 884 | board = &nidio_boards[context]; |
| 885 | if (!board) |
| 886 | return -ENODEV; |
| 887 | dev->board_ptr = board; |
H Hartley Sweeten | 7159888 | 2013-03-05 10:19:36 -0700 | [diff] [blame] | 888 | dev->board_name = board->name; |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 889 | |
H Hartley Sweeten | 818f569 | 2013-03-13 10:36:31 -0700 | [diff] [blame] | 890 | ret = comedi_pci_enable(dev); |
| 891 | if (ret) |
| 892 | return ret; |
H Hartley Sweeten | 818f569 | 2013-03-13 10:36:31 -0700 | [diff] [blame] | 893 | |
H Hartley Sweeten | 0bdab50 | 2013-06-24 16:55:44 -0700 | [diff] [blame] | 894 | devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); |
H Hartley Sweeten | c34fa26 | 2012-10-23 13:22:37 -0700 | [diff] [blame] | 895 | if (!devpriv) |
| 896 | return -ENOMEM; |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 897 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 898 | spin_lock_init(&devpriv->mite_channel_lock); |
| 899 | |
H Hartley Sweeten | 48f2c1a | 2016-05-02 10:11:45 -0700 | [diff] [blame] | 900 | devpriv->mite = mite_attach(dev, false); /* use win0 */ |
Ian Abbott | 21b74c2 | 2012-09-14 17:34:17 +0100 | [diff] [blame] | 901 | if (!devpriv->mite) |
Ian Abbott | f822a6a | 2012-09-14 17:34:32 +0100 | [diff] [blame] | 902 | return -ENOMEM; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 903 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 904 | devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite); |
H Hartley Sweeten | 4ce82de | 2015-03-04 12:15:37 -0700 | [diff] [blame] | 905 | if (!devpriv->di_mite_ring) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 906 | return -ENOMEM; |
| 907 | |
H Hartley Sweeten | 7159888 | 2013-03-05 10:19:36 -0700 | [diff] [blame] | 908 | if (board->uses_firmware) { |
Ian Abbott | 9fb5c14 | 2012-09-14 17:34:16 +0100 | [diff] [blame] | 909 | ret = pci_6534_upload_firmware(dev); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 910 | if (ret < 0) |
| 911 | return ret; |
| 912 | } |
Benjamin Adolphi | 2d2facd | 2010-02-06 16:17:06 +0100 | [diff] [blame] | 913 | |
H Hartley Sweeten | de1e27a | 2013-12-05 13:43:48 -0700 | [diff] [blame] | 914 | nidio_reset_board(dev); |
| 915 | |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 916 | ret = comedi_alloc_subdevices(dev, 1); |
H Hartley Sweeten | 8b6c569 | 2012-06-12 11:59:33 -0700 | [diff] [blame] | 917 | if (ret) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 918 | return ret; |
| 919 | |
Ian Abbott | 6b26ecf | 2012-09-14 17:34:15 +0100 | [diff] [blame] | 920 | dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name, |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 921 | readb(dev->mmio + Chip_Version)); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 922 | |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 923 | s = &dev->subdevices[0]; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 924 | |
H Hartley Sweeten | b37c1ae | 2012-09-13 10:24:00 -0700 | [diff] [blame] | 925 | dev->read_subdev = s; |
| 926 | s->type = COMEDI_SUBD_DIO; |
| 927 | s->subdev_flags = |
| 928 | SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED | |
| 929 | SDF_CMD_READ; |
| 930 | s->n_chan = 32; |
| 931 | s->range_table = &range_digital; |
| 932 | s->maxdata = 1; |
| 933 | s->insn_config = &ni_pcidio_insn_config; |
| 934 | s->insn_bits = &ni_pcidio_insn_bits; |
| 935 | s->do_cmd = &ni_pcidio_cmd; |
| 936 | s->do_cmdtest = &ni_pcidio_cmdtest; |
| 937 | s->cancel = &ni_pcidio_cancel; |
| 938 | s->len_chanlist = 32; /* XXX */ |
| 939 | s->buf_change = &ni_pcidio_change; |
| 940 | s->async_dma_dir = DMA_BIDIRECTIONAL; |
| 941 | s->poll = &ni_pcidio_poll; |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 942 | |
H Hartley Sweeten | ba9d29f | 2014-06-20 11:10:33 -0700 | [diff] [blame] | 943 | irq = pcidev->irq; |
H Hartley Sweeten | 19f5224 | 2013-12-03 12:07:26 -0700 | [diff] [blame] | 944 | if (irq) { |
| 945 | ret = request_irq(irq, nidio_interrupt, IRQF_SHARED, |
| 946 | dev->board_name, dev); |
| 947 | if (ret == 0) |
| 948 | dev->irq = irq; |
| 949 | } |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 950 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 951 | return 0; |
| 952 | } |
| 953 | |
H Hartley Sweeten | 484ecc9 | 2012-05-17 17:11:14 -0700 | [diff] [blame] | 954 | static void nidio_detach(struct comedi_device *dev) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 955 | { |
H Hartley Sweeten | 9a1a6cf | 2012-10-15 10:15:52 -0700 | [diff] [blame] | 956 | struct nidio96_private *devpriv = dev->private; |
| 957 | |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 958 | if (dev->irq) |
Greg Kroah-Hartman | 5f74ea1 | 2009-04-27 14:44:31 -0700 | [diff] [blame] | 959 | free_irq(dev->irq, dev); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 960 | if (devpriv) { |
| 961 | if (devpriv->di_mite_ring) { |
| 962 | mite_free_ring(devpriv->di_mite_ring); |
| 963 | devpriv->di_mite_ring = NULL; |
| 964 | } |
H Hartley Sweeten | b876e985 | 2014-06-20 11:10:35 -0700 | [diff] [blame] | 965 | mite_detach(devpriv->mite); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 966 | } |
H Hartley Sweeten | 5f8a5f4 | 2014-07-29 15:01:38 -0700 | [diff] [blame] | 967 | if (dev->mmio) |
| 968 | iounmap(dev->mmio); |
H Hartley Sweeten | 7f072f5 | 2013-03-13 10:35:51 -0700 | [diff] [blame] | 969 | comedi_pci_disable(dev); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 970 | } |
| 971 | |
H Hartley Sweeten | cb4c516 | 2012-05-15 17:09:09 -0700 | [diff] [blame] | 972 | static struct comedi_driver ni_pcidio_driver = { |
| 973 | .driver_name = "ni_pcidio", |
| 974 | .module = THIS_MODULE, |
Ian Abbott | 750af5e | 2012-10-30 13:30:04 +0000 | [diff] [blame] | 975 | .auto_attach = nidio_auto_attach, |
H Hartley Sweeten | cb4c516 | 2012-05-15 17:09:09 -0700 | [diff] [blame] | 976 | .detach = nidio_detach, |
| 977 | }; |
| 978 | |
Bill Pemberton | a690b7e | 2012-11-19 13:21:58 -0500 | [diff] [blame] | 979 | static int ni_pcidio_pci_probe(struct pci_dev *dev, |
H Hartley Sweeten | b8f4ac2 | 2013-03-05 09:53:41 -0700 | [diff] [blame] | 980 | const struct pci_device_id *id) |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 981 | { |
H Hartley Sweeten | b8f4ac2 | 2013-03-05 09:53:41 -0700 | [diff] [blame] | 982 | return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data); |
David Schleef | e209031 | 2009-02-19 09:47:26 -0800 | [diff] [blame] | 983 | } |
| 984 | |
Jingoo Han | 41e043f | 2013-12-03 08:26:00 +0900 | [diff] [blame] | 985 | static const struct pci_device_id ni_pcidio_pci_table[] = { |
H Hartley Sweeten | 6d6d443 | 2013-03-05 10:17:31 -0700 | [diff] [blame] | 986 | { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS }, |
| 987 | { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 }, |
| 988 | { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 }, |
H Hartley Sweeten | cb4c516 | 2012-05-15 17:09:09 -0700 | [diff] [blame] | 989 | { 0 } |
Arun Thomas | 727b286 | 2010-06-06 22:23:31 +0200 | [diff] [blame] | 990 | }; |
H Hartley Sweeten | cb4c516 | 2012-05-15 17:09:09 -0700 | [diff] [blame] | 991 | MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table); |
Arun Thomas | 727b286 | 2010-06-06 22:23:31 +0200 | [diff] [blame] | 992 | |
H Hartley Sweeten | cb4c516 | 2012-05-15 17:09:09 -0700 | [diff] [blame] | 993 | static struct pci_driver ni_pcidio_pci_driver = { |
| 994 | .name = "ni_pcidio", |
| 995 | .id_table = ni_pcidio_pci_table, |
| 996 | .probe = ni_pcidio_pci_probe, |
Peter Huewe | 9901a4d | 2013-01-22 23:40:03 +0100 | [diff] [blame] | 997 | .remove = comedi_pci_auto_unconfig, |
H Hartley Sweeten | cb4c516 | 2012-05-15 17:09:09 -0700 | [diff] [blame] | 998 | }; |
| 999 | module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver); |
Ian Abbott | 3c323c0 | 2011-02-07 13:39:52 +0000 | [diff] [blame] | 1000 | |
| 1001 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
| 1002 | MODULE_DESCRIPTION("Comedi low-level driver"); |
| 1003 | MODULE_LICENSE("GPL"); |