blob: cc0f4254a4fd2eb666990e5066e1e8410ec3a1cf [file] [log] [blame]
Stefan Roese3e1f1b32005-08-01 16:49:12 +02001/*
2 * (C) Copyright 2000-2005
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
Stefan Roese3e1f1b32005-08-01 16:49:12 +02006 */
7
8/*
9 * Modified 4/5/2001
10 * Wait for completion of each sector erase command issued
11 * 4/5/2001
12 * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
13 */
14
15#include <common.h>
Stefan Roese247e9d72010-09-09 19:18:00 +020016#include <asm/ppc4xx.h>
Stefan Roese3e1f1b32005-08-01 16:49:12 +020017#include <asm/processor.h>
18
19#undef DEBUG
20#ifdef DEBUG
21#define DEBUGF(x...) printf(x)
22#else
23#define DEBUGF(x...)
24#endif /* DEBUG */
25
26/*
27 * include common flash code (for amcc boards)
28 */
29#include "../common/flash.c"
30
31/*-----------------------------------------------------------------------
32 * Functions
33 */
34static ulong flash_get_size(vu_long * addr, flash_info_t * info);
35static void flash_get_offsets(ulong base, flash_info_t * info);
36
37unsigned long flash_init(void)
38{
39 unsigned long size_b0, size_b1;
40 int i;
41 uint pbcr;
42 unsigned long base_b0, base_b1;
43
44 /* Init: no FLASHes known */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020045 for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
Stefan Roese3e1f1b32005-08-01 16:49:12 +020046 flash_info[i].flash_id = FLASH_UNKNOWN;
47 }
48
49 /* Static FLASH Bank configuration here - FIXME XXX */
50
51 size_b0 =
52 flash_get_size((vu_long *) FLASH_BASE0_PRELIM, &flash_info[0]);
53
54 if (flash_info[0].flash_id == FLASH_UNKNOWN) {
55 printf("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
56 size_b0, size_b0 << 20);
57 }
58
59 /* Only one bank */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020060 if (CONFIG_SYS_MAX_FLASH_BANKS == 1) {
Stefan Roese3e1f1b32005-08-01 16:49:12 +020061 /* Setup offsets */
62 flash_get_offsets(FLASH_BASE0_PRELIM, &flash_info[0]);
63
64 /* Monitor protection ON by default */
65 (void)flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020066 CONFIG_SYS_MONITOR_BASE,
67 CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1,
Stefan Roese3e1f1b32005-08-01 16:49:12 +020068 &flash_info[0]);
Jean-Christophe PLAGNIOL-VILLARD53db4cd2008-09-10 22:48:04 +020069#ifdef CONFIG_ENV_IS_IN_FLASH
Jean-Christophe PLAGNIOL-VILLARD7e1cda62008-09-10 22:48:06 +020070 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR,
71 CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1,
Stefan Roese3e1f1b32005-08-01 16:49:12 +020072 &flash_info[0]);
Jean-Christophe PLAGNIOL-VILLARD7e1cda62008-09-10 22:48:06 +020073 (void)flash_protect(FLAG_PROTECT_SET, CONFIG_ENV_ADDR_REDUND,
74 CONFIG_ENV_ADDR_REDUND + CONFIG_ENV_SECT_SIZE - 1,
Stefan Roese3e1f1b32005-08-01 16:49:12 +020075 &flash_info[0]);
76#endif
77
78 size_b1 = 0;
79 flash_info[0].size = size_b0;
80 } else {
81 /* 2 banks */
82 size_b1 =
83 flash_get_size((vu_long *) FLASH_BASE1_PRELIM,
84 &flash_info[1]);
85
86 /* Re-do sizing to get full correct info */
87
88 if (size_b1) {
Stefan Roese918010a2009-09-09 16:25:29 +020089 mtdcr(EBC0_CFGADDR, PB0CR);
90 pbcr = mfdcr(EBC0_CFGDATA);
91 mtdcr(EBC0_CFGADDR, PB0CR);
Stefan Roese3e1f1b32005-08-01 16:49:12 +020092 base_b1 = -size_b1;
93 pbcr =
94 (pbcr & 0x0001ffff) | base_b1 |
95 (((size_b1 / 1024 / 1024) - 1) << 17);
Stefan Roese918010a2009-09-09 16:25:29 +020096 mtdcr(EBC0_CFGDATA, pbcr);
97 /* printf("PB1CR = %x\n", pbcr); */
Stefan Roese3e1f1b32005-08-01 16:49:12 +020098 }
99
100 if (size_b0) {
Stefan Roese918010a2009-09-09 16:25:29 +0200101 mtdcr(EBC0_CFGADDR, PB1CR);
102 pbcr = mfdcr(EBC0_CFGDATA);
103 mtdcr(EBC0_CFGADDR, PB1CR);
Stefan Roese3e1f1b32005-08-01 16:49:12 +0200104 base_b0 = base_b1 - size_b0;
105 pbcr =
106 (pbcr & 0x0001ffff) | base_b0 |
107 (((size_b0 / 1024 / 1024) - 1) << 17);
Stefan Roese918010a2009-09-09 16:25:29 +0200108 mtdcr(EBC0_CFGDATA, pbcr);
109 /* printf("PB0CR = %x\n", pbcr); */
Stefan Roese3e1f1b32005-08-01 16:49:12 +0200110 }
111
112 size_b0 = flash_get_size((vu_long *) base_b0, &flash_info[0]);
113
114 flash_get_offsets(base_b0, &flash_info[0]);
115
116 /* monitor protection ON by default */
117 (void)flash_protect(FLAG_PROTECT_SET,
118 base_b0 + size_b0 - monitor_flash_len,
119 base_b0 + size_b0 - 1, &flash_info[0]);
120
121 if (size_b1) {
122 /* Re-do sizing to get full correct info */
123 size_b1 =
124 flash_get_size((vu_long *) base_b1, &flash_info[1]);
125
126 flash_get_offsets(base_b1, &flash_info[1]);
127
128 /* monitor protection ON by default */
129 (void)flash_protect(FLAG_PROTECT_SET,
130 base_b1 + size_b1 -
131 monitor_flash_len,
132 base_b1 + size_b1 - 1,
133 &flash_info[1]);
134 /* monitor protection OFF by default (one is enough) */
135 (void)flash_protect(FLAG_PROTECT_CLEAR,
136 base_b0 + size_b0 -
137 monitor_flash_len,
138 base_b0 + size_b0 - 1,
139 &flash_info[0]);
140 } else {
141 flash_info[1].flash_id = FLASH_UNKNOWN;
142 flash_info[1].sector_count = -1;
143 }
144
145 flash_info[0].size = size_b0;
146 flash_info[1].size = size_b1;
147 } /* else 2 banks */
148 return (size_b0 + size_b1);
149}
150
151
152static void flash_get_offsets(ulong base, flash_info_t * info)
153{
154 int i;
155
156 /* set up sector start address table */
157 if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
158 (info->flash_id == FLASH_AM040)) {
159 for (i = 0; i < info->sector_count; i++)
160 info->start[i] = base + (i * 0x00010000);
161 } else {
162 if (info->flash_id & FLASH_BTYPE) {
163 /* set sector offsets for bottom boot block type */
164 info->start[0] = base + 0x00000000;
165 info->start[1] = base + 0x00004000;
166 info->start[2] = base + 0x00006000;
167 info->start[3] = base + 0x00008000;
168 for (i = 4; i < info->sector_count; i++) {
169 info->start[i] =
170 base + (i * 0x00010000) - 0x00030000;
171 }
172 } else {
173 /* set sector offsets for top boot block type */
174 i = info->sector_count - 1;
175 info->start[i--] = base + info->size - 0x00004000;
176 info->start[i--] = base + info->size - 0x00006000;
177 info->start[i--] = base + info->size - 0x00008000;
178 for (; i >= 0; i--) {
179 info->start[i] = base + i * 0x00010000;
180 }
181 }
182 }
183}