summaryrefslogtreecommitdiff
path: root/drivers/staging/bcm/InterfaceDld.c
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/staging/bcm/InterfaceDld.c
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/staging/bcm/InterfaceDld.c')
-rw-r--r--drivers/staging/bcm/InterfaceDld.c332
1 files changed, 332 insertions, 0 deletions
diff --git a/drivers/staging/bcm/InterfaceDld.c b/drivers/staging/bcm/InterfaceDld.c
new file mode 100644
index 00000000..348ad75b
--- /dev/null
+++ b/drivers/staging/bcm/InterfaceDld.c
@@ -0,0 +1,332 @@
+#include "headers.h"
+
+int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
+{
+ /* unsigned int reg = 0; */
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0; /* ,is_config_file = 0 */
+ loff_t pos = 0;
+ struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
+ /* struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter; */
+ char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
+
+ if (!buff)
+ return -ENOMEM;
+
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff,
+ MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ if (len <= 0) {
+ if (len < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, MP_INIT,
+ DBG_LVL_ALL, "len < 0");
+ errno = len;
+ } else {
+ errno = 0;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_INITEXIT, MP_INIT,
+ DBG_LVL_ALL,
+ "Got end of file!");
+ }
+ break;
+ }
+ /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
+ * DBG_LVL_ALL, buff,
+ * MAX_TRANSFER_CTRL_BYTE_USB);
+ */
+ errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
+ if (errno) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
+ DBG_TYPE_PRINTK, 0, 0,
+ "WRM Failed! status: %d", errno);
+ break;
+ }
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ }
+
+ kfree(buff);
+ return errno;
+}
+
+int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc)
+{
+ char *buff, *buff_readback;
+ unsigned int reg = 0;
+ mm_segment_t oldfs = {0};
+ int errno = 0, len = 0, is_config_file = 0;
+ loff_t pos = 0;
+ static int fw_down;
+ INT Status = STATUS_SUCCESS;
+ struct bcm_interface_adapter *psIntfAdapter = (struct bcm_interface_adapter *)arg;
+ int bytes;
+
+ buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
+ buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
+ if (!buff || !buff_readback) {
+ kfree(buff);
+ kfree(buff_readback);
+
+ return -ENOMEM;
+ }
+
+ is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
+
+ memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB);
+ memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB);
+ while (1) {
+ oldfs = get_fs();
+ set_fs(get_ds());
+ len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
+ set_fs(oldfs);
+ fw_down++;
+
+ if (len <= 0) {
+ if (len < 0) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
+ errno = len;
+ } else {
+ errno = 0;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
+ }
+ break;
+ }
+
+ bytes = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
+ if (bytes < 0) {
+ Status = bytes;
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
+ goto exit;
+ }
+ reg++;
+ if ((len-sizeof(unsigned int)) < 4) {
+ if (memcmp(buff_readback, buff, len)) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len);
+ Status = -EIO;
+ goto exit;
+ }
+ } else {
+ len -= 4;
+
+ while (len) {
+ if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) {
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]);
+ BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
+ Status = -EIO;
+ goto exit;
+ }
+ len -= 4;
+ }
+ }
+ on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
+ } /* End of while(1) */
+
+exit:
+ kfree(buff);
+ kfree(buff_readback);
+ return Status;
+}
+
+static int bcm_download_config_file(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo)
+{
+ int retval = STATUS_SUCCESS;
+ B_UINT32 value = 0;
+
+ if (Adapter->pstargetparams == NULL) {
+ Adapter->pstargetparams = kmalloc(sizeof(struct bcm_target_params), GFP_KERNEL);
+ if (Adapter->pstargetparams == NULL)
+ return -ENOMEM;
+ }
+
+ if (psFwInfo->u32FirmwareLength != sizeof(struct bcm_target_params))
+ return -EIO;
+
+ retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
+ if (retval) {
+ kfree(Adapter->pstargetparams);
+ Adapter->pstargetparams = NULL;
+ return -EFAULT;
+ }
+
+ /* Parse the structure and then Download the Firmware */
+ beceem_parse_target_struct(Adapter);
+
+ /* Initializing the NVM. */
+ BcmInitNVM(Adapter);
+ retval = InitLedSettings(Adapter);
+
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
+ return retval;
+ }
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->LEDInfo.bLedInitDone = FALSE;
+ Adapter->DriverState = DRIVER_INIT;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
+ Adapter->DriverState = FW_DOWNLOAD;
+ wake_up(&Adapter->LEDInfo.notify_led_event);
+ }
+
+ /* Initialize the DDR Controller */
+ retval = ddr_init(Adapter);
+ if (retval) {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
+ return retval;
+ }
+
+ value = 0;
+ wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
+ wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
+
+ if (Adapter->eNVMType == NVM_FLASH) {
+ retval = PropagateCalParamsFromFlashToMemory(Adapter);
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval);
+ return retval;
+ }
+ }
+
+ retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(struct bcm_target_params), CONFIG_BEGIN_ADDR);
+
+ if (retval)
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
+ else
+ Adapter->bCfgDownloaded = TRUE;
+
+ return retval;
+}
+
+int bcm_ioctl_fw_download(struct bcm_mini_adapter *Adapter, struct bcm_firmware_info *psFwInfo)
+{
+ int retval = STATUS_SUCCESS;
+ PUCHAR buff = NULL;
+
+ /* Config File is needed for the Driver to download the Config file and
+ * Firmware. Check for the Config file to be first to be sent from the
+ * Application
+ */
+ atomic_set(&Adapter->uiMBupdate, FALSE);
+ if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
+ /* Can't Download Firmware. */
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n");
+ return -EINVAL;
+ }
+
+ /* If Config File, Finish the DDR Settings and then Download CFG File */
+ if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
+ retval = bcm_download_config_file(Adapter, psFwInfo);
+ } else {
+ buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
+ if (buff == NULL) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory");
+ return -ENOMEM;
+ }
+
+ retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
+ retval = -EFAULT;
+ goto error;
+ }
+
+ retval = buffDnldVerify(Adapter,
+ buff,
+ psFwInfo->u32FirmwareLength,
+ psFwInfo->u32StartingAddress);
+
+ if (retval != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval);
+ goto error;
+ }
+ }
+
+error:
+ kfree(buff);
+ return retval;
+}
+
+static INT buffDnld(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
+{
+ unsigned int len = 0;
+ int retval = STATUS_SUCCESS;
+ len = u32FirmwareLength;
+
+ while (u32FirmwareLength) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
+
+ if (retval) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
+ break;
+ }
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
+ }
+ return retval;
+}
+
+static INT buffRdbkVerify(struct bcm_mini_adapter *Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
+{
+ UINT len = u32FirmwareLength;
+ INT retval = STATUS_SUCCESS;
+ PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
+ int bytes;
+
+ if (NULL == readbackbuff) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
+ return -ENOMEM;
+ }
+
+ while (u32FirmwareLength && !retval) {
+ len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
+ bytes = rdm(Adapter, u32StartingAddress, readbackbuff, len);
+
+ if (bytes < 0) {
+ retval = bytes;
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
+ break;
+ }
+
+ if (memcmp(readbackbuff, mappedbuffer, len) != 0) {
+ pr_err("%s() failed. The firmware doesn't match what was written",
+ __func__);
+ retval = -EIO;
+ }
+
+ u32StartingAddress += len;
+ u32FirmwareLength -= len;
+ mappedbuffer += len;
+
+ } /* end of while (u32FirmwareLength && !retval) */
+ kfree(readbackbuff);
+ return retval;
+}
+
+INT buffDnldVerify(struct bcm_mini_adapter *Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress)
+{
+ INT status = STATUS_SUCCESS;
+
+ status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed");
+ goto error;
+ }
+
+ status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
+ if (status != STATUS_SUCCESS) {
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed");
+ goto error;
+ }
+error:
+ return status;
+}