static int if_hsi_close_channel(struct if_hsi_channel *channel)
{
	unsigned long int flags;

	if (!channel->opened) {
		pr_debug("[MIPI-HSI] channel %d is already closed\n",
					channel->channel_id);
		return 0;
	}

	if_hsi_set_wakeline(channel, 0);
	hsi_write_cancel(channel->dev);
	hsi_read_cancel(channel->dev);

	spin_lock_irqsave(&channel->tx_state_lock, flags);
	channel->tx_state &= ~HSI_CHANNEL_TX_STATE_WRITING;
	spin_unlock_irqrestore(&channel->tx_state_lock, flags);
	spin_lock_irqsave(&channel->rx_state_lock, flags);
	channel->rx_state &= ~HSI_CHANNEL_RX_STATE_READING;
	spin_unlock_irqrestore(&channel->rx_state_lock, flags);

	hsi_close(channel->dev);
	channel->opened = 0;

	channel->send_step = STEP_CLOSED;
	channel->recv_step = STEP_CLOSED;

	pr_debug("[MIPI-HSI] hsi_close Done : %d\n", channel->channel_id);
	return 0;
}
Пример #2
0
void if_hsi_cancel_read(int ch)
{
	struct if_hsi_channel *channel;
	channel = &hsi_protocol_iface.channels[ch];
	dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, ch);
	if (channel->state & HSI_CHANNEL_STATE_READING)
		hsi_read_cancel(channel->dev);
	spin_lock(&channel->lock);
	channel->state &= ~HSI_CHANNEL_STATE_READING;
	spin_unlock(&channel->lock);
}
Пример #3
0
int if_hsi_closechannel(struct if_hsi_channel *channel)
{
	int ret = 0;

	dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__,
		channel->channel_id);
	spin_lock(&channel->lock);

	if (!channel->opened)
		goto leave;

	if (!channel->dev) {
		pr_err("Channel %d is not ready??\n", channel->channel_id);
		ret = -ENODEV;
		goto leave;
	}

	/* Stop any pending read/write */
	if (channel->state & HSI_CHANNEL_STATE_READING) {
		channel->state &= ~HSI_CHANNEL_STATE_READING;
		spin_unlock(&channel->lock);
		hsi_read_cancel(channel->dev);
		spin_lock(&channel->lock);
	}
	if (channel->state & HSI_CHANNEL_STATE_WRITING) {
		channel->state &= ~HSI_CHANNEL_STATE_WRITING;

		spin_unlock(&channel->lock);
		hsi_write_cancel(channel->dev);
	} else
		spin_unlock(&channel->lock);

	hsi_close(channel->dev);

	spin_lock(&channel->lock);
	channel->opened = 0;
	channel->tx_state = HSI_LL_TX_STATE_CLOSED;
	channel->rx_state = HSI_LL_RX_STATE_CLOSED;
leave:
	spin_unlock(&channel->lock);
	return ret;
}
static int hsi_init_handshake(struct mipi_link_device *mipi_ld, int mode)
{
	int ret;
	int i;
	struct hst_ctx tx_config;
	struct hsr_ctx rx_config;

	switch (mode) {
	case HSI_INIT_MODE_NORMAL:
		if (timer_pending(&mipi_ld->hsi_acwake_down_timer))
			del_timer(&mipi_ld->hsi_acwake_down_timer);

		for (i = 0; i < HSI_NUM_OF_USE_CHANNELS; i++) {
			if (mipi_ld->hsi_channles[i].opened) {
				hsi_write_cancel(mipi_ld->hsi_channles[i].dev);
				hsi_read_cancel(mipi_ld->hsi_channles[i].dev);
			} else {
				ret = if_hsi_open_channel(
						&mipi_ld->hsi_channles[i]);
				if (ret)
					return ret;
			}
			mipi_ld->hsi_channles[i].send_step = STEP_IDLE;
			mipi_ld->hsi_channles[i].recv_step = STEP_IDLE;

			hsi_ioctl(mipi_ld->hsi_channles[i].dev,
						HSI_IOCTL_GET_TX, &tx_config);
			tx_config.mode = 2;
			tx_config.divisor = 0; /* Speed : 96MHz */
			tx_config.channels = HSI_MAX_CHANNELS;
			hsi_ioctl(mipi_ld->hsi_channles[i].dev,
						HSI_IOCTL_SET_TX, &tx_config);

			hsi_ioctl(mipi_ld->hsi_channles[i].dev,
						HSI_IOCTL_GET_RX, &rx_config);
			rx_config.mode = 2;
			rx_config.divisor = 0; /* Speed : 96MHz */
			rx_config.channels = HSI_MAX_CHANNELS;
			hsi_ioctl(mipi_ld->hsi_channles[i].dev,
						HSI_IOCTL_SET_RX, &rx_config);
			pr_debug("[MIPI-HSI] Set TX/RX MIPI-HSI\n");
		}

		hsi_ioctl(mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].dev,
			HSI_IOCTL_SET_WAKE_RX_4WIRES_MODE, NULL);
		pr_debug("[MIPI-HSI] Set 4 WIRE MODE\n");

		if (mipi_ld->ld.com_state != COM_ONLINE)
			mipi_ld->ld.com_state = COM_HANDSHAKE;

		ret = hsi_read(mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].dev,
			mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL].rx_data,
					1);
		if (ret)
			pr_err("[MIPI-HSI] hsi_read fail : %d\n", ret);

		if (mipi_ld->ld.com_state != COM_ONLINE)
			schedule_delayed_work(&mipi_ld->start_work, 3 * HZ);

		pr_debug("[MIPI-HSI] hsi_init_handshake Done : MODE_NORMAL\n");
		return 0;

	case HSI_INIT_MODE_FLASHLESS_BOOT:
		mipi_ld->ld.com_state = COM_BOOT;

		if (mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].opened) {
			hsi_ioctl(mipi_ld->hsi_channles[
			HSI_FLASHLESS_CHANNEL].dev, HSI_IOCTL_SW_RESET,
						NULL);
			for (i = 0; i < HSI_NUM_OF_USE_CHANNELS; i++)
				mipi_ld->hsi_channles[i].opened = 0;
		}

		if (!mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].opened)
			if_hsi_open_channel(
				&mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL]);
		mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].send_step
					= STEP_IDLE;
		mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].recv_step
					= STEP_IDLE;

		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_GET_TX, &tx_config);
		tx_config.mode = 2;
		tx_config.divisor = 3; /* Speed : 24MHz */
		tx_config.channels = 1;
		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_SET_TX, &tx_config);

		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_GET_RX, &rx_config);
		rx_config.mode = 2;
		rx_config.divisor = 3; /* Speed : 24MHz */
		rx_config.channels = 1;
		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_SET_RX, &rx_config);
		pr_debug("[MIPI-HSI] Set TX/RX MIPI-HSI\n");

		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
				HSI_IOCTL_SET_WAKE_RX_3WIRES_MODE, NULL);
		pr_debug("[MIPI-HSI] Set 3 WIRE MODE\n");

		if (!wake_lock_active(&mipi_ld->wlock)) {
			wake_lock(&mipi_ld->wlock);
			pr_debug("[MIPI-HSI] wake_lock\n");
		}

		ret = hsi_read(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
		mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].rx_data, 1);
		if (ret)
			pr_err("[MIPI-HSI] hsi_read fail : %d\n", ret);

		pr_debug("[MIPI-HSI] hsi_init_handshake Done : FLASHLESS_BOOT\n");
		return 0;

	case HSI_INIT_MODE_FLASHLESS_BOOT_EBL:
		mipi_ld->ld.com_state = COM_BOOT_EBL;

		if (mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].opened) {
			hsi_ioctl(mipi_ld->hsi_channles[
			HSI_FLASHLESS_CHANNEL].dev, HSI_IOCTL_SW_RESET,
						NULL);
			for (i = 0; i < HSI_NUM_OF_USE_CHANNELS; i++)
				mipi_ld->hsi_channles[i].opened = 0;
		}

		if (!mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].opened)
			if_hsi_open_channel(
				&mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL]);

		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_GET_TX, &tx_config);
		tx_config.mode = 2;
		tx_config.divisor = 0; /* Speed : 96MHz */
		tx_config.channels = 1;
		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_SET_TX, &tx_config);

		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_GET_RX, &rx_config);
		rx_config.mode = 2;
		rx_config.divisor = 0; /* Speed : 96MHz */
		rx_config.channels = 1;
		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
					HSI_IOCTL_SET_RX, &rx_config);
		pr_debug("[MIPI-HSI] Set TX/RX MIPI-HSI\n");

		hsi_ioctl(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
				HSI_IOCTL_SET_WAKE_RX_4WIRES_MODE, NULL);
		pr_debug("[MIPI-HSI] Set 4 WIRE MODE\n");

		if (!wake_lock_active(&mipi_ld->wlock)) {
			wake_lock(&mipi_ld->wlock);
			pr_debug("[MIPI-HSI] wake_lock\n");
		}

		if_hsi_set_wakeline(
			&mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL], 1);

		ret = hsi_read(mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].dev,
		mipi_ld->hsi_channles[HSI_FLASHLESS_CHANNEL].rx_data, 1);
		if (ret)
			pr_err("[MIPI-HSI] hsi_read fail : %d\n", ret);

		pr_debug("[MIPI-HSI] hsi_init_handshake Done : FLASHLESS_BOOT_EBL\n");
		return 0;

	case HSI_INIT_MODE_CP_RAMDUMP:
		mipi_ld->ld.com_state = COM_CRASH;

		if (mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].opened) {
			hsi_ioctl(mipi_ld->hsi_channles[
			HSI_CP_RAMDUMP_CHANNEL].dev, HSI_IOCTL_SW_RESET,
						NULL);
			for (i = 0; i < HSI_NUM_OF_USE_CHANNELS; i++)
				mipi_ld->hsi_channles[i].opened = 0;
		}

		if (!mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].opened)
			if_hsi_open_channel(
				&mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL]);
		mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].send_step
					= STEP_IDLE;
		mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].recv_step
					= STEP_IDLE;

		hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev,
					HSI_IOCTL_GET_TX, &tx_config);
		tx_config.mode = 2;
		tx_config.divisor = 0; /* Speed : 96MHz */
		tx_config.channels = 1;
		hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev,
					HSI_IOCTL_SET_TX, &tx_config);

		hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev,
					HSI_IOCTL_GET_RX, &rx_config);
		rx_config.mode = 2;
		rx_config.divisor = 0; /* Speed : 96MHz */
		rx_config.channels = 1;
		hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev,
					HSI_IOCTL_SET_RX, &rx_config);
		pr_debug("[MIPI-HSI] Set TX/RX MIPI-HSI\n");

		hsi_ioctl(mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev,
				HSI_IOCTL_SET_WAKE_RX_4WIRES_MODE, NULL);
		pr_debug("[MIPI-HSI] Set 4 WIRE MODE\n");

		if (!wake_lock_active(&mipi_ld->wlock)) {
			wake_lock(&mipi_ld->wlock);
			pr_debug("[MIPI-HSI] wake_lock\n");
		}

		if_hsi_set_wakeline(
			&mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL], 1);

		ret = hsi_read(
			mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].dev,
			mipi_ld->hsi_channles[HSI_CP_RAMDUMP_CHANNEL].rx_data,
					DUMP_ERR_INFO_SIZE);
		if (ret)
			pr_err("[MIPI-HSI] hsi_read fail : %d\n", ret);

		pr_debug("[MIPI-HSI] hsi_init_handshake Done : RAMDUMP\n");
		return 0;

	default:
		return -EINVAL;
	}
}