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

📄 chipio.c

📁 Centrality Atlas II development software
💻 C
字号:
/* * $QNXLicenseC:  * Copyright 2007,2008, QNX Software Systems.   *   * Licensed under the Apache License, Version 2.0 (the "License"). You   * may not reproduce, modify or distribute this software except in   * compliance with the License. You may obtain a copy of the License   * at: http://www.apache.org/licenses/LICENSE-2.0   *   * Unless required by applicable law or agreed to in writing, software   * distributed under the License is distributed on an "AS IS" basis,   * WITHOUT WARRANTIES OF ANY KIND, either express or implied.  *  * This file may contain contributions from others, either as   * contributors under the License or as licensors under other terms.    * Please review this entire file for other proprietary rights or license   * notices, as well as the QNX Development Suite License Guide at   * http://licensing.qnx.com/license-guide/ for other information.  * $  */#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <sys/slog.h>#include <sys/mman.h>#include <sys/neutrino.h>#include <hw/inout.h>#include <fs/etfs.h>struct chipio;#define CHIPIO	struct chipio#include "devio.h"#define PRINT_FUNCTIONNAME fprintf(stderr, "ETFS: %s \n", __FUNCTION__);#define ATLASII_NAND_BASE			0x80070000#define ATLASII_NAND_SIZE			0xF20#define ATLASII_IOBRDG_FLUSH		0xB0000804#define EXT_PIO_BASE                            0x14000000#define ATLASII_SM_WAIT			0x04#define ATLASII_SM_BANK_SEL		0x08#define ATLASII_SM_ADD_NUM		0x0C#define ATLASII_SM_CMD				0x10#define ATLASII_SM_LOW_ADDR		0x14#define ATLASII_SM_HIGH_ADDR		0x18#define ATLASII_SM_PAGE_SIZE		0x1C#define ATLASII_SM_INT_EN			0x20#define ATLASII_SM_INT_STATUS		0x24#define ATLASII_SM_CTRL				0x28#define ATLASII_SM_ECC_SET			0x2C#define ATLASII_SM_ECC_AREA1		0x30#define ATLASII_SM_ECC_AREA2		0x34#define ATLASII_SM_DMA_IO_CTRL	0xF00#define ATLASII_SM_DMA_IO_LEN		0xF04#define ATLASII_SM_FIFO_CTRL 		0xF08#define ATLASII_SM_FIFO_LEVEL_CHK	0xF0C#define ATLASII_SM_FIFO_OP 			0xF10#define ATLASII_SM_FIFO_STATUS	0xF14#define ATLASII_SM_FIFO_DATA 		0xF18#define NAND_STATUS_READY			0x01#define NAND_STATUS_WT_CMD		0x02#define NAND_STATUS_WT_IO			0x04#define NAND_STATUS_WT_FIFO		0x08#define NAND_MODE_CMD			0x10#define NAND_MODE_IO_READ		0x3#define NAND_MODE_IO_WRITE	0x1//// Device specific data structure for the jace5 with 528 byte NAND pages.//struct chipio {	struct _chipio	chip;	unsigned		phy_base;	unsigned		bank;	unsigned		iobase;	unsigned		io_data;	unsigned		io_address;	unsigned		io_command;	unsigned		io_status;	unsigned		io_brdg;} chipio;intmain(int argc, char *argv[]) {	return(etfs_main(argc, argv));}//// Process device specific options (if any).// This is always called before any access to the part.// It is called by the -D option to the filesystem. If no -D option is given// this function will still be called with "" for optstr.//int devio_options(struct etfs_devio *dev, char *optstr) {	struct chipio	*cio;	char			*value;	static char		*opts[] ={	"use",		// 0						"addr",		// 1						"cs",	// 2 						NULL					} ;	cio = dev->cio = &chipio;	while(*optstr) {		switch(getsubopt(&optstr, opts, &value)) {		case 0:			printf("Device specific options:\n");			printf("  -D use,addr=xxxx,cs\n");			return(-1);		case 1:			cio->phy_base = strtol(value, NULL, 16);			break;		case 2:			cio->bank = 1;			break;		default:			dev->log(_SLOG_ERROR, "Invalid -D suboption.");			return(EINVAL);		}	}	return(EOK);}// Called once at startupintnand_init(struct etfs_devio *dev) {	uint8_t 			nandcs;	unsigned		expiobase;	struct chipio	*cio = dev->cio;	// Pick a default for the board.	if(cio->phy_base == 0)		cio->phy_base = ATLASII_NAND_BASE;	// Map in the device registers	cio->iobase = mmap_device_io(ATLASII_NAND_SIZE, cio->phy_base);	if(cio->iobase == (uintptr_t) MAP_FAILED) {		dev->log(_SLOG_CRITICAL, "Unable to map in device registers (%d).", errno);		return(-1);	}	cio->io_brdg = mmap_device_io(4, ATLASII_IOBRDG_FLUSH);	if(cio->io_brdg == (uintptr_t) MAP_FAILED) {		dev->log(_SLOG_CRITICAL, "Unable to map in device registers (%d).", errno);		return(-1);	}	expiobase = mmap_device_io(0x6000, EXT_PIO_BASE);	if(expiobase == (uintptr_t) MAP_FAILED) {		dev->log(_SLOG_CRITICAL, "Unable to map in device registers (%d).", errno);		return(-1);	}		//where we are booting from	nandcs = (in8(expiobase+0x1A00)>>1) & 0x7;	if(nandcs==7) //boting from SM card	{		if(cio->bank==1)		{			//set FCE2 t0 empty			out8(expiobase+0x1C00, 0x0f);			//set FCE3 to NANDCS0			out8(expiobase+0x1E00, 0);			nandcs=3;		}		else			nandcs=0;	}else if(nandcs==0)	{		if(cio->bank==1)		{			//set FCE2 t0 empty			out8(expiobase+0x1C00, 0x0f);			//set FCE3 to SM card			out8(expiobase+0x1E00, 0x08);			nandcs=3;		}		else			nandcs=0;	}else //default to booting device		nandcs=0;	cio->io_data = cio->iobase + ATLASII_SM_FIFO_DATA;	cio->io_address = cio->iobase + ATLASII_SM_LOW_ADDR;	cio->io_command = cio->iobase + ATLASII_SM_CMD;	out32(cio->iobase+ATLASII_SM_CTRL, in32(cio->iobase+ATLASII_SM_CTRL) & (~0x1));  //IO-Read mode	out32(cio->iobase+ATLASII_SM_CTRL, in32(cio->iobase+ATLASII_SM_CTRL) & (~0x2));  //force 8-bit		out32(cio->iobase+ATLASII_SM_WAIT, 0x1878);  //Set Wait Reg	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x1);  //Start FIFO	out32(cio->iobase+ATLASII_SM_ECC_SET, 0x0);  //disable hardware ECC		//NAND bank select	out32(cio->iobase+ATLASII_SM_BANK_SEL,  (~(0x1<<nandcs)) & 0xF);  	cio->io_status =NAND_STATUS_READY;	//clear all Intrrupt	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xe);	return(0);}// Read bit 0 of status/control reg (0xffff4003/0xffff5003). 0=chip busyintnand_wait_busy(struct chipio *cio, uint32_t usec) {	uint32_t		x;	for(usec = MAX_ERASE_USEC; usec ; --usec) {		if(cio->io_status == NAND_STATUS_READY)			return(0);		else if(cio->io_status == NAND_STATUS_WT_CMD)		{			x=in32(cio->iobase+ATLASII_SM_INT_STATUS);			if(x & NAND_STATUS_WT_CMD)			{				//clear intr				out32(cio->iobase+ATLASII_SM_INT_STATUS, x |NAND_STATUS_WT_CMD);				cio->io_status = NAND_STATUS_READY;				return(0);			}			else				nanospin_ns(1000);						}		else if(cio->io_status == NAND_STATUS_WT_IO)		{			x=in32(cio->iobase+ATLASII_SM_INT_STATUS);			if(x & NAND_STATUS_WT_IO)			{				//clear intr				out32(cio->iobase+ATLASII_SM_INT_STATUS, x |NAND_STATUS_WT_IO);				cio->io_status = NAND_STATUS_READY;				return(0);			}			else				nanospin_ns(1000);		}		else if(cio->io_status == NAND_STATUS_WT_FIFO)		{			x=in32(cio->iobase+ATLASII_SM_INT_STATUS);			if(x & NAND_STATUS_WT_FIFO)			{				//clear intr				out32(cio->iobase+ATLASII_SM_INT_STATUS, x |NAND_STATUS_WT_FIFO);				cio->io_status = NAND_STATUS_READY;				return(0);			}			else				nanospin_ns(1000);		}		else nanospin_ns(1000);	}	return(-1);		// We will exit from the log and never reach here. }// Accessing the command reg automatically sets ALE=0, CLE=1voidnand_write_cmd(struct chipio *cio, int command) {	//enter to command mode	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD);	out32(cio->io_command, (uint8_t) command);	cio->chip.lastcmd = command;	cio->io_status = NAND_STATUS_WT_CMD;}int nand_read_flashid(struct chipio * cio, uint8_t *id, int data_cycles){	int i=100000000;	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x2);  //Reset FIFO	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x0);  //Reset FIFO	//enter to io read mode	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_READ);	//set io-len	out32(cio->iobase+ATLASII_SM_DMA_IO_LEN, 0x4);	out32(cio->iobase+ATLASII_SM_FIFO_CTRL, 0x4<<2);	//set addr num	out32(cio->iobase+ATLASII_SM_ADD_NUM, 0x1);	//set low addr=0;	out32(cio->iobase+ATLASII_SM_LOW_ADDR, 0x0);	//clear intr	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xf);	//set command	out32(cio->io_command, 0x90);  //read id command	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x1);  //Reset FIFO	while((in32(cio->iobase+ATLASII_SM_FIFO_STATUS) & 0x80) && i--) ;	if(i<0)		return -1;	*(uint32_t *)id = in32(cio->iobase+ATLASII_SM_FIFO_DATA);	out32(cio->io_brdg, 1);	while (in32(cio->io_brdg));	return (0);}int nand_read_status(struct chipio * cio, uint8_t *databuffer){	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x2);  //Reset FIFO	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x0);  //Reset FIFO	//enter to io read mode	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_READ);	//set addr num	out32(cio->iobase+ATLASII_SM_ADD_NUM, 0);	//set low addr=0;	out32(cio->iobase+ATLASII_SM_HIGH_ADDR, 0x0);	out32(cio->iobase+ATLASII_SM_LOW_ADDR, 0x0);	//set io-len	out32(cio->iobase+ATLASII_SM_DMA_IO_LEN, 0x4);	out32(cio->iobase+ATLASII_SM_FIFO_CTRL, 0x4<<2);	//clear intr	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xf);	//set command	out32(cio->io_command, 0x70);  //read status command	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x1);  //Reset FIFO	//wait command end	cio->io_status = NAND_STATUS_WT_FIFO;	if(nand_wait_busy(cio,  MAX_READ_USEC) != 0)		return(-1);	else		*(uint32_t *)databuffer = in32(cio->iobase+ATLASII_SM_FIFO_DATA);			out32(cio->io_brdg, 1);	while (in32(cio->io_brdg));	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x2);  //Reset FIFO	return 0;}//op=0, read data//op=1, read spareint nand_read_page(struct chipio * cio, unsigned page, uint8_t *databuffer, int data_cycles, int op){	if(op==0)	{	//Reset ECC		out32(cio->iobase+ATLASII_SM_ECC_SET, 0x07);		out32(cio->iobase+ATLASII_SM_ECC_SET, 0x05);	}	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x2);  //Reset FIFO	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x0);  //Reset FIFO	//enter to io read mode	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_READ);	//set io-len	out32(cio->iobase+ATLASII_SM_DMA_IO_LEN, data_cycles);	//set addr num	out32(cio->iobase+ATLASII_SM_ADD_NUM, 0x4);	//set low addr=0;	out32(cio->iobase+ATLASII_SM_LOW_ADDR, page<<8);	out32(cio->iobase+ATLASII_SM_HIGH_ADDR, 0);	//clear intr	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xf);	//set command	if(op==1)	{		out32(cio->io_command, 0x50);  //read2 command			cio->chip.lastcmd = NANDCMD_SPAREREAD;	}	else 	{		out32(cio->io_command, 0x0);  //read1 command		cio->chip.lastcmd = NANDCMD_READ;	}	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x1);  //Reset FIFO	//wait command end	cio->io_status = NAND_STATUS_WT_IO;	if(nand_read_data(cio, databuffer, data_cycles)!=0)		return -1;	return data_cycles;}//op=0, write data//op=1, write spareint nand_write_page(struct chipio * cio, unsigned page, uint8_t *databuffer, int data_cycles, int op){	if(op==0)	{	//Reset ECC		out32(cio->iobase+ATLASII_SM_ECC_SET, 0x07);		out32(cio->iobase+ATLASII_SM_ECC_SET, 0x05);	}		//change the write pointer to either data area or spare area	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD);	out32(cio->iobase+ATLASII_SM_ADD_NUM, 0x0);	//clear intr	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xf);	if(op==0)	{		cio->chip.lastcmd = NANDCMD_READ;		out32(cio->io_command, 0x0);  //read1 command	}	else	{		cio->chip.lastcmd = NANDCMD_SPAREREAD;		out32(cio->io_command, 0x50);  //read2 command		}	cio->io_status = NAND_STATUS_WT_CMD;	//wait for the command end	if(nand_wait_busy(cio, MAX_READ_USEC) !=0)		return (-1);	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x2);  //Reset FIFO	out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x0);  //Reset FIFO	//enter to io write mode	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_IO_WRITE);	//set io-len	out32(cio->iobase+ATLASII_SM_DMA_IO_LEN, data_cycles);	//set addr num	out32(cio->iobase+ATLASII_SM_ADD_NUM, 0x4);	//set low addr=0;	out32(cio->iobase+ATLASII_SM_LOW_ADDR, page<<8);	out32(cio->iobase+ATLASII_SM_HIGH_ADDR, 0);	//clear interrupt	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xf);	//set command	cio->chip.lastcmd = NANDCMD_PROGRAM;	out32(cio->io_command, 0x80);  //write command		out32(cio->iobase+ATLASII_SM_FIFO_OP, 0x1);  //Reset FIFO	if(nand_write_data(cio, databuffer, data_cycles)!=0)		return -1;	//wait command end	cio->io_status = NAND_STATUS_WT_IO;	if(nand_wait_busy(cio,  MAX_POST_USEC) != 0)		return(-2);	//enter to command mode	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD);	out32(cio->iobase+ATLASII_SM_ADD_NUM, 0x0);	//clear interrupt	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xf);	//set command	cio->chip.lastcmd = NANDCMD_PROGRAMCONFIRM;	out32(cio->io_command, 0x10);  //write confirm command		cio->io_status = NAND_STATUS_WT_CMD;	if(nand_wait_busy(cio,  MAX_POST_USEC) != 0)		return(-3);	return 0;}int nand_erase_blk(struct chipio * cio, unsigned blk){	out32(cio->iobase+ATLASII_SM_DMA_IO_CTRL, NAND_MODE_CMD);	out32(cio->iobase+ATLASII_SM_ADD_NUM, 0x3);  	//set low addr=0;	out32(cio->iobase+ATLASII_SM_LOW_ADDR, (blk<<5));	out32(cio->iobase+ATLASII_SM_HIGH_ADDR, 0);	//clear interrupt	out32(cio->iobase+ATLASII_SM_INT_STATUS, 0xf);	//set command	cio->chip.lastcmd = NANDCMD_ERASECONFIRM;	out32(cio->io_command, 0xD060);  //blk erase command		//wait command end	cio->io_status = NAND_STATUS_WT_CMD;	if(nand_wait_busy(cio,  MAX_ERASE_USEC) != 0)		return(-1);	return 0;}// Accessing the address reg automatically sets ALE=1, CLE=0voidnand_write_pageaddr(struct chipio *cio, unsigned page, int addr_cycles) {}// Accessing the address reg automatically sets ALE=1, CLE=0voidnand_write_blkaddr(struct chipio *cio, unsigned blk, int addr_cycles) {}// Accessing the data reg automatically sets ALE=0, CLE=0intnand_write_data(struct chipio *cio, uint8_t *databuffer, int data_cycles) {	int i;	volatile unsigned *tmp;	volatile unsigned val;		if(data_cycles%4 !=0)	{		fprintf(stderr, "data not aligned on 4-byte boundary\n");		return -1;	}	tmp=(volatile unsigned *)databuffer;	for(i = 0; i < data_cycles/4; i++){		while(in32(cio->iobase+ATLASII_SM_FIFO_STATUS) & 0x40) ; 		val=tmp[i];		out32(cio->io_data, val);	}	out32(cio->io_brdg, 1);	while (in32(cio->io_brdg)); 	return 0; }// Accessing the data reg automatically sets ALE=0,CLE=0//must be 4-byte alignedintnand_read_data(struct chipio *cio, uint8_t *databuffer, int data_cycles) {	int i;	volatile unsigned *tmp;	volatile unsigned val;	if(data_cycles%4 !=0)	{		fprintf(stderr, "data not aligned on 4-byte boundary\n");		return -1;	}	tmp=(volatile unsigned *)databuffer;	for(i = 0; i < data_cycles/4; i++){		while(in32(cio->iobase+ATLASII_SM_FIFO_STATUS) & 0x80) ;   		val = in32(cio->io_data);		tmp[i]=val;	}	out32(cio->io_brdg, 1);	while (in32(cio->io_brdg));	return 0;}

⌨️ 快捷键说明

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