]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/glsdk-u-boot.git/blob - arch/ppc/cpu/mpc512x/iim.c
nios2: Move individual board linker scripts to common script in cpu tree.
[glsdk/glsdk-u-boot.git] / arch / ppc / cpu / mpc512x / iim.c
1 /*
2  * Copyright 2008 Silicon Turnkey Express, Inc.
3  * Martha Marx <mmarx@silicontkx.com>
4  *
5  * ADS5121 IIM (Fusebox) Interface
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
26 #include <common.h>
27 #include <command.h>
28 #include <asm/io.h>
30 #ifdef CONFIG_CMD_FUSE
32 DECLARE_GLOBAL_DATA_PTR;
34 static char cur_bank = '1';
36 char *iim_err_msg(u32 err)
37 {
38         static char *IIM_errs[] = {
39                 "Parity Error in cache",
40                 "Explicit Sense Cycle Error",
41                 "Write to Locked Register Error",
42                 "Read Protect Error",
43                 "Override Protect Error",
44                 "Write Protect Error"};
46         int i;
48         if (!err)
49                 return "";
50         for (i = 1; i < 8; i++)
51                 if (err & (1 << i))
52                         printf("IIM - %s\n", IIM_errs[i-1]);
53         return "";
54 }
56 int in_range(int n, int min, int max, char *err, char *usg)
57 {
58         if (n > max || n < min) {
59                 printf(err);
60                 printf("Usage:\n%s\n", usg);
61                 return 0;
62         }
63         return 1;
64 }
66 int ads5121_fuse_read(int bank, int fstart, int num)
67 {
68         iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
69         u32 *iim_fb, dummy;
70         int f, ctr;
72         out_be32(&iim->err, in_be32(&iim->err));
73         if (bank == 0)
74                 iim_fb = (u32 *)&(iim->fbac0);
75         else
76                 iim_fb = (u32 *)&(iim->fbac1);
77 /* try a read to see if Read Protect is set */
78         dummy = in_be32(&iim_fb[0]);
79         if (in_be32(&iim->err) & IIM_ERR_RPE) {
80                 printf("\tRead protect fuse is set\n");
81                 out_be32(&iim->err, IIM_ERR_RPE);
82                 return 0;
83         }
84         printf("Reading Bank %d cache\n", bank);
85         for (f = fstart, ctr = 0; num > 0; ctr++, num--, f++) {
86                 if (ctr % 4 == 0)
87                         printf("F%2d:", f);
88                 printf("\t%#04x", (u8)(iim_fb[f]));
89                 if (ctr % 4 == 3)
90                         printf("\n");
91         }
92         if (ctr % 4 != 0)
93                 printf("\n");
94 }
96 int ads5121_fuse_override(int bank, int f, u8 val)
97 {
98         iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
99         u32 *iim_fb;
100         u32 iim_stat;
101         int i;
103         out_be32(&iim->err, in_be32(&iim->err));
104         if (bank == 0)
105                 iim_fb = (u32 *)&(iim->fbac0);
106         else
107                 iim_fb = (u32 *)&(iim->fbac1);
108 /* try a read to see if Read Protect is set */
109         iim_stat = in_be32(&iim_fb[0]);
110         if (in_be32(&iim->err) & IIM_ERR_RPE) {
111                 printf("Read protect fuse is set on bank %d;"
112                         "Override protect may also be set\n", bank);
113                 printf("An attempt will be made to override\n");
114                 out_be32(&iim->err, IIM_ERR_RPE);
115         }
116         if (iim_stat & IIM_FBAC_FBOP) {
117                 printf("Override protect fuse is set on bank %d\n", bank);
118                 return 1;
119         }
120         if (f > IIM_FMAX) /* reset the entire bank */
121                 for (i = 0; i < IIM_FMAX + 1; i++)
122                         out_be32(&iim_fb[i],  0);
123         else
124                 out_be32(&iim_fb[f], val);
125         return 0;
128 int ads5121_fuse_prog(cmd_tbl_t *cmdtp, int bank, char *fuseno_bitno)
130         iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
131         int f, i, bitno;
132         u32 stat, err;
134         f = simple_strtol(fuseno_bitno, NULL, 10);
135         if (f == 0 && fuseno_bitno[0] != '0')
136                 f = -1;
137         if (!in_range(f, 0, IIM_FMAX,
138                 "<frow> must be between 0-31\n\n", cmdtp->usage))
139                 return 1;
140         bitno = -1;
141         for (i = 0; i < 6; i++) {
142                 if (fuseno_bitno[i] == '_') {
143                         bitno = simple_strtol(&(fuseno_bitno[i+1]), NULL, 10);
144                         if (bitno == 0 && fuseno_bitno[i+1] != '0')
145                                 bitno = -1;
146                         break;
147                 }
148         }
149         if (!in_range(bitno, 0, 7, "Bit number ranges from 0-7\n"
150                 "Example of <frow_bitno>: \"18_4\" sets bit 4 of row 18\n",
151                 cmdtp->usage))
152                 return 1;
153         out_be32(&iim->err, in_be32(&iim->err));
154         out_be32(&iim->prg_p, IIM_PRG_P_SET);
155         out_be32(&iim->ua, IIM_SET_UA(bank, f));
156         out_be32(&iim->la, IIM_SET_LA(f, bitno));
157 #ifdef DEBUG
158         printf("Programming disabled with DEBUG defined \n");
159         printf(""Set up to pro
160         printf("iim.ua = %x; iim.la = %x\n", iim->ua, iim->la);
161 #else
162         out_be32(&iim->fctl, IIM_FCTL_PROG_PULSE | IIM_FCTL_PROG);
163         do
164                 udelay(20);
165         while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
166         out_be32(&iim->prg_p, 0);
167         err = in_be32(&iim->err);
168         if (stat & IIM_STAT_PRGD) {
169                 if (!(err & (IIM_ERR_WPE | IIM_ERR_WPE))) {
170                         printf("Fuse is successfully set");
171                         if (err)
172                                 printf(" - however there are other errors");
173                         printf("\n");
174                 }
175                 iim->stat = 0;
176         }
177         if (err) {
178                 iim_err_msg(err);
179                 out_be32(&iim->err, in_be32(&iim->err));
180         }
181 #endif
184 int ads5121_fuse_sense(int bank, int fstart, int num)
186         iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
187         u32 iim_fbac;
188         u32 stat, err, err_hold = 0;
189         int f, ctr;
191         out_be32(&iim->err, in_be32(&iim->err));
192         if (bank == 0)
193                 iim_fbac = in_be32(&iim->fbac0);
194         else
195                 iim_fbac = in_be32(&iim->fbac1);
196         if (iim_fbac & IIM_FBAC_FBESP) {
197                 printf("\tSense Protect disallows this operation\n");
198                 out_be32(&iim->err, IIM_FBAC_FBESP);
199                 return 1;
200         }
201         err = in_be32(&iim->err);
202         if (err) {
203                 iim_err_msg(err);
204                 err_hold |= err;
205         }
206         if (err & IIM_ERR_RPE)
207                 printf("\tRead protect fuse is set; "
208                         "Sense Protect may be set but will be attempted\n");
209         if (err)
210                 out_be32(&iim->err, err);
211         printf("Sensing fuse(s) on Bank %d\n", bank);
212         for (f = fstart, ctr = 0; num > 0; ctr++, f++, num--) {
213                 out_be32(&iim->ua, IIM_SET_UA(bank, f));
214                 out_be32(&iim->la, IIM_SET_LA(f, 0));
215                 out_be32(&iim->fctl,  IIM_FCTL_ESNS_N);
216                 do
217                         udelay(20);
218                 while ((stat = in_be32(&iim->stat)) & IIM_STAT_BUSY);
219                 err = in_be32(&iim->err);
220                 if (err & IIM_ERR_SNSE) {
221                         iim_err_msg(err);
222                         out_be32(&iim->err, IIM_ERR_SNSE);
223                         return 1;
224                 }
225                 if (stat & IIM_STAT_SNSD) {
226                         out_be32(&iim->stat, 0);
227                         if (ctr % 4 == 0)
228                                 printf("F%2d:", f);
229                         printf("\t%#04x", (u8)iim->sdat);
230                         if (ctr % 4 == 3)
231                                 printf("\n");
232                 }
233                 if (err) {
234                         err_hold |= err;
235                         out_be32(&iim->err, err);
236                 }
237         }
238         if (ctr % 4 != 0)
239                 printf("\n");
240         if (err_hold)
241                 iim_err_msg(err_hold);
243         return 0;
246 int ads5121_fuse_stat(int bank)
248         iim512x_t *iim = &((immap_t *) CONFIG_SYS_IMMR)->iim;
249         u32 iim_fbac;
250         u32 err;
252         out_be32(&iim->err, in_be32(&iim->err));
253         if (bank == 0)
254                 iim_fbac = in_be32(&iim->fbac0);
255         else
256                 iim_fbac = in_be32(&iim->fbac1);
257         err = in_be32(&iim->err);
258         if (err)
259                 iim_err_msg(err);
260         if (err & IIM_ERR_RPE  || iim_fbac & IIM_FBAC_FBRP) {
261                 if (iim_fbac == 0)
262                         printf("Since protection settings can't be read - "
263                                 "try sensing fuse row 0;\n");
264                 return 0;
265         }
266         if (iim_fbac & IIM_PROTECTION)
267                 printf("Protection Fuses Bank %d = %#04x:\n", bank, iim_fbac);
268         else if (!(err & IIM_ERR_RPE))
269                 printf("No Protection fuses are set\n");
270         if (iim_fbac & IIM_FBAC_FBWP)
271                 printf("\tWrite Protect fuse is set\n");
272         if (iim_fbac & IIM_FBAC_FBOP)
273                 printf("\tOverride Protect fuse is set\n");
274         if (iim_fbac & IIM_FBAC_FBESP)
275                 printf("\tSense Protect Fuse is set\n");
276         out_be32(&iim->err, in_be32(&iim->err));
278         return 0;
281 int do_ads5121_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
283         int frow, n, v, bank;
285         if (cur_bank == '0')
286                 bank = 0;
287         else
288                 bank = 1;
290         switch (argc) {
291         case 0:
292         case 1:
293                 printf("Usage:\n%s\n", cmdtp->usage);
294                 return 1;
295         case 2:
296                 if (strncmp(argv[1], "stat", 4) == 0)
297                         return ads5121_fuse_stat(bank);
298                 if (strncmp(argv[1], "read", 4) == 0)
299                         return ads5121_fuse_read(bank, 0, IIM_FMAX + 1);
300                 if (strncmp(argv[1], "sense", 5) == 0)
301                         return ads5121_fuse_sense(bank, 0, IIM_FMAX + 1);
302                 if (strncmp(argv[1], "ovride", 6) == 0)
303                         return ads5121_fuse_override(bank, IIM_FMAX + 1, 0);
304                 if (strncmp(argv[1], "bank", 4) == 0) {
305                         printf("Active Fuse Bank is %c\n", cur_bank);
306                         return 0;
307                 }
308                 printf("Usage:\n%s\n", cmdtp->usage);
309                 return 1;
310         case 3:
311                 if (strncmp(argv[1], "bank", 4) == 0) {
312                         if (argv[2][0] == '0')
313                                 cur_bank = '0';
314                         else if (argv[2][0] == '1')
315                                 cur_bank = '1';
316                         else {
317                                 printf("Usage:\n%s\n", cmdtp->usage);
318                                 return 1;
319                         }
321                         printf("Setting Active Fuse Bank to %c\n", cur_bank);
322                         return 0;
323                 }
324                 if (strncmp(argv[1], "prog", 4) == 0)
325                         return ads5121_fuse_prog(cmdtp, bank, argv[2]);
327                 frow = (int)simple_strtol(argv[2], NULL, 10);
328                 if (frow == 0 && argv[2][0] != '0')
329                         frow = -1;
330                 if (!in_range(frow, 0, IIM_FMAX,
331                         "<frow> must be between 0-31\n\n", cmdtp->usage))
332                         return 1;
333                 if (strncmp(argv[1], "read", 4) == 0)
334                         return ads5121_fuse_read(bank, frow, 1);
335                 if (strncmp(argv[1], "ovride", 6) == 0)
336                         return ads5121_fuse_override(bank, frow, 0);
337                 if (strncmp(argv[1], "sense", 5) == 0)
338                         return ads5121_fuse_sense(bank, frow, 1);
339                 printf("Usage:\n%s\n", cmdtp->usage);
340                 return 1;
341         case 4:
342                 frow = (int)simple_strtol(argv[2], NULL, 10);
343                 if (frow == 0 && argv[2][0] != '0')
344                         frow = -1;
345                 if (!in_range(frow, 0, IIM_FMAX,
346                         "<frow> must be between 0-31\n\n", cmdtp->usage))
347                         return 1;
348                 if (strncmp(argv[1], "read", 4) == 0) {
349                         n = (int)simple_strtol(argv[3], NULL, 10);
350                         if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
351                                 "<frow>+<n> must be between 1-32\n\n",
352                                 cmdtp->usage))
353                                 return 1;
354                         return ads5121_fuse_read(bank, frow, n);
355                 }
356                 if (strncmp(argv[1], "ovride", 6) == 0) {
357                         v = (int)simple_strtol(argv[3], NULL, 10);
358                         return ads5121_fuse_override(bank, frow, v);
359                 }
360                 if (strncmp(argv[1], "sense", 5) == 0) {
361                         n = (int)simple_strtol(argv[3], NULL, 10);
362                         if (!in_range(frow + n, frow + 1, IIM_FMAX + 1,
363                                 "<frow>+<n> must be between 1-32\n\n",
364                                 cmdtp->usage))
365                                 return 1;
366                         return ads5121_fuse_sense(bank, frow, n);
367                 }
368                 printf("Usage:\n%s\n", cmdtp->usage);
369                 return 1;
370         default: /* at least 5 args */
371                 printf("Usage:\n%s\n", cmdtp->usage);
372                 return 1;
373         }
376 U_BOOT_CMD(
377         fuse, CONFIG_SYS_MAXARGS, 0, do_ads5121_fuse,
378         "   - Read, Sense, Override or Program Fuses\n",
379         "bank <n>               - sets active Fuse Bank to 0 or 1\n"
380         "                           no args shows current active bank\n"
381         "fuse stat              - print active fuse bank's protection status\n"
382         "fuse read [<frow> [<n>]] - print <n> fuse rows starting at <frow>\n"
383         "                           no args to print entire bank's fuses\n"
384         "fuse ovride [<frow> [<v>]]- override fuses at <frow> with <v>\n"
385         "                           no <v> defaults to 0 for the row\n"
386         "                           no args resets entire bank to 0\n"
387         "                         NOTE - settings persist until hard reset\n"
388         "fuse sense [<frow>]    - senses current fuse at <frow>\n"
389         "                           no args for entire bank\n"
390         "fuse prog <frow_bit>   - program fuse at row <frow>, bit <_bit>\n"
391         "                           <frow> is 0-31, <bit> is 0-7; eg. 13_2 \n"
392         "                         WARNING - this is permanent"
393 );
394 #endif /* CONFIG_CMD_FUSE */