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; }
int __devexit if_hsi_exit(void) { struct if_hsi_channel *channel; unsigned long *address; int i, port; pr_debug("%s\n", __func__); for (port = 0; port < HSI_MAX_PORTS; port++) { if (if_hsi_protocol_driver.ch_mask[port]) break; } address = &if_hsi_protocol_driver.ch_mask[port]; for (i = 0; i < HSI_MAX_CHANNELS; i++) { channel = &hsi_protocol_iface.channels[i]; if (channel->opened) { if_hsi_set_wakeline(i, HSI_IOCTL_ACWAKE_DOWN); if_hsi_closechannel(channel); } } hsi_unregister_driver(&if_hsi_protocol_driver); return 0; }
static void if_hsi_cmd_work(struct work_struct *work) { int ret; int retry_count = 0; unsigned long int flags; struct mipi_link_device *mipi_ld = container_of(work, struct mipi_link_device, cmd_work.work); struct if_hsi_channel *channel = &mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL]; struct if_hsi_command *hsi_cmd; pr_debug("[MIPI-HSI] cmd_work\n"); do { spin_lock_irqsave(&mipi_ld->list_cmd_lock, flags); if (!list_empty(&mipi_ld->list_of_hsi_cmd)) { hsi_cmd = list_entry(mipi_ld->list_of_hsi_cmd.next, struct if_hsi_command, list); list_del(&hsi_cmd->list); spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags); channel->send_step = STEP_TX; if_hsi_set_wakeline(channel, 1); mod_timer(&mipi_ld->hsi_acwake_down_timer, jiffies + HSI_ACWAKE_DOWN_TIMEOUT); } else { spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags); channel->send_step = STEP_IDLE; break; } pr_debug("[MIPI-HSI] take command : %08x\n", hsi_cmd->command); ret = if_hsi_write(channel, &hsi_cmd->command, 4); if (ret < 0) { pr_err("[MIPI-HSI] write command fail : %d\n", ret); retry_count++; if (retry_count > 5) { channel->send_step = STEP_IDLE; kfree(hsi_cmd); return; } hsi_conn_err_recovery(mipi_ld); channel->send_step = STEP_IDLE; spin_lock_irqsave(&mipi_ld->list_cmd_lock, flags); list_add(&hsi_cmd->list, &mipi_ld->list_of_hsi_cmd); spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags); pr_err("[MIPI-HSI] retry write command : %d\n", retry_count); continue; } pr_debug("[MIPI-HSI] SEND CMD : %08x\n", hsi_cmd->command); kfree(hsi_cmd); } while (true);
static void if_hsi_acwake_down_func(unsigned long data) { int i; struct if_hsi_channel *channel; struct mipi_link_device *mipi_ld = (struct mipi_link_device *)data; pr_debug("[MIPI-HSI] %s\n", __func__); for (i = 0; i < HSI_NUM_OF_USE_CHANNELS; i++) { channel = &mipi_ld->hsi_channles[i]; if ((channel->send_step == STEP_IDLE) && (channel->recv_step == STEP_IDLE)) { if_hsi_set_wakeline(channel, 0); } else { mod_timer(&mipi_ld->hsi_acwake_down_timer, jiffies + HSI_ACWAKE_DOWN_TIMEOUT); pr_debug("[MIPI-HSI] mod_timer done(%d)\n", HSI_ACWAKE_DOWN_TIMEOUT); return; } } }
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; } }