- Fixes '==' whitespace
[fw/openocd] / src / flash / ocl / at91sam7x / samflash.c
index 253e410c22bac20d5f2038ebf5ab5c1ff659b382..a534f6d8de1dc270efa879609a583cf1ea4cc5f5 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2007 by Pavel Chromy                                    *\r
- *   chromy@asix.cz                                                        *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-#include "samflash.h"\r
-\r
-\r
-unsigned int flash_page_count=1024;\r
-unsigned int flash_page_size=256;\r
-\r
-/* pages per lock bit */\r
-unsigned int flash_lock_pages=1024/16;\r
-\r
-\r
-/* detect chip and set loader parameters */\r
-int flash_init(void)\r
-{\r
-       unsigned int nvpsiz;\r
-\r
-       nvpsiz=(inr(DBGU_CIDR)>>8)&0xf;\r
-\r
-       switch (nvpsiz) {\r
-               case 3:\r
-                       /* AT91SAM7x32 */\r
-                       flash_page_count=256;\r
-                       flash_page_size=128;\r
-                       flash_lock_pages=256/8;\r
-                       break;\r
-               case 5:\r
-                       /* AT91SAM7x64 */\r
-                       flash_page_count=512;\r
-                       flash_page_size=128;\r
-                       flash_lock_pages=512/16;\r
-                       break;\r
-               case 7:\r
-                       /* AT91SAM7x128*/\r
-                       flash_page_count=512;\r
-                       flash_page_size=256;\r
-                       flash_lock_pages=512/8;\r
-                       break;\r
-               case 9:\r
-                       /* AT91SAM7x256 */\r
-                       flash_page_count=1024;\r
-                       flash_page_size=256;\r
-                       flash_lock_pages=1024/16;\r
-                       break;\r
-               case 10:\r
-                       /* AT91SAM7x512 */\r
-                       flash_page_count=2048;\r
-                       flash_page_size=256;\r
-                       flash_lock_pages=2048/32;\r
-                       break;\r
-               default:\r
-                       return FLASH_STAT_INITE;\r
-       }\r
-       return FLASH_STAT_OK;\r
-}\r
-\r
-\r
-/* program single flash page */\r
-int flash_page_program(uint32 *data, int page_num)\r
-{\r
-       int i;\r
-       int efc_ofs;\r
-\r
-       uint32 *flash_ptr;\r
-       uint32 *data_ptr;\r
-\r
-       /* select proper controller */\r
-       if (page_num>=1024) efc_ofs=0x10;\r
-       else efc_ofs=0;\r
-\r
-       /* wait until FLASH is ready, just for sure */\r
-       while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);\r
-\r
-       /* calculate page address, only lower 8 bits are used to address the latch,\r
-                but the upper part of address is needed for writing to proper EFC */\r
-       flash_ptr=(uint32 *)(FLASH_AREA_ADDR+(page_num*flash_page_size));\r
-       data_ptr=data;\r
-\r
-       /* copy data to latch */\r
-       for (i=flash_page_size/4; i; i--) {\r
-               /* we do not use memcpy to be sure that only 32 bit access is used */\r
-               *(flash_ptr++)=*(data_ptr++);\r
-       }\r
-\r
-       /* page number and page write command to FCR */\r
-       outr(MC_FCR+efc_ofs, ((page_num&0x3ff)<<8) | MC_KEY | MC_FCMD_WP);\r
-\r
-       /* wait until it's done */\r
-       while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);\r
-\r
-       /* check for errors */\r
-       if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;\r
-       if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;\r
-\r
-#if 0\r
-       /* verify written data */\r
-       flash_ptr=(uint32 *)(FLASH_AREA_ADDR+(page_num*flash_page_size));\r
-       data_ptr=data;\r
-\r
-       for (i=flash_page_size/4; i; i--) {\r
-               if (*(flash_ptr++)!=*(data_ptr++)) return FLASH_STAT_VERIFE;\r
-       }\r
-#endif\r
-\r
-       return FLASH_STAT_OK;\r
-}\r
-\r
-\r
-int flash_erase_plane(int efc_ofs)\r
-{\r
-       unsigned int lockbits;\r
-       int page_num;\r
-\r
-       page_num=0;\r
-       lockbits=inr(MC_FSR+efc_ofs)>>16;\r
-       while (lockbits) {\r
-               if (lockbits&1) {\r
-\r
-                       /* wait until FLASH is ready, just for sure */\r
-                       while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);\r
-\r
-                       outr(MC_FCR+efc_ofs, ((page_num&0x3ff)<<8) | 0x5a000004);\r
-\r
-                       /* wait until it's done */\r
-                       while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);\r
-\r
-                       /* check for errors */\r
-                       if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;\r
-                       if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;\r
-\r
-               }\r
-               if ((page_num+=flash_lock_pages)>flash_page_count) break;\r
-               lockbits>>=1;\r
-       }\r
-\r
-       /* wait until FLASH is ready, just for sure */\r
-       while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);\r
-\r
-       /* erase all command to FCR */\r
-       outr(MC_FCR+efc_ofs, 0x5a000008);\r
-\r
-       /* wait until it's done */\r
-       while ((inr(MC_FSR+efc_ofs)&MC_FRDY)==0);\r
-\r
-       /* check for errors */\r
-       if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;\r
-       if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;\r
-\r
-       /* set no erase before programming */\r
-       outr(MC_FMR+efc_ofs, inr(MC_FMR+efc_ofs)|0x80);\r
-\r
-       return FLASH_STAT_OK;\r
-}\r
-\r
-\r
-/* erase whole chip */\r
-int flash_erase_all(void)\r
-{\r
-       int result;\r
-       \r
-       if ((result=flash_erase_plane(0))!=FLASH_STAT_OK) return result;\r
-\r
-       /* the second flash controller, if any */\r
-       if (flash_page_count>1024) result=flash_erase_plane(0x10);\r
-\r
-       return result;\r
-}\r
-\r
-\r
-int flash_verify(uint32 adr, unsigned int len, uint8 *src)\r
-{\r
-       unsigned char *flash_ptr;\r
-\r
-       flash_ptr=(uint8 *)FLASH_AREA_ADDR+adr;\r
-       for ( ;len; len--) {\r
-               if (*(flash_ptr++)!=*(src++)) return FLASH_STAT_VERIFE;\r
-       }\r
-       return FLASH_STAT_OK;\r
-}\r
+/***************************************************************************
+ *   Copyright (C) 2007 by Pavel Chromy                                    *
+ *   chromy@asix.cz                                                        *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#include "samflash.h"
+
+
+unsigned int flash_page_count=1024;
+unsigned int flash_page_size=256;
+
+/* pages per lock bit */
+unsigned int flash_lock_pages=1024/16;
+
+
+/* detect chip and set loader parameters */
+int flash_init(void)
+{
+       unsigned int nvpsiz;
+
+       nvpsiz=(inr(DBGU_CIDR) >> 8)&0xf;
+
+       switch (nvpsiz) {
+               case 3:
+                       /* AT91SAM7x32 */
+                       flash_page_count=256;
+                       flash_page_size=128;
+                       flash_lock_pages=256/8;
+                       break;
+               case 5:
+                       /* AT91SAM7x64 */
+                       flash_page_count=512;
+                       flash_page_size=128;
+                       flash_lock_pages=512/16;
+                       break;
+               case 7:
+                       /* AT91SAM7x128*/
+                       flash_page_count=512;
+                       flash_page_size=256;
+                       flash_lock_pages=512/8;
+                       break;
+               case 9:
+                       /* AT91SAM7x256 */
+                       flash_page_count=1024;
+                       flash_page_size=256;
+                       flash_lock_pages=1024/16;
+                       break;
+               case 10:
+                       /* AT91SAM7x512 */
+                       flash_page_count=2048;
+                       flash_page_size=256;
+                       flash_lock_pages=2048/32;
+                       break;
+               default:
+                       return FLASH_STAT_INITE;
+       }
+       return FLASH_STAT_OK;
+}
+
+
+/* program single flash page */
+int flash_page_program(uint32 *data, int page_num)
+{
+       int i;
+       int efc_ofs;
+
+       uint32 *flash_ptr;
+       uint32 *data_ptr;
+
+       /* select proper controller */
+       if (page_num >= 1024) efc_ofs=0x10;
+       else efc_ofs=0;
+
+       /* wait until FLASH is ready, just for sure */
+       while ((inr(MC_FSR+efc_ofs)&MC_FRDY) == 0);
+
+       /* calculate page address, only lower 8 bits are used to address the latch,
+                but the upper part of address is needed for writing to proper EFC */
+       flash_ptr=(uint32 *)(FLASH_AREA_ADDR+(page_num*flash_page_size));
+       data_ptr=data;
+
+       /* copy data to latch */
+       for (i=flash_page_size/4; i; i--) {
+               /* we do not use memcpy to be sure that only 32 bit access is used */
+               *(flash_ptr++)=*(data_ptr++);
+       }
+
+       /* page number and page write command to FCR */
+       outr(MC_FCR+efc_ofs, ((page_num&0x3ff) << 8) | MC_KEY | MC_FCMD_WP);
+
+       /* wait until it's done */
+       while ((inr(MC_FSR+efc_ofs)&MC_FRDY) == 0);
+
+       /* check for errors */
+       if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
+       if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
+
+#if 0
+       /* verify written data */
+       flash_ptr=(uint32 *)(FLASH_AREA_ADDR+(page_num*flash_page_size));
+       data_ptr=data;
+
+       for (i=flash_page_size/4; i; i--) {
+               if (*(flash_ptr++)!=*(data_ptr++)) return FLASH_STAT_VERIFE;
+       }
+#endif
+
+       return FLASH_STAT_OK;
+}
+
+
+int flash_erase_plane(int efc_ofs)
+{
+       unsigned int lockbits;
+       int page_num;
+
+       page_num=0;
+       lockbits=inr(MC_FSR+efc_ofs) >> 16;
+       while (lockbits) {
+               if (lockbits&1) {
+
+                       /* wait until FLASH is ready, just for sure */
+                       while ((inr(MC_FSR+efc_ofs)&MC_FRDY) == 0);
+
+                       outr(MC_FCR+efc_ofs, ((page_num&0x3ff) << 8) | 0x5a000004);
+
+                       /* wait until it's done */
+                       while ((inr(MC_FSR+efc_ofs)&MC_FRDY) == 0);
+
+                       /* check for errors */
+                       if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
+                       if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
+
+               }
+               if ((page_num += flash_lock_pages)>flash_page_count) break;
+               lockbits>>=1;
+       }
+
+       /* wait until FLASH is ready, just for sure */
+       while ((inr(MC_FSR+efc_ofs)&MC_FRDY) == 0);
+
+       /* erase all command to FCR */
+       outr(MC_FCR+efc_ofs, 0x5a000008);
+
+       /* wait until it's done */
+       while ((inr(MC_FSR+efc_ofs)&MC_FRDY) == 0);
+
+       /* check for errors */
+       if ((inr(MC_FSR+efc_ofs)&MC_PROGE)) return FLASH_STAT_PROGE;
+       if ((inr(MC_FSR+efc_ofs)&MC_LOCKE)) return FLASH_STAT_LOCKE;
+
+       /* set no erase before programming */
+       outr(MC_FMR+efc_ofs, inr(MC_FMR+efc_ofs)|0x80);
+
+       return FLASH_STAT_OK;
+}
+
+
+/* erase whole chip */
+int flash_erase_all(void)
+{
+       int result;
+       
+       if ((result=flash_erase_plane(0)) != FLASH_STAT_OK) return result;
+
+       /* the second flash controller, if any */
+       if (flash_page_count>1024) result=flash_erase_plane(0x10);
+
+       return result;
+}
+
+
+int flash_verify(uint32 adr, unsigned int len, uint8 *src)
+{
+       unsigned char *flash_ptr;
+
+       flash_ptr=(uint8 *)FLASH_AREA_ADDR+adr;
+       for ( ;len; len--) {
+               if (*(flash_ptr++)!=*(src++)) return FLASH_STAT_VERIFE;
+       }
+       return FLASH_STAT_OK;
+}