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

📄 epcs.c

📁 Universal Bootloader which support OMAP2420.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (C) Copyright 2004, Psyent Corporation <www.psyent.com> * Scott McNutt <smcnutt@psyent.com> * * See file CREDITS for list of people who contributed to this * project. * * This program 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 of * the License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#if defined(CFG_NIOS_EPCSBASE)#include <command.h>#include <nios2.h>#include <nios2-io.h>#include <nios2-epcs.h>/*-----------------------------------------------------------------------*/#define SHORT_HELP\	"epcs    - read/write Cyclone EPCS configuration device.\n"#define LONG_HELP\	"\n"\	"epcs erase start [end]\n"\	"    - erase sector start or sectors start through end.\n"\	"epcs info\n"\	"    - display EPCS device information.\n"\	"epcs protect on | off\n"\	"    - turn device protection on or off.\n"\	"epcs read addr offset count\n"\	"    - read count bytes from offset to addr.\n"\	"epcs write addr offset count\n"\	"    - write count bytes to offset from addr.\n"\	"epcs verify addr offset count\n"\	"    - verify count bytes at offset from addr.\n"/*-----------------------------------------------------------------------*//* Operation codes for serial configuration devices */#define EPCS_WRITE_ENA		0x06	/* Write enable */#define EPCS_WRITE_DIS		0x04	/* Write disable */#define EPCS_READ_STAT		0x05	/* Read status */#define EPCS_READ_BYTES		0x03	/* Read bytes */#define EPCS_READ_ID		0xab	/* Read silicon id */#define EPCS_WRITE_STAT		0x01	/* Write status */#define EPCS_WRITE_BYTES	0x02	/* Write bytes */#define EPCS_ERASE_BULK		0xc7	/* Erase entire device */#define EPCS_ERASE_SECT		0xd8	/* Erase sector *//* Device status register bits */#define EPCS_STATUS_WIP		(1<<0)	/* Write in progress */#define EPCS_STATUS_WEL		(1<<1)	/* Write enable latch *//* Misc */#define EPCS_TIMEOUT		100	/* 100 msec timeout */static nios_spi_t *epcs =	(nios_spi_t *)CACHE_BYPASS(CFG_NIOS_EPCSBASE);/*********************************************************************** * Device access ***********************************************************************/static int epcs_cs (int assert){	ulong start;	if (assert) {		epcs->control |= NIOS_SPI_SSO;	} else {		/* Let all bits shift out */		start = get_timer (0);		while ((epcs->status & NIOS_SPI_TMT) == 0)			if (get_timer (start) > EPCS_TIMEOUT)				return (-1);		epcs->control &= ~NIOS_SPI_SSO;	}	return (0);}static int epcs_tx (unsigned char c){	ulong start;	start = get_timer (0);	while ((epcs->status & NIOS_SPI_TRDY) == 0)		if (get_timer (start) > EPCS_TIMEOUT)			return (-1);	epcs->txdata = c;	return (0);}static int epcs_rx (void){	ulong start;	start = get_timer (0);	while ((epcs->status & NIOS_SPI_RRDY) == 0)		if (get_timer (start) > EPCS_TIMEOUT)			return (-1);	return (epcs->rxdata);}static unsigned char bitrev[] = {	0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,	0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f};static unsigned char epcs_bitrev (unsigned char c){	unsigned char val;	val  = bitrev[c>>4];	val |= bitrev[c & 0x0f]<<4;	return (val);}static void epcs_rcv (unsigned char *dst, int len){	while (len--) {		epcs_tx (0);		*dst++ = epcs_rx ();	}}static void epcs_rrcv (unsigned char *dst, int len){	while (len--) {		epcs_tx (0);		*dst++ = epcs_bitrev (epcs_rx ());	}}static void epcs_snd (unsigned char *src, int len){	while (len--) {		epcs_tx (*src++);		epcs_rx ();	}}static void epcs_rsnd (unsigned char *src, int len){	while (len--) {		epcs_tx (epcs_bitrev (*src++));		epcs_rx ();	}}static void epcs_wr_enable (void){	epcs_cs (1);	epcs_tx (EPCS_WRITE_ENA);	epcs_rx ();	epcs_cs (0);}static unsigned char epcs_status_rd (void){	unsigned char status;	epcs_cs (1);	epcs_tx (EPCS_READ_STAT);	epcs_rx ();	epcs_tx (0);	status = epcs_rx ();	epcs_cs (0);	return (status);}static void epcs_status_wr (unsigned char status){	epcs_wr_enable ();	epcs_cs (1);	epcs_tx (EPCS_WRITE_STAT);	epcs_rx ();	epcs_tx (status);	epcs_rx ();	epcs_cs (0);	return;}/*********************************************************************** * Device information ***********************************************************************/static struct epcs_devinfo_t devinfo[] = {	{ "EPCS1 ", 0x10, 17, 4, 15, 8, 0x0c },	{ "EPCS4 ", 0x12, 19, 8, 16, 8, 0x1c },	{ 0, 0, 0, 0, 0, 0 }};epcs_devinfo_t *epcs_dev_find (void){	unsigned char buf[4];	unsigned char id;	int i;	struct epcs_devinfo_t *dev = NULL;	/* Read silicon id requires 3 "dummy bytes" before it's put	 * on the wire.	 */	buf[0] = EPCS_READ_ID;	buf[1] = 0;	buf[2] = 0;	buf[3] = 0;	epcs_cs (1);	epcs_snd (buf,4);	epcs_rcv (buf,1);	if (epcs_cs (0) == -1)		return (NULL);	id = buf[0];	/* Find the info struct */	i = 0;	while (devinfo[i].name) {		if (id == devinfo[i].id) {			dev = &devinfo[i];			break;		}		i++;	}	return (dev);}/*********************************************************************** * Misc Utilities ***********************************************************************/int epcs_cfgsz (void){	int sz = 0;	unsigned char buf[128];	unsigned char *p;	struct epcs_devinfo_t *dev = epcs_dev_find ();	if (!dev)		return (-1);	/* Read in the first 128 bytes of the device */	buf[0] = EPCS_READ_BYTES;	buf[1] = 0;	buf[2] = 0;	buf[3] = 0;	epcs_cs (1);	epcs_snd (buf,4);	epcs_rrcv (buf, sizeof(buf));	epcs_cs (0);	/* Search for the starting 0x6a which is followed by the	 * 4-byte 'register' and 4-byte bit-count.	 */	p = buf;	while (p < buf + sizeof(buf)-8) {		if ( *p == 0x6a ) {			/* Point to bit count and extract */			p += 5;			sz = *p++;			sz |= *p++ << 8;			sz |= *p++ << 16;			sz |= *p++ << 24;			/* Convert to byte count */			sz += 7;			sz >>= 3;		} else if (*p == 0xff) {			/* 0xff is ok ... just skip */			p++;			continue;		} else {			/* Not 0xff or 0x6a ... something's not			 * right ... report 'unknown' (sz=0).			 */			break;		}	}	return (sz);}int epcs_erase (unsigned start, unsigned end){	unsigned off, sectsz;	unsigned char buf[4];	struct epcs_devinfo_t *dev = epcs_dev_find ();	if (!dev || (start>end))		return (-1);	/* Erase the requested sectors. An address is required	 * that lies within the requested sector -- we'll just	 * use the first address in the sector.	 */	printf ("epcs erasing sector %d ", start);	if (start != end)		printf ("to %d ", end);	sectsz = (1 << dev->sz_sect);	while (start <= end) {		off = start * sectsz;		start++;		buf[0] = EPCS_ERASE_SECT;		buf[1] = off >> 16;		buf[2] = off >> 8;		buf[3] = off;		epcs_wr_enable ();		epcs_cs (1);		epcs_snd (buf,4);		epcs_cs (0);		printf ("."); /* Some user feedback */		/* Wait for erase to complete */		while (epcs_status_rd() & EPCS_STATUS_WIP)			;	}	printf (" done.\n");	return (0);}int epcs_read (ulong addr, ulong off, ulong cnt){	unsigned char buf[4];	struct epcs_devinfo_t *dev = epcs_dev_find ();	if (!dev)		return (-1);	buf[0] = EPCS_READ_BYTES;	buf[1] = off >> 16;	buf[2] = off >> 8;	buf[3] = off;	epcs_cs (1);	epcs_snd (buf,4);	epcs_rrcv ((unsigned char *)addr, cnt);	epcs_cs (0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -