1affae2bfSwdenk /* 2affae2bfSwdenk * (C) Copyright 2000 3affae2bfSwdenk * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4affae2bfSwdenk * 5affae2bfSwdenk * See file CREDITS for list of people who contributed to this 6affae2bfSwdenk * project. 7affae2bfSwdenk * 8affae2bfSwdenk * This program is free software; you can redistribute it and/or 9affae2bfSwdenk * modify it under the terms of the GNU General Public License as 10affae2bfSwdenk * published by the Free Software Foundation; either version 2 of 11affae2bfSwdenk * the License, or (at your option) any later version. 12affae2bfSwdenk * 13affae2bfSwdenk * This program is distributed in the hope that it will be useful, 14affae2bfSwdenk * but WITHOUT ANY WARRANTY; without even the implied warranty of 15affae2bfSwdenk * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16affae2bfSwdenk * GNU General Public License for more details. 17affae2bfSwdenk * 18affae2bfSwdenk * You should have received a copy of the GNU General Public License 19affae2bfSwdenk * along with this program; if not, write to the Free Software 20affae2bfSwdenk * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21affae2bfSwdenk * MA 02111-1307 USA 22affae2bfSwdenk */ 23affae2bfSwdenk 247e780369Swdenk /* #define DEBUG */ 257e780369Swdenk 26affae2bfSwdenk #include <common.h> 27affae2bfSwdenk #include <flash.h> 28affae2bfSwdenk 29affae2bfSwdenk #if !defined(CFG_NO_FLASH) 30affae2bfSwdenk 31e6f2e902SMarian Balakowicz extern flash_info_t flash_info[]; /* info for FLASH chips */ 32affae2bfSwdenk 33affae2bfSwdenk /*----------------------------------------------------------------------- 34affae2bfSwdenk * Functions 35affae2bfSwdenk */ 36affae2bfSwdenk 37affae2bfSwdenk /*----------------------------------------------------------------------- 38affae2bfSwdenk * Set protection status for monitor sectors 39affae2bfSwdenk * 40affae2bfSwdenk * The monitor is always located in the _first_ Flash bank. 41affae2bfSwdenk * If necessary you have to map the second bank at lower addresses. 42affae2bfSwdenk */ 43affae2bfSwdenk void 44affae2bfSwdenk flash_protect (int flag, ulong from, ulong to, flash_info_t *info) 45affae2bfSwdenk { 46affae2bfSwdenk ulong b_end = info->start[0] + info->size - 1; /* bank end address */ 47affae2bfSwdenk short s_end = info->sector_count - 1; /* index of last sector */ 48affae2bfSwdenk int i; 49affae2bfSwdenk 50affae2bfSwdenk /* Do nothing if input data is bad. */ 51affae2bfSwdenk if (info->sector_count == 0 || info->size == 0 || to < from) { 52affae2bfSwdenk return; 53affae2bfSwdenk } 54affae2bfSwdenk 55*d2f68006SEugene OBrien debug ("flash_protect %s: from 0x%08lX to 0x%08lX\n", 56*d2f68006SEugene OBrien (flag & FLAG_PROTECT_SET) ? "ON" : 57*d2f68006SEugene OBrien (flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???", 58*d2f68006SEugene OBrien from, to); 59*d2f68006SEugene OBrien 60affae2bfSwdenk /* There is nothing to do if we have no data about the flash 61affae2bfSwdenk * or the protect range and flash range don't overlap. 62affae2bfSwdenk */ 63affae2bfSwdenk if (info->flash_id == FLASH_UNKNOWN || 64affae2bfSwdenk to < info->start[0] || from > b_end) { 65affae2bfSwdenk return; 66affae2bfSwdenk } 67affae2bfSwdenk 68affae2bfSwdenk for (i=0; i<info->sector_count; ++i) { 69affae2bfSwdenk ulong end; /* last address in current sect */ 70affae2bfSwdenk 71affae2bfSwdenk end = (i == s_end) ? b_end : info->start[i + 1] - 1; 72affae2bfSwdenk 73affae2bfSwdenk /* Update protection if any part of the sector 74affae2bfSwdenk * is in the specified range. 75affae2bfSwdenk */ 76affae2bfSwdenk if (from <= end && to >= info->start[i]) { 77affae2bfSwdenk if (flag & FLAG_PROTECT_CLEAR) { 78affae2bfSwdenk #if defined(CFG_FLASH_PROTECTION) 79affae2bfSwdenk flash_real_protect(info, i, 0); 80affae2bfSwdenk #else 81affae2bfSwdenk info->protect[i] = 0; 82affae2bfSwdenk #endif /* CFG_FLASH_PROTECTION */ 837e780369Swdenk debug ("protect off %d\n", i); 84affae2bfSwdenk } 85affae2bfSwdenk else if (flag & FLAG_PROTECT_SET) { 86affae2bfSwdenk #if defined(CFG_FLASH_PROTECTION) 87affae2bfSwdenk flash_real_protect(info, i, 1); 88affae2bfSwdenk #else 89affae2bfSwdenk info->protect[i] = 1; 90affae2bfSwdenk #endif /* CFG_FLASH_PROTECTION */ 917e780369Swdenk debug ("protect on %d\n", i); 92affae2bfSwdenk } 93affae2bfSwdenk } 94affae2bfSwdenk } 95affae2bfSwdenk } 96affae2bfSwdenk 97affae2bfSwdenk /*----------------------------------------------------------------------- 98affae2bfSwdenk */ 99affae2bfSwdenk 100affae2bfSwdenk flash_info_t * 101affae2bfSwdenk addr2info (ulong addr) 102affae2bfSwdenk { 103affae2bfSwdenk #ifndef CONFIG_SPD823TS 104affae2bfSwdenk flash_info_t *info; 105affae2bfSwdenk int i; 106affae2bfSwdenk 107affae2bfSwdenk for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) { 108affae2bfSwdenk if (info->flash_id != FLASH_UNKNOWN && 109affae2bfSwdenk addr >= info->start[0] && 110affae2bfSwdenk /* WARNING - The '- 1' is needed if the flash 111affae2bfSwdenk * is at the end of the address space, since 112affae2bfSwdenk * info->start[0] + info->size wraps back to 0. 113affae2bfSwdenk * Please don't change this unless you understand this. 114affae2bfSwdenk */ 115affae2bfSwdenk addr <= info->start[0] + info->size - 1) { 116affae2bfSwdenk return (info); 117affae2bfSwdenk } 118affae2bfSwdenk } 119affae2bfSwdenk #endif /* CONFIG_SPD823TS */ 120affae2bfSwdenk 121affae2bfSwdenk return (NULL); 122affae2bfSwdenk } 123affae2bfSwdenk 124affae2bfSwdenk /*----------------------------------------------------------------------- 125affae2bfSwdenk * Copy memory to flash. 126affae2bfSwdenk * Make sure all target addresses are within Flash bounds, 127affae2bfSwdenk * and no protected sectors are hit. 128affae2bfSwdenk * Returns: 129affae2bfSwdenk * ERR_OK 0 - OK 130affae2bfSwdenk * ERR_TIMOUT 1 - write timeout 131affae2bfSwdenk * ERR_NOT_ERASED 2 - Flash not erased 132affae2bfSwdenk * ERR_PROTECTED 4 - target range includes protected sectors 133affae2bfSwdenk * ERR_INVAL 8 - target address not in Flash memory 134affae2bfSwdenk * ERR_ALIGN 16 - target address not aligned on boundary 135affae2bfSwdenk * (only some targets require alignment) 136affae2bfSwdenk */ 137affae2bfSwdenk int 13877ddac94SWolfgang Denk flash_write (char *src, ulong addr, ulong cnt) 139affae2bfSwdenk { 140affae2bfSwdenk #ifdef CONFIG_SPD823TS 141affae2bfSwdenk return (ERR_TIMOUT); /* any other error codes are possible as well */ 142affae2bfSwdenk #else 143affae2bfSwdenk int i; 144affae2bfSwdenk ulong end = addr + cnt - 1; 145affae2bfSwdenk flash_info_t *info_first = addr2info (addr); 146affae2bfSwdenk flash_info_t *info_last = addr2info (end ); 147affae2bfSwdenk flash_info_t *info; 148affae2bfSwdenk 149affae2bfSwdenk if (cnt == 0) { 150affae2bfSwdenk return (ERR_OK); 151affae2bfSwdenk } 152affae2bfSwdenk 153affae2bfSwdenk if (!info_first || !info_last) { 154affae2bfSwdenk return (ERR_INVAL); 155affae2bfSwdenk } 156affae2bfSwdenk 157affae2bfSwdenk for (info = info_first; info <= info_last; ++info) { 158affae2bfSwdenk ulong b_end = info->start[0] + info->size; /* bank end addr */ 159affae2bfSwdenk short s_end = info->sector_count - 1; 160affae2bfSwdenk for (i=0; i<info->sector_count; ++i) { 161affae2bfSwdenk ulong e_addr = (i == s_end) ? b_end : info->start[i + 1]; 162affae2bfSwdenk 163affae2bfSwdenk if ((end >= info->start[i]) && (addr < e_addr) && 164affae2bfSwdenk (info->protect[i] != 0) ) { 165affae2bfSwdenk return (ERR_PROTECTED); 166affae2bfSwdenk } 167affae2bfSwdenk } 168affae2bfSwdenk } 169affae2bfSwdenk 170affae2bfSwdenk /* finally write data to flash */ 171affae2bfSwdenk for (info = info_first; info <= info_last && cnt>0; ++info) { 172affae2bfSwdenk ulong len; 173affae2bfSwdenk 174affae2bfSwdenk len = info->start[0] + info->size - addr; 175affae2bfSwdenk if (len > cnt) 176affae2bfSwdenk len = cnt; 17777ddac94SWolfgang Denk if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) { 178affae2bfSwdenk return (i); 179affae2bfSwdenk } 180affae2bfSwdenk cnt -= len; 181affae2bfSwdenk addr += len; 182affae2bfSwdenk src += len; 183affae2bfSwdenk } 184affae2bfSwdenk return (ERR_OK); 185affae2bfSwdenk #endif /* CONFIG_SPD823TS */ 186affae2bfSwdenk } 187affae2bfSwdenk 188affae2bfSwdenk /*----------------------------------------------------------------------- 189affae2bfSwdenk */ 190affae2bfSwdenk 191affae2bfSwdenk void flash_perror (int err) 192affae2bfSwdenk { 193affae2bfSwdenk switch (err) { 194affae2bfSwdenk case ERR_OK: 195affae2bfSwdenk break; 196affae2bfSwdenk case ERR_TIMOUT: 197affae2bfSwdenk puts ("Timeout writing to Flash\n"); 198affae2bfSwdenk break; 199affae2bfSwdenk case ERR_NOT_ERASED: 200affae2bfSwdenk puts ("Flash not Erased\n"); 201affae2bfSwdenk break; 202affae2bfSwdenk case ERR_PROTECTED: 203affae2bfSwdenk puts ("Can't write to protected Flash sectors\n"); 204affae2bfSwdenk break; 205affae2bfSwdenk case ERR_INVAL: 206affae2bfSwdenk puts ("Outside available Flash\n"); 207affae2bfSwdenk break; 208affae2bfSwdenk case ERR_ALIGN: 209affae2bfSwdenk puts ("Start and/or end address not on sector boundary\n"); 210affae2bfSwdenk break; 211affae2bfSwdenk case ERR_UNKNOWN_FLASH_VENDOR: 212affae2bfSwdenk puts ("Unknown Vendor of Flash\n"); 213affae2bfSwdenk break; 214affae2bfSwdenk case ERR_UNKNOWN_FLASH_TYPE: 215affae2bfSwdenk puts ("Unknown Type of Flash\n"); 216affae2bfSwdenk break; 217affae2bfSwdenk case ERR_PROG_ERROR: 218affae2bfSwdenk puts ("General Flash Programming Error\n"); 219affae2bfSwdenk break; 220affae2bfSwdenk default: 221affae2bfSwdenk printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err); 222affae2bfSwdenk break; 223affae2bfSwdenk } 224affae2bfSwdenk } 225affae2bfSwdenk 226affae2bfSwdenk /*----------------------------------------------------------------------- 227affae2bfSwdenk */ 228affae2bfSwdenk #endif /* !CFG_NO_FLASH */ 229