コード例 #1
0
ファイル: rockchip.c プロジェクト: coreboot/depthcharge
static int i2c_read(RkI2cReg *reg_addr, I2cSeg segment)
{
	int res = 0;
	uint8_t *data = segment.buf;
	int timeout = I2C_TIMEOUT_US;
	unsigned int bytes_remaining = segment.len;
	unsigned int bytes_transfered = 0;
	unsigned int words_transfered = 0;
	unsigned int rxdata = 0;
	unsigned int con = 0;
	unsigned int i, j;

	writel(I2C_8BIT | segment.chip << 1 | 1, &reg_addr->i2c_mrxaddr);
	writel(0, &reg_addr->i2c_mrxraddr);
	con = I2C_MODE_TRX | I2C_EN | I2C_ACT2NAK;
	while (bytes_remaining) {
		bytes_transfered = MIN(bytes_remaining, 32);
		bytes_remaining -= bytes_transfered;
		if(!bytes_remaining)
			con |= I2C_EN | I2C_NAK;
		words_transfered = ALIGN_UP(bytes_transfered, 4) / 4;

		writel(I2C_CLEANI, &reg_addr->i2c_ipd);
		writel(con, &reg_addr->i2c_con);
		writel(bytes_transfered, &reg_addr->i2c_mrxcnt);

		timeout = I2C_TIMEOUT_US;
		while (timeout--) {
			if (readl(&reg_addr->i2c_ipd) & I2C_NAKRCVI) {
				writel(0, &reg_addr->i2c_mrxcnt);
				writel(0, &reg_addr->i2c_con);
				return I2C_NOACK;
			}
			if (readl(&reg_addr->i2c_ipd) & I2C_MBRFI)
				break;
			udelay(1);
		}
		if (timeout <= 0) {
			i2c_err("I2C Read::Recv Data Timeout\n");
			writel(0, &reg_addr->i2c_mrxcnt);
			writel(0, &reg_addr->i2c_con);
			return  I2C_TIMEOUT;
		}

		for (i = 0; i < words_transfered; i++) {
			rxdata = readl(&reg_addr->rxdata[i]);
			i2c_info("I2c Read::RXDATA[%d] = 0x%x\n", i, rxdata);
			for (j = 0; j < 4; j++) {
				if ((i * 4 + j) == bytes_transfered)
					break;
				*data++ = (rxdata >> (j * 8)) & 0xff;
			}
		}
		con = I2C_MODE_RX | I2C_EN | I2C_ACT2NAK;
	}
	return res;
}
コード例 #2
0
ファイル: i2c.c プロジェクト: WingBot/Senior-Project
// send repeated start condition
void i2cf_rstart() {
   if( (TWSR & 0xF8) == 0x28 ) {
      TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA) | (1<<TWIE);
      i2c_next = i2cf_raddress;
      i2c_state = 8;
   } else {
      i2c_err();
   }
}
コード例 #3
0
ファイル: i2c.c プロジェクト: WingBot/Senior-Project
// write i2c address
void i2cf_address() {
   if( (TWSR & 0xF8) == 0x08 ) {
      TWDR = i2c_address;
      TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
      i2c_next = i2cf_register;
      i2c_state = 13;
   } else {
      i2c_err();
   }
}
コード例 #4
0
ファイル: i2c.c プロジェクト: WingBot/Senior-Project
// send i2c read address
void i2cf_raddress() {
   if( (TWSR & 0xF8) == 0x10 ) {
      TWDR = i2c_address | 1;
      TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
      i2c_next = i2cf_read;
      i2c_state = 7;
   } else {
      i2c_err();
   }
}
コード例 #5
0
ファイル: rockchip.c プロジェクト: coreboot/depthcharge
static int i2c_write(RkI2cReg *reg_addr, I2cSeg segment)
{
	int res = 0;
	uint8_t *data = segment.buf;
	int timeout = I2C_TIMEOUT_US;
	int bytes_remaining = segment.len + 1;
	int bytes_transfered = 0;
	int words_transfered = 0;
	unsigned int i;
	unsigned int j = 1;
	u32 txdata = 0;

	txdata |= (segment.chip << 1);
	while (bytes_remaining) {
		bytes_transfered = MIN(bytes_remaining, 32);
		words_transfered = ALIGN_UP(bytes_transfered, 4) / 4;
		for (i = 0; i < words_transfered; i++) {
			do {
				if ((i * 4 + j) == bytes_transfered)
					break;
				txdata |= (*data++) << (j * 8);
			} while (++j < 4);
			writel(txdata, &reg_addr->txdata[i]);
			j = 0;
			i2c_info("I2c Write::TXDATA[%d] = 0x%x\n", i, txdata);
			txdata = 0;
		}

		writel(I2C_CLEANI, &reg_addr->i2c_ipd);
		writel(I2C_EN | I2C_MODE_TX | I2C_ACT2NAK, &reg_addr->i2c_con);
		writel(bytes_transfered, &reg_addr->i2c_mtxcnt);

		timeout = I2C_TIMEOUT_US;
		while (timeout--) {
			if (readl(&reg_addr->i2c_ipd) & I2C_NAKRCVI) {
				writel(0, &reg_addr->i2c_mtxcnt);
				writel(0, &reg_addr->i2c_con);
				return I2C_NOACK;
			}
			if (readl(&reg_addr->i2c_ipd) & I2C_MBTFI)
				break;
			udelay(1);
		}

		if (timeout <= 0) {
			i2c_err("I2C Write::Send Data Timeout\n");
			writel(0, &reg_addr->i2c_mtxcnt);
			writel(0, &reg_addr->i2c_con);
			return  I2C_TIMEOUT;
		}

		bytes_remaining -= bytes_transfered;
	}
	return res;
}
コード例 #6
0
ファイル: i2c.c プロジェクト: WingBot/Senior-Project
// write i2c data
void i2cf_wdata() {
   if( (TWSR & 0xF8) == 0x28 ) {
      TWDR = *i2c_data;
      ++i2c_data;
      --i2c_data_sz;
      if( i2c_data_sz == 0 ) {
         i2c_next = i2cf_wstop;
         i2c_state = 10;
      }
      TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
   } else {
      i2c_err();
   }
}
コード例 #7
0
static int rk29_wait_event(struct rk29_i2c_data *i2c,
					enum rk29_event mr_event)
{
	int ret = 0;

	if(unlikely(irqs_disabled()))
	{
		i2c_err(i2c->dev, "irqs are disabled on this system!\n");
		return -EIO;
	}
	i2c->cmd_err = RK29_ERROR_NONE;
	i2c->cmd_event = mr_event;
	rk29_i2c_enable_irqs(i2c);
	if(i2c->mode == I2C_MODE_IRQ)
	{
		ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete,
								usecs_to_jiffies(i2c->ack_timeout));
	}
	else
	{
		i2c->poll_status = 0;
		ret = wait_for_completion_poll_timeout(i2c);
	}
	if(ret < 0)
	{
		i2c_err(i2c->dev, "i2c wait for event %04x, retrun %d \n", mr_event, ret);
		return ret;
	}
	if(ret == 0)
	{
		i2c_err(i2c->dev, "i2c wait for envent timeout, but not return -ETIMEDOUT\n");
		return 0;
		//return -ETIMEDOUT;
	}
	return 0;
}
コード例 #8
0
ファイル: i2c.c プロジェクト: WingBot/Senior-Project
// write i2c register
void i2cf_register() {
   if( (TWSR & 0xF8) == 0x18 ) {
      TWDR = i2c_register;
      TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
      if( i2c_mode == WRITE ) {
         i2c_next = i2cf_wdata;
         i2c_state = 11;
      } else {
         i2c_next = i2cf_rstart;
         i2c_state = 12;
      }
   } else {
      i2c_err();
   }
}
コード例 #9
0
ファイル: rockchip.c プロジェクト: coreboot/depthcharge
static int i2c_send_stop(RkI2cReg *reg_addr)
{
	int res = 0;
	int timeout = I2C_TIMEOUT_US;
	i2c_info("I2c Stop::Send Stop bit\n");
	writel(I2C_CLEANI, &reg_addr->i2c_ipd);
	writel(I2C_EN | I2C_STOP, &reg_addr->i2c_con);
	while (timeout--) {
		if (readl(&reg_addr->i2c_ipd) & I2C_STOPI)
			break;
		udelay(1);
	}
	writel(0, &reg_addr->i2c_con);
	if (timeout <= 0) {
		i2c_err("I2C Stop::Send Stop Bit Timeout\n");
		res = I2C_TIMEOUT;
	}

	return res;
}
コード例 #10
0
static int rk29_event_occurred(struct rk29_i2c_data *i2c)
{
	unsigned long isr, lsr;

	isr = readl(i2c->regs + I2C_ISR);
	lsr = readl(i2c->regs + I2C_LSR);
	i2c_dbg(i2c->dev,"event occurred, isr = %lx, lsr = %lx\n", isr, lsr);
	if(isr & I2C_ISR_ARBITR_LOSE)
	{
		writel(0, i2c->regs + I2C_ISR);
		i2c->cmd_err = RK29_ERROR_ARBITR_LOSE;
		i2c_err(i2c->dev, "<error>arbitration loss\n");
		return 0;
	}

	switch(i2c->cmd_event)
	{
		case RK29_EVENT_MTX_RCVD_ACK:
			if(isr & I2C_ISR_MTX_RCVD_ACK)
			{
				isr &= ~I2C_ISR_MTX_RCVD_ACK;
				writel(isr, i2c->regs + I2C_ISR);
				return 1;
			}
		break;
		case RK29_EVENT_MRX_NEED_ACK:
			if(isr & I2C_ISR_MRX_NEED_ACK)
			{
				isr &= ~I2C_ISR_MRX_NEED_ACK;
				writel(isr, i2c->regs + I2C_ISR);
				return 1;
			}
			break;
		default:
			break;
	}
	writel(0, i2c->regs + I2C_ISR);
	i2c->cmd_err = RK29_ERROR_UNKNOWN;
	return 0;
}
コード例 #11
0
static int rk29_send_2nd_addr(struct rk29_i2c_data *i2c,
						struct i2c_msg *msg, int start)
{
	int ret = 0;
	unsigned long lsr;
	unsigned long addr_2nd = msg->addr & 0xff;

	i2c_dbg(i2c->dev, "i2c send addr_2nd: %lx\n", addr_2nd);	
	writel(addr_2nd, i2c->regs + I2C_MTXR);
	if(i2c->mode == I2C_MODE_IRQ)
		INIT_COMPLETION(i2c->cmd_complete);
	writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR);
	rk29_set_ack(i2c);
	
	if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0)
	{
		i2c_err(i2c->dev, "after sent addr_2nd, i2c wait for ACK timeout\n");
		return ret;
	}
	lsr = readl(i2c->regs + I2C_LSR);
	if((lsr & I2C_LSR_RCV_NAK) && !(msg->flags & I2C_M_IGNORE_NAK))
		return -EINVAL;
	return ret;
}
コード例 #12
0
ファイル: i2c.c プロジェクト: WingBot/Senior-Project
void i2cf_read() {
   if( (TWSR & 0xF8) == 0x40 ) {
      // if we sent an address, wait for data
      --i2c_data_sz;
      if( i2c_data_sz > 0 ) {
         // we want more data; transmit ack
         TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA) | (1<<TWIE);
      } else {
         // the next byte will be the last
         TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
      }
      i2c_next = i2cf_read;
      i2c_state = 3;
   } else if( (TWSR & 0xF8) == 0x50 ) {
      // if we received data, wait for more data or nak
      i2c_data[i2c_data_pos++] = TWDR;
      --i2c_data_sz;
      if( i2c_data_sz > 0 ) {
         // we want more data; transmit ack
         TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA) | (1<<TWIE);
      } else {
         // the next byte will be the last
         TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE);
      }
      i2c_next = i2cf_read;
      i2c_state = 4;
   } else if( (TWSR & 0xF8) == 0x58 ) {
      // we got our last byte and sent nak
      i2c_data[i2c_data_pos] = TWDR;
      TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO) | (1<<TWIE);
      i2c_ready = 1;
      i2c_next = i2c_none;
      i2c_state = 5;
      sei();
      if(i2c_r_callback) {
         void (*tmp_callback)(uint8_t*) = i2c_r_callback;
         i2c_r_callback = 0;
         tmp_callback(i2c_data);
      } else {
         i2c_err();
      }
   } else if( (TWSR & 0xF8) == 0x08 ) {
      // Start sent. shouldn't happen
      i2c_err();
   } else if( (TWSR & 0xF8) == 0x10 ) {
      // repeated start sent. shouldn't happen
      //led_on();
      i2c_err();
   } else if( (TWSR & 0xF8) == 0x38 ) {
      // arbitration lost or NAK
      i2c_err();
   } else if( (TWSR & 0xF8) == 0x48 ) {
      // SLA+R sent; NAK received
      // generate a stop condition
      //TWCR = (1<<TWSTA) | (1<<TWSTO) | (1<<TWINT);
      //i2c_next = i2cf_address;
      i2c_err();
      i2c_state = 6;
   } else {
      i2c_err();
   }
}
コード例 #13
0
static int __init i2c_davinci_init(void)
{
	int status;
	struct device 	*dev = NULL;

	DEB0("%s %s", __TIME__, __DATE__);

	DEB1("i2c_davinci_init()\n");

        davinci_i2c_fix_ths7353_lockup( );

#if 0
	if (i2c_davinci_busFreq > 200)
		i2c_davinci_busFreq = 400;	/*Fast mode */
	else
		i2c_davinci_busFreq = 100;	/*Standard mode */
#endif

	i2c_clock = clk_get (dev, "I2CCLK");	

	if (i2c_clock == NULL)
        	return -1;
        
	clk_use (i2c_clock);
	clk_enable (i2c_clock);
	i2c_davinci_inputClock = clk_get_rate (i2c_clock);

	DEB1 ("IP CLOCK = %ld\n", i2c_davinci_inputClock);

	memset(&i2c_davinci_dev, 0, sizeof(i2c_davinci_dev));

	i2c_davinci_dev.regs = (davinci_i2cregsovly)I2C_BASE;

	status = (int)request_region(I2C_BASE, I2C_IOSIZE, MODULE_NAME);
	if (!status) {
		i2c_err("I2C is already in use\n");
		return -ENODEV;
	}

	status = request_irq(IRQ_I2C, i2c_davinci_isr, 0, MODULE_NAME,
			     &i2c_davinci_dev);
	if (status) {
		i2c_err("failed to request I2C IRQ");
		goto do_release_region;
	}

	i2c_set_adapdata(&i2c_davinci_adap, &i2c_davinci_dev);
	status = i2c_add_adapter(&i2c_davinci_adap);
	if (status) {
		i2c_err("failed to add adapter");
		goto do_free_irq;
		return status;
	}

	i2c_davinci_reset(&i2c_davinci_dev);

	if (driver_register(&davinci_i2c_driver) != 0)
		printk(KERN_ERR "Driver register failed for davinci_i2c\n");
	if (platform_device_register(&davinci_i2c_device) != 0) {
		printk(KERN_ERR "Device register failed for i2c\n");
		driver_unregister(&davinci_i2c_driver);
	}

	return 0;

      do_free_irq:
	free_irq(IRQ_I2C, &i2c_davinci_dev);
      do_release_region:
	release_region(I2C_BASE, I2C_IOSIZE);

	return status;
}
コード例 #14
0
static int __init i2c_davinci_init(void)
{
	int status;
	struct device 	*dev = NULL;

	DEB0("%s %s", __TIME__, __DATE__);

	DEB1("i2c_davinci_init()");

	if (cpu_is_davinci_dm6467())
		davinci_i2c_expander_op (0x3A, I2C_INT_DM646X, 0);

        /* 
	 * NOTE: On DaVinci EVM, the i2c bus frequency is set to 20kHz
	 *       so that the MSP430, which is doing software i2c, has
	 *       some extra processing time
	 */
	if (machine_is_davinci_evm())
		i2c_davinci_busFreq = 20;
	else if (machine_is_davinci_dm6467_evm())
		i2c_davinci_busFreq = 100;
	else if (i2c_davinci_busFreq > 200)
		i2c_davinci_busFreq = 400;	/*Fast mode */
	else
		i2c_davinci_busFreq = 100;	/*Standard mode */

	i2c_clock = clk_get (dev, "I2CCLK");

	if (IS_ERR(i2c_clock))
        	return -1;

	clk_use (i2c_clock);
	clk_enable (i2c_clock);
	i2c_davinci_inputClock = clk_get_rate (i2c_clock);

	DEB1 ("IP CLOCK = %ld", i2c_davinci_inputClock);

	memset(&i2c_davinci_dev, 0, sizeof(i2c_davinci_dev));
	init_waitqueue_head(&i2c_davinci_dev.cmd_wait);

	i2c_davinci_dev.regs = (davinci_i2cregsovly)I2C_BASE;

	status = (int)request_region(I2C_BASE, I2C_IOSIZE, MODULE_NAME);
	if (!status) {
		i2c_err("I2C is already in use\n");
		return -ENODEV;
	}

	status = request_irq(IRQ_I2C, i2c_davinci_isr, 0, "i2c",
			     &i2c_davinci_dev);
	if (status) {
		i2c_err("failed to request I2C IRQ");
		goto do_release_region;
	}

	i2c_set_adapdata(&i2c_davinci_adap, &i2c_davinci_dev);
	status = i2c_add_adapter(&i2c_davinci_adap);
	if (status) {
		i2c_err("failed to add adapter");
		goto do_free_irq;
	}

	i2c_davinci_reset(&i2c_davinci_dev);

	if (driver_register(&davinci_i2c_driver) != 0)
		printk(KERN_ERR "Driver register failed for davinci_i2c\n");
	if (platform_device_register(&davinci_i2c_device) != 0) {
		printk(KERN_ERR "Device register failed for i2c\n");
		driver_unregister(&davinci_i2c_driver);
	}

	return 0;

      do_free_irq:
	free_irq(IRQ_I2C, &i2c_davinci_dev);
      do_release_region:
	release_region(I2C_BASE, I2C_IOSIZE);

	return status;
}
コード例 #15
0
/** \brief set system time(date not modify).
 *
 * \param rt_uint32_t hour   e.g: 0~23.
 * \param rt_uint32_t minute e.g: 0~59.
 * \param rt_uint32_t second e.g: 0~59.
 * \return rt_err_t if set success, return RT_EOK.
 *
 */
rt_err_t i2c(rt_uint8_t wr, rt_uint32_t addr, rt_uint32_t reg, rt_uint32_t data)
{
    struct rt_i2c_priv_data i2c_priv_data;
    struct rt_i2c_msg i2c_msg[2];
    rt_uint8_t i2c_data[10];
    rt_device_t device;
    rt_err_t ret = -RT_ERROR;

    device = rt_device_find("I2C");
    if (device == RT_NULL)
    {
        i2c_err("Can't find I2C device.\n");
        return -RT_ERROR;
    }

    if(!wr)
    {
        // Write Action
        i2c_msg[0].addr=addr;
        i2c_msg[0].flags=RT_I2C_WR ;
        i2c_msg[0].len=2;
        i2c_data[0]=reg;
        i2c_data[1]=data;
        i2c_msg[0].buf=i2c_data;

        i2c_priv_data.msgs=i2c_msg;
        i2c_priv_data.number=1;

        if (rt_device_open(device, 0) == RT_EOK)
        {
            i2c_dbg("write msg addr=0x%x, len=%d, reg=0x%d,  data=0x%x\n",i2c_msg[0].addr, i2c_msg[0].len, i2c_data[0], i2c_data[1]);
            rt_device_control(device, RT_I2C_DEV_CTRL_RW, &i2c_priv_data);
            rt_device_close(device);
        }
        else
        {
            i2c_err("open:w err\n");
            goto l_err;
        }
    }
    else
    {
        // Read Action
        // Write reg addr msg
        i2c_msg[0].addr=addr;
        i2c_msg[0].flags=RT_I2C_WR;
        i2c_msg[0].len=1;
        i2c_data[0]=reg;
        i2c_msg[0].buf=i2c_data;
        // Read data msg
        i2c_msg[1].addr=addr;
        i2c_msg[1].flags=RT_I2C_RD;
        i2c_msg[1].len=1;
        i2c_data[1]=0;
        i2c_msg[1].buf=&i2c_data[1];

        i2c_priv_data.msgs=i2c_msg;
        i2c_priv_data.number=2;

        if (rt_device_open(device, 0) == RT_EOK)
        {
            rt_device_control(device, RT_I2C_DEV_CTRL_RW, &i2c_priv_data);
            i2c_dbg("read msg addr=0x%x, len=%d, addr=0x%d,  data=0x%x\n",i2c_msg[0].addr, i2c_msg[0].len, i2c_data[0], i2c_data[1]);
            rt_device_close(device);
        }
        else
        {

            i2c_err("open:r err\n");
            goto l_err;
        }
    }

l_err:
    return ret;
}