int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode) { int ret, raddr; #if 1 WRITE_S1(SEND_I2C_STOP | ACK); WRITE_S1(SELECT(S0) | ENABLE_SERIAL); vfc_i2c_delay(dev); #endif switch(mode) { case VFC_I2C_READ: raddr = SHIFT(((unsigned int)addr | 0x1)); WRITE_REG(raddr); VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", dev->instance, addr | 0x1)); break; case VFC_I2C_WRITE: raddr = SHIFT((unsigned int)addr & ~0x1); WRITE_REG(raddr); VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", dev->instance, addr & ~0x1)); break; default: return -EINVAL; }; WRITE_S1(SEND_I2C_START); vfc_i2c_delay(dev); ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait for the i2c send to finish here but Sun doesn't, hmm */ if (ret) { printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", dev->instance); return ret; } else if (mode == VFC_I2C_READ) { if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { printk(KERN_WARNING "vfc%d: returned slave address " "mismatch(%x,%x)\n", dev->instance, raddr, ret); } } return 0; }
int vfc_i2c_reset_bus(struct vfc_dev *dev) { VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", dev->instance)); if(dev == NULL) return -EINVAL; if(dev->regs == NULL) return -EINVAL; WRITE_S1(SEND_I2C_STOP); WRITE_S1(SEND_I2C_STOP | ACK); vfc_i2c_delay(dev); WRITE_S1(CLEAR_I2C_BUS); VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", dev->instance, sbus_readl(&dev->regs->i2c_s1))); return 0; }
int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, char *buf, int count) { int ret; if (!(buf && dev && dev->regs)) return -EINVAL; if ((ret = vfc_i2c_wait_for_bus(dev))) { printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); return ret; } if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { WRITE_S1(SEND_I2C_STOP); vfc_i2c_delay(dev); return ret; } while(count--) { ret = vfc_i2c_xmit_byte(dev, buf); switch(ret) { case XMIT_LAST_BYTE: VFC_I2C_DEBUG_PRINTK(("vfc%d: " "Receiver ended transmission with " " %d bytes remaining\n", dev->instance, count)); ret = 0; goto done; break; case 0: break; default: printk(KERN_ERR "vfc%d: " "VFC error while sending byte\n", dev->instance); break; }; buf++; } done: WRITE_S1(SEND_I2C_STOP | ACK); vfc_i2c_delay(dev); return ret; }
int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, int last) { int ret; if (last) { WRITE_REG(NEGATIVE_ACK); VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", dev->instance)); } else { WRITE_S1(ACK); } ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); if(ret) { printk(KERN_ERR "vfc%d: " "VFC recv byte timed out\n", dev->instance); } *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; return ret; }
void vfc_i2c_delay_wakeup(struct vfc_dev *dev) { /* Used to profile code and eliminate too many delays */ VFC_I2C_DEBUG_PRINTK(("vfc%d: Delaying\n", dev->instance)); wake_up(&dev->poll_wait); }