Merge branch 'for-next' of git://git.infradead.org/users/sameo/mfd-2.6
[pandora-kernel.git] / drivers / staging / bcm / InterfaceDld.c
1 #include "headers.h"
2
3 int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc)
4 {
5         /* unsigned int reg = 0; */
6         mm_segment_t oldfs = {0};
7         int errno = 0, len = 0; /* ,is_config_file = 0 */
8         loff_t pos = 0;
9         PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
10         /* PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; */
11         char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
12
13         if (!buff)
14                 return -ENOMEM;
15
16         while (1) {
17                 oldfs = get_fs();
18                 set_fs(get_ds());
19                 len = vfs_read(flp, (void __force __user *)buff,
20                         MAX_TRANSFER_CTRL_BYTE_USB, &pos);
21                 set_fs(oldfs);
22                 if (len <= 0) {
23                         if (len < 0) {
24                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
25                                                 DBG_TYPE_INITEXIT, MP_INIT,
26                                                 DBG_LVL_ALL, "len < 0");
27                                 errno = len;
28                         } else {
29                                 errno = 0;
30                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
31                                                 DBG_TYPE_INITEXIT, MP_INIT,
32                                                 DBG_LVL_ALL,
33                                                 "Got end of file!");
34                         }
35                         break;
36                 }
37                 /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT,
38                  *                        DBG_LVL_ALL, buff,
39                  *                        MAX_TRANSFER_CTRL_BYTE_USB);
40                  */
41                 errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len);
42                 if (errno) {
43                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,
44                                         DBG_TYPE_PRINTK, 0, 0,
45                                         "WRM Failed! status: %d", errno);
46                         break;
47                 }
48                 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
49         }
50
51         kfree(buff);
52         return errno;
53 }
54
55 int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc)
56 {
57         char *buff, *buff_readback;
58         unsigned int reg = 0;
59         mm_segment_t oldfs = {0};
60         int errno = 0, len = 0, is_config_file = 0;
61         loff_t pos = 0;
62         static int fw_down;
63         INT Status = STATUS_SUCCESS;
64         PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg;
65
66         buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA);
67         buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA);
68         if (!buff || !buff_readback) {
69                 kfree(buff);
70                 kfree(buff_readback);
71
72                 return -ENOMEM;
73         }
74
75         is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0;
76
77         memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB);
78         memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB);
79         while (1) {
80                 oldfs = get_fs();
81                 set_fs(get_ds());
82                 len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos);
83                 set_fs(oldfs);
84                 fw_down++;
85
86                 if (len <= 0) {
87                         if (len < 0) {
88                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0");
89                                 errno = len;
90                         } else {
91                                 errno = 0;
92                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!");
93                         }
94                         break;
95                 }
96
97                 Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len);
98                 if (Status) {
99                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg);
100                         goto exit;
101                 }
102                 reg++;
103                 if ((len-sizeof(unsigned int)) < 4) {
104                         if (memcmp(buff_readback, buff, len)) {
105                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
106                                 BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len);
107                                 Status = -EIO;
108                                 goto exit;
109                         }
110                 } else {
111                         len -= 4;
112
113                         while (len) {
114                                 if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) {
115                                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down);
116                                         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]);
117                                         BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
118                                         Status = -EIO;
119                                         goto exit;
120                                 }
121                                 len -= 4;
122                         }
123                 }
124                 on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB;
125         } /* End of while(1) */
126
127 exit:
128         kfree(buff);
129         kfree(buff_readback);
130         return Status;
131 }
132
133 static int bcm_download_config_file(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
134 {
135         int retval = STATUS_SUCCESS;
136         B_UINT32 value = 0;
137
138         if (Adapter->pstargetparams == NULL) {
139                 Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL);
140                 if (Adapter->pstargetparams == NULL)
141                         return -ENOMEM;
142         }
143
144         if (psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS))
145                 return -EIO;
146
147         retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
148         if (retval) {
149                 kfree(Adapter->pstargetparams);
150                 Adapter->pstargetparams = NULL;
151                 return -EFAULT;
152         }
153
154         /* Parse the structure and then Download the Firmware */
155         beceem_parse_target_struct(Adapter);
156
157         /* Initializing the NVM. */
158         BcmInitNVM(Adapter);
159         retval = InitLedSettings(Adapter);
160
161         if (retval) {
162                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n");
163                 return retval;
164         }
165
166         if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
167                 Adapter->LEDInfo.bLedInitDone = FALSE;
168                 Adapter->DriverState = DRIVER_INIT;
169                 wake_up(&Adapter->LEDInfo.notify_led_event);
170         }
171
172         if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) {
173                 Adapter->DriverState = FW_DOWNLOAD;
174                 wake_up(&Adapter->LEDInfo.notify_led_event);
175         }
176
177         /* Initialize the DDR Controller */
178         retval = ddr_init(Adapter);
179         if (retval) {
180                 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n");
181                 return retval;
182         }
183
184         value = 0;
185         wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value));
186         wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value));
187
188         if (Adapter->eNVMType == NVM_FLASH) {
189                 retval = PropagateCalParamsFromFlashToMemory(Adapter);
190                 if (retval) {
191                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval);
192                         return retval;
193                 }
194         }
195
196         retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(STARGETPARAMS), CONFIG_BEGIN_ADDR);
197
198         if (retval)
199                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly");
200         else
201                 Adapter->bCfgDownloaded = TRUE;
202
203         return retval;
204 }
205
206 static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len)
207 {
208         int retval = STATUS_SUCCESS;
209         PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
210         if ((len-sizeof(unsigned int)) < 4) {
211                 if (memcmp(readbackbuff , buff, len))
212                         retval = -EINVAL;
213         } else {
214                 len -= 4;
215
216                 while (len) {
217                         if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) {
218                                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper");
219                                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]);
220                                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len);
221                                 retval = -EINVAL;
222                                 break;
223                         }
224                         len -= 4;
225                 }
226         }
227         return retval;
228 }
229
230 int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo)
231 {
232         int retval = STATUS_SUCCESS;
233         PUCHAR buff = NULL;
234
235         /* Config File is needed for the Driver to download the Config file and
236          * Firmware. Check for the Config file to be first to be sent from the
237          * Application
238          */
239         atomic_set(&Adapter->uiMBupdate, FALSE);
240         if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) {
241                 /* Can't Download Firmware. */
242                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n");
243                 return -EINVAL;
244         }
245
246         /* If Config File, Finish the DDR Settings and then Download CFG File */
247         if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) {
248                 retval = bcm_download_config_file(Adapter, psFwInfo);
249         } else {
250                 buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL);
251                 if (buff == NULL) {
252                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory");
253                         return -ENOMEM;
254                 }
255
256                 retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength);
257                 if (retval != STATUS_SUCCESS) {
258                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed");
259                         retval = -EFAULT;
260                         goto error;
261                 }
262
263                 retval = buffDnldVerify(Adapter,
264                                         buff,
265                                         psFwInfo->u32FirmwareLength,
266                                         psFwInfo->u32StartingAddress);
267
268                 if (retval != STATUS_SUCCESS) {
269                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval);
270                         goto error;
271                 }
272         }
273
274 error:
275         kfree(buff);
276         return retval;
277 }
278
279 static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
280 {
281         unsigned int len = 0;
282         int retval = STATUS_SUCCESS;
283         len = u32FirmwareLength;
284
285         while (u32FirmwareLength) {
286                 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
287                 retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len);
288
289                 if (retval) {
290                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval);
291                         break;
292                 }
293                 u32StartingAddress += len;
294                 u32FirmwareLength -= len;
295                 mappedbuffer += len;
296         }
297         return retval;
298 }
299
300 static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress)
301 {
302         UINT len = u32FirmwareLength;
303         INT retval = STATUS_SUCCESS;
304         PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL);
305
306         if (NULL == readbackbuff) {
307                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED");
308                 return -ENOMEM;
309         }
310
311         while (u32FirmwareLength && !retval) {
312                 len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB);
313                 retval = rdm(Adapter, u32StartingAddress, readbackbuff, len);
314
315                 if (retval) {
316                         BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval);
317                         break;
318                 }
319
320                 retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len);
321                 if (STATUS_SUCCESS != retval)
322                         break;
323
324                 u32StartingAddress += len;
325                 u32FirmwareLength -= len;
326                 mappedbuffer += len;
327
328         } /* end of while (u32FirmwareLength && !retval) */
329         kfree(readbackbuff);
330         return retval;
331 }
332
333 INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress)
334 {
335         INT status = STATUS_SUCCESS;
336
337         status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
338         if (status != STATUS_SUCCESS) {
339                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed");
340                 goto error;
341         }
342
343         status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress);
344         if (status != STATUS_SUCCESS) {
345                 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed");
346                 goto error;
347         }
348 error:
349         return status;
350 }