Jammy,
The EEPROM shows up as mtd2 on with my setup. It is very unlikely the
EEPROM is mtd2 on your system. That's why in my original e-mail, I
suggested use
> cat /proc/mtd
to determine the correct mtd device node to use.
Regards,
Steve
On Thu, 2008-12-25 at 21:45 +0800, Jammy Dane wrote:
> thanks steve,
>
> i have a doubt that why the eeprom is mtd2?
>
>
> 2008-12-25
>
> ______________________________________________________________________
> Jammy Dane
>
> ______________________________________________________________________
> 发件人: Steve Chen
> 发送时间: 2008-12-24 22:33:20
> 收件人: Jammy Dane
> 抄送: gasparini; BJ_Opp; davinci-linux-open-source
> 主题: Re: FW: dm355 spi
>
> 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
>
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source