aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax_cmc/download.c
diff options
context:
space:
mode:
authorDorian Snyder <dastin1015@gmail.com>2013-06-12 02:24:45 -0700
committerDorian Snyder <dastin1015@gmail.com>2013-06-20 00:06:04 -0700
commit4b2308ce699b9c599dd6e6acf57ac11f483381d9 (patch)
tree4c31179b06d094887b1c8ca70264cf8f184a5981 /drivers/net/wimax_cmc/download.c
parent855d6a6c1f7c54ef073caac3f6c5f9b1ed72eb4d (diff)
downloadkernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.zip
kernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.tar.gz
kernel_samsung_smdk4412-4b2308ce699b9c599dd6e6acf57ac11f483381d9.tar.bz2
d710: initial support for the Epic 4G Touch (SPH-D710)
Change-Id: Iafbd9fb45253b02d539ac0ba114f57b3bf9eeed4
Diffstat (limited to 'drivers/net/wimax_cmc/download.c')
-rwxr-xr-xdrivers/net/wimax_cmc/download.c227
1 files changed, 227 insertions, 0 deletions
diff --git a/drivers/net/wimax_cmc/download.c b/drivers/net/wimax_cmc/download.c
new file mode 100755
index 0000000..e51b210
--- /dev/null
+++ b/drivers/net/wimax_cmc/download.c
@@ -0,0 +1,227 @@
+/*
+ * download.c
+ *
+ * Firmware download (host booting) functions and definitions
+ */
+#include "headers.h"
+#include "download.h"
+#include "firmware.h"
+
+#include <linux/vmalloc.h>
+
+struct image_data g_wimax_image;
+
+int load_wimax_image(int mode)
+{
+ struct file *fp;
+ int read_size = 0;
+
+ if (mode == AUTH_MODE)
+ fp = klib_fopen(WIMAX_LOADER_PATH, O_RDONLY, 0); /* download mode */
+ else
+ fp = klib_fopen(WIMAX_IMAGE_PATH, O_RDONLY, 0); /* wimax mode */
+
+ if (fp) {
+ if (g_wimax_image.data == NULL) { /* check already allocated */
+ g_wimax_image.data = (u_char *)vmalloc(MAX_WIMAXFW_SIZE);
+
+ if (!g_wimax_image.data) {
+ dump_debug("Error: Memory alloc failure");
+ klib_fclose(fp);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ memset(g_wimax_image.data, 0, MAX_WIMAXFW_SIZE);
+ read_size = klib_flen_fcopy(g_wimax_image.data, MAX_WIMAXFW_SIZE, fp);
+
+ g_wimax_image.size = read_size;
+ g_wimax_image.address = CMC732_WIMAX_ADDRESS;
+ g_wimax_image.offset = 0;
+
+ klib_fclose(fp);
+ } else {
+ dump_debug("Error: WiMAX image file open failed");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+void unload_wimax_image(void)
+{
+ if (g_wimax_image.data != NULL) {
+ dump_debug("Delete the Image Loaded");
+ vfree(g_wimax_image.data);
+ g_wimax_image.data = NULL;
+ }
+}
+
+u_char send_cmd_packet(struct net_adapter *adapter, u_short cmd_id)
+{
+ struct hw_packet_header *pkt_hdr;
+ struct wimax_msg_header *msg_hdr;
+ u_char tx_buf[CMD_MSG_TOTAL_LENGTH];
+ int status = 0;
+ u_int offset;
+ u_int size;
+
+ pkt_hdr = (struct hw_packet_header *)tx_buf;
+ pkt_hdr->id0 = 'W';
+ pkt_hdr->id1 = 'C';
+ pkt_hdr->length = be16_to_cpu(CMD_MSG_TOTAL_LENGTH);
+
+ offset = sizeof(struct hw_packet_header);
+ msg_hdr = (struct wimax_msg_header *)(tx_buf + offset);
+ msg_hdr->type = be16_to_cpu(ETHERTYPE_DL);
+ msg_hdr->id = be16_to_cpu(cmd_id);
+ msg_hdr->length = be32_to_cpu(CMD_MSG_LENGTH);
+
+ size = CMD_MSG_TOTAL_LENGTH;
+
+ status = sd_send(adapter, tx_buf, size);
+ if (status != STATUS_SUCCESS) {
+ /* crc error or data error - set PCWRT '1' & send current type A packet again */
+ dump_debug("hwSdioWrite : crc or data error");
+ return status;
+ }
+ return status;
+}
+
+u_char send_image_info_packet(struct net_adapter *adapter, u_short cmd_id)
+{
+ struct hw_packet_header *pkt_hdr;
+ struct wimax_msg_header *msg_hdr;
+ u_int image_info[4];
+ u_char tx_buf[IMAGE_INFO_MSG_TOTAL_LENGTH];
+ int status;
+ u_int offset;
+ u_int size;
+
+ pkt_hdr = (struct hw_packet_header *)tx_buf;
+ pkt_hdr->id0 = 'W';
+ pkt_hdr->id1 = 'C';
+ pkt_hdr->length = be16_to_cpu(IMAGE_INFO_MSG_TOTAL_LENGTH);
+
+ offset = sizeof(struct hw_packet_header);
+ msg_hdr = (struct wimax_msg_header *)(tx_buf + offset);
+ msg_hdr->type = be16_to_cpu(ETHERTYPE_DL);
+ msg_hdr->id = be16_to_cpu(cmd_id);
+ msg_hdr->length = be32_to_cpu(IMAGE_INFO_MSG_LENGTH);
+
+ image_info[0] = 0;
+ image_info[1] = be32_to_cpu(g_wimax_image.size);
+ image_info[2] = be32_to_cpu(g_wimax_image.address);
+ image_info[3] = 0;
+
+ offset += sizeof(struct wimax_msg_header);
+ memcpy(&(tx_buf[offset]), image_info, sizeof(image_info));
+
+ size = IMAGE_INFO_MSG_TOTAL_LENGTH;
+ status = sd_send(adapter, tx_buf, size);
+
+ if (status != STATUS_SUCCESS) {
+ /* crc error or data error - set PCWRT '1' & send current type A packet again */
+ dump_debug("hwSdioWrite : crc error");
+ return status;
+ }
+ return status;
+}
+
+u_char send_image_data_packet(struct net_adapter *adapter, u_short cmd_id)
+{
+ struct hw_packet_header *pkt_hdr;
+ struct image_data_payload *pImageDataPayload;
+ struct wimax_msg_header *msg_hdr;
+ u_char *tx_buf = NULL;
+ int status;
+ u_int len;
+ u_int offset;
+ u_int size;
+
+ tx_buf = (u_char *)kmalloc(MAX_IMAGE_DATA_MSG_LENGTH, GFP_KERNEL);
+ if (tx_buf == NULL) {
+ dump_debug("MALLOC FAIL!!");
+ return -1;
+ }
+
+ pkt_hdr = (struct hw_packet_header *)tx_buf;
+ pkt_hdr->id0 = 'W';
+ pkt_hdr->id1 = 'C';
+
+ offset = sizeof(struct hw_packet_header);
+ msg_hdr = (struct wimax_msg_header *)(tx_buf + offset);
+ msg_hdr->type = be16_to_cpu(ETHERTYPE_DL);
+ msg_hdr->id = be16_to_cpu(cmd_id);
+
+ if (g_wimax_image.offset < (g_wimax_image.size - MAX_IMAGE_DATA_LENGTH))
+ len = MAX_IMAGE_DATA_LENGTH;
+ else
+ len = g_wimax_image.size - g_wimax_image.offset;
+
+ offset += sizeof(struct wimax_msg_header);
+ pImageDataPayload = (struct image_data_payload *)(tx_buf + offset);
+ pImageDataPayload->offset = be32_to_cpu(g_wimax_image.offset);
+ pImageDataPayload->size = be32_to_cpu(len);
+
+ memcpy(pImageDataPayload->data, g_wimax_image.data + g_wimax_image.offset, len);
+
+ size = len + 8; /* length of Payload offset + length + data */
+ pkt_hdr->length = be16_to_cpu(CMD_MSG_TOTAL_LENGTH + size);
+ msg_hdr->length = be32_to_cpu(size);
+
+ size = CMD_MSG_TOTAL_LENGTH + size;
+
+ status = sd_send(adapter, tx_buf, size);
+
+ if (status != STATUS_SUCCESS) {
+ /* crc error or data error - set PCWRT '1' & send current type A packet again */
+ dump_debug("hwSdioWrite : crc error");
+ kfree(tx_buf);
+ return status;
+ }
+
+ g_wimax_image.offset += len;
+
+ kfree(tx_buf);
+
+ return status;
+}
+
+/* used only during firmware download */
+u_int sd_send(struct net_adapter *adapter, u_char *buffer, u_int len)
+{
+ int nRet = 0;
+
+ int nWriteIdx;
+
+ len += (len & 1) ? 1 : 0;
+
+ if (adapter->halted || adapter->removed) {
+ dump_debug("Halted Already");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ sdio_claim_host(adapter->func);
+ hwSdioWriteBankIndex(adapter, &nWriteIdx, &nRet);
+
+ if(nRet || (nWriteIdx < 0) )
+ return STATUS_UNSUCCESSFUL;
+
+ sdio_writeb(adapter->func, (nWriteIdx + 1) % 15, SDIO_H2C_WP_REG, NULL);
+
+ nRet = sdio_memcpy_toio(adapter->func, SDIO_TX_BANK_ADDR+(SDIO_BANK_SIZE * nWriteIdx)+4, buffer, len);
+
+ if (nRet < 0) {
+ dump_debug("sd_send : error in sending packet!! nRet = %d",nRet);
+ }
+
+ nRet = sdio_memcpy_toio(adapter->func, SDIO_TX_BANK_ADDR + (SDIO_BANK_SIZE * nWriteIdx), &len, 4);
+
+ if (nRet < 0) {
+ dump_debug("sd_send : error in writing bank length!! nRet = %d",nRet);
+ }
+ sdio_release_host(adapter->func);
+
+ return nRet;
+}