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