9f41965c76caa966ab50417e76ff78848707eab3
[fw/openocd] / contrib / loaders / flash / pic32mx.s
1 /***************************************************************************
2  *   Copyright (C) 2010 by Spencer Oliver                                  *
3  *   spen@spen-soft.co.uk                                                  *
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, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
19  ***************************************************************************/
20
21         .text
22         .arch m4k
23         .set noreorder
24         .set noat
25
26 /* params:
27  * $a0 src adr - ram + result
28  * $a1 dest adr - flash
29  * $a2 count (32bit words)
30  * vars
31  *
32  * temps:
33  * $t0, $t1, $t2, $t3, $t4, $t5
34  * $s0, $s1, $s3, $s4, $s5
35  */
36
37         .type main, @function
38         .global main
39
40 .ent main
41 main:
42         /* setup constants */
43         lui             $t0, 0xaa99
44         ori             $t0, 0x6655                             /* NVMKEY1 */
45         lui             $t1, 0x5566
46         ori             $t1, 0x99AA                             /* NVMKEY2 */
47         lui             $t2, 0xBF80
48         ori             $t2, 0xF400                             /* NVMCON */
49         ori             $t3, $zero, 0x4003              /* NVMCON row write cmd */
50         ori             $t4, $zero, 0x8000              /* NVMCON start cmd */
51
52 write_row:
53         /* can we perform a row write: 128 32bit words */
54         sltiu   $s3, $a2, 128
55         bne             $s3, $zero, write_word
56         ori             $t5, $zero, 0x4000              /* NVMCON clear cmd */
57
58         /* perform row write 512 bytes */
59         sw              $a1, 32($t2)    /* set NVMADDR with dest addr - real addr */
60         sw              $a0, 64($t2)    /* set NVMSRCADDR with src addr - real addr */
61
62         bal             progflash
63         addiu   $a0, $a0, 512
64         addiu   $a1, $a1, 512
65         beq             $zero, $zero, write_row
66         addiu   $a2, $a2, -128
67
68 write_word:
69         /* write 32bit words */
70         lui             $s5, 0xa000
71         ori             $s5, 0x0000
72         or              $a0, $a0, $s5                   /* convert to virtual addr */
73
74         beq             $zero, $zero, next_word
75         ori             $t3, $zero, 0x4001              /* NVMCON word write cmd */
76
77 prog_word:
78         lw              $s4, 0($a0)             /* load data - from virtual addr */
79         sw              $s4, 48($t2)    /* set NVMDATA with data */
80         sw              $a1, 32($t2)    /* set NVMADDR with dest addr - real addr */
81
82         bal             progflash
83         addiu   $a0, $a0, 4
84         addiu   $a1, $a1, 4
85         addiu   $a2, $a2, -1
86 next_word:
87         bne             $a2, $zero, prog_word
88         nop
89
90 done:
91         beq             $zero, $zero, exit
92         addiu   $a0, $zero, 0
93
94 error:
95         /* save result to $a0 */
96         addiu   $a0, $s1, 0
97
98 exit:
99         sdbbp
100 .end main
101
102         .type progflash, @function
103         .global progflash
104
105 .ent progflash
106 progflash:
107         sw              $t3, 0($t2)             /* set NVMWREN */
108         sw              $t0, 16($t2)    /* write NVMKEY1 */
109         sw              $t1, 16($t2)    /* write NVMKEY2 */
110         sw              $t4, 8($t2)             /* start operation */
111
112 waitflash:
113         lw              $s0, 0($t2)
114         and             $s0, $s0, $t4
115         bne             $s0, $zero, waitflash
116         nop
117
118         /* following is to comply with errata #34
119          * 500ns delay required */
120         nop
121         nop
122         nop
123         nop
124         /* check for errors */
125         lw              $s1, 0($t2)
126         andi    $s1, $zero, 0x3000
127         bne             $s1, $zero, error
128         sw              $t5, 4($t2)             /* clear NVMWREN */
129         jr              $ra
130         nop
131
132 .end progflash