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

📄 chipio.c

📁 QNX ADS BSP code for i.MX27 chips
💻 C
字号:
/* * $QNXLicenseC:  * Copyright 2007, 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>#include <string.h>struct chipio;#define CHIPIO	struct chipio#include "devio.h"#define	COGNAC_NAND_BUF	3	/* Only buffer 3 can be used because we boot from NAND *//* * Device specific data structure for the Freescale i.mx31ads, with 528 byte NAND pages. */struct chipio {	struct _chipio	chip;	uint32_t		phys_base;	uintptr_t		io_base;	uintptr_t		reg_base;	uint32_t		data;	uint32_t		spare;	uint32_t		hwecc;} 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						"ecc",		// 2						NULL					} ;	cio = dev->cio = &chipio;	/* Default NANDC base address for i.MX21. */	cio->phys_base = 0xDF003000;	/* Bypass hardware ECC auto correction */	cio->hwecc     = 0;	while (*optstr) {		switch (getsubopt(&optstr, opts, &value)) {			case 0:				fprintf(stderr, "Device specific options:\n");				fprintf(stderr, "  -D use,ecc,addr=xxxx\n");				return (-1);			case 1:				cio->phys_base = strtol(value, NULL, 16);				break;			case 2:				cio->hwecc = 1;				break;			default:				dev->log(_SLOG_ERROR, "Invalid -D suboption.");				return (EINVAL);		}	}	return (EOK);}/* * Called once at startup */intnand_init(struct etfs_devio *dev) {	struct chipio	*cio = dev->cio;	/* Map in the device registers */	cio->io_base = mmap_device_io(0x1000, cio->phys_base);	if (cio->io_base == (uintptr_t) MAP_FAILED)		dev->log(_SLOG_CRITICAL, "Unable to map in device registers (%d).", errno);	cio->data     = cio->io_base + 0x600;	cio->spare    = cio->io_base + 0x830;	cio->reg_base = cio->io_base + 0xE00;	/* unlock the internal RAM buffer */	out16(cio->reg_base + 0x0A, 0x02);	/* set up configuration bits */	out16(cio->reg_base + 0x1A, 0x08);	/* Disable Write Protection */	out16(cio->reg_base + 0x14, 0);		out16(cio->reg_base + 0x16, 0xFFFF);	out16(cio->reg_base + 0x12, 0x04);	/* We only use buffer 3 */	out16(cio->reg_base + 0x04, COGNAC_NAND_BUF);	return (0);}/* * Read MX31_ECC_STATUS_RESULT register */uint16_t nand_read_status(struct chipio *cio){	return (in16(cio->reg_base + 0x0C));}/* * Read bit 15 of NAND_CONFIG2 register. 1 == chip ready, 0=chip busy */intnand_wait_busy(struct chipio *cio, uint32_t usec) {	uint16_t		stat;	for (usec = MAX_ERASE_USEC ; usec ; --usec) {		stat = in16(cio->reg_base + 0x1C);		if (stat & 0x8000)			return (0);		nanospin_ns(1000);	}	return (-1);}voidnand_write_cmd(struct chipio *cio, int command){	out16(cio->reg_base + 0x1C, 0);	out16(cio->reg_base + 0x08, (uint16_t)command);	out16(cio->reg_base + 0x1C, 1);	nand_wait_busy(cio, MAX_READ_USEC);	cio->chip.lastcmd = command;}voidnand_write_pageaddr(struct chipio *cio, unsigned page, int addr_cycles) {	int			i;	unsigned	addr = page << 8;	for (i = 0; i < addr_cycles; i++) {		out16(cio->reg_base + 0x1C, 0);		out16(cio->reg_base + 0x06, addr & 0xFF);		addr >>= 8;		out16(cio->reg_base + 0x1C, 2);		nand_wait_busy(cio, MAX_READ_USEC);	}}voidnand_write_blkaddr(struct chipio *cio, unsigned blk, int addr_cycles) {	int			i;	unsigned	addr = blk << 5;	for (i = 0; i < addr_cycles; i++) {		out16(cio->reg_base + 0x1C, 0);		out16(cio->reg_base + 0x06, addr & 0xFF);		addr >>= 8;		out16(cio->reg_base + 0x1C, 0x0002);		nand_wait_busy(cio, MAX_READ_USEC);	}}/* * write an entire page (data + spare). The calling function has been configured * to always pass an entire page, so we can avoid having to toggle the SP_EN bit * of the CONFIG1 register, which seems to cause problems */voidnand_write_data(struct chipio *cio, uint8_t *databuffer, uint8_t *sparebuffer){	int			i;	uint32_t	*p1, *p2;	out16(cio->reg_base + 0x04, COGNAC_NAND_BUF);	p1 = (uint32_t *)databuffer;	p2 = (uint32_t *)cio->data;	for (i = 0; i < DATASIZE; i += 4)		*p2++ = *p1++;	p1 = (uint32_t *)sparebuffer;	p2 = (uint32_t *)cio->spare;	for (i = 0; i < SPARESIZE; i += 4)		*p2++ = *p1++;	out16(cio->reg_base + 0x1C, 0x0004);	nand_wait_busy(cio, MAX_READ_USEC);}voidnand_read_data(struct chipio *cio, uint8_t *databuffer, int data_cycles) {	uint16_t	status, cfg1;	uint32_t	*pbuf = (uint32_t *)databuffer;	uint32_t	*psrc;	uint8_t		*ptrerr;	int			i, poserr;	out16(cio->reg_base + 0x04, COGNAC_NAND_BUF);	if (cio->hwecc)		cfg1 = 1 << 3;	else		cfg1 = 0;	/*	 * Determine what is being read; page data, chip ID, or chip status, 	 * and set the config2 register accordingly	 */	switch (cio->chip.lastcmd) {		case NANDCMD_IDREAD:			out16(cio->reg_base + 0x1C, 0x0000);			out16(cio->reg_base + 0x1C, 0x0010);			nand_wait_busy(cio, MAX_READ_USEC);			*(uint16_t *)databuffer = in16(cio->data);			break;		case NANDCMD_STATUSREAD:			out16(cio->reg_base + 0x1C, 0);			out16(cio->reg_base + 0x1C, 0x0020);			nand_wait_busy(cio, MAX_READ_USEC);			databuffer[0] = in16(cio->data);			break;		case NANDCMD_SPAREREAD:			cfg1 |= 0x0004;		case NANDCMD_READ:			out16(cio->reg_base + 0x1C, 0);			out16(cio->reg_base + 0x1A, cfg1);			out16(cio->reg_base + 0x1C, 0x0008);			nand_wait_busy(cio, MAX_READ_USEC);			status = in16(cio->reg_base + 0x0C);			/* Must be page read, read main buffer first */			if (data_cycles > DATASIZE) {				if (!cio->hwecc) {					if ((status & 0x0C) == 0x04) {	/* 1 bit correctable error in main area */						ptrerr = (uint8_t *)cio->data;						poserr = in16(cio->reg_base + 0x0E);						ptrerr[(poserr >> 3) & 0x1FF] ^= (1 << (poserr & 0x07));					}				}				for (i = 0, psrc = (uint32_t *)cio->data; i < DATASIZE; i += 4)					*pbuf++ = *psrc++;			}			if (!cio->hwecc) {				if ((status & 0x03) == 0x01) {		/* 1 bit correctable error in spare area */					ptrerr = (uint8_t *)cio->spare;					poserr = in16(cio->reg_base + 0x10);					ptrerr[(poserr >> 3) & 0x03] ^= (1 << (poserr & 0x07));				}			}			/* Read spare area */			for (i = 0, psrc = (uint32_t *)cio->spare; i < SPARESIZE; i += 4)				*pbuf++ = *psrc++;			break;	}	out16(cio->reg_base + 0x1A, 0x0008);}

⌨️ 快捷键说明

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