OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [xscale/] [iq80310/] [v2_0/] [src/] [diag/] [i557_eep.c] - Blame information for rev 594

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//=============================================================================
2
//
3
//      i557_eep.c - Cyclone Diagnostics
4
//
5
//=============================================================================
6
//####ECOSGPLCOPYRIGHTBEGIN####
7
// -------------------------------------------
8
// This file is part of eCos, the Embedded Configurable Operating System.
9
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
10
//
11
// eCos is free software; you can redistribute it and/or modify it under
12
// the terms of the GNU General Public License as published by the Free
13
// Software Foundation; either version 2 or (at your option) any later version.
14
//
15
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
16
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18
// for more details.
19
//
20
// You should have received a copy of the GNU General Public License along
21
// with eCos; if not, write to the Free Software Foundation, Inc.,
22
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23
//
24
// As a special exception, if other files instantiate templates or use macros
25
// or inline functions from this file, or you compile this file and link it
26
// with other works to produce a work based on this file, this file does not
27
// by itself cause the resulting work to be covered by the GNU General Public
28
// License. However the source code for this file must still be made available
29
// in accordance with section (3) of the GNU General Public License.
30
//
31
// This exception does not invalidate any other reasons why a work based on
32
// this file might be covered by the GNU General Public License.
33
//
34
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
35
// at http://sources.redhat.com/ecos/ecos-license/
36
// -------------------------------------------
37
//####ECOSGPLCOPYRIGHTEND####
38
//=============================================================================
39
//#####DESCRIPTIONBEGIN####
40
//
41
// Author(s):   Scott Coulter, Jeff Frazier, Eric Breeden
42
// Contributors:
43
// Date:        2001-01-25
44
// Purpose:     
45
// Description: 
46
//
47
//####DESCRIPTIONEND####
48
//
49
//===========================================================================*/
50
 
51
#include "i557_eep.h"
52
 
53
/*****************************************************************************
54
*
55
* Serial EEPROM Access code for the i557/558
56
*
57
* Revision History:
58
* -----------------
59
*
60
*
61
* 05jun98, snc Added setup time for eeprom CS.  Changed eeprom_delay to use the
62
*                          processor's internal timer.  Fixed programming algorithm to poll
63
*                          the eeprom's DO line to look for the transition from BUSY to READY
64
*                          which indicates that the programming operation has completed.
65
* 03jun98, snc Added setup time delay on data writes (delay before asserting
66
*                          a rising edge on the SK.  Fixed eeprom_get_word() to explicitly
67
*                          clear a bit position in the buffer after reading a low on the
68
*                          data lines.
69
* 23oct96, snc Ported to the PCI914
70
*
71
*/
72
 
73
/*
74
 * Timing information.  According to the National Semiconductor manual,
75
 * the SK High Minimum time = SK Low Minimum time = 250 nsec.  However,
76
 * the minimum SK cycle time is 1 usec, so a 250 nsec high/750 nsec. low
77
 * sequence or equivalent would be required.
78
 */
79
 
80
/* Serial clock line */
81
#define SK_LOW_PERIOD           500     /* nsec, Time serial clock is low */
82
#define SK_HIGH_PERIOD          500     /* nsec, Time serial clock is high */
83
 
84
/* Serial data line */
85
#define DATA_IN_HOLD_TIME       20      /* nsec, SK low to EEDI change */
86
#define DATA_IN_SETUP_TIME      100     /* nsec, EEDI change to SK high */
87
 
88
/* Serial clock and data line states (assumes ports are non-inverting) */
89
#define HIGH                    1
90
#define LOW                     0
91
 
92
/* Select setup time to rising edge of SK */
93
#define SELECT_SETUP_TIME       50      /* nsec */
94
 
95
/* De-select time between consecutive commands */
96
#define DESELECT_TIME           100     /* nsec */
97
 
98
 
99
/* local functions */
100
 
101
static void set_sda_line (unsigned long pci_base,       /* PCI Base address */
102
                          int state);                   /* HIGH or LOW */
103
 
104
static int get_sda_line (unsigned long pci_base);       /* PCI Base address */
105
 
106
static void set_scl_line (unsigned long pci_base,       /* PCI Base address */
107
                          int state);                   /* HIGH or LOW */
108
 
109
void eeprom_delay (int nsec);
110
static int eeprom_send_start (unsigned long pci_base, int command);
111
static int eeprom_send_addr (unsigned long pci_base,
112
                             unsigned char eeprom_addr);
113
static int eeprom_get_word (unsigned long pci_base,
114
                            unsigned short *word_addr);
115
static int eeprom_put_word (unsigned long pci_base,
116
                            unsigned short data);
117
static int eeprom_write_enable(unsigned long pci_base);
118
static int eeprom_write_disable(unsigned long pci_base);
119
 
120
/* global variables */
121
int powerup_wait_done = 0;               /* set true after power-up wait done */
122
 
123
 
124
/*-------------------------------------------------------------
125
 * Function:    int eeprom_read ()
126
 *
127
 * Action:      Read data from the eeprom, place it at p_data
128
 *
129
 * Returns:     OK if read worked, EEPROM_NOT_RESPONDING if
130
 *              read fails.
131
 *-------------------------------------------------------------*/
132
int eeprom_read (unsigned long pci_base,/* PCI Base address */
133
                 int eeprom_addr,       /* word offset from start of eeprom */
134
                 unsigned short *p_data,/* where to put data in memory */
135
                 int nwords             /* number of 16bit words to read */
136
                 )
137
{
138
    int status;         /* result code */
139
    int i;              /* loop variable */
140
 
141
    /*
142
     * Make sure caller isn't requesting a read beyond the end of the
143
     * eeprom.
144
     */
145
    if ((eeprom_addr + nwords) > EEPROM_WORD_SIZE)
146
        return (EEPROM_TO_SMALL);
147
 
148
 
149
    /* Read in desired number of words */
150
    for (i = 0; i < nwords; i++, eeprom_addr++) {
151
        /* Select the serial EEPROM */
152
        SELECT_557_EEP(pci_base);
153
 
154
        /* Wait CS setup time */
155
        eeprom_delay (SELECT_SETUP_TIME);
156
 
157
        /* Send start/read command to begin the read */
158
        if (((status = eeprom_send_start (pci_base, EEPROM_READ)) != OK) ||
159
        /* Send address */
160
            ((status = eeprom_send_addr (pci_base, eeprom_addr)) != OK))
161
            return (status);
162
 
163
        if ((status = eeprom_get_word (pci_base, p_data++)) != OK)
164
            return (status);
165
 
166
        /* De-Select the serial EEPROM */
167
        DESELECT_557_EEP(pci_base);
168
 
169
        /* wait the required de-select time between commands */
170
        eeprom_delay (DESELECT_TIME);
171
    }
172
 
173
    return (OK);
174
}
175
 
176
/*-------------------------------------------------------------
177
 * Function:    int eeprom_write ()
178
 *
179
 * Action:      Write data from p_data to the eeprom
180
 *
181
 * Returns:     OK if write worked, EEPROM_NOT_RESPONDING if
182
 *              write failed.
183
 *-------------------------------------------------------------*/
184
int eeprom_write (unsigned long pci_base,/* PCI Base address */
185
                 int eeprom_addr,       /* word offset from start of eeprom */
186
                 unsigned short *p_data,/* data source in memory */
187
                 int nwords             /* number of 16bit words to read */
188
                 )
189
{
190
    int status;                 /* result code */
191
    int i;                      /* loop variable */
192
    int check_cntr;
193
    unsigned short data;
194
 
195
    /*
196
     * Make sure caller isn't requesting a read beyond the end of the
197
     * eeprom.
198
     */
199
    if ((eeprom_addr + nwords) > EEPROM_WORD_SIZE)
200
        return (EEPROM_TO_SMALL);
201
 
202
    /* enable eeprom writes */
203
    if ((status = eeprom_write_enable(pci_base)) != OK)
204
        return(status);
205
 
206
    /* Read in desired number of words */
207
    for (i = 0; i < nwords; i++, eeprom_addr++) {
208
        /* Select the serial EEPROM */
209
        SELECT_557_EEP(pci_base);
210
 
211
        /* Wait CS setup time */
212
        eeprom_delay (SELECT_SETUP_TIME);
213
 
214
        /* Send start/write command to begin the read */
215
        if (((status = eeprom_send_start (pci_base, EEPROM_WRITE)) != OK) ||
216
        /* Send address */
217
            ((status = eeprom_send_addr (pci_base, eeprom_addr)) != OK))
218
            return (status);
219
 
220
        data = *p_data++;
221
        if ((status = eeprom_put_word (pci_base, data)) != OK)
222
            return (status);
223
 
224
        /* De-Select the serial EEPROM */
225
        DESELECT_557_EEP(pci_base);
226
 
227
        /* wait the required de-select time between commands */
228
        eeprom_delay (DESELECT_TIME);
229
 
230
        /* Re-Select the serial EEPROM */
231
        SELECT_557_EEP(pci_base);
232
 
233
        /* now that the write command/data have been clocked into the EEPROM
234
           we must wait for the BUSY indicator (DO driven low) to indicate
235
           READY (DO driven high) */
236
        check_cntr = 0;
237
 
238
        while (1) {
239
            check_cntr++;
240
 
241
            if (get_sda_line (pci_base) == HIGH) break;         /* programming complete */
242
 
243
            if (check_cntr > 100000) {                                          /* timeout */
244
                /* De-Select the serial EEPROM */
245
                DESELECT_557_EEP(pci_base);
246
                /* wait the required de-select time between commands */
247
                eeprom_delay (DESELECT_TIME);
248
                return (EEPROM_ERROR);
249
            }
250
        }
251
 
252
        /* De-Select the serial EEPROM */
253
        DESELECT_557_EEP(pci_base);
254
 
255
        /* wait the required de-select time between commands */
256
        eeprom_delay (DESELECT_TIME);
257
    }
258
 
259
    /* disable eeprom writes */
260
    if ((status = eeprom_write_disable(pci_base)) != OK)
261
        return(status);
262
 
263
    return (OK);
264
}
265
 
266
/*-------------------------------------------------------------
267
 * Function:    int eeprom_write_enable ()
268
 *
269
 * Action:      Enable writes to the eeprom
270
 *
271
 * Returns:     OK if command sent, EEPROM_NOT_RESPONDING if not.
272
 *
273
 *-------------------------------------------------------------*/
274
int eeprom_write_enable (unsigned long pci_base)
275
{
276
    int status;                         /* result code */
277
 
278
    /* Select the serial EEPROM */
279
    SELECT_557_EEP(pci_base);
280
 
281
    /* Wait CS setup time */
282
    eeprom_delay (SELECT_SETUP_TIME);
283
 
284
    /* Send start/write enable command */
285
    if (((status = eeprom_send_start (pci_base, EEPROM_EWEN)) != OK) ||
286
        /* Send address */
287
        ((status = eeprom_send_addr (pci_base, EEPROM_EWEN_OP)) != OK))
288
        return (status);
289
 
290
    /* De-Select the serial EEPROM */
291
    DESELECT_557_EEP(pci_base);
292
 
293
    /* wait the required de-select time between commands */
294
    eeprom_delay (DESELECT_TIME);
295
 
296
    return (OK);
297
}
298
 
299
/*-------------------------------------------------------------
300
 * Function:    int eeprom_write_disable ()
301
 *
302
 * Action:      Disable writes to the eeprom
303
 *
304
 * Returns:     OK if command sent, EEPROM_NOT_RESPONDING if not.
305
 *
306
 *-------------------------------------------------------------*/
307
int eeprom_write_disable (unsigned long pci_base)
308
{
309
    int status;                         /* result code */
310
 
311
    /* Select the serial EEPROM */
312
    SELECT_557_EEP(pci_base);
313
 
314
    /* Wait CS setup time */
315
    eeprom_delay (SELECT_SETUP_TIME);
316
 
317
    /* Send start/write enable command */
318
    if (((status = eeprom_send_start (pci_base, EEPROM_EWDS)) != OK) ||
319
        /* Send address */
320
         ((status = eeprom_send_addr (pci_base, EEPROM_EWDS_OP)) != OK))
321
        return (status);
322
 
323
    /* De-Select the serial EEPROM */
324
    DESELECT_557_EEP(pci_base);
325
 
326
    /* wait the required de-select time between commands */
327
    eeprom_delay (DESELECT_TIME);
328
 
329
    return (OK);
330
}
331
 
332
 
333
/******************************************************************************
334
*
335
* eeprom_delay - delay for a specified number of nanoseconds
336
*
337
* Note: this routine is a generous approximation as delays for eeproms
338
*       are specified as minimums.
339
*/
340
void eeprom_delay (int nsec)
341
{
342
    extern void polled_delay (int usec);
343
 
344
    /* generously delay 1 usec. for each nsec. */
345
    polled_delay (nsec);
346
}
347
 
348
/******************************************************************************
349
*
350
* eeprom_send_start - send a start bit with a read opcode to the '557 serial
351
*                     eeprom
352
*
353
*/
354
static int eeprom_send_start (unsigned long pci_base, int command)
355
{
356
    int op_code[2];
357
 
358
    switch (command) {
359
    case EEPROM_WRITE:
360
        op_code[0] = LOW;
361
        op_code[1] = HIGH;
362
        break;
363
 
364
    case EEPROM_READ:
365
        op_code[0] = HIGH;
366
        op_code[1] = LOW;
367
        break;
368
 
369
    case EEPROM_ERASE:
370
        op_code[0] = HIGH;
371
        op_code[1] = HIGH;
372
        break;
373
 
374
    case EEPROM_EWEN:
375
    case EEPROM_EWDS:
376
        op_code[0] = LOW;
377
        op_code[1] = LOW;
378
        break;
379
 
380
    default:
381
        return(EEPROM_INVALID_CMD);
382
    }
383
 
384
    set_scl_line (pci_base, LOW);
385
    set_sda_line (pci_base, HIGH);      /* start bit */
386
    eeprom_delay (DATA_IN_SETUP_TIME);
387
    set_scl_line (pci_base, HIGH);      /* clock high */
388
    eeprom_delay (SK_HIGH_PERIOD);
389
    set_scl_line (pci_base, LOW);       /* clock low */
390
    eeprom_delay (SK_LOW_PERIOD);
391
 
392
    /* send the opcode */
393
    set_sda_line (pci_base, op_code[0]); /* MSB of opcode */
394
    eeprom_delay (DATA_IN_SETUP_TIME);
395
    set_scl_line (pci_base, HIGH);      /* clock high */
396
    eeprom_delay (SK_HIGH_PERIOD);
397
    set_scl_line (pci_base, LOW);       /* clock low */
398
    eeprom_delay (SK_LOW_PERIOD);
399
    set_sda_line (pci_base, op_code[1]);        /* LSB of opcode */
400
    eeprom_delay (DATA_IN_SETUP_TIME);
401
    set_scl_line (pci_base, HIGH);      /* clock high */
402
    eeprom_delay (SK_HIGH_PERIOD);
403
    set_scl_line (pci_base, LOW);       /* clock low */
404
    eeprom_delay (SK_LOW_PERIOD);
405
 
406
    return (OK);
407
}
408
 
409
/******************************************************************************
410
*
411
* eeprom_send_addr - send the read address to the '557 serial eeprom
412
*
413
*/
414
static int eeprom_send_addr (unsigned long pci_base,
415
                             unsigned char eeprom_addr)
416
{
417
    register int i;
418
 
419
    /* Do each address bit, MSB => LSB - after each address bit is
420
       sent, read the EEDO bit on the '557 to check for the "dummy 0 bit"
421
       which when set to 0, indicates that the address field is complete */
422
    for (i = 5; i >= 0; i--) {
423
        /* If this bit is a 1, set SDA high.  If 0, set it low */
424
        if (eeprom_addr & (1 << i))
425
            set_sda_line (pci_base, HIGH);
426
        else
427
            set_sda_line (pci_base, LOW);
428
 
429
        eeprom_delay (DATA_IN_SETUP_TIME); /* Data setup before raising clock */
430
        set_scl_line (pci_base, HIGH);     /* Clock in this data bit */
431
        eeprom_delay (SK_HIGH_PERIOD);
432
        set_scl_line (pci_base, LOW);      /* Prepare for next bit */
433
        eeprom_delay (SK_LOW_PERIOD);
434
 
435
        /* check to see if "dummy 0 bit" is set to 0 indicating address
436
           complete */
437
        if (get_sda_line (pci_base) == LOW)
438
            break;                         /* address complete */
439
    }
440
    return (OK);
441
}
442
 
443
/******************************************************************************
444
*
445
* eeprom_get_word - read a 16 bit word from the '557 serial eeprom
446
*
447
* Note: this routine assumes that the start/opcode/address have already
448
*       been set up
449
*/
450
static int eeprom_get_word (unsigned long pci_base,
451
                            unsigned short *word_addr)
452
{
453
    register int i;
454
 
455
    /* Do each data bit, MSB => LSB */
456
    for (i = 15; i >= 0; i--) {
457
        set_scl_line (pci_base, HIGH);
458
        eeprom_delay (SK_HIGH_PERIOD);
459
 
460
        if (get_sda_line (pci_base) == HIGH)
461
            *word_addr |=  (1 << i);                    /* store bit as a '1' */
462
        else
463
            *word_addr &= ~(1 << i);                    /* store bit as a '0' */
464
 
465
        set_scl_line (pci_base, LOW);
466
        eeprom_delay (SK_LOW_PERIOD);
467
    }
468
    return (OK);
469
}
470
 
471
/******************************************************************************
472
*
473
* eeprom_put_word - write a 16 bit word to the '557 serial eeprom
474
*
475
* Note: this routine assumes that the start/opcode/address have already
476
*       been set up
477
*/
478
static int eeprom_put_word (unsigned long pci_base,
479
                            unsigned short data)
480
{
481
    register int i;
482
 
483
    /* Do each data bit, MSB => LSB */
484
    for (i = 15; i >= 0; i--) {
485
        if (data & (1 << i))
486
            set_sda_line(pci_base, HIGH);
487
        else
488
            set_sda_line(pci_base, LOW);
489
 
490
        eeprom_delay (DATA_IN_SETUP_TIME);
491
        set_scl_line (pci_base, HIGH);
492
        eeprom_delay (SK_HIGH_PERIOD);
493
        set_scl_line (pci_base, LOW);
494
        eeprom_delay (SK_LOW_PERIOD);
495
    }
496
    return (OK);
497
}
498
 
499
/*-------------------------------------------------------------
500
 * Function:    void set_scl_line ()
501
 *
502
 * Action:      Sets the value of the eeprom's serial clock line
503
 *              to the value HIGH or LOW.
504
 *
505
 * Returns:     N/A.
506
 *-------------------------------------------------------------*/
507
static void set_scl_line (unsigned long pci_base, /* PCI address */
508
                          int state)              /* HIGH or LOW */
509
{
510
    if (state == HIGH)
511
        SK_HIGH_557_EEP (pci_base);
512
    else if (state == LOW)
513
        SK_LOW_557_EEP (pci_base);
514
}
515
 
516
/*-------------------------------------------------------------
517
 * Function:    void set_sda_line ()
518
 *
519
 * Action:      Sets the value of the eeprom's serial data line
520
 *              to the value HIGH or LOW.
521
 *
522
 * Returns:     N/A.
523
 *-------------------------------------------------------------*/
524
static void set_sda_line (unsigned long pci_base, /* PCI address */
525
                          int state)              /* HIGH or LOW */
526
{
527
    if (state == HIGH)
528
        EEDI_HIGH_557_EEP (pci_base);
529
    else if (state == LOW)
530
        EEDI_LOW_557_EEP (pci_base);
531
}
532
 
533
/*-------------------------------------------------------------
534
 * Function:    int get_sda_line ()
535
 *
536
 * Action:      Returns the value of the eeprom's serial data line
537
 *
538
 * Returns:     HIGH or LOW.
539
 *-------------------------------------------------------------*/
540
static int get_sda_line (unsigned long pci_base) /* PCI address */
541
{
542
    int ret_val;                                /* result code */
543
 
544
    if (EEDO_557_EEP (pci_base))
545
        ret_val = HIGH;
546
    else
547
        ret_val = LOW;
548
 
549
    return (ret_val);
550
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.