diff options
author | Gianluca Palli <gpalli@deis.unibo.it> | 2008-11-19 17:10:49 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-01-06 16:52:26 -0500 |
commit | 11e865c1dad436d2ce65c7d366030d1b62967a83 (patch) | |
tree | 665351bc4cf80108c2a2b9390937e9b3bdf61019 | |
parent | d2f63f9c67ef1a627e7b0ccd5e236272db118ceb (diff) |
Staging: comedi: add s626 driver
This adds the s626 comedi driver to the build.
From: Gianluca Palli <gpalli@deis.unibo.it>
Cc: David Schleef <ds@schleef.org>
Cc: Frank Mori Hess <fmhess@users.sourceforge.net>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/comedi/drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/s626.c | 3254 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers/s626.h | 802 |
3 files changed, 4057 insertions, 0 deletions
diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index bcc9ce816d05..cec0625c2388 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile | |||
@@ -11,6 +11,7 @@ obj-$(CONFIG_COMEDI) += comedi_parport.o | |||
11 | obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o | 11 | obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o |
12 | obj-$(CONFIG_COMEDI_PCI_DRIVERS) += icp_multi.o | 12 | obj-$(CONFIG_COMEDI_PCI_DRIVERS) += icp_multi.o |
13 | obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me4000.o | 13 | obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me4000.o |
14 | obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s626.o | ||
14 | 15 | ||
15 | # Comedi USB drivers | 16 | # Comedi USB drivers |
16 | obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o | 17 | obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o |
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c new file mode 100644 index 000000000000..469ee8c474c9 --- /dev/null +++ b/drivers/staging/comedi/drivers/s626.c | |||
@@ -0,0 +1,3254 @@ | |||
1 | /* | ||
2 | comedi/drivers/s626.c | ||
3 | Sensoray s626 Comedi driver | ||
4 | |||
5 | COMEDI - Linux Control and Measurement Device Interface | ||
6 | Copyright (C) 2000 David A. Schleef <ds@schleef.org> | ||
7 | |||
8 | Based on Sensoray Model 626 Linux driver Version 0.2 | ||
9 | Copyright (C) 2002-2004 Sensoray Co., Inc. | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | |||
25 | */ | ||
26 | |||
27 | /* | ||
28 | Driver: s626 | ||
29 | Description: Sensoray 626 driver | ||
30 | Devices: [Sensoray] 626 (s626) | ||
31 | Authors: Gianluca Palli <gpalli@deis.unibo.it>, | ||
32 | Updated: Fri, 15 Feb 2008 10:28:42 +0000 | ||
33 | Status: experimental | ||
34 | |||
35 | Configuration options: | ||
36 | [0] - PCI bus of device (optional) | ||
37 | [1] - PCI slot of device (optional) | ||
38 | If bus/slot is not specified, the first supported | ||
39 | PCI device found will be used. | ||
40 | |||
41 | INSN_CONFIG instructions: | ||
42 | analog input: | ||
43 | none | ||
44 | |||
45 | analog output: | ||
46 | none | ||
47 | |||
48 | digital channel: | ||
49 | s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels | ||
50 | supported configuration options: | ||
51 | INSN_CONFIG_DIO_QUERY | ||
52 | COMEDI_INPUT | ||
53 | COMEDI_OUTPUT | ||
54 | |||
55 | encoder: | ||
56 | Every channel must be configured before reading. | ||
57 | |||
58 | Example code | ||
59 | |||
60 | insn.insn=INSN_CONFIG; //configuration instruction | ||
61 | insn.n=1; //number of operation (must be 1) | ||
62 | insn.data=&initialvalue; //initial value loaded into encoder | ||
63 | //during configuration | ||
64 | insn.subdev=5; //encoder subdevice | ||
65 | insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel | ||
66 | //to configure | ||
67 | |||
68 | comedi_do_insn(cf,&insn); //executing configuration | ||
69 | */ | ||
70 | |||
71 | #include <linux/kernel.h> | ||
72 | #include <linux/types.h> | ||
73 | |||
74 | #include "../comedidev.h" | ||
75 | |||
76 | #include "comedi_pci.h" | ||
77 | |||
78 | #include "comedi_fc.h" | ||
79 | #include "s626.h" | ||
80 | |||
81 | MODULE_AUTHOR("Gianluca Palli <gpalli@deis.unibo.it>"); | ||
82 | MODULE_DESCRIPTION("Sensoray 626 Comedi driver module"); | ||
83 | MODULE_LICENSE("GPL"); | ||
84 | |||
85 | typedef struct s626_board_struct { | ||
86 | const char *name; | ||
87 | int ai_chans; | ||
88 | int ai_bits; | ||
89 | int ao_chans; | ||
90 | int ao_bits; | ||
91 | int dio_chans; | ||
92 | int dio_banks; | ||
93 | int enc_chans; | ||
94 | } s626_board; | ||
95 | |||
96 | static const s626_board s626_boards[] = { | ||
97 | { | ||
98 | name: "s626", | ||
99 | ai_chans:S626_ADC_CHANNELS, | ||
100 | ai_bits: 14, | ||
101 | ao_chans:S626_DAC_CHANNELS, | ||
102 | ao_bits: 13, | ||
103 | dio_chans:S626_DIO_CHANNELS, | ||
104 | dio_banks:S626_DIO_BANKS, | ||
105 | enc_chans:S626_ENCODER_CHANNELS, | ||
106 | } | ||
107 | }; | ||
108 | |||
109 | #define thisboard ((const s626_board *)dev->board_ptr) | ||
110 | #define PCI_VENDOR_ID_S626 0x1131 | ||
111 | #define PCI_DEVICE_ID_S626 0x7146 | ||
112 | |||
113 | static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = { | ||
114 | {PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
115 | 0}, | ||
116 | {0} | ||
117 | }; | ||
118 | |||
119 | MODULE_DEVICE_TABLE(pci, s626_pci_table); | ||
120 | |||
121 | static int s626_attach(comedi_device * dev, comedi_devconfig * it); | ||
122 | static int s626_detach(comedi_device * dev); | ||
123 | |||
124 | static comedi_driver driver_s626 = { | ||
125 | driver_name:"s626", | ||
126 | module:THIS_MODULE, | ||
127 | attach:s626_attach, | ||
128 | detach:s626_detach, | ||
129 | }; | ||
130 | |||
131 | typedef struct { | ||
132 | struct pci_dev *pdev; | ||
133 | void *base_addr; | ||
134 | int got_regions; | ||
135 | short allocatedBuf; | ||
136 | uint8_t ai_cmd_running; // ai_cmd is running | ||
137 | uint8_t ai_continous; // continous aquisition | ||
138 | int ai_sample_count; // number of samples to aquire | ||
139 | unsigned int ai_sample_timer; // time between samples in | ||
140 | // units of the timer | ||
141 | int ai_convert_count; // conversion counter | ||
142 | unsigned int ai_convert_timer; // time between conversion in | ||
143 | // units of the timer | ||
144 | uint16_t CounterIntEnabs; //Counter interrupt enable | ||
145 | //mask for MISC2 register. | ||
146 | uint8_t AdcItems; //Number of items in ADC poll | ||
147 | //list. | ||
148 | DMABUF RPSBuf; //DMA buffer used to hold ADC | ||
149 | //(RPS1) program. | ||
150 | DMABUF ANABuf; //DMA buffer used to receive | ||
151 | //ADC data and hold DAC data. | ||
152 | uint32_t *pDacWBuf; //Pointer to logical adrs of | ||
153 | //DMA buffer used to hold DAC | ||
154 | //data. | ||
155 | uint16_t Dacpol; //Image of DAC polarity | ||
156 | //register. | ||
157 | uint8_t TrimSetpoint[12]; //Images of TrimDAC setpoints. | ||
158 | //registers. | ||
159 | uint16_t ChargeEnabled; //Image of MISC2 Battery | ||
160 | //Charge Enabled (0 or | ||
161 | //WRMISC2_CHARGE_ENABLE). | ||
162 | uint16_t WDInterval; //Image of MISC2 watchdog | ||
163 | //interval control bits. | ||
164 | uint32_t I2CAdrs; //I2C device address for | ||
165 | //onboard EEPROM (board rev | ||
166 | //dependent). | ||
167 | // short I2Cards; | ||
168 | lsampl_t ao_readback[S626_DAC_CHANNELS]; | ||
169 | } s626_private; | ||
170 | |||
171 | typedef struct { | ||
172 | uint16_t RDDIn; | ||
173 | uint16_t WRDOut; | ||
174 | uint16_t RDEdgSel; | ||
175 | uint16_t WREdgSel; | ||
176 | uint16_t RDCapSel; | ||
177 | uint16_t WRCapSel; | ||
178 | uint16_t RDCapFlg; | ||
179 | uint16_t RDIntSel; | ||
180 | uint16_t WRIntSel; | ||
181 | } dio_private; | ||
182 | |||
183 | static dio_private dio_private_A = { | ||
184 | RDDIn:LP_RDDINA, | ||
185 | WRDOut:LP_WRDOUTA, | ||
186 | RDEdgSel:LP_RDEDGSELA, | ||
187 | WREdgSel:LP_WREDGSELA, | ||
188 | RDCapSel:LP_RDCAPSELA, | ||
189 | WRCapSel:LP_WRCAPSELA, | ||
190 | RDCapFlg:LP_RDCAPFLGA, | ||
191 | RDIntSel:LP_RDINTSELA, | ||
192 | WRIntSel:LP_WRINTSELA, | ||
193 | }; | ||
194 | |||
195 | static dio_private dio_private_B = { | ||
196 | RDDIn:LP_RDDINB, | ||
197 | WRDOut:LP_WRDOUTB, | ||
198 | RDEdgSel:LP_RDEDGSELB, | ||
199 | WREdgSel:LP_WREDGSELB, | ||
200 | RDCapSel:LP_RDCAPSELB, | ||
201 | WRCapSel:LP_WRCAPSELB, | ||
202 | RDCapFlg:LP_RDCAPFLGB, | ||
203 | RDIntSel:LP_RDINTSELB, | ||
204 | WRIntSel:LP_WRINTSELB, | ||
205 | }; | ||
206 | |||
207 | static dio_private dio_private_C = { | ||
208 | RDDIn:LP_RDDINC, | ||
209 | WRDOut:LP_WRDOUTC, | ||
210 | RDEdgSel:LP_RDEDGSELC, | ||
211 | WREdgSel:LP_WREDGSELC, | ||
212 | RDCapSel:LP_RDCAPSELC, | ||
213 | WRCapSel:LP_WRCAPSELC, | ||
214 | RDCapFlg:LP_RDCAPFLGC, | ||
215 | RDIntSel:LP_RDINTSELC, | ||
216 | WRIntSel:LP_WRINTSELC, | ||
217 | }; | ||
218 | |||
219 | /* to group dio devices (48 bits mask and data are not allowed ???) | ||
220 | static dio_private *dio_private_word[]={ | ||
221 | &dio_private_A, | ||
222 | &dio_private_B, | ||
223 | &dio_private_C, | ||
224 | }; | ||
225 | */ | ||
226 | |||
227 | #define devpriv ((s626_private *)dev->private) | ||
228 | #define diopriv ((dio_private *)s->private) | ||
229 | |||
230 | COMEDI_PCI_INITCLEANUP_NOMODULE(driver_s626, s626_pci_table); | ||
231 | |||
232 | //ioctl routines | ||
233 | static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s, | ||
234 | comedi_insn * insn, lsampl_t * data); | ||
235 | /* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data); */ | ||
236 | static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s, | ||
237 | comedi_insn * insn, lsampl_t * data); | ||
238 | static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s); | ||
239 | static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s, | ||
240 | comedi_cmd * cmd); | ||
241 | static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s); | ||
242 | static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s, | ||
243 | comedi_insn * insn, lsampl_t * data); | ||
244 | static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s, | ||
245 | comedi_insn * insn, lsampl_t * data); | ||
246 | static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s, | ||
247 | comedi_insn * insn, lsampl_t * data); | ||
248 | static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s, | ||
249 | comedi_insn * insn, lsampl_t * data); | ||
250 | static int s626_dio_set_irq(comedi_device * dev, unsigned int chan); | ||
251 | static int s626_dio_reset_irq(comedi_device * dev, unsigned int gruop, | ||
252 | unsigned int mask); | ||
253 | static int s626_dio_clear_irq(comedi_device * dev); | ||
254 | static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s, | ||
255 | comedi_insn * insn, lsampl_t * data); | ||
256 | static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s, | ||
257 | comedi_insn * insn, lsampl_t * data); | ||
258 | static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s, | ||
259 | comedi_insn * insn, lsampl_t * data); | ||
260 | static int s626_ns_to_timer(int *nanosec, int round_mode); | ||
261 | static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd); | ||
262 | static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s, | ||
263 | unsigned int trignum); | ||
264 | static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG); | ||
265 | static lsampl_t s626_ai_reg_to_uint(int data); | ||
266 | /* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data); */ | ||
267 | |||
268 | //end ioctl routines | ||
269 | |||
270 | //internal routines | ||
271 | static void s626_dio_init(comedi_device * dev); | ||
272 | static void ResetADC(comedi_device * dev, uint8_t * ppl); | ||
273 | static void LoadTrimDACs(comedi_device * dev); | ||
274 | static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan, | ||
275 | uint8_t DacData); | ||
276 | static uint8_t I2Cread(comedi_device * dev, uint8_t addr); | ||
277 | static uint32_t I2Chandshake(comedi_device * dev, uint32_t val); | ||
278 | static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata); | ||
279 | static void SendDAC(comedi_device * dev, uint32_t val); | ||
280 | static void WriteMISC2(comedi_device * dev, uint16_t NewImage); | ||
281 | static void DEBItransfer(comedi_device * dev); | ||
282 | static uint16_t DEBIread(comedi_device * dev, uint16_t addr); | ||
283 | static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata); | ||
284 | static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask, | ||
285 | uint16_t wdata); | ||
286 | static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize); | ||
287 | |||
288 | // COUNTER OBJECT ------------------------------------------------ | ||
289 | typedef struct enc_private_struct { | ||
290 | // Pointers to functions that differ for A and B counters: | ||
291 | uint16_t(*GetEnable) (comedi_device * dev, struct enc_private_struct *); //Return clock enable. | ||
292 | uint16_t(*GetIntSrc) (comedi_device * dev, struct enc_private_struct *); //Return interrupt source. | ||
293 | uint16_t(*GetLoadTrig) (comedi_device * dev, struct enc_private_struct *); //Return preload trigger source. | ||
294 | uint16_t(*GetMode) (comedi_device * dev, struct enc_private_struct *); //Return standardized operating mode. | ||
295 | void (*PulseIndex) (comedi_device * dev, struct enc_private_struct *); //Generate soft index strobe. | ||
296 | void (*SetEnable) (comedi_device * dev, struct enc_private_struct *, uint16_t enab); //Program clock enable. | ||
297 | void (*SetIntSrc) (comedi_device * dev, struct enc_private_struct *, uint16_t IntSource); //Program interrupt source. | ||
298 | void (*SetLoadTrig) (comedi_device * dev, struct enc_private_struct *, uint16_t Trig); //Program preload trigger source. | ||
299 | void (*SetMode) (comedi_device * dev, struct enc_private_struct *, uint16_t Setup, uint16_t DisableIntSrc); //Program standardized operating mode. | ||
300 | void (*ResetCapFlags) (comedi_device * dev, struct enc_private_struct *); //Reset event capture flags. | ||
301 | |||
302 | uint16_t MyCRA; // Address of CRA register. | ||
303 | uint16_t MyCRB; // Address of CRB register. | ||
304 | uint16_t MyLatchLsw; // Address of Latch least-significant-word | ||
305 | // register. | ||
306 | uint16_t MyEventBits[4]; // Bit translations for IntSrc -->RDMISC2. | ||
307 | } enc_private; //counter object | ||
308 | |||
309 | #define encpriv ((enc_private *)(dev->subdevices+5)->private) | ||
310 | |||
311 | //counters routines | ||
312 | static void s626_timer_load(comedi_device * dev, enc_private * k, int tick); | ||
313 | static uint32_t ReadLatch(comedi_device * dev, enc_private * k); | ||
314 | static void ResetCapFlags_A(comedi_device * dev, enc_private * k); | ||
315 | static void ResetCapFlags_B(comedi_device * dev, enc_private * k); | ||
316 | static uint16_t GetMode_A(comedi_device * dev, enc_private * k); | ||
317 | static uint16_t GetMode_B(comedi_device * dev, enc_private * k); | ||
318 | static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup, | ||
319 | uint16_t DisableIntSrc); | ||
320 | static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup, | ||
321 | uint16_t DisableIntSrc); | ||
322 | static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab); | ||
323 | static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab); | ||
324 | static uint16_t GetEnable_A(comedi_device * dev, enc_private * k); | ||
325 | static uint16_t GetEnable_B(comedi_device * dev, enc_private * k); | ||
326 | static void SetLatchSource(comedi_device * dev, enc_private * k, | ||
327 | uint16_t value); | ||
328 | /* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ); */ | ||
329 | static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig); | ||
330 | static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig); | ||
331 | static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k); | ||
332 | static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k); | ||
333 | static void SetIntSrc_B(comedi_device * dev, enc_private * k, | ||
334 | uint16_t IntSource); | ||
335 | static void SetIntSrc_A(comedi_device * dev, enc_private * k, | ||
336 | uint16_t IntSource); | ||
337 | static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k); | ||
338 | static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k); | ||
339 | /* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) ; */ | ||
340 | /* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) ; */ | ||
341 | /* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ); */ | ||
342 | /* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) ; */ | ||
343 | /* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */ | ||
344 | /* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ); */ | ||
345 | /* static void SetIndexSrc( comedi_device *dev,enc_private *k, uint16_t value ); */ | ||
346 | /* static uint16_t GetIndexSrc( comedi_device *dev,enc_private *k ); */ | ||
347 | static void PulseIndex_A(comedi_device * dev, enc_private * k); | ||
348 | static void PulseIndex_B(comedi_device * dev, enc_private * k); | ||
349 | static void Preload(comedi_device * dev, enc_private * k, uint32_t value); | ||
350 | static void CountersInit(comedi_device * dev); | ||
351 | //end internal routines | ||
352 | |||
353 | ///////////////////////////////////////////////////////////////////////// | ||
354 | // Counter objects constructor. | ||
355 | |||
356 | // Counter overflow/index event flag masks for RDMISC2. | ||
357 | #define INDXMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 - 1 ) : ( (C) * 2 + 4 ) ) ) | ||
358 | #define OVERMASK(C) ( 1 << ( ( (C) > 2 ) ? ( (C) * 2 + 5 ) : ( (C) * 2 + 10 ) ) ) | ||
359 | #define EVBITS(C) { 0, OVERMASK(C), INDXMASK(C), OVERMASK(C) | INDXMASK(C) } | ||
360 | |||
361 | // Translation table to map IntSrc into equivalent RDMISC2 event flag | ||
362 | // bits. | ||
363 | //static const uint16_t EventBits[][4] = { EVBITS(0), EVBITS(1), EVBITS(2), EVBITS(3), EVBITS(4), EVBITS(5) }; | ||
364 | |||
365 | /* enc_private; */ | ||
366 | static enc_private enc_private_data[] = { | ||
367 | { | ||
368 | GetEnable:GetEnable_A, | ||
369 | GetIntSrc:GetIntSrc_A, | ||
370 | GetLoadTrig:GetLoadTrig_A, | ||
371 | GetMode: GetMode_A, | ||
372 | PulseIndex:PulseIndex_A, | ||
373 | SetEnable:SetEnable_A, | ||
374 | SetIntSrc:SetIntSrc_A, | ||
375 | SetLoadTrig:SetLoadTrig_A, | ||
376 | SetMode: SetMode_A, | ||
377 | ResetCapFlags:ResetCapFlags_A, | ||
378 | MyCRA: LP_CR0A, | ||
379 | MyCRB: LP_CR0B, | ||
380 | MyLatchLsw:LP_CNTR0ALSW, | ||
381 | MyEventBits:EVBITS(0), | ||
382 | }, | ||
383 | { | ||
384 | GetEnable:GetEnable_A, | ||
385 | GetIntSrc:GetIntSrc_A, | ||
386 | GetLoadTrig:GetLoadTrig_A, | ||
387 | GetMode: GetMode_A, | ||
388 | PulseIndex:PulseIndex_A, | ||
389 | SetEnable:SetEnable_A, | ||
390 | SetIntSrc:SetIntSrc_A, | ||
391 | SetLoadTrig:SetLoadTrig_A, | ||
392 | SetMode: SetMode_A, | ||
393 | ResetCapFlags:ResetCapFlags_A, | ||
394 | MyCRA: LP_CR1A, | ||
395 | MyCRB: LP_CR1B, | ||
396 | MyLatchLsw:LP_CNTR1ALSW, | ||
397 | MyEventBits:EVBITS(1), | ||
398 | }, | ||
399 | { | ||
400 | GetEnable:GetEnable_A, | ||
401 | GetIntSrc:GetIntSrc_A, | ||
402 | GetLoadTrig:GetLoadTrig_A, | ||
403 | GetMode: GetMode_A, | ||
404 | PulseIndex:PulseIndex_A, | ||
405 | SetEnable:SetEnable_A, | ||
406 | SetIntSrc:SetIntSrc_A, | ||
407 | SetLoadTrig:SetLoadTrig_A, | ||
408 | SetMode: SetMode_A, | ||
409 | ResetCapFlags:ResetCapFlags_A, | ||
410 | MyCRA: LP_CR2A, | ||
411 | MyCRB: LP_CR2B, | ||
412 | MyLatchLsw:LP_CNTR2ALSW, | ||
413 | MyEventBits:EVBITS(2), | ||
414 | }, | ||
415 | { | ||
416 | GetEnable:GetEnable_B, | ||
417 | GetIntSrc:GetIntSrc_B, | ||
418 | GetLoadTrig:GetLoadTrig_B, | ||
419 | GetMode: GetMode_B, | ||
420 | PulseIndex:PulseIndex_B, | ||
421 | SetEnable:SetEnable_B, | ||
422 | SetIntSrc:SetIntSrc_B, | ||
423 | SetLoadTrig:SetLoadTrig_B, | ||
424 | SetMode: SetMode_B, | ||
425 | ResetCapFlags:ResetCapFlags_B, | ||
426 | MyCRA: LP_CR0A, | ||
427 | MyCRB: LP_CR0B, | ||
428 | MyLatchLsw:LP_CNTR0BLSW, | ||
429 | MyEventBits:EVBITS(3), | ||
430 | }, | ||
431 | { | ||
432 | GetEnable:GetEnable_B, | ||
433 | GetIntSrc:GetIntSrc_B, | ||
434 | GetLoadTrig:GetLoadTrig_B, | ||
435 | GetMode: GetMode_B, | ||
436 | PulseIndex:PulseIndex_B, | ||
437 | SetEnable:SetEnable_B, | ||
438 | SetIntSrc:SetIntSrc_B, | ||
439 | SetLoadTrig:SetLoadTrig_B, | ||
440 | SetMode: SetMode_B, | ||
441 | ResetCapFlags:ResetCapFlags_B, | ||
442 | MyCRA: LP_CR1A, | ||
443 | MyCRB: LP_CR1B, | ||
444 | MyLatchLsw:LP_CNTR1BLSW, | ||
445 | MyEventBits:EVBITS(4), | ||
446 | }, | ||
447 | { | ||
448 | GetEnable:GetEnable_B, | ||
449 | GetIntSrc:GetIntSrc_B, | ||
450 | GetLoadTrig:GetLoadTrig_B, | ||
451 | GetMode: GetMode_B, | ||
452 | PulseIndex:PulseIndex_B, | ||
453 | SetEnable:SetEnable_B, | ||
454 | SetIntSrc:SetIntSrc_B, | ||
455 | SetLoadTrig:SetLoadTrig_B, | ||
456 | SetMode: SetMode_B, | ||
457 | ResetCapFlags:ResetCapFlags_B, | ||
458 | MyCRA: LP_CR2A, | ||
459 | MyCRB: LP_CR2B, | ||
460 | MyLatchLsw:LP_CNTR2BLSW, | ||
461 | MyEventBits:EVBITS(5), | ||
462 | }, | ||
463 | }; | ||
464 | |||
465 | // enab/disable a function or test status bit(s) that are accessed | ||
466 | // through Main Control Registers 1 or 2. | ||
467 | #define MC_ENABLE( REGADRS, CTRLWORD ) writel( ( (uint32_t)( CTRLWORD ) << 16 ) | (uint32_t)( CTRLWORD ),devpriv->base_addr+( REGADRS ) ) | ||
468 | |||
469 | #define MC_DISABLE( REGADRS, CTRLWORD ) writel( (uint32_t)( CTRLWORD ) << 16 , devpriv->base_addr+( REGADRS ) ) | ||
470 | |||
471 | #define MC_TEST( REGADRS, CTRLWORD ) ( ( readl(devpriv->base_addr+( REGADRS )) & CTRLWORD ) != 0 ) | ||
472 | |||
473 | /* #define WR7146(REGARDS,CTRLWORD) | ||
474 | writel(CTRLWORD,(uint32_t)(devpriv->base_addr+(REGARDS))) */ | ||
475 | #define WR7146(REGARDS,CTRLWORD) writel(CTRLWORD,devpriv->base_addr+(REGARDS)) | ||
476 | |||
477 | /* #define RR7146(REGARDS) | ||
478 | readl((uint32_t)(devpriv->base_addr+(REGARDS))) */ | ||
479 | #define RR7146(REGARDS) readl(devpriv->base_addr+(REGARDS)) | ||
480 | |||
481 | #define BUGFIX_STREG(REGADRS) ( REGADRS - 4 ) | ||
482 | |||
483 | // Write a time slot control record to TSL2. | ||
484 | #define VECTPORT( VECTNUM ) (P_TSL2 + ( (VECTNUM) << 2 )) | ||
485 | #define SETVECT( VECTNUM, VECTVAL ) WR7146(VECTPORT( VECTNUM ), (VECTVAL)) | ||
486 | |||
487 | // Code macros used for constructing I2C command bytes. | ||
488 | #define I2C_B2(ATTR,VAL) ( ( (ATTR) << 6 ) | ( (VAL) << 24 ) ) | ||
489 | #define I2C_B1(ATTR,VAL) ( ( (ATTR) << 4 ) | ( (VAL) << 16 ) ) | ||
490 | #define I2C_B0(ATTR,VAL) ( ( (ATTR) << 2 ) | ( (VAL) << 8 ) ) | ||
491 | |||
492 | static const comedi_lrange s626_range_table = { 2, { | ||
493 | RANGE(-5, 5), | ||
494 | RANGE(-10, 10), | ||
495 | } | ||
496 | }; | ||
497 | |||
498 | static int s626_attach(comedi_device * dev, comedi_devconfig * it) | ||
499 | { | ||
500 | /* uint8_t PollList; */ | ||
501 | /* uint16_t AdcData; */ | ||
502 | /* uint16_t StartVal; */ | ||
503 | /* uint16_t index; */ | ||
504 | /* unsigned int data[16]; */ | ||
505 | int result; | ||
506 | int i; | ||
507 | int ret; | ||
508 | resource_size_t resourceStart; | ||
509 | dma_addr_t appdma; | ||
510 | comedi_subdevice *s; | ||
511 | struct pci_dev *pdev; | ||
512 | |||
513 | if (alloc_private(dev, sizeof(s626_private)) < 0) | ||
514 | return -ENOMEM; | ||
515 | |||
516 | for (pdev = pci_get_device(PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, | ||
517 | NULL); pdev != NULL; | ||
518 | pdev = pci_get_device(PCI_VENDOR_ID_S626, | ||
519 | PCI_DEVICE_ID_S626, pdev)) { | ||
520 | if (it->options[0] || it->options[1]) { | ||
521 | if (pdev->bus->number == it->options[0] && | ||
522 | PCI_SLOT(pdev->devfn) == it->options[1]) { | ||
523 | /* matches requested bus/slot */ | ||
524 | break; | ||
525 | } | ||
526 | } else { | ||
527 | /* no bus/slot specified */ | ||
528 | break; | ||
529 | } | ||
530 | } | ||
531 | devpriv->pdev = pdev; | ||
532 | |||
533 | if (pdev == NULL) { | ||
534 | printk("s626_attach: Board not present!!!\n"); | ||
535 | return -ENODEV; | ||
536 | } | ||
537 | |||
538 | if ((result = comedi_pci_enable(pdev, "s626")) < 0) { | ||
539 | printk("s626_attach: comedi_pci_enable fails\n"); | ||
540 | return -ENODEV; | ||
541 | } | ||
542 | devpriv->got_regions = 1; | ||
543 | |||
544 | resourceStart = pci_resource_start(devpriv->pdev, 0); | ||
545 | |||
546 | devpriv->base_addr = ioremap(resourceStart, SIZEOF_ADDRESS_SPACE); | ||
547 | if (devpriv->base_addr == NULL) { | ||
548 | printk("s626_attach: IOREMAP failed\n"); | ||
549 | return -ENODEV; | ||
550 | } | ||
551 | |||
552 | if (devpriv->base_addr) { | ||
553 | //disable master interrupt | ||
554 | writel(0, devpriv->base_addr + P_IER); | ||
555 | |||
556 | //soft reset | ||
557 | writel(MC1_SOFT_RESET, devpriv->base_addr + P_MC1); | ||
558 | |||
559 | //DMA FIXME DMA// | ||
560 | DEBUG("s626_attach: DMA ALLOCATION\n"); | ||
561 | |||
562 | //adc buffer allocation | ||
563 | devpriv->allocatedBuf = 0; | ||
564 | |||
565 | if ((devpriv->ANABuf.LogicalBase = | ||
566 | pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, | ||
567 | &appdma)) == NULL) { | ||
568 | printk("s626_attach: DMA Memory mapping error\n"); | ||
569 | return -ENOMEM; | ||
570 | } | ||
571 | |||
572 | devpriv->ANABuf.PhysicalBase = appdma; | ||
573 | |||
574 | DEBUG("s626_attach: AllocDMAB ADC Logical=%p, bsize=%d, Physical=0x%x\n", devpriv->ANABuf.LogicalBase, DMABUF_SIZE, (uint32_t) devpriv->ANABuf.PhysicalBase); | ||
575 | |||
576 | devpriv->allocatedBuf++; | ||
577 | |||
578 | if ((devpriv->RPSBuf.LogicalBase = | ||
579 | pci_alloc_consistent(devpriv->pdev, DMABUF_SIZE, | ||
580 | &appdma)) == NULL) { | ||
581 | printk("s626_attach: DMA Memory mapping error\n"); | ||
582 | return -ENOMEM; | ||
583 | } | ||
584 | |||
585 | devpriv->RPSBuf.PhysicalBase = appdma; | ||
586 | |||
587 | DEBUG("s626_attach: AllocDMAB RPS Logical=%p, bsize=%d, Physical=0x%x\n", devpriv->RPSBuf.LogicalBase, DMABUF_SIZE, (uint32_t) devpriv->RPSBuf.PhysicalBase); | ||
588 | |||
589 | devpriv->allocatedBuf++; | ||
590 | |||
591 | } | ||
592 | |||
593 | dev->board_ptr = s626_boards; | ||
594 | dev->board_name = thisboard->name; | ||
595 | |||
596 | if (alloc_subdevices(dev, 6) < 0) | ||
597 | return -ENOMEM; | ||
598 | |||
599 | dev->iobase = (unsigned long)devpriv->base_addr; | ||
600 | dev->irq = devpriv->pdev->irq; | ||
601 | |||
602 | //set up interrupt handler | ||
603 | if (dev->irq == 0) { | ||
604 | printk(" unknown irq (bad)\n"); | ||
605 | } else { | ||
606 | if ((ret = comedi_request_irq(dev->irq, s626_irq_handler, | ||
607 | IRQF_SHARED, "s626", dev)) < 0) { | ||
608 | printk(" irq not available\n"); | ||
609 | dev->irq = 0; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | DEBUG("s626_attach: -- it opts %d,%d -- \n", | ||
614 | it->options[0], it->options[1]); | ||
615 | |||
616 | s = dev->subdevices + 0; | ||
617 | /* analog input subdevice */ | ||
618 | dev->read_subdev = s; | ||
619 | /* we support single-ended (ground) and differential */ | ||
620 | s->type = COMEDI_SUBD_AI; | ||
621 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_CMD_READ; | ||
622 | s->n_chan = thisboard->ai_chans; | ||
623 | s->maxdata = (0xffff >> 2); | ||
624 | s->range_table = &s626_range_table; | ||
625 | s->len_chanlist = thisboard->ai_chans; /* This is the maximum chanlist | ||
626 | length that the board can | ||
627 | handle */ | ||
628 | s->insn_config = s626_ai_insn_config; | ||
629 | s->insn_read = s626_ai_insn_read; | ||
630 | s->do_cmd = s626_ai_cmd; | ||
631 | s->do_cmdtest = s626_ai_cmdtest; | ||
632 | s->cancel = s626_ai_cancel; | ||
633 | |||
634 | s = dev->subdevices + 1; | ||
635 | /* analog output subdevice */ | ||
636 | s->type = COMEDI_SUBD_AO; | ||
637 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; | ||
638 | s->n_chan = thisboard->ao_chans; | ||
639 | s->maxdata = (0x3fff); | ||
640 | s->range_table = &range_bipolar10; | ||
641 | s->insn_write = s626_ao_winsn; | ||
642 | s->insn_read = s626_ao_rinsn; | ||
643 | |||
644 | s = dev->subdevices + 2; | ||
645 | /* digital I/O subdevice */ | ||
646 | s->type = COMEDI_SUBD_DIO; | ||
647 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; | ||
648 | s->n_chan = S626_DIO_CHANNELS; | ||
649 | s->maxdata = 1; | ||
650 | s->io_bits = 0xffff; | ||
651 | s->private = &dio_private_A; | ||
652 | s->range_table = &range_digital; | ||
653 | s->insn_config = s626_dio_insn_config; | ||
654 | s->insn_bits = s626_dio_insn_bits; | ||
655 | |||
656 | s = dev->subdevices + 3; | ||
657 | /* digital I/O subdevice */ | ||
658 | s->type = COMEDI_SUBD_DIO; | ||
659 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; | ||
660 | s->n_chan = 16; | ||
661 | s->maxdata = 1; | ||
662 | s->io_bits = 0xffff; | ||
663 | s->private = &dio_private_B; | ||
664 | s->range_table = &range_digital; | ||
665 | s->insn_config = s626_dio_insn_config; | ||
666 | s->insn_bits = s626_dio_insn_bits; | ||
667 | |||
668 | s = dev->subdevices + 4; | ||
669 | /* digital I/O subdevice */ | ||
670 | s->type = COMEDI_SUBD_DIO; | ||
671 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; | ||
672 | s->n_chan = 16; | ||
673 | s->maxdata = 1; | ||
674 | s->io_bits = 0xffff; | ||
675 | s->private = &dio_private_C; | ||
676 | s->range_table = &range_digital; | ||
677 | s->insn_config = s626_dio_insn_config; | ||
678 | s->insn_bits = s626_dio_insn_bits; | ||
679 | |||
680 | s = dev->subdevices + 5; | ||
681 | /* encoder (counter) subdevice */ | ||
682 | s->type = COMEDI_SUBD_COUNTER; | ||
683 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL; | ||
684 | s->n_chan = thisboard->enc_chans; | ||
685 | s->private = enc_private_data; | ||
686 | s->insn_config = s626_enc_insn_config; | ||
687 | s->insn_read = s626_enc_insn_read; | ||
688 | s->insn_write = s626_enc_insn_write; | ||
689 | s->maxdata = 0xffffff; | ||
690 | s->range_table = &range_unknown; | ||
691 | |||
692 | //stop ai_command | ||
693 | devpriv->ai_cmd_running = 0; | ||
694 | |||
695 | if (devpriv->base_addr && (devpriv->allocatedBuf == 2)) { | ||
696 | dma_addr_t pPhysBuf; | ||
697 | uint16_t chan; | ||
698 | |||
699 | // enab DEBI and audio pins, enable I2C interface. | ||
700 | MC_ENABLE(P_MC1, MC1_DEBI | MC1_AUDIO | MC1_I2C); | ||
701 | // Configure DEBI operating mode. | ||
702 | WR7146(P_DEBICFG, DEBI_CFG_SLAVE16 // Local bus is 16 | ||
703 | // bits wide. | ||
704 | | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) // Declare DEBI | ||
705 | // transfer timeout | ||
706 | // interval. | ||
707 | | DEBI_SWAP // Set up byte lane | ||
708 | // steering. | ||
709 | | DEBI_CFG_INTEL); // Intel-compatible | ||
710 | // local bus (DEBI | ||
711 | // never times out). | ||
712 | DEBUG("s626_attach: %d debi init -- %d\n", | ||
713 | DEBI_CFG_SLAVE16 | (DEBI_TOUT << DEBI_CFG_TOUT_BIT) | | ||
714 | DEBI_SWAP | DEBI_CFG_INTEL, | ||
715 | DEBI_CFG_INTEL | DEBI_CFG_TOQ | DEBI_CFG_INCQ | | ||
716 | DEBI_CFG_16Q); | ||
717 | |||
718 | //DEBI INIT S626 WR7146( P_DEBICFG, DEBI_CFG_INTEL | DEBI_CFG_TOQ | ||
719 | //| DEBI_CFG_INCQ| DEBI_CFG_16Q); //end | ||
720 | |||
721 | // Paging is disabled. | ||
722 | WR7146(P_DEBIPAGE, DEBI_PAGE_DISABLE); // Disable MMU paging. | ||
723 | |||
724 | // Init GPIO so that ADC Start* is negated. | ||
725 | WR7146(P_GPIO, GPIO_BASE | GPIO1_HI); | ||
726 | |||
727 | //IsBoardRevA is a boolean that indicates whether the board is | ||
728 | //RevA. | ||
729 | |||
730 | // VERSION 2.01 CHANGE: REV A & B BOARDS NOW SUPPORTED BY DYNAMIC | ||
731 | // EEPROM ADDRESS SELECTION. Initialize the I2C interface, which | ||
732 | // is used to access the onboard serial EEPROM. The EEPROM's I2C | ||
733 | // DeviceAddress is hardwired to a value that is dependent on the | ||
734 | // 626 board revision. On all board revisions, the EEPROM stores | ||
735 | // TrimDAC calibration constants for analog I/O. On RevB and | ||
736 | // higher boards, the DeviceAddress is hardwired to 0 to enable | ||
737 | // the EEPROM to also store the PCI SubVendorID and SubDeviceID; | ||
738 | // this is the address at which the SAA7146 expects a | ||
739 | // configuration EEPROM to reside. On RevA boards, the EEPROM | ||
740 | // device address, which is hardwired to 4, prevents the SAA7146 | ||
741 | // from retrieving PCI sub-IDs, so the SAA7146 uses its built-in | ||
742 | // default values, instead. | ||
743 | |||
744 | // devpriv->I2Cards= IsBoardRevA ? 0xA8 : 0xA0; // Set I2C EEPROM | ||
745 | // DeviceType (0xA0) | ||
746 | // and DeviceAddress<<1. | ||
747 | |||
748 | devpriv->I2CAdrs = 0xA0; // I2C device address for onboard | ||
749 | // eeprom(revb) | ||
750 | |||
751 | // Issue an I2C ABORT command to halt any I2C operation in | ||
752 | //progress and reset BUSY flag. | ||
753 | WR7146(P_I2CSTAT, I2C_CLKSEL | I2C_ABORT); // Write I2C control: | ||
754 | // abort any I2C | ||
755 | // activity. | ||
756 | MC_ENABLE(P_MC2, MC2_UPLD_IIC); // Invoke command | ||
757 | // upload | ||
758 | while ((RR7146(P_MC2) & MC2_UPLD_IIC) == 0) ; // and wait for | ||
759 | // upload to | ||
760 | // complete. | ||
761 | |||
762 | // Per SAA7146 data sheet, write to STATUS reg twice to reset all | ||
763 | // I2C error flags. | ||
764 | for (i = 0; i < 2; i++) { | ||
765 | WR7146(P_I2CSTAT, I2C_CLKSEL); // Write I2C control: reset | ||
766 | // error flags. | ||
767 | MC_ENABLE(P_MC2, MC2_UPLD_IIC); // Invoke command upload | ||
768 | while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ; // and wait for | ||
769 | // upload to | ||
770 | // complete. | ||
771 | } | ||
772 | |||
773 | // Init audio interface functional attributes: set DAC/ADC serial | ||
774 | // clock rates, invert DAC serial clock so that DAC data setup | ||
775 | // times are satisfied, enable DAC serial clock out. | ||
776 | WR7146(P_ACON2, ACON2_INIT); | ||
777 | |||
778 | // Set up TSL1 slot list, which is used to control the | ||
779 | // accumulation of ADC data: RSD1 = shift data in on SD1. SIB_A1 | ||
780 | // = store data uint8_t at next available location in FB BUFFER1 | ||
781 | // register. | ||
782 | WR7146(P_TSL1, RSD1 | SIB_A1); // Fetch ADC high data | ||
783 | // uint8_t. | ||
784 | WR7146(P_TSL1 + 4, RSD1 | SIB_A1 | EOS); // Fetch ADC low data | ||
785 | // uint8_t; end of | ||
786 | // TSL1. | ||
787 | |||
788 | // enab TSL1 slot list so that it executes all the time. | ||
789 | WR7146(P_ACON1, ACON1_ADCSTART); | ||
790 | |||
791 | // Initialize RPS registers used for ADC. | ||
792 | |||
793 | //Physical start of RPS program. | ||
794 | WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase); | ||
795 | |||
796 | WR7146(P_RPSPAGE1, 0); // RPS program performs no | ||
797 | // explicit mem writes. | ||
798 | WR7146(P_RPS1_TOUT, 0); // Disable RPS timeouts. | ||
799 | |||
800 | // SAA7146 BUG WORKAROUND. Initialize SAA7146 ADC interface to a | ||
801 | // known state by invoking ADCs until FB BUFFER 1 register shows | ||
802 | // that it is correctly receiving ADC data. This is necessary | ||
803 | // because the SAA7146 ADC interface does not start up in a | ||
804 | // defined state after a PCI reset. | ||
805 | |||
806 | /* PollList = EOPL; // Create a simple polling */ | ||
807 | /* // list for analog input */ | ||
808 | /* // channel 0. */ | ||
809 | /* ResetADC( dev, &PollList ); */ | ||
810 | |||
811 | /* s626_ai_rinsn(dev,dev->subdevices,NULL,data); //( &AdcData ); // */ | ||
812 | /* //Get initial ADC */ | ||
813 | /* //value. */ | ||
814 | |||
815 | /* StartVal = data[0]; */ | ||
816 | |||
817 | /* // VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. */ | ||
818 | /* // Invoke ADCs until the new ADC value differs from the initial */ | ||
819 | /* // value or a timeout occurs. The timeout protects against the */ | ||
820 | /* // possibility that the driver is restarting and the ADC data is a */ | ||
821 | /* // fixed value resulting from the applied ADC analog input being */ | ||
822 | /* // unusually quiet or at the rail. */ | ||
823 | |||
824 | /* for ( index = 0; index < 500; index++ ) */ | ||
825 | /* { */ | ||
826 | /* s626_ai_rinsn(dev,dev->subdevices,NULL,data); */ | ||
827 | /* AdcData = data[0]; //ReadADC( &AdcData ); */ | ||
828 | /* if ( AdcData != StartVal ) */ | ||
829 | /* break; */ | ||
830 | /* } */ | ||
831 | |||
832 | // end initADC | ||
833 | |||
834 | // init the DAC interface | ||
835 | |||
836 | // Init Audio2's output DMAC attributes: burst length = 1 DWORD, | ||
837 | // threshold = 1 DWORD. | ||
838 | WR7146(P_PCI_BT_A, 0); | ||
839 | |||
840 | // Init Audio2's output DMA physical addresses. The protection | ||
841 | // address is set to 1 DWORD past the base address so that a | ||
842 | // single DWORD will be transferred each time a DMA transfer is | ||
843 | // enabled. | ||
844 | |||
845 | pPhysBuf = | ||
846 | devpriv->ANABuf.PhysicalBase + | ||
847 | (DAC_WDMABUF_OS * sizeof(uint32_t)); | ||
848 | |||
849 | WR7146(P_BASEA2_OUT, (uint32_t) pPhysBuf); // Buffer base adrs. | ||
850 | WR7146(P_PROTA2_OUT, (uint32_t) (pPhysBuf + sizeof(uint32_t))); // Protection address. | ||
851 | |||
852 | // Cache Audio2's output DMA buffer logical address. This is | ||
853 | // where DAC data is buffered for A2 output DMA transfers. | ||
854 | devpriv->pDacWBuf = | ||
855 | (uint32_t *) devpriv->ANABuf.LogicalBase + | ||
856 | DAC_WDMABUF_OS; | ||
857 | |||
858 | // Audio2's output channels does not use paging. The protection | ||
859 | // violation handling bit is set so that the DMAC will | ||
860 | // automatically halt and its PCI address pointer will be reset | ||
861 | // when the protection address is reached. | ||
862 | WR7146(P_PAGEA2_OUT, 8); | ||
863 | |||
864 | // Initialize time slot list 2 (TSL2), which is used to control | ||
865 | // the clock generation for and serialization of data to be sent | ||
866 | // to the DAC devices. Slot 0 is a NOP that is used to trap TSL | ||
867 | // execution; this permits other slots to be safely modified | ||
868 | // without first turning off the TSL sequencer (which is | ||
869 | // apparently impossible to do). Also, SD3 (which is driven by a | ||
870 | // pull-up resistor) is shifted in and stored to the MSB of | ||
871 | // FB_BUFFER2 to be used as evidence that the slot sequence has | ||
872 | // not yet finished executing. | ||
873 | SETVECT(0, XSD2 | RSD3 | SIB_A2 | EOS); // Slot 0: Trap TSL | ||
874 | // execution, shift 0xFF | ||
875 | // into FB_BUFFER2. | ||
876 | |||
877 | // Initialize slot 1, which is constant. Slot 1 causes a DWORD to | ||
878 | // be transferred from audio channel 2's output FIFO to the FIFO's | ||
879 | // output buffer so that it can be serialized and sent to the DAC | ||
880 | // during subsequent slots. All remaining slots are dynamically | ||
881 | // populated as required by the target DAC device. | ||
882 | SETVECT(1, LF_A2); // Slot 1: Fetch DWORD from Audio2's | ||
883 | // output FIFO. | ||
884 | |||
885 | // Start DAC's audio interface (TSL2) running. | ||
886 | WR7146(P_ACON1, ACON1_DACSTART); | ||
887 | |||
888 | //////////////////////////////////////////////////////// | ||
889 | |||
890 | // end init DAC interface | ||
891 | |||
892 | // Init Trim DACs to calibrated values. Do it twice because the | ||
893 | // SAA7146 audio channel does not always reset properly and | ||
894 | // sometimes causes the first few TrimDAC writes to malfunction. | ||
895 | |||
896 | LoadTrimDACs(dev); | ||
897 | LoadTrimDACs(dev); // Insurance. | ||
898 | |||
899 | ////////////////////////////////////////////////////////////////// | ||
900 | // Manually init all gate array hardware in case this is a soft | ||
901 | // reset (we have no way of determining whether this is a warm or | ||
902 | // cold start). This is necessary because the gate array will | ||
903 | // reset only in response to a PCI hard reset; there is no soft | ||
904 | // reset function. | ||
905 | |||
906 | // Init all DAC outputs to 0V and init all DAC setpoint and | ||
907 | // polarity images. | ||
908 | for (chan = 0; chan < S626_DAC_CHANNELS; chan++) | ||
909 | SetDAC(dev, chan, 0); | ||
910 | |||
911 | // Init image of WRMISC2 Battery Charger Enabled control bit. | ||
912 | // This image is used when the state of the charger control bit, | ||
913 | // which has no direct hardware readback mechanism, is queried. | ||
914 | devpriv->ChargeEnabled = 0; | ||
915 | |||
916 | // Init image of watchdog timer interval in WRMISC2. This image | ||
917 | // maintains the value of the control bits of MISC2 are | ||
918 | // continuously reset to zero as long as the WD timer is disabled. | ||
919 | devpriv->WDInterval = 0; | ||
920 | |||
921 | // Init Counter Interrupt enab mask for RDMISC2. This mask is | ||
922 | // applied against MISC2 when testing to determine which timer | ||
923 | // events are requesting interrupt service. | ||
924 | devpriv->CounterIntEnabs = 0; | ||
925 | |||
926 | // Init counters. | ||
927 | CountersInit(dev); | ||
928 | |||
929 | // Without modifying the state of the Battery Backup enab, disable | ||
930 | // the watchdog timer, set DIO channels 0-5 to operate in the | ||
931 | // standard DIO (vs. counter overflow) mode, disable the battery | ||
932 | // charger, and reset the watchdog interval selector to zero. | ||
933 | WriteMISC2(dev, (uint16_t) (DEBIread(dev, | ||
934 | LP_RDMISC2) & MISC2_BATT_ENABLE)); | ||
935 | |||
936 | // Initialize the digital I/O subsystem. | ||
937 | s626_dio_init(dev); | ||
938 | |||
939 | //enable interrupt test | ||
940 | // writel(IRQ_GPIO3 | IRQ_RPS1,devpriv->base_addr+P_IER); | ||
941 | } | ||
942 | |||
943 | DEBUG("s626_attach: comedi%d s626 attached %04x\n", dev->minor, | ||
944 | (uint32_t) devpriv->base_addr); | ||
945 | |||
946 | return 1; | ||
947 | } | ||
948 | |||
949 | static lsampl_t s626_ai_reg_to_uint(int data) | ||
950 | { | ||
951 | lsampl_t tempdata; | ||
952 | |||
953 | tempdata = (data >> 18); | ||
954 | if (tempdata & 0x2000) | ||
955 | tempdata &= 0x1fff; | ||
956 | else | ||
957 | tempdata += (1 << 13); | ||
958 | |||
959 | return tempdata; | ||
960 | } | ||
961 | |||
962 | /* static lsampl_t s626_uint_to_reg(comedi_subdevice *s, int data){ */ | ||
963 | /* return 0; */ | ||
964 | /* } */ | ||
965 | |||
966 | static irqreturn_t s626_irq_handler(int irq, void *d PT_REGS_ARG) | ||
967 | { | ||
968 | comedi_device *dev = d; | ||
969 | comedi_subdevice *s; | ||
970 | comedi_cmd *cmd; | ||
971 | enc_private *k; | ||
972 | unsigned long flags; | ||
973 | int32_t *readaddr; | ||
974 | uint32_t irqtype, irqstatus; | ||
975 | int i = 0; | ||
976 | sampl_t tempdata; | ||
977 | uint8_t group; | ||
978 | uint16_t irqbit; | ||
979 | |||
980 | DEBUG("s626_irq_handler: interrupt request recieved!!!\n"); | ||
981 | |||
982 | if (dev->attached == 0) | ||
983 | return IRQ_NONE; | ||
984 | // lock to avoid race with comedi_poll | ||
985 | comedi_spin_lock_irqsave(&dev->spinlock, flags); | ||
986 | |||
987 | //save interrupt enable register state | ||
988 | irqstatus = readl(devpriv->base_addr + P_IER); | ||
989 | |||
990 | //read interrupt type | ||
991 | irqtype = readl(devpriv->base_addr + P_ISR); | ||
992 | |||
993 | //disable master interrupt | ||
994 | writel(0, devpriv->base_addr + P_IER); | ||
995 | |||
996 | //clear interrupt | ||
997 | writel(irqtype, devpriv->base_addr + P_ISR); | ||
998 | |||
999 | //do somethings | ||
1000 | DEBUG("s626_irq_handler: interrupt type %d\n", irqtype); | ||
1001 | |||
1002 | switch (irqtype) { | ||
1003 | case IRQ_RPS1: // end_of_scan occurs | ||
1004 | |||
1005 | DEBUG("s626_irq_handler: RPS1 irq detected\n"); | ||
1006 | |||
1007 | // manage ai subdevice | ||
1008 | s = dev->subdevices; | ||
1009 | cmd = &(s->async->cmd); | ||
1010 | |||
1011 | // Init ptr to DMA buffer that holds new ADC data. We skip the | ||
1012 | // first uint16_t in the buffer because it contains junk data from | ||
1013 | // the final ADC of the previous poll list scan. | ||
1014 | readaddr = (int32_t *) devpriv->ANABuf.LogicalBase + 1; | ||
1015 | |||
1016 | // get the data and hand it over to comedi | ||
1017 | for (i = 0; i < (s->async->cmd.chanlist_len); i++) { | ||
1018 | // Convert ADC data to 16-bit integer values and copy to application | ||
1019 | // buffer. | ||
1020 | tempdata = s626_ai_reg_to_uint((int)*readaddr); | ||
1021 | readaddr++; | ||
1022 | |||
1023 | //put data into read buffer | ||
1024 | // comedi_buf_put(s->async, tempdata); | ||
1025 | if (cfc_write_to_buffer(s, tempdata) == 0) | ||
1026 | printk("s626_irq_handler: cfc_write_to_buffer error!\n"); | ||
1027 | |||
1028 | DEBUG("s626_irq_handler: ai channel %d acquired: %d\n", | ||
1029 | i, tempdata); | ||
1030 | } | ||
1031 | |||
1032 | //end of scan occurs | ||
1033 | s->async->events |= COMEDI_CB_EOS; | ||
1034 | |||
1035 | if (!(devpriv->ai_continous)) | ||
1036 | devpriv->ai_sample_count--; | ||
1037 | if (devpriv->ai_sample_count <= 0) { | ||
1038 | devpriv->ai_cmd_running = 0; | ||
1039 | |||
1040 | // Stop RPS program. | ||
1041 | MC_DISABLE(P_MC1, MC1_ERPS1); | ||
1042 | |||
1043 | //send end of acquisition | ||
1044 | s->async->events |= COMEDI_CB_EOA; | ||
1045 | |||
1046 | //disable master interrupt | ||
1047 | irqstatus = 0; | ||
1048 | } | ||
1049 | |||
1050 | if (devpriv->ai_cmd_running && cmd->scan_begin_src == TRIG_EXT) { | ||
1051 | DEBUG("s626_irq_handler: enable interrupt on dio channel %d\n", cmd->scan_begin_arg); | ||
1052 | |||
1053 | s626_dio_set_irq(dev, cmd->scan_begin_arg); | ||
1054 | |||
1055 | DEBUG("s626_irq_handler: External trigger is set!!!\n"); | ||
1056 | } | ||
1057 | // tell comedi that data is there | ||
1058 | DEBUG("s626_irq_handler: events %d\n", s->async->events); | ||
1059 | comedi_event(dev, s); | ||
1060 | break; | ||
1061 | case IRQ_GPIO3: //check dio and conter interrupt | ||
1062 | |||
1063 | DEBUG("s626_irq_handler: GPIO3 irq detected\n"); | ||
1064 | |||
1065 | // manage ai subdevice | ||
1066 | s = dev->subdevices; | ||
1067 | cmd = &(s->async->cmd); | ||
1068 | |||
1069 | //s626_dio_clear_irq(dev); | ||
1070 | |||
1071 | for (group = 0; group < S626_DIO_BANKS; group++) { | ||
1072 | irqbit = 0; | ||
1073 | //read interrupt type | ||
1074 | irqbit = DEBIread(dev, | ||
1075 | ((dio_private *) (dev->subdevices + 2 + | ||
1076 | group)->private)->RDCapFlg); | ||
1077 | |||
1078 | //check if interrupt is generated from dio channels | ||
1079 | if (irqbit) { | ||
1080 | s626_dio_reset_irq(dev, group, irqbit); | ||
1081 | DEBUG("s626_irq_handler: check interrupt on dio group %d %d\n", group, i); | ||
1082 | if (devpriv->ai_cmd_running) { | ||
1083 | //check if interrupt is an ai acquisition start trigger | ||
1084 | if ((irqbit >> (cmd->start_arg - | ||
1085 | (16 * group))) | ||
1086 | == 1 | ||
1087 | && cmd->start_src == TRIG_EXT) { | ||
1088 | DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->start_arg); | ||
1089 | |||
1090 | // Start executing the RPS program. | ||
1091 | MC_ENABLE(P_MC1, MC1_ERPS1); | ||
1092 | |||
1093 | DEBUG("s626_irq_handler: aquisition start triggered!!!\n"); | ||
1094 | |||
1095 | if (cmd->scan_begin_src == | ||
1096 | TRIG_EXT) { | ||
1097 | DEBUG("s626_ai_cmd: enable interrupt on dio channel %d\n", cmd->scan_begin_arg); | ||
1098 | |||
1099 | s626_dio_set_irq(dev, | ||
1100 | cmd-> | ||
1101 | scan_begin_arg); | ||
1102 | |||
1103 | DEBUG("s626_irq_handler: External scan trigger is set!!!\n"); | ||
1104 | } | ||
1105 | } | ||
1106 | if ((irqbit >> (cmd->scan_begin_arg - | ||
1107 | (16 * group))) | ||
1108 | == 1 | ||
1109 | && cmd->scan_begin_src == | ||
1110 | TRIG_EXT) { | ||
1111 | DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->scan_begin_arg); | ||
1112 | |||
1113 | // Trigger ADC scan loop start by setting RPS Signal 0. | ||
1114 | MC_ENABLE(P_MC2, MC2_ADC_RPS); | ||
1115 | |||
1116 | DEBUG("s626_irq_handler: scan triggered!!! %d\n", devpriv->ai_sample_count); | ||
1117 | if (cmd->convert_src == | ||
1118 | TRIG_EXT) { | ||
1119 | |||
1120 | DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n", cmd->convert_arg - (16 * group), group); | ||
1121 | |||
1122 | devpriv-> | ||
1123 | ai_convert_count | ||
1124 | = | ||
1125 | cmd-> | ||
1126 | chanlist_len; | ||
1127 | |||
1128 | s626_dio_set_irq(dev, | ||
1129 | cmd-> | ||
1130 | convert_arg); | ||
1131 | |||
1132 | DEBUG("s626_irq_handler: External convert trigger is set!!!\n"); | ||
1133 | } | ||
1134 | |||
1135 | if (cmd->convert_src == | ||
1136 | TRIG_TIMER) { | ||
1137 | k = &encpriv[5]; | ||
1138 | devpriv-> | ||
1139 | ai_convert_count | ||
1140 | = | ||
1141 | cmd-> | ||
1142 | chanlist_len; | ||
1143 | k->SetEnable(dev, k, | ||
1144 | CLKENAB_ALWAYS); | ||
1145 | } | ||
1146 | } | ||
1147 | if ((irqbit >> (cmd->convert_arg - | ||
1148 | (16 * group))) | ||
1149 | == 1 | ||
1150 | && cmd->convert_src == | ||
1151 | TRIG_EXT) { | ||
1152 | DEBUG("s626_irq_handler: Edge capture interrupt recieved from channel %d\n", cmd->convert_arg); | ||
1153 | |||
1154 | // Trigger ADC scan loop start by setting RPS Signal 0. | ||
1155 | MC_ENABLE(P_MC2, MC2_ADC_RPS); | ||
1156 | |||
1157 | DEBUG("s626_irq_handler: adc convert triggered!!!\n"); | ||
1158 | |||
1159 | devpriv->ai_convert_count--; | ||
1160 | |||
1161 | if (devpriv->ai_convert_count > | ||
1162 | 0) { | ||
1163 | |||
1164 | DEBUG("s626_ai_cmd: enable interrupt on dio channel %d group %d\n", cmd->convert_arg - (16 * group), group); | ||
1165 | |||
1166 | s626_dio_set_irq(dev, | ||
1167 | cmd-> | ||
1168 | convert_arg); | ||
1169 | |||
1170 | DEBUG("s626_irq_handler: External trigger is set!!!\n"); | ||
1171 | } | ||
1172 | } | ||
1173 | } | ||
1174 | break; | ||
1175 | } | ||
1176 | } | ||
1177 | |||
1178 | //read interrupt type | ||
1179 | irqbit = DEBIread(dev, LP_RDMISC2); | ||
1180 | |||
1181 | //check interrupt on counters | ||
1182 | DEBUG("s626_irq_handler: check counters interrupt %d\n", | ||
1183 | irqbit); | ||
1184 | |||
1185 | if (irqbit & IRQ_COINT1A) { | ||
1186 | DEBUG("s626_irq_handler: interrupt on counter 1A overflow\n"); | ||
1187 | k = &encpriv[0]; | ||
1188 | |||
1189 | //clear interrupt capture flag | ||
1190 | k->ResetCapFlags(dev, k); | ||
1191 | } | ||
1192 | if (irqbit & IRQ_COINT2A) { | ||
1193 | DEBUG("s626_irq_handler: interrupt on counter 2A overflow\n"); | ||
1194 | k = &encpriv[1]; | ||
1195 | |||
1196 | //clear interrupt capture flag | ||
1197 | k->ResetCapFlags(dev, k); | ||
1198 | } | ||
1199 | if (irqbit & IRQ_COINT3A) { | ||
1200 | DEBUG("s626_irq_handler: interrupt on counter 3A overflow\n"); | ||
1201 | k = &encpriv[2]; | ||
1202 | |||
1203 | //clear interrupt capture flag | ||
1204 | k->ResetCapFlags(dev, k); | ||
1205 | } | ||
1206 | if (irqbit & IRQ_COINT1B) { | ||
1207 | DEBUG("s626_irq_handler: interrupt on counter 1B overflow\n"); | ||
1208 | k = &encpriv[3]; | ||
1209 | |||
1210 | //clear interrupt capture flag | ||
1211 | k->ResetCapFlags(dev, k); | ||
1212 | } | ||
1213 | if (irqbit & IRQ_COINT2B) { | ||
1214 | DEBUG("s626_irq_handler: interrupt on counter 2B overflow\n"); | ||
1215 | k = &encpriv[4]; | ||
1216 | |||
1217 | //clear interrupt capture flag | ||
1218 | k->ResetCapFlags(dev, k); | ||
1219 | |||
1220 | if (devpriv->ai_convert_count > 0) { | ||
1221 | devpriv->ai_convert_count--; | ||
1222 | if (devpriv->ai_convert_count == 0) | ||
1223 | k->SetEnable(dev, k, CLKENAB_INDEX); | ||
1224 | |||
1225 | if (cmd->convert_src == TRIG_TIMER) { | ||
1226 | DEBUG("s626_irq_handler: conver timer trigger!!! %d\n", devpriv->ai_convert_count); | ||
1227 | |||
1228 | // Trigger ADC scan loop start by setting RPS Signal 0. | ||
1229 | MC_ENABLE(P_MC2, MC2_ADC_RPS); | ||
1230 | } | ||
1231 | } | ||
1232 | } | ||
1233 | if (irqbit & IRQ_COINT3B) { | ||
1234 | DEBUG("s626_irq_handler: interrupt on counter 3B overflow\n"); | ||
1235 | k = &encpriv[5]; | ||
1236 | |||
1237 | //clear interrupt capture flag | ||
1238 | k->ResetCapFlags(dev, k); | ||
1239 | |||
1240 | if (cmd->scan_begin_src == TRIG_TIMER) { | ||
1241 | DEBUG("s626_irq_handler: scan timer trigger!!!\n"); | ||
1242 | |||
1243 | // Trigger ADC scan loop start by setting RPS Signal 0. | ||
1244 | MC_ENABLE(P_MC2, MC2_ADC_RPS); | ||
1245 | } | ||
1246 | |||
1247 | if (cmd->convert_src == TRIG_TIMER) { | ||
1248 | DEBUG("s626_irq_handler: convert timer trigger is set\n"); | ||
1249 | k = &encpriv[4]; | ||
1250 | devpriv->ai_convert_count = cmd->chanlist_len; | ||
1251 | k->SetEnable(dev, k, CLKENAB_ALWAYS); | ||
1252 | } | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | //enable interrupt | ||
1257 | writel(irqstatus, devpriv->base_addr + P_IER); | ||
1258 | |||
1259 | DEBUG("s626_irq_handler: exit interrupt service routine.\n"); | ||
1260 | |||
1261 | comedi_spin_unlock_irqrestore(&dev->spinlock, flags); | ||
1262 | return IRQ_HANDLED; | ||
1263 | } | ||
1264 | |||
1265 | static int s626_detach(comedi_device * dev) | ||
1266 | { | ||
1267 | if (devpriv) { | ||
1268 | //stop ai_command | ||
1269 | devpriv->ai_cmd_running = 0; | ||
1270 | |||
1271 | if (devpriv->base_addr) { | ||
1272 | //interrupt mask | ||
1273 | WR7146(P_IER, 0); // Disable master interrupt. | ||
1274 | WR7146(P_ISR, IRQ_GPIO3 | IRQ_RPS1); // Clear board's IRQ status flag. | ||
1275 | |||
1276 | // Disable the watchdog timer and battery charger. | ||
1277 | WriteMISC2(dev, 0); | ||
1278 | |||
1279 | // Close all interfaces on 7146 device. | ||
1280 | WR7146(P_MC1, MC1_SHUTDOWN); | ||
1281 | WR7146(P_ACON1, ACON1_BASE); | ||
1282 | |||
1283 | CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE); | ||
1284 | CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE); | ||
1285 | } | ||
1286 | |||
1287 | if (dev->irq) { | ||
1288 | comedi_free_irq(dev->irq, dev); | ||
1289 | } | ||
1290 | |||
1291 | if (devpriv->base_addr) { | ||
1292 | iounmap(devpriv->base_addr); | ||
1293 | } | ||
1294 | |||
1295 | if (devpriv->pdev) { | ||
1296 | if (devpriv->got_regions) { | ||
1297 | comedi_pci_disable(devpriv->pdev); | ||
1298 | } | ||
1299 | pci_dev_put(devpriv->pdev); | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | DEBUG("s626_detach: S626 detached!\n"); | ||
1304 | |||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | /* | ||
1309 | * this functions build the RPS program for hardware driven acquistion | ||
1310 | */ | ||
1311 | void ResetADC(comedi_device * dev, uint8_t * ppl) | ||
1312 | { | ||
1313 | register uint32_t *pRPS; | ||
1314 | uint32_t JmpAdrs; | ||
1315 | uint16_t i; | ||
1316 | uint16_t n; | ||
1317 | uint32_t LocalPPL; | ||
1318 | comedi_cmd *cmd = &(dev->subdevices->async->cmd); | ||
1319 | |||
1320 | // Stop RPS program in case it is currently running. | ||
1321 | MC_DISABLE(P_MC1, MC1_ERPS1); | ||
1322 | |||
1323 | // Set starting logical address to write RPS commands. | ||
1324 | pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase; | ||
1325 | |||
1326 | // Initialize RPS instruction pointer. | ||
1327 | WR7146(P_RPSADDR1, (uint32_t) devpriv->RPSBuf.PhysicalBase); | ||
1328 | |||
1329 | // Construct RPS program in RPSBuf DMA buffer | ||
1330 | |||
1331 | if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) { | ||
1332 | DEBUG("ResetADC: scan_begin pause inserted\n"); | ||
1333 | // Wait for Start trigger. | ||
1334 | *pRPS++ = RPS_PAUSE | RPS_SIGADC; | ||
1335 | *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; | ||
1336 | } | ||
1337 | // SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary | ||
1338 | // because the first RPS DEBI Write following a non-RPS DEBI write | ||
1339 | // seems to always fail. If we don't do this dummy write, the ADC | ||
1340 | // gain might not be set to the value required for the first slot in | ||
1341 | // the poll list; the ADC gain would instead remain unchanged from | ||
1342 | // the previously programmed value. | ||
1343 | *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI Write command | ||
1344 | // and address to shadow RAM. | ||
1345 | *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; | ||
1346 | *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI immediate data | ||
1347 | // to shadow RAM: | ||
1348 | *pRPS++ = GSEL_BIPOLAR5V; // arbitrary immediate data | ||
1349 | // value. | ||
1350 | *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM | ||
1351 | // uploaded" flag. | ||
1352 | *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload. | ||
1353 | *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to finish. | ||
1354 | |||
1355 | // Digitize all slots in the poll list. This is implemented as a | ||
1356 | // for loop to limit the slot count to 16 in case the application | ||
1357 | // forgot to set the EOPL flag in the final slot. | ||
1358 | for (devpriv->AdcItems = 0; devpriv->AdcItems < 16; devpriv->AdcItems++) { | ||
1359 | // Convert application's poll list item to private board class | ||
1360 | // format. Each app poll list item is an uint8_t with form | ||
1361 | // (EOPL,x,x,RANGE,CHAN<3:0>), where RANGE code indicates 0 = | ||
1362 | // +-10V, 1 = +-5V, and EOPL = End of Poll List marker. | ||
1363 | LocalPPL = | ||
1364 | (*ppl << 8) | (*ppl & 0x10 ? GSEL_BIPOLAR5V : | ||
1365 | GSEL_BIPOLAR10V); | ||
1366 | |||
1367 | // Switch ADC analog gain. | ||
1368 | *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI command | ||
1369 | // and address to | ||
1370 | // shadow RAM. | ||
1371 | *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; | ||
1372 | *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI | ||
1373 | // immediate data to | ||
1374 | // shadow RAM. | ||
1375 | *pRPS++ = LocalPPL; | ||
1376 | *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM uploaded" | ||
1377 | // flag. | ||
1378 | *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload. | ||
1379 | *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to | ||
1380 | // finish. | ||
1381 | |||
1382 | // Select ADC analog input channel. | ||
1383 | *pRPS++ = RPS_LDREG | (P_DEBICMD >> 2); // Write DEBI command | ||
1384 | // and address to | ||
1385 | // shadow RAM. | ||
1386 | *pRPS++ = DEBI_CMD_WRWORD | LP_ISEL; | ||
1387 | *pRPS++ = RPS_LDREG | (P_DEBIAD >> 2); // Write DEBI | ||
1388 | // immediate data to | ||
1389 | // shadow RAM. | ||
1390 | *pRPS++ = LocalPPL; | ||
1391 | *pRPS++ = RPS_CLRSIGNAL | RPS_DEBI; // Reset "shadow RAM uploaded" | ||
1392 | // flag. | ||
1393 | *pRPS++ = RPS_UPLOAD | RPS_DEBI; // Invoke shadow RAM upload. | ||
1394 | *pRPS++ = RPS_PAUSE | RPS_DEBI; // Wait for shadow upload to | ||
1395 | // finish. | ||
1396 | |||
1397 | // Delay at least 10 microseconds for analog input settling. | ||
1398 | // Instead of padding with NOPs, we use RPS_JUMP instructions | ||
1399 | // here; this allows us to produce a longer delay than is | ||
1400 | // possible with NOPs because each RPS_JUMP flushes the RPS' | ||
1401 | // instruction prefetch pipeline. | ||
1402 | JmpAdrs = | ||
1403 | (uint32_t) devpriv->RPSBuf.PhysicalBase + | ||
1404 | (uint32_t) ((unsigned long)pRPS - | ||
1405 | (unsigned long)devpriv->RPSBuf.LogicalBase); | ||
1406 | for (i = 0; i < (10 * RPSCLK_PER_US / 2); i++) { | ||
1407 | JmpAdrs += 8; // Repeat to implement time delay: | ||
1408 | *pRPS++ = RPS_JUMP; // Jump to next RPS instruction. | ||
1409 | *pRPS++ = JmpAdrs; | ||
1410 | } | ||
1411 | |||
1412 | if (cmd != NULL && cmd->convert_src != TRIG_NOW) { | ||
1413 | DEBUG("ResetADC: convert pause inserted\n"); | ||
1414 | // Wait for Start trigger. | ||
1415 | *pRPS++ = RPS_PAUSE | RPS_SIGADC; | ||
1416 | *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; | ||
1417 | } | ||
1418 | // Start ADC by pulsing GPIO1. | ||
1419 | *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // Begin ADC Start pulse. | ||
1420 | *pRPS++ = GPIO_BASE | GPIO1_LO; | ||
1421 | *pRPS++ = RPS_NOP; | ||
1422 | // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. | ||
1423 | *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // End ADC Start pulse. | ||
1424 | *pRPS++ = GPIO_BASE | GPIO1_HI; | ||
1425 | |||
1426 | // Wait for ADC to complete (GPIO2 is asserted high when ADC not | ||
1427 | // busy) and for data from previous conversion to shift into FB | ||
1428 | // BUFFER 1 register. | ||
1429 | *pRPS++ = RPS_PAUSE | RPS_GPIO2; // Wait for ADC done. | ||
1430 | |||
1431 | // Transfer ADC data from FB BUFFER 1 register to DMA buffer. | ||
1432 | *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); | ||
1433 | *pRPS++ = | ||
1434 | (uint32_t) devpriv->ANABuf.PhysicalBase + | ||
1435 | (devpriv->AdcItems << 2); | ||
1436 | |||
1437 | // If this slot's EndOfPollList flag is set, all channels have | ||
1438 | // now been processed. | ||
1439 | if (*ppl++ & EOPL) { | ||
1440 | devpriv->AdcItems++; // Adjust poll list item count. | ||
1441 | break; // Exit poll list processing loop. | ||
1442 | } | ||
1443 | } | ||
1444 | DEBUG("ResetADC: ADC items %d \n", devpriv->AdcItems); | ||
1445 | |||
1446 | // VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the | ||
1447 | // ADC to stabilize for 2 microseconds before starting the final | ||
1448 | // (dummy) conversion. This delay is necessary to allow sufficient | ||
1449 | // time between last conversion finished and the start of the dummy | ||
1450 | // conversion. Without this delay, the last conversion's data value | ||
1451 | // is sometimes set to the previous conversion's data value. | ||
1452 | for (n = 0; n < (2 * RPSCLK_PER_US); n++) | ||
1453 | *pRPS++ = RPS_NOP; | ||
1454 | |||
1455 | // Start a dummy conversion to cause the data from the last | ||
1456 | // conversion of interest to be shifted in. | ||
1457 | *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // Begin ADC Start pulse. | ||
1458 | *pRPS++ = GPIO_BASE | GPIO1_LO; | ||
1459 | *pRPS++ = RPS_NOP; | ||
1460 | // VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. | ||
1461 | *pRPS++ = RPS_LDREG | (P_GPIO >> 2); // End ADC Start pulse. | ||
1462 | *pRPS++ = GPIO_BASE | GPIO1_HI; | ||
1463 | |||
1464 | // Wait for the data from the last conversion of interest to arrive | ||
1465 | // in FB BUFFER 1 register. | ||
1466 | *pRPS++ = RPS_PAUSE | RPS_GPIO2; // Wait for ADC done. | ||
1467 | |||
1468 | // Transfer final ADC data from FB BUFFER 1 register to DMA buffer. | ||
1469 | *pRPS++ = RPS_STREG | (BUGFIX_STREG(P_FB_BUFFER1) >> 2); // | ||
1470 | *pRPS++ = | ||
1471 | (uint32_t) devpriv->ANABuf.PhysicalBase + | ||
1472 | (devpriv->AdcItems << 2); | ||
1473 | |||
1474 | // Indicate ADC scan loop is finished. | ||
1475 | // *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ; // Signal ReadADC() that scan is done. | ||
1476 | |||
1477 | //invoke interrupt | ||
1478 | if (devpriv->ai_cmd_running == 1) { | ||
1479 | DEBUG("ResetADC: insert irq in ADC RPS task\n"); | ||
1480 | *pRPS++ = RPS_IRQ; | ||
1481 | } | ||
1482 | // Restart RPS program at its beginning. | ||
1483 | *pRPS++ = RPS_JUMP; // Branch to start of RPS program. | ||
1484 | *pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase; | ||
1485 | |||
1486 | // End of RPS program build | ||
1487 | // ------------------------------------------------------------ | ||
1488 | } | ||
1489 | |||
1490 | /* TO COMPLETE, IF NECESSARY */ | ||
1491 | static int s626_ai_insn_config(comedi_device * dev, comedi_subdevice * s, | ||
1492 | comedi_insn * insn, lsampl_t * data) | ||
1493 | { | ||
1494 | |||
1495 | return -EINVAL; | ||
1496 | } | ||
1497 | |||
1498 | /* static int s626_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) */ | ||
1499 | /* { */ | ||
1500 | /* register uint8_t i; */ | ||
1501 | /* register int32_t *readaddr; */ | ||
1502 | |||
1503 | /* DEBUG("as626_ai_rinsn: ai_rinsn enter \n"); */ | ||
1504 | |||
1505 | /* // Trigger ADC scan loop start by setting RPS Signal 0. */ | ||
1506 | /* MC_ENABLE( P_MC2, MC2_ADC_RPS ); */ | ||
1507 | |||
1508 | /* // Wait until ADC scan loop is finished (RPS Signal 0 reset). */ | ||
1509 | /* while ( MC_TEST( P_MC2, MC2_ADC_RPS ) ); */ | ||
1510 | |||
1511 | /* // Init ptr to DMA buffer that holds new ADC data. We skip the */ | ||
1512 | /* // first uint16_t in the buffer because it contains junk data from */ | ||
1513 | /* // the final ADC of the previous poll list scan. */ | ||
1514 | /* readaddr = (uint32_t *)devpriv->ANABuf.LogicalBase + 1; */ | ||
1515 | |||
1516 | /* // Convert ADC data to 16-bit integer values and copy to application */ | ||
1517 | /* // buffer. */ | ||
1518 | /* for ( i = 0; i < devpriv->AdcItems; i++ ) { */ | ||
1519 | /* *data = s626_ai_reg_to_uint( *readaddr++ ); */ | ||
1520 | /* DEBUG("s626_ai_rinsn: data %d \n",*data); */ | ||
1521 | /* data++; */ | ||
1522 | /* } */ | ||
1523 | |||
1524 | /* DEBUG("s626_ai_rinsn: ai_rinsn escape \n"); */ | ||
1525 | /* return i; */ | ||
1526 | /* } */ | ||
1527 | |||
1528 | static int s626_ai_insn_read(comedi_device * dev, comedi_subdevice * s, | ||
1529 | comedi_insn * insn, lsampl_t * data) | ||
1530 | { | ||
1531 | uint16_t chan = CR_CHAN(insn->chanspec); | ||
1532 | uint16_t range = CR_RANGE(insn->chanspec); | ||
1533 | uint16_t AdcSpec = 0; | ||
1534 | uint32_t GpioImage; | ||
1535 | int n; | ||
1536 | |||
1537 | /* //interrupt call test */ | ||
1538 | /* writel(IRQ_GPIO3,devpriv->base_addr+P_PSR); //Writing a logical 1 */ | ||
1539 | /* //into any of the RPS_PSR */ | ||
1540 | /* //bits causes the */ | ||
1541 | /* //corresponding interrupt */ | ||
1542 | /* //to be generated if */ | ||
1543 | /* //enabled */ | ||
1544 | |||
1545 | DEBUG("s626_ai_insn_read: entering\n"); | ||
1546 | |||
1547 | // Convert application's ADC specification into form | ||
1548 | // appropriate for register programming. | ||
1549 | if (range == 0) | ||
1550 | AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V); | ||
1551 | else | ||
1552 | AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V); | ||
1553 | |||
1554 | // Switch ADC analog gain. | ||
1555 | DEBIwrite(dev, LP_GSEL, AdcSpec); // Set gain. | ||
1556 | |||
1557 | // Select ADC analog input channel. | ||
1558 | DEBIwrite(dev, LP_ISEL, AdcSpec); // Select channel. | ||
1559 | |||
1560 | for (n = 0; n < insn->n; n++) { | ||
1561 | |||
1562 | // Delay 10 microseconds for analog input settling. | ||
1563 | comedi_udelay(10); | ||
1564 | |||
1565 | // Start ADC by pulsing GPIO1 low. | ||
1566 | GpioImage = RR7146(P_GPIO); | ||
1567 | // Assert ADC Start command | ||
1568 | WR7146(P_GPIO, GpioImage & ~GPIO1_HI); | ||
1569 | // and stretch it out. | ||
1570 | WR7146(P_GPIO, GpioImage & ~GPIO1_HI); | ||
1571 | WR7146(P_GPIO, GpioImage & ~GPIO1_HI); | ||
1572 | // Negate ADC Start command. | ||
1573 | WR7146(P_GPIO, GpioImage | GPIO1_HI); | ||
1574 | |||
1575 | // Wait for ADC to complete (GPIO2 is asserted high when | ||
1576 | // ADC not busy) and for data from previous conversion to | ||
1577 | // shift into FB BUFFER 1 register. | ||
1578 | |||
1579 | // Wait for ADC done. | ||
1580 | while (!(RR7146(P_PSR) & PSR_GPIO2)) ; | ||
1581 | |||
1582 | // Fetch ADC data. | ||
1583 | if (n != 0) | ||
1584 | data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1)); | ||
1585 | |||
1586 | // Allow the ADC to stabilize for 4 microseconds before | ||
1587 | // starting the next (final) conversion. This delay is | ||
1588 | // necessary to allow sufficient time between last | ||
1589 | // conversion finished and the start of the next | ||
1590 | // conversion. Without this delay, the last conversion's | ||
1591 | // data value is sometimes set to the previous | ||
1592 | // conversion's data value. | ||
1593 | comedi_udelay(4); | ||
1594 | } | ||
1595 | |||
1596 | // Start a dummy conversion to cause the data from the | ||
1597 | // previous conversion to be shifted in. | ||
1598 | GpioImage = RR7146(P_GPIO); | ||
1599 | |||
1600 | //Assert ADC Start command | ||
1601 | WR7146(P_GPIO, GpioImage & ~GPIO1_HI); | ||
1602 | // and stretch it out. | ||
1603 | WR7146(P_GPIO, GpioImage & ~GPIO1_HI); | ||
1604 | WR7146(P_GPIO, GpioImage & ~GPIO1_HI); | ||
1605 | // Negate ADC Start command. | ||
1606 | WR7146(P_GPIO, GpioImage | GPIO1_HI); | ||
1607 | |||
1608 | // Wait for the data to arrive in FB BUFFER 1 register. | ||
1609 | |||
1610 | // Wait for ADC done. | ||
1611 | while (!(RR7146(P_PSR) & PSR_GPIO2)) ; | ||
1612 | |||
1613 | // Fetch ADC data from audio interface's input shift | ||
1614 | // register. | ||
1615 | |||
1616 | // Fetch ADC data. | ||
1617 | if (n != 0) | ||
1618 | data[n - 1] = s626_ai_reg_to_uint(RR7146(P_FB_BUFFER1)); | ||
1619 | |||
1620 | DEBUG("s626_ai_insn_read: samples %d, data %d\n", n, data[n - 1]); | ||
1621 | |||
1622 | return n; | ||
1623 | } | ||
1624 | |||
1625 | static int s626_ai_load_polllist(uint8_t * ppl, comedi_cmd * cmd) | ||
1626 | { | ||
1627 | |||
1628 | int n; | ||
1629 | |||
1630 | for (n = 0; n < cmd->chanlist_len; n++) { | ||
1631 | if (CR_RANGE((cmd->chanlist)[n]) == 0) | ||
1632 | ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_5V); | ||
1633 | else | ||
1634 | ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_10V); | ||
1635 | } | ||
1636 | ppl[n - 1] |= EOPL; | ||
1637 | |||
1638 | return n; | ||
1639 | } | ||
1640 | |||
1641 | static int s626_ai_inttrig(comedi_device * dev, comedi_subdevice * s, | ||
1642 | unsigned int trignum) | ||
1643 | { | ||
1644 | if (trignum != 0) | ||
1645 | return -EINVAL; | ||
1646 | |||
1647 | DEBUG("s626_ai_inttrig: trigger adc start..."); | ||
1648 | |||
1649 | // Start executing the RPS program. | ||
1650 | MC_ENABLE(P_MC1, MC1_ERPS1); | ||
1651 | |||
1652 | s->async->inttrig = NULL; | ||
1653 | |||
1654 | DEBUG(" done\n"); | ||
1655 | |||
1656 | return 1; | ||
1657 | } | ||
1658 | |||
1659 | /* TO COMPLETE */ | ||
1660 | static int s626_ai_cmd(comedi_device * dev, comedi_subdevice * s) | ||
1661 | { | ||
1662 | |||
1663 | uint8_t ppl[16]; | ||
1664 | comedi_cmd *cmd = &s->async->cmd; | ||
1665 | enc_private *k; | ||
1666 | int tick; | ||
1667 | |||
1668 | DEBUG("s626_ai_cmd: entering command function\n"); | ||
1669 | |||
1670 | if (devpriv->ai_cmd_running) { | ||
1671 | printk("s626_ai_cmd: Another ai_cmd is running %d\n", | ||
1672 | dev->minor); | ||
1673 | return -EBUSY; | ||
1674 | } | ||
1675 | //disable interrupt | ||
1676 | writel(0, devpriv->base_addr + P_IER); | ||
1677 | |||
1678 | //clear interrupt request | ||
1679 | writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->base_addr + P_ISR); | ||
1680 | |||
1681 | //clear any pending interrupt | ||
1682 | s626_dio_clear_irq(dev); | ||
1683 | // s626_enc_clear_irq(dev); | ||
1684 | |||
1685 | //reset ai_cmd_running flag | ||
1686 | devpriv->ai_cmd_running = 0; | ||
1687 | |||
1688 | // test if cmd is valid | ||
1689 | if (cmd == NULL) { | ||
1690 | DEBUG("s626_ai_cmd: NULL command\n"); | ||
1691 | return -EINVAL; | ||
1692 | } else { | ||
1693 | DEBUG("s626_ai_cmd: command recieved!!!\n"); | ||
1694 | } | ||
1695 | |||
1696 | if (dev->irq == 0) { | ||
1697 | comedi_error(dev, | ||
1698 | "s626_ai_cmd: cannot run command without an irq"); | ||
1699 | return -EIO; | ||
1700 | } | ||
1701 | |||
1702 | s626_ai_load_polllist(ppl, cmd); | ||
1703 | devpriv->ai_cmd_running = 1; | ||
1704 | devpriv->ai_convert_count = 0; | ||
1705 | |||
1706 | switch (cmd->scan_begin_src) { | ||
1707 | case TRIG_FOLLOW: | ||
1708 | break; | ||
1709 | case TRIG_TIMER: | ||
1710 | // set a conter to generate adc trigger at scan_begin_arg interval | ||
1711 | k = &encpriv[5]; | ||
1712 | tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg, | ||
1713 | cmd->flags & TRIG_ROUND_MASK); | ||
1714 | |||
1715 | //load timer value and enable interrupt | ||
1716 | s626_timer_load(dev, k, tick); | ||
1717 | k->SetEnable(dev, k, CLKENAB_ALWAYS); | ||
1718 | |||
1719 | DEBUG("s626_ai_cmd: scan trigger timer is set with value %d\n", | ||
1720 | tick); | ||
1721 | |||
1722 | break; | ||
1723 | case TRIG_EXT: | ||
1724 | // set the digital line and interrupt for scan trigger | ||
1725 | if (cmd->start_src != TRIG_EXT) | ||
1726 | s626_dio_set_irq(dev, cmd->scan_begin_arg); | ||
1727 | |||
1728 | DEBUG("s626_ai_cmd: External scan trigger is set!!!\n"); | ||
1729 | |||
1730 | break; | ||
1731 | } | ||
1732 | |||
1733 | switch (cmd->convert_src) { | ||
1734 | case TRIG_NOW: | ||
1735 | break; | ||
1736 | case TRIG_TIMER: | ||
1737 | // set a conter to generate adc trigger at convert_arg interval | ||
1738 | k = &encpriv[4]; | ||
1739 | tick = s626_ns_to_timer((int *)&cmd->convert_arg, | ||
1740 | cmd->flags & TRIG_ROUND_MASK); | ||
1741 | |||
1742 | //load timer value and enable interrupt | ||
1743 | s626_timer_load(dev, k, tick); | ||
1744 | k->SetEnable(dev, k, CLKENAB_INDEX); | ||
1745 | |||
1746 | DEBUG("s626_ai_cmd: convert trigger timer is set with value %d\n", tick); | ||
1747 | break; | ||
1748 | case TRIG_EXT: | ||
1749 | // set the digital line and interrupt for convert trigger | ||
1750 | if (cmd->scan_begin_src != TRIG_EXT | ||
1751 | && cmd->start_src == TRIG_EXT) | ||
1752 | s626_dio_set_irq(dev, cmd->convert_arg); | ||
1753 | |||
1754 | DEBUG("s626_ai_cmd: External convert trigger is set!!!\n"); | ||
1755 | |||
1756 | break; | ||
1757 | } | ||
1758 | |||
1759 | switch (cmd->stop_src) { | ||
1760 | case TRIG_COUNT: | ||
1761 | // data arrives as one packet | ||
1762 | devpriv->ai_sample_count = cmd->stop_arg; | ||
1763 | devpriv->ai_continous = 0; | ||
1764 | break; | ||
1765 | case TRIG_NONE: | ||
1766 | // continous aquisition | ||
1767 | devpriv->ai_continous = 1; | ||
1768 | devpriv->ai_sample_count = 0; | ||
1769 | break; | ||
1770 | } | ||
1771 | |||
1772 | ResetADC(dev, ppl); | ||
1773 | |||
1774 | switch (cmd->start_src) { | ||
1775 | case TRIG_NOW: | ||
1776 | // Trigger ADC scan loop start by setting RPS Signal 0. | ||
1777 | // MC_ENABLE( P_MC2, MC2_ADC_RPS ); | ||
1778 | |||
1779 | // Start executing the RPS program. | ||
1780 | MC_ENABLE(P_MC1, MC1_ERPS1); | ||
1781 | |||
1782 | DEBUG("s626_ai_cmd: ADC triggered\n"); | ||
1783 | s->async->inttrig = NULL; | ||
1784 | break; | ||
1785 | case TRIG_EXT: | ||
1786 | //configure DIO channel for acquisition trigger | ||
1787 | s626_dio_set_irq(dev, cmd->start_arg); | ||
1788 | |||
1789 | DEBUG("s626_ai_cmd: External start trigger is set!!!\n"); | ||
1790 | |||
1791 | s->async->inttrig = NULL; | ||
1792 | break; | ||
1793 | case TRIG_INT: | ||
1794 | s->async->inttrig = s626_ai_inttrig; | ||
1795 | break; | ||
1796 | } | ||
1797 | |||
1798 | //enable interrupt | ||
1799 | writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->base_addr + P_IER); | ||
1800 | |||
1801 | DEBUG("s626_ai_cmd: command function terminated\n"); | ||
1802 | |||
1803 | return 0; | ||
1804 | } | ||
1805 | |||
1806 | static int s626_ai_cmdtest(comedi_device * dev, comedi_subdevice * s, | ||
1807 | comedi_cmd * cmd) | ||
1808 | { | ||
1809 | int err = 0; | ||
1810 | int tmp; | ||
1811 | |||
1812 | /* cmdtest tests a particular command to see if it is valid. Using | ||
1813 | * the cmdtest ioctl, a user can create a valid cmd and then have it | ||
1814 | * executes by the cmd ioctl. | ||
1815 | * | ||
1816 | * cmdtest returns 1,2,3,4 or 0, depending on which tests the | ||
1817 | * command passes. */ | ||
1818 | |||
1819 | /* step 1: make sure trigger sources are trivially valid */ | ||
1820 | |||
1821 | tmp = cmd->start_src; | ||
1822 | cmd->start_src &= TRIG_NOW | TRIG_INT | TRIG_EXT; | ||
1823 | if (!cmd->start_src || tmp != cmd->start_src) | ||
1824 | err++; | ||
1825 | |||
1826 | tmp = cmd->scan_begin_src; | ||
1827 | cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW; | ||
1828 | if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) | ||
1829 | err++; | ||
1830 | |||
1831 | tmp = cmd->convert_src; | ||
1832 | cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW; | ||
1833 | if (!cmd->convert_src || tmp != cmd->convert_src) | ||
1834 | err++; | ||
1835 | |||
1836 | tmp = cmd->scan_end_src; | ||
1837 | cmd->scan_end_src &= TRIG_COUNT; | ||
1838 | if (!cmd->scan_end_src || tmp != cmd->scan_end_src) | ||
1839 | err++; | ||
1840 | |||
1841 | tmp = cmd->stop_src; | ||
1842 | cmd->stop_src &= TRIG_COUNT | TRIG_NONE; | ||
1843 | if (!cmd->stop_src || tmp != cmd->stop_src) | ||
1844 | err++; | ||
1845 | |||
1846 | if (err) | ||
1847 | return 1; | ||
1848 | |||
1849 | /* step 2: make sure trigger sources are unique and mutually | ||
1850 | compatible */ | ||
1851 | |||
1852 | /* note that mutual compatiblity is not an issue here */ | ||
1853 | if (cmd->scan_begin_src != TRIG_TIMER && | ||
1854 | cmd->scan_begin_src != TRIG_EXT | ||
1855 | && cmd->scan_begin_src != TRIG_FOLLOW) | ||
1856 | err++; | ||
1857 | if (cmd->convert_src != TRIG_TIMER && | ||
1858 | cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) | ||
1859 | err++; | ||
1860 | if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) | ||
1861 | err++; | ||
1862 | |||
1863 | if (err) | ||
1864 | return 2; | ||
1865 | |||
1866 | /* step 3: make sure arguments are trivially compatible */ | ||
1867 | |||
1868 | if (cmd->start_src != TRIG_EXT && cmd->start_arg != 0) { | ||
1869 | cmd->start_arg = 0; | ||
1870 | err++; | ||
1871 | } | ||
1872 | |||
1873 | if (cmd->start_src == TRIG_EXT && cmd->start_arg < 0) { | ||
1874 | cmd->start_arg = 0; | ||
1875 | err++; | ||
1876 | } | ||
1877 | |||
1878 | if (cmd->start_src == TRIG_EXT && cmd->start_arg > 39) { | ||
1879 | cmd->start_arg = 39; | ||
1880 | err++; | ||
1881 | } | ||
1882 | |||
1883 | if (cmd->scan_begin_src == TRIG_EXT && cmd->scan_begin_arg < 0) { | ||
1884 | cmd->scan_begin_arg = 0; | ||
1885 | err++; | ||
1886 | } | ||
1887 | |||
1888 | if (cmd->scan_begin_src == TRIG_EXT && cmd->scan_begin_arg > 39) { | ||
1889 | cmd->scan_begin_arg = 39; | ||
1890 | err++; | ||
1891 | } | ||
1892 | |||
1893 | if (cmd->convert_src == TRIG_EXT && cmd->convert_arg < 0) { | ||
1894 | cmd->convert_arg = 0; | ||
1895 | err++; | ||
1896 | } | ||
1897 | |||
1898 | if (cmd->convert_src == TRIG_EXT && cmd->convert_arg > 39) { | ||
1899 | cmd->convert_arg = 39; | ||
1900 | err++; | ||
1901 | } | ||
1902 | #define MAX_SPEED 200000 /* in nanoseconds */ | ||
1903 | #define MIN_SPEED 2000000000 /* in nanoseconds */ | ||
1904 | |||
1905 | if (cmd->scan_begin_src == TRIG_TIMER) { | ||
1906 | if (cmd->scan_begin_arg < MAX_SPEED) { | ||
1907 | cmd->scan_begin_arg = MAX_SPEED; | ||
1908 | err++; | ||
1909 | } | ||
1910 | if (cmd->scan_begin_arg > MIN_SPEED) { | ||
1911 | cmd->scan_begin_arg = MIN_SPEED; | ||
1912 | err++; | ||
1913 | } | ||
1914 | } else { | ||
1915 | /* external trigger */ | ||
1916 | /* should be level/edge, hi/lo specification here */ | ||
1917 | /* should specify multiple external triggers */ | ||
1918 | /* if(cmd->scan_begin_arg>9){ */ | ||
1919 | /* cmd->scan_begin_arg=9; */ | ||
1920 | /* err++; */ | ||
1921 | /* } */ | ||
1922 | } | ||
1923 | if (cmd->convert_src == TRIG_TIMER) { | ||
1924 | if (cmd->convert_arg < MAX_SPEED) { | ||
1925 | cmd->convert_arg = MAX_SPEED; | ||
1926 | err++; | ||
1927 | } | ||
1928 | if (cmd->convert_arg > MIN_SPEED) { | ||
1929 | cmd->convert_arg = MIN_SPEED; | ||
1930 | err++; | ||
1931 | } | ||
1932 | } else { | ||
1933 | /* external trigger */ | ||
1934 | /* see above */ | ||
1935 | /* if(cmd->convert_arg>9){ */ | ||
1936 | /* cmd->convert_arg=9; */ | ||
1937 | /* err++; */ | ||
1938 | /* } */ | ||
1939 | } | ||
1940 | |||
1941 | if (cmd->scan_end_arg != cmd->chanlist_len) { | ||
1942 | cmd->scan_end_arg = cmd->chanlist_len; | ||
1943 | err++; | ||
1944 | } | ||
1945 | if (cmd->stop_src == TRIG_COUNT) { | ||
1946 | if (cmd->stop_arg > 0x00ffffff) { | ||
1947 | cmd->stop_arg = 0x00ffffff; | ||
1948 | err++; | ||
1949 | } | ||
1950 | } else { | ||
1951 | /* TRIG_NONE */ | ||
1952 | if (cmd->stop_arg != 0) { | ||
1953 | cmd->stop_arg = 0; | ||
1954 | err++; | ||
1955 | } | ||
1956 | } | ||
1957 | |||
1958 | if (err) | ||
1959 | return 3; | ||
1960 | |||
1961 | /* step 4: fix up any arguments */ | ||
1962 | |||
1963 | if (cmd->scan_begin_src == TRIG_TIMER) { | ||
1964 | tmp = cmd->scan_begin_arg; | ||
1965 | s626_ns_to_timer((int *)&cmd->scan_begin_arg, | ||
1966 | cmd->flags & TRIG_ROUND_MASK); | ||
1967 | if (tmp != cmd->scan_begin_arg) | ||
1968 | err++; | ||
1969 | } | ||
1970 | if (cmd->convert_src == TRIG_TIMER) { | ||
1971 | tmp = cmd->convert_arg; | ||
1972 | s626_ns_to_timer((int *)&cmd->convert_arg, | ||
1973 | cmd->flags & TRIG_ROUND_MASK); | ||
1974 | if (tmp != cmd->convert_arg) | ||
1975 | err++; | ||
1976 | if (cmd->scan_begin_src == TRIG_TIMER && | ||
1977 | cmd->scan_begin_arg < | ||
1978 | cmd->convert_arg * cmd->scan_end_arg) { | ||
1979 | cmd->scan_begin_arg = | ||
1980 | cmd->convert_arg * cmd->scan_end_arg; | ||
1981 | err++; | ||
1982 | } | ||
1983 | } | ||
1984 | |||
1985 | if (err) | ||
1986 | return 4; | ||
1987 | |||
1988 | return 0; | ||
1989 | } | ||
1990 | |||
1991 | static int s626_ai_cancel(comedi_device * dev, comedi_subdevice * s) | ||
1992 | { | ||
1993 | // Stop RPS program in case it is currently running. | ||
1994 | MC_DISABLE(P_MC1, MC1_ERPS1); | ||
1995 | |||
1996 | //disable master interrupt | ||
1997 | writel(0, devpriv->base_addr + P_IER); | ||
1998 | |||
1999 | devpriv->ai_cmd_running = 0; | ||
2000 | |||
2001 | return 0; | ||
2002 | } | ||
2003 | |||
2004 | /* This function doesn't require a particular form, this is just what | ||
2005 | * happens to be used in some of the drivers. It should convert ns | ||
2006 | * nanoseconds to a counter value suitable for programming the device. | ||
2007 | * Also, it should adjust ns so that it cooresponds to the actual time | ||
2008 | * that the device will use. */ | ||
2009 | static int s626_ns_to_timer(int *nanosec, int round_mode) | ||
2010 | { | ||
2011 | int divider, base; | ||
2012 | |||
2013 | base = 500; //2MHz internal clock | ||
2014 | |||
2015 | switch (round_mode) { | ||
2016 | case TRIG_ROUND_NEAREST: | ||
2017 | default: | ||
2018 | divider = (*nanosec + base / 2) / base; | ||
2019 | break; | ||
2020 | case TRIG_ROUND_DOWN: | ||
2021 | divider = (*nanosec) / base; | ||
2022 | break; | ||
2023 | case TRIG_ROUND_UP: | ||
2024 | divider = (*nanosec + base - 1) / base; | ||
2025 | break; | ||
2026 | } | ||
2027 | |||
2028 | *nanosec = base * divider; | ||
2029 | return divider - 1; | ||
2030 | } | ||
2031 | |||
2032 | static int s626_ao_winsn(comedi_device * dev, comedi_subdevice * s, | ||
2033 | comedi_insn * insn, lsampl_t * data) | ||
2034 | { | ||
2035 | |||
2036 | int i; | ||
2037 | uint16_t chan = CR_CHAN(insn->chanspec); | ||
2038 | int16_t dacdata; | ||
2039 | |||
2040 | for (i = 0; i < insn->n; i++) { | ||
2041 | dacdata = (int16_t) data[i]; | ||
2042 | devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[i]; | ||
2043 | dacdata -= (0x1fff); | ||
2044 | |||
2045 | SetDAC(dev, chan, dacdata); | ||
2046 | } | ||
2047 | |||
2048 | return i; | ||
2049 | } | ||
2050 | |||
2051 | static int s626_ao_rinsn(comedi_device * dev, comedi_subdevice * s, | ||
2052 | comedi_insn * insn, lsampl_t * data) | ||
2053 | { | ||
2054 | int i; | ||
2055 | |||
2056 | for (i = 0; i < insn->n; i++) { | ||
2057 | data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; | ||
2058 | } | ||
2059 | |||
2060 | return i; | ||
2061 | } | ||
2062 | |||
2063 | ///////////////////////////////////////////////////////////////////// | ||
2064 | /////////////// DIGITAL I/O FUNCTIONS ///////////////////////////// | ||
2065 | ///////////////////////////////////////////////////////////////////// | ||
2066 | // All DIO functions address a group of DIO channels by means of | ||
2067 | // "group" argument. group may be 0, 1 or 2, which correspond to DIO | ||
2068 | // ports A, B and C, respectively. | ||
2069 | ///////////////////////////////////////////////////////////////////// | ||
2070 | |||
2071 | static void s626_dio_init(comedi_device * dev) | ||
2072 | { | ||
2073 | uint16_t group; | ||
2074 | comedi_subdevice *s; | ||
2075 | |||
2076 | // Prepare to treat writes to WRCapSel as capture disables. | ||
2077 | DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); | ||
2078 | |||
2079 | // For each group of sixteen channels ... | ||
2080 | for (group = 0; group < S626_DIO_BANKS; group++) { | ||
2081 | s = dev->subdevices + 2 + group; | ||
2082 | DEBIwrite(dev, diopriv->WRIntSel, 0); // Disable all interrupts. | ||
2083 | DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF); // Disable all event | ||
2084 | // captures. | ||
2085 | DEBIwrite(dev, diopriv->WREdgSel, 0); // Init all DIOs to | ||
2086 | // default edge | ||
2087 | // polarity. | ||
2088 | DEBIwrite(dev, diopriv->WRDOut, 0); // Program all outputs | ||
2089 | // to inactive state. | ||
2090 | } | ||
2091 | DEBUG("s626_dio_init: DIO initialized \n"); | ||
2092 | } | ||
2093 | |||
2094 | /* DIO devices are slightly special. Although it is possible to | ||
2095 | * implement the insn_read/insn_write interface, it is much more | ||
2096 | * useful to applications if you implement the insn_bits interface. | ||
2097 | * This allows packed reading/writing of the DIO channels. The comedi | ||
2098 | * core can convert between insn_bits and insn_read/write */ | ||
2099 | |||
2100 | static int s626_dio_insn_bits(comedi_device * dev, comedi_subdevice * s, | ||
2101 | comedi_insn * insn, lsampl_t * data) | ||
2102 | { | ||
2103 | |||
2104 | /* Length of data must be 2 (mask and new data, see below) */ | ||
2105 | if (insn->n == 0) { | ||
2106 | return 0; | ||
2107 | } | ||
2108 | if (insn->n != 2) { | ||
2109 | printk("comedi%d: s626: s626_dio_insn_bits(): Invalid instruction length\n", dev->minor); | ||
2110 | return -EINVAL; | ||
2111 | } | ||
2112 | |||
2113 | /* | ||
2114 | * The insn data consists of a mask in data[0] and the new data in | ||
2115 | * data[1]. The mask defines which bits we are concerning about. | ||
2116 | * The new data must be anded with the mask. Each channel | ||
2117 | * corresponds to a bit. | ||
2118 | */ | ||
2119 | if (data[0]) { | ||
2120 | /* Check if requested ports are configured for output */ | ||
2121 | if ((s->io_bits & data[0]) != data[0]) | ||
2122 | return -EIO; | ||
2123 | |||
2124 | s->state &= ~data[0]; | ||
2125 | s->state |= data[0] & data[1]; | ||
2126 | |||
2127 | /* Write out the new digital output lines */ | ||
2128 | |||
2129 | DEBIwrite(dev, diopriv->WRDOut, s->state); | ||
2130 | } | ||
2131 | data[1] = DEBIread(dev, diopriv->RDDIn); | ||
2132 | |||
2133 | return 2; | ||
2134 | } | ||
2135 | |||
2136 | static int s626_dio_insn_config(comedi_device * dev, comedi_subdevice * s, | ||
2137 | comedi_insn * insn, lsampl_t * data) | ||
2138 | { | ||
2139 | |||
2140 | switch (data[0]) { | ||
2141 | case INSN_CONFIG_DIO_QUERY: | ||
2142 | data[1] = | ||
2143 | (s->io_bits & (1 << CR_CHAN(insn-> | ||
2144 | chanspec))) ? COMEDI_OUTPUT : | ||
2145 | COMEDI_INPUT; | ||
2146 | return insn->n; | ||
2147 | break; | ||
2148 | case COMEDI_INPUT: | ||
2149 | s->io_bits &= ~(1 << CR_CHAN(insn->chanspec)); | ||
2150 | break; | ||
2151 | case COMEDI_OUTPUT: | ||
2152 | s->io_bits |= 1 << CR_CHAN(insn->chanspec); | ||
2153 | break; | ||
2154 | default: | ||
2155 | return -EINVAL; | ||
2156 | break; | ||
2157 | } | ||
2158 | DEBIwrite(dev, diopriv->WRDOut, s->io_bits); | ||
2159 | |||
2160 | return 1; | ||
2161 | } | ||
2162 | |||
2163 | static int s626_dio_set_irq(comedi_device * dev, unsigned int chan) | ||
2164 | { | ||
2165 | unsigned int group; | ||
2166 | unsigned int bitmask; | ||
2167 | unsigned int status; | ||
2168 | |||
2169 | //select dio bank | ||
2170 | group = chan / 16; | ||
2171 | bitmask = 1 << (chan - (16 * group)); | ||
2172 | DEBUG("s626_dio_set_irq: enable interrupt on dio channel %d group %d\n", | ||
2173 | chan - (16 * group), group); | ||
2174 | |||
2175 | //set channel to capture positive edge | ||
2176 | status = DEBIread(dev, | ||
2177 | ((dio_private *) (dev->subdevices + 2 + | ||
2178 | group)->private)->RDEdgSel); | ||
2179 | DEBIwrite(dev, | ||
2180 | ((dio_private *) (dev->subdevices + 2 + | ||
2181 | group)->private)->WREdgSel, bitmask | status); | ||
2182 | |||
2183 | //enable interrupt on selected channel | ||
2184 | status = DEBIread(dev, | ||
2185 | ((dio_private *) (dev->subdevices + 2 + | ||
2186 | group)->private)->RDIntSel); | ||
2187 | DEBIwrite(dev, | ||
2188 | ((dio_private *) (dev->subdevices + 2 + | ||
2189 | group)->private)->WRIntSel, bitmask | status); | ||
2190 | |||
2191 | //enable edge capture write command | ||
2192 | DEBIwrite(dev, LP_MISC1, MISC1_EDCAP); | ||
2193 | |||
2194 | //enable edge capture on selected channel | ||
2195 | status = DEBIread(dev, | ||
2196 | ((dio_private *) (dev->subdevices + 2 + | ||
2197 | group)->private)->RDCapSel); | ||
2198 | DEBIwrite(dev, | ||
2199 | ((dio_private *) (dev->subdevices + 2 + | ||
2200 | group)->private)->WRCapSel, bitmask | status); | ||
2201 | |||
2202 | return 0; | ||
2203 | } | ||
2204 | |||
2205 | static int s626_dio_reset_irq(comedi_device * dev, unsigned int group, | ||
2206 | unsigned int mask) | ||
2207 | { | ||
2208 | DEBUG("s626_dio_reset_irq: disable interrupt on dio channel %d group %d\n", mask, group); | ||
2209 | |||
2210 | //disable edge capture write command | ||
2211 | DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); | ||
2212 | |||
2213 | //enable edge capture on selected channel | ||
2214 | DEBIwrite(dev, | ||
2215 | ((dio_private *) (dev->subdevices + 2 + | ||
2216 | group)->private)->WRCapSel, mask); | ||
2217 | |||
2218 | return 0; | ||
2219 | } | ||
2220 | |||
2221 | static int s626_dio_clear_irq(comedi_device * dev) | ||
2222 | { | ||
2223 | unsigned int group; | ||
2224 | |||
2225 | //disable edge capture write command | ||
2226 | DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); | ||
2227 | |||
2228 | for (group = 0; group < S626_DIO_BANKS; group++) { | ||
2229 | //clear pending events and interrupt | ||
2230 | DEBIwrite(dev, | ||
2231 | ((dio_private *) (dev->subdevices + 2 + | ||
2232 | group)->private)->WRCapSel, 0xffff); | ||
2233 | } | ||
2234 | |||
2235 | return 0; | ||
2236 | } | ||
2237 | |||
2238 | /* Now this function initializes the value of the counter (data[0]) | ||
2239 | and set the subdevice. To complete with trigger and interrupt | ||
2240 | configuration */ | ||
2241 | static int s626_enc_insn_config(comedi_device * dev, comedi_subdevice * s, | ||
2242 | comedi_insn * insn, lsampl_t * data) | ||
2243 | { | ||
2244 | uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon | ||
2245 | // index. | ||
2246 | (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index. | ||
2247 | (CLKSRC_COUNTER << BF_CLKSRC) | // Operating mode is Counter. | ||
2248 | (CLKPOL_POS << BF_CLKPOL) | // Active high clock. | ||
2249 | //( CNTDIR_UP << BF_CLKPOL ) | // Count direction is Down. | ||
2250 | (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x. | ||
2251 | (CLKENAB_INDEX << BF_CLKENAB); | ||
2252 | /* uint16_t DisableIntSrc=TRUE; */ | ||
2253 | // uint32_t Preloadvalue; //Counter initial value | ||
2254 | uint16_t valueSrclatch = LATCHSRC_AB_READ; | ||
2255 | uint16_t enab = CLKENAB_ALWAYS; | ||
2256 | enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; | ||
2257 | |||
2258 | DEBUG("s626_enc_insn_config: encoder config\n"); | ||
2259 | |||
2260 | // (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); | ||
2261 | |||
2262 | k->SetMode(dev, k, Setup, TRUE); | ||
2263 | Preload(dev, k, *(insn->data)); | ||
2264 | k->PulseIndex(dev, k); | ||
2265 | SetLatchSource(dev, k, valueSrclatch); | ||
2266 | k->SetEnable(dev, k, (uint16_t) (enab != 0)); | ||
2267 | |||
2268 | return insn->n; | ||
2269 | } | ||
2270 | |||
2271 | static int s626_enc_insn_read(comedi_device * dev, comedi_subdevice * s, | ||
2272 | comedi_insn * insn, lsampl_t * data) | ||
2273 | { | ||
2274 | |||
2275 | int n; | ||
2276 | enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; | ||
2277 | |||
2278 | DEBUG("s626_enc_insn_read: encoder read channel %d \n", | ||
2279 | CR_CHAN(insn->chanspec)); | ||
2280 | |||
2281 | for (n = 0; n < insn->n; n++) | ||
2282 | data[n] = ReadLatch(dev, k); | ||
2283 | |||
2284 | DEBUG("s626_enc_insn_read: encoder sample %d\n", data[n]); | ||
2285 | |||
2286 | return n; | ||
2287 | } | ||
2288 | |||
2289 | static int s626_enc_insn_write(comedi_device * dev, comedi_subdevice * s, | ||
2290 | comedi_insn * insn, lsampl_t * data) | ||
2291 | { | ||
2292 | |||
2293 | enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; | ||
2294 | |||
2295 | DEBUG("s626_enc_insn_write: encoder write channel %d \n", | ||
2296 | CR_CHAN(insn->chanspec)); | ||
2297 | |||
2298 | // Set the preload register | ||
2299 | Preload(dev, k, data[0]); | ||
2300 | |||
2301 | // Software index pulse forces the preload register to load | ||
2302 | // into the counter | ||
2303 | k->SetLoadTrig(dev, k, 0); | ||
2304 | k->PulseIndex(dev, k); | ||
2305 | k->SetLoadTrig(dev, k, 2); | ||
2306 | |||
2307 | DEBUG("s626_enc_insn_write: End encoder write\n"); | ||
2308 | |||
2309 | return 1; | ||
2310 | } | ||
2311 | |||
2312 | static void s626_timer_load(comedi_device * dev, enc_private * k, int tick) | ||
2313 | { | ||
2314 | uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon | ||
2315 | // index. | ||
2316 | (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index. | ||
2317 | (CLKSRC_TIMER << BF_CLKSRC) | // Operating mode is Timer. | ||
2318 | (CLKPOL_POS << BF_CLKPOL) | // Active high clock. | ||
2319 | (CNTDIR_DOWN << BF_CLKPOL) | // Count direction is Down. | ||
2320 | (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x. | ||
2321 | (CLKENAB_INDEX << BF_CLKENAB); | ||
2322 | uint16_t valueSrclatch = LATCHSRC_A_INDXA; | ||
2323 | // uint16_t enab=CLKENAB_ALWAYS; | ||
2324 | |||
2325 | k->SetMode(dev, k, Setup, FALSE); | ||
2326 | |||
2327 | // Set the preload register | ||
2328 | Preload(dev, k, tick); | ||
2329 | |||
2330 | // Software index pulse forces the preload register to load | ||
2331 | // into the counter | ||
2332 | k->SetLoadTrig(dev, k, 0); | ||
2333 | k->PulseIndex(dev, k); | ||
2334 | |||
2335 | //set reload on counter overflow | ||
2336 | k->SetLoadTrig(dev, k, 1); | ||
2337 | |||
2338 | //set interrupt on overflow | ||
2339 | k->SetIntSrc(dev, k, INTSRC_OVER); | ||
2340 | |||
2341 | SetLatchSource(dev, k, valueSrclatch); | ||
2342 | // k->SetEnable(dev,k,(uint16_t)(enab != 0)); | ||
2343 | } | ||
2344 | |||
2345 | /////////////////////////////////////////////////////////////////////// | ||
2346 | ///////////////////// DAC FUNCTIONS ///////////////////////////////// | ||
2347 | /////////////////////////////////////////////////////////////////////// | ||
2348 | |||
2349 | // Slot 0 base settings. | ||
2350 | #define VECT0 ( XSD2 | RSD3 | SIB_A2 ) // Slot 0 always shifts in | ||
2351 | // 0xFF and store it to | ||
2352 | // FB_BUFFER2. | ||
2353 | |||
2354 | // TrimDac LogicalChan-to-PhysicalChan mapping table. | ||
2355 | static uint8_t trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 }; | ||
2356 | |||
2357 | // TrimDac LogicalChan-to-EepromAdrs mapping table. | ||
2358 | static uint8_t trimadrs[] = | ||
2359 | { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 }; | ||
2360 | |||
2361 | static void LoadTrimDACs(comedi_device * dev) | ||
2362 | { | ||
2363 | register uint8_t i; | ||
2364 | |||
2365 | // Copy TrimDac setpoint values from EEPROM to TrimDacs. | ||
2366 | for (i = 0; i < (sizeof(trimchan) / sizeof(trimchan[0])); i++) | ||
2367 | WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i])); | ||
2368 | } | ||
2369 | |||
2370 | static void WriteTrimDAC(comedi_device * dev, uint8_t LogicalChan, | ||
2371 | uint8_t DacData) | ||
2372 | { | ||
2373 | uint32_t chan; | ||
2374 | |||
2375 | // Save the new setpoint in case the application needs to read it back later. | ||
2376 | devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData; | ||
2377 | |||
2378 | // Map logical channel number to physical channel number. | ||
2379 | chan = (uint32_t) trimchan[LogicalChan]; | ||
2380 | |||
2381 | // Set up TSL2 records for TrimDac write operation. All slots shift | ||
2382 | // 0xFF in from pulled-up SD3 so that the end of the slot sequence | ||
2383 | // can be detected. | ||
2384 | SETVECT(2, XSD2 | XFIFO_1 | WS3); // Slot 2: Send high uint8_t | ||
2385 | // to target TrimDac. | ||
2386 | SETVECT(3, XSD2 | XFIFO_0 | WS3); // Slot 3: Send low uint8_t to | ||
2387 | // target TrimDac. | ||
2388 | SETVECT(4, XSD2 | XFIFO_3 | WS1); // Slot 4: Send NOP high | ||
2389 | // uint8_t to DAC0 to keep | ||
2390 | // clock running. | ||
2391 | SETVECT(5, XSD2 | XFIFO_2 | WS1 | EOS); // Slot 5: Send NOP low | ||
2392 | // uint8_t to DAC0. | ||
2393 | |||
2394 | // Construct and transmit target DAC's serial packet: ( 0000 AAAA | ||
2395 | // ),( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the DAC | ||
2396 | // channel's address, and D<7:0> is the DAC setpoint. Append a WORD | ||
2397 | // value (that writes a channel 0 NOP command to a non-existent main | ||
2398 | // DAC channel) that serves to keep the clock running after the | ||
2399 | // packet has been sent to the target DAC. | ||
2400 | |||
2401 | SendDAC(dev, ((uint32_t) chan << 8) // Address the DAC channel | ||
2402 | // within the trimdac device. | ||
2403 | | (uint32_t) DacData); // Include DAC setpoint data. | ||
2404 | } | ||
2405 | |||
2406 | ///////////////////////////////////////////////////////////////////////// | ||
2407 | //////////////// EEPROM ACCESS FUNCTIONS ////////////////////////////// | ||
2408 | ///////////////////////////////////////////////////////////////////////// | ||
2409 | |||
2410 | /////////////////////////////////////////// | ||
2411 | // Read uint8_t from EEPROM. | ||
2412 | |||
2413 | static uint8_t I2Cread(comedi_device * dev, uint8_t addr) | ||
2414 | { | ||
2415 | uint8_t rtnval; | ||
2416 | |||
2417 | // Send EEPROM target address. | ||
2418 | if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CW) // Byte2 = I2C | ||
2419 | // command: | ||
2420 | // write to | ||
2421 | // I2C EEPROM | ||
2422 | // device. | ||
2423 | | I2C_B1(I2C_ATTRSTOP, addr) // Byte1 = EEPROM | ||
2424 | // internal target | ||
2425 | // address. | ||
2426 | | I2C_B0(I2C_ATTRNOP, 0))) // Byte0 = Not | ||
2427 | // sent. | ||
2428 | { | ||
2429 | // Abort function and declare error if handshake failed. | ||
2430 | DEBUG("I2Cread: error handshake I2Cread a\n"); | ||
2431 | return 0; | ||
2432 | } | ||
2433 | // Execute EEPROM read. | ||
2434 | if (I2Chandshake(dev, I2C_B2(I2C_ATTRSTART, I2CR) // Byte2 = I2C | ||
2435 | // command: read | ||
2436 | // from I2C EEPROM | ||
2437 | // device. | ||
2438 | | I2C_B1(I2C_ATTRSTOP, 0) // Byte1 receives | ||
2439 | // uint8_t from | ||
2440 | // EEPROM. | ||
2441 | | I2C_B0(I2C_ATTRNOP, 0))) // Byte0 = Not | ||
2442 | // sent. | ||
2443 | { | ||
2444 | // Abort function and declare error if handshake failed. | ||
2445 | DEBUG("I2Cread: error handshake I2Cread b\n"); | ||
2446 | return 0; | ||
2447 | } | ||
2448 | // Return copy of EEPROM value. | ||
2449 | rtnval = (uint8_t) (RR7146(P_I2CCTRL) >> 16); | ||
2450 | return rtnval; | ||
2451 | } | ||
2452 | |||
2453 | static uint32_t I2Chandshake(comedi_device * dev, uint32_t val) | ||
2454 | { | ||
2455 | // Write I2C command to I2C Transfer Control shadow register. | ||
2456 | WR7146(P_I2CCTRL, val); | ||
2457 | |||
2458 | // Upload I2C shadow registers into working registers and wait for | ||
2459 | // upload confirmation. | ||
2460 | |||
2461 | MC_ENABLE(P_MC2, MC2_UPLD_IIC); | ||
2462 | while (!MC_TEST(P_MC2, MC2_UPLD_IIC)) ; | ||
2463 | |||
2464 | // Wait until I2C bus transfer is finished or an error occurs. | ||
2465 | while ((RR7146(P_I2CCTRL) & (I2C_BUSY | I2C_ERR)) == I2C_BUSY) ; | ||
2466 | |||
2467 | // Return non-zero if I2C error occured. | ||
2468 | return RR7146(P_I2CCTRL) & I2C_ERR; | ||
2469 | |||
2470 | } | ||
2471 | |||
2472 | // Private helper function: Write setpoint to an application DAC channel. | ||
2473 | |||
2474 | static void SetDAC(comedi_device * dev, uint16_t chan, short dacdata) | ||
2475 | { | ||
2476 | register uint16_t signmask; | ||
2477 | register uint32_t WSImage; | ||
2478 | |||
2479 | // Adjust DAC data polarity and set up Polarity Control Register | ||
2480 | // image. | ||
2481 | signmask = 1 << chan; | ||
2482 | if (dacdata < 0) { | ||
2483 | dacdata = -dacdata; | ||
2484 | devpriv->Dacpol |= signmask; | ||
2485 | } else | ||
2486 | devpriv->Dacpol &= ~signmask; | ||
2487 | |||
2488 | // Limit DAC setpoint value to valid range. | ||
2489 | if ((uint16_t) dacdata > 0x1FFF) | ||
2490 | dacdata = 0x1FFF; | ||
2491 | |||
2492 | // Set up TSL2 records (aka "vectors") for DAC update. Vectors V2 | ||
2493 | // and V3 transmit the setpoint to the target DAC. V4 and V5 send | ||
2494 | // data to a non-existent TrimDac channel just to keep the clock | ||
2495 | // running after sending data to the target DAC. This is necessary | ||
2496 | // to eliminate the clock glitch that would otherwise occur at the | ||
2497 | // end of the target DAC's serial data stream. When the sequence | ||
2498 | // restarts at V0 (after executing V5), the gate array automatically | ||
2499 | // disables gating for the DAC clock and all DAC chip selects. | ||
2500 | WSImage = (chan & 2) ? WS1 : WS2; // Choose DAC chip select to | ||
2501 | // be asserted. | ||
2502 | SETVECT(2, XSD2 | XFIFO_1 | WSImage); // Slot 2: Transmit high | ||
2503 | // data byte to target DAC. | ||
2504 | SETVECT(3, XSD2 | XFIFO_0 | WSImage); // Slot 3: Transmit low data | ||
2505 | // byte to target DAC. | ||
2506 | SETVECT(4, XSD2 | XFIFO_3 | WS3); // Slot 4: Transmit to | ||
2507 | // non-existent TrimDac | ||
2508 | // channel to keep clock | ||
2509 | SETVECT(5, XSD2 | XFIFO_2 | WS3 | EOS); // Slot 5: running after | ||
2510 | // writing target DAC's | ||
2511 | // low data byte. | ||
2512 | |||
2513 | // Construct and transmit target DAC's serial packet: ( A10D DDDD | ||
2514 | // ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, and D<12:0> | ||
2515 | // is the DAC setpoint. Append a WORD value (that writes to a | ||
2516 | // non-existent TrimDac channel) that serves to keep the clock | ||
2517 | // running after the packet has been sent to the target DAC. | ||
2518 | SendDAC(dev, 0x0F000000 //Continue clock after target DAC | ||
2519 | //data (write to non-existent | ||
2520 | //trimdac). | ||
2521 | | 0x00004000 // Address the two main dual-DAC | ||
2522 | // devices (TSL's chip select enables | ||
2523 | // target device). | ||
2524 | | ((uint32_t) (chan & 1) << 15) // Address the DAC | ||
2525 | // channel within the | ||
2526 | // device. | ||
2527 | | (uint32_t) dacdata); // Include DAC setpoint data. | ||
2528 | |||
2529 | } | ||
2530 | |||
2531 | //////////////////////////////////////////////////////// | ||
2532 | // Private helper function: Transmit serial data to DAC via Audio | ||
2533 | // channel 2. Assumes: (1) TSL2 slot records initialized, and (2) | ||
2534 | // Dacpol contains valid target image. | ||
2535 | |||
2536 | static void SendDAC(comedi_device * dev, uint32_t val) | ||
2537 | { | ||
2538 | |||
2539 | // START THE SERIAL CLOCK RUNNING ------------- | ||
2540 | |||
2541 | // Assert DAC polarity control and enable gating of DAC serial clock | ||
2542 | // and audio bit stream signals. At this point in time we must be | ||
2543 | // assured of being in time slot 0. If we are not in slot 0, the | ||
2544 | // serial clock and audio stream signals will be disabled; this is | ||
2545 | // because the following DEBIwrite statement (which enables signals | ||
2546 | // to be passed through the gate array) would execute before the | ||
2547 | // trailing edge of WS1/WS3 (which turns off the signals), thus | ||
2548 | // causing the signals to be inactive during the DAC write. | ||
2549 | DEBIwrite(dev, LP_DACPOL, devpriv->Dacpol); | ||
2550 | |||
2551 | // TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- | ||
2552 | |||
2553 | // Copy DAC setpoint value to DAC's output DMA buffer. | ||
2554 | |||
2555 | //WR7146( (uint32_t)devpriv->pDacWBuf, val ); | ||
2556 | *devpriv->pDacWBuf = val; | ||
2557 | |||
2558 | // enab the output DMA transfer. This will cause the DMAC to copy | ||
2559 | // the DAC's data value to A2's output FIFO. The DMA transfer will | ||
2560 | // then immediately terminate because the protection address is | ||
2561 | // reached upon transfer of the first DWORD value. | ||
2562 | MC_ENABLE(P_MC1, MC1_A2OUT); | ||
2563 | |||
2564 | // While the DMA transfer is executing ... | ||
2565 | |||
2566 | // Reset Audio2 output FIFO's underflow flag (along with any other | ||
2567 | // FIFO underflow/overflow flags). When set, this flag will | ||
2568 | // indicate that we have emerged from slot 0. | ||
2569 | WR7146(P_ISR, ISR_AFOU); | ||
2570 | |||
2571 | // Wait for the DMA transfer to finish so that there will be data | ||
2572 | // available in the FIFO when time slot 1 tries to transfer a DWORD | ||
2573 | // from the FIFO to the output buffer register. We test for DMA | ||
2574 | // Done by polling the DMAC enable flag; this flag is automatically | ||
2575 | // cleared when the transfer has finished. | ||
2576 | while ((RR7146(P_MC1) & MC1_A2OUT) != 0) ; | ||
2577 | |||
2578 | // START THE OUTPUT STREAM TO THE TARGET DAC -------------------- | ||
2579 | |||
2580 | // FIFO data is now available, so we enable execution of time slots | ||
2581 | // 1 and higher by clearing the EOS flag in slot 0. Note that SD3 | ||
2582 | // will be shifted in and stored in FB_BUFFER2 for end-of-slot-list | ||
2583 | // detection. | ||
2584 | SETVECT(0, XSD2 | RSD3 | SIB_A2); | ||
2585 | |||
2586 | // Wait for slot 1 to execute to ensure that the Packet will be | ||
2587 | // transmitted. This is detected by polling the Audio2 output FIFO | ||
2588 | // underflow flag, which will be set when slot 1 execution has | ||
2589 | // finished transferring the DAC's data DWORD from the output FIFO | ||
2590 | // to the output buffer register. | ||
2591 | while ((RR7146(P_SSR) & SSR_AF2_OUT) == 0) ; | ||
2592 | |||
2593 | // Set up to trap execution at slot 0 when the TSL sequencer cycles | ||
2594 | // back to slot 0 after executing the EOS in slot 5. Also, | ||
2595 | // simultaneously shift out and in the 0x00 that is ALWAYS the value | ||
2596 | // stored in the last byte to be shifted out of the FIFO's DWORD | ||
2597 | // buffer register. | ||
2598 | SETVECT(0, XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS); | ||
2599 | |||
2600 | // WAIT FOR THE TRANSACTION TO FINISH ----------------------- | ||
2601 | |||
2602 | // Wait for the TSL to finish executing all time slots before | ||
2603 | // exiting this function. We must do this so that the next DAC | ||
2604 | // write doesn't start, thereby enabling clock/chip select signals: | ||
2605 | // 1. Before the TSL sequence cycles back to slot 0, which disables | ||
2606 | // the clock/cs signal gating and traps slot // list execution. If | ||
2607 | // we have not yet finished slot 5 then the clock/cs signals are | ||
2608 | // still gated and we have // not finished transmitting the stream. | ||
2609 | // 2. While slots 2-5 are executing due to a late slot 0 trap. In | ||
2610 | // this case, the slot sequence is currently // repeating, but with | ||
2611 | // clock/cs signals disabled. We must wait for slot 0 to trap | ||
2612 | // execution before setting // up the next DAC setpoint DMA transfer | ||
2613 | // and enabling the clock/cs signals. To detect the end of slot 5, | ||
2614 | // we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If | ||
2615 | // the TSL has not yet finished executing slot 5 ... | ||
2616 | if ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) { | ||
2617 | // The trap was set on time and we are still executing somewhere | ||
2618 | // in slots 2-5, so we now wait for slot 0 to execute and trap | ||
2619 | // TSL execution. This is detected when FB_BUFFER2 MSB changes | ||
2620 | // from 0xFF to 0x00, which slot 0 causes to happen by shifting | ||
2621 | // out/in on SD2 the 0x00 that is always referenced by slot 5. | ||
2622 | while ((RR7146(P_FB_BUFFER2) & 0xFF000000) != 0) ; | ||
2623 | } | ||
2624 | // Either (1) we were too late setting the slot 0 trap; the TSL | ||
2625 | // sequencer restarted slot 0 before we could set the EOS trap flag, | ||
2626 | // or (2) we were not late and execution is now trapped at slot 0. | ||
2627 | // In either case, we must now change slot 0 so that it will store | ||
2628 | // value 0xFF (instead of 0x00) to FB_BUFFER2 next time it executes. | ||
2629 | // In order to do this, we reprogram slot 0 so that it will shift in | ||
2630 | // SD3, which is driven only by a pull-up resistor. | ||
2631 | SETVECT(0, RSD3 | SIB_A2 | EOS); | ||
2632 | |||
2633 | // Wait for slot 0 to execute, at which time the TSL is setup for | ||
2634 | // the next DAC write. This is detected when FB_BUFFER2 MSB changes | ||
2635 | // from 0x00 to 0xFF. | ||
2636 | while ((RR7146(P_FB_BUFFER2) & 0xFF000000) == 0) ; | ||
2637 | } | ||
2638 | |||
2639 | static void WriteMISC2(comedi_device * dev, uint16_t NewImage) | ||
2640 | { | ||
2641 | DEBIwrite(dev, LP_MISC1, MISC1_WENABLE); // enab writes to | ||
2642 | // MISC2 register. | ||
2643 | DEBIwrite(dev, LP_WRMISC2, NewImage); // Write new image to MISC2. | ||
2644 | DEBIwrite(dev, LP_MISC1, MISC1_WDISABLE); // Disable writes to MISC2. | ||
2645 | } | ||
2646 | |||
2647 | ///////////////////////////////////////////////////////////////////// | ||
2648 | // Initialize the DEBI interface for all transfers. | ||
2649 | |||
2650 | static uint16_t DEBIread(comedi_device * dev, uint16_t addr) | ||
2651 | { | ||
2652 | uint16_t retval; | ||
2653 | |||
2654 | // Set up DEBI control register value in shadow RAM. | ||
2655 | WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); | ||
2656 | |||
2657 | // Execute the DEBI transfer. | ||
2658 | DEBItransfer(dev); | ||
2659 | |||
2660 | // Fetch target register value. | ||
2661 | retval = (uint16_t) RR7146(P_DEBIAD); | ||
2662 | |||
2663 | // Return register value. | ||
2664 | return retval; | ||
2665 | } | ||
2666 | |||
2667 | // Execute a DEBI transfer. This must be called from within a | ||
2668 | // critical section. | ||
2669 | static void DEBItransfer(comedi_device * dev) | ||
2670 | { | ||
2671 | // Initiate upload of shadow RAM to DEBI control register. | ||
2672 | MC_ENABLE(P_MC2, MC2_UPLD_DEBI); | ||
2673 | |||
2674 | // Wait for completion of upload from shadow RAM to DEBI control | ||
2675 | // register. | ||
2676 | while (!MC_TEST(P_MC2, MC2_UPLD_DEBI)) ; | ||
2677 | |||
2678 | // Wait until DEBI transfer is done. | ||
2679 | while (RR7146(P_PSR) & PSR_DEBI_S) ; | ||
2680 | } | ||
2681 | |||
2682 | // Write a value to a gate array register. | ||
2683 | static void DEBIwrite(comedi_device * dev, uint16_t addr, uint16_t wdata) | ||
2684 | { | ||
2685 | |||
2686 | // Set up DEBI control register value in shadow RAM. | ||
2687 | WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); | ||
2688 | WR7146(P_DEBIAD, wdata); | ||
2689 | |||
2690 | // Execute the DEBI transfer. | ||
2691 | DEBItransfer(dev); | ||
2692 | } | ||
2693 | |||
2694 | ///////////////////////////////////////////////////////////////////////////// | ||
2695 | // Replace the specified bits in a gate array register. Imports: mask | ||
2696 | // specifies bits that are to be preserved, wdata is new value to be | ||
2697 | // or'd with the masked original. | ||
2698 | static void DEBIreplace(comedi_device * dev, uint16_t addr, uint16_t mask, | ||
2699 | uint16_t wdata) | ||
2700 | { | ||
2701 | |||
2702 | // Copy target gate array register into P_DEBIAD register. | ||
2703 | WR7146(P_DEBICMD, DEBI_CMD_RDWORD | addr); // Set up DEBI control | ||
2704 | // reg value in shadow | ||
2705 | // RAM. | ||
2706 | DEBItransfer(dev); // Execute the DEBI | ||
2707 | // Read transfer. | ||
2708 | |||
2709 | // Write back the modified image. | ||
2710 | WR7146(P_DEBICMD, DEBI_CMD_WRWORD | addr); // Set up DEBI control | ||
2711 | // reg value in shadow | ||
2712 | // RAM. | ||
2713 | |||
2714 | WR7146(P_DEBIAD, wdata | ((uint16_t) RR7146(P_DEBIAD) & mask)); // Modify the register image. | ||
2715 | DEBItransfer(dev); // Execute the DEBI Write transfer. | ||
2716 | } | ||
2717 | |||
2718 | static void CloseDMAB(comedi_device * dev, DMABUF * pdma, size_t bsize) | ||
2719 | { | ||
2720 | void *vbptr; | ||
2721 | dma_addr_t vpptr; | ||
2722 | |||
2723 | DEBUG("CloseDMAB: Entering S626DRV_CloseDMAB():\n"); | ||
2724 | if (pdma == NULL) | ||
2725 | return; | ||
2726 | //find the matching allocation from the board struct | ||
2727 | |||
2728 | vbptr = pdma->LogicalBase; | ||
2729 | vpptr = pdma->PhysicalBase; | ||
2730 | if (vbptr) { | ||
2731 | pci_free_consistent(devpriv->pdev, bsize, vbptr, vpptr); | ||
2732 | pdma->LogicalBase = 0; | ||
2733 | pdma->PhysicalBase = 0; | ||
2734 | |||
2735 | DEBUG("CloseDMAB(): Logical=%p, bsize=%d, Physical=0x%x\n", | ||
2736 | vbptr, bsize, (uint32_t) vpptr); | ||
2737 | } | ||
2738 | } | ||
2739 | |||
2740 | //////////////////////////////////////////////////////////////////////// | ||
2741 | ///////////////// COUNTER FUNCTIONS ////////////////////////////////// | ||
2742 | //////////////////////////////////////////////////////////////////////// | ||
2743 | // All counter functions address a specific counter by means of the | ||
2744 | // "Counter" argument, which is a logical counter number. The Counter | ||
2745 | // argument may have any of the following legal values: 0=0A, 1=1A, | ||
2746 | // 2=2A, 3=0B, 4=1B, 5=2B. | ||
2747 | //////////////////////////////////////////////////////////////////////// | ||
2748 | |||
2749 | // Forward declarations for functions that are common to both A and B | ||
2750 | // counters: | ||
2751 | |||
2752 | ///////////////////////////////////////////////////////////////////// | ||
2753 | //////////////////// PRIVATE COUNTER FUNCTIONS ///////////////////// | ||
2754 | ///////////////////////////////////////////////////////////////////// | ||
2755 | |||
2756 | ///////////////////////////////////////////////////////////////// | ||
2757 | // Read a counter's output latch. | ||
2758 | |||
2759 | static uint32_t ReadLatch(comedi_device * dev, enc_private * k) | ||
2760 | { | ||
2761 | register uint32_t value; | ||
2762 | //DEBUG FIXME DEBUG("ReadLatch: Read Latch enter\n"); | ||
2763 | |||
2764 | // Latch counts and fetch LSW of latched counts value. | ||
2765 | value = (uint32_t) DEBIread(dev, k->MyLatchLsw); | ||
2766 | |||
2767 | // Fetch MSW of latched counts and combine with LSW. | ||
2768 | value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16); | ||
2769 | |||
2770 | // DEBUG FIXME DEBUG("ReadLatch: Read Latch exit\n"); | ||
2771 | |||
2772 | // Return latched counts. | ||
2773 | return value; | ||
2774 | } | ||
2775 | |||
2776 | /////////////////////////////////////////////////////////////////// | ||
2777 | // Reset a counter's index and overflow event capture flags. | ||
2778 | |||
2779 | static void ResetCapFlags_A(comedi_device * dev, enc_private * k) | ||
2780 | { | ||
2781 | DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), | ||
2782 | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); | ||
2783 | } | ||
2784 | |||
2785 | static void ResetCapFlags_B(comedi_device * dev, enc_private * k) | ||
2786 | { | ||
2787 | DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), | ||
2788 | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B); | ||
2789 | } | ||
2790 | |||
2791 | ///////////////////////////////////////////////////////////////////////// | ||
2792 | // Return counter setup in a format (COUNTER_SETUP) that is consistent | ||
2793 | // for both A and B counters. | ||
2794 | |||
2795 | static uint16_t GetMode_A(comedi_device * dev, enc_private * k) | ||
2796 | { | ||
2797 | register uint16_t cra; | ||
2798 | register uint16_t crb; | ||
2799 | register uint16_t setup; | ||
2800 | |||
2801 | // Fetch CRA and CRB register images. | ||
2802 | cra = DEBIread(dev, k->MyCRA); | ||
2803 | crb = DEBIread(dev, k->MyCRB); | ||
2804 | |||
2805 | // Populate the standardized counter setup bit fields. Note: | ||
2806 | // IndexSrc is restricted to ENC_X or IndxPol. | ||
2807 | setup = ((cra & STDMSK_LOADSRC) // LoadSrc = LoadSrcA. | ||
2808 | | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) // LatchSrc = LatchSrcA. | ||
2809 | | ((cra << (STDBIT_INTSRC - CRABIT_INTSRC_A)) & STDMSK_INTSRC) // IntSrc = IntSrcA. | ||
2810 | | ((cra << (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1))) & STDMSK_INDXSRC) // IndxSrc = IndxSrcA<1>. | ||
2811 | | ((cra >> (CRABIT_INDXPOL_A - STDBIT_INDXPOL)) & STDMSK_INDXPOL) // IndxPol = IndxPolA. | ||
2812 | | ((crb >> (CRBBIT_CLKENAB_A - STDBIT_CLKENAB)) & STDMSK_CLKENAB)); // ClkEnab = ClkEnabA. | ||
2813 | |||
2814 | // Adjust mode-dependent parameters. | ||
2815 | if (cra & (2 << CRABIT_CLKSRC_A)) // If Timer mode (ClkSrcA<1> == 1): | ||
2816 | setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) // Indicate Timer mode. | ||
2817 | | ((cra << (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) & STDMSK_CLKPOL) // Set ClkPol to indicate count direction (ClkSrcA<0>). | ||
2818 | | (MULT_X1 << STDBIT_CLKMULT)); // ClkMult must be 1x in Timer mode. | ||
2819 | |||
2820 | else // If Counter mode (ClkSrcA<1> == 0): | ||
2821 | setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) // Indicate Counter mode. | ||
2822 | | ((cra >> (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) & STDMSK_CLKPOL) // Pass through ClkPol. | ||
2823 | | (((cra & CRAMSK_CLKMULT_A) == (MULT_X0 << CRABIT_CLKMULT_A)) ? // Force ClkMult to 1x if not legal, else pass through. | ||
2824 | (MULT_X1 << STDBIT_CLKMULT) : | ||
2825 | ((cra >> (CRABIT_CLKMULT_A - | ||
2826 | STDBIT_CLKMULT)) & | ||
2827 | STDMSK_CLKMULT))); | ||
2828 | |||
2829 | // Return adjusted counter setup. | ||
2830 | return setup; | ||
2831 | } | ||
2832 | |||
2833 | static uint16_t GetMode_B(comedi_device * dev, enc_private * k) | ||
2834 | { | ||
2835 | register uint16_t cra; | ||
2836 | register uint16_t crb; | ||
2837 | register uint16_t setup; | ||
2838 | |||
2839 | // Fetch CRA and CRB register images. | ||
2840 | cra = DEBIread(dev, k->MyCRA); | ||
2841 | crb = DEBIread(dev, k->MyCRB); | ||
2842 | |||
2843 | // Populate the standardized counter setup bit fields. Note: | ||
2844 | // IndexSrc is restricted to ENC_X or IndxPol. | ||
2845 | setup = (((crb << (STDBIT_INTSRC - CRBBIT_INTSRC_B)) & STDMSK_INTSRC) // IntSrc = IntSrcB. | ||
2846 | | ((crb << (STDBIT_LATCHSRC - CRBBIT_LATCHSRC)) & STDMSK_LATCHSRC) // LatchSrc = LatchSrcB. | ||
2847 | | ((crb << (STDBIT_LOADSRC - CRBBIT_LOADSRC_B)) & STDMSK_LOADSRC) // LoadSrc = LoadSrcB. | ||
2848 | | ((crb << (STDBIT_INDXPOL - CRBBIT_INDXPOL_B)) & STDMSK_INDXPOL) // IndxPol = IndxPolB. | ||
2849 | | ((crb >> (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) & STDMSK_CLKENAB) // ClkEnab = ClkEnabB. | ||
2850 | | ((cra >> ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)) & STDMSK_INDXSRC)); // IndxSrc = IndxSrcB<1>. | ||
2851 | |||
2852 | // Adjust mode-dependent parameters. | ||
2853 | if ((crb & CRBMSK_CLKMULT_B) == (MULT_X0 << CRBBIT_CLKMULT_B)) // If Extender mode (ClkMultB == MULT_X0): | ||
2854 | setup |= ((CLKSRC_EXTENDER << STDBIT_CLKSRC) // Indicate Extender mode. | ||
2855 | | (MULT_X1 << STDBIT_CLKMULT) // Indicate multiplier is 1x. | ||
2856 | | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); // Set ClkPol equal to Timer count direction (ClkSrcB<0>). | ||
2857 | |||
2858 | else if (cra & (2 << CRABIT_CLKSRC_B)) // If Timer mode (ClkSrcB<1> == 1): | ||
2859 | setup |= ((CLKSRC_TIMER << STDBIT_CLKSRC) // Indicate Timer mode. | ||
2860 | | (MULT_X1 << STDBIT_CLKMULT) // Indicate multiplier is 1x. | ||
2861 | | ((cra >> (CRABIT_CLKSRC_B - STDBIT_CLKPOL)) & STDMSK_CLKPOL)); // Set ClkPol equal to Timer count direction (ClkSrcB<0>). | ||
2862 | |||
2863 | else // If Counter mode (ClkSrcB<1> == 0): | ||
2864 | setup |= ((CLKSRC_COUNTER << STDBIT_CLKSRC) // Indicate Timer mode. | ||
2865 | | ((crb >> (CRBBIT_CLKMULT_B - STDBIT_CLKMULT)) & STDMSK_CLKMULT) // Clock multiplier is passed through. | ||
2866 | | ((crb << (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) & STDMSK_CLKPOL)); // Clock polarity is passed through. | ||
2867 | |||
2868 | // Return adjusted counter setup. | ||
2869 | return setup; | ||
2870 | } | ||
2871 | |||
2872 | ///////////////////////////////////////////////////////////////////////////////////////////// | ||
2873 | // Set the operating mode for the specified counter. The setup | ||
2874 | // parameter is treated as a COUNTER_SETUP data type. The following | ||
2875 | // parameters are programmable (all other parms are ignored): ClkMult, | ||
2876 | // ClkPol, ClkEnab, IndexSrc, IndexPol, LoadSrc. | ||
2877 | |||
2878 | static void SetMode_A(comedi_device * dev, enc_private * k, uint16_t Setup, | ||
2879 | uint16_t DisableIntSrc) | ||
2880 | { | ||
2881 | register uint16_t cra; | ||
2882 | register uint16_t crb; | ||
2883 | register uint16_t setup = Setup; // Cache the Standard Setup. | ||
2884 | |||
2885 | // Initialize CRA and CRB images. | ||
2886 | cra = ((setup & CRAMSK_LOADSRC_A) // Preload trigger is passed through. | ||
2887 | | ((setup & STDMSK_INDXSRC) >> (STDBIT_INDXSRC - (CRABIT_INDXSRC_A + 1)))); // IndexSrc is restricted to ENC_X or IndxPol. | ||
2888 | |||
2889 | crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A // Reset any pending CounterA event captures. | ||
2890 | | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_A - STDBIT_CLKENAB))); // Clock enable is passed through. | ||
2891 | |||
2892 | // Force IntSrc to Disabled if DisableIntSrc is asserted. | ||
2893 | if (!DisableIntSrc) | ||
2894 | cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - | ||
2895 | CRABIT_INTSRC_A)); | ||
2896 | |||
2897 | // Populate all mode-dependent attributes of CRA & CRB images. | ||
2898 | switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) { | ||
2899 | case CLKSRC_EXTENDER: // Extender Mode: Force to Timer mode | ||
2900 | // (Extender valid only for B counters). | ||
2901 | |||
2902 | case CLKSRC_TIMER: // Timer Mode: | ||
2903 | cra |= ((2 << CRABIT_CLKSRC_A) // ClkSrcA<1> selects system clock | ||
2904 | | ((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRABIT_CLKSRC_A)) // with count direction (ClkSrcA<0>) obtained from ClkPol. | ||
2905 | | (1 << CRABIT_CLKPOL_A) // ClkPolA behaves as always-on clock enable. | ||
2906 | | (MULT_X1 << CRABIT_CLKMULT_A)); // ClkMult must be 1x. | ||
2907 | break; | ||
2908 | |||
2909 | default: // Counter Mode: | ||
2910 | cra |= (CLKSRC_COUNTER // Select ENC_C and ENC_D as clock/direction inputs. | ||
2911 | | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKPOL_A - STDBIT_CLKPOL)) // Clock polarity is passed through. | ||
2912 | | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? // Force multiplier to x1 if not legal, otherwise pass through. | ||
2913 | (MULT_X1 << CRABIT_CLKMULT_A) : | ||
2914 | ((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A - | ||
2915 | STDBIT_CLKMULT)))); | ||
2916 | } | ||
2917 | |||
2918 | // Force positive index polarity if IndxSrc is software-driven only, | ||
2919 | // otherwise pass it through. | ||
2920 | if (~setup & STDMSK_INDXSRC) | ||
2921 | cra |= ((setup & STDMSK_INDXPOL) << (CRABIT_INDXPOL_A - | ||
2922 | STDBIT_INDXPOL)); | ||
2923 | |||
2924 | // If IntSrc has been forced to Disabled, update the MISC2 interrupt | ||
2925 | // enable mask to indicate the counter interrupt is disabled. | ||
2926 | if (DisableIntSrc) | ||
2927 | devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; | ||
2928 | |||
2929 | // While retaining CounterB and LatchSrc configurations, program the | ||
2930 | // new counter operating mode. | ||
2931 | DEBIreplace(dev, k->MyCRA, CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B, cra); | ||
2932 | DEBIreplace(dev, k->MyCRB, | ||
2933 | (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), crb); | ||
2934 | } | ||
2935 | |||
2936 | static void SetMode_B(comedi_device * dev, enc_private * k, uint16_t Setup, | ||
2937 | uint16_t DisableIntSrc) | ||
2938 | { | ||
2939 | register uint16_t cra; | ||
2940 | register uint16_t crb; | ||
2941 | register uint16_t setup = Setup; // Cache the Standard Setup. | ||
2942 | |||
2943 | // Initialize CRA and CRB images. | ||
2944 | cra = ((setup & STDMSK_INDXSRC) << ((CRABIT_INDXSRC_B + 1) - STDBIT_INDXSRC)); // IndexSrc field is restricted to ENC_X or IndxPol. | ||
2945 | |||
2946 | crb = (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B // Reset event captures and disable interrupts. | ||
2947 | | ((setup & STDMSK_CLKENAB) << (CRBBIT_CLKENAB_B - STDBIT_CLKENAB)) // Clock enable is passed through. | ||
2948 | | ((setup & STDMSK_LOADSRC) >> (STDBIT_LOADSRC - CRBBIT_LOADSRC_B))); // Preload trigger source is passed through. | ||
2949 | |||
2950 | // Force IntSrc to Disabled if DisableIntSrc is asserted. | ||
2951 | if (!DisableIntSrc) | ||
2952 | crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - | ||
2953 | CRBBIT_INTSRC_B)); | ||
2954 | |||
2955 | // Populate all mode-dependent attributes of CRA & CRB images. | ||
2956 | switch ((setup & STDMSK_CLKSRC) >> STDBIT_CLKSRC) { | ||
2957 | case CLKSRC_TIMER: // Timer Mode: | ||
2958 | cra |= ((2 << CRABIT_CLKSRC_B) // ClkSrcB<1> selects system clock | ||
2959 | | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); // with direction (ClkSrcB<0>) obtained from ClkPol. | ||
2960 | crb |= ((1 << CRBBIT_CLKPOL_B) // ClkPolB behaves as always-on clock enable. | ||
2961 | | (MULT_X1 << CRBBIT_CLKMULT_B)); // ClkMultB must be 1x. | ||
2962 | break; | ||
2963 | |||
2964 | case CLKSRC_EXTENDER: // Extender Mode: | ||
2965 | cra |= ((2 << CRABIT_CLKSRC_B) // ClkSrcB source is OverflowA (same as "timer") | ||
2966 | | ((setup & STDMSK_CLKPOL) << (CRABIT_CLKSRC_B - STDBIT_CLKPOL))); // with direction obtained from ClkPol. | ||
2967 | crb |= ((1 << CRBBIT_CLKPOL_B) // ClkPolB controls IndexB -- always set to active. | ||
2968 | | (MULT_X0 << CRBBIT_CLKMULT_B)); // ClkMultB selects OverflowA as the clock source. | ||
2969 | break; | ||
2970 | |||
2971 | default: // Counter Mode: | ||
2972 | cra |= (CLKSRC_COUNTER << CRABIT_CLKSRC_B); // Select ENC_C and ENC_D as clock/direction inputs. | ||
2973 | crb |= (((setup & STDMSK_CLKPOL) >> (STDBIT_CLKPOL - CRBBIT_CLKPOL_B)) // ClkPol is passed through. | ||
2974 | | (((setup & STDMSK_CLKMULT) == (MULT_X0 << STDBIT_CLKMULT)) ? // Force ClkMult to x1 if not legal, otherwise pass through. | ||
2975 | (MULT_X1 << CRBBIT_CLKMULT_B) : | ||
2976 | ((setup & STDMSK_CLKMULT) << (CRBBIT_CLKMULT_B - | ||
2977 | STDBIT_CLKMULT)))); | ||
2978 | } | ||
2979 | |||
2980 | // Force positive index polarity if IndxSrc is software-driven only, | ||
2981 | // otherwise pass it through. | ||
2982 | if (~setup & STDMSK_INDXSRC) | ||
2983 | crb |= ((setup & STDMSK_INDXPOL) >> (STDBIT_INDXPOL - | ||
2984 | CRBBIT_INDXPOL_B)); | ||
2985 | |||
2986 | // If IntSrc has been forced to Disabled, update the MISC2 interrupt | ||
2987 | // enable mask to indicate the counter interrupt is disabled. | ||
2988 | if (DisableIntSrc) | ||
2989 | devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; | ||
2990 | |||
2991 | // While retaining CounterA and LatchSrc configurations, program the | ||
2992 | // new counter operating mode. | ||
2993 | DEBIreplace(dev, k->MyCRA, | ||
2994 | (uint16_t) (~(CRAMSK_INDXSRC_B | CRAMSK_CLKSRC_B)), cra); | ||
2995 | DEBIreplace(dev, k->MyCRB, CRBMSK_CLKENAB_A | CRBMSK_LATCHSRC, crb); | ||
2996 | } | ||
2997 | |||
2998 | //////////////////////////////////////////////////////////////////////// | ||
2999 | // Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index. | ||
3000 | |||
3001 | static void SetEnable_A(comedi_device * dev, enc_private * k, uint16_t enab) | ||
3002 | { | ||
3003 | DEBUG("SetEnable_A: SetEnable_A enter 3541\n"); | ||
3004 | DEBIreplace(dev, k->MyCRB, | ||
3005 | (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A)), | ||
3006 | (uint16_t) (enab << CRBBIT_CLKENAB_A)); | ||
3007 | } | ||
3008 | |||
3009 | static void SetEnable_B(comedi_device * dev, enc_private * k, uint16_t enab) | ||
3010 | { | ||
3011 | DEBIreplace(dev, k->MyCRB, | ||
3012 | (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B)), | ||
3013 | (uint16_t) (enab << CRBBIT_CLKENAB_B)); | ||
3014 | } | ||
3015 | |||
3016 | static uint16_t GetEnable_A(comedi_device * dev, enc_private * k) | ||
3017 | { | ||
3018 | return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_A) & 1; | ||
3019 | } | ||
3020 | |||
3021 | static uint16_t GetEnable_B(comedi_device * dev, enc_private * k) | ||
3022 | { | ||
3023 | return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1; | ||
3024 | } | ||
3025 | |||
3026 | //////////////////////////////////////////////////////////////////////// | ||
3027 | // Return/set a counter pair's latch trigger source. 0: On read | ||
3028 | // access, 1: A index latches A, 2: B index latches B, 3: A overflow | ||
3029 | // latches B. | ||
3030 | |||
3031 | static void SetLatchSource(comedi_device * dev, enc_private * k, uint16_t value) | ||
3032 | { | ||
3033 | DEBUG("SetLatchSource: SetLatchSource enter 3550 \n"); | ||
3034 | DEBIreplace(dev, k->MyCRB, | ||
3035 | (uint16_t) (~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC)), | ||
3036 | (uint16_t) (value << CRBBIT_LATCHSRC)); | ||
3037 | |||
3038 | DEBUG("SetLatchSource: SetLatchSource exit \n"); | ||
3039 | } | ||
3040 | |||
3041 | /* static uint16_t GetLatchSource(comedi_device *dev, enc_private *k ) */ | ||
3042 | /* { */ | ||
3043 | /* return ( DEBIread( dev, k->MyCRB) >> CRBBIT_LATCHSRC ) & 3; */ | ||
3044 | /* } */ | ||
3045 | |||
3046 | ///////////////////////////////////////////////////////////////////////// | ||
3047 | // Return/set the event that will trigger transfer of the preload | ||
3048 | // register into the counter. 0=ThisCntr_Index, 1=ThisCntr_Overflow, | ||
3049 | // 2=OverflowA (B counters only), 3=disabled. | ||
3050 | |||
3051 | static void SetLoadTrig_A(comedi_device * dev, enc_private * k, uint16_t Trig) | ||
3052 | { | ||
3053 | DEBIreplace(dev, k->MyCRA, (uint16_t) (~CRAMSK_LOADSRC_A), | ||
3054 | (uint16_t) (Trig << CRABIT_LOADSRC_A)); | ||
3055 | } | ||
3056 | |||
3057 | static void SetLoadTrig_B(comedi_device * dev, enc_private * k, uint16_t Trig) | ||
3058 | { | ||
3059 | DEBIreplace(dev, k->MyCRB, | ||
3060 | (uint16_t) (~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL)), | ||
3061 | (uint16_t) (Trig << CRBBIT_LOADSRC_B)); | ||
3062 | } | ||
3063 | |||
3064 | static uint16_t GetLoadTrig_A(comedi_device * dev, enc_private * k) | ||
3065 | { | ||
3066 | return (DEBIread(dev, k->MyCRA) >> CRABIT_LOADSRC_A) & 3; | ||
3067 | } | ||
3068 | |||
3069 | static uint16_t GetLoadTrig_B(comedi_device * dev, enc_private * k) | ||
3070 | { | ||
3071 | return (DEBIread(dev, k->MyCRB) >> CRBBIT_LOADSRC_B) & 3; | ||
3072 | } | ||
3073 | |||
3074 | //////////////////// | ||
3075 | // Return/set counter interrupt source and clear any captured | ||
3076 | // index/overflow events. IntSource: 0=Disabled, 1=OverflowOnly, | ||
3077 | // 2=IndexOnly, 3=IndexAndOverflow. | ||
3078 | |||
3079 | static void SetIntSrc_A(comedi_device * dev, enc_private * k, | ||
3080 | uint16_t IntSource) | ||
3081 | { | ||
3082 | // Reset any pending counter overflow or index captures. | ||
3083 | DEBIreplace(dev, k->MyCRB, (uint16_t) (~CRBMSK_INTCTRL), | ||
3084 | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); | ||
3085 | |||
3086 | // Program counter interrupt source. | ||
3087 | DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A, | ||
3088 | (uint16_t) (IntSource << CRABIT_INTSRC_A)); | ||
3089 | |||
3090 | // Update MISC2 interrupt enable mask. | ||
3091 | devpriv->CounterIntEnabs = | ||
3092 | (devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k-> | ||
3093 | MyEventBits[IntSource]; | ||
3094 | } | ||
3095 | |||
3096 | static void SetIntSrc_B(comedi_device * dev, enc_private * k, | ||
3097 | uint16_t IntSource) | ||
3098 | { | ||
3099 | uint16_t crb; | ||
3100 | |||
3101 | // Cache writeable CRB register image. | ||
3102 | crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; | ||
3103 | |||
3104 | // Reset any pending counter overflow or index captures. | ||
3105 | DEBIwrite(dev, k->MyCRB, | ||
3106 | (uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B)); | ||
3107 | |||
3108 | // Program counter interrupt source. | ||
3109 | DEBIwrite(dev, k->MyCRB, | ||
3110 | (uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource << | ||
3111 | CRBBIT_INTSRC_B))); | ||
3112 | |||
3113 | // Update MISC2 interrupt enable mask. | ||
3114 | devpriv->CounterIntEnabs = | ||
3115 | (devpriv->CounterIntEnabs & ~k->MyEventBits[3]) | k-> | ||
3116 | MyEventBits[IntSource]; | ||
3117 | } | ||
3118 | |||
3119 | static uint16_t GetIntSrc_A(comedi_device * dev, enc_private * k) | ||
3120 | { | ||
3121 | return (DEBIread(dev, k->MyCRA) >> CRABIT_INTSRC_A) & 3; | ||
3122 | } | ||
3123 | |||
3124 | static uint16_t GetIntSrc_B(comedi_device * dev, enc_private * k) | ||
3125 | { | ||
3126 | return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3; | ||
3127 | } | ||
3128 | |||
3129 | ///////////////////////////////////////////////////////////////////////// | ||
3130 | // Return/set the clock multiplier. | ||
3131 | |||
3132 | /* static void SetClkMult(comedi_device *dev, enc_private *k, uint16_t value ) */ | ||
3133 | /* { */ | ||
3134 | /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKMULT ) | ( value << STDBIT_CLKMULT ) ), FALSE ); */ | ||
3135 | /* } */ | ||
3136 | |||
3137 | /* static uint16_t GetClkMult(comedi_device *dev, enc_private *k ) */ | ||
3138 | /* { */ | ||
3139 | /* return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */ | ||
3140 | /* } */ | ||
3141 | |||
3142 | /* ////////////////////////////////////////////////////////////////////////// */ | ||
3143 | /* // Return/set the clock polarity. */ | ||
3144 | |||
3145 | /* static void SetClkPol( comedi_device *dev,enc_private *k, uint16_t value ) */ | ||
3146 | /* { */ | ||
3147 | /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKPOL ) | ( value << STDBIT_CLKPOL ) ), FALSE ); */ | ||
3148 | /* } */ | ||
3149 | |||
3150 | /* static uint16_t GetClkPol(comedi_device *dev, enc_private *k ) */ | ||
3151 | /* { */ | ||
3152 | /* return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */ | ||
3153 | /* } */ | ||
3154 | |||
3155 | /* /////////////////////////////////////////////////////////////////////// */ | ||
3156 | /* // Return/set the clock source. */ | ||
3157 | |||
3158 | /* static void SetClkSrc( comedi_device *dev,enc_private *k, uint16_t value ) */ | ||
3159 | /* { */ | ||
3160 | /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_CLKSRC ) | ( value << STDBIT_CLKSRC ) ), FALSE ); */ | ||
3161 | /* } */ | ||
3162 | |||
3163 | /* static uint16_t GetClkSrc( comedi_device *dev,enc_private *k ) */ | ||
3164 | /* { */ | ||
3165 | /* return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */ | ||
3166 | /* } */ | ||
3167 | |||
3168 | /* //////////////////////////////////////////////////////////////////////// */ | ||
3169 | /* // Return/set the index polarity. */ | ||
3170 | |||
3171 | /* static void SetIndexPol(comedi_device *dev, enc_private *k, uint16_t value ) */ | ||
3172 | /* { */ | ||
3173 | /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXPOL ) | ( (value != 0) << STDBIT_INDXPOL ) ), FALSE ); */ | ||
3174 | /* } */ | ||
3175 | |||
3176 | /* static uint16_t GetIndexPol(comedi_device *dev, enc_private *k ) */ | ||
3177 | /* { */ | ||
3178 | /* return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */ | ||
3179 | /* } */ | ||
3180 | |||
3181 | /* //////////////////////////////////////////////////////////////////////// */ | ||
3182 | /* // Return/set the index source. */ | ||
3183 | |||
3184 | /* static void SetIndexSrc(comedi_device *dev, enc_private *k, uint16_t value ) */ | ||
3185 | /* { */ | ||
3186 | /* DEBUG("SetIndexSrc: set index src enter 3700\n"); */ | ||
3187 | /* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */ | ||
3188 | /* } */ | ||
3189 | |||
3190 | /* static uint16_t GetIndexSrc(comedi_device *dev, enc_private *k ) */ | ||
3191 | /* { */ | ||
3192 | /* return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */ | ||
3193 | /* } */ | ||
3194 | |||
3195 | /////////////////////////////////////////////////////////////////// | ||
3196 | // Generate an index pulse. | ||
3197 | |||
3198 | static void PulseIndex_A(comedi_device * dev, enc_private * k) | ||
3199 | { | ||
3200 | register uint16_t cra; | ||
3201 | |||
3202 | DEBUG("PulseIndex_A: pulse index enter\n"); | ||
3203 | |||
3204 | cra = DEBIread(dev, k->MyCRA); // Pulse index. | ||
3205 | DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A)); | ||
3206 | DEBUG("PulseIndex_A: pulse index step1\n"); | ||
3207 | DEBIwrite(dev, k->MyCRA, cra); | ||
3208 | } | ||
3209 | |||
3210 | static void PulseIndex_B(comedi_device * dev, enc_private * k) | ||
3211 | { | ||
3212 | register uint16_t crb; | ||
3213 | |||
3214 | crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; // Pulse index. | ||
3215 | DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B)); | ||
3216 | DEBIwrite(dev, k->MyCRB, crb); | ||
3217 | } | ||
3218 | |||
3219 | ///////////////////////////////////////////////////////// | ||
3220 | // Write value into counter preload register. | ||
3221 | |||
3222 | static void Preload(comedi_device * dev, enc_private * k, uint32_t value) | ||
3223 | { | ||
3224 | DEBUG("Preload: preload enter\n"); | ||
3225 | DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value); // Write value to preload register. | ||
3226 | DEBUG("Preload: preload step 1\n"); | ||
3227 | DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2), | ||
3228 | (uint16_t) (value >> 16)); | ||
3229 | } | ||
3230 | |||
3231 | static void CountersInit(comedi_device * dev) | ||
3232 | { | ||
3233 | int chan; | ||
3234 | enc_private *k; | ||
3235 | uint16_t Setup = (LOADSRC_INDX << BF_LOADSRC) | // Preload upon | ||
3236 | // index. | ||
3237 | (INDXSRC_SOFT << BF_INDXSRC) | // Disable hardware index. | ||
3238 | (CLKSRC_COUNTER << BF_CLKSRC) | // Operating mode is counter. | ||
3239 | (CLKPOL_POS << BF_CLKPOL) | // Active high clock. | ||
3240 | (CNTDIR_UP << BF_CLKPOL) | // Count direction is up. | ||
3241 | (CLKMULT_1X << BF_CLKMULT) | // Clock multiplier is 1x. | ||
3242 | (CLKENAB_INDEX << BF_CLKENAB); // Enabled by index | ||
3243 | |||
3244 | // Disable all counter interrupts and clear any captured counter events. | ||
3245 | for (chan = 0; chan < S626_ENCODER_CHANNELS; chan++) { | ||
3246 | k = &encpriv[chan]; | ||
3247 | k->SetMode(dev, k, Setup, TRUE); | ||
3248 | k->SetIntSrc(dev, k, 0); | ||
3249 | k->ResetCapFlags(dev, k); | ||
3250 | k->SetEnable(dev, k, CLKENAB_ALWAYS); | ||
3251 | } | ||
3252 | DEBUG("CountersInit: counters initialized \n"); | ||
3253 | |||
3254 | } | ||
diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h new file mode 100644 index 000000000000..11d8b1ceb0b8 --- /dev/null +++ b/drivers/staging/comedi/drivers/s626.h | |||
@@ -0,0 +1,802 @@ | |||
1 | /* | ||
2 | comedi/drivers/s626.h | ||
3 | Sensoray s626 Comedi driver, header file | ||
4 | |||
5 | COMEDI - Linux Control and Measurement Device Interface | ||
6 | Copyright (C) 2000 David A. Schleef <ds@schleef.org> | ||
7 | |||
8 | Based on Sensoray Model 626 Linux driver Version 0.2 | ||
9 | Copyright (C) 2002-2004 Sensoray Co., Inc. | ||
10 | |||
11 | This program is free software; you can redistribute it and/or modify | ||
12 | it under the terms of the GNU General Public License as published by | ||
13 | the Free Software Foundation; either version 2 of the License, or | ||
14 | (at your option) any later version. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | You should have received a copy of the GNU General Public License | ||
22 | along with this program; if not, write to the Free Software | ||
23 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | |||
25 | */ | ||
26 | |||
27 | /* | ||
28 | Driver: s626.o (s626.ko) | ||
29 | Description: Sensoray 626 driver | ||
30 | Devices: Sensoray s626 | ||
31 | Authors: Gianluca Palli <gpalli@deis.unibo.it>, | ||
32 | Updated: Thu, 12 Jul 2005 | ||
33 | Status: experimental | ||
34 | |||
35 | Configuration Options: | ||
36 | analog input: | ||
37 | none | ||
38 | |||
39 | analog output: | ||
40 | none | ||
41 | |||
42 | digital channel: | ||
43 | s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels | ||
44 | supported configuration options: | ||
45 | INSN_CONFIG_DIO_QUERY | ||
46 | COMEDI_INPUT | ||
47 | COMEDI_OUTPUT | ||
48 | |||
49 | encoder: | ||
50 | Every channel must be configured before reading. | ||
51 | |||
52 | Example code | ||
53 | |||
54 | insn.insn=INSN_CONFIG; //configuration instruction | ||
55 | insn.n=1; //number of operation (must be 1) | ||
56 | insn.data=&initialvalue; //initial value loaded into encoder | ||
57 | //during configuration | ||
58 | insn.subdev=5; //encoder subdevice | ||
59 | insn.chanspec=CR_PACK(encoder_channel,0,AREF_OTHER); //encoder_channel | ||
60 | //to configure | ||
61 | |||
62 | comedi_do_insn(cf,&insn); //executing configuration | ||
63 | */ | ||
64 | |||
65 | #ifdef _DEBUG_ | ||
66 | #define DEBUG(...); rt_printk(__VA_ARGS__); | ||
67 | #else | ||
68 | #define DEBUG(...) | ||
69 | #endif | ||
70 | |||
71 | #if !defined(TRUE) | ||
72 | #define TRUE (1) | ||
73 | #endif | ||
74 | |||
75 | #if !defined(FALSE) | ||
76 | #define FALSE (0) | ||
77 | #endif | ||
78 | |||
79 | #if !defined(EXTERN) | ||
80 | #if defined(__cplusplus) | ||
81 | #define EXTERN extern "C" | ||
82 | #else | ||
83 | #define EXTERN extern | ||
84 | #endif | ||
85 | #endif | ||
86 | |||
87 | #if !defined(INLINE) | ||
88 | #define INLINE static __inline | ||
89 | #endif | ||
90 | |||
91 | ///////////////////////////////////////////////////// | ||
92 | #include<linux/slab.h> | ||
93 | |||
94 | #define S626_SIZE 0x0200 | ||
95 | #define SIZEOF_ADDRESS_SPACE 0x0200 | ||
96 | #define DMABUF_SIZE 4096 // 4k pages | ||
97 | |||
98 | #define S626_ADC_CHANNELS 16 | ||
99 | #define S626_DAC_CHANNELS 4 | ||
100 | #define S626_ENCODER_CHANNELS 6 | ||
101 | #define S626_DIO_CHANNELS 48 | ||
102 | #define S626_DIO_BANKS 3 // Number of DIO groups. | ||
103 | #define S626_DIO_EXTCHANS 40 // Number of | ||
104 | // extended-capability | ||
105 | // DIO channels. | ||
106 | |||
107 | #define NUM_TRIMDACS 12 // Number of valid TrimDAC channels. | ||
108 | |||
109 | // PCI bus interface types. | ||
110 | #define INTEL 1 // Intel bus type. | ||
111 | #define MOTOROLA 2 // Motorola bus type. | ||
112 | |||
113 | ////////////////////////////////////////////////////////// | ||
114 | |||
115 | ////////////////////////////////////////////////////////// | ||
116 | #define PLATFORM INTEL // *** SELECT PLATFORM TYPE *** | ||
117 | ////////////////////////////////////////////////////////// | ||
118 | |||
119 | #define RANGE_5V 0x10 // +/-5V range | ||
120 | #define RANGE_10V 0x00 // +/-10V range | ||
121 | |||
122 | #define EOPL 0x80 // End of ADC poll list marker. | ||
123 | #define GSEL_BIPOLAR5V 0x00F0 // LP_GSEL setting for 5V bipolar range. | ||
124 | #define GSEL_BIPOLAR10V 0x00A0 // LP_GSEL setting for 10V bipolar range. | ||
125 | |||
126 | // Error codes that must be visible to this base class. | ||
127 | #define ERR_ILLEGAL_PARM 0x00010000 // Illegal function parameter value was specified. | ||
128 | #define ERR_I2C 0x00020000 // I2C error. | ||
129 | #define ERR_COUNTERSETUP 0x00200000 // Illegal setup specified for counter channel. | ||
130 | #define ERR_DEBI_TIMEOUT 0x00400000 // DEBI transfer timed out. | ||
131 | |||
132 | // Organization (physical order) and size (in DWORDs) of logical DMA buffers contained by ANA_DMABUF. | ||
133 | #define ADC_DMABUF_DWORDS 40 // ADC DMA buffer must hold 16 samples, plus pre/post garbage samples. | ||
134 | #define DAC_WDMABUF_DWORDS 1 // DAC output DMA buffer holds a single sample. | ||
135 | |||
136 | // All remaining space in 4KB DMA buffer is available for the RPS1 program. | ||
137 | |||
138 | // Address offsets, in DWORDS, from base of DMA buffer. | ||
139 | #define DAC_WDMABUF_OS ADC_DMABUF_DWORDS | ||
140 | |||
141 | // Interrupt enab bit in ISR and IER. | ||
142 | #define IRQ_GPIO3 0x00000040 // IRQ enable for GPIO3. | ||
143 | #define IRQ_RPS1 0x10000000 | ||
144 | #define ISR_AFOU 0x00000800 // Audio fifo | ||
145 | // under/overflow | ||
146 | // detected. | ||
147 | #define IRQ_COINT1A 0x0400 // conter 1A overflow | ||
148 | // interrupt mask | ||
149 | #define IRQ_COINT1B 0x0800 // conter 1B overflow | ||
150 | // interrupt mask | ||
151 | #define IRQ_COINT2A 0x1000 // conter 2A overflow | ||
152 | // interrupt mask | ||
153 | #define IRQ_COINT2B 0x2000 // conter 2B overflow | ||
154 | // interrupt mask | ||
155 | #define IRQ_COINT3A 0x4000 // conter 3A overflow | ||
156 | // interrupt mask | ||
157 | #define IRQ_COINT3B 0x8000 // conter 3B overflow | ||
158 | // interrupt mask | ||
159 | |||
160 | // RPS command codes. | ||
161 | #define RPS_CLRSIGNAL 0x00000000 // CLEAR SIGNAL | ||
162 | #define RPS_SETSIGNAL 0x10000000 // SET SIGNAL | ||
163 | #define RPS_NOP 0x00000000 // NOP | ||
164 | #define RPS_PAUSE 0x20000000 // PAUSE | ||
165 | #define RPS_UPLOAD 0x40000000 // UPLOAD | ||
166 | #define RPS_JUMP 0x80000000 // JUMP | ||
167 | #define RPS_LDREG 0x90000100 // LDREG (1 uint32_t only) | ||
168 | #define RPS_STREG 0xA0000100 // STREG (1 uint32_t only) | ||
169 | #define RPS_STOP 0x50000000 // STOP | ||
170 | #define RPS_IRQ 0x60000000 // IRQ | ||
171 | |||
172 | #define RPS_LOGICAL_OR 0x08000000 // Logical OR conditionals. | ||
173 | #define RPS_INVERT 0x04000000 // Test for negated semaphores. | ||
174 | #define RPS_DEBI 0x00000002 // DEBI done | ||
175 | |||
176 | #define RPS_SIG0 0x00200000 // RPS semaphore 0 (used by ADC). | ||
177 | #define RPS_SIG1 0x00400000 // RPS semaphore 1 (used by DAC). | ||
178 | #define RPS_SIG2 0x00800000 // RPS semaphore 2 (not used). | ||
179 | #define RPS_GPIO2 0x00080000 // RPS GPIO2 | ||
180 | #define RPS_GPIO3 0x00100000 // RPS GPIO3 | ||
181 | |||
182 | #define RPS_SIGADC RPS_SIG0 // Trigger/status for ADC's RPS program. | ||
183 | #define RPS_SIGDAC RPS_SIG1 // Trigger/status for DAC's RPS program. | ||
184 | |||
185 | // RPS clock parameters. | ||
186 | #define RPSCLK_SCALAR 8 // This is apparent ratio of PCI/RPS clks (undocumented!!). | ||
187 | #define RPSCLK_PER_US ( 33 / RPSCLK_SCALAR ) // Number of RPS clocks in one microsecond. | ||
188 | |||
189 | // Event counter source addresses. | ||
190 | #define SBA_RPS_A0 0x27 // Time of RPS0 busy, in PCI clocks. | ||
191 | |||
192 | // GPIO constants. | ||
193 | #define GPIO_BASE 0x10004000 // GPIO 0,2,3 = inputs, GPIO3 = IRQ; GPIO1 = out. | ||
194 | #define GPIO1_LO 0x00000000 // GPIO1 set to LOW. | ||
195 | #define GPIO1_HI 0x00001000 // GPIO1 set to HIGH. | ||
196 | |||
197 | // Primary Status Register (PSR) constants. | ||
198 | #define PSR_DEBI_E 0x00040000 // DEBI event flag. | ||
199 | #define PSR_DEBI_S 0x00080000 // DEBI status flag. | ||
200 | #define PSR_A2_IN 0x00008000 // Audio output DMA2 protection address reached. | ||
201 | #define PSR_AFOU 0x00000800 // Audio FIFO under/overflow detected. | ||
202 | #define PSR_GPIO2 0x00000020 // GPIO2 input pin: 0=AdcBusy, 1=AdcIdle. | ||
203 | #define PSR_EC0S 0x00000001 // Event counter 0 threshold reached. | ||
204 | |||
205 | // Secondary Status Register (SSR) constants. | ||
206 | #define SSR_AF2_OUT 0x00000200 // Audio 2 output FIFO under/overflow detected. | ||
207 | |||
208 | // Master Control Register 1 (MC1) constants. | ||
209 | #define MC1_SOFT_RESET 0x80000000 // Invoke 7146 soft reset. | ||
210 | #define MC1_SHUTDOWN 0x3FFF0000 // Shut down all MC1-controlled enables. | ||
211 | |||
212 | #define MC1_ERPS1 0x2000 // enab/disable RPS task 1. | ||
213 | #define MC1_ERPS0 0x1000 // enab/disable RPS task 0. | ||
214 | #define MC1_DEBI 0x0800 // enab/disable DEBI pins. | ||
215 | #define MC1_AUDIO 0x0200 // enab/disable audio port pins. | ||
216 | #define MC1_I2C 0x0100 // enab/disable I2C interface. | ||
217 | #define MC1_A2OUT 0x0008 // enab/disable transfer on A2 out. | ||
218 | #define MC1_A2IN 0x0004 // enab/disable transfer on A2 in. | ||
219 | #define MC1_A1IN 0x0001 // enab/disable transfer on A1 in. | ||
220 | |||
221 | // Master Control Register 2 (MC2) constants. | ||
222 | #define MC2_UPLD_DEBIq 0x00020002 // Upload DEBI registers. | ||
223 | #define MC2_UPLD_IICq 0x00010001 // Upload I2C registers. | ||
224 | #define MC2_RPSSIG2_ONq 0x20002000 // Assert RPS_SIG2. | ||
225 | #define MC2_RPSSIG1_ONq 0x10001000 // Assert RPS_SIG1. | ||
226 | #define MC2_RPSSIG0_ONq 0x08000800 // Assert RPS_SIG0. | ||
227 | #define MC2_UPLD_DEBI_MASKq 0x00000002 // Upload DEBI mask. | ||
228 | #define MC2_UPLD_IIC_MASKq 0x00000001 // Upload I2C mask. | ||
229 | #define MC2_RPSSIG2_MASKq 0x00002000 // RPS_SIG2 bit mask. | ||
230 | #define MC2_RPSSIG1_MASKq 0x00001000 // RPS_SIG1 bit mask. | ||
231 | #define MC2_RPSSIG0_MASKq 0x00000800 // RPS_SIG0 bit mask. | ||
232 | |||
233 | #define MC2_DELAYTRIG_4USq MC2_RPSSIG1_ON | ||
234 | #define MC2_DELAYBUSY_4USq MC2_RPSSIG1_MASK | ||
235 | |||
236 | #define MC2_DELAYTRIG_6USq MC2_RPSSIG2_ON | ||
237 | #define MC2_DELAYBUSY_6USq MC2_RPSSIG2_MASK | ||
238 | |||
239 | #define MC2_UPLD_DEBI 0x0002 // Upload DEBI. | ||
240 | #define MC2_UPLD_IIC 0x0001 // Upload I2C. | ||
241 | #define MC2_RPSSIG2 0x2000 // RPS signal 2 (not used). | ||
242 | #define MC2_RPSSIG1 0x1000 // RPS signal 1 (DAC RPS busy). | ||
243 | #define MC2_RPSSIG0 0x0800 // RPS signal 0 (ADC RPS busy). | ||
244 | |||
245 | #define MC2_ADC_RPS MC2_RPSSIG0 // ADC RPS busy. | ||
246 | #define MC2_DAC_RPS MC2_RPSSIG1 // DAC RPS busy. | ||
247 | |||
248 | ///////////////////oldies/////////// | ||
249 | #define MC2_UPLD_DEBIQ 0x00020002 // Upload DEBI registers. | ||
250 | #define MC2_UPLD_IICQ 0x00010001 // Upload I2C registers. | ||
251 | //////////////////////////////////////// | ||
252 | |||
253 | // PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS //////////////////////// | ||
254 | #define P_PCI_BT_A 0x004C // Audio DMA | ||
255 | // burst/threshold | ||
256 | // control. | ||
257 | #define P_DEBICFG 0x007C // DEBI configuration. | ||
258 | #define P_DEBICMD 0x0080 // DEBI command. | ||
259 | #define P_DEBIPAGE 0x0084 // DEBI page. | ||
260 | #define P_DEBIAD 0x0088 // DEBI target address. | ||
261 | #define P_I2CCTRL 0x008C // I2C control. | ||
262 | #define P_I2CSTAT 0x0090 // I2C status. | ||
263 | #define P_BASEA2_IN 0x00AC // Audio input 2 base | ||
264 | // physical DMAbuf | ||
265 | // address. | ||
266 | #define P_PROTA2_IN 0x00B0 // Audio input 2 | ||
267 | // physical DMAbuf | ||
268 | // protection address. | ||
269 | #define P_PAGEA2_IN 0x00B4 // Audio input 2 | ||
270 | // paging attributes. | ||
271 | #define P_BASEA2_OUT 0x00B8 // Audio output 2 base | ||
272 | // physical DMAbuf | ||
273 | // address. | ||
274 | #define P_PROTA2_OUT 0x00BC // Audio output 2 | ||
275 | // physical DMAbuf | ||
276 | // protection address. | ||
277 | #define P_PAGEA2_OUT 0x00C0 // Audio output 2 | ||
278 | // paging attributes. | ||
279 | #define P_RPSPAGE0 0x00C4 // RPS0 page. | ||
280 | #define P_RPSPAGE1 0x00C8 // RPS1 page. | ||
281 | #define P_RPS0_TOUT 0x00D4 // RPS0 time-out. | ||
282 | #define P_RPS1_TOUT 0x00D8 // RPS1 time-out. | ||
283 | #define P_IER 0x00DC // Interrupt enable. | ||
284 | #define P_GPIO 0x00E0 // General-purpose I/O. | ||
285 | #define P_EC1SSR 0x00E4 // Event counter set 1 | ||
286 | // source select. | ||
287 | #define P_ECT1R 0x00EC // Event counter | ||
288 | // threshold set 1. | ||
289 | #define P_ACON1 0x00F4 // Audio control 1. | ||
290 | #define P_ACON2 0x00F8 // Audio control 2. | ||
291 | #define P_MC1 0x00FC // Master control 1. | ||
292 | #define P_MC2 0x0100 // Master control 2. | ||
293 | #define P_RPSADDR0 0x0104 // RPS0 instruction pointer. | ||
294 | #define P_RPSADDR1 0x0108 // RPS1 instruction pointer. | ||
295 | #define P_ISR 0x010C // Interrupt status. | ||
296 | #define P_PSR 0x0110 // Primary status. | ||
297 | #define P_SSR 0x0114 // Secondary status. | ||
298 | #define P_EC1R 0x0118 // Event counter set 1. | ||
299 | #define P_ADP4 0x0138 // Logical audio DMA | ||
300 | // pointer of audio | ||
301 | // input FIFO A2_IN. | ||
302 | #define P_FB_BUFFER1 0x0144 // Audio feedback buffer 1. | ||
303 | #define P_FB_BUFFER2 0x0148 // Audio feedback buffer 2. | ||
304 | #define P_TSL1 0x0180 // Audio time slot list 1. | ||
305 | #define P_TSL2 0x01C0 // Audio time slot list 2. | ||
306 | |||
307 | // LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS ///////////////// | ||
308 | // Analog I/O registers: | ||
309 | #define LP_DACPOL 0x0082 // Write DAC polarity. | ||
310 | #define LP_GSEL 0x0084 // Write ADC gain. | ||
311 | #define LP_ISEL 0x0086 // Write ADC channel select. | ||
312 | // Digital I/O (write only): | ||
313 | #define LP_WRINTSELA 0x0042 // Write A interrupt enable. | ||
314 | #define LP_WREDGSELA 0x0044 // Write A edge selection. | ||
315 | #define LP_WRCAPSELA 0x0046 // Write A capture enable. | ||
316 | #define LP_WRDOUTA 0x0048 // Write A digital output. | ||
317 | #define LP_WRINTSELB 0x0052 // Write B interrupt enable. | ||
318 | #define LP_WREDGSELB 0x0054 // Write B edge selection. | ||
319 | #define LP_WRCAPSELB 0x0056 // Write B capture enable. | ||
320 | #define LP_WRDOUTB 0x0058 // Write B digital output. | ||
321 | #define LP_WRINTSELC 0x0062 // Write C interrupt enable. | ||
322 | #define LP_WREDGSELC 0x0064 // Write C edge selection. | ||
323 | #define LP_WRCAPSELC 0x0066 // Write C capture enable. | ||
324 | #define LP_WRDOUTC 0x0068 // Write C digital output. | ||
325 | |||
326 | // Digital I/O (read only): | ||
327 | #define LP_RDDINA 0x0040 // Read digital input. | ||
328 | #define LP_RDCAPFLGA 0x0048 // Read edges captured. | ||
329 | #define LP_RDINTSELA 0x004A // Read interrupt | ||
330 | // enable register. | ||
331 | #define LP_RDEDGSELA 0x004C // Read edge | ||
332 | // selection | ||
333 | // register. | ||
334 | #define LP_RDCAPSELA 0x004E // Read capture | ||
335 | // enable register. | ||
336 | #define LP_RDDINB 0x0050 // Read digital input. | ||
337 | #define LP_RDCAPFLGB 0x0058 // Read edges captured. | ||
338 | #define LP_RDINTSELB 0x005A // Read interrupt | ||
339 | // enable register. | ||
340 | #define LP_RDEDGSELB 0x005C // Read edge | ||
341 | // selection | ||
342 | // register. | ||
343 | #define LP_RDCAPSELB 0x005E // Read capture | ||
344 | // enable register. | ||
345 | #define LP_RDDINC 0x0060 // Read digital input. | ||
346 | #define LP_RDCAPFLGC 0x0068 // Read edges captured. | ||
347 | #define LP_RDINTSELC 0x006A // Read interrupt | ||
348 | // enable register. | ||
349 | #define LP_RDEDGSELC 0x006C // Read edge | ||
350 | // selection | ||
351 | // register. | ||
352 | #define LP_RDCAPSELC 0x006E // Read capture | ||
353 | // enable register. | ||
354 | // Counter Registers (read/write): | ||
355 | #define LP_CR0A 0x0000 // 0A setup register. | ||
356 | #define LP_CR0B 0x0002 // 0B setup register. | ||
357 | #define LP_CR1A 0x0004 // 1A setup register. | ||
358 | #define LP_CR1B 0x0006 // 1B setup register. | ||
359 | #define LP_CR2A 0x0008 // 2A setup register. | ||
360 | #define LP_CR2B 0x000A // 2B setup register. | ||
361 | // Counter PreLoad (write) and Latch (read) Registers: | ||
362 | #define LP_CNTR0ALSW 0x000C // 0A lsw. | ||
363 | #define LP_CNTR0AMSW 0x000E // 0A msw. | ||
364 | #define LP_CNTR0BLSW 0x0010 // 0B lsw. | ||
365 | #define LP_CNTR0BMSW 0x0012 // 0B msw. | ||
366 | #define LP_CNTR1ALSW 0x0014 // 1A lsw. | ||
367 | #define LP_CNTR1AMSW 0x0016 // 1A msw. | ||
368 | #define LP_CNTR1BLSW 0x0018 // 1B lsw. | ||
369 | #define LP_CNTR1BMSW 0x001A // 1B msw. | ||
370 | #define LP_CNTR2ALSW 0x001C // 2A lsw. | ||
371 | #define LP_CNTR2AMSW 0x001E // 2A msw. | ||
372 | #define LP_CNTR2BLSW 0x0020 // 2B lsw. | ||
373 | #define LP_CNTR2BMSW 0x0022 // 2B msw. | ||
374 | // Miscellaneous Registers (read/write): | ||
375 | #define LP_MISC1 0x0088 // Read/write Misc1. | ||
376 | #define LP_WRMISC2 0x0090 // Write Misc2. | ||
377 | #define LP_RDMISC2 0x0082 // Read Misc2. | ||
378 | |||
379 | // Bit masks for MISC1 register that are the same for reads and writes. | ||
380 | #define MISC1_WENABLE 0x8000 // enab writes to | ||
381 | // MISC2 (except Clear | ||
382 | // Watchdog bit). | ||
383 | #define MISC1_WDISABLE 0x0000 // Disable writes to MISC2. | ||
384 | #define MISC1_EDCAP 0x1000 // enab edge capture | ||
385 | // on DIO chans | ||
386 | // specified by | ||
387 | // LP_WRCAPSELx. | ||
388 | #define MISC1_NOEDCAP 0x0000 // Disable edge | ||
389 | // capture on | ||
390 | // specified DIO | ||
391 | // chans. | ||
392 | |||
393 | // Bit masks for MISC1 register reads. | ||
394 | #define RDMISC1_WDTIMEOUT 0x4000 // Watchdog timer timed out. | ||
395 | |||
396 | // Bit masks for MISC2 register writes. | ||
397 | #define WRMISC2_WDCLEAR 0x8000 // Reset watchdog | ||
398 | // timer to zero. | ||
399 | #define WRMISC2_CHARGE_ENABLE 0x4000 // enab battery | ||
400 | // trickle charging. | ||
401 | |||
402 | // Bit masks for MISC2 register that are the same for reads and writes. | ||
403 | #define MISC2_BATT_ENABLE 0x0008 // Backup battery enable. | ||
404 | #define MISC2_WDENABLE 0x0004 // Watchdog timer enable. | ||
405 | #define MISC2_WDPERIOD_MASK 0x0003 // Watchdog interval | ||
406 | // select mask. | ||
407 | |||
408 | // Bit masks for ACON1 register. | ||
409 | #define A2_RUN 0x40000000 // Run A2 based on TSL2. | ||
410 | #define A1_RUN 0x20000000 // Run A1 based on TSL1. | ||
411 | #define A1_SWAP 0x00200000 // Use big-endian for A1. | ||
412 | #define A2_SWAP 0x00100000 // Use big-endian for A2. | ||
413 | #define WS_MODES 0x00019999 // WS0 = TSL1 trigger | ||
414 | // input, WS1-WS4 = | ||
415 | // CS* outputs. | ||
416 | |||
417 | #if PLATFORM == INTEL // Base ACON1 config: | ||
418 | // always run A1 based | ||
419 | // on TSL1. | ||
420 | #define ACON1_BASE ( WS_MODES | A1_RUN ) | ||
421 | #elif PLATFORM == MOTOROLA | ||
422 | #define ACON1_BASE ( WS_MODES | A1_RUN | A1_SWAP | A2_SWAP ) | ||
423 | #endif | ||
424 | |||
425 | #define ACON1_ADCSTART ACON1_BASE // Start ADC: run A1 | ||
426 | // based on TSL1. | ||
427 | #define ACON1_DACSTART ( ACON1_BASE | A2_RUN ) // Start | ||
428 | // transmit to | ||
429 | // DAC: run A2 | ||
430 | // based on | ||
431 | // TSL2. | ||
432 | #define ACON1_DACSTOP ACON1_BASE // Halt A2. | ||
433 | |||
434 | // Bit masks for ACON2 register. | ||
435 | #define A1_CLKSRC_BCLK1 0x00000000 // A1 bit rate = BCLK1 (ADC). | ||
436 | #define A2_CLKSRC_X1 0x00800000 // A2 bit rate = ACLK/1 (DACs). | ||
437 | #define A2_CLKSRC_X2 0x00C00000 // A2 bit rate = ACLK/2 (DACs). | ||
438 | #define A2_CLKSRC_X4 0x01400000 // A2 bit rate = ACLK/4 (DACs). | ||
439 | #define INVERT_BCLK2 0x00100000 // Invert BCLK2 (DACs). | ||
440 | #define BCLK2_OE 0x00040000 // enab BCLK2 (DACs). | ||
441 | #define ACON2_XORMASK 0x000C0000 // XOR mask for ACON2 | ||
442 | // active-low bits. | ||
443 | |||
444 | #define ACON2_INIT ( ACON2_XORMASK ^ ( A1_CLKSRC_BCLK1 | A2_CLKSRC_X2 | INVERT_BCLK2 | BCLK2_OE ) ) | ||
445 | |||
446 | // Bit masks for timeslot records. | ||
447 | #define WS1 0x40000000 // WS output to assert. | ||
448 | #define WS2 0x20000000 | ||
449 | #define WS3 0x10000000 | ||
450 | #define WS4 0x08000000 | ||
451 | #define RSD1 0x01000000 // Shift A1 data in on SD1. | ||
452 | #define SDW_A1 0x00800000 // Store rcv'd char at | ||
453 | // next char slot of | ||
454 | // DWORD1 buffer. | ||
455 | #define SIB_A1 0x00400000 // Store rcv'd char at | ||
456 | // next char slot of | ||
457 | // FB1 buffer. | ||
458 | #define SF_A1 0x00200000 // Write unsigned long | ||
459 | // buffer to input | ||
460 | // FIFO. | ||
461 | |||
462 | //Select parallel-to-serial converter's data source: | ||
463 | #define XFIFO_0 0x00000000 // Data fifo byte 0. | ||
464 | #define XFIFO_1 0x00000010 // Data fifo byte 1. | ||
465 | #define XFIFO_2 0x00000020 // Data fifo byte 2. | ||
466 | #define XFIFO_3 0x00000030 // Data fifo byte 3. | ||
467 | #define XFB0 0x00000040 // FB_BUFFER byte 0. | ||
468 | #define XFB1 0x00000050 // FB_BUFFER byte 1. | ||
469 | #define XFB2 0x00000060 // FB_BUFFER byte 2. | ||
470 | #define XFB3 0x00000070 // FB_BUFFER byte 3. | ||
471 | #define SIB_A2 0x00000200 // Store next dword | ||
472 | // from A2's input | ||
473 | // shifter to FB2 | ||
474 | // buffer. | ||
475 | #define SF_A2 0x00000100 // Store next dword | ||
476 | // from A2's input | ||
477 | // shifter to its | ||
478 | // input fifo. | ||
479 | #define LF_A2 0x00000080 // Load next dword | ||
480 | // from A2's output | ||
481 | // fifo into its | ||
482 | // output dword | ||
483 | // buffer. | ||
484 | #define XSD2 0x00000008 // Shift data out on SD2. | ||
485 | #define RSD3 0x00001800 // Shift data in on SD3. | ||
486 | #define RSD2 0x00001000 // Shift data in on SD2. | ||
487 | #define LOW_A2 0x00000002 // Drive last SD low | ||
488 | // for 7 clks, then | ||
489 | // tri-state. | ||
490 | #define EOS 0x00000001 // End of superframe. | ||
491 | |||
492 | ////////////////////// | ||
493 | |||
494 | // I2C configuration constants. | ||
495 | #define I2C_CLKSEL 0x0400 // I2C bit rate = | ||
496 | // PCIclk/480 = 68.75 | ||
497 | // KHz. | ||
498 | #define I2C_BITRATE 68.75 // I2C bus data bit | ||
499 | // rate (determined by | ||
500 | // I2C_CLKSEL) in KHz. | ||
501 | #define I2C_WRTIME 15.0 // Worst case time,in | ||
502 | // msec, for EEPROM | ||
503 | // internal write op. | ||
504 | |||
505 | // I2C manifest constants. | ||
506 | |||
507 | // Max retries to wait for EEPROM write. | ||
508 | #define I2C_RETRIES ( I2C_WRTIME * I2C_BITRATE / 9.0 ) | ||
509 | #define I2C_ERR 0x0002 // I2C control/status | ||
510 | // flag ERROR. | ||
511 | #define I2C_BUSY 0x0001 // I2C control/status | ||
512 | // flag BUSY. | ||
513 | #define I2C_ABORT 0x0080 // I2C status flag ABORT. | ||
514 | #define I2C_ATTRSTART 0x3 // I2C attribute START. | ||
515 | #define I2C_ATTRCONT 0x2 // I2C attribute CONT. | ||
516 | #define I2C_ATTRSTOP 0x1 // I2C attribute STOP. | ||
517 | #define I2C_ATTRNOP 0x0 // I2C attribute NOP. | ||
518 | |||
519 | // I2C read command | EEPROM address. | ||
520 | #define I2CR ( devpriv->I2CAdrs | 1 ) | ||
521 | |||
522 | // I2C write command | EEPROM address. | ||
523 | #define I2CW ( devpriv->I2CAdrs ) | ||
524 | |||
525 | // Code macros used for constructing I2C command bytes. | ||
526 | #define I2C_B2(ATTR,VAL) ( ( (ATTR) << 6 ) | ( (VAL) << 24 ) ) | ||
527 | #define I2C_B1(ATTR,VAL) ( ( (ATTR) << 4 ) | ( (VAL) << 16 ) ) | ||
528 | #define I2C_B0(ATTR,VAL) ( ( (ATTR) << 2 ) | ( (VAL) << 8 ) ) | ||
529 | |||
530 | //////////////////////////////////////////////////////// | ||
531 | //oldest | ||
532 | #define P_DEBICFGq 0x007C // DEBI configuration. | ||
533 | #define P_DEBICMDq 0x0080 // DEBI command. | ||
534 | #define P_DEBIPAGEq 0x0084 // DEBI page. | ||
535 | #define P_DEBIADq 0x0088 // DEBI target address. | ||
536 | |||
537 | #define DEBI_CFG_TOQ 0x03C00000 // timeout (15 PCI cycles) | ||
538 | #define DEBI_CFG_FASTQ 0x10000000 // fast mode enable | ||
539 | #define DEBI_CFG_16Q 0x00080000 // 16-bit access enable | ||
540 | #define DEBI_CFG_INCQ 0x00040000 // enable address increment | ||
541 | #define DEBI_CFG_TIMEROFFQ 0x00010000 // disable timer | ||
542 | #define DEBI_CMD_RDQ 0x00050000 // read immediate 2 bytes | ||
543 | #define DEBI_CMD_WRQ 0x00040000 // write immediate 2 bytes | ||
544 | #define DEBI_PAGE_DISABLEQ 0x00000000 // paging disable | ||
545 | |||
546 | /////////////////////////////////////////// | ||
547 | // DEBI command constants. | ||
548 | #define DEBI_CMD_SIZE16 ( 2 << 17 ) // Transfer size is | ||
549 | // always 2 bytes. | ||
550 | #define DEBI_CMD_READ 0x00010000 // Read operation. | ||
551 | #define DEBI_CMD_WRITE 0x00000000 // Write operation. | ||
552 | |||
553 | // Read immediate 2 bytes. | ||
554 | #define DEBI_CMD_RDWORD ( DEBI_CMD_READ | DEBI_CMD_SIZE16 ) | ||
555 | |||
556 | // Write immediate 2 bytes. | ||
557 | #define DEBI_CMD_WRWORD ( DEBI_CMD_WRITE | DEBI_CMD_SIZE16 ) | ||
558 | |||
559 | // DEBI configuration constants. | ||
560 | #define DEBI_CFG_XIRQ_EN 0x80000000 // enab external | ||
561 | // interrupt on GPIO3. | ||
562 | #define DEBI_CFG_XRESUME 0x40000000 // Resume block | ||
563 | // transfer when XIRQ | ||
564 | // deasserted. | ||
565 | #define DEBI_CFG_FAST 0x10000000 // Fast mode enable. | ||
566 | |||
567 | // 4-bit field that specifies DEBI timeout value in PCI clock cycles: | ||
568 | #define DEBI_CFG_TOUT_BIT 22 // Finish DEBI cycle after | ||
569 | // this many clocks. | ||
570 | |||
571 | // 2-bit field that specifies Endian byte lane steering: | ||
572 | #define DEBI_CFG_SWAP_NONE 0x00000000 // Straight - don't | ||
573 | // swap any bytes | ||
574 | // (Intel). | ||
575 | #define DEBI_CFG_SWAP_2 0x00100000 // 2-byte swap (Motorola). | ||
576 | #define DEBI_CFG_SWAP_4 0x00200000 // 4-byte swap. | ||
577 | #define DEBI_CFG_16 0x00080000 // Slave is able to | ||
578 | // serve 16-bit | ||
579 | // cycles. | ||
580 | |||
581 | #define DEBI_CFG_SLAVE16 0x00080000 // Slave is able to | ||
582 | // serve 16-bit | ||
583 | // cycles. | ||
584 | #define DEBI_CFG_INC 0x00040000 // enab address | ||
585 | // increment for block | ||
586 | // transfers. | ||
587 | #define DEBI_CFG_INTEL 0x00020000 // Intel style local bus. | ||
588 | #define DEBI_CFG_TIMEROFF 0x00010000 // Disable timer. | ||
589 | |||
590 | #if PLATFORM == INTEL | ||
591 | |||
592 | #define DEBI_TOUT 7 // Wait 7 PCI clocks | ||
593 | // (212 ns) before | ||
594 | // polling RDY. | ||
595 | |||
596 | // Intel byte lane steering (pass through all byte lanes). | ||
597 | #define DEBI_SWAP DEBI_CFG_SWAP_NONE | ||
598 | |||
599 | #elif PLATFORM == MOTOROLA | ||
600 | |||
601 | #define DEBI_TOUT 15 // Wait 15 PCI clocks (454 ns) | ||
602 | // maximum before timing out. | ||
603 | #define DEBI_SWAP DEBI_CFG_SWAP_2 // Motorola byte lane steering. | ||
604 | |||
605 | #endif | ||
606 | |||
607 | // DEBI page table constants. | ||
608 | #define DEBI_PAGE_DISABLE 0x00000000 // Paging disable. | ||
609 | |||
610 | ///////////////////EXTRA FROM OTHER SANSORAY * .h//////// | ||
611 | |||
612 | // LoadSrc values: | ||
613 | #define LOADSRC_INDX 0 // Preload core in response to | ||
614 | // Index. | ||
615 | #define LOADSRC_OVER 1 // Preload core in response to | ||
616 | // Overflow. | ||
617 | #define LOADSRCB_OVERA 2 // Preload B core in response | ||
618 | // to A Overflow. | ||
619 | #define LOADSRC_NONE 3 // Never preload core. | ||
620 | |||
621 | // IntSrc values: | ||
622 | #define INTSRC_NONE 0 // Interrupts disabled. | ||
623 | #define INTSRC_OVER 1 // Interrupt on Overflow. | ||
624 | #define INTSRC_INDX 2 // Interrupt on Index. | ||
625 | #define INTSRC_BOTH 3 // Interrupt on Index or Overflow. | ||
626 | |||
627 | // LatchSrc values: | ||
628 | #define LATCHSRC_AB_READ 0 // Latch on read. | ||
629 | #define LATCHSRC_A_INDXA 1 // Latch A on A Index. | ||
630 | #define LATCHSRC_B_INDXB 2 // Latch B on B Index. | ||
631 | #define LATCHSRC_B_OVERA 3 // Latch B on A Overflow. | ||
632 | |||
633 | // IndxSrc values: | ||
634 | #define INDXSRC_HARD 0 // Hardware or software index. | ||
635 | #define INDXSRC_SOFT 1 // Software index only. | ||
636 | |||
637 | // IndxPol values: | ||
638 | #define INDXPOL_POS 0 // Index input is active high. | ||
639 | #define INDXPOL_NEG 1 // Index input is active low. | ||
640 | |||
641 | // ClkSrc values: | ||
642 | #define CLKSRC_COUNTER 0 // Counter mode. | ||
643 | #define CLKSRC_TIMER 2 // Timer mode. | ||
644 | #define CLKSRC_EXTENDER 3 // Extender mode. | ||
645 | |||
646 | // ClkPol values: | ||
647 | #define CLKPOL_POS 0 // Counter/Extender clock is | ||
648 | // active high. | ||
649 | #define CLKPOL_NEG 1 // Counter/Extender clock is | ||
650 | // active low. | ||
651 | #define CNTDIR_UP 0 // Timer counts up. | ||
652 | #define CNTDIR_DOWN 1 // Timer counts down. | ||
653 | |||
654 | // ClkEnab values: | ||
655 | #define CLKENAB_ALWAYS 0 // Clock always enabled. | ||
656 | #define CLKENAB_INDEX 1 // Clock is enabled by index. | ||
657 | |||
658 | // ClkMult values: | ||
659 | #define CLKMULT_4X 0 // 4x clock multiplier. | ||
660 | #define CLKMULT_2X 1 // 2x clock multiplier. | ||
661 | #define CLKMULT_1X 2 // 1x clock multiplier. | ||
662 | |||
663 | // Bit Field positions in COUNTER_SETUP structure: | ||
664 | #define BF_LOADSRC 9 // Preload trigger. | ||
665 | #define BF_INDXSRC 7 // Index source. | ||
666 | #define BF_INDXPOL 6 // Index polarity. | ||
667 | #define BF_CLKSRC 4 // Clock source. | ||
668 | #define BF_CLKPOL 3 // Clock polarity/count direction. | ||
669 | #define BF_CLKMULT 1 // Clock multiplier. | ||
670 | #define BF_CLKENAB 0 // Clock enable. | ||
671 | |||
672 | // Enumerated counter operating modes specified by ClkSrc bit field in | ||
673 | // a COUNTER_SETUP. | ||
674 | |||
675 | #define CLKSRC_COUNTER 0 // Counter: ENC_C clock, ENC_D | ||
676 | // direction. | ||
677 | #define CLKSRC_TIMER 2 // Timer: SYS_C clock, | ||
678 | // direction specified by | ||
679 | // ClkPol. | ||
680 | #define CLKSRC_EXTENDER 3 // Extender: OVR_A clock, | ||
681 | // ENC_D direction. | ||
682 | |||
683 | // Enumerated counter clock multipliers. | ||
684 | |||
685 | #define MULT_X0 0x0003 // Supports no multipliers; | ||
686 | // fixed physical multiplier = | ||
687 | // 3. | ||
688 | #define MULT_X1 0x0002 // Supports multiplier x1; | ||
689 | // fixed physical multiplier = | ||
690 | // 2. | ||
691 | #define MULT_X2 0x0001 // Supports multipliers x1, | ||
692 | // x2; physical multipliers = | ||
693 | // 1 or 2. | ||
694 | #define MULT_X4 0x0000 // Supports multipliers x1, | ||
695 | // x2, x4; physical | ||
696 | // multipliers = 0, 1 or 2. | ||
697 | |||
698 | // Sanity-check limits for parameters. | ||
699 | |||
700 | #define NUM_COUNTERS 6 // Maximum valid counter | ||
701 | // logical channel number. | ||
702 | #define NUM_INTSOURCES 4 | ||
703 | #define NUM_LATCHSOURCES 4 | ||
704 | #define NUM_CLKMULTS 4 | ||
705 | #define NUM_CLKSOURCES 4 | ||
706 | #define NUM_CLKPOLS 2 | ||
707 | #define NUM_INDEXPOLS 2 | ||
708 | #define NUM_INDEXSOURCES 2 | ||
709 | #define NUM_LOADTRIGS 4 | ||
710 | |||
711 | // Bit field positions in CRA and CRB counter control registers. | ||
712 | |||
713 | // Bit field positions in CRA: | ||
714 | #define CRABIT_INDXSRC_B 14 // B index source. | ||
715 | #define CRABIT_CLKSRC_B 12 // B clock source. | ||
716 | #define CRABIT_INDXPOL_A 11 // A index polarity. | ||
717 | #define CRABIT_LOADSRC_A 9 // A preload trigger. | ||
718 | #define CRABIT_CLKMULT_A 7 // A clock multiplier. | ||
719 | #define CRABIT_INTSRC_A 5 // A interrupt source. | ||
720 | #define CRABIT_CLKPOL_A 4 // A clock polarity. | ||
721 | #define CRABIT_INDXSRC_A 2 // A index source. | ||
722 | #define CRABIT_CLKSRC_A 0 // A clock source. | ||
723 | |||
724 | // Bit field positions in CRB: | ||
725 | #define CRBBIT_INTRESETCMD 15 // Interrupt reset command. | ||
726 | #define CRBBIT_INTRESET_B 14 // B interrupt reset enable. | ||
727 | #define CRBBIT_INTRESET_A 13 // A interrupt reset enable. | ||
728 | #define CRBBIT_CLKENAB_A 12 // A clock enable. | ||
729 | #define CRBBIT_INTSRC_B 10 // B interrupt source. | ||
730 | #define CRBBIT_LATCHSRC 8 // A/B latch source. | ||
731 | #define CRBBIT_LOADSRC_B 6 // B preload trigger. | ||
732 | #define CRBBIT_CLKMULT_B 3 // B clock multiplier. | ||
733 | #define CRBBIT_CLKENAB_B 2 // B clock enable. | ||
734 | #define CRBBIT_INDXPOL_B 1 // B index polarity. | ||
735 | #define CRBBIT_CLKPOL_B 0 // B clock polarity. | ||
736 | |||
737 | // Bit field masks for CRA and CRB. | ||
738 | |||
739 | #define CRAMSK_INDXSRC_B ( (uint16_t)( 3 << CRABIT_INDXSRC_B) ) | ||
740 | #define CRAMSK_CLKSRC_B ( (uint16_t)( 3 << CRABIT_CLKSRC_B) ) | ||
741 | #define CRAMSK_INDXPOL_A ( (uint16_t)( 1 << CRABIT_INDXPOL_A) ) | ||
742 | #define CRAMSK_LOADSRC_A ( (uint16_t)( 3 << CRABIT_LOADSRC_A) ) | ||
743 | #define CRAMSK_CLKMULT_A ( (uint16_t)( 3 << CRABIT_CLKMULT_A) ) | ||
744 | #define CRAMSK_INTSRC_A ( (uint16_t)( 3 << CRABIT_INTSRC_A) ) | ||
745 | #define CRAMSK_CLKPOL_A ( (uint16_t)( 3 << CRABIT_CLKPOL_A) ) | ||
746 | #define CRAMSK_INDXSRC_A ( (uint16_t)( 3 << CRABIT_INDXSRC_A) ) | ||
747 | #define CRAMSK_CLKSRC_A ( (uint16_t)( 3 << CRABIT_CLKSRC_A) ) | ||
748 | |||
749 | #define CRBMSK_INTRESETCMD ( (uint16_t)( 1 << CRBBIT_INTRESETCMD) ) | ||
750 | #define CRBMSK_INTRESET_B ( (uint16_t)( 1 << CRBBIT_INTRESET_B) ) | ||
751 | #define CRBMSK_INTRESET_A ( (uint16_t)( 1 << CRBBIT_INTRESET_A) ) | ||
752 | #define CRBMSK_CLKENAB_A ( (uint16_t)( 1 << CRBBIT_CLKENAB_A) ) | ||
753 | #define CRBMSK_INTSRC_B ( (uint16_t)( 3 << CRBBIT_INTSRC_B) ) | ||
754 | #define CRBMSK_LATCHSRC ( (uint16_t)( 3 << CRBBIT_LATCHSRC) ) | ||
755 | #define CRBMSK_LOADSRC_B ( (uint16_t)( 3 << CRBBIT_LOADSRC_B) ) | ||
756 | #define CRBMSK_CLKMULT_B ( (uint16_t)( 3 << CRBBIT_CLKMULT_B) ) | ||
757 | #define CRBMSK_CLKENAB_B ( (uint16_t)( 1 << CRBBIT_CLKENAB_B) ) | ||
758 | #define CRBMSK_INDXPOL_B ( (uint16_t)( 1 << CRBBIT_INDXPOL_B) ) | ||
759 | #define CRBMSK_CLKPOL_B ( (uint16_t)( 1 << CRBBIT_CLKPOL_B) ) | ||
760 | |||
761 | #define CRBMSK_INTCTRL ( CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B ) // Interrupt reset control bits. | ||
762 | |||
763 | // Bit field positions for standardized SETUP structure. | ||
764 | |||
765 | #define STDBIT_INTSRC 13 | ||
766 | #define STDBIT_LATCHSRC 11 | ||
767 | #define STDBIT_LOADSRC 9 | ||
768 | #define STDBIT_INDXSRC 7 | ||
769 | #define STDBIT_INDXPOL 6 | ||
770 | #define STDBIT_CLKSRC 4 | ||
771 | #define STDBIT_CLKPOL 3 | ||
772 | #define STDBIT_CLKMULT 1 | ||
773 | #define STDBIT_CLKENAB 0 | ||
774 | |||
775 | // Bit field masks for standardized SETUP structure. | ||
776 | |||
777 | #define STDMSK_INTSRC ( (uint16_t)( 3 << STDBIT_INTSRC ) ) | ||
778 | #define STDMSK_LATCHSRC ( (uint16_t)( 3 << STDBIT_LATCHSRC ) ) | ||
779 | #define STDMSK_LOADSRC ( (uint16_t)( 3 << STDBIT_LOADSRC ) ) | ||
780 | #define STDMSK_INDXSRC ( (uint16_t)( 1 << STDBIT_INDXSRC ) ) | ||
781 | #define STDMSK_INDXPOL ( (uint16_t)( 1 << STDBIT_INDXPOL ) ) | ||
782 | #define STDMSK_CLKSRC ( (uint16_t)( 3 << STDBIT_CLKSRC ) ) | ||
783 | #define STDMSK_CLKPOL ( (uint16_t)( 1 << STDBIT_CLKPOL ) ) | ||
784 | #define STDMSK_CLKMULT ( (uint16_t)( 3 << STDBIT_CLKMULT ) ) | ||
785 | #define STDMSK_CLKENAB ( (uint16_t)( 1 << STDBIT_CLKENAB ) ) | ||
786 | |||
787 | ////////////////////////////////////////////////////////// | ||
788 | |||
789 | /* typedef struct indexCounter */ | ||
790 | /* { */ | ||
791 | /* unsigned int ao; */ | ||
792 | /* unsigned int ai; */ | ||
793 | /* unsigned int digout; */ | ||
794 | /* unsigned int digin; */ | ||
795 | /* unsigned int enc; */ | ||
796 | /* }CallCounter; */ | ||
797 | |||
798 | typedef struct bufferDMA { | ||
799 | dma_addr_t PhysicalBase; | ||
800 | void *LogicalBase; | ||
801 | uint32_t DMAHandle; | ||
802 | } DMABUF; | ||