#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Function code bits. */ #define SMC_EB ((u_char)0x10) /* Set big endian byte order */ #define CPM_MAXBD 1 #define CPM_MAX_READ 513 #define CORE_SPEED 50000000 #define SPI_BAUD 1750000 #define SPI_PM_VALUE ((CORE_SPEED/(4*SPI_BAUD)) - 1) #define DPRAM_BASE ((u8 __iomem __force *)cpm_muram_addr(0)) #define I2COM_START 0x80 #define I2COM_MASTER 0x01 #define I2CER_TXE 0x10 #define I2CER_BUSY 0x04 #define I2CER_TXB 0x02 #define I2CER_RXB 0x01 #define I2MOD_EN 0x01 #define MPC885_SPI_MAJOR 120 /* SPI parameter RAM. */ struct spi_ram { ushort rbase; /* Rx Buffer descriptor base address */ ushort tbase; /* Tx Buffer descriptor base address */ u_char rfcr; /* Rx function code */ u_char tfcr; /* Tx function code */ ushort mrblr; /* Max receive buffer length */ uint rstate; /* Internal */ uint rdp; /* Internal */ ushort rbptr; /* Internal */ ushort rbc; /* Internal */ uint rxtmp; /* Internal */ uint tstate; /* Internal */ uint tdp; /* Internal */ ushort tbptr; /* Internal */ ushort tbc; /* Internal */ uint txtmp; /* Internal */ uint res; ushort rpbase; /* Relocation pointer */ ushort res2; }; /* SPI Registers */ struct spi_reg { u16 spmod; u8 res1[4]; u8 spie; u8 res2[3]; u8 spim; u8 res3[2]; u8 spcom; u8 res4[4]; }; struct cpm_spi { struct of_device *ofdev; uint dp_addr; int version; /* CPM1=1, CPM2=2 */ int irq; int cp_command; int freq; struct spi_reg __iomem *spi_reg; struct spi_ram __iomem *spi_ram; u16 spi_addr; wait_queue_head_t spi_wait; cbd_t __iomem *tbase; cbd_t __iomem *rbase; u_char *txbuf[CPM_MAXBD]; u_char *rxbuf[CPM_MAXBD]; u32 txdma[CPM_MAXBD]; u32 rxdma[CPM_MAXBD]; }; static struct cpm_spi *cpm; static irqreturn_t mpc885_spi_interrupt(int irq, void *dev_id) { struct spi_reg __iomem *spi_reg = cpm->spi_reg; unsigned int i,j; unsigned char buf[20]; cbd_t __iomem *rbdf; rbdf = cpm->rbase; printk("\n mpc885_spi_interrupt "); /* Clear interrupt. */ i = in_8(&spi_reg->spie); printk("\n mpc885_spi_interrupt: status = %x", i); out_8(&spi_reg->spie, i); wake_up(&cpm->spi_wait); printk("\n in int after wakeup"); out_8(&spi_reg->spie, i); /* if (!(in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY)) { i = in_be16(&rbdf->cbd_datlen); memcpy(buf, cpm->rxbuf[0], i); printk("\nspi rcv bytes :"); for (j = 0; j < i; j++) printk ("%x ", buf[j]); } */ return IRQ_HANDLED; } static void mpc885_spi_force_close(void) { struct spi_reg __iomem *spi_reg = cpm->spi_reg; printk("in spi mpc885_spi_force_close\n"); cpm_command(cpm->cp_command, CPM_CR_CLOSE_RX_BD); out_8(&spi_reg->spim, 0x00); /* Disable all interrupts */ out_8(&spi_reg->spie, 0xff); } static void cpm_spi_parse_message(struct i2c_msg *pmsg, int num, int tx, int rx) { cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; u_char *tb; u_char *rb; printk ("\nin spi parse message\n"); tx = rx = 0; tbdf = cpm->tbase + tx; rbdf = cpm->rbase + rx; tb = cpm->txbuf[tx]; rb = cpm->rxbuf[rx]; /* Align read buffer */ rb = (u_char *) (((ulong) rb + 1) & ~1); out_be16(&tbdf->cbd_datlen, pmsg->len + 1); out_be16(&tbdf->cbd_sc, 0); if (!(pmsg->flags & I2C_M_NOSTART)) setbits16(&tbdf->cbd_sc, BD_I2C_START); if (tx + 1 == num) setbits16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP); // if (pmsg->flags & I2C_M_RD) { /* * To read, we need an empty buffer of the proper length. * All that is used is the first byte for address, the remainder * is just used for timing (and doesn't really have to exist). */ out_be16(&rbdf->cbd_datlen, 0); out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT); if (rx + 1 == CPM_MAXBD) setbits16(&rbdf->cbd_sc, BD_SC_WRAP); eieio(); setbits16(&tbdf->cbd_sc, BD_SC_READY); // } else { if (!(pmsg->flags & I2C_M_RD)) { memcpy(tb + 1, pmsg->buf, pmsg->len); eieio(); setbits16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_INTRPT); } } static int cpm_spi_check_message(struct i2c_msg *pmsg, int tx, int rx) { cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; u_char *tb; u_char *rb; printk ("\nin spi check message\n"); tx = rx = 0; tbdf = cpm->tbase + tx; rbdf = cpm->rbase + rx; tb = cpm->txbuf[tx]; rb = cpm->rxbuf[rx]; /* Align read buffer */ rb = (u_char *) (((uint) rb + 1) & ~1); eieio(); if (pmsg->flags & I2C_M_RD) { if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) { printk("I2C read; No ack\n"); return -ENXIO; } if (in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY) { printk("I2C read; complete but rbuf empty\n"); return -EREMOTEIO; } if (in_be16(&rbdf->cbd_sc) & BD_SC_OV) { printk("I2C read; Overrun\n"); return -EREMOTEIO; } memcpy(pmsg->buf, rb, pmsg->len); } else { if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) { printk("I2C write; No ack\n"); return -ENXIO; } if (in_be16(&tbdf->cbd_sc) & BD_SC_UN) { printk("I2C write; Underrun\n"); return -EIO; } if (in_be16(&tbdf->cbd_sc) & BD_SC_UN) { printk("I2C write; Underrun\n"); return -EIO; } if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) { printk("I2C write; Collision\n"); return -EIO; } } return 0; } static int mpc885_spi_xfer(struct i2c_msg *msgs, int num) { struct spi_reg __iomem *spi_reg = cpm->spi_reg; struct spi_ram __iomem *spi_ram = cpm->spi_ram; struct i2c_msg *pmsg; int ret = 0, i; int tptr; int rptr; cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; u_char *rb; printk ("\nin spi_xfer\n"); if (num > CPM_MAXBD) return -EINVAL; /* Check if we have any oversized READ requests */ for (i = 0; i < num; i++) { pmsg = &msgs[i]; if (pmsg->len >= CPM_MAX_READ) return -EINVAL; } /* Reset to use first buffer */ out_be16(&spi_ram->rbptr, in_be16(&spi_ram->rbase)); out_be16(&spi_ram->tbptr, in_be16(&spi_ram->tbase)); tbdf = cpm->tbase; rbdf = cpm->rbase; tptr = 0; rptr = 0; if (msgs->flags & I2C_M_RD) { /* * We go twice through the buffer descs */ while (i < (CPM_MAXBD * 2)) { if (!(in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY)) { // printk("\ndata found"); rb = cpm->rxbuf[rptr]; ret = in_be16(&rbdf->cbd_datlen); memcpy(msgs->buf, rb, ret); // printk("%s\n", pmsg->buf); if (rptr >= CPM_MAXBD) rptr = 0; else rptr++; /* * To read, we need an empty buffer of the proper length. * All that is used is the first byte for address, the remainder * is just used for timing (and doesn't really have to exist). */ out_be16(&rbdf->cbd_datlen, 0); out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT); if (rptr + 1 == CPM_MAXBD) setbits16(&rbdf->cbd_sc, BD_SC_WRAP); break; } rptr++; if (rptr >= CPM_MAXBD) rptr = 0; rbdf = cpm->rbase + rptr; i++; } return ret; } while (tptr < num) { pmsg = &msgs[tptr]; cpm_spi_parse_message(pmsg, num, tptr, rptr); if (pmsg->flags & I2C_M_RD) rptr++; tptr++; } /* Start transfer now */ /* Enable RX/TX/Error interupts */ out_8(&spi_reg->spim, I2CER_TXE | I2CER_TXB | I2CER_RXB); out_8(&spi_reg->spie, 0xff); /* Clear interrupt status */ out_be16(&spi_reg->spmod, 0x3770 | SPI_PM_VALUE ); //enabling spi out_be16(&spi_reg->spmod, (in_be16(&spi_reg->spmod)) | 0x0100 ); //enabling spi /* Begin transmission */ out_8(&spi_reg->spcom, 0x80); tptr = 0; rptr = 0; while (tptr < num) { /* Check for outstanding messages */ pmsg = &msgs[tptr]; if (pmsg->flags & I2C_M_RD) ret = wait_event_timeout(cpm->spi_wait, (in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) || !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY), 1 * HZ); else ret = wait_event_timeout(cpm->spi_wait, !(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY), 1 * HZ); if (ret == 0) { ret = -EREMOTEIO; goto out_err; } if (ret > 0) { ret = cpm_spi_check_message(pmsg, tptr, rptr); tptr++; if (pmsg->flags & I2C_M_RD) rptr++; if (ret) goto out_err; } } #ifdef I2C_CHIP_ERRATA /* * Chip errata, clear enable. This is not needed on rev D4 CPUs. * Disabling I2C too early may cause too short stop condition */ udelay(4); out_be16(&spi_reg->spmod, (in_be16(&spi_reg->spmod)) & 0xfeff ); //disabling spi #endif out_be16(&spi_reg->spmod, (in_be16(&spi_reg->spmod)) & 0xfdff ); //configuring as slave return (num); out_err: mpc885_spi_force_close(); #ifdef I2C_CHIP_ERRATA /* * Chip errata, clear enable. This is not needed on rev D4 CPUs. */ out_be16(&spi_reg->spmod, (in_be16(&spi_reg->spmod)) & 0xfeff ); //disabling spi #endif out_be16(&spi_reg->spmod, (in_be16(&spi_reg->spmod)) & 0xfdff ); //configuring as slave return ret; } static void mpc885_reset_spi_params(struct cpm_spi *cpm) { struct spi_ram __iomem *spi_ram = cpm->spi_ram; printk ("\nreset spi params\n"); /* Set up the SPI parameters in the parameter ram. */ out_be16(&spi_ram->tbase, (u8 __iomem *)cpm->tbase - DPRAM_BASE); out_be16(&spi_ram->rbase, (u8 __iomem *)cpm->rbase - DPRAM_BASE); if (cpm->version == 1) { out_8(&spi_ram->tfcr, SMC_EB); out_8(&spi_ram->rfcr, SMC_EB); } out_be16(&spi_ram->mrblr, CPM_MAX_READ); out_be32(&spi_ram->rstate, 0); out_be32(&spi_ram->rdp, 0); out_be16(&spi_ram->rbptr, 0); out_be16(&spi_ram->rbc, 0); out_be32(&spi_ram->rxtmp, 0); out_be32(&spi_ram->tstate, 0); out_be32(&spi_ram->tdp, 0); out_be16(&spi_ram->tbptr, 0); out_be16(&spi_ram->tbc, 0); out_be32(&spi_ram->txtmp, 0); } static int __devinit mpc885_spi_setup(struct cpm_spi *cpm) { struct of_device *ofdev = cpm->ofdev; const u32 *data; int len, ret, i; void __iomem *spi_base; cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; cpm8xx_t __iomem *pa_reg = immr_map(im_cpm); printk ("\nSPI: setup\n"); init_waitqueue_head(&cpm->spi_wait); cpm->irq = of_irq_to_resource(ofdev->node, 0, NULL); printk("SPI: irq no %d\n",cpm->irq); if (cpm->irq == NO_IRQ) { printk("SPI: irq invalid\n"); return -EINVAL; } /* Install interrupt handler. */ ret = request_irq(cpm->irq, mpc885_spi_interrupt, IRQF_DISABLED, "mpc885_spi", cpm); if(ret) { printk("SPI:request_irq invalid\n"); return ret; } /* SPI parameter RAM */ spi_base = of_iomap(ofdev->node, 1); // request_mem_region if (spi_base == NULL) { printk("SPI: of_iomap invalid\n"); ret = -EINVAL; goto out_irq; } if (of_device_is_compatible(ofdev->node, "fsl,mpc885-spi")) { /* Check for and use a microcode relocation patch. */ printk("SPI:of_device_is_compatible\n"); cpm->spi_ram = spi_base; cpm->spi_addr = in_be16(&cpm->spi_ram->rpbase); /* * Maybe should use cpm_muram_alloc instead of hardcoding * this in micropatch.c */ if (cpm->spi_addr) { printk("SPI:of_device_is_compatible spi_addr\n"); cpm->spi_ram = spi_base; cpm->spi_ram = cpm_muram_addr(cpm->spi_addr); iounmap(spi_base); } cpm->version = 1; } else { printk("SPI:of_device_is_compatible spi_addr invalid\n "); cpm->spi_ram = spi_base; iounmap(spi_base); ret = -EINVAL; goto out_irq; } /* SPI control/status registers */ cpm->spi_reg = of_iomap(ofdev->node, 0); if (cpm->spi_reg == NULL) { ret = -EINVAL; goto out_ram; } data = of_get_property(ofdev->node, "fsl,cpm-command", &len); if (!data || len != 4) { printk("SPI:of_get_property fsl,cpm_command\n "); ret = -EINVAL; goto out_reg; } cpm->cp_command = *data; printk("SPI: fsl,cpm_command %d\n",cpm->cp_command ); data = of_get_property(ofdev->node, "clock-frequency", &len); if (data && len == 4) { cpm->freq = *data; printk("SPI: clockfreq %d\n",cpm->freq ); } else // cpm->freq = 60000; /* use 60kHz i2c clock by default */ cpm->freq = SPI_BAUD; /* use 60kHz i2c clock by default */ printk("SPI: clockfreq %d\n",cpm->freq ); /* * Allocate space for CPM_MAXBD transmit and receive buffer * descriptors in the DP ram. */ cpm->dp_addr = cpm_muram_alloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8); if (!cpm->dp_addr) { printk("SPI: invalid dp_addr\n" ); ret = -ENOMEM; goto out_reg; } cpm->tbase = cpm_muram_addr(cpm->dp_addr); cpm->rbase = cpm_muram_addr(cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD); /* Allocate TX and RX buffers */ tbdf = cpm->tbase; rbdf = cpm->rbase; for (i = 0; i < CPM_MAXBD; i++) { cpm->rxbuf[i] = dma_alloc_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, &cpm->rxdma[i], GFP_KERNEL); if (!cpm->rxbuf[i]) { ret = -ENOMEM; goto out_muram; } out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1)); out_be16(&rbdf[i].cbd_datlen, 0); out_be16(&rbdf[i].cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT); if (i + 1 == CPM_MAXBD) setbits16(&rbdf[i].cbd_sc, BD_SC_WRAP); eieio(); cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL); if (!cpm->txbuf[i]) { ret = -ENOMEM; goto out_muram; } out_be16(&tbdf[i].cbd_datlen, 0); out_be16(&tbdf[i].cbd_sc, 0); out_be32(&tbdf[i].cbd_bufaddr, cpm->txdma[i]); printk("\ncbd_bufaddr in init = %p",in_be32(&tbdf[i].cbd_bufaddr)); } /* Initialize Tx/Rx parameters. */ mpc885_reset_spi_params(cpm); dev_dbg(&cpm->ofdev->dev, "spi_ram 0x%p, spi_addr 0x%04x, freq %d\n", cpm->spi_ram, cpm->spi_addr, cpm->freq); dev_dbg(&cpm->ofdev->dev, "tbase 0x%04x, rbase 0x%04x\n", (u8 __iomem *)cpm->tbase - DPRAM_BASE, (u8 __iomem *)cpm->rbase - DPRAM_BASE); cpm_command(cpm->cp_command, CPM_CR_INIT_TRX); /* * PDIV is set to 00 in i2mod, so brgclk/32 is used as input to the * i2c baud rate generator. This is divided by 2 x (DIV + 3) to get * the actual i2c bus frequency. */ out_be32(&pa_reg->cp_pbdir, (in_be32(&pa_reg->cp_pbdir)) | 0x0006 ); //spi out_be32(&pa_reg->cp_pbpar, (in_be32(&pa_reg->cp_pbpar)) | 0x000e );//miso i/p // pc13 cs hip select dsp /* out_be16(&cpm->spi_reg->spmod, 0); out_8(&cpm->spi_reg->spie, 0xff); out_8(&cpm->spi_reg->spim, 0);*/ // out_8(&cpm->spi_reg->spcom, 0xff); out_8(&cpm->spi_reg->spim,I2CER_TXE | I2CER_TXB | I2CER_RXB); out_8(&cpm->spi_reg->spie, 0xff); /* Clear interrupt status */ out_be16(&cpm->spi_reg->spmod, 0x3770 | SPI_PM_VALUE ); //enabling spi out_be16(&cpm->spi_reg->spmod, (in_be16(&cpm->spi_reg->spmod)) | 0x0100 ); //enabling spi return 0; out_muram: for (i = 0; i < CPM_MAXBD; i++) { if (cpm->rxbuf[i]) dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->rxbuf[i], cpm->rxdma[i]); if (cpm->txbuf[i]) dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->txbuf[i], cpm->txdma[i]); } cpm_muram_free(cpm->dp_addr); out_reg: iounmap(cpm->spi_reg); out_ram: if ((cpm->version == 1) && (!cpm->spi_addr)) iounmap(cpm->spi_ram); out_irq: free_irq(cpm->irq, cpm); return ret; } static void mpc885_spi_shutdown(struct cpm_spi *cpm) { int i; struct spi_reg __iomem *spi_reg = cpm->spi_reg; printk ("\nspi shutdown\n"); /* Shut down SPI. */ out_be16(&spi_reg->spmod, (in_be16(&spi_reg->spmod)) & 0xfeff ); //disabling spi out_8(&spi_reg->spim, 0x00); /* Disable all interrupts */ out_8(&spi_reg->spie, 0xff); free_irq(cpm->irq, cpm); /* Free all memory */ for (i = 0; i < CPM_MAXBD; i++) { dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->rxbuf[i], cpm->rxdma[i]); dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, cpm->txbuf[i], cpm->txdma[i]); } cpm_muram_free(cpm->dp_addr); iounmap(cpm->spi_reg); if ((cpm->version == 1) && (!cpm->spi_addr)) iounmap(cpm->spi_ram); } static int spi_open (struct inode *inode, struct file *filep) { return 0; } static ssize_t spi_read (struct file *filep, char __user *buf, size_t count, loff_t *off) { int ret =0,i; unsigned char *rxptr; cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; struct spi_ram __iomem *spi_ram = cpm->spi_ram; iop8xx_t __iomem *pa_reg = immr_map(im_ioport); // printk ("\n Spi Read 0: \n"); tbdf = cpm->tbase; rbdf = cpm->rbase; out_be16(&pa_reg->iop_pcdat, (in_be16(&pa_reg->iop_pcdat)) & 0xfffb ); // pc13 as low for dsp if (count > 8192) count = 8192; // printk ("\n Spi Read 1: \n"); out_be16(&spi_ram->rbptr, in_be16(&spi_ram->rbase)); out_be16(&spi_ram->tbptr, in_be16(&spi_ram->tbase)); out_be16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP| BD_SC_READY | BD_SC_INTRPT); out_be16(&tbdf->cbd_datlen, count); out_be16(&rbdf->cbd_sc, BD_SC_WRAP | BD_SC_INTRPT | BD_SC_EMPTY); out_be16(&rbdf->cbd_datlen, count); // cpm->txbuf[0] = (u_char*)(((uint)cpm->txbuf[0] +15) & ~15); for(i =0;itxbuf[i] =0x10 + i *3; // memset(cpm->txbuf[0], 0x55, count); /* Begin transmission */ out_8(&cpm->spi_reg->spcom, 0x80); // printk ("\n Spi Read 2: \n"); // wait_event(cpm->spi_wait, (!(in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY))); ret = wait_event_timeout(cpm->spi_wait, !(in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY), 1 * HZ); if (ret == 0) { printk ("\n Spi wait event timeout : \n"); ret = -EREMOTEIO; goto out_err; } udelay (30); printk ("\n Spi Read 3 : \n"); cpm->rxbuf[0] = (u_char *) (((ulong) cpm->rxbuf[0] + 1) & ~1); rxptr = (unsigned char *) cpm->rxbuf[0]; for (i=0; i < count; i++) { printk(" %x",*rxptr); rxptr++; } printk ("\n"); /* * Skip address byte */ ret = copy_to_user(buf, cpm->rxbuf[0],count); printk ("\n Spi Read 4%d : \n",ret); // out_be16(&pa_reg->iop_pcdat, (in_be16(&pa_reg->iop_pcdat)) | 0x0004 ); // pc13 as high for dsp out_err: mpc885_spi_force_close(); return ret; } static ssize_t spi_write (struct file *filep, const char __user *buf, size_t count, loff_t *off) { char *tmp ; cbd_t __iomem *tbdf; cbd_t __iomem *rbdf; struct spi_ram __iomem *spi_ram = cpm->spi_ram; iop8xx_t __iomem *pa_reg = immr_map(im_ioport); tbdf = cpm->tbase; rbdf = cpm->rbase; printk ("\nin driver spi write\n"); if (count > 8192) count = 8192; out_be16(&spi_ram->rbptr, in_be16(&spi_ram->rbase)); out_be16(&spi_ram->tbptr, in_be16(&spi_ram->tbase)); out_be16(&pa_reg->iop_pcdat, (in_be16(&pa_reg->iop_pcdat)) & 0xfffb ); // pc13 as low for dsp out_be16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP| BD_SC_READY | BD_SC_INTRPT); out_be16(&tbdf->cbd_datlen, count); out_be16(&rbdf->cbd_sc, BD_SC_WRAP | BD_SC_INTRPT | BD_SC_EMPTY); out_be16(&rbdf->cbd_datlen, 0); if(copy_from_user(cpm->txbuf[0], buf, count)) { return -EFAULT; } /* Begin transmission */ out_8(&cpm->spi_reg->spcom, 0x80); wait_event(cpm->spi_wait,!(in_be16(&tbdf->cbd_sc) & BD_SC_READY)); // out_be16(&pa_reg->iop_pcdat, (in_be16(&pa_reg->iop_pcdat)) | 0x0004 ); // pc13 as high for dsp return 0; } static struct file_operations spiops = { .open = spi_open, .read = spi_read, .write = spi_write, }; static int __devinit mpc885_spi_probe(struct of_device *ofdev, const struct of_device_id *match) { int result; iop8xx_t __iomem *pa_reg = immr_map(im_ioport); printk ("\n*********in mpc885 spi probe**************\n"); cpm = kzalloc(sizeof(struct cpm_spi), GFP_KERNEL); if (!cpm) return -ENOMEM; cpm->ofdev = ofdev; dev_set_drvdata(&ofdev->dev, cpm); result = mpc885_spi_setup(cpm); if (result) { printk("Unable to init hardware\n"); goto out_free; } out_be16(&pa_reg->iop_pcdir, (in_be16(&pa_reg->iop_pcdir)) | 0x0004 ); //pc13 //dsp chip out_be16(&pa_reg->iop_pcpar, (in_be16(&pa_reg->iop_pcpar)) & 0xfffb ); /* * Register with char */ result = register_chrdev(MPC885_SPI_MAJOR, "spi_mpc885", &spiops); if (result) { printk("Unable to register spi char dev driver\n"); goto out_shut; } return 0; out_shut: mpc885_spi_shutdown(cpm); out_free: dev_set_drvdata(&ofdev->dev, NULL); kfree(cpm); return result; } static int __devexit mpc885_spi_remove(struct of_device *ofdev) { struct cpm_spi *cpm = dev_get_drvdata(&ofdev->dev); unregister_chrdev(MPC885_SPI_MAJOR, "spi_mpc885"); mpc885_spi_shutdown(cpm); dev_set_drvdata(&ofdev->dev, NULL); kfree(cpm); return 0; } static const struct of_device_id mpc885_spi_match[] = { { .compatible = "fsl,mpc885-spi", }, {}, }; static struct of_platform_driver mpc885_spi_driver = { .match_table = mpc885_spi_match, .probe =mpc885_spi_probe, .remove = __devexit_p(mpc885_spi_remove), .driver = { .name = "fsl-spi-mpc885", .owner = THIS_MODULE, } }; static int __init mpc885_spi_init(void) { return of_register_platform_driver(&mpc885_spi_driver); } static void __exit mpc885_spi_exit(void) { of_unregister_platform_driver(&mpc885_spi_driver); } module_init(mpc885_spi_init); module_exit(mpc885_spi_exit); MODULE_DESCRIPTION("SPI-Bus adapter routines for MPC885 board"); MODULE_LICENSE("GPL");