/* * File - hsi_protocol_if.c * * Implements HSI protocol for Infineon Modem. * * Copyright (C) 2011 Samsung Electronics. * * Author: Rupesh Gujare * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hsi-protocol-if.h" //#define DEBUG 1 //#define DEBUG_PHY_DATA 1 #define HSI_CHANNEL_STATE_UNAVAIL (1 << 0) #define HSI_CHANNEL_STATE_READING (1 << 1) #define HSI_CHANNEL_STATE_WRITING (1 << 2) struct if_hsi_iface hsi_protocol_iface; wait_queue_head_t ipc_read_wait, ipc_write_wait; static void if_hsi_protocol_port_event(struct hsi_device *dev, unsigned int event, void *arg); static int __devinit hsi_protocol_probe(struct hsi_device *dev); static int __devexit hsi_protocol_remove(struct hsi_device *dev); static struct hsi_device_driver if_hsi_protocol_driver = { .ctrl_mask = ANY_HSI_CONTROLLER, .probe = hsi_protocol_probe, .remove = __devexit_p(hsi_protocol_remove), .driver = { .name = "hsi_protocol" }, }; struct if_hsi_cmd hsi_cmd_history; int tx_cmd_history_p = 0; int rx_cmd_history_p = 0; static int if_hsi_read_on(int ch, u32 *data, unsigned int count) { struct if_hsi_channel *channel; int ret; channel = &hsi_protocol_iface.channels[ch]; dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, ch); spin_lock(&channel->lock); if (channel->state & HSI_CHANNEL_STATE_READING) { pr_err("Read still pending on channel %d\n", ch); spin_unlock(&channel->lock); return -EBUSY; } channel->state |= HSI_CHANNEL_STATE_READING; channel->rx_data = data; channel->rx_count = count; spin_unlock(&channel->lock); ret = hsi_read(channel->dev, data, count / 4); dev_dbg(&channel->dev->device, "%s, ch = %d, ret = %d\n", __func__, ch, ret); return ret; } static void if_hsi_proto_read_done(struct hsi_device *dev, unsigned int size) { struct if_hsi_channel *channel; struct hsi_event ev; #ifdef DEBUG_PHY_DATA u32 *tmp; u32 i; #endif //printk(KERN_INFO "if_hsi_proto_read_done() is called for ch-> %d\n", dev->n_ch); channel = &hsi_protocol_iface.channels[dev->n_ch]; dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, dev->n_ch); spin_lock(&channel->lock); channel->state &= ~HSI_CHANNEL_STATE_READING; ev.event = HSI_EV_IN; ev.data = channel->rx_data; ev.count = 4 * size; spin_unlock(&channel->lock); #ifdef DEBUG_PHY_DATA //Check received data -> Commented as it adds delay which causes MSG_BREAK tmp = channel->rx_data; printk(KERN_INFO "[%s](%d)(%d) RX = ", __func__, dev->n_ch, ev.count); for (i = 0; i < ((size > 5) ? 5 : size); i++) { printk(KERN_INFO "%08x ", *tmp); tmp++; } printk(KERN_INFO "\n"); #endif if_notify(dev->n_ch, &ev); } int if_hsi_read(int ch, u32 *data, unsigned int count) { int ret = 0; struct if_hsi_channel *channel; channel = &hsi_protocol_iface.channels[ch]; dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, ch); ret = if_hsi_read_on(ch, data, count); return ret; } int if_hsi_poll(int ch) { struct if_hsi_channel *channel; int ret = 0; channel = &hsi_protocol_iface.channels[ch]; dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, ch); ret = hsi_poll(channel->dev); return ret; } static int if_hsi_write_on(int ch, u32 *address, unsigned int count) { struct if_hsi_channel *channel; int ret; channel = &hsi_protocol_iface.channels[ch]; spin_lock(&channel->lock); if (channel->state & HSI_CHANNEL_STATE_WRITING) { pr_err("Write still pending on channel %d\n", ch); printk(KERN_INFO "Write still pending on channel %d\n", ch); spin_unlock(&channel->lock); return -EBUSY; } channel->tx_data = address; channel->tx_count = count; channel->state |= HSI_CHANNEL_STATE_WRITING; spin_unlock(&channel->lock); dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, ch); ret = hsi_write(channel->dev, address, count / 4); return ret; } static void if_hsi_proto_write_done(struct hsi_device *dev, unsigned int size) { struct if_hsi_channel *channel; struct hsi_event ev; #ifdef DEBUG_PHY_DATA u32 *tmp; u32 i; #endif //printk(KERN_INFO "if_hsi_proto_write_done() is called for ch-> %d\n", dev->n_ch); channel = &hsi_protocol_iface.channels[dev->n_ch]; dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, dev->n_ch); spin_lock(&channel->lock); channel->state &= ~HSI_CHANNEL_STATE_WRITING; ev.event = HSI_EV_OUT; ev.data = channel->tx_data; ev.count = 4 * size; spin_unlock(&channel->lock); #ifdef DEBUG_PHY_DATA //Check Outgoing data, Commented as it adds delay which causes MSG_BREAK tmp = channel->tx_data; printk(KERN_INFO "[%s](%d)(%d) TX = ", __func__, dev->n_ch, ev.count); for (i = 0; i < ((size > 5) ? 5 : size); i++) { printk(KERN_INFO "%08x ", *tmp); tmp++; } printk(KERN_INFO "\n"); #endif if_notify(dev->n_ch, &ev); } int if_hsi_write(int ch, u32 *data, unsigned int count) { int ret = 0; struct if_hsi_channel *channel; channel = &hsi_protocol_iface.channels[ch]; dev_dbg(&channel->dev->device, "%s, ch = %d\n", __func__, ch); ret = if_hsi_write_on(ch, data, count); return ret; } 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); } void if_hsi_set_wakeline(int ch, unsigned int state) { struct if_hsi_channel *channel; channel = &hsi_protocol_iface.channels[ch]; hsi_ioctl(channel->dev, state ? HSI_IOCTL_ACWAKE_UP : HSI_IOCTL_ACWAKE_DOWN, NULL); } static void if_hsi_protocol_port_event(struct hsi_device *dev, unsigned int event, void *arg) { struct hsi_event ev; int i; ev.event = HSI_EV_EXCEP; ev.data = (u32 *) 0; ev.count = 0; switch (event) { case HSI_EVENT_BREAK_DETECTED: pr_debug("%s, HWBREAK detected\n", __func__); ev.data = (u32 *) HSI_HWBREAK; for (i = 0; i < HSI_MAX_CHANNELS; i++) { if (hsi_protocol_iface.channels[i].opened) if_notify(i, &ev); } break; case HSI_EVENT_HSR_DATAAVAILABLE: i = (int)arg; pr_debug("%s, HSI_EVENT_HSR_DATAAVAILABLE channel = %d\n", __func__, i); ev.event = HSI_EV_AVAIL; if (hsi_protocol_iface.channels[i].opened) if_notify(i, &ev); break; case HSI_EVENT_CAWAKE_UP: pr_debug("%s, CAWAKE up\n", __func__); break; case HSI_EVENT_CAWAKE_DOWN: pr_debug("%s, CAWAKE down\n", __func__); break; case HSI_EVENT_ERROR: pr_debug("%s, HSI ERROR occured\n", __func__); break; default: pr_warning("%s, Unknown event(%d)\n", __func__, event); break; } } int if_hsi_openchannel(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->state == HSI_CHANNEL_STATE_UNAVAIL) { ret = -ENODEV; goto leave; } if (channel->opened) { ret = -EBUSY; goto leave; } if (!channel->dev) { pr_err("Channel %d is not ready??\n", channel->channel_id); ret = -ENODEV; goto leave; } spin_unlock(&channel->lock); ret = hsi_open(channel->dev); spin_lock(&channel->lock); if (ret < 0) { pr_err("Could not open channel %d\n", channel->channel_id); goto leave; } channel->opened = 1; channel->tx_state = HSI_LL_TX_STATE_IDLE; channel->rx_state = HSI_LL_RX_STATE_TO_CONN_READY; printk(KERN_INFO "setting channel->opened=1 for channel %d\n", channel->dev->n_ch); leave: spin_unlock(&channel->lock); return ret; } 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; } /* Read Thread * Should be responsible for handling commands * Should wait on port events - waitqueue * */ static int hsi_read_thrd(void *data) { u32 cmd_data[4], cmd, channel, param = 0; int ret; printk(KERN_INFO "Inside read thread\n"); while (1) { /*Call hsi_proto_read*/ /*Read 16 bytes due to Modem limitation*/ //hsi_proto_read(0, cmd_data, (4 * 4)); // For es 2.1 ver. hsi_proto_read(0, cmd_data, 4); hsi_cmd_history.rx_cmd[rx_cmd_history_p] = cmd_data[0]; hsi_cmd_history.rx_cmd_time[rx_cmd_history_p] = CURRENT_TIME; rx_cmd_history_p++; if (rx_cmd_history_p >= 50) rx_cmd_history_p = 0; /*Decode Command*/ ret = hsi_decode_cmd(&cmd_data[0], &cmd, &channel, ¶m); if (ret != 0) { pr_err("Can not decode command\n"); } else { printk(KERN_INFO "%s(),CMD Received-> %x, ch-> %d, param-> %d.\n", __func__, cmd, channel, param); /*Rx State Machine*/ rx_stm(cmd, channel, param); } } return 0; } int hsi_start_protocol(void) { struct hst_ctx tx_config; struct hsr_ctx rx_config; int i, ret = 0; printk(KERN_INFO "In function %s()\n", __func__); /*Open All channels */ for (i = 0; i <= 5; i++) { ret = if_hsi_openchannel(&hsi_protocol_iface.channels[i]); if (ret < 0) pr_err("Can not Open channel->%d . Can not start HSI protocol\n", i); else printk(KERN_INFO "Channel->%d Open Successful\n", i); /*Set Rx Config*/ hsi_ioctl(hsi_protocol_iface.channels[i].dev, HSI_IOCTL_GET_RX, &rx_config); rx_config.mode = 2; rx_config.divisor = 1; rx_config.channels = HSI_MAX_CHANNELS; ret = hsi_ioctl(hsi_protocol_iface.channels[i].dev, HSI_IOCTL_SET_RX, &rx_config); if (ret == 0) printk(KERN_INFO "SET_RX Successful for ch->%d\n", i); /*Set Tx Config*/ hsi_ioctl(hsi_protocol_iface.channels[i].dev, HSI_IOCTL_GET_TX, &tx_config); tx_config.mode = 2; tx_config.divisor = 1; tx_config.channels = HSI_MAX_CHANNELS; ret = hsi_ioctl(hsi_protocol_iface.channels[i].dev, HSI_IOCTL_SET_TX, &tx_config); if (ret == 0) printk(KERN_INFO "SET_TX Successful for ch->%d\n", i); } /*Make channel-0 tx_state to IDLE*/ hsi_protocol_iface.channels[0].tx_state = HSI_LL_TX_STATE_IDLE; return ret; } EXPORT_SYMBOL(hsi_start_protocol); static int hsi_protocol_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { char *p = page; int len, i; p += sprintf(p, "======= HISTORY OF CMD =======\n"); p += sprintf(p, " tx_cmd_history_p : %d\n", tx_cmd_history_p); p += sprintf(p, " rx_cmd_history_p : %d\n", rx_cmd_history_p); for (i = 0; i < 50; i++) { p += sprintf(p, " [%d] tx : 0x%08x(%lu.%09lu), rx : 0x%08x(%lu.%09lu)\n", i, hsi_cmd_history.tx_cmd[i], (unsigned long)hsi_cmd_history.tx_cmd_time[i].tv_sec, (unsigned long)hsi_cmd_history.tx_cmd_time[i].tv_nsec, hsi_cmd_history.rx_cmd[i], (unsigned long)hsi_cmd_history.rx_cmd_time[i].tv_sec, (unsigned long)hsi_cmd_history.rx_cmd_time[i].tv_nsec); } p += sprintf(p, "======= HISTORY OF CMD =======\n"); len = (p - page) - off; if (len < 0) len = 0; *eof = (len <= count) ? 1 : 0; *start = page + off; return len; } int __devexit hsi_protocol_remove(struct hsi_device *dev) { struct if_hsi_channel *channel; unsigned long *address; int port, ret; //dev_dbg(&dev->device, "%s, port = %d, ch = %d\n", __func__, dev->n_p, // dev->n_ch); 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]; spin_lock_bh(&hsi_protocol_iface.lock); if (test_bit(dev->n_ch, address) && (dev->n_p == port)) { hsi_set_read_cb(dev, NULL); hsi_set_write_cb(dev, NULL); hsi_set_port_event_cb(dev, NULL); channel = &hsi_protocol_iface.channels[dev->n_ch]; channel->dev = NULL; channel->state = HSI_CHANNEL_STATE_UNAVAIL; ret = 0; } spin_unlock_bh(&hsi_protocol_iface.lock); return ret; } int __devinit hsi_protocol_probe(struct hsi_device *dev) { struct if_hsi_channel *channel; unsigned long *address; int port; printk(KERN_INFO "Inside Function %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]; spin_lock_bh(&hsi_protocol_iface.lock); if (test_bit(dev->n_ch, address) && (dev->n_p == port)) { printk(KERN_INFO "Regestering callback functions\n"); hsi_set_read_cb(dev, if_hsi_proto_read_done); hsi_set_write_cb(dev, if_hsi_proto_write_done); hsi_set_port_event_cb(dev, if_hsi_protocol_port_event); channel = &hsi_protocol_iface.channels[dev->n_ch]; channel->dev = dev; channel->state = 0; channel->rx_state = HSI_LL_RX_STATE_CLOSED; channel->tx_state = HSI_LL_TX_STATE_CLOSED; channel->tx_count = 0; channel->rx_count = 0; channel->tx_nak_count = 0; channel->rx_nak_count = 0; channel->rx_buf = NULL; channel->tx_buf = NULL; hsi_protocol_iface.init_chan_map ^= (1 << dev->n_ch); } spin_unlock_bh(&hsi_protocol_iface.lock); return 0; } int __init if_hsi_init(void) { struct if_hsi_channel *channel; int i, ret; struct proc_dir_entry *dir; for (i = 0; i < HSI_MAX_PORTS; i++) if_hsi_protocol_driver.ch_mask[i] = 0; for (i = 0; i < HSI_MAX_CHANNELS; i++) { channel = &hsi_protocol_iface.channels[i]; channel->dev = NULL; channel->opened = 0; channel->state = HSI_CHANNEL_STATE_UNAVAIL; channel->channel_id = i; spin_lock_init(&channel->lock); } /*Initialize waitqueue for IPC read*/ init_waitqueue_head(&ipc_read_wait); init_waitqueue_head(&ipc_write_wait); /*Select All Channels of PORT-1.*/ if_hsi_protocol_driver.ch_mask[0] = CHANNEL_MASK; ret = hsi_register_driver(&if_hsi_protocol_driver); if (ret) pr_err("Error while registering HSI driver %d", ret); dir = create_proc_read_entry("driver/hsi_cmd", 0, 0, hsi_protocol_proc, NULL); if (dir == NULL) printk(KERN_INFO "create_proc_read_entry Fail.\n"); printk(KERN_INFO "create_proc_read_entry Done.\n"); return ret; } 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; } u32 initialization = 0; /*Write data to channel*/ int write_hsi(u32 ch, u32 *data, int length) { int ret; //u32 cmd[4] = {0x00000000, 0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC}; struct if_hsi_channel *channel; struct task_struct *read_thread; channel = &hsi_protocol_iface.channels[ch]; channel->tx_buf = data; channel->tx_count = 0; //cmd[0] = protocol_create_cmd(HSI_LL_MSG_OPEN_CONN_OCTET, ch, (void *)&length); //printk(KERN_INFO "data ptr is %x\n", data); if (initialization == 0) { #if 0 /* ACWAKE ->HIGH */ ret = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_ACWAKE_UP, NULL); if (ret == 0) printk(KERN_INFO "ACWAKE pulled high in %s()\n", __func__); else printk(KERN_INFO "ACWAKE pulled high in %s() ERROR : %d\n", __func__, ret); #endif /*Creating read thread*/ read_thread = kthread_run(hsi_read_thrd, NULL, "hsi_read_thread"); initialization++; } /*Wait till previous data transfer is over*/ while (channel->tx_state != HSI_LL_TX_STATE_IDLE) { //printk(KERN_INFO "Wait 5ms previous data transfer isn't over %s()\n", __func__); //msleep(5); return -EAGAIN; } #if 1 /* ACWAKE ->HIGH */ ret = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_ACWAKE_UP, NULL); if (ret == 0) printk(KERN_INFO "ACWAKE pulled high in %s()\n", __func__); else printk(KERN_INFO "ACWAKE pulled high in %s() ERROR : %d\n", __func__, ret); #endif channel->tx_state = HSI_LL_TX_STATE_WAIT_FOR_ACK; //send_cmd(cmd, channel, data) //ret = hsi_proto_write(0, &cmd, 4*4); //printk(KERN_INFO "Write returned %d\n", ret); hsi_protocol_send_command(HSI_LL_MSG_OPEN_CONN_OCTET, ch, length); wait_event_interruptible(ipc_write_wait, channel->tx_count != 0); return channel->tx_count; } EXPORT_SYMBOL(write_hsi); int read_hsi(u8 *data, u32 ch, u32 *length) { int ret, size, tmp, actual_length; struct if_hsi_channel *channel; channel = &hsi_protocol_iface.channels[ch]; channel->rx_state = HSI_LL_RX_STATE_IDLE; //printk(KERN_INFO "In read_hsi() function, Sleeping ... channel-> %d\n", ch); wait_event_interruptible(ipc_read_wait, (channel->rx_count != 0)); //printk(KERN_INFO "In read_hsi() function, Waking Up ... channel-> %d\n", ch); actual_length = channel->rx_count; size = channel->rx_count; #if 0 // TEMP: send/read by 16 byte unit for v.11A(CP) if ((size > 16) && (size % 16)) size += (16 - (size % 16)); else if (size < 16) size = 16; #endif // For es 2.1 ver. if (size % 4) size += (4 - (size % 4)); ret = hsi_proto_read(ch, (u32 *)data, size); if (ret < 0) printk(KERN_INFO "Read in IPC failed, %s()\n", __func__); //printk(KERN_INFO "%s() read returned %d, actual_length = %d, ch-> %d\n", __func__, ret, actual_length, ch); //printk(KERN_INFO "%s() sending CONN_CLOSED.\n", __func__); tmp = hsi_protocol_send_command(HSI_LL_MSG_CONN_CLOSED, ch, 0); //printk(KERN_INFO "%s() Sending CONN_CLOSED Finished. ret = %d\n", __func__, tmp); *length = actual_length; channel->rx_count = 0; //printk(KERN_INFO "%s() RETURNING TO IPC with ret = %d\n", __func__, ret); return ret; } EXPORT_SYMBOL(read_hsi); //========================================================// // ++ Flashless Boot. ++ // //========================================================// int hsi_start_protocol_single(void) { int ret = 0; struct hst_ctx tx_config; struct hsr_ctx rx_config; /*Open channel 0 */ ret = if_hsi_openchannel(&hsi_protocol_iface.channels[0]); if (ret < 0) { pr_err("Can not Open channel 0. Can not start HSI protocol\n"); goto err; } else printk(KERN_INFO "if_hsi_openchannel() returned %d\n", ret); /*Set Tx Config*/ hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_GET_TX, &tx_config); tx_config.mode = 2; tx_config.channels = 1; tx_config.divisor = 0; ret = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_SET_TX, &tx_config); if (ret < 0) { printk(KERN_INFO "write_hsi_direct : SET_TX Fail : %d\n", ret); return ret; } hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_GET_RX, &rx_config); rx_config.mode = 2; rx_config.channels = 1; rx_config.divisor = 0; //rx_config.timeout = HZ / 2; ret = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_SET_RX, &rx_config); if (ret < 0) { printk(KERN_INFO "write_hsi_direct : SET_RX Fail : %d\n", ret); return ret; } /* ACWAKE ->HIGH */ ret = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_ACWAKE_UP, NULL); if (ret == 0) printk(KERN_INFO "ACWAKE pulled high in %s()\n", __func__); err: return ret; } EXPORT_SYMBOL(hsi_start_protocol_single); int hsi_reconfigure_protocol(void) { int ret = 0; /* ACWAKE ->LOW */ ret = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_ACWAKE_DOWN, NULL); if (ret == 0) printk(KERN_INFO "ACWAKE pulled low in %s()\n", __func__); else printk(KERN_INFO "ACWAKE down fail!! %d\n", ret); /*Clse channel 0 */ ret = if_hsi_closechannel(&hsi_protocol_iface.channels[0]); if (ret < 0) { pr_err("Can not Close channel 0. Can not Stop HSI protocol for flashless\n"); goto err; } printk(KERN_INFO "(%s)(%d) hsi_start_protocol Start.\n", __func__, __LINE__); hsi_start_protocol(); printk(KERN_INFO "(%s)(%d) hsi_start_protocol Done.\n", __func__, __LINE__); err: return ret; } EXPORT_SYMBOL(hsi_reconfigure_protocol); int write_hsi_direct(u32 *data, int length) { int retval = 0; #if 0 struct hst_ctx tx_config; printk(KERN_INFO "write_hsi_direct : len : %d\n", length); hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_GET_TX, &tx_config); tx_config.mode = 2; tx_config.channels = 1; tx_config.divisor = 47; retval = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_SET_TX, &tx_config); if (retval < 0) { printk(KERN_INFO "write_hsi_direct : SET_TX Fail : %d\n", retval); return retval; } printk(KERN_INFO "write_hsi_direct : SET_TX Successful\n"); retval = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_ACWAKE_UP, NULL); if (retval < 0) { printk(KERN_INFO "write_hsi_direct : ACWAKE High Fail : %d\n", retval); return retval; } #endif #if 0 if ((length > 16) && (length % 4)) length += (4 - (length % 4)); else if (length < 16) length = 16; #endif // printk(KERN_INFO "write_hsi_direct : new len : %d\n", length); retval = hsi_proto_write(0, data, length); if (retval < 0) { printk(KERN_INFO "write_hsi_direct : hsi_proto_write Fail : %d\n", retval); return retval; } //printk(KERN_INFO "write_hsi_direct : Write returned %d\n", retval); return retval; } EXPORT_SYMBOL(write_hsi_direct); int read_hsi_direct(u32 *data, int length) { int retval = 0; #if 0 struct hsr_ctx rx_config; printk(KERN_INFO "read_hsi_direct : len : %d\n", length); hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_GET_RX, &rx_config); rx_config.mode = 2; rx_config.channels = 1; rx_config.divisor = 47; retval = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_SET_RX, &rx_config); if (retval < 0) { printk(KERN_INFO "read_hsi_direct : SET_RX Fail : %d\n", retval); return retval; } printk(KERN_INFO "read_hsi_direct : SET_RX Successful\n"); retval = hsi_ioctl(hsi_protocol_iface.channels[0].dev, HSI_IOCTL_ACWAKE_UP, NULL); if (retval < 0) { printk(KERN_INFO "read_hsi_direct : ACWAKE High Fail : %d\n", retval); return retval; } printk(KERN_INFO "read_hsi_direct : ACWAKE High\n"); #endif #if 0 if ((length > 16) && (length % 4)) length += (4 - (length % 4)); else if (length < 16) length = 16; #endif //printk(KERN_INFO "read_hsi_direct : new len : %d\n", length); retval = hsi_proto_read(0, data, length); if (retval < 0) { printk(KERN_INFO "read_hsi_direct : hsi_proto_read Fail : %d\n", retval); return retval; } //printk(KERN_INFO "read_hsi_direct : Read returned %d\n", retval); return retval; } EXPORT_SYMBOL(read_hsi_direct); //========================================================// // -- Flashless Boot. -- // //========================================================//