diff options
author | Dorian Snyder <dastin1015@gmail.com> | 2013-06-12 02:24:45 -0700 |
---|---|---|
committer | Dorian Snyder <dastin1015@gmail.com> | 2013-06-20 00:06:04 -0700 |
commit | 4b2308ce699b9c599dd6e6acf57ac11f483381d9 (patch) | |
tree | 4c31179b06d094887b1c8ca70264cf8f184a5981 /drivers/net/wimax_cmc/download.c | |
parent | 855d6a6c1f7c54ef073caac3f6c5f9b1ed72eb4d (diff) | |
download | kernel_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-x | drivers/net/wimax_cmc/download.c | 227 |
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; +} |