Esempio n. 1
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;
}
Esempio n. 2
0
/* set twi clock
 *
 * clk_n: clock divider factor n
 * clk_m: clock divider factor m
 */
static inline void twi_clk_write_reg(unsigned int clk_n, unsigned int clk_m, void __iomem *base_addr)
{
	unsigned int reg_val = readl(base_addr + TWI_CLK_REG);
	I2C_DBG("%s: clk_n = %d, clk_m = %d\n", __FUNCTION__, clk_n, clk_m);
	reg_val &= ~(TWI_CLK_DIV_M | TWI_CLK_DIV_N);
	reg_val |= ( clk_n |(clk_m << 3) );
	writel(reg_val, base_addr + TWI_CLK_REG);
}
Esempio n. 3
0
//struct mutex msm_i2c_rw_mutex;
int msm_i2c_write(int chip, void *buf, size_t count)
{
	int rc = ERR_NOT_READY;
	if (!dev.pdata) {
		I2C_DBG(ALWAYS, "[MSM-I2C]: %s: called when driver is not installed\n", __func__);
		return rc;
	}

	struct i2c_msg msg[] = {
		{.addr = chip,	.flags = 0,		.len = count,	.buf = buf,}
	};
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
static void dump_status(uint32_t status)
{
	I2C_DBG(DEBUGLEVEL, "STATUS (0x%.8x): ", status);
	if (status & I2C_STATUS_BUS_MASTER)
		I2C_DBG(DEBUGLEVEL, "MST ");
	if (status & I2C_STATUS_BUS_ACTIVE)
		I2C_DBG(DEBUGLEVEL, "ACT ");
	if (status & I2C_STATUS_INVALID_WRITE)
		I2C_DBG(DEBUGLEVEL, "INV_WR ");
	if (status & I2C_STATUS_ARB_LOST)
		I2C_DBG(DEBUGLEVEL, "ARB_LST ");
	if (status & I2C_STATUS_PACKET_NACKED)
		I2C_DBG(DEBUGLEVEL, "NAK ");
	if (status & I2C_STATUS_BUS_ERROR)
		I2C_DBG(DEBUGLEVEL, "BUS_ERR ");
	if (status & I2C_STATUS_RD_BUFFER_FULL)
		I2C_DBG(DEBUGLEVEL, "RD_FULL ");
	if (status & I2C_STATUS_WR_BUFFER_FULL)
		I2C_DBG(DEBUGLEVEL, "WR_FULL ");
	if (status & I2C_STATUS_FAILED)
		I2C_DBG(DEBUGLEVEL, "FAIL 0x%x", (status & I2C_STATUS_FAILED));
	I2C_DBG(DEBUGLEVEL, "\n");
}
Esempio n. 7
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;
}
Esempio n. 8
0
static int msm_i2c_recover_bus_busy(void)
{
	int i;
	bool gpio_clk_status = false;
	uint32_t status = readl(dev.pdata->i2c_base + I2C_STATUS);
	I2C_DBG_FUNC_LINE();

	if (!(status & (I2C_STATUS_BUS_ACTIVE | I2C_STATUS_WR_BUFFER_FULL)))
		return 0;

	if (dev.pdata->set_mux_to_i2c)
		dev.pdata->set_mux_to_i2c(0);

	if (status & I2C_STATUS_RD_BUFFER_FULL) {
		I2C_DBG(DEBUGLEVEL, "Read buffer full, status %x, intf %x\n",  status, readl(dev.pdata->i2c_base + I2C_INTERFACE_SELECT));
		writel(I2C_WRITE_DATA_LAST_BYTE, dev.pdata->i2c_base + I2C_WRITE_DATA);
		readl(dev.pdata->i2c_base + I2C_READ_DATA);
	}
	else if (status & I2C_STATUS_BUS_MASTER) {
		I2C_DBG(DEBUGLEVEL, "Still the bus master, status %x, intf %x\n", status, readl(dev.pdata->i2c_base + I2C_INTERFACE_SELECT));
		writel(I2C_WRITE_DATA_LAST_BYTE | 0xff, dev.pdata->i2c_base + I2C_WRITE_DATA);
	}

	I2C_DBG(DEBUGLEVEL, "i2c_scl: %d, i2c_sda: %d\n", gpio_get(dev.pdata->scl_gpio), gpio_get(dev.pdata->sda_gpio));

	for (i = 0; i < 9; i++) {
		if (gpio_get(dev.pdata->sda_gpio) && gpio_clk_status)
			break;
			
		gpio_set(dev.pdata->scl_gpio, 0);
		udelay(5);
		
		gpio_set(dev.pdata->sda_gpio, 0);
		udelay(5);
		
		gpio_config(dev.pdata->scl_gpio, GPIO_INPUT);
		udelay(5);
		
		if (!gpio_get(dev.pdata->scl_gpio))
			udelay(20);
			
		if (!gpio_get(dev.pdata->scl_gpio))
			mdelay(10);
			
		gpio_clk_status = gpio_get(dev.pdata->scl_gpio);
		gpio_config(dev.pdata->sda_gpio, GPIO_INPUT);
		udelay(5);
	}
	
	if (dev.pdata->set_mux_to_i2c)
		dev.pdata->set_mux_to_i2c(1);

	udelay(10);

	status = readl(dev.pdata->i2c_base + I2C_STATUS);
	if (!(status & I2C_STATUS_BUS_ACTIVE)) {
		I2C_DBG(DEBUGLEVEL, "Bus busy cleared after %d clock cycles, status %x, intf %x\n", i, status, readl(dev.pdata->i2c_base + I2C_INTERFACE_SELECT));
		return 0;
	}
	
	I2C_DBG(DEBUGLEVEL, "Bus still busy, status %x, intf %x\n", status, readl(dev.pdata->i2c_base + I2C_INTERFACE_SELECT));
	return ERR_NOT_READY;
}