]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/amcc/bubinga/flash.c
imported Freescale specific U-Boot additions for i.MX28,... release L2.6.31_10.08.01
[karo-tx-uboot.git] / board / amcc / bubinga / flash.c
1 /*
2  * (C) Copyright 2000
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 /*
25  * Modified 4/5/2001
26  * Wait for completion of each sector erase command issued
27  * 4/5/2001
28  * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
29  */
30
31 #include <common.h>
32 #include <ppc4xx.h>
33 #include <asm/processor.h>
34
35 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];    /* info for FLASH chips        */
36
37 #undef DEBUG
38 #ifdef DEBUG
39 #define DEBUGF(x...) printf(x)
40 #else
41 #define DEBUGF(x...)
42 #endif                          /* DEBUG */
43
44 /*
45  * include common flash code (for amcc boards)
46  */
47 #include "../common/flash.c"
48
49 /*-----------------------------------------------------------------------
50  * Functions
51  */
52 static ulong flash_get_size(vu_long * addr, flash_info_t * info);
53 static void flash_get_offsets(ulong base, flash_info_t * info);
54
55 unsigned long flash_init(void)
56 {
57         unsigned long size_b0, size_b1;
58         int i;
59         uint pbcr;
60         unsigned long base_b0, base_b1;
61
62         /* Init: no FLASHes known */
63         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
64                 flash_info[i].flash_id = FLASH_UNKNOWN;
65         }
66
67         /* Static FLASH Bank configuration here - FIXME XXX */
68
69         size_b0 =
70             flash_get_size((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);
71
72         if (flash_info[0].flash_id == FLASH_UNKNOWN) {
73                 printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
74                        size_b0, size_b0 << 20);
75         }
76
77         /* Only one bank */
78         if (CONFIG_SYS_MAX_FLASH_BANKS == 1) {
79                 /* Setup offsets */
80                 flash_get_offsets(FLASH_BASE0_PRELIM, &flash_info[0]);
81
82                 /* Monitor protection ON by default */
83                 (void)flash_protect(FLAG_PROTECT_SET,
84                                     CONFIG_SYS_MONITOR_BASE,
85                                     CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
86                                     &flash_info[0]);
87 #ifdef CONFIG_ENV_IS_IN_FLASH
88                 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
89                                     CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
90                                     &flash_info[0]);
91                 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
92                                     CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
93                                     &flash_info[0]);
94 #endif
95
96                 size_b1 = 0;
97                 flash_info[0].size = size_b0;
98         }
99
100         /* 2 banks */
101         else {
102                 size_b1 =
103                     flash_get_size((vu_long *) FLASH_BASE1_PRELIM,
104                                    &flash_info[1]);
105
106                 /* Re-do sizing to get full correct info */
107
108                 if (size_b1) {
109                         mtdcr(ebccfga, pb0cr);
110                         pbcr = mfdcr(ebccfgd);
111                         mtdcr(ebccfga, pb0cr);
112                         base_b1 = -size_b1;
113                         pbcr = (pbcr & 0x0001ffff) | base_b1 |
114                             (((size_b1 / 1024 / 1024) - 1) << 17);
115                         mtdcr(ebccfgd, pbcr);
116                         /*          printf("pb1cr = %x\n", pbcr); */
117                 }
118
119                 if (size_b0) {
120                         mtdcr(ebccfga, pb1cr);
121                         pbcr = mfdcr(ebccfgd);
122                         mtdcr(ebccfga, pb1cr);
123                         base_b0 = base_b1 - size_b0;
124                         pbcr = (pbcr & 0x0001ffff) | base_b0 |
125                             (((size_b0 / 1024 / 1024) - 1) << 17);
126                         mtdcr(ebccfgd, pbcr);
127                         /*            printf("pb0cr = %x\n", pbcr); */
128                 }
129
130                 size_b0 = flash_get_size((vu_long *) base_b0, &flash_info[0]);
131
132                 flash_get_offsets(base_b0, &flash_info[0]);
133
134                 /* monitor protection ON by default */
135                 (void)flash_protect(FLAG_PROTECT_SET,
136                                     base_b0 + size_b0 - CONFIG_SYS_MONITOR_LEN,
137                                     base_b0 + size_b0 - 1, &flash_info[0]);
138                 /* Also protect sector containing initial power-up instruction */
139                 /* (flash_protect() checks address range - other call ignored) */
140                 (void)flash_protect(FLAG_PROTECT_SET,
141                                     0xFFFFFFFC, 0xFFFFFFFF, &flash_info[0]);
142                 (void)flash_protect(FLAG_PROTECT_SET,
143                                     0xFFFFFFFC, 0xFFFFFFFF, &flash_info[1]);
144
145                 if (size_b1) {
146                         /* Re-do sizing to get full correct info */
147                         size_b1 =
148                             flash_get_size((vu_long *) base_b1, &flash_info[1]);
149
150                         flash_get_offsets(base_b1, &flash_info[1]);
151
152                         /* monitor protection ON by default */
153                         (void)flash_protect(FLAG_PROTECT_SET,
154                                             base_b1 + size_b1 - CONFIG_SYS_MONITOR_LEN,
155                                             base_b1 + size_b1 - 1,
156                                             &flash_info[1]);
157                         /* monitor protection OFF by default (one is enough) */
158                         (void)flash_protect(FLAG_PROTECT_CLEAR,
159                                             base_b0 + size_b0 - CONFIG_SYS_MONITOR_LEN,
160                                             base_b0 + size_b0 - 1,
161                                             &flash_info[0]);
162                 } else {
163                         flash_info[1].flash_id = FLASH_UNKNOWN;
164                         flash_info[1].sector_count = -1;
165                 }
166
167                 flash_info[0].size = size_b0;
168                 flash_info[1].size = size_b1;
169         }                       /* else 2 banks */
170         return (size_b0 + size_b1);
171 }
172
173 static void flash_get_offsets(ulong base, flash_info_t * info)
174 {
175         int i;
176
177         /* set up sector start address table */
178         if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
179             (info->flash_id == FLASH_AM040)) {
180                 for (i = 0; i < info->sector_count; i++)
181                         info->start[i] = base + (i * 0x00010000);
182         } else {
183                 if (info->flash_id & FLASH_BTYPE) {
184                         /* set sector offsets for bottom boot block type        */
185                         info->start[0] = base + 0x00000000;
186                         info->start[1] = base + 0x00004000;
187                         info->start[2] = base + 0x00006000;
188                         info->start[3] = base + 0x00008000;
189                         for (i = 4; i < info->sector_count; i++) {
190                                 info->start[i] =
191                                     base + (i * 0x00010000) - 0x00030000;
192                         }
193                 } else {
194                         /* set sector offsets for top boot block type           */
195                         i = info->sector_count - 1;
196                         info->start[i--] = base + info->size - 0x00004000;
197                         info->start[i--] = base + info->size - 0x00006000;
198                         info->start[i--] = base + info->size - 0x00008000;
199                         for (; i >= 0; i--) {
200                                 info->start[i] = base + i * 0x00010000;
201                         }
202                 }
203         }
204 }