02c829b318b439e03b514c6d6e44276479ee1151
[safe/jmp/linux-2.6] / drivers / staging / cxt1e1 / pmc93x6_eeprom.c
1 /* pmc93x6_eeprom.c - PMC's 93LC46 EEPROM Device
2  *
3  *    The 93LC46 is a low-power, serial Electrically Erasable and
4  *    Programmable Read Only Memory organized as 128 8-bit bytes.
5  *
6  *    Accesses to the 93LC46 are done in a bit serial stream, organized
7  *    in a 3 wire format.  Writes are internally timed by the device
8  *    (the In data bit is pulled low until the write is complete and
9  *    then is pulled high) and take about 6 milliseconds.
10  *
11  * Copyright (C) 2003-2005  SBE, Inc.
12  *
13  *   This program is free software; you can redistribute it and/or modify
14  *   it under the terms of the GNU General Public License as published by
15  *   the Free Software Foundation; either version 2 of the License, or
16  *   (at your option) any later version.
17  *
18  *   This program is distributed in the hope that it will be useful,
19  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *   GNU General Public License for more details.
22  */
23
24 #include <linux/types.h>
25 #include "pmcc4_sysdep.h"
26 #include "sbecom_inline_linux.h"
27 #include "pmcc4.h"
28 #include "sbe_promformat.h"
29
30 #ifndef TRUE
31 #define TRUE   1
32 #define FALSE  0
33 #endif
34
35 #ifdef SBE_INCLUDE_SYMBOLS
36 #define STATIC
37 #else
38 #define STATIC  static
39 #endif
40
41
42 /*------------------------------------------------------------------------
43  *      EEPROM address definitions
44  *------------------------------------------------------------------------
45  *
46  *      The offset in the definitions below allows the test to skip over
47  *      areas of the EEPROM that other programs (such a VxWorks) are
48  *      using.
49  */
50
51 #define EE_MFG      (long)0     /* Index to manufacturing record */
52 #define EE_FIRST    0x28        /* Index to start testing at */
53 #define EE_LIMIT    128         /* Index to end testing at */
54
55
56 /*  Bit Ordering for Instructions
57 **
58 **  A0, A1, A2, A3, A4, A5, A6, OP0, OP1, SB   (lsb, or 1st bit out)
59 **
60 */
61
62 #define EPROM_EWEN      0x0019  /* Erase/Write enable (reversed) */
63 #define EPROM_EWDS      0x0001  /* Erase/Write disable (reversed) */
64 #define EPROM_READ      0x0003  /* Read (reversed) */
65 #define EPROM_WRITE     0x0005  /* Write (reversed) */
66 #define EPROM_ERASE     0x0007  /* Erase (reversed) */
67 #define EPROM_ERAL      0x0009  /* Erase All (reversed) */
68 #define EPROM_WRAL      0x0011  /* Write All (reversed) */
69
70 #define EPROM_ADR_SZ    7       /* Number of bits in offset address */
71 #define EPROM_OP_SZ     3       /* Number of bits in command */
72 #define SIZE_ADDR_OP    (EPROM_ADR_SZ + EPROM_OP_SZ)
73 #define LC46A_MAX_OPS   10      /* Number of bits in Instruction */
74 #define NUM_OF_BITS     8       /* Number of bits in data */
75
76
77 /* EEPROM signal bits */
78 #define EPROM_ACTIVE_OUT_BIT    0x0001  /* Out data bit */
79 #define EPROM_ACTIVE_IN_BIT     0x0002  /* In data bit */
80 #define ACTIVE_IN_BIT_SHIFT     0x0001  /* Shift In data bit to LSB */
81 #define EPROM_ENCS              0x0004  /* Set EEPROM CS during operation */
82
83
84 /*------------------------------------------------------------------------
85  *      The ByteReverse table is used to reverses the 8 bits within a byte
86  *------------------------------------------------------------------------
87  */
88
89 static unsigned char ByteReverse[256];
90 static int  ByteReverseBuilt = FALSE;
91
92
93 /*------------------------------------------------------------------------
94  *      mfg_template - initial serial EEPROM data structure
95  *------------------------------------------------------------------------
96  */
97
98 short       mfg_template[sizeof (FLD_TYPE2)] =
99 {
100     PROM_FORMAT_TYPE2,          /* type; */
101     0x00, 0x1A,                 /* length[2]; */
102     0x00, 0x00, 0x00, 0x00,     /* Crc32[4]; */
103     0x11, 0x76,                 /* Id[2]; */
104     0x07, 0x05,                 /* SubId[2] E1; */
105     0x00, 0xA0, 0xD6, 0x00, 0x00, 0x00, /* Serial[6]; */
106     0x00, 0x00, 0x00, 0x00,     /* CreateTime[4]; */
107     0x00, 0x00, 0x00, 0x00,     /* HeatRunTime[4]; */
108     0x00, 0x00, 0x00, 0x00,     /* HeatRunIterations[4]; */
109     0x00, 0x00, 0x00, 0x00,     /* HeatRunErrors[4]; */
110 };
111
112
113 /*------------------------------------------------------------------------
114  *      BuildByteReverse - build the 8-bit reverse table
115  *------------------------------------------------------------------------
116  *
117  *      The 'ByteReverse' table reverses the 8 bits within a byte
118  *      (the MSB becomes the LSB etc.).
119  */
120
121 STATIC void
122 BuildByteReverse (void)
123 {
124     long        half;           /* Used to build by powers to 2 */
125     int         i;
126
127     ByteReverse[0] = 0;
128
129     for (half = 1; half < sizeof (ByteReverse); half <<= 1)
130         for (i = 0; i < half; i++)
131             ByteReverse[half + i] = (char) (ByteReverse[i] | (0x80 / half));
132
133     ByteReverseBuilt = TRUE;
134 }
135
136
137 /*------------------------------------------------------------------------
138  *      eeprom_delay - small delay for EEPROM timing
139  *------------------------------------------------------------------------
140  */
141
142 STATIC void
143 eeprom_delay (void)
144 {
145     int         timeout;
146
147     for (timeout = 20; timeout; --timeout)
148     {
149         OS_uwait_dummy ();
150     }
151 }
152
153
154 /*------------------------------------------------------------------------
155  *      eeprom_put_byte - Send a byte to the EEPROM serially
156  *------------------------------------------------------------------------
157  *
158  *      Given the PCI address and the data, this routine serially sends
159  *      the data to the EEPROM.
160  */
161
162 void
163 eeprom_put_byte (long addr, long data, int count)
164 {
165     u_int32_t output;
166
167     while (--count >= 0)
168     {
169         output = (data & EPROM_ACTIVE_OUT_BIT) ? 1 : 0; /* Get next data bit */
170         output |= EPROM_ENCS;       /* Add Chip Select */
171         data >>= 1;
172
173         eeprom_delay ();
174         pci_write_32 ((u_int32_t *) addr, output);      /* Output it */
175     }
176 }
177
178
179 /*------------------------------------------------------------------------
180  *      eeprom_get_byte - Receive a byte from the EEPROM serially
181  *------------------------------------------------------------------------
182  *
183  *      Given the PCI address, this routine serially fetches the data
184  *      from the  EEPROM.
185  */
186
187 u_int32_t
188 eeprom_get_byte (long addr)
189 {
190     u_int32_t   input;
191     u_int32_t   data;
192     int         count;
193
194 /*  Start the Reading of DATA
195 **
196 **  The first read is a dummy as the data is latched in the
197 **  EPLD and read on the next read access to the EEPROM.
198 */
199
200     input = pci_read_32 ((u_int32_t *) addr);
201
202     data = 0;
203     count = NUM_OF_BITS;
204     while (--count >= 0)
205     {
206         eeprom_delay ();
207         input = pci_read_32 ((u_int32_t *) addr);
208
209         data <<= 1;                 /* Shift data over */
210         data |= (input & EPROM_ACTIVE_IN_BIT) ? 1 : 0;
211
212     }
213
214     return data;
215 }
216
217
218 /*------------------------------------------------------------------------
219  *      disable_pmc_eeprom - Disable writes to the EEPROM
220  *------------------------------------------------------------------------
221  *
222  *      Issue the EEPROM command to disable writes.
223  */
224
225 STATIC void
226 disable_pmc_eeprom (long addr)
227 {
228     eeprom_put_byte (addr, EPROM_EWDS, SIZE_ADDR_OP);
229
230     pci_write_32 ((u_int32_t *) addr, 0);       /* this removes Chip Select
231                                                  * from EEPROM */
232 }
233
234
235 /*------------------------------------------------------------------------
236  *      enable_pmc_eeprom - Enable writes to the EEPROM
237  *------------------------------------------------------------------------
238  *
239  *      Issue the EEPROM command to enable writes.
240  */
241
242 STATIC void
243 enable_pmc_eeprom (long addr)
244 {
245     eeprom_put_byte (addr, EPROM_EWEN, SIZE_ADDR_OP);
246
247     pci_write_32 ((u_int32_t *) addr, 0);       /* this removes Chip Select
248                                                  * from EEPROM */
249 }
250
251
252 /*------------------------------------------------------------------------
253  *      pmc_eeprom_read - EEPROM location read
254  *------------------------------------------------------------------------
255  *
256  *      Given a EEPROM PCI address and location offset, this routine returns
257  *      the contents of the specified location to the calling routine.
258  */
259
260 u_int32_t
261 pmc_eeprom_read (long addr, long mem_offset)
262 {
263     u_int32_t   data;           /* Data from chip */
264
265     if (!ByteReverseBuilt)
266         BuildByteReverse ();
267
268     mem_offset = ByteReverse[0x7F & mem_offset];        /* Reverse address */
269     /*
270      * NOTE: The max offset address is 128 or half the reversal table. So the
271      * LSB is always zero and counts as a built in shift of one bit.  So even
272      * though we need to shift 3 bits to make room for the command, we only
273      * need to shift twice more because of the built in shift.
274      */
275     mem_offset <<= 2;               /* Shift for command */
276     mem_offset |= EPROM_READ;       /* Add command */
277
278     eeprom_put_byte (addr, mem_offset, SIZE_ADDR_OP);   /* Output chip address */
279
280     data = eeprom_get_byte (addr);  /* Read chip data */
281
282     pci_write_32 ((u_int32_t *) addr, 0);       /* Remove Chip Select from
283                                                  * EEPROM */
284
285     return (data & 0x000000FF);
286 }
287
288
289 /*------------------------------------------------------------------------
290  *      pmc_eeprom_write - EEPROM location write
291  *------------------------------------------------------------------------
292  *
293  *      Given a EEPROM PCI address, location offset and value, this
294  *      routine writes the value to the specified location.
295  *
296  *      Note: it is up to the caller to determine if the write
297  *      operation succeeded.
298  */
299
300 int
301 pmc_eeprom_write (long addr, long mem_offset, u_int32_t data)
302 {
303     volatile u_int32_t temp;
304     int         count;
305
306     if (!ByteReverseBuilt)
307         BuildByteReverse ();
308
309     mem_offset = ByteReverse[0x7F & mem_offset];        /* Reverse address */
310     /*
311      * NOTE: The max offset address is 128 or half the reversal table. So the
312      * LSB is always zero and counts as a built in shift of one bit.  So even
313      * though we need to shift 3 bits to make room for the command, we only
314      * need to shift twice more because of the built in shift.
315      */
316     mem_offset <<= 2;               /* Shift for command */
317     mem_offset |= EPROM_WRITE;      /* Add command */
318
319     eeprom_put_byte (addr, mem_offset, SIZE_ADDR_OP);   /* Output chip address */
320
321     data = ByteReverse[0xFF & data];/* Reverse data */
322     eeprom_put_byte (addr, data, NUM_OF_BITS);  /* Output chip data */
323
324     pci_write_32 ((u_int32_t *) addr, 0);       /* Remove Chip Select from
325                                                  * EEPROM */
326
327 /*
328 **  Must see Data In at a low state before completing this transaction.
329 **
330 **  Afterwards, the data bit will return to a high state, ~6 ms, terminating
331 **  the operation.
332 */
333     pci_write_32 ((u_int32_t *) addr, EPROM_ENCS);      /* Re-enable Chip Select */
334     temp = pci_read_32 ((u_int32_t *) addr);    /* discard first read */
335     temp = pci_read_32 ((u_int32_t *) addr);
336     if (temp & EPROM_ACTIVE_IN_BIT)
337     {
338         temp = pci_read_32 ((u_int32_t *) addr);
339         if (temp & EPROM_ACTIVE_IN_BIT)
340         {
341             pci_write_32 ((u_int32_t *) addr, 0);       /* Remove Chip Select
342                                                          * from EEPROM */
343             return (1);
344         }
345     }
346     count = 1000;
347     while (count--)
348     {
349         for (temp = 0; temp < 0x10; temp++)
350             OS_uwait_dummy ();
351
352         if (pci_read_32 ((u_int32_t *) addr) & EPROM_ACTIVE_IN_BIT)
353             break;
354     }
355
356     if (count == -1)
357         return (2);
358
359     return (0);
360 }
361
362
363 /*------------------------------------------------------------------------
364  *      pmcGetBuffValue - read the specified value from buffer
365  *------------------------------------------------------------------------
366  */
367
368 long
369 pmcGetBuffValue (char *ptr, int size)
370 {
371     long        value = 0;
372     int         index;
373
374     for (index = 0; index < size; ++index)
375     {
376         value <<= 8;
377         value |= ptr[index] & 0xFF;
378     }
379
380     return value;
381 }
382
383
384 /*------------------------------------------------------------------------
385  *      pmcSetBuffValue - save the specified value to buffer
386  *------------------------------------------------------------------------
387  */
388
389 void
390 pmcSetBuffValue (char *ptr, long value, int size)
391 {
392     int         index = size;
393
394     while (--index >= 0)
395     {
396         ptr[index] = (char) (value & 0xFF);
397         value >>= 8;
398     }
399 }
400
401
402 /*------------------------------------------------------------------------
403  *      pmc_eeprom_read_buffer - read EEPROM data into specified buffer
404  *------------------------------------------------------------------------
405  */
406
407 void
408 pmc_eeprom_read_buffer (long addr, long mem_offset, char *dest_ptr, int size)
409 {
410     while (--size >= 0)
411         *dest_ptr++ = (char) pmc_eeprom_read (addr, mem_offset++);
412 }
413
414
415 /*------------------------------------------------------------------------
416  *      pmc_eeprom_write_buffer - write EEPROM data from specified buffer
417  *------------------------------------------------------------------------
418  */
419
420 void
421 pmc_eeprom_write_buffer (long addr, long mem_offset, char *dest_ptr, int size)
422 {
423     enable_pmc_eeprom (addr);
424
425     while (--size >= 0)
426         pmc_eeprom_write (addr, mem_offset++, *dest_ptr++);
427
428     disable_pmc_eeprom (addr);
429 }
430
431
432 /*------------------------------------------------------------------------
433  *      pmcCalcCrc - calculate the CRC for the serial EEPROM structure
434  *------------------------------------------------------------------------
435  */
436
437 u_int32_t
438 pmcCalcCrc_T01 (void *bufp)
439 {
440     FLD_TYPE2  *buf = bufp;
441     u_int32_t   crc;            /* CRC of the structure */
442
443     /* Calc CRC for type and length fields */
444     sbeCrc (
445             (u_int8_t *) &buf->type,
446             (u_int32_t) STRUCT_OFFSET (FLD_TYPE1, Crc32),
447             (u_int32_t) 0,
448             (u_int32_t *) &crc);
449
450 #ifdef EEPROM_TYPE_DEBUG
451     printk ("sbeCrc: crc 1 calculated as %08x\n", crc); /* RLD DEBUG */
452 #endif
453     return ~crc;
454 }
455
456 u_int32_t
457 pmcCalcCrc_T02 (void *bufp)
458 {
459     FLD_TYPE2  *buf = bufp;
460     u_int32_t   crc;            /* CRC of the structure */
461
462     /* Calc CRC for type and length fields */
463     sbeCrc (
464             (u_int8_t *) &buf->type,
465             (u_int32_t) STRUCT_OFFSET (FLD_TYPE2, Crc32),
466             (u_int32_t) 0,
467             (u_int32_t *) &crc);
468
469     /* Calc CRC for remaining fields */
470     sbeCrc (
471             (u_int8_t *) &buf->Id[0],
472             (u_int32_t) (sizeof (FLD_TYPE2) - STRUCT_OFFSET (FLD_TYPE2, Id)),
473             (u_int32_t) crc,
474             (u_int32_t *) &crc);
475
476 #ifdef EEPROM_TYPE_DEBUG
477     printk ("sbeCrc: crc 2 calculated as %08x\n", crc); /* RLD DEBUG */
478 #endif
479     return crc;
480 }
481
482
483 /*------------------------------------------------------------------------
484  *      pmc_init_seeprom - initialize the serial EEPROM structure
485  *------------------------------------------------------------------------
486  *
487  *      At the front of the serial EEPROM there is a record that contains
488  *      manufacturing information.  If the info does not already exist, it
489  *      is created.  The only field modifiable by the operator is the
490  *      serial number field.
491  */
492
493 void
494 pmc_init_seeprom (u_int32_t addr, u_int32_t serialNum)
495 {
496     PROMFORMAT  buffer;         /* Memory image of structure */
497     u_int32_t   crc;            /* CRC of structure */
498     time_t      createTime;
499     int         i;
500
501 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
502     createTime = CURRENT_TIME;
503 #else
504     createTime = get_seconds ();
505 #endif
506
507     /* use template data */
508     for (i = 0; i < sizeof (FLD_TYPE2); ++i)
509         buffer.bytes[i] = mfg_template[i];
510
511     /* Update serial number field in buffer */
512     pmcSetBuffValue (&buffer.fldType2.Serial[3], serialNum, 3);
513
514     /* Update create time field in buffer */
515     pmcSetBuffValue (&buffer.fldType2.CreateTime[0], createTime, 4);
516
517     /* Update CRC field in buffer */
518     crc = pmcCalcCrc_T02 (&buffer);
519     pmcSetBuffValue (&buffer.fldType2.Crc32[0], crc, 4);
520
521 #ifdef DEBUG
522     for (i = 0; i < sizeof (FLD_TYPE2); ++i)
523         printk ("[%02X] = %02X\n", i, buffer.bytes[i] & 0xFF);
524 #endif
525
526     /* Write structure to serial EEPROM */
527     pmc_eeprom_write_buffer (addr, EE_MFG, (char *) &buffer, sizeof (FLD_TYPE2));
528 }
529
530
531 char
532 pmc_verify_cksum (void *bufp)
533 {
534     FLD_TYPE1  *buf1 = bufp;
535     FLD_TYPE2  *buf2 = bufp;
536     u_int32_t   crc1, crc2;     /* CRC read from EEPROM */
537
538     /* Retrieve contents of CRC field */
539     crc1 = pmcGetBuffValue (&buf1->Crc32[0], sizeof (buf1->Crc32));
540 #ifdef EEPROM_TYPE_DEBUG
541     printk ("EEPROM: chksum 1 reads   as %08x\n", crc1);        /* RLD DEBUG */
542 #endif
543     if ((buf1->type == PROM_FORMAT_TYPE1) &&
544         (pmcCalcCrc_T01 ((void *) buf1) == crc1))
545         return PROM_FORMAT_TYPE1;   /* checksum type 1 verified */
546
547     crc2 = pmcGetBuffValue (&buf2->Crc32[0], sizeof (buf2->Crc32));
548 #ifdef EEPROM_TYPE_DEBUG
549     printk ("EEPROM: chksum 2 reads   as %08x\n", crc2);        /* RLD DEBUG */
550 #endif
551     if ((buf2->type == PROM_FORMAT_TYPE2) &&
552         (pmcCalcCrc_T02 ((void *) buf2) == crc2))
553         return PROM_FORMAT_TYPE2;   /* checksum type 2 verified */
554
555     return PROM_FORMAT_Unk;         /* failed to validate */
556 }
557
558
559 /*** End-of-File ***/