Jammy,
It is very difficult to tell what is the kernel is suppose to do without
knowing more information about the hardware and the code. In general,
there are some things you can check.
1. Verify pinmux are set correctly.
2. Verify chip_select is correct in the code.
3. Put a printk in the prob function of your fpga_spi.c to see if it is
being called.
4. If there are test points available to access the fpga spi device,
verify signals (clock, chip select, etc.)
In general, you should be able to talk to 2 spi devices by setting up 2
chip select. Lastly, just a comment regarding the FPGA spi. I have no
idea what it does, but I suspect it is probably not implemented as a
memory storage device. If that is the case, making it a mtd is probably
not the way to go.
Regards,
Steve
On Wed, 2008-12-31 at 12:29 +0800, Jammy Dane wrote:
>
> I am sorry to truble you but your suggestions are very important to
> me.
>
> I wrote a fpga_spi.c which is similar with at25xxA_eeprom.c, and i
> have changed the spi_board_info.c, when i make a new linux kernel and
> load it, it does not register the fpga spi module. what i want to ask
> is :
> if the fpga little board is not mounted, can i mount the fpga spi
> module?
> how can i use two slave chips on dm355 evm? where should i change?
>
> thank you for responding.
> 2008-12-31
>
> ______________________________________________________________________
> Jammy Dane
>
> ______________________________________________________________________
> 发件人: Steve Chen
> 发送时间: 2008-12-25 22:07:19
> 收件人: Jammy Dane
> 抄送: gasparini; BJ_Opp; davinci-linux-open-source
> 主题: Re: Re: FW: dm355 spi
>
> 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