00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00055 #include <cfg/os.h>
00056 #include <cfg/memory.h>
00057
00058 #include <sys/timer.h>
00059
00060 #include <string.h>
00061 #include <stdlib.h>
00062
00063 #include <dev/at91_spi.h>
00064 #include <dev/at45db.h>
00065
00066 #ifndef MAX_AT45_DEVICES
00067 #define MAX_AT45_DEVICES 1
00068 #endif
00069
00070 #ifndef MAX_AT45_CMDLEN
00071 #define MAX_AT45_CMDLEN 8
00072 #endif
00073
00074 #ifndef AT45_CONF_DFSPI
00075 #define AT45_CONF_DFSPI SPI0_BASE
00076 #endif
00077
00078 #ifndef AT45_CONF_DFPCS
00079 #define AT45_CONF_DFPCS 1
00080 #endif
00081
00082 #ifndef AT45_ERASE_WAIT
00083 #define AT45_ERASE_WAIT 3000
00084 #endif
00085
00086 #ifndef AT45_CHIP_ERASE_WAIT
00087 #define AT45_CHIP_ERASE_WAIT 50000
00088 #endif
00089
00090 #ifndef AT45_WRITE_POLLS
00091 #define AT45_WRITE_POLLS 1000
00092 #endif
00093
00104 #define DFCMD_CONT_READ_LF 0x03
00105
00111 #define DFCMD_CONT_READ_HF 0x0B
00112
00114 #define DFCMD_BLOCK_ERASE 0x50
00115
00117 #define DFCMD_SECTOR_ERASE 0x7C
00118
00120 #define DFCMD_PAGE_ERASE 0x81
00121
00123 #define DFCMD_BUF1_PROG 0x82
00124
00126 #define DFCMD_BUF1_FLASH 0x83
00127
00129 #define DFCMD_BUF1_WRITE 0x84
00130
00132 #define DFCMD_BUF2_PROG 0x85
00133
00135 #define DFCMD_BUF2_FLASH 0x86
00136
00138 #define DFCMD_BUF2_WRITE 0x87
00139
00141 #define DFCMD_BUF1_FLASH_NE 0x88
00142
00144 #define DFCMD_BUF2_FLASH_NE 0x89
00145
00147 #define DFCMD_CHIP_ERASE 0xC7
00148
00150 #define DFCMD_BUF1_READ_LF 0xD1
00151
00156 #define DFCMD_READ_PAGE 0xD2
00157
00159 #define DFCMD_BUF2_READ_LF 0xD3
00160
00162 #define DFCMD_BUF1_READ 0xD4
00163
00165 #define DFCMD_BUF2_READ 0xD6
00166
00168 #define DFCMD_READ_STATUS 0xD7
00169
00175 #define DFCMD_CONT_READ 0xE8
00176
00178 #define AT45DB_AT91
00179
00180
00181 #if defined(AT45DB_SPI0_DEVICE)
00182
00183 #include <dev/sppif0.h>
00184 #if defined(AT45DB_RESET_ACTIVE_HIGH)
00185 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, act)
00186 #else
00187 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, !act)
00188 #endif
00189 #define SpiSetMode() Sppi0SetMode(AT45DB_SPI0_DEVICE, AT45DB_SPI_MODE)
00190 #define SpiSetSpeed() Sppi0SetSpeed(AT45DB_SPI0_DEVICE, AT45DB_SPI_RATE)
00191 #if defined(AT45DB_SELECT_ACTIVE_HIGH)
00192 #define SpiSelect() Sppi0SelectDevice(AT45DB_SPI0_DEVICE)
00193 #define SpiDeselect() Sppi0DeselectDevice(AT45DB_SPI0_DEVICE)
00194 #else
00195 #define SpiSelect() Sppi0NegSelectDevice(AT45DB_SPI0_DEVICE)
00196 #define SpiDeselect() Sppi0NegDeselectDevice(AT45DB_SPI0_DEVICE)
00197 #endif
00198 #define SpiByte Sppi0Byte
00199
00200 #elif defined(AT45DB_SBBI0_DEVICE)
00201
00202 #include <dev/sbbif0.h>
00203 #if defined(VS10XX_RESET_ACTIVE_HIGH)
00204 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, act)
00205 #else
00206 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, !act)
00207 #endif
00208 #define SpiSetMode() Sbbi0SetMode(AT45DB_SBBI0_DEVICE, AT45DB_SPI_MODE)
00209 #define SpiSetSpeed() Sbbi0SetSpeed(AT45DB_SBBI0_DEVICE, AT45DB_SPI_RATE)
00210 #if defined(VS10XX_SELECT_ACTIVE_HIGH)
00211 #define SpiSelect() Sbbi0SelectDevice(AT45DB_SBBI0_DEVICE)
00212 #define SpiDeselect() Sbbi0DeselectDevice(AT45DB_SBBI0_DEVICE)
00213 #else
00214 #define SpiSelect() Sbbi0NegSelectDevice(AT45DB_SBBI0_DEVICE)
00215 #define SpiDeselect() Sbbi0NegDeselectDevice(AT45DB_SBBI0_DEVICE)
00216 #endif
00217 #define SpiByte Sbbi0Byte
00218
00219 #endif
00220
00224 typedef struct _AT45_DEVTAB {
00225 u_long devt_pages;
00226 u_int devt_pagsiz;
00227 u_int devt_offs;
00228 u_char devt_srmsk;
00229 u_char devt_srval;
00230 } AT45_DEVTAB;
00231
00235 typedef struct _AT45DB_DCB {
00236 AT45_DEVTAB *dcb_devt;
00237 u_int dcb_spibas;
00238 u_int dcb_spipcs;
00239 u_char dcb_cmdbuf[MAX_AT45_CMDLEN];
00240 } AT45DB_DCB;
00241
00245 AT45_DEVTAB at45_devt[] = {
00246 {512, 264, 9, 0x3C, 0x0C},
00247 {1025, 264, 9, 0x3C, 0x14},
00248 {2048, 264, 9, 0x3C, 0x1C},
00249 {4096, 264, 9, 0x3C, 0x24},
00250 {4096, 528, 10, 0x3C, 0x2C},
00251 {8192, 528, 10, 0x3C, 0x34},
00252 {8192, 1056, 11, 0x38, 0x38},
00253 {0, 0, 0, 0, 0}
00254 };
00255
00259 static AT45DB_DCB dcbtab[MAX_AT45_DEVICES];
00260
00261
00262 static int dcbnum;
00263
00264
00265 static int dd_param = -1;
00266
00278 int At45dbSendCmd(int dd, u_char op, u_long parm, int len, CONST void *tdata, void *rdata, int datalen)
00279 {
00280 u_char *cb = dcbtab[dd].dcb_cmdbuf;
00281
00282 if (len > MAX_AT45_CMDLEN) {
00283 return -1;
00284 }
00285 memset(cb, 0, len);
00286 cb[0] = op;
00287 if (parm) {
00288 cb[1] = (u_char) (parm >> 16);
00289 cb[2] = (u_char) (parm >> 8);
00290 cb[3] = (u_char) parm;
00291 }
00292 return At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, cb, cb, len, tdata, rdata, datalen);
00293 }
00294
00295 u_char At45dbGetStatus(int dd)
00296 {
00297 u_char buf[2] = { DFCMD_READ_STATUS, 0xFF };
00298
00299 if (At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, buf, buf, 2, NULL, NULL, 0)) {
00300 return (u_char) - 1;
00301 }
00302 return buf[1];
00303 }
00304
00310 int At45dbWaitReady(int dd, u_long tmo, int poll)
00311 {
00312 u_char sr;
00313
00314 while (((sr = At45dbGetStatus(dd)) & 0x80) == 0) {
00315 if (!poll) {
00316 NutSleep(1);
00317 }
00318 if (tmo-- == 0) {
00319 return -1;
00320 }
00321 }
00322 return 0;
00323 }
00324
00334 int At45dbInit(u_int spibas, u_int spipcs)
00335 {
00336 int dd = -1;
00337 u_char sr;
00338 int i;
00339
00340 for (i = 0; i < dcbnum; i++) {
00341 if (dcbtab[i].dcb_spibas == spibas && dcbtab[i].dcb_spipcs == spipcs) {
00342 return i;
00343 }
00344 }
00345
00346 if (dcbnum >= MAX_AT45_DEVICES) {
00347 return -1;
00348 }
00349
00350 #if defined(MCU_AT91SAM7X256) || defined(MCU_AT91SAM9260)
00351 At91SpiInit(spibas);
00352 At91SpiReset(spibas);
00353 At91SpiInitChipSelects(spibas, _BV(spipcs));
00354 At91SpiSetRate(spibas, spipcs, 1000000);
00355 At91SpiSetModeFlags(spibas, spipcs, SPIMF_MASTER | SPIMF_SCKIAHI | SPIMF_CAPRISE);
00356 #elif defined(MCU_AT91R40008)
00357 #endif
00358
00359 dcbtab[dcbnum].dcb_spibas = spibas;
00360 dcbtab[dcbnum].dcb_spipcs = spipcs;
00361 sr = At45dbGetStatus(dcbnum);
00362
00363 for (i = 0; at45_devt[i].devt_pages; i++) {
00364 if ((sr & at45_devt[i].devt_srmsk) == at45_devt[i].devt_srval) {
00365 dcbtab[dcbnum].dcb_devt = &at45_devt[i];
00366 dd = dcbnum++;
00367 break;
00368 }
00369 }
00370 return dd;
00371 }
00372
00376 int At45dbPageErase(int dd, u_int pgn)
00377 {
00378 return At45dbSendCmd(dd, DFCMD_PAGE_ERASE, pgn, 4, NULL, NULL, 0);
00379 }
00380
00384 int At45dbChipErase(void)
00385 {
00386 return -1;
00387 }
00388
00399 int At45dbPageRead(int dd, u_long pgn, void *data, u_int len)
00400 {
00401 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00402 return At45dbSendCmd(dd, DFCMD_CONT_READ, pgn, 8, data, data, len);
00403 }
00404
00417 int At45dbPageWrite(int dd, u_int pgn, CONST void *data, u_int len)
00418 {
00419 int rc = -1;
00420 void *rp;
00421
00422 if ((rp = malloc(len)) != NULL) {
00423
00424 if (At45dbSendCmd(dd, DFCMD_BUF1_WRITE, 0, 4, data, rp, len) == 0) {
00425
00426 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00427 if (At45dbSendCmd(dd, DFCMD_BUF1_FLASH, pgn, 4, NULL, NULL, 0) == 0) {
00428 rc = At45dbWaitReady(dd, AT45_WRITE_POLLS, 1);
00429 }
00430 }
00431 free(rp);
00432 }
00433 return rc;
00434 }
00435
00436 u_long At45dbParamPage(void)
00437 {
00438 #ifdef AT45_CONF_PAGE
00439 return AT45_CONF_PAGE;
00440 #else
00441 return dcbtab[dd_param].dcb_devt->devt_pages - 1;
00442 #endif
00443 }
00444
00456 int At45dbParamSize(void)
00457 {
00458 int rc;
00459
00460 if (dd_param == -1 && (dd_param = At45dbInit(AT45_CONF_DFSPI, AT45_CONF_DFPCS)) == -1) {
00461 return -1;
00462 }
00463 #ifdef AT45_CONF_SIZE
00464 rc = AT45_CONF_SIZE;
00465 #else
00466 rc = dcbtab[dd_param].dcb_devt->devt_pagsiz;
00467 #endif
00468 return rc;
00469 }
00470
00480 int At45dbParamRead(u_int pos, void *data, u_int len)
00481 {
00482 int rc = -1;
00483 u_char *buff;
00484 int csize = At45dbParamSize();
00485 u_long cpage = At45dbParamPage();
00486
00487
00488 if (csize > len && (buff = malloc(csize)) != NULL) {
00489 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00490
00491 memcpy(data, buff + pos, len);
00492 free(buff);
00493 }
00494 return rc;
00495 }
00496
00506 int At45dbParamWrite(u_int pos, CONST void *data, u_int len)
00507 {
00508 int rc = -1;
00509 u_char *buff;
00510 int csize = At45dbParamSize();
00511 u_long cpage = At45dbParamPage();
00512
00513
00514 if (csize > len && (buff = malloc(csize)) != NULL) {
00515 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00516
00517 if (memcmp(buff + pos, data, len)) {
00518
00519 memcpy(buff + pos, data, len);
00520
00521 rc = At45dbPageWrite(dd_param, cpage, buff, csize);
00522 }
00523 free(buff);
00524 }
00525 return rc;
00526 }