⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i557_eep.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
//=============================================================================
//
//      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 + -