📄 i2c1.c
字号:
ByteToRcv = 0; return I2CBUFFFULL; } return I2CSUCCESS; } return I2CBUFFFULL;}/****************** Device Control Function *************//********************************************************* * function: I2C_Init * * description: Initialize I2C unit with desired frequency divider, * master's listening address, with interrupt enabled * or disabled. * * note: ********************************************************/static I2CStatus I2C_Init (unsigned int eumbbar, unsigned char fdr, /* frequency divider */ unsigned char slave_addr, /* driver's address used for receiving */ unsigned int en_int){ /* 1 - enable I2C interrupt * 0 - disable I2C interrup */ I2C_CTRL ctrl; unsigned int tmp;#ifdef I2CDBG0 PRINT ("%s(%d): I2C_Init enter\n", __FILE__, __LINE__);#endif ctrl = I2C_Get_Ctrl (eumbbar); /* disable the I2C module before we change everything */ ctrl.men = 0; I2C_Set_Ctrl (eumbbar, ctrl); /* set the frequency diver */ tmp = load_runtime_reg (eumbbar, I2CFDR); tmp = (tmp & 0xffffffc0) | (fdr & 0x3f); store_runtime_reg (eumbbar, I2CFDR, tmp); /* Set our listening (slave) address */ tmp = load_runtime_reg (eumbbar, I2CADR); tmp = (tmp & 0xffffff01) | ((slave_addr & 0x7f) << 1); store_runtime_reg (eumbbar, I2CADR, tmp); /* enable I2C with desired interrupt setting */ ctrl.men = 1; ctrl.mien = en_int & 0x1; I2C_Set_Ctrl (eumbbar, ctrl);#ifdef I2CDBG0 PRINT ("%s(%d): I2C_Init exit\n", __FILE__, __LINE__);#endif return I2CSUCCESS;}/***************************************** * function I2c_Get_Stat * * description: Query I2C Status, i.e., read I2CSR * ****************************************/static I2C_STAT I2C_Get_Stat (unsigned int eumbbar){ unsigned int temp; I2C_STAT stat; temp = load_runtime_reg (eumbbar, I2CSR);#ifdef I2CDBG0 PRINT ("%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp);#endif stat.rsrv0 = (temp & 0xffffff00) >> 8; stat.mcf = (temp & 0x00000080) >> 7; stat.maas = (temp & 0x00000040) >> 6; stat.mbb = (temp & 0x00000020) >> 5; stat.mal = (temp & 0x00000010) >> 4; stat.rsrv1 = (temp & 0x00000008) >> 3; stat.srw = (temp & 0x00000004) >> 2; stat.mif = (temp & 0x00000002) >> 1; stat.rxak = (temp & 0x00000001); return stat;}/********************************************* * function: I2c_Set_Ctrl * * description: Change I2C Control bits, * i.e., write to I2CCR * ********************************************/static void I2C_Set_Ctrl (unsigned int eumbbar, I2C_CTRL ctrl){ /* new control value */ unsigned int temp = load_runtime_reg (eumbbar, I2CCR); temp &= 0xffffff03; temp |= ((ctrl.men & 0x1) << 7); temp |= ((ctrl.mien & 0x1) << 6); temp |= ((ctrl.msta & 0x1) << 5); temp |= ((ctrl.mtx & 0x1) << 4); temp |= ((ctrl.txak & 0x1) << 3); temp |= ((ctrl.rsta & 0x1) << 2);#ifdef I2CDBG0 PRINT ("%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp);#endif store_runtime_reg (eumbbar, I2CCR, temp);}/***************************************** * function: I2C_Get_Ctrl * * description: Query I2C Control bits, * i.e., read I2CCR *****************************************/static I2C_CTRL I2C_Get_Ctrl (unsigned int eumbbar){ union { I2C_CTRL ctrl; unsigned int temp; } s; s.temp = load_runtime_reg (eumbbar, I2CCR);#ifdef I2CDBG0 PRINT ("%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp);#endif return s.ctrl;}/**************************************** * function: I2C_Slave_Addr * * description: Process slave address phase. * return I2CSUCCESS if no error * * note: Precondition for calling this function: * I2CSR(MIF) == 1 && * I2CSR(MAAS) == 1 ****************************************/static I2CStatus I2C_Slave_Addr (unsigned int eumbbar){ I2C_STAT stat = I2C_Get_Stat (eumbbar); I2C_CTRL ctrl = I2C_Get_Ctrl (eumbbar); if (stat.srw == 1) { /* we are asked to xmit */ ctrl.mtx = 1; I2C_Set_Ctrl (eumbbar, ctrl); /* set MTX */ return I2C_Slave_Xmit (eumbbar); } /* we are asked to receive data */ ctrl.mtx = 0; I2C_Set_Ctrl (eumbbar, ctrl); (void) load_runtime_reg (eumbbar, I2CDR); /* do a fake read to start */ return I2CADDRESS;}/*********************************************** * function: I2C_ISR * * description: I2C Interrupt service routine * * note: Precondition: * I2CSR(MIF) == 1 **********************************************/static I2CStatus I2C_ISR (unsigned int eumbbar){ I2C_STAT stat; I2C_CTRL ctrl;#ifdef I2CDBG0 PRINT ("%s(%d): I2C_ISR\n", __FILE__, __LINE__);#endif stat = I2C_Get_Stat (eumbbar); ctrl = I2C_Get_Ctrl (eumbbar); /* clear MIF */ stat.mif = 0; /* Now let see what kind of event this is */ if (stat.mcf == 1) { /* transfer compete */ /* clear the MIF bit */ I2C_Set_Stat (eumbbar, stat); if (ctrl.msta == 1) { /* master */ if (ctrl.mtx == 1) { /* check if this is the address phase for master receive */ if (MasterRcvAddress == 1) { /* Yes, it is the address phase of master receive */ ctrl.mtx = 0; /* now check how much we want to receive */ if (ByteToRcv == 1 && RcvBufFulStop == 1) { ctrl.txak = 1; } I2C_Set_Ctrl (eumbbar, ctrl); (void) load_runtime_reg (eumbbar, I2CDR); /* fake read first */ MasterRcvAddress = 0; return I2CADDRESS; } /* master xmit */ if (stat.rxak == 0) { /* slave has acknowledged */ return I2C_Master_Xmit (eumbbar); } /* slave has not acknowledged yet, generate a STOP */ if (XmitBufEmptyStop == 1) { ctrl.msta = 0; I2C_Set_Ctrl (eumbbar, ctrl); } return I2CSUCCESS; } /* master receive */ return I2C_Master_Rcv (eumbbar); } /* slave */ if (ctrl.mtx == 1) { /* slave xmit */ if (stat.rxak == 0) { /* master has acknowledged */ return I2C_Slave_Xmit (eumbbar); } /* master has not acknowledged, wait for STOP */ /* do nothing for preventing bus from hung */ return I2CSUCCESS; } /* slave rcv */ return I2C_Slave_Rcv (eumbbar); } else if (stat.maas == 1) { /* received a call from master */ /* clear the MIF bit */ I2C_Set_Stat (eumbbar, stat); /* master is calling us, process the address phase */ return I2C_Slave_Addr (eumbbar); } else { /* has to be arbitration lost */ stat.mal = 0; I2C_Set_Stat (eumbbar, stat); ctrl.msta = 0; /* return to receive mode */ I2C_Set_Ctrl (eumbbar, ctrl); } return I2CSUCCESS;}/****************************************************** * function: I2C_Set_Stat * * description: modify the I2CSR * *****************************************************/static void I2C_Set_Stat (unsigned int eumbbar, I2C_STAT stat){ union { unsigned int val; I2C_STAT stat; } s_tmp; union { unsigned int val; I2C_STAT stat; } s; s.val = load_runtime_reg (eumbbar, I2CSR); s.val &= 0xffffff08; s_tmp.stat = stat; s.val |= (s_tmp.val & 0xf7);#ifdef I2CDBG0 PRINT ("%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val);#endif store_runtime_reg (eumbbar, I2CSR, s.val);}/****************************************************** * The following are routines to glue the rest of * PPCBoot to the Sandpoint I2C driver. *****************************************************/void i2c_init (int speed, int slaveadd){#ifdef DEBUG I2C_Initialize (0x7f, 0, (void *) printf);#else I2C_Initialize (0x7f, 0, 0);#endif}int i2c_probe (uchar chip){ int tmp; /* * Try to read the first location of the chip. The underlying * driver doesn't appear to support sending just the chip address * and looking for an <ACK> back. */ udelay(10000); return i2c_read (chip, 0, 1, (char *)&tmp, 1);}int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len){ I2CStatus status; uchar xaddr[4]; if (alen > 0) { xaddr[0] = (addr >> 24) & 0xFF; xaddr[1] = (addr >> 16) & 0xFF; xaddr[2] = (addr >> 8) & 0xFF; xaddr[3] = addr & 0xFF; status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen, &xaddr[4 - alen], I2C_NO_STOP, 1, I2C_NO_RESTART); if (status != I2C_SUCCESS) { PRINT ("i2c_read: can't send data address for read\n"); return 1; } } /* The data transfer will be a continuation. */ status = I2C_do_buffer (0, I2C_MASTER_RCV, chip, len, buffer, I2C_STOP, 1, (alen > 0 ? I2C_RESTART : I2C_NO_RESTART)); if (status != I2C_SUCCESS) { PRINT ("i2c_read: can't perform data transfer\n"); return 1; } return 0;}int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len){ I2CStatus status; unsigned char dummy_buffer[I2C_RXTX_LEN + 2]; int i; dummy_buffer[0] = addr & 0xFF; if (alen == 2) dummy_buffer[1] = (addr >> 8) & 0xFF; for (i = 0; i < len; i++) dummy_buffer[i + alen] = buffer[i]; status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen + len, dummy_buffer, I2C_STOP, 1, I2C_NO_RESTART);#ifdef CFG_EEPROM_PAGE_WRITE_DELAY_MS udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000);#endif if (status != I2C_SUCCESS) { PRINT ("i2c_write: can't perform data transfer\n"); return 1; } return 0;}uchar i2c_reg_read (uchar i2c_addr, uchar reg){ char buf[1]; i2c_init (0, 0); i2c_read (i2c_addr, reg, 1, buf, 1); return (buf[0]);}void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val){ i2c_init (0, 0); i2c_write (i2c_addr, reg, 1, &val, 1);}#endif /* CONFIG_HARD_I2C */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -