aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
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
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')
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/Kconfig0
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/Makefile0
-rwxr-xr-xdrivers/net/wimax_cmc/buffer.h75
-rwxr-xr-xdrivers/net/wimax_cmc/control.c264
-rwxr-xr-xdrivers/net/wimax_cmc/ctl_types.h91
-rwxr-xr-xdrivers/net/wimax_cmc/download.c227
-rwxr-xr-xdrivers/net/wimax_cmc/download.h56
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/firmware.c25
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/firmware.h20
-rwxr-xr-xdrivers/net/wimax_cmc/hardware.c599
-rwxr-xr-xdrivers/net/wimax_cmc/headers.h116
-rwxr-xr-xdrivers/net/wimax_cmc/hw_types.h96
-rwxr-xr-xdrivers/net/wimax_cmc/receive.c301
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/wimax_i2c.c167
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/wimax_i2c.h1
-rwxr-xr-xdrivers/net/wimax_cmc/wimax_plat.h36
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/wimax_sdio.c108
-rwxr-xr-x[-rw-r--r--]drivers/net/wimax_cmc/wimax_sdio.h4
18 files changed, 2024 insertions, 162 deletions
diff --git a/drivers/net/wimax_cmc/Kconfig b/drivers/net/wimax_cmc/Kconfig
index 16efe94..16efe94 100644..100755
--- a/drivers/net/wimax_cmc/Kconfig
+++ b/drivers/net/wimax_cmc/Kconfig
diff --git a/drivers/net/wimax_cmc/Makefile b/drivers/net/wimax_cmc/Makefile
index e49f7fb..e49f7fb 100644..100755
--- a/drivers/net/wimax_cmc/Makefile
+++ b/drivers/net/wimax_cmc/Makefile
diff --git a/drivers/net/wimax_cmc/buffer.h b/drivers/net/wimax_cmc/buffer.h
new file mode 100755
index 0000000..f37d902
--- /dev/null
+++ b/drivers/net/wimax_cmc/buffer.h
@@ -0,0 +1,75 @@
+/*
+ * buffer.h
+ *
+ * Used q_send for the control and data packet sending, uses the BUFFER_DESCRIPTOR
+ * q_received used for the control packet receive, data packet sent directly
+ */
+#ifndef _WIMAX_BUFFER_H
+#define _WIMAX_BUFFER_H
+
+/* structures */
+struct buffer_descriptor {
+ struct list_head node; /* list node */
+ void *buffer; /* allocated buffer: It is used for copying and transfer */
+ u_long length; /* current data length */
+ u_short type; /* buffer type (used for control buffers) */
+};
+
+struct queue_info {
+ struct list_head head; /* list head */
+ spinlock_t lock; /* protection */
+};
+
+/******************************************************************************
+ * queue_init_list -- Macro which will initialize a queue to NULL.
+ ******************************************************************************/
+#define queue_init_list(_L) ((_L).next = (_L).prev = NULL)
+
+/******************************************************************************
+ * queue_empty -- Macro which checks to see if a queue is empty.
+ ******************************************************************************/
+#define queue_empty(_L) (queue_get_head((_L)) == NULL)
+
+/******************************************************************************
+ * queue_get_head -- Macro which returns the head of the queue, but does not
+ * remove the head from the queue.
+ ******************************************************************************/
+#define queue_get_head(_L) ((struct list_head *)((_L).next))
+
+/******************************************************************************
+ * queue_remove_head -- Macro which removes the head of the head of queue.
+ ******************************************************************************/
+#define queue_remove_head(_L) \
+{ \
+ struct list_head *h; \
+ if ((h = (struct list_head *)(_L).next)) { /* then fix up our our list to point to next elem */ \
+ if (!((_L).next = h->next)) /* rechain list pointer to next link */ \
+ /* if the list pointer is null, null out the reverse link */ \
+ (_L).prev = NULL; \
+ } \
+}
+
+/******************************************************************************
+ * queue_put_tail -- Macro which puts an element at the tail (end) of the queue.
+ ******************************************************************************/
+#define queue_put_tail(_L,_E) \
+{ \
+ if ((_L).prev) { \
+ ((struct list_head *)(_L).prev)->next = (struct list_head *)(&(_E)); \
+ (_L).prev = (struct list_head *)(&(_E)); \
+ } else \
+ (_L).next = (_L).prev = (struct list_head *)(&(_E)); \
+ (_E).next = NULL; \
+}
+
+/******************************************************************************
+ * queue_pop_head -- Macro which will pop the head off of a queue (list), and
+ * return it (this differs only from queueremovehead only in the 1st line)
+ ******************************************************************************/
+#define queue_pop_head(_L) \
+{ \
+ (struct list_head *) (_L).next; \
+ queue_remove_head(_L); \
+}
+
+#endif /* _WIMAX_BUFFER_H */
diff --git a/drivers/net/wimax_cmc/control.c b/drivers/net/wimax_cmc/control.c
new file mode 100755
index 0000000..b4abd60
--- /dev/null
+++ b/drivers/net/wimax_cmc/control.c
@@ -0,0 +1,264 @@
+/*
+ * control.c
+ *
+ * send and receive control packet and handle it
+ */
+#include "headers.h"
+
+u_int control_init(struct net_adapter *adapter)
+{
+ queue_init_list(adapter->ctl.q_received.head);
+ spin_lock_init(&adapter->ctl.q_received.lock);
+
+ queue_init_list(adapter->ctl.apps.process_list);
+ spin_lock_init(&adapter->ctl.apps.lock);
+
+ adapter->ctl.apps.ready = TRUE;
+
+ return STATUS_SUCCESS;
+}
+
+void control_remove(struct net_adapter *adapter)
+{
+ struct buffer_descriptor *dsc;
+ struct process_descriptor *process;
+ unsigned long flags;
+ /* Free the received control packets queue */
+ while (!queue_empty(adapter->ctl.q_received.head)) {
+ /* queue is not empty */
+ dump_debug("Freeing Control Receive Queue");
+ dsc = (struct buffer_descriptor *)
+ queue_get_head(adapter->ctl.q_received.head);
+ if (!dsc) {
+ dump_debug("Fail...node is null");
+ continue;
+ }
+ queue_remove_head(adapter->ctl.q_received.head);
+ if (dsc->buffer)
+ kfree(dsc->buffer);
+ if (dsc)
+ kfree(dsc);
+ }
+
+ /* process list */
+ if (adapter->ctl.apps.ready) {
+ if (!queue_empty(adapter->ctl.apps.process_list)) {
+ /* first time gethead needed to get the dsc nodes */
+ process = (struct process_descriptor *)queue_get_head(adapter->ctl.apps.process_list);
+ spin_lock_irqsave(&adapter->ctl.apps.lock, flags);
+ while (process != NULL) {
+ if (process->irp) {
+ process->irp = FALSE;
+ wake_up_interruptible(&process->read_wait);
+ }
+ process = (struct process_descriptor *)process->node.next;
+ dump_debug("sangam dbg : waking processes");
+ }
+ spin_unlock_irqrestore(&adapter->ctl.apps.lock, flags);
+ /* delay for the process release */
+ msleep(100);
+ }
+ }
+ adapter->ctl.apps.ready = FALSE;
+}
+
+/* add received packet to pending list */
+static void control_enqueue_buffer(struct net_adapter *adapter,
+ u_short type, void *buffer, u_long length)
+{
+ struct buffer_descriptor *dsc;
+ struct process_descriptor *process;
+
+ /* Queue and wake read only if process exist. */
+ process = process_by_type(adapter, type);
+ if (process) {
+ dsc = (struct buffer_descriptor *)
+ kmalloc(sizeof(struct buffer_descriptor),
+ GFP_ATOMIC);
+ if (dsc == NULL) {
+ dump_debug("dsc Memory Alloc Failure *****");
+ return;
+ }
+ dsc->buffer = kmalloc(length, GFP_ATOMIC);
+ if (dsc->buffer == NULL) {
+ kfree(dsc);
+ dump_debug("dsc->buffer Memory Alloc Failure *****");
+ return;
+ }
+
+ memcpy(dsc->buffer, buffer, length);
+ /* fill out descriptor */
+ dsc->length = length;
+ dsc->type = type;
+ /* add to pending list */
+ queue_put_tail(adapter->ctl.q_received.head, dsc->node)
+
+ if (process->irp) {
+ process->irp = FALSE;
+ wake_up_interruptible(&process->read_wait);
+ }
+ } else
+ dump_debug("Waiting process not found skip the packet");
+}
+
+/* receive control data */
+void control_recv(struct net_adapter *adapter, void *buffer, u_long length)
+{
+ struct eth_header *hdr;
+
+ /* dump rx control frame */
+ if (adapter->pdata->g_cfg->enable_dump_msg == 1)
+ dump_buffer("Control Rx", (u_char *)buffer + 12, length - 12);
+
+ /* check halt flag */
+ if (adapter->halted)
+ return;
+
+ hdr = (struct eth_header *)buffer;
+
+ /* not found, add to pending buffers list */
+ spin_lock(&adapter->ctl.q_received.lock);
+ control_enqueue_buffer(adapter, hdr->type, buffer, length);
+ spin_unlock(&adapter->ctl.q_received.lock);
+}
+
+u_int control_send(struct net_adapter *adapter, void *buffer, u_long length)
+{
+ if ((length + sizeof(struct hw_packet_header)) >= WIMAX_MAX_TOTAL_SIZE)
+ return STATUS_RESOURCES;
+ /* changed from SUCCESS return status */
+
+ return hw_send_data(adapter, buffer, length, CONTROL_PACKET);
+
+}
+
+struct process_descriptor *process_by_id(struct net_adapter *adapter, u_int id)
+{
+ struct process_descriptor *process;
+
+ if (queue_empty(adapter->ctl.apps.process_list)) {
+ dump_debug("process_by_id: Empty process list");
+ return NULL;
+ }
+
+ /* first time gethead needed to get the dsc nodes */
+ process = (struct process_descriptor *)
+ queue_get_head(adapter->ctl.apps.process_list);
+ while (process != NULL) {
+ if (process->id == id) /* process found */
+ return process;
+ process = (struct process_descriptor *)process->node.next;
+ }
+ dump_debug("process_by_id: process not found");
+
+ return NULL;
+}
+
+struct process_descriptor *process_by_type(struct net_adapter *adapter,
+ u_short type)
+{
+ struct process_descriptor *process;
+
+ if (queue_empty(adapter->ctl.apps.process_list)) {
+ dump_debug("process_by_type: Empty process list");
+ return NULL;
+ }
+
+ /* first time gethead needed to get the dsc nodes */
+ process = (struct process_descriptor *)
+ queue_get_head(adapter->ctl.apps.process_list);
+ while (process != NULL) {
+ if (process->type == type) /* process found */
+ return process;
+ process = (struct process_descriptor *)process->node.next;
+ }
+ dump_debug("process_by_type: process not found");
+
+ return NULL;
+}
+
+void remove_process(struct net_adapter *adapter, u_int id)
+{
+ struct process_descriptor *curElem;
+ struct process_descriptor *prevElem = NULL;
+
+ if (queue_empty(adapter->ctl.apps.process_list))
+ return;
+
+ /* first time get head needed to get the dsc nodes */
+ curElem = (struct process_descriptor *)
+ queue_get_head(adapter->ctl.apps.process_list);
+
+ for ( ; curElem != NULL; prevElem = curElem,
+ curElem = (struct process_descriptor *)
+ curElem->node.next) {
+ if (curElem->id == id) { /* process found */
+ if (prevElem == NULL) {
+ /* only one node present */
+ (adapter->ctl.apps.process_list).next =
+ (((struct list_head *)curElem)->next);
+ if (!((adapter->ctl.apps.process_list).next)) {
+ /*rechain list pointer to next link*/
+ dump_debug("sangam dbg first and only process delete");
+ (adapter->ctl.apps.process_list).prev = NULL;
+ }
+ } else if (((struct list_head *)curElem)->next ==
+ NULL) {
+ /* last node */
+ dump_debug("sangam dbg only last packet");
+ ((struct list_head *)prevElem)->next = NULL;
+ (adapter->ctl.apps.process_list).prev =
+ (struct list_head *)(prevElem);
+ } else {
+ /* middle node */
+ dump_debug("sangam dbg middle node");
+ ((struct list_head *)prevElem)->next =
+ ((struct list_head *)curElem)->next;
+ }
+
+ kfree(curElem);
+ break;
+ }
+ }
+}
+
+/* find buffer by buffer type */
+struct buffer_descriptor *buffer_by_type(struct list_head ListHead,
+ u_short type)
+{
+ struct buffer_descriptor *dsc;
+
+ if (queue_empty(ListHead))
+ return NULL;
+
+ /* first time gethead needed to get the dsc nodes */
+ dsc = (struct buffer_descriptor *)queue_get_head(ListHead);
+ while (dsc != NULL) {
+ if (dsc->type == type) /* process found */
+ return dsc;
+ dsc = (struct buffer_descriptor *)dsc->node.next;
+ }
+
+ return NULL;
+}
+
+void dump_buffer(const char *desc, u_char *buffer, u_int len)
+{
+ char print_buf[256] = {0};
+ char chr[8] = {0};
+ int i;
+
+ /* dump packets */
+ u_char *b = buffer;
+ dump_debug("%s (%d) =>", desc, len);
+
+ for (i = 0; i < len; i++) {
+ sprintf(chr, " %02x", b[i]);
+ strcat(print_buf, chr);
+ if (((i + 1) != len) && (i % 16 == 15)) {
+ dump_debug(print_buf);
+ memset(print_buf, 0x0, 256);
+ }
+ }
+ dump_debug(print_buf);
+}
diff --git a/drivers/net/wimax_cmc/ctl_types.h b/drivers/net/wimax_cmc/ctl_types.h
new file mode 100755
index 0000000..0c3543e
--- /dev/null
+++ b/drivers/net/wimax_cmc/ctl_types.h
@@ -0,0 +1,91 @@
+/*
+ * ctl_types.h
+ *
+ * Control types and definitions
+ */
+#ifndef _WIMAX_CTL_TYPES_H
+#define _WIMAX_CTL_TYPES_H
+
+#ifndef FILE_DEVICE_UNKNOWN
+#define FILE_DEVICE_UNKNOWN 0x89
+#endif
+
+/* Macro definition for defining IOCTL */
+#define CTL_CODE( DeviceType, Function, Method, Access ) \
+( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+/* Define the method codes for how buffers are passed for I/O and FS controls */
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+
+/*
+ Define the access check value for any access
+
+ The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
+ ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
+ constants *MUST* always be in sync.
+*/
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS (0x0001)
+#define FILE_WRITE_ACCESS (0x0002)
+
+#define CONTROL_ETH_TYPE_WCM 0x0015
+
+#define CONTROL_IOCTL_WRITE_REQUEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_POWER_CTL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_MODE_CHANGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x838, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_EEPROM_DOWNLOAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x839, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_SLEEP_MODE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83A, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_WRITE_REV CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83B, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_CHECK_CERT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83C, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define CONTROL_IOCTL_WIMAX_CHECK_CAL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x83D, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define MAX_APPLICATION_LEN 50
+
+#define ETHERNET_ADDRESS_LENGTH 6
+
+/* eth types for control message */
+enum {
+ ETHERTYPE_HIM = 0x1500,
+ ETHERTYPE_MC = 0x1501,
+ ETHERTYPE_DM = 0x1502,
+ ETHERTYPE_CT = 0x1503,
+ ETHERTYPE_DL = 0x1504,
+ ETHERTYPE_VSP = 0x1510,
+ ETHERTYPE_AUTH = 0x1521
+};
+
+/* eth header structure */
+#pragma pack(1)
+struct eth_header {
+ u_char dest[ETHERNET_ADDRESS_LENGTH];
+ u_char src[ETHERNET_ADDRESS_LENGTH];
+ u_short type;
+};
+#pragma pack()
+
+/* process element managed by control type */
+struct process_descriptor {
+ struct list_head node;
+ wait_queue_head_t read_wait;
+ u_long id;
+ u_short type;
+ u_short irp; /* Used for the read thread indication */
+};
+
+/* head structure for process element */
+struct ctl_app_descriptor {
+ struct list_head process_list; /* there could be undefined number of applications */
+ spinlock_t lock;
+ u_char ready;
+};
+
+struct ctl_info {
+ struct ctl_app_descriptor apps; /* application device structure */
+ struct queue_info q_received; /* pending queue */
+};
+
+#endif /* _WIMAX_CTL_TYPES_H */
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;
+}
diff --git a/drivers/net/wimax_cmc/download.h b/drivers/net/wimax_cmc/download.h
new file mode 100755
index 0000000..d46e6b6
--- /dev/null
+++ b/drivers/net/wimax_cmc/download.h
@@ -0,0 +1,56 @@
+/*
+ * download.h
+ *
+ * Firmware download (host booting) functions and definitions
+ */
+#ifndef _WIMAX_DOWNLOAD_H__
+#define _WIMAX_DOWNLOAD_H__
+
+#define CMC732_RAM_START 0xC0000000
+#define CMC732_WIMAX_ADDRESS CMC732_RAM_START
+
+#define CMD_MSG_TOTAL_LENGTH 12
+#define IMAGE_INFO_MSG_TOTAL_LENGTH 28
+#define CMD_MSG_LENGTH 0
+#define IMAGE_INFO_MSG_LENGTH 16
+#define MAX_IMAGE_DATA_LENGTH 3564
+#define MAX_IMAGE_DATA_MSG_LENGTH 4096
+
+#define FWDOWNLOAD_TIMEOUT 12000
+#define MAX_WIMAXFW_SIZE 2100000
+
+/* used for host boot (firmware download) */
+enum {
+ MSG_DRIVER_OK_REQ = 0x5010,
+ MSG_DRIVER_OK_RESP = 0x6010,
+ MSG_IMAGE_INFO_REQ = 0x3021,
+ MSG_IMAGE_INFO_RESP = 0x4021,
+ MSG_IMAGE_DATA_REQ = 0x3022,
+ MSG_IMAGE_DATA_RESP = 0x4022,
+ MSG_RUN_REQ = 0x5014,
+ MSG_RUN_RESP = 0x6014
+};
+
+struct image_data {
+ u_int size;
+ u_int address;
+ u_int offset;
+ struct mutex lock;
+ u_char *data;
+};
+
+struct image_data_payload {
+ u_int offset;
+ u_int size;
+ u_char data[MAX_IMAGE_DATA_LENGTH];
+};
+
+int load_wimax_image(int mode);
+void unload_wimax_image(void);
+
+u_char send_image_info_packet(struct net_adapter *adapter, u_short cmd_id);
+u_char send_image_data_packet(struct net_adapter *adapter, u_short cmd_id);
+u_char send_cmd_packet(struct net_adapter *adapter, u_short cmd_id);
+u_int sd_send(struct net_adapter *adapter, u_char *buffer, u_int len);
+
+#endif /* _WIMAX_DOWNLOAD_H__ */
diff --git a/drivers/net/wimax_cmc/firmware.c b/drivers/net/wimax_cmc/firmware.c
index d31eb8c..f4b6c9b 100644..100755
--- a/drivers/net/wimax_cmc/firmware.c
+++ b/drivers/net/wimax_cmc/firmware.c
@@ -5,7 +5,6 @@
* Firmware binary file is on the filesystem, read fild and send it through SDIO
*/
#include "firmware.h"
-#include <linux/wimax/samsung/wimax732.h>
#define SEEK_SET 0
#define SEEK_CUR 1
@@ -27,12 +26,8 @@
*************************************************************************/
struct file *klib_fopen(
const char *filename, /*!< filename to open */
- /*!< O_RDONLY, O_WRONLY, O_RDWR, O_CREAT,
- O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_SYNC,...*/
- int flags,
- /*!< file creation permisstion. S_IRxxx
- S_IWxxx S_IXxxx (xxx=USR,GRP,OTH), S_IRWXx(x=U,G,O)*/
- int mode
+ int flags, /*!< O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_SYNC, ... */
+ int mode /*!< file creation permisstion. S_IRxxx S_IWxxx S_IXxxx (xxx=USR,GRP,OTH), S_IRWXx(x=U,G,O) */
)
{
struct file *filp = filp_open(filename, flags, mode);
@@ -83,8 +78,7 @@ int klib_fseek(
if (pos < 0)
pos = 0;
- filp->f_pos = pos;
- return pos;
+ return (filp->f_pos = pos);
} else
return -ENOENT;
}
@@ -110,17 +104,17 @@ klib_fread(
mm_segment_t oldfs;
if (filp == NULL) {
- printk(KERN_INFO "filp == NULL\n");
+ printk(" filp == NULL\n");
return -ENOENT;
}
if (filp->f_op->read == NULL) {
- printk(KERN_INFO "filp->f_op->read == NULL\n");
+ printk(" filp->f_op->read == NULL\n");
return -ENOSYS;
}
if (((filp->f_flags & O_ACCMODE) & O_RDONLY) != 0) {
- printk(KERN_INFO "((filp->f_flags & O_ACCMODE) & O_RDONLY) != 0\n");
+ printk(" ((filp->f_flags & O_ACCMODE) & O_RDONLY) != 0\n");
return -EACCES;
}
@@ -214,12 +208,12 @@ int klib_fwrite(
mm_segment_t oldfs;
if (filp == NULL) {
- printk(KERN_INFO "filp == NULL\n");
+ printk(" filp == NULL\n");
return -ENOENT;
}
if (filp->f_op->write == NULL) {
- printk(KERN_INFO "filp->f_op->write == NULL\n");
+ printk(" filp->f_op->write == NULL\n");
return -ENOSYS;
}
@@ -238,10 +232,9 @@ void s3c_bat_use_wimax(int onoff)
if (!fp)
pr_err("open fail");
- if (onoff)
+ if (onoff)
klib_fwrite("1", 1, fp);
else
klib_fwrite("0", 1, fp);
klib_fclose(fp);
}
-EXPORT_SYMBOL(s3c_bat_use_wimax);
diff --git a/drivers/net/wimax_cmc/firmware.h b/drivers/net/wimax_cmc/firmware.h
index 862d0d8..9629344 100644..100755
--- a/drivers/net/wimax_cmc/firmware.h
+++ b/drivers/net/wimax_cmc/firmware.h
@@ -9,7 +9,7 @@
#include <linux/fs.h>
#include <linux/file.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
#define SEEK_SET 0
#define SEEK_CUR 1
@@ -18,12 +18,14 @@
/******************************************************************************
* Function Prototypes
******************************************************************************/
-struct file *klib_fopen(const char *filename, int flags, int mode);
-void klib_fclose(struct file *filp);
-int klib_fseek(struct file *filp, int offset, int whence);
-int klib_fread(char *buf, int len, struct file *filp);
-int klib_fgetc(struct file *filp);
-int klib_flength(struct file *filp);
-int klib_flen_fcopy(char *buf, int len, struct file *filp);
-int klib_fwrite(char *buf, int len, struct file *filp);
+struct file *klib_fopen (const char *filename, int flags, int mode);
+void klib_fclose (struct file *filp);
+int klib_fseek (struct file *filp, int offset, int whence);
+int klib_fread (char *buf, int len, struct file *filp);
+int klib_fgetc (struct file *filp);
+int klib_flength (struct file *filp);
+int klib_flen_fcopy (char *buf, int len, struct file *filp);
+int klib_fwrite (char *buf, int len, struct file *filp);
+
+void s3c_bat_use_wimax(int onoff);
#endif /* _WIMAX_FIRMWARE_H */
diff --git a/drivers/net/wimax_cmc/hardware.c b/drivers/net/wimax_cmc/hardware.c
new file mode 100755
index 0000000..7540584
--- /dev/null
+++ b/drivers/net/wimax_cmc/hardware.c
@@ -0,0 +1,599 @@
+/*
+ * hardware.c
+ *
+ * gpio control functions (power on/off, init/deinit gpios)
+ * data tx and tx thread implemented.
+ */
+#include "headers.h"
+#include "download.h"
+#include "wimax_plat.h"
+
+#include <mach/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <mach/hardware.h>
+#include <plat/sdhci.h>
+#include <plat/devs.h>
+#include <linux/spinlock.h>
+
+#define WIMAX_POWER_SUCCESS 0
+#define WIMAX_ALREADY_POWER_ON -1
+#define WIMAX_PROBE_FAIL -2
+#define WIMAX_ALREADY_POWER_OFF -3
+
+
+static void wimax_hostwake_task(unsigned long data)
+{
+ struct net_adapter *adapter = (struct net_adapter *)data;
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+
+ wake_lock_timeout(&g_cfg->wimax_wake_lock, 1 * HZ);
+
+}
+
+static irqreturn_t wimax_hostwake_isr(int irq, void *dev)
+{
+ struct net_adapter *adapter = (struct net_adapter *)dev;
+ tasklet_schedule(&adapter->hostwake_task);
+ return IRQ_HANDLED;
+}
+static int cmc732_setup_wake_irq(struct net_adapter *adapter)
+{
+ int rc = -EIO;
+ int irq;
+
+ rc = gpio_request(WIMAX_INT, "gpio_wimax_int");
+ if (rc < 0) {
+ dump_debug("%s: gpio %d request failed (%d)\n",
+ __func__, WIMAX_INT, rc);
+ return rc;
+ }
+
+ rc = gpio_direction_input(WIMAX_INT);
+ if (rc < 0) {
+ dump_debug("%s: failed to set gpio %d as input (%d)\n",
+ __func__, WIMAX_INT, rc);
+ goto err_gpio_direction_input;
+ }
+
+ irq = gpio_to_irq(WIMAX_INT);
+
+ rc = request_irq(irq, wimax_hostwake_isr, IRQF_TRIGGER_FALLING,
+ "wimax_int", adapter);
+ if (rc < 0) {
+ dump_debug("%s: request_irq(%d) failed for gpio %d (%d)\n",
+ __func__, irq,
+ WIMAX_INT, rc);
+ goto err_request_irq;
+ }
+
+ rc = enable_irq_wake(irq);
+
+ if (rc < 0) {
+ dump_debug("%s: enable_irq_wake(%d) failed for gpio %d (%d)\n",
+ __func__, irq,
+ WIMAX_INT, rc);
+ goto err_enable_irq_wake;
+ }
+
+ adapter->wake_irq = irq;
+
+ tasklet_init(&adapter->hostwake_task,
+ wimax_hostwake_task, (unsigned long)adapter);
+
+ goto done;
+err_enable_irq_wake:
+ free_irq(irq, adapter);
+err_request_irq:
+err_gpio_direction_input:
+ gpio_free(WIMAX_INT);
+done:
+ return rc;
+
+}
+void cmc732_release_wake_irq(struct net_adapter *adapter)
+{
+ if (adapter->wake_irq) {
+ disable_irq_wake(adapter->wake_irq);
+ free_irq(adapter->wake_irq, adapter);
+ gpio_free(WIMAX_INT);
+ tasklet_kill(&adapter->hostwake_task);
+ }
+}
+
+
+
+int hw_start(struct net_adapter *adapter)
+{
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+
+ if (load_wimax_image(g_cfg->wimax_mode))
+ return STATUS_UNSUCCESSFUL;
+
+ adapter->download_complete = FALSE;
+
+ if (adapter->downloading) {
+ sdio_claim_host(adapter->func);
+ send_cmd_packet(adapter, MSG_DRIVER_OK_REQ);
+ sdio_release_host(adapter->func);
+ switch (wait_event_interruptible_timeout
+ (adapter->download_event,
+ (adapter->download_complete == TRUE),
+ msecs_to_jiffies(FWDOWNLOAD_TIMEOUT))) {
+ case 0:
+ /* timeout */
+ dump_debug("Error hw_start :"
+ "F/W Download timeout failed");
+ adapter->halted = TRUE;
+ return STATUS_UNSUCCESSFUL;
+ case -ERESTARTSYS:
+ /* Interrupted by signal */
+ dump_debug("Error hw_start : -ERESTARTSYS retry");
+ return STATUS_UNSUCCESSFUL;
+ default:
+ /* normal condition check */
+ if (adapter->removed == TRUE
+ || adapter->halted == TRUE) {
+ dump_debug("Error hw_start : "
+ " F/W Download surprise removed");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /*Setup hostwake interrupt*/
+
+ if (cmc732_setup_wake_irq(adapter) < 0)
+ dump_debug("hw_start : "
+ " Error setting up wimax_int");
+
+
+ break;
+ }
+ adapter->downloading = FALSE;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+int hw_stop(struct net_adapter *adapter)
+{
+ adapter->halted = TRUE;
+
+
+ /* Stop Sdio Interface */
+ sdio_claim_host(adapter->func);
+ sdio_release_irq(adapter->func);
+ sdio_disable_func(adapter->func);
+ sdio_release_host(adapter->func);
+
+ /*Remove wakeup interrupt*/
+ cmc732_release_wake_irq(adapter);
+
+ return STATUS_SUCCESS;
+}
+
+int hw_init(struct net_adapter *adapter)
+{
+
+ /* set WIMAX_WAKEUP & WIMAX_IF_MODE0 */
+ adapter->pdata->set_mode();
+
+ /* initilize hardware info structure */
+ memset(&adapter->hw, 0x0, sizeof(struct hardware_info));
+
+ /* allocate sdio receive buffer once */
+ if (adapter->hw.receive_buffer == NULL) {
+ dump_debug("Alloc ReceiveBuffer");
+ /* the extra 8 bytes space required to copy ethernet header */
+ adapter->hw.receive_buffer = kmalloc(SDIO_BUFFER_SIZE + 8,
+ GFP_ATOMIC | GFP_DMA);
+ if (adapter->hw.receive_buffer == NULL) {
+ dump_debug("kmalloc fail!!");
+ return -ENOMEM;
+ }
+ }
+
+ /* initialize sdio receive buffer */
+ memset(adapter->hw.receive_buffer, 0x0, SDIO_BUFFER_SIZE + 8);
+
+ /* For sending data and control packets */
+ queue_init_list(adapter->hw.q_send.head);
+ spin_lock_init(&adapter->hw.q_send.lock);
+
+ init_waitqueue_head(&adapter->download_event);
+
+ return STATUS_SUCCESS;
+}
+
+void hw_remove(struct net_adapter *adapter)
+{
+ struct buffer_descriptor *dsc;
+
+ /* Free the pending data packets and control packets */
+ spin_lock(&adapter->hw.q_send.lock);
+ while (!queue_empty(adapter->hw.q_send.head)) {
+ dump_debug("Freeing q_send");
+ dsc = (struct buffer_descriptor *)
+ queue_get_head(adapter->hw.q_send.head);
+ if (!dsc) {
+ dump_debug("Fail...node is null");
+ continue;
+ }
+ queue_remove_head(adapter->hw.q_send.head);
+ kfree(dsc->buffer);
+ kfree(dsc);
+ }
+ spin_unlock(&adapter->hw.q_send.lock);
+
+}
+
+int con0_poll_thread(void *data)
+{
+ struct net_adapter *adapter = (struct net_adapter *)data;
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+ int prev_val = 0;
+ int curr_val = 0;
+
+ wake_lock(&g_cfg->wimax_tx_lock);
+
+ while ((!adapter->halted)) {
+ curr_val = gpio_get_value(GPIO_WIMAX_CON0);
+ if ((prev_val && (!curr_val)) || (curr_val == GPIO_LEVEL_LOW)) {
+ adapter->pdata->restore_uart_path();
+ break;
+ }
+ prev_val = curr_val;
+ msleep(40);
+ }
+ wake_unlock(&g_cfg->wimax_tx_lock);
+ do_exit(0);
+ return 0;
+}
+
+
+
+
+
+/* get MAC address from device */
+void hw_get_mac_address(void *data)
+{
+ struct net_adapter *adapter = (struct net_adapter *)data;
+ struct hw_private_packet req;
+ int nResult = 0;
+ int retry = 5;
+ req.id0 = 'W';
+ req.id1 = 'P';
+ req.code = HwCodeMacRequest;
+ req.value = 0;
+ do {
+ if (adapter == NULL)
+ break;
+
+ if (retry == 2) //odb backup takes 5.8sec
+ msleep(6000);
+
+ sdio_claim_host(adapter->func);
+ nResult = sd_send(adapter, (u_char *)&req,
+ sizeof(struct hw_private_packet));
+ sdio_release_host(adapter->func);
+
+ if (nResult != STATUS_SUCCESS)
+ dump_debug("hw_get_mac_address: sd_send fail!!");
+ msleep(300);
+ retry--;
+ /*in case we dont get MAC we need
+ to release power lock and probe finsh */
+ if (!retry) {
+ adapter->download_complete = TRUE;
+ wake_up_interruptible(&adapter->download_event);
+ msleep(100);
+
+ }
+ } while ((!adapter->mac_ready) && (!adapter->halted) && retry);
+
+ adapter->pdata->g_cfg->powerup_done = true ;
+ dump_debug("MAC thread exit");
+ return;
+}
+
+u_int hw_send_data(struct net_adapter *adapter,
+ void *buffer , u_long length, bool control)
+{
+ struct buffer_descriptor *dsc;
+ struct hw_packet_header *hdr;
+ struct net_device *net = adapter->net;
+ u_char *ptr;
+ unsigned long flags ;
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+
+ spin_lock_irqsave(&adapter->hw.q_send.lock, flags);
+
+ dsc = (struct buffer_descriptor *)kmalloc(
+ sizeof(struct buffer_descriptor), GFP_ATOMIC | GFP_DMA);
+ if (dsc == NULL)
+ return STATUS_RESOURCES;
+
+ dsc->buffer = kmalloc(BUFFER_DATA_SIZE , GFP_ATOMIC | GFP_DMA);
+ if (dsc->buffer == NULL) {
+ kfree(dsc);
+ return STATUS_RESOURCES;
+ }
+
+ ptr = dsc->buffer;
+
+ /* shift data pointer */
+ ptr += sizeof(struct hw_packet_header);
+#ifdef HARDWARE_USE_ALIGN_HEADER
+ ptr += 2;
+#endif
+ hdr = (struct hw_packet_header *)dsc->buffer;
+
+ if (control) {
+ memcpy(ptr, buffer + (ETHERNET_ADDRESS_LENGTH * 2),
+ length - (ETHERNET_ADDRESS_LENGTH * 2));
+
+ /* add packet header */
+ hdr->id0 = 'W';
+ hdr->id1 = 'C';
+ hdr->length = (u_short)length - (ETHERNET_ADDRESS_LENGTH * 2);
+
+ /* set length */
+ dsc->length = (u_short)length - (ETHERNET_ADDRESS_LENGTH * 2)
+ + sizeof(struct hw_packet_header);
+ #ifdef HARDWARE_USE_ALIGN_HEADER
+ dsc->length += 2;
+ #endif
+
+ /* dump control packet for debug */
+ if (g_cfg->enable_dump_msg == 1)
+ dump_buffer("Control Tx",
+ (u_char *)dsc->buffer + 6, dsc->length - 6);
+ } else {
+
+ length -= (ETHERNET_ADDRESS_LENGTH * 2);
+ buffer += (ETHERNET_ADDRESS_LENGTH * 2);
+
+ memcpy(ptr, buffer, length);
+
+ hdr->id0 = 'W';
+ hdr->id1 = 'D';
+ hdr->length = (u_short)length;
+
+ dsc->length = length + sizeof(struct hw_packet_header);
+ #ifdef HARDWARE_USE_ALIGN_HEADER
+ dsc->length += 2;
+ #endif
+ adapter->netstats.tx_packets++;
+ adapter->netstats.tx_bytes += dsc->length;
+
+ /* add statistics */
+ if (!netif_running(net))
+ dump_debug("!netif_running");
+
+ }
+
+
+ queue_put_tail(adapter->hw.q_send.head, dsc->node);
+ spin_unlock_irqrestore(&adapter->hw.q_send.lock, flags);
+
+ queue_work(adapter->wimax_workqueue, &adapter->transmit_work);
+ return STATUS_SUCCESS;
+}
+
+u_int sd_send_data(struct net_adapter *adapter, struct buffer_descriptor *dsc)
+{
+ int nRet = 0;
+ int nWriteIdx;
+ dsc->length += (dsc->length & 1) ? 1 : 0;
+
+#ifdef HARDWARE_USE_ALIGN_HEADER
+ if (dsc->length > SDIO_MAX_BYTE_SIZE)
+ dsc->length = (dsc->length + SDIO_MAX_BYTE_SIZE)
+ & ~(SDIO_MAX_BYTE_SIZE);
+#endif
+
+ if (adapter->halted) {
+ dump_debug("Halted Already");
+ return STATUS_UNSUCCESSFUL;
+ }
+ hwSdioWriteBankIndex(adapter, &nWriteIdx, &nRet);
+
+ if (nRet || (nWriteIdx < 0)) {
+ dump_debug("sd_send_data : "
+ " error fetch bank index!! nRet = %d", nRet);
+ 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,
+ dsc->buffer, dsc->length);
+
+ if (nRet < 0)
+ dump_debug("sd_send_data :"
+ " error writing dsc packet!! nRet = %d", nRet);
+ nRet = sdio_memcpy_toio(adapter->func,
+ SDIO_TX_BANK_ADDR + (SDIO_BANK_SIZE * nWriteIdx),
+ &(dsc->length), 4);
+
+ if (nRet < 0)
+ dump_debug("sd_send_data :"
+ "error writing bank length info!! nRet = %d", nRet);
+ return nRet;
+}
+
+/* Return packet for packet buffer freeing */
+void hw_return_packet(struct net_adapter *adapter, u_short type)
+{
+ struct buffer_descriptor *curElem;
+ struct buffer_descriptor *prevElem = NULL;
+
+ if (queue_empty(adapter->ctl.q_received.head))
+ return;
+
+ /* first time get head needed to get the dsc nodes */
+ curElem = (struct buffer_descriptor *)
+ queue_get_head(adapter->ctl.q_received.head);
+
+ for ( ; curElem != NULL; prevElem = curElem,
+ curElem = (struct buffer_descriptor *)curElem->node.next) {
+ if (curElem->type == type) {
+ /* process found*/
+ if (prevElem == NULL) {
+ /* First node or only
+ one node present to delete */
+ adapter->ctl.q_received.head.next =
+ ((struct list_head *)curElem)->next;
+ if (!((adapter->ctl.q_received.head).next)) {
+ /* rechain list pointer to next link */
+ /* if the list pointer is null,
+ null out the reverse link */
+ (adapter->ctl.q_received.head).prev =
+ NULL;
+ }
+ } else if (((struct list_head *)curElem)->next
+ == NULL) {
+ /* last node */
+ ((struct list_head *)prevElem)->next = NULL;
+ (adapter->ctl.q_received.head).prev =
+ (struct list_head *)(&prevElem);
+ } else {
+ /* middle node */
+ ((struct list_head *)prevElem)->next =
+ ((struct list_head *)curElem)->next;
+ }
+
+ kfree(curElem->buffer);
+ kfree(curElem);
+ break;
+ }
+ }
+}
+
+int hw_device_wakeup(struct net_adapter *adapter)
+{
+ int rc = 0;
+
+ adapter->pdata->wakeup_assert(1);
+
+ while (!adapter->pdata->is_modem_awake()) {
+ if (rc == 0)
+ dump_debug("hw_device_wakeup (CON0 status):"
+ " waiting for modem awake");
+ rc++;
+ if (rc > WAKEUP_MAX_TRY) {
+ dump_debug("hw_device_wakeup (CON0 status):"
+ " modem wake up time out!!");
+ return -1;
+ }
+ msleep(WAKEUP_TIMEOUT/2);
+ adapter->pdata->wakeup_assert(0);
+ msleep(WAKEUP_TIMEOUT/2);
+ adapter->pdata->wakeup_assert(1);
+ s3c_bat_use_wimax(1);
+ }
+ if (rc != 0)
+ dump_debug("hw_device_wakeup (CON0 status): modem awake");
+ adapter->pdata->wakeup_assert(0);
+
+ return 0;
+}
+
+/*
+This Work is responsible for Transmiting Both Control And Data packet
+*/
+
+void hw_transmit_thread(struct work_struct *work)
+{
+ struct buffer_descriptor *dsc;
+ struct hw_private_packet hdr;
+ struct net_adapter *adapter;
+ int nRet = 0;
+ int modem_reset = false;
+ struct wimax_cfg *g_cfg;
+
+ adapter = container_of(work, struct net_adapter, transmit_work);
+ g_cfg = adapter->pdata->g_cfg;
+ wake_lock(&g_cfg->wimax_tx_lock);
+
+ if (!gpio_get_value(WIMAX_EN)) {
+ dump_debug("WiMAX Power OFF!! (TX)");
+ goto exit;
+ }
+
+ mutex_lock(&adapter->rx_lock);
+
+ while (!queue_empty(adapter->hw.q_send.head)) {
+ if (adapter->halted) {
+ /* send stop message */
+ hdr.id0 = 'W';
+ hdr.id1 = 'P';
+ hdr.code = HwCodeHaltedIndication;
+ hdr.value = 0;
+
+ if (sd_send(adapter, (unsigned char *)&hdr,
+ sizeof(struct hw_private_packet)))
+ dump_debug("halted,"
+ " send HaltIndication to FW err");
+ modem_reset = true;
+ break;
+ }
+
+ if (!g_cfg->modem_reset_flag) {
+ dump_debug("modem_reset_flag is not set");
+ break;
+ }
+
+ if(hw_device_wakeup(adapter)) {
+ modem_reset = true;
+ break;
+ }
+
+ dsc = (struct buffer_descriptor *)
+ queue_get_head(adapter->hw.q_send.head);
+
+ if (!dsc->buffer) {
+ dump_debug("dsc->buffer is NULL");
+ break;
+ }
+
+ if (!dsc) {
+ dump_debug("Fail...node is null");
+ break;
+ }
+
+ sdio_claim_host(adapter->func);
+ nRet = sd_send_data(adapter, dsc);
+ sdio_release_host(adapter->func);
+ queue_remove_head(adapter->hw.q_send.head);
+ kfree(dsc->buffer);
+ kfree(dsc);
+ if (nRet != STATUS_SUCCESS) {
+ sdio_claim_host(adapter->func);
+ sdio_release_irq(adapter->func);
+ sdio_release_host(adapter->func);
+ ++adapter->XmitErr;
+ dump_debug("SendData Fail******");
+ if (nRet == -ENOMEDIUM || nRet == /*-ETIMEOUT*/-110) {
+ dump_debug("%s: No medium or timeout error", __func__);
+ // adapter->halted = TRUE;
+ }
+ modem_reset = true;
+ break;
+ }
+ }
+
+ if(modem_reset) {
+ while (!g_cfg->modem_reset_flag) {
+ dump_debug("Waiting for PM_POST_SUSPEND notifier");
+ msleep(100);
+ }
+ adapter->pdata->power(0);
+ dump_debug("Modem reset done");
+ }
+
+ mutex_unlock(&adapter->rx_lock);
+exit:
+ wake_unlock(&g_cfg->wimax_tx_lock);
+ return ;
+}
diff --git a/drivers/net/wimax_cmc/headers.h b/drivers/net/wimax_cmc/headers.h
new file mode 100755
index 0000000..f6a5b84
--- /dev/null
+++ b/drivers/net/wimax_cmc/headers.h
@@ -0,0 +1,116 @@
+/*
+ * headers.h
+ *
+ * Global definitions and fynctions
+ */
+#ifndef _WIMAX_HEADERS_H
+#define _WIMAX_HEADERS_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/proc_fs.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/mmc/sdio_func.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+#include <linux/wakelock.h>
+#include <linux/wimax/samsung/wimax732.h>
+#include "buffer.h"
+#include "wimax_sdio.h"
+
+#define WIMAXMAC_TXT_PATH "/efs/WiMAXMAC.txt"
+#define WIMAX_IMAGE_PATH "/system/etc/wimaxfw.bin"
+#define WIMAX_LOADER_PATH "/system/etc/wimaxloader.bin"
+#define WIMAX_BOOTIMAGE_PATH "/system/etc/wimax_boot.bin"
+
+#define STATUS_SUCCESS ((u_long)0x00000000L)
+#define STATUS_PENDING ((u_long)0x00000103L) /* The operation that was requested is pending completion */
+#define STATUS_RESOURCES ((u_long)0x00001003L)
+#define STATUS_RESET_IN_PROGRESS ((u_long)0xc001000dL)
+#define STATUS_DEVICE_FAILED ((u_long)0xc0010008L)
+#define STATUS_NOT_ACCEPTED ((u_long)0x00010003L)
+#define STATUS_FAILURE ((u_long)0xC0000001L)
+#define STATUS_UNSUCCESSFUL ((u_long)0xC0000002L) /* The requested operation was unsuccessful */
+#define STATUS_CANCELLED ((u_long)0xC0000003L)
+
+#ifndef TRUE_FALSE_
+#define TRUE_FALSE_
+enum BOOL {
+ FALSE,
+ TRUE
+};
+#endif
+
+#define HARDWARE_USE_ALIGN_HEADER
+
+#define dump_debug(args...) \
+{ \
+ printk(KERN_ALERT"\x1b[1;33m[WiMAX] "); \
+ printk(args); \
+ printk("\x1b[0m\n"); \
+}
+
+
+/* external functions & variables */
+extern void set_wimax_pm(void(*suspend)(void), void(*resume)(void));
+extern void unset_wimax_pm(void);
+extern int cmc732_sdio_reset_comm(struct mmc_card *card);
+extern u_int system_rev;
+
+/* receive.c functions */
+u_int process_sdio_data(struct net_adapter *adapter, void *buffer, u_long length, long Timeout);
+
+/* control.c functions */
+u_int control_send(struct net_adapter *adapter, void *buffer, u_long length);
+void control_recv(struct net_adapter *adapter, void *buffer, u_long length);
+u_int control_init(struct net_adapter *adapter);
+void control_remove(struct net_adapter *adapter);
+
+struct process_descriptor *process_by_id(struct net_adapter *adapter, u_int id);
+struct process_descriptor *process_by_type(struct net_adapter *adapter, u_short type);
+void remove_process(struct net_adapter *adapter, u_int id);
+
+u_long buffer_count(struct list_head ListHead);
+struct buffer_descriptor *buffer_by_type(struct list_head ListHead, u_short type);
+void dump_buffer(const char *desc, u_char *buffer, u_int len);
+
+/* hardware.c functions */
+void switch_eeprom_ap(void);
+void switch_eeprom_wimax(void);
+void switch_usb_ap(void);
+void switch_usb_wimax(void);
+void display_gpios(void); /* display GPIO status used by WiMAX module */
+void switch_uart_ap(void);
+void switch_uart_wimax(void);
+void hw_init_gpios(void);
+void hw_deinit_gpios(void);
+
+u_int sd_send(struct net_adapter *adapter, u_char *buffer, u_int len);
+u_int sd_send_data(struct net_adapter *adapter, struct buffer_descriptor *dsc);
+u_int hw_send_data(struct net_adapter *adapter, void *buffer, u_long length,bool);
+void hw_return_packet(struct net_adapter *adapter, u_short type);
+
+void s3c_bat_use_wimax(int onoff);
+
+int gpio_wimax_poweron (void);
+int gpio_wimax_poweroff (void);
+
+int hw_start(struct net_adapter *adapter);
+int hw_stop(struct net_adapter *adapter);
+int hw_init(struct net_adapter *adapter);
+void hw_remove(struct net_adapter *adapter);
+void hw_get_mac_address(void *data);
+int con0_poll_thread(void *data);
+void hw_transmit_thread(struct work_struct *work);
+void adapter_interrupt(struct sdio_func *func);
+/* structures for global access */
+extern struct net_adapter *g_adapter;
+
+#endif /* _WIMAX_HEADERS_H */
diff --git a/drivers/net/wimax_cmc/hw_types.h b/drivers/net/wimax_cmc/hw_types.h
new file mode 100755
index 0000000..3a1606c
--- /dev/null
+++ b/drivers/net/wimax_cmc/hw_types.h
@@ -0,0 +1,96 @@
+/**
+ * hw_types.h
+ *
+ * Hardware types and definitions
+ */
+#ifndef _WIMAX_HW_TYPES_H
+#define _WIMAX_HW_TYPES_H
+
+#include "ctl_types.h"
+
+/* private protocol defines */
+#define HW_PROT_VALUE_LINK_DOWN 0x00
+#define HW_PROT_VALUE_LINK_UP 0xff
+
+/* SDIO general defines */
+#define SDIO_BANK_SIZE 4096 /* size of a bank in cmc's rx and tx buffers */
+#define SDIO_MAX_BLOCK_SIZE 2048 /* maximum block size (SDIO) */
+#define SDIO_MAX_BYTE_SIZE 511 /* maximum size in byte mode */
+#define SDIO_BUFFER_SIZE SDIO_MAX_BLOCK_SIZE
+/*
+ *We need the HEADER_MANIPULATION_OFFSET because
+ *we now use only one buffer while receiving data.
+ *since the ehternet header is larger than the hardware packet header,
+ *we need to keep some space at the beginning of the buffer to accomodate the
+ *ethernet header. 8 bytes is enough for this purpose.
+ */
+#define HEADER_MANIPULATION_OFFSET 8
+/* SDIO function addresses */
+#define SDIO_TX_BANK_ADDR 0x1000
+#define SDIO_RX_BANK_ADDR 0x10000
+#define SDIO_INT_STATUS_REG 0xC0
+#define SDIO_INT_STATUS_CLR_REG 0xC4
+
+#define SDIO_C2H_WP_REG 0xE4
+#define SDIO_C2H_RP_REG 0xE8
+#define SDIO_H2C_WP_REG 0xEC
+#define SDIO_H2C_RP_REG 0xF0
+
+/* SDIO function registers */
+#define SDIO_INT_DATA_READY 0x01
+#define SDIO_INT_ERROR 0x02
+
+#define WAKEUP_MAX_TRY 20
+#define WAKEUP_TIMEOUT 300
+#define CONTROL_PACKET 1
+#define DATA_PACKET 0
+
+/* packet types */
+enum {
+ HwPktTypeNone = 0xff00,
+ HwPktTypePrivate,
+ HwPktTypeControl,
+ HwPktTypeData,
+ HwPktTypeTimeout
+};
+
+/* private packet opcodes */
+enum {
+ HwCodeMacRequest = 0x01,
+ HwCodeMacResponse,
+ HwCodeLinkIndication,
+ HwCodeRxReadyIndication,
+ HwCodeHaltedIndication,
+ HwCodeIdleNtfy,
+ HwCodeWakeUpNtfy
+};
+
+
+#pragma pack(1)
+struct hw_packet_header {
+ char id0; /* packet ID */
+ char id1;
+ u_short length; /* packet length */
+};
+
+struct hw_private_packet {
+ char id0; /* packet ID */
+ char id1;
+ u_char code; /* command code */
+ u_char value; /* command value */
+};
+#pragma pack()
+
+struct wimax_msg_header {
+ u_short type;
+ u_short id;
+ u_int length;
+};
+
+struct hardware_info {
+ void *receive_buffer;
+ u_char eth_header[ETHERNET_ADDRESS_LENGTH * 2]; /* ethernet header */
+ struct queue_info q_send; /* send pending queue */
+};
+
+#endif /* _WIMAX_HW_TYPES_H */
diff --git a/drivers/net/wimax_cmc/receive.c b/drivers/net/wimax_cmc/receive.c
new file mode 100755
index 0000000..a0e43d1
--- /dev/null
+++ b/drivers/net/wimax_cmc/receive.c
@@ -0,0 +1,301 @@
+/*
+ * receive.c
+ *
+ * handle download packet, private cmd and control/data packet
+ */
+#include "headers.h"
+#include "wimax_plat.h"
+#include "firmware.h"
+#include "download.h"
+
+#include <plat/sdhci.h>
+#include <plat/devs.h>
+#include <linux/mmc/host.h>
+#include <linux/kthread.h>
+extern struct image_data g_wimax_image;
+
+void process_indicate_packet(struct net_adapter *adapter, u_char *buffer)
+{
+ struct wimax_msg_header *packet;
+ char *tmp_byte;
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+
+ packet = (struct wimax_msg_header *)buffer;
+
+ if (packet->type == be16_to_cpu(ETHERTYPE_DL)) {
+ switch (be16_to_cpu(packet->id)) {
+ case MSG_DRIVER_OK_RESP:
+ dump_debug("process_indicate_packet: MSG_DRIVER_OK_RESP");
+ send_image_info_packet(adapter, MSG_IMAGE_INFO_REQ);
+ break;
+ case MSG_IMAGE_INFO_RESP:
+ dump_debug("process_indicate_packet: MSG_IMAGE_INFO_RESP");
+ send_image_data_packet(adapter, MSG_IMAGE_DATA_REQ);
+ break;
+ case MSG_IMAGE_DATA_RESP:
+ if (g_wimax_image.offset == g_wimax_image.size) {
+ dump_debug("process_indicate_packet: Image Download Complete");
+ send_cmd_packet(adapter, MSG_RUN_REQ); /* Run Message Send */
+ } else
+ send_image_data_packet(adapter, MSG_IMAGE_DATA_REQ);
+ break;
+ case MSG_RUN_RESP:
+ tmp_byte = (char *)(buffer + sizeof(struct wimax_msg_header));
+
+ if (*tmp_byte == 0x01) {
+ dump_debug("process_indicate_packet: MSG_RUN_RESP");
+
+ if (g_cfg->wimax_mode == SDIO_MODE || g_cfg->wimax_mode == DM_MODE
+ || g_cfg->wimax_mode == USB_MODE
+ || g_cfg->wimax_mode == USIM_RELAY_MODE) {
+
+ dump_debug("%s: F/W Download Complete and Running ",__func__);
+ dump_debug("Wait for SDIO ready...");
+ msleep(1200); /* IMPORTANT!! wait for cmc730 can handle mac req packet */
+
+ kernel_thread((int (*)(void *))hw_get_mac_address, adapter, 0);
+ } else if (g_cfg->wimax_mode == WTM_MODE) {
+ adapter->download_complete = TRUE;
+ wake_up_interruptible(&adapter->download_event);
+ adapter->pdata->g_cfg->powerup_done = true ;
+ adapter->wtm_task = kthread_create(
+ con0_poll_thread, adapter, "%s",
+ "wimax_con0_poll_thread");
+ if (adapter->wtm_task)
+ wake_up_process(
+ adapter->wtm_task);
+ } else if (g_cfg->wimax_mode == AUTH_MODE) {
+ adapter->download_complete = TRUE;
+ wake_up_interruptible(&adapter->download_event);
+ adapter->pdata->g_cfg->powerup_done = true ;
+ }
+ }
+ break;
+ default:
+ dump_debug("process_indicate_packet: Unkown type");
+ break;
+ }
+ }
+ else
+ dump_debug("process_indicate_packet - is not download pakcet");
+}
+
+u_long process_private_cmd(struct net_adapter *adapter, void *buffer)
+{
+ struct hw_private_packet *cmd;
+ u_char *bufp;
+ struct wimax_cfg *g_cfg = adapter->pdata->g_cfg;
+ cmd = (struct hw_private_packet *)buffer;
+
+ switch (cmd->code) {
+ case HwCodeMacResponse: {
+ u_char mac_addr[ETHERNET_ADDRESS_LENGTH];
+ bufp = (u_char *)buffer;
+
+ /* processing for mac_req request */
+ #ifndef PRODUCT_SHIP
+ dump_debug("MAC address = %02x:%02x:%02x:%02x:%02x:%02x",
+ bufp[3], bufp[4], bufp[5], bufp[6], bufp[7], bufp[8]);
+ #endif
+ memcpy(mac_addr, bufp + 3, ETHERNET_ADDRESS_LENGTH);
+
+ /* create ethernet header */
+ memcpy(adapter->hw.eth_header, mac_addr, ETHERNET_ADDRESS_LENGTH);
+ memcpy(adapter->hw.eth_header + ETHERNET_ADDRESS_LENGTH, mac_addr, ETHERNET_ADDRESS_LENGTH);
+ adapter->hw.eth_header[(ETHERNET_ADDRESS_LENGTH * 2) - 1] += 1;
+
+ memcpy(adapter->net->dev_addr, bufp + 3, ETHERNET_ADDRESS_LENGTH);
+ adapter->mac_ready = TRUE;
+
+ if (adapter->downloading) {
+ adapter->download_complete = TRUE;
+ wake_up_interruptible(&adapter->download_event);
+ }
+ return (sizeof(struct hw_private_packet) + ETHERNET_ADDRESS_LENGTH - sizeof(u_char));
+ }
+ case HwCodeLinkIndication: {
+ if ((cmd->value == HW_PROT_VALUE_LINK_DOWN)
+ && (adapter->media_state != MEDIA_DISCONNECTED)) {
+ dump_debug("LINK_DOWN_INDICATION");
+ s3c_bat_use_wimax(0);
+
+ /* set values */
+ adapter->media_state = MEDIA_DISCONNECTED;
+
+ /* indicate link down */
+ netif_stop_queue(adapter->net);
+ netif_carrier_off(adapter->net);
+ } else if ((cmd->value == HW_PROT_VALUE_LINK_UP)
+ && (adapter->media_state != MEDIA_CONNECTED)) {
+ dump_debug("LINK_UP_INDICATION");
+
+ s3c_bat_use_wimax(1);
+ /* set values */
+ adapter->media_state = MEDIA_CONNECTED;
+ adapter->net->mtu = WIMAX_MTU_SIZE;
+
+ /* indicate link up */
+ netif_start_queue(adapter->net);
+ netif_carrier_on(adapter->net);
+ }
+ break;
+ }
+ case HwCodeHaltedIndication: {
+ dump_debug("Device is about to reset, stop driver");
+ break;
+ }
+ case HwCodeRxReadyIndication: {
+ dump_debug("Device RxReady");
+ /* to start the data packet send queue again after stopping in xmit */
+ if (adapter->media_state == MEDIA_CONNECTED)
+ netif_wake_queue(adapter->net);
+ break;
+ }
+ case HwCodeIdleNtfy: {
+ /* set idle / vi */
+
+ dump_debug("process_private_cmd: HwCodeIdleNtfy");
+
+ s3c_bat_use_wimax(0);
+ break;
+ }
+ case HwCodeWakeUpNtfy: {
+ /* IMPORTANT!! at least 4 sec is required after modem waked up */
+ wake_lock_timeout(&g_cfg->wimax_wake_lock, 4 * HZ);
+ dump_debug("process_private_cmd: HwCodeWakeUpNtfy");
+ s3c_bat_use_wimax(1);
+ break;
+ }
+ default:
+ dump_debug("Command = %04x", cmd->code);
+ break;
+ }
+
+ return sizeof(struct hw_private_packet);
+}
+
+u_int process_sdio_data(struct net_adapter *adapter,
+ void *buffer, u_long length, long Timeout)
+{
+ struct hw_packet_header *hdr;
+ struct net_device *net = adapter->net;
+ u_char *ofs = (u_char *)buffer;
+ int res = 0;
+ u_int machdrlen = (ETHERNET_ADDRESS_LENGTH * 2);
+ u_int rlen = length;
+ u_long type;
+ u_short data_len;
+ struct sk_buff *skb;
+ while ((int)rlen > 0) {
+ hdr = (struct hw_packet_header *)ofs;
+ type = HwPktTypeNone;
+
+ if (unlikely(hdr->id0 != 'W')) { /* "WD", "WC", "WP" or "WE" */
+ if (rlen > 4) {
+ dump_debug("Wrong packet ID (%02x %02x)", hdr->id0, hdr->id1);
+ dump_buffer("Wrong packet", (u_char *)ofs, rlen);
+ }
+ /* skip rest of packets */
+ return 0;
+ }
+
+ /* check packet type */
+ switch (hdr->id1) {
+ case 'P': {
+ u_long l = 0;
+ type = HwPktTypePrivate;
+
+ /* process packet */
+ l = process_private_cmd(adapter, ofs);
+
+ /* shift */
+ ofs += l;
+ rlen -= l;
+
+ /* process next packet */
+ continue;
+ }
+ case 'C':
+ type = HwPktTypeControl;
+ break;
+ case 'D':
+ type = HwPktTypeData;
+ break;
+ case 'E':
+ /* skip rest of buffer */
+ return 0;
+ default:
+ dump_debug("hwParseReceivedData : Wrong packet ID [%02x %02x]",
+ hdr->id0, hdr->id1);
+ /* skip rest of buffer */
+ return 0;
+ }
+
+ if (likely(!adapter->downloading)) {
+ if (unlikely(hdr->length > WIMAX_MAX_TOTAL_SIZE
+ || ((hdr->length + sizeof(struct hw_packet_header)) > rlen))) {
+ dump_debug("Packet length is too big (%d)", hdr->length);
+ /* skip rest of packets */
+ return 0;
+ }
+ }
+
+ /* change offset */
+ ofs += sizeof(struct hw_packet_header);
+ rlen -= sizeof(struct hw_packet_header);
+
+ /* process download packet, data and control packet */
+ if (likely(!adapter->downloading))
+ {
+#ifdef HARDWARE_USE_ALIGN_HEADER
+ ofs += 2;
+ rlen -= 2;
+#endif
+ /* store the packet length */
+ /* because we will overwrite the hardware packet header */
+ data_len = hdr->length;
+ /* copy the MAC to ofs buffer */
+ memcpy((u_char *)ofs - machdrlen, adapter->hw.eth_header, machdrlen);
+
+ if (unlikely(type == HwPktTypeControl))
+ control_recv(adapter, (u_char *)ofs -machdrlen,
+ data_len + machdrlen);
+ else {
+
+ skb = dev_alloc_skb(data_len + machdrlen + 2);
+ if(!skb)
+ {
+ dump_debug("MEMORY PINCH: unable to allocate skb");
+ return -ENOMEM;
+ }
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb, (data_len + machdrlen)),
+ (u_char *)ofs -machdrlen,
+ (data_len + machdrlen));
+ skb->dev = net;
+ skb->protocol = eth_type_trans(skb, net);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ res = netif_rx(skb);
+
+ adapter->netstats.rx_packets++;
+ adapter->netstats.rx_bytes += (data_len + machdrlen);
+
+
+ }
+ /* restore the hardware packet length information */
+ hdr->length = data_len;
+ } else {
+ hdr->length -= sizeof(struct hw_packet_header);
+ process_indicate_packet(adapter, ofs);
+ }
+ /*
+ * If the packet is unreasonably long, quietly drop it rather than
+ * kernel panicing by calling skb_put.
+ */
+ /* shift */
+ ofs += hdr->length;
+ rlen-= hdr->length;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wimax_cmc/wimax_i2c.c b/drivers/net/wimax_cmc/wimax_i2c.c
index 018bfd3..474688a 100644..100755
--- a/drivers/net/wimax_cmc/wimax_i2c.c
+++ b/drivers/net/wimax_cmc/wimax_i2c.c
@@ -3,6 +3,7 @@
*
* EEPROM access functions
*/
+//#include "download.h"
#include "wimax_i2c.h"
#include "firmware.h"
#include <linux/i2c.h>
@@ -28,7 +29,7 @@
struct boot_image_data g_wimax_image;
-static void wimax_i2c_reset(void);
+void wimax_i2c_reset(void);
void dump_buffer(const char *desc, u_char *buffer, u_int len)
{
@@ -62,9 +63,8 @@ void eeprom_poweron(void)
gpio_set_value(EEPROM_SCL, GPIO_LEVEL_HIGH);
gpio_set_value(EEPROM_SDA, GPIO_LEVEL_HIGH);
- /* SEL = 1 to switch i2c-eeprom path to AP */
- gpio_set_value(I2C_SEL, GPIO_LEVEL_HIGH);
- usleep_range(10000, 10000);
+ gpio_set_value(I2C_SEL, GPIO_LEVEL_HIGH); // SEL = 1 to switch i2c-eeprom path to AP
+ msleep(10);
/* power on */
@@ -73,7 +73,7 @@ void eeprom_poweron(void)
msleep(100);
wimax_i2c_reset();
- usleep_range(10000, 10000);
+ msleep(10);
}
void eeprom_poweroff(void)
@@ -81,8 +81,7 @@ void eeprom_poweroff(void)
/* power off */
gpio_set_value(WIMAX_EN, GPIO_LEVEL_LOW);
- /* SEL = 0 to switch i2c-eeprom path to wimax */
- gpio_set_value(I2C_SEL, GPIO_LEVEL_LOW);
+ gpio_set_value(I2C_SEL, GPIO_LEVEL_LOW); // SEL = 0 to switch i2c-eeprom path to wimax
msleep(100);
@@ -145,8 +144,7 @@ void wimax_i2c_init(void)
gpio_set_value(EEPROM_SDA, GPIO_LEVEL_LOW);
udelay(2);
- /* send 7 bits address */
- wimax_i2c_write_byte(DEVICE_ADDRESS, 7);
+ wimax_i2c_write_byte(DEVICE_ADDRESS, 7); /* send 7 bits address */
}
void wimax_i2c_deinit(void)
@@ -284,7 +282,7 @@ int wimax_i2c_eeprom_address(short addr)
/* send 2 bytes address */
wimax_i2c_write_byte(buf[1], 8);
- if (wimax_i2c_check_ack())
+ if(wimax_i2c_check_ack())
return -1;
wimax_i2c_write_byte(buf[0], 8);
return wimax_i2c_check_ack();
@@ -292,8 +290,9 @@ int wimax_i2c_eeprom_address(short addr)
int wimax_i2c_write_buffer(char *data, int len)
{
- int i;
- for (i = 0; i < len; i++) {
+ int i;
+
+ for(i = 0; i < len; i++) {
wimax_i2c_write_byte(data[i], 8); /* 1 byte data */
if (wimax_i2c_check_ack())
return -1;
@@ -352,19 +351,19 @@ int wimax_i2c_write(u_short addr, u_char *data, int length)
struct i2c_msg msg;
data_buffer[0] = (unsigned char)((addr >> 8) & 0xff);
data_buffer[1] = (unsigned char)(addr & 0xff);
- while (length) {
- len = (length > MAX_BOOT_WRITE_LENGTH) ?
- MAX_BOOT_WRITE_LENGTH : length ;
+ while(length)
+ {
+ len = (length > MAX_BOOT_WRITE_LENGTH)? MAX_BOOT_WRITE_LENGTH : length ;
memcpy(data_buffer+WIMAX_EEPROM_ADDRLEN, data, len);
msg.addr = pclient->addr;
- msg.flags = 0; /*write*/
+ msg.flags = 0; //write
msg.len = (u16)length+WIMAX_EEPROM_ADDRLEN;
msg.buf = data_buffer;
rc = i2c_transfer(pclient->adapter, &msg, 1);
if (rc < 0)
return rc;
- length -= len;
- data += len;
+ length-=len;
+ data+=len;
}
return 0;
}
@@ -376,11 +375,11 @@ int wimax_i2c_read(u_short addr, u_char *data, int length)
data_buffer[0] = (unsigned char)((addr >> 8) & 0xff);
data_buffer[1] = (unsigned char)(addr & 0xff);
msgs[0].addr = pclient->addr;
- msgs[0].flags = 0; /*write*/
+ msgs[0].flags = 0; //write
msgs[0].len = WIMAX_EEPROM_ADDRLEN;
msgs[0].buf = data_buffer;
msgs[1].addr = pclient->addr;
- msgs[1].flags = I2C_M_RD; /*read*/
+ msgs[1].flags = I2C_M_RD; //read
msgs[1].len = length;
msgs[1].buf = data;
return i2c_transfer(pclient->adapter, msgs, 2);
@@ -398,9 +397,8 @@ static ssize_t eeprom_show(struct device *dev,
}
-static ssize_t eeprom_store(struct device *dev,
- struct device_attribute *attr,
- const char *buffer, size_t count) {
+static ssize_t eeprom_store(struct device *dev,
+ struct device_attribute *attr, const char *buffer, size_t count) {
if (strncmp(buffer, "wb00", 4) == 0) {
pr_debug("Write EEPROM!!");
@@ -426,7 +424,7 @@ static ssize_t eeprom_store(struct device *dev,
} else if (strncmp(buffer, "wrev", 4) == 0) {
pr_debug("Write Rev!!");
eeprom_write_rev();
- } else
+ } else
pr_debug("Wrong option");
return count;
@@ -465,8 +463,8 @@ int wmxeeprom_remove(struct i2c_client *client)
return 0;
}
-const struct i2c_device_id wmxeeprom_id[] = {
- { "wmxeeprom", 0 },
+const struct i2c_device_id wmxeeprom_id[]={
+ { "wmxeeprom",0 },
{ }
};
@@ -499,7 +497,7 @@ int load_wimax_boot(void)
if (fp) {
pr_debug("LoadWiMAXBootImage ..");
- g_wimax_image.data = vmalloc(MAX_WIMAXBOOTIMAGE_SIZE);
+ g_wimax_image.data = (u_char *)vmalloc(MAX_WIMAXBOOTIMAGE_SIZE);
if (!g_wimax_image.data) {
pr_debug("Error: Memory alloc failure.");
klib_fclose(fp);
@@ -507,8 +505,7 @@ int load_wimax_boot(void)
}
memset(g_wimax_image.data, 0, MAX_WIMAXBOOTIMAGE_SIZE);
- read_size = klib_flen_fcopy(g_wimax_image.data,
- MAX_WIMAXBOOTIMAGE_SIZE, fp);
+ read_size = klib_flen_fcopy(g_wimax_image.data, MAX_WIMAXBOOTIMAGE_SIZE, fp);
g_wimax_image.size = read_size;
g_wimax_image.address = 0;
g_wimax_image.offset = 0;
@@ -534,10 +531,12 @@ int write_rev(void)
/* swap */
val = be32_to_cpu(system_rev);
- do {
+ do
+ {
err = wimax_i2c_write(0x7080, (char *)(&val), 4);
- } while (err < 0 ? ((retry--) > 0) : 0);
- if (retry < 0)
+ }
+ while(err<0?((retry--)>0):0);
+ if(retry<0)
pr_debug("eeprom error");
return err ;
}
@@ -549,10 +548,12 @@ void erase_cert(void)
int retry = 100;
int err;
- do {
+ do
+ {
err = wimax_i2c_write(0x5800, buf, len);
- } while (err < 0 ? ((retry--) > 0) : 0);
- if (retry < 0)
+ }
+ while(err<0?((retry--)>0):0);
+ if(retry<0)
pr_debug("eeprom error");
}
@@ -563,17 +564,18 @@ int check_cert(void)
int retry = 100;
int err;
- do {
+ do
+ {
err = wimax_i2c_read(0x5800, buf, len);
- } while (err < 0 ? ((retry--) > 0) : 0);
- if (retry < 0)
+ }
+ while(err<0?((retry--)>0):0);
+ if(retry<0)
pr_debug("eeprom error");
dump_buffer("Certification", (u_char *)buf, (u_int)len);
/* check "Cert" */
- if (buf[0] == 0x43 && buf[1] == 0x65 &&
- buf[2] == 0x72 && buf[3] == 0x74)
+ if (buf[0] == 0x43 && buf[1] == 0x65 && buf[2] == 0x72 && buf[3] == 0x74)
return 0;
return -1;
@@ -587,10 +589,12 @@ int check_cal(void)
int retry = 100;
int err;
- do {
+ do
+ {
err = wimax_i2c_read(0x5400, buf, len);
- } while (err < 0 ? ((retry--) > 0) : 0);
- if (retry < 0)
+ }
+ while(err<0?((retry--)>0):0);
+ if(retry<0)
pr_debug("eeprom error");
dump_buffer("Calibration", (u_char *)buf, (u_int)len);
@@ -616,7 +620,7 @@ void eeprom_read_boot()
eeprom_poweron();
- buf = kmalloc(4096, GFP_KERNEL);
+ buf = (char *)kmalloc(4096, GFP_KERNEL);
if (buf == NULL) {
pr_debug("eeprom_read_boot: MALLOC FAIL!!");
return;
@@ -625,12 +629,12 @@ void eeprom_read_boot()
addr = 0x0;
for (j = 0; j < 1; j++) { /* read 4K */
len = 4096;
- do {
+ do
+ {
err = wimax_i2c_read(addr, buf, len);
- } while (err < 0 ? ((retry--) > 0) : 0);
-
- {
- /* dump boot data */
+ }
+ while(err<0?((retry--)>0):0);
+ { /* dump boot data */
char print_buf[256] = {0};
char chr[8] = {0};
@@ -657,7 +661,7 @@ void eeprom_read_boot()
kfree(buf);
eeprom_poweroff();
- if (retry < 0)
+ if(retry<0)
pr_debug("eeprom error");
}
@@ -674,23 +678,22 @@ void eeprom_read_all()
eeprom_poweron();
/* allocate 4K buffer */
- buf = kmalloc(4096, GFP_KERNEL);
+ buf = (char *)kmalloc(4096, GFP_KERNEL);
if (buf == NULL) {
pr_debug("eeprom_read_all: MALLOC FAIL!!");
return;
}
addr = 0x0;
-
- /* read 64K */
- for (j = 0; j < 16; j++) {
+ for (j = 0; j < 16; j++) /* read 64K */
+ {
len = 4096;
- do {
+ do
+ {
err = wimax_i2c_read(addr, buf, len);
- } while (err < 0 ? ((retry--) > 0) : 0);
-
- {
- /* dump EEPROM */
+ }
+ while(err<0?((retry--)>0):0);
+ { /* dump EEPROM */
char print_buf[256] = {0};
char chr[8] = {0};
@@ -718,7 +721,7 @@ void eeprom_read_all()
kfree(buf);
eeprom_poweroff();
- if (retry < 0)
+ if(retry<0)
pr_debug("eeprom error");
}
@@ -734,13 +737,15 @@ void eeprom_erase_all()
memset(buf, 0xff, 128);
for (i = 0; i < 512; i++) { /* clear all EEPROM */
pr_debug("ERASE [0x%04x]\n", i * 128);
- do {
+ do
+ {
err = wimax_i2c_write(128 * i, buf, 128);
- } while (err < 0 ? ((retry--) > 0) : 0);
+ }
+ while(err<0?((retry--)>0):0);
}
eeprom_poweroff();
- if (retry < 0)
+ if(retry<0)
pr_debug("eeprom error");
}
@@ -762,28 +767,28 @@ int eeprom_write_boot(void)
g_wimax_image.offset = 0;
while (g_wimax_image.size > g_wimax_image.offset) {
- buffer = (u_char *)(g_wimax_image.data + g_wimax_image.offset);
+ buffer =(u_char *)(g_wimax_image.data + g_wimax_image.offset);
ucsize = MAX_BOOT_WRITE_LENGTH;
/* write buffer */
- do {
- err = wimax_i2c_write(
- (u_short)g_wimax_image.offset, buffer, ucsize);
- } while (err < 0 ? ((retry--) > 0) : 0);
+ do
+ {
+ err = wimax_i2c_write((u_short)g_wimax_image.offset, buffer, ucsize);
+ }
+ while(err<0?((retry--)>0):0);
g_wimax_image.offset += MAX_BOOT_WRITE_LENGTH;
- if ((g_wimax_image.size - g_wimax_image.offset)
- < MAX_BOOT_WRITE_LENGTH) {
- buffer = (u_char *)(g_wimax_image.data +
- g_wimax_image.offset);
+ if ((g_wimax_image.size - g_wimax_image.offset) < MAX_BOOT_WRITE_LENGTH) {
+ buffer = (u_char *)(g_wimax_image.data + g_wimax_image.offset);
ucsize = g_wimax_image.size - g_wimax_image.offset;
/* write last data */
- do {
- err = wimax_i2c_write(
- (u_short)g_wimax_image.offset, buffer, ucsize);
- } while (err < 0 ? ((retry--) > 0) : 0);
+ do
+ {
+ err = wimax_i2c_write((u_short)g_wimax_image.offset, buffer, ucsize);
+ }
+ while(err<0?((retry--)>0):0);
g_wimax_image.offset += MAX_BOOT_WRITE_LENGTH;
}
@@ -796,12 +801,12 @@ int eeprom_write_boot(void)
vfree(g_wimax_image.data);
g_wimax_image.data = NULL;
}
-
- if (retry < 0)
+ if(retry<0)
+ {
pr_debug("eeprom error");
- else
- pr_debug("EEPROM WRITING DONE.");
-
+ }else{
+ pr_debug("EEPROM WRITING DONE.");
+}
return err;
}
diff --git a/drivers/net/wimax_cmc/wimax_i2c.h b/drivers/net/wimax_cmc/wimax_i2c.h
index cadd762..dc4fd3b 100644..100755
--- a/drivers/net/wimax_cmc/wimax_i2c.h
+++ b/drivers/net/wimax_cmc/wimax_i2c.h
@@ -5,6 +5,7 @@
*/
#ifndef __WIMAX_I2C_H__
#define __WIMAX_I2C_H__
+//#define DRIVER_BIT_BANG
#include <linux/mutex.h>
#define WIMAX_BOOTIMAGE_PATH "/system/etc/wimax_boot.bin"
diff --git a/drivers/net/wimax_cmc/wimax_plat.h b/drivers/net/wimax_cmc/wimax_plat.h
new file mode 100755
index 0000000..b71f055
--- /dev/null
+++ b/drivers/net/wimax_cmc/wimax_plat.h
@@ -0,0 +1,36 @@
+/**
+ * wimax_plat.h
+ *
+ * GPIO settings for specific HW
+ */
+#ifndef __WIMAX_PLAT_H__
+#define __WIMAX_PLAT_H__
+
+#define WIMAX_EN GPIO_WIMAX_EN
+#define WIMAX_RESET GPIO_WIMAX_RESET_N
+#define WIMAX_USB_EN GPIO_WIMAX_USB_EN
+
+#define DEVICE_HSMMC s3c_device_hsmmc3
+
+#define WIMAX_WAKEUP GPIO_WIMAX_WAKEUP
+#define WIMAX_IF_MODE0 GPIO_WIMAX_IF_MODE0
+#define WIMAX_IF_MODE1 GPIO_WIMAX_IF_MODE1
+#define WIMAX_CON0 GPIO_WIMAX_CON0
+#define WIMAX_CON1 GPIO_WIMAX_CON1
+#define WIMAX_CON2 GPIO_WIMAX_CON2
+#define WIMAX_INT GPIO_WIMAX_INT
+
+#define I2C_SEL GPIO_WIMAX_I2C_CON
+#define EEPROM_SCL GPIO_CMC_SCL_18V
+#define EEPROM_SDA GPIO_CMC_SDA_18V
+
+#define UART_SEL1 GPIO_UART_SEL1
+#define UART_SEL GPIO_UART_SEL
+#if defined(CONFIG_MACH_C1_REV02)
+#define USB_SEL GPIO_USB_SW_EN_WIMAX
+#endif /* CONFIG_MACH_C1_REV02 */
+#define DBGEN GPIO_WIMAX_DBGEN_28V//TBD
+#define GPIO_LEVEL_LOW 0
+#define GPIO_LEVEL_HIGH 1
+#define GPIO_LEVEL_NONE 2
+#endif /* __WIMAX_PLAT_H__ */
diff --git a/drivers/net/wimax_cmc/wimax_sdio.c b/drivers/net/wimax_cmc/wimax_sdio.c
index ece4b04..7e57a29 100644..100755
--- a/drivers/net/wimax_cmc/wimax_sdio.c
+++ b/drivers/net/wimax_cmc/wimax_sdio.c
@@ -370,58 +370,60 @@ void control_recv(struct net_adapter *adapter, void *buffer, u32 length)
mutex_unlock(&adapter->control_lock);
}
-void prepare_skb(struct net_adapter *adapter, struct sk_buff *rx_skb)
+void prepare_skb(struct net_adapter *adapter, struct sk_buff *rx_skb )
{
- skb_reserve(rx_skb,
- (ETHERNET_ADDRESS_LENGTH * 2) +
- NET_IP_ALIGN);
+ skb_reserve(rx_skb,
+ (ETHERNET_ADDRESS_LENGTH * 2) +
+ NET_IP_ALIGN);
- memcpy(skb_push(rx_skb,
- (ETHERNET_ADDRESS_LENGTH * 2)),
- adapter->eth_header,
- (ETHERNET_ADDRESS_LENGTH * 2));
+ memcpy(skb_push(rx_skb,
+ (ETHERNET_ADDRESS_LENGTH * 2)),
+ adapter->eth_header,
+ (ETHERNET_ADDRESS_LENGTH * 2));
- rx_skb->dev = adapter->net;
- rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
+ rx_skb->dev = adapter->net;
+ rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
}
void flush_skb(struct net_adapter *adapter)
{
- if (adapter->rx_skb) {
- dev_kfree_skb(adapter->rx_skb);
- adapter->rx_skb = NULL;
- }
+ if (adapter->rx_skb) {
+ dev_kfree_skb(adapter->rx_skb);
+ adapter->rx_skb = NULL;
+ }
}
struct sk_buff *fetch_skb(struct net_adapter *adapter)
{
- struct sk_buff *ret_skb;
- if (adapter->rx_skb) {
- ret_skb = adapter->rx_skb;
- adapter->rx_skb = NULL;
- return ret_skb;
- }
- ret_skb = dev_alloc_skb(WIMAX_MTU_SIZE+2+
- (ETHERNET_ADDRESS_LENGTH * 2) +
- NET_IP_ALIGN);
- if (!ret_skb) {
- pr_debug("unable to allocate skb");
- return NULL;
- }
- prepare_skb(adapter, ret_skb);
- return ret_skb;
+ struct sk_buff *ret_skb;
+ if (adapter->rx_skb)
+ {
+ ret_skb = adapter->rx_skb;
+ adapter->rx_skb = NULL;
+ return ret_skb;
+ }
+ ret_skb = dev_alloc_skb(WIMAX_MTU_SIZE+2+
+ (ETHERNET_ADDRESS_LENGTH * 2) +
+ NET_IP_ALIGN);
+ if (!ret_skb) {
+ pr_debug("unable to allocate skb");
+ return NULL;
+ }
+ prepare_skb(adapter, ret_skb);
+ return ret_skb;
}
void pull_skb(struct net_adapter *adapter)
{
- struct sk_buff *t_skb;
- if (adapter->rx_skb == NULL) {
- t_skb = dev_alloc_skb(WIMAX_MTU_SIZE+2+
- (ETHERNET_ADDRESS_LENGTH * 2) +
- NET_IP_ALIGN);
- if (!t_skb) {
- pr_debug("unable to allocate skb");
- return;
- }
- prepare_skb(adapter, t_skb);
- adapter->rx_skb = t_skb;
+ struct sk_buff *t_skb;
+ if (adapter->rx_skb == NULL)
+ {
+ t_skb = dev_alloc_skb(WIMAX_MTU_SIZE+2+
+ (ETHERNET_ADDRESS_LENGTH * 2) +
+ NET_IP_ALIGN);
+ if (!t_skb) {
+ pr_debug("unable to allocate skb");
+ return;
+ }
+ prepare_skb(adapter, t_skb);
+ adapter->rx_skb = t_skb;
}
}
@@ -497,8 +499,7 @@ static void adapter_rx_packet(struct net_adapter *adapter)
}
} else {
rx_skb = dev_alloc_skb(hdr->length +
- (ETHERNET_ADDRESS_LENGTH * 2) +
- NET_IP_ALIGN);
+ (ETHERNET_ADDRESS_LENGTH * 2) + NET_IP_ALIGN);
if (!rx_skb) {
pr_err("unable to allocate skb");
break;
@@ -1087,7 +1088,7 @@ int con0_poll_thread(void *data)
wake_lock(&g_cfg->wimax_driver_lock);
- while ((g_cfg->power_state != CMC_POWERING_OFF) &&
+ while ((g_cfg->power_state != CMC_POWERING_OFF) &&
(g_cfg->power_state != CMC_POWER_OFF)) {
curr_val = adapter->pdata->is_modem_awake();
if ((prev_val && (!curr_val)) || (!curr_val)) {
@@ -1096,9 +1097,8 @@ int con0_poll_thread(void *data)
}
prev_val = curr_val;
wait_event_interruptible_timeout(adapter->con0_poll,
- (g_cfg->power_state == CMC_POWERING_OFF) ||
- (g_cfg->power_state == CMC_POWER_OFF),
- msecs_to_jiffies(40));
+ (g_cfg->power_state == CMC_POWERING_OFF) ||
+ (g_cfg->power_state == CMC_POWER_OFF), msecs_to_jiffies(40));
}
wake_unlock(&g_cfg->wimax_driver_lock);
do_exit(0);
@@ -1227,9 +1227,8 @@ static int wimax_power_on(struct wimax732_platform_data *pdata)
init_waitqueue_head(&adapter->modem_resp_event);
count = 0;
- while (!adapter->modem_resp) {
- /*This command will start the
- firmware download sequence through sdio*/
+ while(!adapter->modem_resp) {
+ /*This command will start the firmware download sequence through sdio*/
send_cmd_packet(adapter, MSG_DRIVER_OK_REQ);
ret = wait_event_interruptible_timeout(
adapter->modem_resp_event,
@@ -1282,7 +1281,7 @@ static int wimax_power_on(struct wimax732_platform_data *pdata)
goto mac_request_fail;
ret = wait_for_completion_interruptible_timeout(
&adapter->mac,
- msecs_to_jiffies((MAC_RETRY_COUNT - count) *
+ msecs_to_jiffies((MAC_RETRY_COUNT - count) *
MAC_RETRY_INTERVAL));
if (ret == -ERESTARTSYS) {
pr_err("-ERESTARTSYS MAC request fail");
@@ -1297,7 +1296,7 @@ static int wimax_power_on(struct wimax732_platform_data *pdata)
adapter->wtm_task = kthread_create(con0_poll_thread,
adapter, "%s", "wimax_con0_poll_thread");
if (adapter->wtm_task)
- wake_up_process(adapter->wtm_task);
+ wake_up_process(adapter->wtm_task);
}
#endif
adapter->uwibro_dev.minor = MISC_DYNAMIC_MINOR;
@@ -1436,8 +1435,9 @@ static int wimax_power_off(struct wimax732_platform_data *pdata)
adapter = (struct net_adapter *) pdata->adapter_data;
g_cfg->power_state = CMC_POWERING_OFF;
#ifdef WIMAX_CON0_POLL
- if (g_cfg->wimax_mode == WTM_MODE)
+ if (g_cfg->wimax_mode == WTM_MODE) {
wake_up_interruptible(&adapter->con0_poll);
+ }
#endif
cmc732_release_wake_irq(adapter);
@@ -1565,14 +1565,14 @@ static long swmxdev_ioctl(struct file *file, u32 cmd,
ret = eeprom_write_rev();
break;
}
- case CONTROL_IOCTL_WIMAX_CHECK_CERT: {
+ case CONTROL_IOCTL_WIMAX_CHECK_CERT: {
pr_debug("CONTROL_IOCTL_WIMAX_CHECK_CERT");
wimax_power_off(gpdata);
ret = eeprom_check_cert();
break;
}
case CONTROL_IOCTL_WIMAX_CHECK_CAL: {
- pr_debug("CONTROL_IOCTL_WIMAX_CHECK_CAL");
+ pr_debug("CONTROL_IOCTL_WIMAX_CHECK_CAL");
wimax_power_off(gpdata);
ret = eeprom_check_cal();
break;
diff --git a/drivers/net/wimax_cmc/wimax_sdio.h b/drivers/net/wimax_cmc/wimax_sdio.h
index 998c695..46e81cb 100644..100755
--- a/drivers/net/wimax_cmc/wimax_sdio.h
+++ b/drivers/net/wimax_cmc/wimax_sdio.h
@@ -246,8 +246,8 @@ struct net_adapter {
struct task_struct *wtm_task;
#endif
struct sk_buff *rx_skb;
- u8 *receive_buffer;
- u32 buff_len;
+ u8 *receive_buffer;
+ u32 buff_len;
u32 image_offset;
u32 msg_enable;
s32 wake_irq;