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

📄 spi_eeprom.c

📁 linux-2.6.15.6
💻 C
字号:
/* * linux/arch/mips/tx4938/toshiba_rbtx4938/spi_eeprom.c * Copyright (C) 2000-2001 Toshiba Corporation * * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the * terms of the GNU General Public License version 2. This program is * licensed "as is" without any warranty of any kind, whether express * or implied. * * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) */#include <linux/config.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/proc_fs.h>#include <linux/spinlock.h>#include <asm/tx4938/spi.h>#include <asm/tx4938/tx4938.h>/* ATMEL 250x0 instructions */#define	ATMEL_WREN	0x06#define	ATMEL_WRDI	0x04#define ATMEL_RDSR	0x05#define ATMEL_WRSR	0x01#define	ATMEL_READ	0x03#define	ATMEL_WRITE	0x02#define ATMEL_SR_BSY	0x01#define ATMEL_SR_WEN	0x02#define ATMEL_SR_BP0	0x04#define ATMEL_SR_BP1	0x08DEFINE_SPINLOCK(spi_eeprom_lock);static struct spi_dev_desc seeprom_dev_desc = {	.baud 		= 1500000,	/* 1.5Mbps */	.tcss		= 1,	.tcsh		= 1,	.tcsr		= 1,	.byteorder	= 1,		/* MSB-First */	.polarity	= 0,		/* High-Active */	.phase		= 0,		/* Sample-Then-Shift */};static inline intspi_eeprom_io(int chipid,	      unsigned char **inbufs, unsigned int *incounts,	      unsigned char **outbufs, unsigned int *outcounts){	return txx9_spi_io(chipid, &seeprom_dev_desc,			   inbufs, incounts, outbufs, outcounts, 0);}int spi_eeprom_write_enable(int chipid, int enable){	unsigned char inbuf[1];	unsigned char *inbufs[1];	unsigned int incounts[2];	unsigned long flags;	int stat;	inbuf[0] = enable ? ATMEL_WREN : ATMEL_WRDI;	inbufs[0] = inbuf;	incounts[0] = sizeof(inbuf);	incounts[1] = 0;	spin_lock_irqsave(&spi_eeprom_lock, flags);	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);	spin_unlock_irqrestore(&spi_eeprom_lock, flags);	return stat;}static int spi_eeprom_read_status_nolock(int chipid){	unsigned char inbuf[2], outbuf[2];	unsigned char *inbufs[1], *outbufs[1];	unsigned int incounts[2], outcounts[2];	int stat;	inbuf[0] = ATMEL_RDSR;	inbuf[1] = 0;	inbufs[0] = inbuf;	incounts[0] = sizeof(inbuf);	incounts[1] = 0;	outbufs[0] = outbuf;	outcounts[0] = sizeof(outbuf);	outcounts[1] = 0;	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);	if (stat < 0)		return stat;	return outbuf[1];}int spi_eeprom_read_status(int chipid){	unsigned long flags;	int stat;	spin_lock_irqsave(&spi_eeprom_lock, flags);	stat = spi_eeprom_read_status_nolock(chipid);	spin_unlock_irqrestore(&spi_eeprom_lock, flags);	return stat;}int spi_eeprom_read(int chipid, int address, unsigned char *buf, int len){	unsigned char inbuf[2];	unsigned char *inbufs[2], *outbufs[2];	unsigned int incounts[2], outcounts[3];	unsigned long flags;	int stat;	inbuf[0] = ATMEL_READ;	inbuf[1] = address;	inbufs[0] = inbuf;	inbufs[1] = NULL;	incounts[0] = sizeof(inbuf);	incounts[1] = 0;	outbufs[0] = NULL;	outbufs[1] = buf;	outcounts[0] = 2;	outcounts[1] = len;	outcounts[2] = 0;	spin_lock_irqsave(&spi_eeprom_lock, flags);	stat = spi_eeprom_io(chipid, inbufs, incounts, outbufs, outcounts);	spin_unlock_irqrestore(&spi_eeprom_lock, flags);	return stat;}int spi_eeprom_write(int chipid, int address, unsigned char *buf, int len){	unsigned char inbuf[2];	unsigned char *inbufs[2];	unsigned int incounts[3];	unsigned long flags;	int i, stat;	if (address / 8 != (address + len - 1) / 8)		return -EINVAL;	stat = spi_eeprom_write_enable(chipid, 1);	if (stat < 0)		return stat;	stat = spi_eeprom_read_status(chipid);	if (stat < 0)		return stat;	if (!(stat & ATMEL_SR_WEN))		return -EPERM;	inbuf[0] = ATMEL_WRITE;	inbuf[1] = address;	inbufs[0] = inbuf;	inbufs[1] = buf;	incounts[0] = sizeof(inbuf);	incounts[1] = len;	incounts[2] = 0;	spin_lock_irqsave(&spi_eeprom_lock, flags);	stat = spi_eeprom_io(chipid, inbufs, incounts, NULL, NULL);	if (stat < 0)		goto unlock_return;	/* write start.  max 10ms */	for (i = 10; i > 0; i--) {		int stat = spi_eeprom_read_status_nolock(chipid);		if (stat < 0)			goto unlock_return;		if (!(stat & ATMEL_SR_BSY))			break;		mdelay(1);	}	spin_unlock_irqrestore(&spi_eeprom_lock, flags);	if (i == 0)		return -EIO;	return len; unlock_return:	spin_unlock_irqrestore(&spi_eeprom_lock, flags);	return stat;}#ifdef CONFIG_PROC_FS#define MAX_SIZE	0x80	/* for ATMEL 25010 */static int spi_eeprom_read_proc(char *page, char **start, off_t off,				int count, int *eof, void *data){	unsigned int size = MAX_SIZE;	if (spi_eeprom_read((int)data, 0, (unsigned char *)page, size) < 0)		size = 0;	return size;}static int spi_eeprom_write_proc(struct file *file, const char *buffer,				 unsigned long count, void *data){	unsigned int size = MAX_SIZE;	int i;	if (file->f_pos >= size)		return -EIO;	if (file->f_pos + count > size)		count = size - file->f_pos;	for (i = 0; i < count; i += 8) {		int len = count - i < 8 ? count - i : 8;		if (spi_eeprom_write((int)data, file->f_pos,				     (unsigned char *)buffer, len) < 0) {			count = -EIO;			break;		}		buffer += len;		file->f_pos += len;	}	return count;}__init void spi_eeprom_proc_create(struct proc_dir_entry *dir, int chipid){	struct proc_dir_entry *entry;	char name[128];	sprintf(name, "seeprom-%d", chipid);	entry = create_proc_entry(name, 0600, dir);	if (entry) {		entry->read_proc = spi_eeprom_read_proc;		entry->write_proc = spi_eeprom_write_proc;		entry->data = (void *)chipid;	}}#endif /* CONFIG_PROC_FS */

⌨️ 快捷键说明

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