iic.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
- /*
- * BK Id: %F% %I% %G% %U% %#%
- */
- /* Minimal support functions to read configuration from IIC EEPROMS
- * on MPC8xx boards. Originally written for RPGC RPX-Lite.
- * Dan Malek (dmalek@jlc.net).
- */
- #include <linux/types.h>
- #include <asm/uaccess.h>
- #include <asm/mpc8xx.h>
- #include <asm/commproc.h>
- /* IIC functions.
- * These are just the basic master read/write operations so we can
- * examine serial EEPROM.
- */
- void iic_read(uint devaddr, u_char *buf, uint offset, uint count);
- static int iic_init_done;
- static void
- iic_init(void)
- {
- volatile iic_t *iip;
- volatile i2c8xx_t *i2c;
- volatile cpm8xx_t *cp;
- volatile immap_t *immap;
- uint dpaddr;
- immap = (immap_t *)IMAP_ADDR;
- cp = (cpm8xx_t *)&(immap->im_cpm);
- /* Reset the CPM. This is necessary on the 860 processors
- * that may have started the SCC1 ethernet without relocating
- * the IIC.
- * This also stops the Ethernet in case we were loaded by a
- * BOOTP rom monitor.
- */
- cp->cp_cpcr = (CPM_CR_RST | CPM_CR_FLG);
- /* Wait for it.
- */
- while (cp->cp_cpcr & (CPM_CR_RST | CPM_CR_FLG));
- /* Remove any microcode patches. We will install our own
- * later.
- */
- cp->cp_cpmcr1 = 0;
- cp->cp_cpmcr2 = 0;
- cp->cp_cpmcr3 = 0;
- cp->cp_cpmcr4 = 0;
- cp->cp_rccr = 0;
- iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
- i2c = (i2c8xx_t *)&(immap->im_i2c);
- /* Initialize Port B IIC pins.
- */
- cp->cp_pbpar |= 0x00000030;
- cp->cp_pbdir |= 0x00000030;
- cp->cp_pbodr |= 0x00000030;
- /* Initialize the parameter ram.
- */
- /* Allocate space for a two transmit and one receive buffer
- * descriptor in the DP ram.
- * For now, this address seems OK, but it may have to
- * change with newer versions of the firmware.
- */
- dpaddr = 0x0840;
- /* Set up the IIC parameters in the parameter ram.
- */
- iip->iic_tbase = dpaddr;
- iip->iic_rbase = dpaddr + (2 * sizeof(cbd_t));
- iip->iic_tfcr = SMC_EB;
- iip->iic_rfcr = SMC_EB;
- /* This should really be done by the reader/writer.
- */
- iip->iic_mrblr = 128;
- /* Initialize Tx/Rx parameters.
- */
- cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG;
- while (cp->cp_cpcr & CPM_CR_FLG);
- /* Select an arbitrary address. Just make sure it is unique.
- */
- i2c->i2c_i2add = 0x34;
- /* Make clock run maximum slow.
- */
- i2c->i2c_i2brg = 7;
- /* Disable interrupts.
- */
- i2c->i2c_i2cmr = 0;
- i2c->i2c_i2cer = 0xff;
- /* Enable SDMA.
- */
- immap->im_siu_conf.sc_sdcr = 1;
- iic_init_done = 1;
- }
- /* Read from IIC.
- * Caller provides device address, memory buffer, and byte count.
- */
- static u_char iitemp[32];
- void
- iic_read(uint devaddr, u_char *buf, uint offset, uint count)
- {
- volatile iic_t *iip;
- volatile i2c8xx_t *i2c;
- volatile cbd_t *tbdf, *rbdf;
- volatile cpm8xx_t *cp;
- volatile immap_t *immap;
- u_char *tb;
- uint temp;
- /* If the interface has not been initialized, do that now.
- */
- if (!iic_init_done)
- iic_init();
- immap = (immap_t *)IMAP_ADDR;
- cp = (cpm8xx_t *)&(immap->im_cpm);
- iip = (iic_t *)&cp->cp_dparam[PROFF_IIC];
- i2c = (i2c8xx_t *)&(immap->im_i2c);
- tbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_tbase];
- rbdf = (cbd_t *)&cp->cp_dpmem[iip->iic_rbase];
- /* Send a "dummy write" operation. This is a write request with
- * only the offset sent, followed by another start condition.
- * This will ensure we start reading from the first location
- * of the EEPROM.
- */
- tb = iitemp;
- tb = (u_char *)(((uint)tb + 15) & ~15);
- tbdf->cbd_bufaddr = (int)tb;
- *tb = devaddr & 0xfe; /* Device address */
- *(tb+1) = offset; /* Offset */
- tbdf->cbd_datlen = 2; /* Length */
- tbdf->cbd_sc =
- BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
- i2c->i2c_i2mod = 1; /* Enable */
- i2c->i2c_i2cer = 0xff;
- i2c->i2c_i2com = 0x81; /* Start master */
- /* Wait for IIC transfer.
- */
- #if 0
- while ((i2c->i2c_i2cer & 3) == 0);
- if (tbdf->cbd_sc & BD_SC_READY)
- printf("IIC ra complete but tbuf readyn");
- #else
- temp = 10000000;
- while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
- temp--;
- #if 0
- /* We can't do this...there is no serial port yet!
- */
- if (temp == 0) {
- printf("Timeout reading EEPROMn");
- return;
- }
- #endif
- #endif
-
- /* Chip errata, clear enable.
- */
- i2c->i2c_i2mod = 0;
- /* 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).
- */
- tbdf->cbd_bufaddr = (int)tb;
- *tb = devaddr | 1; /* Device address */
- rbdf->cbd_bufaddr = (uint)buf; /* Desination buffer */
- tbdf->cbd_datlen = rbdf->cbd_datlen = count + 1; /* Length */
- tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP | BD_IIC_START;
- rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
- /* Chip bug, set enable here.
- */
- i2c->i2c_i2mod = 1; /* Enable */
- i2c->i2c_i2cer = 0xff;
- i2c->i2c_i2com = 0x81; /* Start master */
- /* Wait for IIC transfer.
- */
- #if 0
- while ((i2c->i2c_i2cer & 1) == 0);
- if (rbdf->cbd_sc & BD_SC_EMPTY)
- printf("IIC read complete but rbuf emptyn");
- #else
- temp = 10000000;
- while ((tbdf->cbd_sc & BD_SC_READY) && (temp != 0))
- temp--;
- #endif
-
- /* Chip errata, clear enable.
- */
- i2c->i2c_i2mod = 0;
- }