Remove FSF mailing address.
[fw/openocd] / contrib / loaders / flash / at91sam7x / main.c
1 /***************************************************************************
2  *   Copyright (C) 2007 by Pavel Chromy                                    *
3  *   chromy@asix.cz                                                        *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
17  ***************************************************************************/
18 #include "platform.h"
19
20 #include <flash/nor/ocl.h>
21 #include "dcc.h"
22 #include "samflash.h"
23
24
25 #define BUFSIZE 1024 /* words, i.e. 4 KiB */
26 uint32 buffer[1024];
27
28 void cmd_flash(uint32 cmd)
29 {
30         unsigned int len;
31         uint32 adr;
32         uint32 chksum;
33         unsigned int bi; /* buffer index */
34         unsigned int bi_start; /* receive start mark */
35         unsigned int bi_end; /* receive end mark */
36         unsigned int ofs;
37         int pagenum;
38         int result;
39
40         adr = dcc_rd();
41         len = cmd&0xffff;
42         ofs = adr%flash_page_size;
43         bi_start = ofs/4;
44         bi_end = (ofs + len + 3)/4;
45
46         if (bi_end > BUFSIZE) {
47                 dcc_wr(OCL_BUFF_OVER);
48                 return;
49         }
50
51         chksum = OCL_CHKS_INIT;
52         for (bi = 0; bi < bi_end; bi++) chksum^=buffer[bi]=dcc_rd();
53
54         if (dcc_rd() != chksum) {
55                 dcc_wr(OCL_CHKS_FAIL);
56                 return;
57         }
58
59         /* fill in unused positions with unprogrammed values */
60         for (bi = 0; bi < bi_start; bi++) buffer[bi]=0xffffffff;
61         for (bi = bi_end; bi%flash_page_size; bi++) buffer[bi]=0xffffffff;
62
63         result = 0;
64         pagenum = adr/flash_page_size;
65         for (bi = 0; bi < bi_end; bi += flash_page_size/4) {
66                 result = flash_page_program(buffer + bi, pagenum++);
67                 if (result) break;
68         }
69
70         /* verify written data */
71         if (!result) result = flash_verify(adr, len, ((uint8 *)buffer) + ofs);
72
73         dcc_wr(OCL_CMD_DONE | result);
74 }
75
76
77 int main (void)
78 {
79         uint32 cmd;
80
81         for (;;) {
82                 cmd = dcc_rd();
83                 switch (cmd&OCL_CMD_MASK) {
84                         case OCL_PROBE:
85                                 dcc_wr(OCL_CMD_DONE | flash_init());
86                                 dcc_wr(0x100000); /* base */
87                                 dcc_wr(flash_page_count*flash_page_size); /* size */
88                                 dcc_wr(1); /* num_sectors */
89                                 dcc_wr(4096 | ((unsigned long) flash_page_size << 16)); /* buflen and bufalign */
90                                 break;
91                         case OCL_ERASE_ALL:
92                                 dcc_wr(OCL_CMD_DONE | flash_erase_all());
93                                 break;
94                         case OCL_FLASH_BLOCK:
95                                 cmd_flash(cmd);
96                                 break;
97                         default:
98                                 /* unknown command */
99                                 dcc_wr(OCL_CMD_ERR);
100                                 break;
101                 }
102         }
103
104         return(0); /* we shall never get here, just to supress compiler warning */
105 }