iMX28 SPI driver on Linux

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

iMX28 SPI driver on Linux

Jump to solution
2,894 Views
x10
Contributor V

Hi, All

I got problem on developing imx28 spi driver on WinCE6.0. The MCIMX28RM is the only document, but SPI is poorly documented. It's will be much helpful if anybody can provide the corresponding linux spi driver source code, file name should be "mxs-spi.c".

Thanks in advance

BR

Cheng Shi

emtronix

Labels (1)
0 Kudos
1 Solution
1,481 Views
fabio_estevam
NXP Employee
NXP Employee

Jean-Paul,

You can use the latest mainline kernel that already supports DMA for the mxs-spi driver.

Regards,

Fabio Estevam

View solution in original post

0 Kudos
9 Replies
1,481 Views
Jean-PaulLePape
Contributor I

Hi Cheng Shi,

 No sweat :-), I was able to port the SPI driver to the 3.2.15 kernel.

Thanks,

Jean-Paul

0 Kudos
1,482 Views
fabio_estevam
NXP Employee
NXP Employee

Jean-Paul,

You can use the latest mainline kernel that already supports DMA for the mxs-spi driver.

Regards,

Fabio Estevam

0 Kudos
1,481 Views
Jean-PaulLePape
Contributor I

Hi Cheng Shi,

  I have i.m28EVK boar and I have been trying to port the SPI driver from the freescale kernel 2.6.35.3 to the kernel 3.2.15 but without any luck so far. Since you did it for windows CE. Probably you may know the process for Linux.

 I copy the files spi_mxs.c and spi_mxs.h in spi folder and copy all the dependencies in those two files but I cannot have it to compile properly. It's there a simpler way to achieve it ?

Thanks for your,

Jean-Paul

0 Kudos
1,481 Views
NilsonMagro
Contributor I

Thank you for your fast response.

 

Actually, I am struggling to start using linux spi_mxs driver.

I was able to use spidev driver with spidev_test and everything worked fine, but the performance is not enough for what I need. It is using too much cpu resource.

 

Now, my idea is to test cpu usage with spi_mxs driver and dma but I have no clue how to do this. I have been looking for a example to use with spi_mxs driver, but could not find it.

 

If you have any simple example application as how to use the driver, it will be really helpful.

 

Best regards.

0 Kudos
1,481 Views
x10
Contributor V

I just re-write spi transfer routine (no DMA mode) with referenced linux code which is as follows:

static int mxs_spi_txrx_pio(struct mxs_spi *ss, int cs,
unsigned char *buf, int len,
int *first, int *last, int write)
{
int count;

if (*first) {
mxs_spi_enable(ss);
*first = 0;
}

__raw_writel(mxs_spi_cs(cs), ss->regs + HW_SSP_CTRL0_SET);

while (len--) {
if (*last && len == 0) {
mxs_spi_disable(ss);
*last = 0;
}
__raw_writel(BM_SSP_CTRL0_XFER_COUNT,
ss->regs + HW_SSP_CTRL0_CLR);
__raw_writel(1, ss->regs + HW_SSP_CTRL0_SET); /* byte-by-byte */

if (write)
__raw_writel(BM_SSP_CTRL0_READ,
ss->regs + HW_SSP_CTRL0_CLR);
else
__raw_writel(BM_SSP_CTRL0_READ,
ss->regs + HW_SSP_CTRL0_SET);

/* Run! */
__raw_writel(BM_SSP_CTRL0_RUN, ss->regs + HW_SSP_CTRL0_SET);
count = 10000;
while (((__raw_readl(ss->regs + HW_SSP_CTRL0) &
BM_SSP_CTRL0_RUN) == 0) && count--)
continue;
if (count <= 0) {
printk(KERN_ERR "%c: timeout on line %s:%d\n",
write ? 'W' : 'C', __func__, __LINE__);
break;
}

if (write)
__raw_writel(*buf, ss->regs + HW_SSP_DATA);

/* Set TRANSFER */
__raw_writel(BM_SSP_CTRL0_DATA_XFER,
ss->regs + HW_SSP_CTRL0_SET);

if (!write) {
count = 10000;
while (count-- &&
(__raw_readl(ss->regs + HW_SSP_STATUS) &
BM_SSP_STATUS_FIFO_EMPTY))
continue;
if (count <= 0) {
printk(KERN_ERR "%c: timeout on line %s:%d\n",
write ? 'W' : 'C', __func__, __LINE__);
break;
}
*buf = (__raw_readl(ss->regs + HW_SSP_DATA) & 0xFF);
}

count = 10000;
while ((__raw_readl(ss->regs + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN)
&& count--)
continue;
if (count <= 0) {
printk(KERN_ERR "%c: timeout on line %s:%d\n",
write ? 'W' : 'C', __func__, __LINE__);
break;
}

/* advance to the next byte */
buf++;
}
return len < 0 ? 0 : -ETIMEDOUT;
}

The control flow is right, and you can just replace those hardware read/write functions with ones in WinCE6.0. good luck!

 BTW, you may need other functions:

static inline void mxs_spi_enable(struct mxs_spi *ss)
{
__raw_writel(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0_SET);
__raw_writel(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0_CLR);
}

static inline void mxs_spi_disable(struct mxs_spi *ss)
{
__raw_writel(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0_CLR);
__raw_writel(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0_SET);
}

static inline u32 mxs_spi_cs(unsigned cs)
{
return ((cs & 1) ? BM_SSP_CTRL0_WAIT_FOR_CMD : 0) |
((cs & 2) ? BM_SSP_CTRL0_WAIT_FOR_IRQ : 0);
}

0 Kudos
1,481 Views
NilsonMagro
Contributor I

Hi Cheng.

 

Could you please tell me exactly what you did to make linux spi driver working?

I have been struggling with this for some time without success.

 

Thanks.
 
Cheng Shi said:

I have got linux spi driver code for imx28, and migrate it onto CE6.0 without problem. both spi read and write in no-dma mode are work fine. I haven't test dma mode yet.

Cheng Shi

emtronix

0 Kudos
1,481 Views
x10
Contributor V

I have got linux spi driver code for imx28, and migrate it onto CE6.0 without problem. both spi read and write in no-dma mode are work fine. I haven't test dma mode yet.

Cheng Shi

emtronix

0 Kudos
1,481 Views
yechezkelmett
Contributor I

Hi Cheng Shi,

Did you ever get dma working on CE?

Yechezkel Mett

0 Kudos
1,481 Views
x10
Contributor V

No, only interrupt drived.

0 Kudos