1 /******************************************************************************
2 *                                                                             *
3 * License Agreement                                                           *
4 *                                                                             *
5 * Copyright (c) 2015 Altera Corporation, San Jose, California, USA.           *
6 * All rights reserved.                                                        *
7 *                                                                             *
8 * Permission is hereby granted, free of charge, to any person obtaining a     *
9 * copy of this software and associated documentation files (the "Software"),  *
10 * to deal in the Software without restriction, including without limitation   *
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
12 * and/or sell copies of the Software, and to permit persons to whom the       *
13 * Software is furnished to do so, subject to the following conditions:        *
14 *                                                                             *
15 * The above copyright notice and this permission notice shall be included in  *
16 * all copies or substantial portions of the Software.                         *
17 *                                                                             *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
24 * DEALINGS IN THE SOFTWARE.                                                   *
25 *                                                                             *
26 *                                                                             *
27 ******************************************************************************/
28 
29 #include <errno.h>
30 #include <io.h>
31 #include <string.h>
32 #include <stddef.h>
33 #include "sys/param.h"
34 #include "alt_types.h"
35 #include "altera_epcq_controller_regs.h"
36 #include "altera_epcq_controller.h"
37 #include "priv/alt_busy_sleep.h"
38 #include "sys/alt_debug.h"
39 #include "sys/alt_cache.h"
40 
41 
42 ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments(alt_epcq_controller_dev *flash_info,alt_u32 offset, alt_u32 length);
43 alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info);
44 
45 /*
46  *  Public API
47  *
48  *  Refer to “Using Flash Devices” in the
49  *  Developing Programs Using the Hardware Abstraction Layer chapter
50  *   of the Nios II Software Developer’s Handbook.
51  */
52 
53 
54  /**
55   * alt_epcq_controller_lock
56   *
57   *  Locks the range of the memory sectors, which
58   *  protected from write and erase.
59   *
60   * Arguments:
61   * - *flash_info: Pointer to general flash device structure.
62   * - sectors_to_lock: Block protection bits in EPCQ ==> Bit4 | Bit3 | Bit2 | Bit1 | Bit0
63   *                                                       TB  | BP3  | BP2  | BP1  | BP0
64   * For details of setting sectors protection, please refer to EPCQ datasheet.
65   *
66   * Returns:
67   * 0 -> success
68   * -EINVAL -> Invalid arguments
69   * -ETIME  -> Time out and skipping the looping after 0.7 sec.
70   * -ENOLCK -> Sectors lock failed.
71 **/
alt_epcq_controller_lock(alt_flash_dev * flash_info,alt_u32 sectors_to_lock)72 int alt_epcq_controller_lock(alt_flash_dev *flash_info, alt_u32 sectors_to_lock)
73 {
74     alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */
75     alt_epcq_controller_dev* epcq_flash_info = NULL;
76     alt_u32 result = 0;
77     alt_32 status = 0;
78 
79     /* return -EINVAL if flash_info is NULL */
80     if(NULL == flash_info || 0 > sectors_to_lock)
81     {
82     	return -EINVAL;
83     }
84 
85     epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
86 
87     /* sector value should occupy bits 17:8 */
88     mem_op_value = sectors_to_lock << 8;
89 
90     /* sector protect commands 0b11 occupies lower 2 bits */
91     mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_PROTECT_CMD;
92 
93     /* write sector protect command to EPCQ_MEM_OP register to protect sectors */
94     IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value);
95 
96     /* poll write in progress to make sure no operation is in progress */
97     status = alt_epcq_poll_for_write_in_progress(epcq_flash_info);
98     if(status != 0)
99     {
100     	return status;
101     }
102 
103 	status = IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base);
104 	result |= (status >> 2) & 0x07; /* extract out BP3 - BP0 */
105 	result |= (status >> 3) & 0x08; /* extract out BP4 */
106     result |= (status >> 1) & 0x10; /* extract out TOP/BOTTOM bit */
107 
108 	if(result != sectors_to_lock)
109 	{
110 		return -ENOLCK;
111 	}
112 
113     return 0;
114 }
115 
116 /**
117  * alt_epcq_controller_get_info
118  *
119  * Pass the table of erase blocks to the user. This flash will return a single
120  * flash_region that gives the number and size of sectors for the device used.
121  *
122  * Arguments:
123  * - *fd: Pointer to general flash device structure.
124  * - **info: Pointer to flash region
125  * - *number_of_regions: Pointer to number of regions
126  *
127  * For details of setting sectors protection, please refer to EPCQ datasheet.
128  *
129  * Returns:
130  * 0 -> success
131  * -EINVAL -> Invalid arguments
132  * -EIO -> Could be hardware problem.
133 **/
alt_epcq_controller_get_info(alt_flash_fd * fd,flash_region ** info,int * number_of_regions)134 int alt_epcq_controller_get_info
135 (
136     alt_flash_fd *fd, /** flash device descriptor */
137     flash_region **info, /** pointer to flash_region will be stored here */
138     int *number_of_regions /** number of regions will be stored here */
139 )
140 {
141 	alt_flash_dev* flash = NULL;
142 
143 	/* return -EINVAL if fd,info and number_of_regions are NULL */
144 	if(NULL == fd || NULL == info || NULL == number_of_regions)
145     {
146     	return -EINVAL;
147     }
148 
149     flash = (alt_flash_dev*)fd;
150 
151     *number_of_regions = flash->number_of_regions;
152 
153     if (!flash->number_of_regions)
154     {
155       return -EIO;
156     }
157     else
158     {
159       *info = &flash->region_info[0];
160     }
161 
162     return 0;
163 }
164 
165 /**
166   * alt_epcq_controller_erase_block
167   *
168   * This function erases a single flash sector.
169   *
170   * Arguments:
171   * - *flash_info: Pointer to EPCQ flash device structure.
172   * - block_offset: byte-addressed offset, from start of flash, of the sector to be erased
173   *
174   * Returns:
175   * 0 -> success
176   * -EINVAL -> Invalid arguments
177   * -EIO -> write failed, sector might be protected
178 **/
alt_epcq_controller_erase_block(alt_flash_dev * flash_info,int block_offset)179 int alt_epcq_controller_erase_block(alt_flash_dev *flash_info, int block_offset)
180 {
181     alt_32 ret_code = 0;
182     alt_u32 mem_op_value = 0; /* value to write to EPCQ_MEM_OP register */
183     alt_epcq_controller_dev* epcq_flash_info = NULL;
184     alt_u32 sector_number = 0;
185 
186     /* return -EINVAL if flash_info is NULL */
187     if(NULL == flash_info)
188     {
189     	return -EINVAL;
190     }
191 
192     epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
193 
194     /*
195      * Sanity checks that block_offset is within the flash memory span and that the
196      * block offset is sector aligned.
197      *
198      */
199     if((block_offset < 0)
200         || (block_offset >= epcq_flash_info->size_in_bytes)
201         || (block_offset & (epcq_flash_info->sector_size - 1)) != 0)
202     {
203     	return -EINVAL;
204     }
205 
206     /* calculate current sector/block number */
207     sector_number = (block_offset/(epcq_flash_info->sector_size));
208 
209     /* sector value should occupy bits 23:8 */
210     mem_op_value = (sector_number << 8) & ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_VALUE_MASK;
211 
212     /* sector erase commands 0b10 occupies lower 2 bits */
213     mem_op_value |= ALTERA_EPCQ_CONTROLLER_MEM_OP_SECTOR_ERASE_CMD;
214 
215     /* write sector erase command to EPCQ_MEM_OP register to erase sector "sector_number" */
216     IOWR_ALTERA_EPCQ_CONTROLLER_MEM_OP(epcq_flash_info->csr_base, mem_op_value);
217 
218     /* check whether erase triggered a illegal erase interrupt  */
219     if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) &
220             		ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK) ==
221             				ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_ACTIVE)
222     {
223 	    /* clear register */
224 	    /* EPCQ_ISR access is write one to clear (W1C) */
225     	IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base,
226     		ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_ERASE_MASK );
227     	return -EIO; /* erase failed, sector might be protected */
228     }
229 
230     return ret_code;
231 }
232 
233 /**
234  * alt_epcq_controller_write_block
235  *
236  * This function writes one block/sector of data to flash. The length of the write can NOT
237  * spill into the adjacent sector.
238  *
239  * It assumes that someone has already erased the appropriate sector(s).
240  *
241  * Arguments:
242  * - *flash_info: Pointer to EPCQ flash device structure.
243  * - block_offset: byte-addressed offset, from the start of flash, of the sector to written to
244  * - data-offset: Byte offset (unaligned access) of write into flash memory.
245  *                For best performance, word(32 bits - aligned access) offset of write is recommended.
246  * - *src_addr: source buffer
247  * - length: size of writing
248  *
249  * Returns:
250  * 0 -> success
251  * -EINVAL -> Invalid arguments
252  * -EIO -> write failed, sector might be protected
253 **/
alt_epcq_controller_write_block(alt_flash_dev * flash_info,int block_offset,int data_offset,const void * data,int length)254 int alt_epcq_controller_write_block
255 (
256     alt_flash_dev *flash_info, /** flash device info */
257     int block_offset, /** sector/block offset in byte addressing */
258     int data_offset, /** offset of write from base address */
259     const void *data, /** data to be written */
260     int length /** bytes of data to be written, >0 */
261 )
262 {
263     alt_u32 buffer_offset = 0; /** offset into data buffer to get write data */
264     alt_u32 remaining_length = length; /** length left to write */
265     alt_u32 write_offset = data_offset; /** offset into flash to write too */
266 
267     alt_epcq_controller_dev *epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
268 
269     /*
270      * Sanity checks that data offset is not larger then a sector, that block offset is
271      * sector aligned and within the valid flash memory range and a write doesn't spill into
272      * the adjacent flash sector.
273      */
274     if(block_offset < 0
275         || data_offset < 0
276         || NULL == flash_info
277         || NULL == data
278         || data_offset >= epcq_flash_info->size_in_bytes
279         || block_offset >= epcq_flash_info->size_in_bytes
280         || length > (epcq_flash_info->sector_size - (data_offset - block_offset))
281         || length < 0
282         || (block_offset & (epcq_flash_info->sector_size - 1)) != 0)
283     {
284     	return -EINVAL;
285     }
286 
287     /*
288      * Do writes one 32-bit word at a time.
289      * We need to make sure that we pad the first few bytes so they're word aligned if they are
290      * not already.
291      */
292     while (remaining_length > 0)
293     {
294     	alt_u32 word_to_write = 0xFFFFFFFF; /** initialize word to write to blank word */
295     	alt_u32 padding = 0; /** bytes to pad the next word that is written */
296     	alt_u32 bytes_to_copy = sizeof(alt_u32); /** number of bytes from source to copy */
297 
298         /*
299          * we need to make sure the write is word aligned
300     	 * this should only be true at most 1 time
301     	 */
302         if (0 != (write_offset & (sizeof(alt_u32) - 1)))
303         {
304         	/*
305         	 * data is not word aligned
306         	 * calculate padding bytes need to add before start of a data offset
307         	 */
308             padding = write_offset & (sizeof(alt_u32) - 1);
309 
310             /* update variables to account for padding being added */
311             bytes_to_copy -= padding;
312 
313             if(bytes_to_copy > remaining_length)
314             {
315             	bytes_to_copy = remaining_length;
316             }
317 
318             write_offset = write_offset - padding;
319             if(0 != (write_offset & (sizeof(alt_u32) - 1)))
320             {
321             	return -EINVAL;
322             }
323         }
324         else
325         {
326             if(bytes_to_copy > remaining_length)
327             {
328             	bytes_to_copy = remaining_length;
329             }
330         }
331 
332         /* prepare the word to be written */
333         memcpy((((void*)&word_to_write)) + padding, ((void*)data) + buffer_offset, bytes_to_copy);
334 
335         /* update offset and length variables */
336         buffer_offset += bytes_to_copy;
337         remaining_length -= bytes_to_copy;
338 
339         /* write to flash 32 bits at a time */
340         IOWR_32DIRECT(epcq_flash_info->data_base, write_offset, word_to_write);
341 
342         /* check whether write triggered a illegal write interrupt */
343         if((IORD_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base) &
344         		ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK) ==
345         				ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_ACTIVE)
346         {
347 		    /* clear register */
348         	IOWR_ALTERA_EPCQ_CONTROLLER_ISR(epcq_flash_info->csr_base,
349 			ALTERA_EPCQ_CONTROLLER_ISR_ILLEGAL_WRITE_MASK );
350         	return -EIO; /** write failed, sector might be protected */
351         }
352 
353         /* update current offset */
354         write_offset = write_offset + sizeof(alt_u32);
355     }
356 
357     return 0;
358 }
359 
360 /**
361  * alt_epcq_controller_write
362  *
363  * Program the data into the flash at the selected address.
364  *
365  * The different between this function and alt_epcq_controller_write_block function
366  * is that this function (alt_epcq_controller_write) will automatically erase a block as needed
367  * Arguments:
368  * - *flash_info: Pointer to EPCQ flash device structure.
369  * - offset: Byte offset (unaligned access) of write to flash memory. For best performance,
370  *           word(32 bits - aligned access) offset of write is recommended.
371  * - *src_addr: source buffer
372  * - length: size of writing
373  *
374  * Returns:
375  * 0 -> success
376  * -EINVAL -> Invalid arguments
377  * -EIO -> write failed, sector might be protected
378  *
379 **/
alt_epcq_controller_write(alt_flash_dev * flash_info,int offset,const void * src_addr,int length)380 int alt_epcq_controller_write(
381     alt_flash_dev *flash_info, /** device info */
382     int offset, /** offset of write from base address */
383     const void *src_addr, /** source buffer */
384     int length /** size of writing */
385 )
386 {
387     alt_32 ret_code = 0;
388 
389     alt_epcq_controller_dev *epcq_flash_info = NULL;
390 
391     alt_u32 write_offset = offset; /** address of next byte to write */
392     alt_u32 remaining_length = length; /** length of write data left to be written */
393     alt_u32 buffer_offset = 0; /** offset into source buffer to get write data */
394     alt_u32 i = 0;
395 
396     /* return -EINVAL if flash_info and src_addr are NULL */
397 	if(NULL == flash_info || NULL == src_addr)
398     {
399     	return -EINVAL;
400     }
401 
402 	epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
403 
404     /* make sure the write parameters are within the bounds of the flash */
405     ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length);
406 
407 	if(0 != ret_code)
408 	{
409 		return ret_code;
410 	}
411 
412     /*
413      * This loop erases and writes data one sector at a time. We check for write completion
414      * before starting the next sector.
415      */
416     for(i = offset/epcq_flash_info->sector_size ; i < epcq_flash_info->number_of_sectors; i++)
417     {
418         alt_u32 block_offset = 0; /** block offset in byte addressing */
419     	alt_u32 offset_within_current_sector = 0; /** offset into current sector to write */
420         alt_u32 length_to_write = 0; /** length to write to current sector */
421 
422     	if(0 >= remaining_length)
423     	{
424     		break; /* out of data to write */
425     	}
426 
427         /* calculate current sector/block offset in byte addressing */
428         block_offset = write_offset & ~(epcq_flash_info->sector_size - 1);
429 
430         /* calculate offset into sector/block if there is one */
431         if(block_offset != write_offset)
432         {
433             offset_within_current_sector = write_offset - block_offset;
434         }
435 
436         /* erase sector */
437         ret_code = alt_epcq_controller_erase_block(flash_info, block_offset);
438 
439         if(0 != ret_code)
440         {
441             return ret_code;
442         }
443 
444         /* calculate the byte size of data to be written in a sector */
445         length_to_write = MIN(epcq_flash_info->sector_size - offset_within_current_sector,
446                 remaining_length);
447 
448         /* write data to erased block */
449         ret_code = alt_epcq_controller_write_block(flash_info, block_offset, write_offset,
450             src_addr + buffer_offset, length_to_write);
451 
452 
453         if(0 != ret_code)
454         {
455             return ret_code;
456         }
457 
458         /* update remaining length and buffer_offset pointer */
459         remaining_length -= length_to_write;
460         buffer_offset += length_to_write;
461         write_offset += length_to_write;
462     }
463 
464     return ret_code;
465 }
466 
467 /**
468  * alt_epcq_controller_read
469  *
470  * There's no real need to use this function as opposed to using memcpy directly. It does
471  * do some sanity checks on the bounds of the read.
472  *
473  * Arguments:
474  * - *flash_info: Pointer to general flash device structure.
475  * - offset: offset read from flash memory.
476  * - *dest_addr: destination buffer
477  * - length: size of reading
478  *
479  * Returns:
480  * 0 -> success
481  * -EINVAL -> Invalid arguments
482 **/
alt_epcq_controller_read(alt_flash_dev * flash_info,int offset,void * dest_addr,int length)483 int alt_epcq_controller_read
484 (
485     alt_flash_dev *flash_info, /** device info */
486     int offset, /** offset of read from base address */
487     void *dest_addr, /** destination buffer */
488     int length /** size of read */
489 )
490 {
491     alt_32 ret_code = 0;
492 	alt_epcq_controller_dev *epcq_flash_info = NULL;
493 
494 	/* return -EINVAL if flash_info and dest_addr are NULL */
495 	if(NULL == flash_info || NULL == dest_addr)
496     {
497     	return -EINVAL;
498     }
499 
500     epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
501 
502 	/* validate arguments */
503 	ret_code = alt_epcq_validate_read_write_arguments(epcq_flash_info, offset, length);
504 
505 	/* copy data from flash to destination address */
506 	if(0 == ret_code)
507 	{
508 		memcpy(dest_addr, (alt_u8*)epcq_flash_info->data_base + offset, length);
509 	}
510 
511     return ret_code;
512 }
513 
514 /**
515  * altera_epcq_controller_init
516  *
517  * alt_sys_init.c will call this function automatically through macro
518  *
519  * Information in system.h is checked against expected values that are determined by the silicon_id.
520  * If the information doesn't match then this system is configured incorrectly. Most likely the wrong
521  * type of EPCS or EPCQ device was selected when instantiating the soft IP.
522  *
523  * Arguments:
524  * - *flash: Pointer to EPCQ flash device structure.
525  *
526  * Returns:
527  * 0 -> success
528  * -EINVAL -> Invalid arguments.
529  * -ENODEV -> System is configured incorrectly.
530 **/
altera_epcq_controller_init(alt_epcq_controller_dev * flash)531 alt_32 altera_epcq_controller_init(alt_epcq_controller_dev *flash)
532 {
533 	alt_u32 silicon_id = 0;
534 	alt_u32 size_in_bytes = 0;
535 	alt_u32 number_of_sectors = 0;
536 
537     /* return -EINVAL if flash is NULL */
538 	if(NULL == flash)
539     {
540     	return -EINVAL;
541     }
542 
543 	/* return -ENODEV if CSR slave is not attached */
544 	if(NULL == (void *)flash->csr_base)
545 	{
546 		return -ENODEV;
547 	}
548 
549 
550 	/*
551 	 * If flash is an EPCQ device, we read the EPCQ_RD_RDID register for the ID
552 	 * If flash is an EPCS device, we read the EPCQ_RD_SID register for the ID
553 	 *
554 	 * Whether or not the flash is a EPCQ or EPCS is indicated in the system.h. The system.h gets
555 	 * this value from the hw.tcl of the IP. If this value is set incorrectly, then things will go
556 	 * badly.
557 	 *
558 	 * In both cases, we can determine the number of sectors, which we can use
559 	 * to calculate a size. We compare that size to the system.h value to make sure
560 	 * the EPCQ soft IP was configured correctly.
561 	 */
562 	if(0 == flash->is_epcs)
563 	{
564 		/* If we're an EPCQ, we read EPCQ_RD_RDID for the silicon ID */
565 		silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_RDID(flash->csr_base);
566 		silicon_id &= ALTERA_EPCQ_CONTROLLER_RDID_MASK;
567 
568 		/* Determine which EPCQ device so we can figure out the number of sectors */
569 		/* EPCQ share the same ID for the same capacity*/
570 		switch(silicon_id)
571 		{
572 			case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ16:
573 			{
574 				number_of_sectors = 32;
575 				break;
576 			}
577 			case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ32:
578 			{
579 				number_of_sectors = 64;
580 				break;
581 			}
582 			case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ64:
583 			{
584 				number_of_sectors = 128;
585 				break;
586 			}
587 			case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ128:
588 			{
589 				number_of_sectors = 256;
590 				break;
591 			}
592 			case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ256:
593 			{
594 				number_of_sectors = 512;
595 				break;
596 			}
597 			case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ512:
598 			{
599 				number_of_sectors = 1024;
600 				break;
601 			}
602 			case ALTERA_EPCQ_CONTROLLER_RDID_EPCQ1024:
603 			{
604 				number_of_sectors = 2048;
605 				break;
606 			}
607 			default:
608 			{
609 				return -ENODEV;
610 			}
611 		}
612 	}
613 	else {
614 		/* If we're an EPCS, we read EPCQ_RD_SID for the silicon ID */
615 		silicon_id = IORD_ALTERA_EPCQ_CONTROLLER_SID(flash->csr_base);
616 		silicon_id &= ALTERA_EPCQ_CONTROLLER_SID_MASK;
617 
618 		/* Determine which EPCS device so we can figure out various properties */
619 		switch(silicon_id)
620 		{
621 			case ALTERA_EPCQ_CONTROLLER_SID_EPCS16:
622 			{
623 				number_of_sectors = 32;
624 				break;
625 			}
626 			case ALTERA_EPCQ_CONTROLLER_SID_EPCS64:
627 			{
628 				number_of_sectors = 128;
629 				break;
630 			}
631 			case ALTERA_EPCQ_CONTROLLER_SID_EPCS128:
632 			{
633 				number_of_sectors = 256;
634 				break;
635 			}
636 			default:
637 			{
638 				return -ENODEV;
639 			}
640 		}
641 	}
642 
643 	/* Calculate size of flash based on number of sectors */
644 	size_in_bytes = number_of_sectors * flash->sector_size;
645 
646 	/*
647 	 * Make sure calculated size is the same size given in system.h
648 	 * Also check number of sectors is the same number given in system.h
649 	 * Otherwise the EPCQ IP was not configured correctly
650 	 */
651 	if(	size_in_bytes != flash->size_in_bytes ||
652 			number_of_sectors != flash->number_of_sectors)
653 	{
654 		flash->dev.number_of_regions = 0;
655 		return -ENODEV;
656 	}
657 	else
658 	{
659 		flash->silicon_id = silicon_id;
660 		flash->number_of_sectors = number_of_sectors;
661 
662 		/*
663 		 * populate fields of region_info required to conform to HAL API
664 		 * create 1 region that composed of "number_of_sectors" blocks
665 		 */
666 		flash->dev.number_of_regions = 1;
667 		flash->dev.region_info[0].offset = 0;
668 		flash->dev.region_info[0].region_size = size_in_bytes;
669 		flash->dev.region_info[0].number_of_blocks = number_of_sectors;
670 		flash->dev.region_info[0].block_size = flash->sector_size;
671 	}
672 
673 
674     /*
675      * Register this device as a valid flash device type
676      *
677      * Only register the device if it's configured correctly.
678      */
679 		alt_flash_device_register(&(flash->dev));
680 
681 
682     return 0;
683 }
684 
685 
686 /*
687  *	Private API
688  *
689  *	Helper functions used by Public API functions.
690  *
691  * Arguments:
692  * - *flash_info: Pointer to EPCQ flash device structure.
693  * - offset: Offset of read/write from base address.
694  * - length: Length of read/write in bytes.
695  *
696  * Returns:
697  * 0 -> success
698  * -EINVAL -> Invalid arguments
699  */
700 /**
701  * Used to check that arguments to a read or write are valid
702  */
alt_epcq_validate_read_write_arguments(alt_epcq_controller_dev * flash_info,alt_u32 offset,alt_u32 length)703 ALT_INLINE alt_32 static alt_epcq_validate_read_write_arguments
704 (
705 		alt_epcq_controller_dev *flash_info, /** device info */
706 		alt_u32 offset, /** offset of read/write */
707 		alt_u32 length /** length of read/write */
708 )
709 {
710     alt_epcq_controller_dev *epcq_flash_info = NULL;
711     alt_u32 start_address = 0;
712     alt_32 end_address = 0;
713 
714   /* return -EINVAL if flash_info is NULL */
715    if(NULL == flash_info)
716    {
717     	return -EINVAL;
718    }
719 
720   epcq_flash_info = (alt_epcq_controller_dev*)flash_info;
721 
722   start_address = epcq_flash_info->data_base + offset; /** first address of read or write */
723   end_address = start_address + length; /** last address of read or write (not inclusive) */
724 
725   /* make sure start and end address is less then the end address of the flash */
726   if(
727 		  start_address >= epcq_flash_info->data_end ||
728 		  end_address > epcq_flash_info->data_end ||
729 		  offset < 0 ||
730 		  length < 0
731   )
732   {
733 	  return -EINVAL;
734   }
735 
736   return 0;
737 }
738 
739 /*
740  * Private function that polls write in progress bit EPCQ_RD_STATUS.
741  *
742  * Write in progress will be set if any of the following operations are in progress:
743  * 	-WRITE STATUS REGISTER
744  * 	-WRITE NONVOLATILE CONFIGURATION REGISTER
745  * 	-PROGRAM
746  * 	-ERASE
747  *
748  * Assumes EPCQ was configured correctly.
749  *
750  * If ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE is set, the function will time out after
751  * a period of time determined by that value.
752  *
753  * Arguments:
754  * - *epcq_flash_info: Pointer to EPCQ flash device structure.
755  *
756  * Returns:
757  * 0 -> success
758  * -EINVAL -> Invalid arguments
759  * -ETIME  -> Time out and skipping the looping after 0.7 sec.
760  */
alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev * epcq_flash_info)761 alt_32 static alt_epcq_poll_for_write_in_progress(alt_epcq_controller_dev* epcq_flash_info)
762 {
763     /* we'll want to implement timeout if a timeout value is specified */
764 #if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0
765 	alt_u32 timeout = ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE;
766 	alt_u16 counter = 0;
767 #endif
768 
769     /* return -EINVAL if epcq_flash_info is NULL */
770 	if(NULL == epcq_flash_info)
771     {
772     	return -EINVAL;
773     }
774 
775 	/* while Write in Progress bit is set, we wait */
776 	while((IORD_ALTERA_EPCQ_CONTROLLER_STATUS(epcq_flash_info->csr_base) &
777 			ALTERA_EPCQ_CONTROLLER_STATUS_WIP_MASK) ==
778 			ALTERA_EPCQ_CONTROLLER_STATUS_WIP_BUSY)
779 	{
780         alt_busy_sleep(1); /* delay 1us */
781 #if ALTERA_EPCQ_CONTROLLER_1US_TIMEOUT_VALUE > 0
782 		if(timeout <= counter )
783 		{
784 			return -ETIME;
785 		}
786 
787 		counter++;
788 #endif
789 
790 	}
791 
792 	return 0;
793 }
794