]>
Commit | Line | Data |
---|---|---|
9acb626f HS |
1 | /* |
2 | * Basic Flash Driver for Freescale MCF 5281/5282 internal FLASH | |
3 | * | |
4 | * (C) Copyright 2005 BuS Elektronik GmbH & Co.KG <esw@bus-elektonik.de> | |
5 | * | |
6 | * See file CREDITS for list of people who contributed to this | |
7 | * project. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License as | |
11 | * published by the Free Software Foundation; either version 2 of | |
12 | * the License, or (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
22 | * MA 02111-1307 USA | |
23 | */ | |
24 | ||
b1d71358 | 25 | #include <common.h> |
9acb626f HS |
26 | #include <asm/m5282.h> |
27 | #include "cfm_flash.h" | |
28 | ||
29 | #if defined(CONFIG_M5281) || defined(CONFIG_M5282) | |
30 | ||
6d0f6bcf JCPV |
31 | #if (CONFIG_SYS_CLK>20000000) |
32 | #define CFM_CLK (((long) CONFIG_SYS_CLK / (400000 * 8) + 1) | 0x40) | |
9acb626f | 33 | #else |
6d0f6bcf | 34 | #define CFM_CLK ((long) CONFIG_SYS_CLK / 400000 + 1) |
9acb626f HS |
35 | #endif |
36 | ||
37 | #define cmf_backdoor_address(addr) (((addr) & 0x0007FFFF) | 0x04000000 | \ | |
6d0f6bcf | 38 | (CONFIG_SYS_MBAR & 0xC0000000)) |
9acb626f HS |
39 | |
40 | void cfm_flash_print_info (flash_info_t * info) | |
41 | { | |
42 | printf ("Freescale: "); | |
43 | switch (info->flash_id & FLASH_TYPEMASK) { | |
44 | case FREESCALE_ID_MCF5281 & FLASH_TYPEMASK: | |
45 | printf ("MCF5281 internal FLASH\n"); | |
46 | break; | |
47 | case FREESCALE_ID_MCF5282 & FLASH_TYPEMASK: | |
48 | printf ("MCF5282 internal FLASH\n"); | |
49 | break; | |
50 | default: | |
51 | printf ("Unknown Chip Type\n"); | |
52 | break; | |
53 | } | |
54 | } | |
55 | ||
56 | void cfm_flash_init (flash_info_t * info) | |
57 | { | |
58 | int sector; | |
59 | ulong protection; | |
60 | MCFCFM_MCR = 0; | |
61 | MCFCFM_CLKD = CFM_CLK; | |
62 | debug ("CFM Clock divider: %ld (%d Hz @ %ld Hz)\n",CFM_CLK,\ | |
6d0f6bcf JCPV |
63 | CONFIG_SYS_CLK / (2* ((CFM_CLK & 0x3F)+1) * (1+((CFM_CLK & 0x40)>>6)*7)),\ |
64 | CONFIG_SYS_CLK); | |
9acb626f HS |
65 | MCFCFM_SACC = 0; |
66 | MCFCFM_DACC = 0; | |
67 | ||
68 | if (MCFCFM_SEC & MCFCFM_SEC_KEYEN) | |
69 | puts("CFM backdoor access is enabled\n"); | |
70 | if (MCFCFM_SEC & MCFCFM_SEC_SECSTAT) | |
71 | puts("CFM securety is enabled\n"); | |
72 | ||
73 | #ifdef CONFIG_M5281 | |
74 | info->flash_id = (FREESCALE_MANUFACT & FLASH_VENDMASK) | | |
75 | (FREESCALE_ID_MCF5281 & FLASH_TYPEMASK); | |
76 | info->size = 256*1024; | |
77 | info->sector_count = 16; | |
78 | #else | |
79 | info->flash_id = (FREESCALE_MANUFACT & FLASH_VENDMASK) | | |
80 | (FREESCALE_ID_MCF5282 & FLASH_TYPEMASK); | |
81 | info->size = 512*1024; | |
82 | info->sector_count = 32; | |
83 | #endif | |
84 | protection = MCFCFM_PROT; | |
85 | for (sector = 0; sector < info->sector_count; sector++) | |
86 | { | |
87 | if (sector == 0) | |
88 | { | |
6d0f6bcf | 89 | info->start[sector] = CONFIG_SYS_INT_FLASH_BASE; |
9acb626f HS |
90 | } |
91 | else | |
92 | { | |
93 | info->start[sector] = info->start[sector-1] + 0x04000; | |
94 | } | |
95 | info->protect[sector] = protection & 1; | |
96 | protection >>= 1; | |
97 | } | |
98 | } | |
99 | ||
100 | int cfm_flash_readycheck(int checkblank) | |
101 | { | |
102 | int rc; | |
103 | unsigned char state; | |
104 | ||
105 | rc = ERR_OK; | |
106 | while (!(MCFCFM_USTAT & MCFCFM_USTAT_CCIF)); | |
107 | state = MCFCFM_USTAT; | |
108 | if (state & MCFCFM_USTAT_ACCERR) | |
109 | { | |
110 | debug ("%s(): CFM access error",__FUNCTION__); | |
111 | rc = ERR_PROG_ERROR; | |
112 | } | |
113 | if (state & MCFCFM_USTAT_PVIOL) | |
114 | { | |
115 | debug ("%s(): CFM protection violation",__FUNCTION__); | |
116 | rc = ERR_PROTECTED; | |
117 | } | |
118 | if (checkblank) | |
119 | { | |
120 | if (!(state & MCFCFM_USTAT_BLANK)) | |
121 | { | |
122 | debug ("%s(): CFM erras error",__FUNCTION__); | |
123 | rc = ERR_NOT_ERASED; | |
124 | } | |
125 | } | |
126 | MCFCFM_USTAT = state & 0x34; /* reset state */ | |
127 | return rc; | |
128 | } | |
129 | ||
130 | /* Erase 16KiB = 8 2KiB pages */ | |
131 | ||
132 | int cfm_flash_erase_sector (flash_info_t * info, int sector) | |
133 | { | |
134 | ulong address; | |
135 | int page; | |
136 | int rc; | |
137 | rc= ERR_OK; | |
138 | address = cmf_backdoor_address(info->start[sector]); | |
139 | for (page=0; (page<8) && (rc==ERR_OK); page++) | |
140 | { | |
141 | *(volatile __u32*) address = 0; | |
142 | MCFCFM_CMD = MCFCFM_CMD_PGERS; | |
143 | MCFCFM_USTAT = MCFCFM_USTAT_CBEIF; | |
144 | rc = cfm_flash_readycheck(0); | |
145 | if (rc==ERR_OK) | |
146 | { | |
147 | *(volatile __u32*) address = 0; | |
148 | MCFCFM_CMD = MCFCFM_CMD_PGERSVER; | |
149 | MCFCFM_USTAT = MCFCFM_USTAT_CBEIF; | |
150 | rc = cfm_flash_readycheck(1); | |
151 | } | |
152 | address += 0x800; | |
153 | } | |
154 | return rc; | |
155 | } | |
156 | ||
157 | int cfm_flash_write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) | |
158 | { | |
159 | int rc; | |
160 | ulong dest, data; | |
161 | ||
162 | rc = ERR_OK; | |
163 | if (addr & 3) | |
164 | { | |
165 | debug ("Byte and Word alignment not supported\n"); | |
166 | rc = ERR_ALIGN; | |
167 | } | |
168 | if (cnt & 3) | |
169 | { | |
170 | debug ("Byte and Word transfer not supported\n"); | |
171 | rc = ERR_ALIGN; | |
172 | } | |
173 | dest = cmf_backdoor_address(addr); | |
174 | while ((cnt>=4) && (rc == ERR_OK)) | |
175 | { | |
d0ff51ba | 176 | data = *((volatile u32 *) src); |
9acb626f HS |
177 | *(volatile u32*) dest = data; |
178 | MCFCFM_CMD = MCFCFM_CMD_PGM; | |
179 | MCFCFM_USTAT = MCFCFM_USTAT_CBEIF; | |
180 | rc = cfm_flash_readycheck(0); | |
181 | if (*(volatile u32*) addr != data) rc = ERR_PROG_ERROR; | |
182 | src +=4; | |
183 | dest +=4; | |
184 | addr +=4; | |
185 | cnt -=4; | |
186 | } | |
187 | return rc; | |
188 | } | |
189 | ||
6d0f6bcf | 190 | #ifdef CONFIG_SYS_FLASH_PROTECTION |
9acb626f HS |
191 | |
192 | int cfm_flash_protect(flash_info_t * info,long sector,int prot) | |
193 | { | |
194 | int rc; | |
195 | ||
196 | rc= ERR_OK; | |
197 | if (prot) | |
198 | { | |
199 | MCFCFM_PROT |= (1<<sector); | |
200 | info->protect[sector]=1; | |
201 | } | |
202 | else | |
203 | { | |
204 | MCFCFM_PROT &= ~(1<<sector); | |
205 | info->protect[sector]=0; | |
206 | } | |
207 | return rc; | |
208 | } | |
209 | ||
210 | #endif | |
211 | ||
212 | #endif |