1 /* $NetBSD: i28f128.c,v 1.2 2003/06/15 08:50:05 igy Exp $ */ 2 3 /* 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Naoto Shimazaki of YOKOGAWA Electric Corporation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Flash Memory Writer 41 */ 42 43 #include <lib/libsa/stand.h> 44 45 #include "extern.h" 46 47 #include "i28f128reg.h" 48 49 #define USE_TWIDDLE 50 51 /* 52 * XXX 53 * this function is too much specific for the device. 54 */ 55 int 56 i28f128_probe(void *base) 57 { 58 static const u_int8_t vendor_code[] = { 59 0x89, /* manufacturer code: intel */ 60 0x18, /* device code: 28F128 */ 61 }; 62 63 static const u_int8_t idstr[] = { 64 'Q', 'R', 'Y', 65 0x01, 0x00, 66 0x31, 0x00, 67 0xff 68 }; 69 70 int i; 71 72 /* start Common Flash Interface Query */ 73 REGWRITE_2(base, 0, 0x98); 74 75 /* read CFI Query ID string */ 76 for (i = 0; idstr[i] != 0xff; i++) { 77 if (REGREAD_2(base, (0x10 + i) << 1) != idstr[i]) 78 return 1; 79 } 80 81 /* read manufacturer code and device code */ 82 if (REGREAD_2(base, 0x00) != vendor_code[0]) 83 return 1; 84 if (REGREAD_2(base, 0x02) != vendor_code[1]) 85 return 1; 86 87 REGWRITE_2(base, 0, 0xff); 88 return 0; 89 } 90 91 static int 92 block_erase(void *addr) 93 { 94 int status; 95 96 REGWRITE_2(addr, 0, I28F128_BLK_ERASE_1ST); 97 REGWRITE_2(addr, 0, I28F128_BLK_ERASE_2ND); 98 99 do { 100 status = REGREAD_2(addr, 0); 101 } while (!ISSET(status, I28F128_S_READY)); 102 103 REGWRITE_2(addr, 0, I28F128_CLEAR_STATUS); 104 REGWRITE_2(addr, 0, I28F128_RESET); 105 106 return status & (I28F128_S_ERASE_SUSPEND 107 | I28F128_S_ERASE_ERROR 108 | I28F128_S_BLOCK_LOCKED); 109 } 110 111 static int 112 word_program(void *addr, u_int16_t data) 113 { 114 int status; 115 116 REGWRITE_2(addr, 0, I28F128_WORDBYTE_PROG); 117 REGWRITE_2(addr, 0, data); 118 119 do { 120 status = REGREAD_2(addr, 0); 121 } while (!ISSET(status, I28F128_S_READY)); 122 123 REGWRITE_2(addr, 0, I28F128_CLEAR_STATUS); 124 REGWRITE_2(addr, 0, I28F128_RESET); 125 126 return status & (I28F128_S_PROG_ERROR 127 | I28F128_S_LOW_VOLTAGE 128 | I28F128_S_PROG_SUSPEND 129 | I28F128_S_BLOCK_LOCKED); 130 } 131 132 static int 133 block_write(void *dst, const void *src) 134 { 135 int status; 136 const u_int16_t *p; 137 u_int16_t *q; 138 const u_int16_t *fence; 139 int i; 140 const int wbuf_count = I28F128_WBUF_SIZE >> 1; 141 142 /* dst must be aligned to block boundary. */ 143 if (I28F128_BLOCK_MASK & (u_int32_t) dst) 144 return -1; 145 146 if (memcmp(dst, src, I28F128_BLOCK_SIZE) == 0) 147 return 0; 148 149 if ((status = block_erase(dst)) != 0) 150 return status; 151 152 p = src; 153 q = dst; 154 fence = p + (I28F128_BLOCK_SIZE >> 1); 155 do { 156 do { 157 REGWRITE_2(dst, 0, I28F128_WRITE_BUFFER); 158 status = REGREAD_2(dst, 0); 159 } while (!ISSET(status, I28F128_XS_BUF_AVAIL)); 160 161 REGWRITE_2(dst, 0, wbuf_count - 1); 162 163 for (i = wbuf_count; i > 0; i--, p++, q++) 164 REGWRITE_2(q, 0, *p); 165 166 REGWRITE_2(dst, 0, I28F128_WBUF_CONFIRM); 167 168 do { 169 REGWRITE_2(dst, 0, I28F128_READ_STATUS); 170 status = REGREAD_2(dst, 0); 171 } while (!(status & I28F128_S_READY)); 172 173 } while (p < fence); 174 175 REGWRITE_2(dst, 0, I28F128_CLEAR_STATUS); 176 REGWRITE_2(dst, 0, I28F128_RESET); 177 178 return 0; 179 } 180 181 int 182 i28f128_region_write(void *dst, const void *src, size_t len) 183 { 184 int status; 185 const u_int16_t *p = src; 186 u_int16_t *q = dst; 187 188 /* dst must be aligned to block boundary. */ 189 if (I28F128_BLOCK_MASK & (u_int32_t) dst) 190 return -1; 191 192 while (len >= I28F128_BLOCK_SIZE) { 193 if ((status = block_write(q, p)) != 0) 194 return status; 195 putchar('b'); 196 p += I28F128_BLOCK_SIZE >> 1; 197 q += I28F128_BLOCK_SIZE >> 1; 198 len -= I28F128_BLOCK_SIZE; 199 } 200 201 if (len > 0) { 202 if (memcmp(p, q, len) == 0) 203 return 0; 204 if ((status = block_erase(q)) != 0) 205 return status; 206 for (; len > 0; len -= 2) { 207 #ifdef USE_TWIDDLE 208 if (((u_int32_t) q % 4096) == 0) 209 twiddle(); 210 #endif 211 if ((status = word_program(q++, *p++)) != 0) 212 return status; 213 } 214 printf("w"); 215 } 216 217 putchar('\n'); 218 return 0; 219 } 220