staging: comedi: remove FSF address from boilerplate text
[deliverable/linux.git] / drivers / staging / comedi / drivers / addi-data / addi_eeprom.c
1 /*
2 * addi_eeprom.c - ADDI EEPROM Module
3 * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module.
4 * Project manager: Eric Stolz
5 *
6 * ADDI-DATA GmbH
7 * Dieselstrasse 3
8 * D-77833 Ottersweier
9 * Tel: +19(0)7223/9493-0
10 * Fax: +49(0)7223/9493-92
11 * http://www.addi-data.com
12 * info@addi-data.com
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 #define NVRAM_USER_DATA_START 0x100
26
27 #define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */
28 #define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */
29 #define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */
30
31 #define EE93C76_CLK_BIT (1 << 0)
32 #define EE93C76_CS_BIT (1 << 1)
33 #define EE93C76_DOUT_BIT (1 << 2)
34 #define EE93C76_DIN_BIT (1 << 3)
35 #define EE93C76_READ_CMD (0x0180 << 4)
36 #define EE93C76_CMD_LEN 13
37
38 #define EEPROM_DIGITALINPUT 0
39 #define EEPROM_DIGITALOUTPUT 1
40 #define EEPROM_ANALOGINPUT 2
41 #define EEPROM_ANALOGOUTPUT 3
42 #define EEPROM_TIMER 4
43 #define EEPROM_WATCHDOG 5
44 #define EEPROM_TIMER_WATCHDOG_COUNTER 10
45
46 static void addi_eeprom_clk_93c76(unsigned long iobase, unsigned int val)
47 {
48 outl(val & ~EE93C76_CLK_BIT, iobase);
49 udelay(100);
50
51 outl(val | EE93C76_CLK_BIT, iobase);
52 udelay(100);
53 }
54
55 static unsigned int addi_eeprom_cmd_93c76(unsigned long iobase,
56 unsigned int cmd,
57 unsigned char len)
58 {
59 unsigned int val = EE93C76_CS_BIT;
60 int i;
61
62 /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
63 outl(val, iobase);
64 udelay(100);
65
66 /* Send EEPROM command - one bit at a time */
67 for (i = (len - 1); i >= 0; i--) {
68 if (cmd & (1 << i))
69 val |= EE93C76_DOUT_BIT;
70 else
71 val &= ~EE93C76_DOUT_BIT;
72
73 /* Write the command */
74 outl(val, iobase);
75 udelay(100);
76
77 addi_eeprom_clk_93c76(iobase, val);
78 }
79 return val;
80 }
81
82 static unsigned short addi_eeprom_readw_93c76(unsigned long iobase,
83 unsigned short addr)
84 {
85 unsigned short val = 0;
86 unsigned int cmd;
87 unsigned int tmp;
88 int i;
89
90 /* Send EEPROM read command and offset to EEPROM */
91 cmd = EE93C76_READ_CMD | (addr / 2);
92 cmd = addi_eeprom_cmd_93c76(iobase, cmd, EE93C76_CMD_LEN);
93
94 /* Get the 16-bit value */
95 for (i = 0; i < 16; i++) {
96 addi_eeprom_clk_93c76(iobase, cmd);
97
98 tmp = inl(iobase);
99 udelay(100);
100
101 val <<= 1;
102 if (tmp & EE93C76_DIN_BIT)
103 val |= 0x1;
104 }
105
106 /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
107 outl(0, iobase);
108 udelay(100);
109
110 return val;
111 }
112
113 static void addi_eeprom_nvram_wait(unsigned long iobase)
114 {
115 unsigned char val;
116
117 do {
118 val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD);
119 } while (val & 0x80);
120 }
121
122 static unsigned short addi_eeprom_readw_nvram(unsigned long iobase,
123 unsigned short addr)
124 {
125 unsigned short val = 0;
126 unsigned char tmp;
127 unsigned char i;
128
129 for (i = 0; i < 2; i++) {
130 /* Load the low 8 bit address */
131 outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD);
132 addi_eeprom_nvram_wait(iobase);
133 outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
134 addi_eeprom_nvram_wait(iobase);
135
136 /* Load the high 8 bit address */
137 outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
138 addi_eeprom_nvram_wait(iobase);
139 outb(((addr + i) >> 8) & 0xff,
140 iobase + AMCC_OP_REG_MCSR_NVDATA);
141 addi_eeprom_nvram_wait(iobase);
142
143 /* Read the eeprom data byte */
144 outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
145 addi_eeprom_nvram_wait(iobase);
146 tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
147 addi_eeprom_nvram_wait(iobase);
148
149 if (i == 0)
150 val |= tmp;
151 else
152 val |= (tmp << 8);
153 }
154
155 return val;
156 }
157
158 static unsigned short addi_eeprom_readw(unsigned long iobase,
159 char *type,
160 unsigned short addr)
161 {
162 unsigned short val = 0;
163
164 /* Add the offset to the start of the user data */
165 addr += NVRAM_USER_DATA_START;
166
167 if (!strcmp(type, "S5920") || !strcmp(type, "S5933"))
168 val = addi_eeprom_readw_nvram(iobase, addr);
169
170 if (!strcmp(type, "93C76"))
171 val = addi_eeprom_readw_93c76(iobase, addr);
172
173 return val;
174 }
175
176 static void addi_eeprom_read_di_info(struct comedi_device *dev,
177 unsigned long iobase,
178 unsigned short addr)
179 {
180 const struct addi_board *this_board = comedi_board(dev);
181 struct addi_private *devpriv = dev->private;
182 char *type = this_board->pc_EepromChip;
183 unsigned short tmp;
184
185 /* Number of channels */
186 tmp = addi_eeprom_readw(iobase, type, addr + 6);
187 devpriv->s_EeParameters.i_NbrDiChannel = tmp;
188
189 /* Interruptible or not */
190 tmp = addi_eeprom_readw(iobase, type, addr + 8);
191 tmp = (tmp >> 7) & 0x01;
192
193 /* How many interruptible logic */
194 tmp = addi_eeprom_readw(iobase, type, addr + 10);
195 }
196
197 static void addi_eeprom_read_do_info(struct comedi_device *dev,
198 unsigned long iobase,
199 unsigned short addr)
200 {
201 const struct addi_board *this_board = comedi_board(dev);
202 struct addi_private *devpriv = dev->private;
203 char *type = this_board->pc_EepromChip;
204 unsigned short tmp;
205
206 /* Number of channels */
207 tmp = addi_eeprom_readw(iobase, type, addr + 6);
208 devpriv->s_EeParameters.i_NbrDoChannel = tmp;
209
210 devpriv->s_EeParameters.i_DoMaxdata = 0xffffffff >> (32 - tmp);
211 }
212
213 static void addi_eeprom_read_timer_info(struct comedi_device *dev,
214 unsigned long iobase,
215 unsigned short addr)
216 {
217 struct addi_private *devpriv = dev->private;
218 #if 0
219 const struct addi_board *this_board = comedi_board(dev);
220 char *type = this_board->pc_EepromChip;
221 unsigned short offset = 0;
222 unsigned short ntimers;
223 unsigned short tmp;
224 int i;
225
226 /* Number of Timers */
227 ntimers = addi_eeprom_readw(iobase, type, addr + 6);
228
229 /* Read header size */
230 for (i = 0; i < ntimers; i++) {
231 unsigned short size;
232 unsigned short res;
233 unsigned short mode;
234 unsigned short min_timing;
235 unsigned short timebase;
236
237 size = addi_eeprom_readw(iobase, type, addr + 8 + offset + 0);
238
239 /* Resolution / Mode */
240 tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 2);
241 res = (tmp >> 10) & 0x3f;
242 mode = (tmp >> 4) & 0x3f;
243
244 /* MinTiming / Timebase */
245 tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 4);
246 min_timing = (tmp >> 6) & 0x3ff;
247 Timebase = tmp & 0x3f;
248
249 offset += size;
250 }
251 #endif
252 /* Timer subdevice present */
253 devpriv->s_EeParameters.i_Timer = 1;
254 }
255
256 static void addi_eeprom_read_ao_info(struct comedi_device *dev,
257 unsigned long iobase,
258 unsigned short addr)
259 {
260 const struct addi_board *this_board = comedi_board(dev);
261 struct addi_private *devpriv = dev->private;
262 char *type = this_board->pc_EepromChip;
263 unsigned short tmp;
264
265 /* No of channels for 1st hard component */
266 tmp = addi_eeprom_readw(iobase, type, addr + 10);
267 devpriv->s_EeParameters.i_NbrAoChannel = (tmp >> 4) & 0x3ff;
268
269 /* Resolution for 1st hard component */
270 tmp = addi_eeprom_readw(iobase, type, addr + 16);
271 tmp = (tmp >> 8) & 0xff;
272 devpriv->s_EeParameters.i_AoMaxdata = 0xfff >> (16 - tmp);
273 }
274
275 static void addi_eeprom_read_ai_info(struct comedi_device *dev,
276 unsigned long iobase,
277 unsigned short addr)
278 {
279 const struct addi_board *this_board = comedi_board(dev);
280 struct addi_private *devpriv = dev->private;
281 char *type = this_board->pc_EepromChip;
282 unsigned short offset;
283 unsigned short tmp;
284
285 /* No of channels for 1st hard component */
286 tmp = addi_eeprom_readw(iobase, type, addr + 10);
287 devpriv->s_EeParameters.i_NbrAiChannel = (tmp >> 4) & 0x3ff;
288 if (!strcmp(this_board->pc_DriverName, "apci3200"))
289 devpriv->s_EeParameters.i_NbrAiChannel *= 4;
290
291 tmp = addi_eeprom_readw(iobase, type, addr + 16);
292 devpriv->s_EeParameters.ui_MinAcquisitiontimeNs = tmp * 1000;
293
294 tmp = addi_eeprom_readw(iobase, type, addr + 30);
295 devpriv->s_EeParameters.ui_MinDelaytimeNs = tmp * 1000;
296
297 tmp = addi_eeprom_readw(iobase, type, addr + 20);
298 devpriv->s_EeParameters.i_Dma = (tmp >> 13) & 0x01;
299
300 tmp = addi_eeprom_readw(iobase, type, addr + 72) & 0xff;
301 if (tmp) { /* > 0 */
302 /* offset of first analog input single header */
303 offset = 74 + (2 * tmp) + (10 * (1 + (tmp / 16)));
304 } else { /* = 0 */
305 offset = 74;
306 }
307
308 /* Resolution */
309 tmp = addi_eeprom_readw(iobase, type, addr + offset + 2) & 0x1f;
310 devpriv->s_EeParameters.i_AiMaxdata = 0xffff >> (16 - tmp);
311 }
312
313 static void addi_eeprom_read_info(struct comedi_device *dev,
314 unsigned long iobase)
315 {
316 const struct addi_board *this_board = comedi_board(dev);
317 char *type = this_board->pc_EepromChip;
318 unsigned short size;
319 unsigned char nfuncs;
320 int i;
321
322 size = addi_eeprom_readw(iobase, type, 8);
323 nfuncs = addi_eeprom_readw(iobase, type, 10) & 0xff;
324
325 /* Read functionality details */
326 for (i = 0; i < nfuncs; i++) {
327 unsigned short offset = i * 4;
328 unsigned short addr;
329 unsigned char func;
330
331 func = addi_eeprom_readw(iobase, type, 12 + offset) & 0x3f;
332 addr = addi_eeprom_readw(iobase, type, 14 + offset);
333
334 switch (func) {
335 case EEPROM_DIGITALINPUT:
336 addi_eeprom_read_di_info(dev, iobase, addr);
337 break;
338
339 case EEPROM_DIGITALOUTPUT:
340 addi_eeprom_read_do_info(dev, iobase, addr);
341 break;
342
343 case EEPROM_ANALOGINPUT:
344 addi_eeprom_read_ai_info(dev, iobase, addr);
345 break;
346
347 case EEPROM_ANALOGOUTPUT:
348 addi_eeprom_read_ao_info(dev, iobase, addr);
349 break;
350
351 case EEPROM_TIMER:
352 case EEPROM_WATCHDOG:
353 case EEPROM_TIMER_WATCHDOG_COUNTER:
354 addi_eeprom_read_timer_info(dev, iobase, addr);
355 break;
356 }
357 }
358 }
This page took 0.107351 seconds and 5 git commands to generate.