Beispiel #1
0
static void twi_chan_cfg(struct sunxi_i2c_platform_data *pdata)
{
	int i;
	script_item_u item = {0};
	script_item_value_type_e type = 0;
	char twi_para[16] = {0};

	for (i=0; i<SUNXI_TWI_NUM; i++) {
		sprintf(twi_para, "twi%d", i);
		type = script_get_item(twi_para, "twi_used", &item);
		if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
			I2C_ERR("[twi%d] has no twi_used!\n", i);
			continue;
		}
		if (item.val)
			twi_used_mask |= SUNXI_TWI_CHAN_MASK(i);

		type = script_get_item(twi_para, "twi_regulator", &item);
		if (SCIRPT_ITEM_VALUE_TYPE_STR != type) {
			I2C_ERR("[twi%d] has no twi_regulator.\n", i);
			continue;
		}
		strncpy(pdata[i].regulator_id, item.str, 16);
	}
}
Beispiel #2
0
static int twi_stop(void __iomem *base_addr, int bus_num)
{
	unsigned int timeout = 0xff;

	twi_set_stop(base_addr);
	twi_clear_irq_flag(base_addr);

	twi_get_stop(base_addr);/* it must delay 1 nop to check stop bit */
	while(( 1 == twi_get_stop(base_addr))&& (--timeout));
	if (timeout == 0) {
		I2C_ERR("[i2c%d] STOP can't sendout!\n", bus_num);
		return SUNXI_I2C_TFAIL;
	}

	timeout = 0xff;
	while((TWI_STAT_IDLE != readl(base_addr + TWI_STAT_REG))&&(--timeout));
	if (timeout == 0) {
		I2C_ERR("[i2c%d] i2c state isn't idle(0xf8)\n", bus_num);
		return SUNXI_I2C_TFAIL;
	}

	timeout = 0xff;
	while((TWI_LCR_IDLE_STATUS != readl(base_addr + TWI_LCR_REG))&&(--timeout));
	if (timeout == 0) {
		I2C_ERR("[i2c%d] i2c lcr isn't idle(0x3a)\n", bus_num);
		return SUNXI_I2C_TFAIL;
	}

	return SUNXI_I2C_OK;
}
Beispiel #3
0
static int twi_request_gpio(struct sunxi_i2c *i2c)
{
	int ret = 0;

	I2C_DBG("Pinctrl init %d ... [%s]\n", i2c->bus_num, i2c->adap.dev.parent->init_name);

	if (!twi_chan_is_enable(i2c->bus_num))
		return -1;
	
	i2c->pctrl = devm_pinctrl_get(i2c->adap.dev.parent);
	if (IS_ERR(i2c->pctrl)) {
		I2C_ERR("TWI%d devm_pinctrl_get() failed! return %ld\n", i2c->bus_num, PTR_ERR(i2c->pctrl));
		return -1;
	}

	i2c->pctrl_state = pinctrl_lookup_state(i2c->pctrl, PINCTRL_STATE_DEFAULT);
	if (IS_ERR(i2c->pctrl_state)) {
		I2C_ERR("TWI%d pinctrl_lookup_state() failed! return %p \n", i2c->bus_num, i2c->pctrl_state);
		return -1;
	}

	ret = pinctrl_select_state(i2c->pctrl, i2c->pctrl_state);
	if (ret < 0)
		I2C_ERR("TWI%d pinctrl_select_state() failed! return %d \n", i2c->bus_num, ret);
	
	return ret;
}
Beispiel #4
0
INT32 filter_eeprom_read(INT32 eeprom_id, UINT32 offset, UINT32 cnt, UINT8 *buffer)
{
    unsigned end = offset + cnt;
    int rcode = 0;
    (void) eeprom_id;
    int mutex_rcode;
	
    /* avoid compiler error */
    eeprom_id = 0;
    if( (offset > CONFIG_SYS_FILTER_EEPROM_SIZE) || (offset + cnt > CONFIG_SYS_FILTER_EEPROM_SIZE) )
    {
        I2C_ERR("%s: out of range offset: 0x%x, count: 0x%x max size: 0x%x\n", __func__, offset, cnt, CONFIG_SYS_FILTER_EEPROM_SIZE);
        rcode = 1;
        return rcode;
    }

    while( offset < end )
    {
        unsigned len = 0;
        len = end - offset;
#if defined(CONFIG_SYS_I2C_FRAM)
	len = (len > 128 - offset % 128) ? 128 - offset % 128 : end - offset;
#else
	len = end - offset;
#endif

	mutex_rcode = I2CMUX_MUTEX_LOCK();
	if( mutex_rcode != 0 )
	{
	    I2C_ERR("%s: Failed to initialize i2c mutex \n", __func__);
	    return 1;
	}
	uslSetI2cMux(CONFIG_SYS_I2C_MUX_SF);
	rcode = i2c_read(CONFIG_SYS_I2C_FILTER_EEPROM_PORT, CONFIG_SYS_I2C_FILTER_EEPROM_ADDR, CONFIG_SYS_I2C_FILTER_EEPROM_ADDR_LEN, offset, len, buffer);
	uslSetI2cMux(CONFIG_SYS_I2C_MUX_DISCONNECT);
	I2CMUX_MUTEX_UNLOCK();	

	if(rcode != 0 )
	{
	    I2C_ERR("%s: i2c read from filter eeprom failed - details as follow\n", __func__);
	    I2C_ERR("---------------------------------------------------\n");
	    I2C_ERR("bus - %d\n", CONFIG_SYS_I2C_FILTER_EEPROM_PORT);
	    I2C_ERR("addr - %d\n", CONFIG_SYS_I2C_FILTER_EEPROM_ADDR);
	    I2C_ERR("addr len - %d\n", CONFIG_SYS_I2C_FILTER_EEPROM_ADDR_LEN);
	    I2C_ERR("offset - %d\n", offset);
	    I2C_ERR("length - %d\n", len);
	    I2C_ERR("---------------------------------------------------\n");
	    rcode = 1;
	    return rcode;
	}   
        buffer += len;
        offset += len;
    }
    return rcode;
}
Beispiel #5
0
static int twi_select_gpio_state(struct pinctrl *pctrl, char *name, u32 no)
{
	int ret = 0;
	struct pinctrl_state *pctrl_state = NULL;

	pctrl_state = pinctrl_lookup_state(pctrl, name);
	if (IS_ERR(pctrl_state)) {
		I2C_ERR("TWI%d pinctrl_lookup_state(%s) failed! return %p \n", no, name, pctrl_state);
		return -1;
	}

	ret = pinctrl_select_state(pctrl, pctrl_state);
	if (ret < 0)
		I2C_ERR("TWI%d pinctrl_select_state(%s) failed! return %d \n", no, name, ret);

	return ret;
}
Beispiel #6
0
static int twi_regulator_disable(struct sunxi_i2c_platform_data *pdata)
{
	if (pdata->regulator == NULL)
		return 0;

	if (regulator_disable(pdata->regulator) != 0) {
		I2C_ERR("[i2c%d] enable regulator %s failed!\n", pdata->bus_num, pdata->regulator_id);
		return -1;
	}
	return 0;
}
Beispiel #7
0
static int twi_restart(void __iomem *base_addr, int bus_num)
{
	unsigned int timeout = 0xff;
	twi_set_start(base_addr);
	twi_clear_irq_flag(base_addr);
	while((1 == twi_get_start(base_addr))&&(--timeout));
	if (timeout == 0) {
		I2C_ERR("[i2c%d] Restart can't sendout!\n", bus_num);
		return SUNXI_I2C_FAIL;
	}
	return SUNXI_I2C_OK;
}
Beispiel #8
0
static int twi_regulator_request(struct sunxi_i2c_platform_data *pdata)
{
	struct regulator *regu = NULL;

	/* Consider "n***" as nocare. Support "none", "nocare", "null", "" etc. */
	if ((pdata->regulator_id[0] == 'n') || (pdata->regulator_id[0] == 0))
		return 0;

	regu = regulator_get(NULL, pdata->regulator_id);
	if (IS_ERR(regu)) {
		I2C_ERR("[i2c%d] get regulator %s failed!\n", pdata->bus_num, pdata->regulator_id);
		return -1;
	}
	pdata->regulator = regu;
	return 0;
}
Beispiel #9
0
static int msm_i2c_poll_notbusy(int warn)
{
	uint32_t retries = 0;
	while (retries != 200) {
		uint32_t status = readl(dev.pdata->i2c_base + I2C_STATUS);

		if (!(status & I2C_STATUS_BUS_ACTIVE)) {
			if (retries && warn){
				I2C_DBG(DEBUGLEVEL, "Warning bus was busy (%d)\n", retries);
				return 0;
			}
		}
		
		if (retries++ > 100)
			mdelay(10);
	}
	
	I2C_ERR("Error waiting for notbusy\n");
	return ERR_TIMED_OUT;
}
Beispiel #10
0
static void msm_i2c_interrupt_locked(void)
{
	uint32_t status	= readl(dev.pdata->i2c_base + I2C_STATUS);
	bool not_done = true;

#if DEBUG_I2C
	dump_status(status);
#endif
	if (!dev.msg) {
		I2C_DBG(DEBUGLEVEL, "IRQ but nothing to do!, status %x\n", status);
		return;
	}
	
	if (status & I2C_STATUS_ERROR_MASK)
		goto out_err;

	if (!(status & I2C_STATUS_WR_BUFFER_FULL))
		not_done = msm_i2c_fill_write_buffer();
		
	if (status & I2C_STATUS_RD_BUFFER_FULL)
		msm_i2c_read_buffer();

	if (dev.pos >= 0 && dev.cnt == 0) {
		if (dev.rem > 1) {
			dev.rem--;
			dev.msg++;
			dev.pos = -1;
			dev.cnt = dev.msg->len;
		}
		else if (!not_done && !dev.need_flush) {
			timeout = 0;
			return;
		}
	}
	return;

out_err:
	I2C_ERR("error, status %x\n", status);
	dev.ret = ERROR;
	timeout = ERR_TIMED_OUT;
}
Beispiel #11
0
/* send 9 clock to release sda */
static int twi_send_clk_9pulse(void __iomem *base_addr, int bus_num)
{
    int twi_scl = 1;
    int low = 0;
    int high = 1;
    int cycle = 0;

    /* enable scl control */
    twi_enable_lcr(base_addr, twi_scl);

    while (cycle < 9)
    {
        if (twi_get_sda(base_addr)
            && twi_get_sda(base_addr)
            && twi_get_sda(base_addr)) {
            break;
        }
        /* twi_scl -> low */
        twi_set_scl(base_addr, low);
        udelay(1000);

        /* twi_scl -> high */
        twi_set_scl(base_addr, high);
        udelay(1000);
        cycle++;
    }

    if (twi_get_sda(base_addr)) {
        twi_disable_lcr(base_addr, twi_scl);
        return SUNXI_I2C_OK;
    }
    else {
        I2C_ERR("[i2c%d] SDA is still Stuck Low, failed. \n", bus_num);
        twi_disable_lcr(base_addr, twi_scl);
        return SUNXI_I2C_FAIL;
    }
}
Beispiel #12
0
int msm_i2c_xfer(struct i2c_msg msgs[], int num)
{
	int ret, ret_wait;

	clk_enable(dev.pdata->clk_nr);
	unmask_interrupt(dev.pdata->irq_nr);

	ret = msm_i2c_poll_notbusy(1);

	if (ret) {
		ret = msm_i2c_recover_bus_busy();
		if (ret)
			goto err;
	}

	enter_critical_section();
	if (dev.flush_cnt) {
		I2C_DBG(DEBUGLEVEL, "%d unrequested bytes read\n", dev.flush_cnt);
	}
	dev.msg = msgs;
	dev.rem = num;
	dev.pos = -1;
	dev.ret = num;
	dev.need_flush = false;
	dev.flush_cnt = 0;
	dev.cnt = msgs->len;
	msm_i2c_interrupt_locked();
	exit_critical_section();

	/*
	 * Now that we've setup the xfer, the ISR will transfer the data
	 * and wake us up with dev.err set if there was an error
	 */
	ret_wait = msm_i2c_poll_notbusy(0); /* Read may not have stopped in time */
	
	enter_critical_section();
	if (dev.flush_cnt) {
		I2C_DBG(DEBUGLEVEL, "%d unrequested bytes read\n", dev.flush_cnt);
	}
	ret = dev.ret;
	dev.msg = NULL;
	dev.rem = 0;
	dev.pos = 0;
	dev.ret = 0;
	dev.flush_cnt = 0;
	dev.cnt = 0;
	exit_critical_section();

	if (ret_wait) {
		I2C_DBG(DEBUGLEVEL, "Still busy after xfer completion\n");
		ret_wait = msm_i2c_recover_bus_busy();
		if (ret_wait)
			goto err;
	}
	if (timeout == ERR_TIMED_OUT) {
		I2C_DBG(DEBUGLEVEL, "Transaction timed out\n");
		ret = ERR_TIMED_OUT;
	}
	if (ret < 0) {
		I2C_ERR("Error during data xfer (%d)\n", ret);
		msm_i2c_recover_bus_busy();
	}
	/* if (timeout == ERR_TIMED_OUT) {
		I2C_DBG(DEBUGLEVEL, "Transaction timed out\n");
		ret = 2;
		msm_i2c_recover_bus_busy();
	}
	if (timeout == ERR_TIMED_OUT) {
		I2C_DBG(DEBUGLEVEL, "Transaction timed out\n");
		ret = ERR_TIMED_OUT;
	}
	if (ret < 0) {
		I2C_ERR("Error during data xfer (%d)\n", ret);
		msm_i2c_recover_bus_busy();
	} */
err:
	mask_interrupt(dev.pdata->irq_nr);
	clk_disable(dev.pdata->clk_nr);
	
	return ret;
}