📄 i557_eep.c
字号:
//=============================================================================
//
// i557_eep.c - Cyclone Diagnostics
//
//=============================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//=============================================================================
//#####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 */
/* Select the serial EEPROM */
SELECT_557_EEP(pci_base);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -