Jammy,
You can use echo/cat to /dev/mtd(x) to write to SPI EEPROM and
strings /dev/mtd(x) to read (determine the proper value of x using
'cat /proc/mtd' of course). Alternatively, attached are a couple of
simple programs I used to read/write to SPI EEPROM. Hopefully it would
be helpful to get you started.
Regards,
Steve
On Wed, 2008-12-24 at 21:34 +0800, Jammy Dane wrote:
> Hi, I want use spi in dm355 evm, there is a driver like
> at25xxA_eeprom.c, but there is no example for that, if i want to write
> data to the eeprom or if i want to read data from it, how can use the
> function? what is the process of writing or reading? may you give me
> some advice, and thank you.
> Below is the c code in mtd/devices/at25xxA_eeprom.c:
>
> #include <linux/module.h>
> #include <linux/init.h>
> #include <linux/types.h>
> #include <linux/device.h>
> #include <linux/spi/spi.h>
>
> #include <linux/mtd/mtd.h>
> #include <linux/mtd/partitions.h>
>
> #include <asm/uaccess.h>
>
> #include <linux/spi/at25xxA_eeprom.h>
> #include <linux/spi/dm355_spi_master.h>
>
> static struct davinci_eeprom_info *spi_eeprom_info;
>
> /*
> * Utilities functions
> */
> struct davinci_eeprom_info dm355_spi_eeprom_info = {
> .eeprom_size = 8192,
> .page_size = 32,
> .page_mask = 0x001F,
> .chip_sel = SCS0_SELECT,
> };
>
> #if 0
> static int spi_generic_eeprom_open(struct inode * inode, struct file * file)
> {
> file->private_data = spi_eeprom_info;
> return 0;
> }
>
> static int spi_generic_eeprom_ioctl(struct inode *inode, struct file *file,
> unsigned int cmd, unsigned long arg)
> {
> return 0;
> }
> #endif
> static int spi_generic_config(dm355_spi_config_t *spi_cfg)
> {
> if (spi_cfg == NULL) {
> printk("spi_cfg = NULL\n");
> return -1;
> }
>
> spi_cfg->clkInternal = TRUE;
> spi_cfg->csHold = TRUE;
> spi_cfg->intrLevel = FALSE;
> spi_cfg->pinOpModes = SPI_OPMODE_SPISCS_4PIN;
> spi_cfg->clkHigh = FALSE;
> spi_cfg->lsbFirst = FALSE;
> spi_cfg->parityEnable = TRUE;
> spi_cfg->oddParity = FALSE;
> spi_cfg->phaseIn = TRUE;
> spi_cfg->op_mode = TRUE; /*Polling mode -> FALSE, Interrupt mode -> TRUE */
> spi_cfg->loopBack = FALSE; /* loopback is disabled */
>
> }
> static int spi_generic_eeprom_read(struct mtd_info *mtd, loff_t from,
> size_t count, size_t *retlen, u_char *buf)
> {
> u8 *tx_ptr, *rx_ptr;
> int rx_cnt;
> unsigned int addr;
> unsigned long flags;
> struct spi_transfer x[2];
> struct spi_message msg;
> struct davinci_eeprom_info *priv_dat = mtd->priv;
>
> addr = (u16)from;
> *retlen = 0;
> if(addr > priv_dat->eeprom_size)
> return -EINVAL;
>
> if (count > priv_dat->eeprom_size)
> return -EINVAL;
>
> if((addr + count) > priv_dat->eeprom_size)
> return -EINVAL;
>
> memset(x, 0, sizeof x);
> down(&priv_dat->lock);
> x[0].tx_buf = tx_ptr = priv_dat->tx_buffer;
>
> tx_ptr[0] = DM355_EEPROM_READ;
>
> x[0].len = 3;
>
> /* Handle data return from EEPROM */
> x[1].rx_buf = rx_ptr = priv_dat->rx_buffer;
>
> while (count > 0) {
> if (likely(count > SPI_BUFFER_SIZE))
> rx_cnt = SPI_BUFFER_SIZE;
> else
> rx_cnt = count;
>
> spi_message_init(&msg);
> /* setup read command */
> tx_ptr[1] = (addr >> 8) & 0xFF;
> tx_ptr[2] = (addr & 0xFF);
>
> local_irq_save(flags);
> spi_message_add_tail(&x[0], &msg);
>
> /* read the eeprom */
> x[1].len = rx_cnt;
> spi_message_add_tail(&x[1], &msg);
> local_irq_restore(flags);
>
> spi_sync(priv_dat->spi, &msg);
>
> //spi_read(priv_dat->spi, rx_ptr, rx_cnt);
> memcpy(buf, rx_ptr, rx_cnt);
>
> buf += rx_cnt;
> count -= rx_cnt;
> addr += rx_cnt;
> *retlen += rx_cnt;
> }
> up(&priv_dat->lock);
>
> return 0;
> }
>
> static int spi_generic_eeprom_write (struct mtd_info *mtd, loff_t to,
> size_t count, size_t *retlen, const u_char *buf)
> {
> char *ptr;
> int status;
> int tx_cnt;
> unsigned int addr;
> struct spi_transfer xfer[2];
> struct spi_message msg;
> struct davinci_eeprom_info *priv_dat = mtd->priv;
> unsigned long flags;
>
> addr = (u16)(to);
> *retlen = 0;
> memset(xfer, 0, sizeof xfer);
> if(addr > priv_dat->eeprom_size)
> return -EINVAL;
>
> if (count > priv_dat->eeprom_size)
> return -EINVAL;
>
> if((addr + count) > priv_dat->eeprom_size)
> return -EINVAL;
>
> down(&priv_dat->lock);
> while(count > 0) {
> xfer[0].tx_buf = ptr = priv_dat->tx_buffer;
>
> /* set write enable */
> ptr[0] = DM355_EEPROM_WREN;
> spi_write(priv_dat->spi, ptr, 1);
>
> spi_message_init(&msg);
> /* set the write command */
> ptr[0] = DM355_EEPROM_WRITE;
> ptr[1] = (addr >> 8) & 0xFF;
> ptr[2] = (addr & 0xFF);
> xfer[0].len = DAVINCI_SPI_TX_CMD_SIZE;
> local_irq_save(flags);
> //spi_message_add_tail(&xfer[0], &msg);
>
> /* figure out the max transfer within a page */
> tx_cnt = priv_dat->page_size - (addr & priv_dat->page_mask);
> //if((tx_cnt + DAVINCI_SPI_TX_CMD_SIZE) > SPI_BUFFER_SIZE)
> // tx_cnt = SPI_BUFFER_SIZE - DAVINCI_SPI_TX_CMD_SIZE;
>
> if (count < tx_cnt)
> tx_cnt = count;
>
> ptr = &priv_dat->tx_buffer[DAVINCI_SPI_TX_CMD_SIZE];
> //xfer[1].tx_buf = ptr;
> xfer[0].len += tx_cnt;
> memcpy(ptr, buf, tx_cnt);
> //spi_write(priv_dat->spi, ptr, tx_cnt + DAVINCI_SPI_TX_CMD_SIZE);
> spi_message_add_tail(&xfer[0], &msg);
> local_irq_restore(flags);
> status = spi_sync(priv_dat->spi, &msg);
>
> count -= tx_cnt;
> buf += tx_cnt;
> addr += tx_cnt;
> *retlen += tx_cnt;
> }
> up(&priv_dat->lock);
>
> return (0);
> }
>
> #if 0
> static int spi_generic_eeprom_release(struct inode * inode, struct file *
> file)
> {
> return 0;
> }
>
> struct file_operations spi_eeprom_ops = {
>
> .owner = THIS_MODULE,
> .open = spi_generic_eeprom_open,
> .ioctl = spi_generic_eeprom_ioctl,
> .read = spi_generic_eeprom_read,
> .write = spi_generic_eeprom_write,
> .release = spi_generic_eeprom_release,
>
> };
> #endif
>
> static int spi_eeprom_generic_erase(struct mtd_info *mtd,
> struct erase_info *instr)
> {
> *mtd;
> *instr;
> }
>
> static struct mtd_info davinci_at25;
> static int __devinit eeprom_probe(struct spi_device *spi)
> {
> int ret;
> static struct mtd_info *mtd;
>
> mtd = &davinci_at25;
> memset(mtd, 0, sizeof(struct mtd_info));
>
> /* are there any id we need to read? */
> spi_eeprom_info = &dm355_spi_eeprom_info;
> spi_eeprom_info->spi = spi;
> spi_generic_config(spi->controller_data);
> spi_eeprom_info->spi_data = spi_master_get_devdata(spi->master);
> init_MUTEX(&spi_eeprom_info->lock);
>
> mtd->priv = spi_eeprom_info;
> mtd->size = spi_eeprom_info->eeprom_size;
> mtd->flags = MTD_CAP_RAM;
> mtd->read = spi_generic_eeprom_read;
> mtd->write = spi_generic_eeprom_write;
> mtd->erase = spi_eeprom_generic_erase;
> mtd->type = MTD_RAM;
> mtd->name = "spi_eeprom";
> mtd->erasesize = 0x10;
>
> ret = add_mtd_device(mtd);
> //ret = register_chrdev(SPI_EEPROM_MAJOR, DAVINCI_SPI_EEPROM_NAME,
> // &spi_eeprom_ops);
> if (ret < 0) {
> printk("at25xxA_spi_eeprom device register failed\n");
> }
> printk("at25xxA_spi_eeprom device register Succeeded\n");
> return ret;
> }
>
> static struct spi_driver spi_eeprom_driver = {
> .driver = {
> .name = DAVINCI_SPI_EEPROM_NAME,
> .bus = &spi_bus_type,
> .owner = THIS_MODULE,
> },
> .probe = eeprom_probe,
> /* since eeprom is soldered on, we don't need to worry about remove */
> };
>
> static int __init spi_eeprom_init(void)
> {
> printk("at25xxA_spi_eeprom init \n");
> return spi_register_driver(&spi_eeprom_driver);
> }
> module_init(spi_eeprom_init);
>
> static void __exit spi_eeprom_exit(void)
> {
> printk("at25xxA_spi_eeprom exit \n");
> spi_unregister_driver(&spi_eeprom_driver);
> }
> module_exit(spi_eeprom_exit);
>
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("Steve Chen");
> MODULE_DESCRIPTION("SPI EEPROM driver");
>
> 2008-12-24
>
> ______________________________________________________________________
> Jammy Dane
> _______________________________________________
> Davinci-linux-open-source mailing list
> [email protected]
> http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
#include <stdio.h>
#include <fcntl.h>
#define DATA_SIZE 1050
int main()
{
char data[DATA_SIZE];
int fd;
int i;
fd = open("/dev/mtd2", O_RDWR);
if(fd == -1) {
printf("can not open mtd1\n");
return -1;
}
read(fd, data, DATA_SIZE);
for(i=0; i<DATA_SIZE; i++) {
if((i % 8) == 0)
printf("\n");
printf("%x ", data[i]);
}
printf("\n");
close(fd);
return 0;
}
#include <stdio.h>
#include <fcntl.h>
#define DATA_SIZE 1000
int main()
{
//char *data = "ABCDEFGHIJKLMNOPQ";
//char *data = "0123456789abcdefg";
char data[DATA_SIZE];
int fd;
int i;
fd = open("/dev/mtd2", O_RDWR);
if(fd == -1) {
printf("can not open /dev/mtd1\n");
return -1;
}
for(i=0; i<DATA_SIZE; i++)
data[i] = i;
//data[i] = i << 1;
write(fd, data, DATA_SIZE);
/*
for(i=0; i<DATA_SIZE; i++) {
if((i % 16) == 0)
printf("\n");
printf("%x\n", data);
}
*/
close(fd);
return 0;
}
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source