00001 /* 00002 * Copyright (C) 2002 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 * 00032 */ 00033 00034 /* 00035 * $Log: spiflash.c,v $ 00036 * Revision 1.1 2005/07/26 18:02:40 haraldkipp 00037 * Moved from dev. 00038 * 00039 * Revision 1.2 2004/03/18 14:06:52 haraldkipp 00040 * Deprecated header file replaced 00041 * 00042 * Revision 1.1.1.1 2003/05/09 14:40:50 haraldkipp 00043 * Initial using 3.2.1 00044 * 00045 * Revision 1.4 2003/02/04 17:50:54 harald 00046 * Version 3 released 00047 * 00048 * Revision 1.3 2002/09/15 16:39:44 harald 00049 * *** empty log message *** 00050 * 00051 * Revision 1.2 2002/08/08 17:20:47 harald 00052 * Imagecraft support by Klaus Ummenhofer 00053 * 00054 */ 00055 00056 #include <string.h> 00057 00058 #include <sys/atom.h> 00059 #include <sys/event.h> 00060 #include <sys/timer.h> 00061 #include <sys/heap.h> 00062 #include <sys/device.h> 00063 00064 #include <dev/spiflash.h> 00065 00070 00074 #ifdef __GNUC__ 00075 static __inline u_char SpiByte(u_char c) 00076 #else 00077 static u_char SpiByte(u_char c) 00078 #endif 00079 { 00080 outp(c, SPDR); 00081 loop_until_bit_is_set(SPSR, SPIF); 00082 return inp(SPDR); 00083 } 00084 00090 int SpiFlashEnable(void) 00091 { 00092 u_char i; 00093 u_char rc; 00094 00095 /* 00096 * PB0(O): SS 00097 * PB1(O): SCK 00098 * PB2(O): MOSI 00099 * PB3(I): MISO 00100 * 00101 * PB4(O): Reset target 00102 * PB5(-): Unused 00103 * PB6(-): Unused 00104 * PB7(-): Unused 00105 */ 00106 00107 /* 00108 * SCK and MOSI outputs need configuration, 00109 * even if SPI mode is enabled. 00110 */ 00111 cbi(PORTB, 1); 00112 sbi(DDRB, 1); 00113 cbi(PORTB, 2); 00114 sbi(DDRB, 2); 00115 00116 /* 00117 * Enable pull-up on MISO. 00118 */ 00119 sbi(PORTB, 3); 00120 00121 for (i = 0; i < 32; i++) { 00122 00123 /* 00124 * Set reset low. 00125 */ 00126 cbi(PORTB, 4); 00127 sbi(DDRB, 4); 00128 00129 /* 00130 * Set slave select pin to output. Otherwise a low signal 00131 * on this pin might force us to SPI slave mode. 00132 */ 00133 sbi(DDRB, 0); 00134 outp(BV(MSTR) | BV(SPE) | BV(SPR0), SPCR); 00135 00136 /* 00137 * Try to enable programming. 00138 */ 00139 SpiByte(0xAC); 00140 SpiByte(0x53); 00141 rc = SpiByte(0xFF); 00142 SpiByte(0xff); 00143 00144 if (rc == 0x53) 00145 return 0; 00146 00147 /* 00148 * Programming enable failed. This may be because the 00149 * target is not synchronized. A positive pulse on the 00150 * clock line should help. 00151 */ 00152 outp(0, SPCR); 00153 sbi(PORTB, 1); 00154 cbi(PORTB, 1); 00155 } 00156 return -1; 00157 } 00158 00165 void SpiFlashId(u_char * id) 00166 { 00167 u_char i; 00168 00169 for (i = 0; i < 3; i++) { 00170 SpiByte(0x30); 00171 SpiByte(0x00); 00172 SpiByte(i); 00173 id[i] = SpiByte(0x00); 00174 } 00175 } 00176 00190 int SpiFlashWriteByte(u_char high, u_short addr, u_char data) 00191 { 00192 u_char d; 00193 00194 if (data != 0xff) { 00195 SpiByte(0x40 | high); 00196 SpiByte(addr >> 8); 00197 SpiByte(addr & 0xFF); 00198 SpiByte(data); 00199 00200 /* 00201 * During programming a value of 0x7F appears at the memory location. 00202 * If we are programming this value, we delay execution by 10 ms. 00203 * Otherwise we poll the memory location until we read back the 00204 * programmed value. 00205 */ 00206 if (data == 0x7f) 00207 NutDelay(10); 00208 else { 00209 for (d = 0; d < 255; d++) { 00210 00211 /* 00212 * Read program flash byte. 00213 */ 00214 SpiByte(0x20 | high); 00215 SpiByte(addr >> 8); 00216 SpiByte(addr & 0xFF); 00217 if (SpiByte(0xFF) == data) 00218 break; 00219 } 00220 if (d == 255) 00221 return -1; 00222 } 00223 } 00224 return 0; 00225 } 00226 00235 int SpiFlashWriteWord(u_short addr, u_short data) 00236 { 00237 if (SpiFlashWriteByte(0, addr, data & 0xFF)) 00238 return -1; 00239 if (SpiFlashWriteByte(8, addr, data >> 8)) 00240 return -1; 00241 00242 return 0; 00243 } 00244 00251 void SpiFlashErase(void) 00252 { 00253 /* 00254 * Send chip erase command. 00255 */ 00256 SpiByte(0xAC); 00257 SpiByte(0x80); 00258 SpiByte(0x00); 00259 SpiByte(0x00); 00260 NutDelay(25); 00261 } 00262