📄 i557_eep.c
字号:
//=============================================================================
//
// i557_eep.c - Cyclone Diagnostics
//
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
// Contributors:
// Date: 2001-01-25
// Purpose:
// Description:
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
#include "i557_eep.h"
/*****************************************************************************
*
* Serial EEPROM Access code for the i557/558
*
* Revision History:
* -----------------
*
*
* 05jun98, snc Added setup time for eeprom CS. Changed eeprom_delay to use the
* processor's internal timer. Fixed programming algorithm to poll
* the eeprom's DO line to look for the transition from BUSY to READY
* which indicates that the programming operation has completed.
* 03jun98, snc Added setup time delay on data writes (delay before asserting
* a rising edge on the SK. Fixed eeprom_get_word() to explicitly
* clear a bit position in the buffer after reading a low on the
* data lines.
* 23oct96, snc Ported to the PCI914
*
*/
/*
* Timing information. According to the National Semiconductor manual,
* the SK High Minimum time = SK Low Minimum time = 250 nsec. However,
* the minimum SK cycle time is 1 usec, so a 250 nsec high/750 nsec. low
* sequence or equivalent would be required.
*/
/* Serial clock line */
#define SK_LOW_PERIOD 500 /* nsec, Time serial clock is low */
#define SK_HIGH_PERIOD 500 /* nsec, Time serial clock is high */
/* Serial data line */
#define DATA_IN_HOLD_TIME 20 /* nsec, SK low to EEDI change */
#define DATA_IN_SETUP_TIME 100 /* nsec, EEDI change to SK high */
/* Serial clock and data line states (assumes ports are non-inverting) */
#define HIGH 1
#define LOW 0
/* Select setup time to rising edge of SK */
#define SELECT_SETUP_TIME 50 /* nsec */
/* De-select time between consecutive commands */
#define DESELECT_TIME 100 /* nsec */
/* local functions */
static void set_sda_line (unsigned long pci_base, /* PCI Base address */
int state); /* HIGH or LOW */
static int get_sda_line (unsigned long pci_base); /* PCI Base address */
static void set_scl_line (unsigned long pci_base, /* PCI Base address */
int state); /* HIGH or LOW */
void eeprom_delay (int nsec);
static int eeprom_send_start (unsigned long pci_base, int command);
static int eeprom_send_addr (unsigned long pci_base,
unsigned char eeprom_addr);
static int eeprom_get_word (unsigned long pci_base,
unsigned short *word_addr);
static int eeprom_put_word (unsigned long pci_base,
unsigned short data);
static int eeprom_write_enable(unsigned long pci_base);
static int eeprom_write_disable(unsigned long pci_base);
/* global variables */
int powerup_wait_done = 0; /* set true after power-up wait done */
/*-------------------------------------------------------------
* Function: int eeprom_read ()
*
* Action: Read data from the eeprom, place it at p_data
*
* Returns: OK if read worked, EEPROM_NOT_RESPONDING if
* read fails.
*-------------------------------------------------------------*/
int eeprom_read (unsigned long pci_base,/* PCI Base address */
int eeprom_addr, /* word offset from start of eeprom */
unsigned short *p_data,/* where to put data in memory */
int nwords /* number of 16bit words to read */
)
{
int status; /* result code */
int i; /* loop variable */
/*
* Make sure caller isn't requesting a read beyond the end of the
* eeprom.
*/
if ((eeprom_addr + nwords) > EEPROM_WORD_SIZE)
return (EEPROM_TO_SMALL);
/* Read in desired number of words */
for (i = 0; i < nwords; i++, eeprom_addr++) {
/* Select the serial EEPROM */
SELECT_557_EEP(pci_base);
/* Wait CS setup time */
eeprom_delay (SELECT_SETUP_TIME);
/* Send start/read command to begin the read */
if (((status = eeprom_send_start (pci_base, EEPROM_READ)) != OK) ||
/* Send address */
((status = eeprom_send_addr (pci_base, eeprom_addr)) != OK))
return (status);
if ((status = eeprom_get_word (pci_base, p_data++)) != OK)
return (status);
/* De-Select the serial EEPROM */
DESELECT_557_EEP(pci_base);
/* wait the required de-select time between commands */
eeprom_delay (DESELECT_TIME);
}
return (OK);
}
/*-------------------------------------------------------------
* Function: int eeprom_write ()
*
* Action: Write data from p_data to the eeprom
*
* Returns: OK if write worked, EEPROM_NOT_RESPONDING if
* write failed.
*-------------------------------------------------------------*/
int eeprom_write (unsigned long pci_base,/* PCI Base address */
int eeprom_addr, /* word offset from start of eeprom */
unsigned short *p_data,/* data source in memory */
int nwords /* number of 16bit words to read */
)
{
int status; /* result code */
int i; /* loop variable */
int check_cntr;
unsigned short data;
/*
* Make sure caller isn't requesting a read beyond the end of the
* eeprom.
*/
if ((eeprom_addr + nwords) > EEPROM_WORD_SIZE)
return (EEPROM_TO_SMALL);
/* enable eeprom writes */
if ((status = eeprom_write_enable(pci_base)) != OK)
return(status);
/* Read in desired number of words */
for (i = 0; i < nwords; i++, eeprom_addr++) {
/* Select the serial EEPROM */
SELECT_557_EEP(pci_base);
/* Wait CS setup time */
eeprom_delay (SELECT_SETUP_TIME);
/* Send start/write command to begin the read */
if (((status = eeprom_send_start (pci_base, EEPROM_WRITE)) != OK) ||
/* Send address */
((status = eeprom_send_addr (pci_base, eeprom_addr)) != OK))
return (status);
data = *p_data++;
if ((status = eeprom_put_word (pci_base, data)) != OK)
return (status);
/* De-Select the serial EEPROM */
DESELECT_557_EEP(pci_base);
/* wait the required de-select time between commands */
eeprom_delay (DESELECT_TIME);
/* Re-Select the serial EEPROM */
SELECT_557_EEP(pci_base);
/* now that the write command/data have been clocked into the EEPROM
we must wait for the BUSY indicator (DO driven low) to indicate
READY (DO driven high) */
check_cntr = 0;
while (1) {
check_cntr++;
if (get_sda_line (pci_base) == HIGH) break; /* programming complete */
if (check_cntr > 100000) { /* timeout */
/* De-Select the serial EEPROM */
DESELECT_557_EEP(pci_base);
/* wait the required de-select time between commands */
eeprom_delay (DESELECT_TIME);
return (EEPROM_ERROR);
}
}
/* De-Select the serial EEPROM */
DESELECT_557_EEP(pci_base);
/* wait the required de-select time between commands */
eeprom_delay (DESELECT_TIME);
}
/* disable eeprom writes */
if ((status = eeprom_write_disable(pci_base)) != OK)
return(status);
return (OK);
}
/*-------------------------------------------------------------
* Function: int eeprom_write_enable ()
*
* Action: Enable writes to the eeprom
*
* Returns: OK if command sent, EEPROM_NOT_RESPONDING if not.
*
*-------------------------------------------------------------*/
int eeprom_write_enable (unsigned long pci_base)
{
int status; /* result code */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -