]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Eep.c
db1f2ad62f860adcaf17c95a0aec91a07080cc1d
[arc.git] / arch / ppc / mpc55xx / drivers / Eep.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17
18
19
20
21
22
23
24 /*
25  * IMPLEMENTATION NOTES
26  * - The SPI implementation only supports 64 bytes in one go so this is
27  *   a limitation for the EEP driver also.
28  * - The specification if SPI functions should be blocking or not. For now
29  *   the driver uses blocking SPI communication.
30  */
31
32 /* DEVICE SUPPORT
33  *   STMicroelectronics:
34  *     M95256
35  */
36
37 /* REQUIREMENTS
38  * - EEP060
39  *   Only EEP_WRITE_CYCLE_REDUCTION = STD_OFF is supported
40  *
41  * - EEP075
42  *   MEMIF_COMPARE_UNEQUAL does not exist in the MemIf specification 1.2.1(rel 3.0 )
43  *   So, it's not supported. It returns MEMIF_JOB_FAILED instead.
44  *
45  * - EEP084
46  *   EepJobCallCycle not used
47  *   We are not using interrupts so EEP_USE_INTERRUPTS must be STD_OFF
48  */
49
50
51 #include "Eep.h"
52 #include "Spi.h"
53 //#include "Dem.h"
54 #include "Det.h"
55 #include <stdlib.h>
56 #include <assert.h>
57 #include <string.h>
58
59 //#define USE_DEBUG     1
60 #include "Trace.h"
61 #define MODULE_NAME     "/driver/Eep"
62
63 // Define if you to check if the E2 seems sane at init..
64 #define CHECK_SANE    1
65 //#undef CHECK_SANE
66
67 /* The width in bytes used by this eeprom */
68 #define ADDR_LENGTH     2
69
70 /* Helper macro for the process function */
71 #define SET_STATE(_done,_state) done=(_done);job->state=(_state)
72
73 #if ( EEP_DEV_ERROR_DETECT == STD_ON ) // Report DEV errors
74 #define VALIDATE(_exp,_api,_err ) \
75         if( !(_exp) ) { \
76           Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
77           return; \
78         }
79
80 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
81         if( !(_exp) ) { \
82           Det_ReportError(MODULE_ID_GPT,0,_api,_err); \
83           return (_rv); \
84         }
85
86 #define VALID_CHANNEL(_ch)    ( Gpt_Global.configured & (1<<(_ch)) )
87
88 #else // Validate but do not report
89 #define VALIDATE(_exp,_api,_err )\
90         if( !(_exp) ) { \
91           return; \
92         }
93 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\
94         if( !(_exp) ) { \
95           return (_rv); \
96         }
97 #endif
98
99 #if ( EEP_DEV_ERROR_DETECT == STD_ON )
100 #define VALIDATE_CONFIG(_x) assert(_x)
101 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(MODULE_ID_EEP, _y, _z, _q)
102 #else
103 #define VALIDATE_CONFIG(_x)
104 #define DET_REPORTERROR(_x,_y,_z,_q)
105 #endif
106
107 #define EEP_JOB_END_NOTIFICATION() \
108   if (Eep_Global.config->Eep_JobEndNotification!=NULL) { \
109     Eep_Global.config->Eep_JobEndNotification(); \
110   }
111
112 #define EEP_JOB_ERROR_NOTIFICATION() \
113   if (Eep_Global.config->Eep_JobErrorNotification!=NULL) { \
114     Eep_Global.config->Eep_JobErrorNotification(); \
115   }
116
117 /* Job state */
118 typedef enum {
119   EEP_NONE,
120   EEP_COMPARE,
121   EEP_ERASE,
122   EEP_READ,
123   EEP_WRITE,
124 } Eep_Arc_JobType;
125
126 /* Spi job state */
127 typedef enum {
128         JOB_MAIN,
129         JOB_READ_STATUS,
130         JOB_READ_STATUS_RESULT,
131 } Job_StateType;
132
133 /* Information about a job */
134 typedef struct {
135         uint8 *targetAddr;
136         Eep_AddressType eepAddr;
137         uint32 left;
138         Job_StateType state;
139         Eep_Arc_JobType mainState;
140         Spi_SequenceType currSeq;
141         uint32 chunkSize;
142 } Eep_JobInfoType;
143
144 #define JOB_SET_STATE(_x,_y)            job->state=(_x);job->mainState=(_y)
145
146
147 /*
148  * Holds all global information that is needed by the driver
149  *
150  */
151 typedef struct {
152         // The configuration
153   const Eep_ConfigType *config;
154
155   // Status of driver
156   MemIf_StatusType    status;
157   MemIf_JobResultType jobResultType;
158   Eep_Arc_JobType    jobType;
159
160   // Saved information from API calls.
161   MemIf_AddressType   e2Addr;
162   uint8                                 *targetAddr;
163   MemIf_LengthType    length;
164
165   // Data containers for EB buffers
166   Spi_DataType ebCmd;
167   Spi_DataType ebReadStatus;
168   Spi_DataType ebE2Addr[ADDR_LENGTH];
169   // What mode we are in ( normal/fast )
170   MemIf_ModeType      mode;
171
172   // Hold job information
173   Eep_JobInfoType job;
174
175 } Eep_GlobalType;
176
177 #if 0
178 #define SPI_TRANSMIT_FUNC(_x)   Spi_SyncTransmit(_x)
179 #else
180 #define SPI_TRANSMIT_FUNC(_x,_y)        Eep_AsyncTransmit(_x,_y)
181
182 Std_ReturnType Eep_AsyncTransmit(Spi_SequenceType Sequence,Eep_JobInfoType *job) {
183         Std_ReturnType rv;
184         job->currSeq = Sequence;
185         rv = Spi_AsyncTransmit(Sequence);
186         return rv;
187 }
188 #endif
189
190 #define CFG_P() Eep_Global.config
191
192 Eep_GlobalType Eep_Global;
193
194 /**
195  * Converts Eep_AddressType to one that can be read by SPI( Spi_DataType )
196  *
197  * @param spiAddr Pointer to an address were the result is written.
198  * @param eepAddr The Eep address to convert
199  */
200 static void Spi_ConvertToSpiAddr(Spi_DataType *spiAddr, Eep_AddressType eepAddr ) {
201         spiAddr[1] = (eepAddr)&0xff;
202         spiAddr[0] = (eepAddr>>8)&0xff;
203 }
204
205
206 #if defined(CHECK_SANE)
207 static void Eep_WREN( void ) {
208   Eep_Global.ebCmd = E2_WREN;
209   Spi_SetupEB( CFG_P()->EepDataChannel, NULL ,NULL ,1);
210   Spi_SyncTransmit(CFG_P()->EepCmdSequence);
211 }
212
213 static void Eep_WRDI( void ) {
214   Eep_Global.ebCmd = E2_WRDI;
215   Spi_SetupEB( CFG_P()->EepDataChannel, NULL ,NULL ,1);
216   Spi_SyncTransmit(CFG_P()->EepCmdSequence);
217
218 }
219
220 static uint8 Eep_ReadStatusReg( void ) {
221   Spi_SetupEB( CFG_P()->EepDataChannel, NULL, &Eep_Global.ebReadStatus, 1);
222   Eep_Global.ebCmd = E2_RDSR;
223   Spi_SyncTransmit(CFG_P()->EepCmd2Sequence);
224   return Eep_Global.ebReadStatus;
225 }
226 #endif
227
228 void Eep_Init( const Eep_ConfigType* ConfigPtr ){
229   VALIDATE( (ConfigPtr != NULL) , EEP_INIT_ID, EEP_E_PARAM_CONFIG );
230   Eep_Global.config = ConfigPtr;
231
232   Spi_SetupEB( CFG_P()->EepCmdChannel,  &Eep_Global.ebCmd,NULL,sizeof(Eep_Global.ebCmd)/sizeof(Eep_Global.ebCmd));
233   Spi_SetupEB( CFG_P()->EepAddrChannel,  Eep_Global.ebE2Addr,NULL,sizeof(Eep_Global.ebE2Addr)/sizeof(Eep_Global.ebE2Addr[0]));
234   Spi_SetupEB( CFG_P()->EepWrenChannel,  NULL,NULL,1);
235
236 #if defined( CHECK_SANE )
237
238   // Simple check,
239   // - write WREN,
240   // - check if 1 by reading with RDSR,
241   // - write WRDE
242   // - check if 0 by reading with RDSR,
243   Eep_WREN();
244
245   if( (Eep_ReadStatusReg() & 0x2) == 0 ) {
246     while(1);
247   }
248   Eep_WRDI();
249   if( (Eep_ReadStatusReg() & 0x2)  ) {
250     while(1);
251   }
252
253 #endif
254
255   Eep_Global.status     = MEMIF_IDLE;
256   Eep_Global.jobResultType  = MEMIF_JOB_OK;
257
258 }
259
260
261 void Eep_SetMode( MemIf_ModeType Mode ){
262   VALIDATE( ( Eep_Global.status != MEMIF_UNINIT ), EEP_SETMODE_ID, EEP_E_UNINIT );
263   VALIDATE( ( Eep_Global.status != MEMIF_BUSY ), EEP_SETMODE_ID, EEP_E_BUSY );
264
265   Eep_Global.mode = Mode;
266 }
267
268 Std_ReturnType Eep_Read ( Eep_AddressType EepromAddress,
269                            uint8 *TargetAddressPtr,
270                            Eep_LengthType Length )
271 {
272         Eep_JobInfoType *job = &Eep_Global.job;
273
274   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_UNINIT ), EEP_READ_ID, EEP_E_UNINIT, E_NOT_OK );
275   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_BUSY ), EEP_READ_ID, EEP_E_BUSY, E_NOT_OK );
276   VALIDATE_W_RV( ( TargetAddressPtr != NULL ) , EEP_READ_ID, EEP_E_PARAM_DATA, E_NOT_OK );
277   VALIDATE_W_RV( ( (EepromAddress) < (Eep_Global.config->EepSize) ) , EEP_READ_ID, EEP_E_PARAM_ADDRESS, E_NOT_OK );
278   VALIDATE_W_RV( ( (Eep_Global.config->EepSize - EepromAddress) >= Length ) , EEP_READ_ID, EEP_E_PARAM_LENGTH, E_NOT_OK );
279
280   Eep_Global.status = MEMIF_BUSY;
281   Eep_Global.jobResultType = MEMIF_JOB_PENDING;
282   Eep_Global.jobType = EEP_READ;
283
284   if( Eep_Global.mode == MEMIF_MODE_FAST ) {
285      job->chunkSize = Eep_Global.config->EepFastReadBlockSize;
286   } else {
287      job->chunkSize = Eep_Global.config->EepNormalReadBlockSize;
288   }
289
290   job->eepAddr = EepromAddress;
291   job->targetAddr = TargetAddressPtr;
292   job->left = Length;
293
294   JOB_SET_STATE(JOB_MAIN,EEP_READ);
295
296   return E_OK;
297 }
298
299 Std_ReturnType Eep_Erase( Eep_AddressType   TargetAddress, Eep_LengthType    Length ){
300   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_UNINIT ), EEP_ERASE_ID, EEP_E_UNINIT, E_NOT_OK );
301   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_BUSY ), EEP_ERASE_ID, EEP_E_BUSY, E_NOT_OK );
302   VALIDATE_W_RV( ( (TargetAddress) < (Eep_Global.config->EepSize) ) , EEP_ERASE_ID, EEP_E_PARAM_ADDRESS, E_NOT_OK );
303   VALIDATE_W_RV( ( (Eep_Global.config->EepSize - TargetAddress) >= Length ) , EEP_ERASE_ID, EEP_E_PARAM_LENGTH, E_NOT_OK );
304
305   /* TODO : NOT IMPLEMENTED
306    * ( Since this E2 do not have erase )
307    * */
308   Std_ReturnType rv = E_NOT_OK;
309   Eep_Global.status = MEMIF_BUSY;
310   Eep_Global.status = MEMIF_IDLE;
311   return rv;
312 }
313
314 Std_ReturnType Eep_Write( Eep_AddressType EepromAddress, const uint8* DataBufferPtr, Eep_LengthType Length ){
315         Eep_JobInfoType *job = &Eep_Global.job;
316
317   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_UNINIT ), EEP_WRITE_ID, EEP_E_UNINIT, E_NOT_OK );
318   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_BUSY ), EEP_WRITE_ID, EEP_E_BUSY, E_NOT_OK );
319   VALIDATE_W_RV( ( DataBufferPtr != NULL ) , EEP_WRITE_ID, EEP_E_PARAM_DATA, E_NOT_OK );
320   VALIDATE_W_RV( ( (EepromAddress) < (Eep_Global.config->EepSize) ) , EEP_WRITE_ID, EEP_E_PARAM_ADDRESS, E_NOT_OK );
321   VALIDATE_W_RV( ( Length <= (Eep_Global.config->EepSize - EepromAddress) ) , EEP_WRITE_ID, EEP_E_PARAM_LENGTH, E_NOT_OK );
322
323         Eep_Global.jobResultType = MEMIF_JOB_PENDING;
324         Eep_Global.status = MEMIF_BUSY;
325         Eep_Global.jobType = EEP_WRITE;
326
327         if( Eep_Global.mode == MEMIF_MODE_FAST ) {
328                 job->chunkSize = Eep_Global.config->EepFastWriteBlockSize;
329         } else {
330                 job->chunkSize = Eep_Global.config->EepNormalWriteBlockSize;
331         }
332
333   job->eepAddr = EepromAddress;
334   job->targetAddr = (uint8 *)DataBufferPtr;
335   job->left = Length;
336
337   JOB_SET_STATE(JOB_MAIN,EEP_WRITE);
338
339   return E_OK;
340 }
341
342
343 Std_ReturnType Eep_Compare( Eep_AddressType EepromAddress, uint8 *TargetAddressPtr, Eep_LengthType Length )
344 {
345         Eep_JobInfoType *job = &Eep_Global.job;
346
347   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_UNINIT ), EEP_COMPARE_ID, EEP_E_UNINIT, E_NOT_OK );
348   VALIDATE_W_RV( ( Eep_Global.status != MEMIF_BUSY ), EEP_COMPARE_ID, EEP_E_BUSY, E_NOT_OK );
349   VALIDATE_W_RV( ( TargetAddressPtr != NULL ) , EEP_COMPARE_ID, EEP_E_PARAM_DATA, E_NOT_OK );
350   VALIDATE_W_RV( ( (EepromAddress) < (Eep_Global.config->EepSize) ) , EEP_COMPARE_ID, EEP_E_PARAM_ADDRESS, E_NOT_OK );
351   VALIDATE_W_RV( ( (Eep_Global.config->EepSize - EepromAddress) >= Length ) , EEP_COMPARE_ID, EEP_E_PARAM_LENGTH, E_NOT_OK );
352
353   Eep_Global.status = MEMIF_BUSY;
354   Eep_Global.jobResultType = MEMIF_JOB_PENDING;
355   Eep_Global.jobType = EEP_COMPARE;
356
357   /* This is a compare job but the compare jobs really issues read in portions
358    * big enough to fit it's static buffers
359    */
360   if( Eep_Global.mode == MEMIF_MODE_FAST ) {
361      job->chunkSize = Eep_Global.config->EepFastReadBlockSize;
362   } else {
363      job->chunkSize = Eep_Global.config->EepNormalReadBlockSize;
364   }
365
366   job->eepAddr = EepromAddress;
367   job->targetAddr = TargetAddressPtr;
368   job->left = Length;
369
370   JOB_SET_STATE(JOB_MAIN,EEP_COMPARE);
371
372   return E_OK;
373 }
374
375
376 void Eep_Cancel( void ){
377   EEP_JOB_END_NOTIFICATION();
378
379   if (MEMIF_JOB_PENDING==Eep_Global.jobResultType) {
380         Eep_Global.jobResultType=MEMIF_JOB_CANCELLED;
381   }
382
383   Eep_Global.status = MEMIF_IDLE;
384 }
385
386 MemIf_StatusType Eep_GetStatus( void ){
387   return Eep_Global.status;
388 }
389
390 MemIf_JobResultType Eep_GetJobResult( void ){
391   return Eep_Global.jobResultType;
392 }
393
394
395 /**
396  * Function that process read/write/erase requests to the SPI
397  *
398  * @param job The present job
399  */
400
401 static Spi_SeqResultType Eep_ProcessJob( Eep_JobInfoType *job ) {
402   Spi_SeqResultType rv;
403   _Bool done = 0;
404
405   /* Check if previous sequence is OK */
406   rv = Spi_GetSequenceResult(job->currSeq);
407   if( rv != SPI_SEQ_OK ) {
408         return rv;
409   }
410
411   rv = SPI_SEQ_PENDING;
412
413   do {
414                 switch(job->state ) {
415                 case JOB_READ_STATUS:
416                         DEBUG(DEBUG_LOW,"%s: READ_STATUS\n",MODULE_NAME);
417                         /* Check status from erase cmd, read status from flash */
418                         Spi_SetupEB( CFG_P()->EepDataChannel, NULL, &Eep_Global.ebReadStatus, 1);
419                         Eep_Global.ebCmd = E2_RDSR;
420                         if( SPI_TRANSMIT_FUNC(CFG_P()->EepCmd2Sequence,job ) != E_OK ) {
421                                 assert(0);
422                         }
423                         SET_STATE(1,JOB_READ_STATUS_RESULT);
424                         break;
425
426                 case JOB_READ_STATUS_RESULT:
427                         DEBUG(DEBUG_LOW,"%s: READ_STATUS_RESULT\n",MODULE_NAME);
428                         if( Eep_Global.ebReadStatus&1 ) {
429                                 SET_STATE(0,JOB_READ_STATUS);
430                         } else {
431                                 SET_STATE(0,JOB_MAIN);
432                         }
433                         break;
434
435                 case JOB_MAIN:
436                         if( job->left != 0 ) {
437                                 if( job->left <= job->chunkSize ) {
438                                         job->chunkSize = job->left;
439                                 }
440
441                                 Spi_ConvertToSpiAddr(Eep_Global.ebE2Addr,job->eepAddr);
442
443                                 switch(job->mainState) {
444
445                                 case EEP_ERASE:
446                                         /* NOT USED */
447                                         break;
448                                 case EEP_READ:
449                                 case EEP_COMPARE:
450                                   DEBUG(DEBUG_LOW,"%s: READ s:%04x d:%04x l:%04x\n",MODULE_NAME,job->eepAddr, job->targetAddr, job->left);
451                                         Eep_Global.ebCmd = E2_READ;
452                                         Spi_SetupEB( CFG_P()->EepDataChannel, NULL ,job->targetAddr,job->chunkSize);
453                                         SPI_TRANSMIT_FUNC(CFG_P()->EepReadSequence,job );
454                                         break;
455
456                                 case EEP_WRITE:
457                                         DEBUG(DEBUG_LOW,"%s: WRITE d:%04x s:%04x first data:%02x\n",MODULE_NAME,job->eepAddr,job->targetAddr,*job->targetAddr);
458                                         Eep_Global.ebCmd = E2_WRITE;
459                                         Spi_ConvertToSpiAddr(Eep_Global.ebE2Addr,job->eepAddr);
460                                         Spi_SetupEB( CFG_P()->EepDataChannel, job->targetAddr, NULL, job->chunkSize);
461                                         SPI_TRANSMIT_FUNC(CFG_P()->EepWriteSequence,job );
462                                         break;
463
464                                 default:
465                                         assert(0);
466                                         break;
467                                 }
468
469                                 job->eepAddr += job->chunkSize;
470                                 job->targetAddr += job->chunkSize;
471                                 job->left -= job->chunkSize;
472                                 SET_STATE(1,JOB_READ_STATUS);
473
474                         } else {
475                                 /* We are done :) */
476                                 SET_STATE(1,JOB_MAIN);
477                                 job->mainState = EEP_NONE;
478                                 rv = SPI_SEQ_OK;
479                         }
480                         break;
481
482                 default:
483                         assert(0);
484                         break;
485
486                 }
487         } while(!done);
488   return rv;
489 }
490
491 #define CMP_BUFF_SIZE SPI_EB_MAX_LENGTH
492
493 void Eep_MainFunction( void )
494 {
495   Spi_SeqResultType jobResult;
496
497   if( Eep_Global.jobResultType == MEMIF_JOB_PENDING ) {
498         switch (Eep_Global.jobType) {
499                 case EEP_COMPARE: {
500                         static Eep_JobInfoType readJob;
501                         static uint8 Eep_CompareBuffer[SPI_EB_MAX_LENGTH];
502                         Eep_JobInfoType *gJob = &Eep_Global.job;
503                         static _Bool firstTime = 1;
504                         static uint32 readSize;
505
506                         /* Compare jobs must use a local buffer to hold one portion
507                          * of the job. Since Eep_ProcessJob() also manipulates the
508                          * job structure we need to create a new local job each time.
509                          * The global job updates is updated for each process job.
510                          */
511
512                         if (firstTime == 1) {
513                                 readJob = *gJob;
514
515                                 if ( gJob->left <= CMP_BUFF_SIZE ) {
516                                         readSize = gJob->left;
517                                 } else {
518                                         readSize = CMP_BUFF_SIZE;
519                                 }
520                                 readJob.left = readSize;
521                                 readJob.targetAddr = Eep_CompareBuffer;
522                                 firstTime = 0;
523                         }
524
525                         jobResult = Eep_ProcessJob(&readJob);
526
527                         if( jobResult == SPI_SEQ_PENDING ) {
528                                 /* Do nothing */
529                         } else if( jobResult == SPI_SEQ_OK ) {
530
531                                 if( memcmp(Eep_CompareBuffer,gJob->targetAddr, readSize) != 0 ) {
532                                         DET_REPORTERROR(MODULE_ID_EEP,0, 0x9, MEMIF_JOB_FAILED );
533                                         EEP_JOB_ERROR_NOTIFICATION();
534                                         return;
535                                 }
536                                 // Update the global comare job
537                                 gJob->targetAddr += readSize;
538                                 gJob->eepAddr += readSize;
539                                 gJob->left -= readSize;
540
541                                 // Check if we are done
542                                 if( gJob->left == 0 ) {
543                                         Eep_Global.jobResultType = MEMIF_JOB_OK;
544                                         Eep_Global.jobType = EEP_NONE;
545                                         Eep_Global.status = MEMIF_IDLE;
546                                         EEP_JOB_END_NOTIFICATION();
547                                         firstTime = 1;
548                                         return;
549                                 }
550                                 // Calculate new readSize
551                                 if ( gJob->left <= CMP_BUFF_SIZE ) {
552                                         readSize = gJob->left;
553                                 } else {
554                                         readSize = CMP_BUFF_SIZE;
555                                 }
556
557                                 // Update the readjob for next session
558                                 readJob = *gJob;
559                                 readJob.left = readSize;
560                                 readJob.targetAddr = Eep_CompareBuffer;
561                         } else {
562                           // all other cases are bad
563                           firstTime = 1;
564         Eep_Global.jobResultType = MEMIF_JOB_FAILED;
565         Eep_Global.jobType = EEP_NONE;
566         Eep_Global.status = MEMIF_IDLE;
567
568                                 DET_REPORTERROR(MODULE_ID_EEP,0, 0x9, MEMIF_JOB_FAILED );
569                                 EEP_JOB_ERROR_NOTIFICATION();
570                         }
571                 }
572                 break;
573
574     case EEP_ERASE:
575     case EEP_READ:
576     case EEP_WRITE:
577
578         jobResult =  Eep_ProcessJob(&Eep_Global.job);
579
580         if( jobResult == SPI_SEQ_OK ) {
581
582                 Eep_Global.jobResultType = MEMIF_JOB_OK;
583                 Eep_Global.jobType = EEP_NONE;
584                 Eep_Global.status = MEMIF_IDLE;
585         EEP_JOB_END_NOTIFICATION();
586       } else if( jobResult == SPI_SEQ_PENDING )  {
587         /* Busy, Do nothing */
588       } else {
589         // Error
590         Eep_Global.jobResultType = MEMIF_JOB_FAILED;
591         Eep_Global.jobType = EEP_NONE;
592         Eep_Global.status = MEMIF_IDLE;
593
594         switch(Eep_Global.jobType) {
595         case EEP_ERASE:
596                 DET_REPORTERROR(MODULE_ID_EEP,0, 0x9, MEMIF_JOB_FAILED );
597                                         break;
598         case EEP_READ:
599                 DET_REPORTERROR(MODULE_ID_EEP,0, 0x9, MEMIF_JOB_FAILED );
600                                         break;
601         case EEP_WRITE:
602                 DET_REPORTERROR(MODULE_ID_EEP,0, 0x9, MEMIF_JOB_FAILED );
603                                         break;
604         default:
605                 assert(0);
606         }
607
608         EEP_JOB_ERROR_NOTIFICATION();
609       }
610         break;
611     case EEP_NONE:
612       assert(0);
613       break;
614     }
615   }
616 }