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
00058 #include <cfg/os.h>
00059 #include <cfg/memory.h>
00060
00061 #include <sys/timer.h>
00062
00063 #include <string.h>
00064 #include <stdlib.h>
00065
00066 #include <dev/at91_spi.h>
00067 #include <dev/at45db.h>
00068
00069 #ifndef MAX_AT45_DEVICES
00070 #define MAX_AT45_DEVICES 1
00071 #endif
00072
00073 #ifndef MAX_AT45_CMDLEN
00074 #define MAX_AT45_CMDLEN 8
00075 #endif
00076
00077 #ifndef AT45_CONF_DFSPI
00078 #define AT45_CONF_DFSPI SPI0_BASE
00079 #endif
00080
00081 #ifndef AT45_CONF_DFPCS
00082 #define AT45_CONF_DFPCS 1
00083 #endif
00084
00085 #ifndef AT45_ERASE_WAIT
00086 #define AT45_ERASE_WAIT 3000
00087 #endif
00088
00089 #ifndef AT45_CHIP_ERASE_WAIT
00090 #define AT45_CHIP_ERASE_WAIT 50000
00091 #endif
00092
00093 #ifndef AT45_WRITE_POLLS
00094 #define AT45_WRITE_POLLS 1000
00095 #endif
00096
00107 #define DFCMD_CONT_READ_LF 0x03
00108
00114 #define DFCMD_CONT_READ_HF 0x0B
00115
00117 #define DFCMD_BLOCK_ERASE 0x50
00118
00120 #define DFCMD_SECTOR_ERASE 0x7C
00121
00123 #define DFCMD_PAGE_ERASE 0x81
00124
00126 #define DFCMD_BUF1_PROG 0x82
00127
00129 #define DFCMD_BUF1_FLASH 0x83
00130
00132 #define DFCMD_BUF1_WRITE 0x84
00133
00135 #define DFCMD_BUF2_PROG 0x85
00136
00138 #define DFCMD_BUF2_FLASH 0x86
00139
00141 #define DFCMD_BUF2_WRITE 0x87
00142
00144 #define DFCMD_BUF1_FLASH_NE 0x88
00145
00147 #define DFCMD_BUF2_FLASH_NE 0x89
00148
00150 #define DFCMD_CHIP_ERASE 0xC7
00151
00153 #define DFCMD_BUF1_READ_LF 0xD1
00154
00159 #define DFCMD_READ_PAGE 0xD2
00160
00162 #define DFCMD_BUF2_READ_LF 0xD3
00163
00165 #define DFCMD_BUF1_READ 0xD4
00166
00168 #define DFCMD_BUF2_READ 0xD6
00169
00171 #define DFCMD_READ_STATUS 0xD7
00172
00178 #define DFCMD_CONT_READ 0xE8
00179
00181 #define AT45DB_AT91
00182
00183
00184 #if defined(AT45DB_SPI0_DEVICE)
00185
00186 #include <dev/sppif0.h>
00187 #if defined(AT45DB_RESET_ACTIVE_HIGH)
00188 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, act)
00189 #else
00190 #define SpiReset(act) Sppi0ChipReset(AT45DB_SPI0_DEVICE, !act)
00191 #endif
00192 #define SpiSetMode() Sppi0SetMode(AT45DB_SPI0_DEVICE, AT45DB_SPI_MODE)
00193 #define SpiSetSpeed() Sppi0SetSpeed(AT45DB_SPI0_DEVICE, AT45DB_SPI_RATE)
00194 #if defined(AT45DB_SELECT_ACTIVE_HIGH)
00195 #define SpiSelect() Sppi0SelectDevice(AT45DB_SPI0_DEVICE)
00196 #define SpiDeselect() Sppi0DeselectDevice(AT45DB_SPI0_DEVICE)
00197 #else
00198 #define SpiSelect() Sppi0NegSelectDevice(AT45DB_SPI0_DEVICE)
00199 #define SpiDeselect() Sppi0NegDeselectDevice(AT45DB_SPI0_DEVICE)
00200 #endif
00201 #define SpiByte Sppi0Byte
00202
00203 #elif defined(AT45DB_SBBI0_DEVICE)
00204
00205 #include <dev/sbbif0.h>
00206 #if defined(VS10XX_RESET_ACTIVE_HIGH)
00207 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, act)
00208 #else
00209 #define SpiReset(act) Sbbi0ChipReset(AT45DB_SBBI0_DEVICE, !act)
00210 #endif
00211 #define SpiSetMode() Sbbi0SetMode(AT45DB_SBBI0_DEVICE, AT45DB_SPI_MODE)
00212 #define SpiSetSpeed() Sbbi0SetSpeed(AT45DB_SBBI0_DEVICE, AT45DB_SPI_RATE)
00213 #if defined(VS10XX_SELECT_ACTIVE_HIGH)
00214 #define SpiSelect() Sbbi0SelectDevice(AT45DB_SBBI0_DEVICE)
00215 #define SpiDeselect() Sbbi0DeselectDevice(AT45DB_SBBI0_DEVICE)
00216 #else
00217 #define SpiSelect() Sbbi0NegSelectDevice(AT45DB_SBBI0_DEVICE)
00218 #define SpiDeselect() Sbbi0NegDeselectDevice(AT45DB_SBBI0_DEVICE)
00219 #endif
00220 #define SpiByte Sbbi0Byte
00221
00222 #endif
00223
00227 typedef struct _AT45_DEVTAB {
00228 u_long devt_pages;
00229 u_int devt_pagsiz;
00230 u_int devt_offs;
00231 u_char devt_srmsk;
00232 u_char devt_srval;
00233 } AT45_DEVTAB;
00234
00238 typedef struct _AT45DB_DCB {
00239 AT45_DEVTAB *dcb_devt;
00240 u_int dcb_spibas;
00241 u_int dcb_spipcs;
00242 u_char dcb_cmdbuf[MAX_AT45_CMDLEN];
00243 } AT45DB_DCB;
00244
00248 AT45_DEVTAB at45_devt[] = {
00249 {512, 264, 9, 0x3C, 0x0C},
00250 {1025, 264, 9, 0x3C, 0x14},
00251 {2048, 264, 9, 0x3C, 0x1C},
00252 {4096, 264, 9, 0x3C, 0x24},
00253 {4096, 528, 10, 0x3C, 0x2C},
00254 {8192, 528, 10, 0x3C, 0x34},
00255 {8192, 1056, 11, 0x38, 0x38},
00256 {0, 0, 0, 0, 0}
00257 };
00258
00262 static AT45DB_DCB dcbtab[MAX_AT45_DEVICES];
00263
00264
00265 static int dcbnum;
00266
00267
00268 static int dd_param = -1;
00269
00281 int At45dbSendCmd(int dd, u_char op, u_long parm, int len, CONST void *tdata, void *rdata, int datalen)
00282 {
00283 u_char *cb = dcbtab[dd].dcb_cmdbuf;
00284
00285 if (len > MAX_AT45_CMDLEN) {
00286 return -1;
00287 }
00288 memset(cb, 0, len);
00289 cb[0] = op;
00290 if (parm) {
00291 cb[1] = (u_char) (parm >> 16);
00292 cb[2] = (u_char) (parm >> 8);
00293 cb[3] = (u_char) parm;
00294 }
00295 return At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, cb, cb, len, tdata, rdata, datalen);
00296 }
00297
00298 u_char At45dbGetStatus(int dd)
00299 {
00300 u_char buf[2] = { DFCMD_READ_STATUS, 0xFF };
00301
00302 if (At91SpiTransfer2(dcbtab[dd].dcb_spibas, dcbtab[dd].dcb_spipcs, buf, buf, 2, NULL, NULL, 0)) {
00303 return (u_char) - 1;
00304 }
00305 return buf[1];
00306 }
00307
00313 int At45dbWaitReady(int dd, u_long tmo, int poll)
00314 {
00315 u_char sr;
00316
00317 while (((sr = At45dbGetStatus(dd)) & 0x80) == 0) {
00318 if (!poll) {
00319 NutSleep(1);
00320 }
00321 if (tmo-- == 0) {
00322 return -1;
00323 }
00324 }
00325 return 0;
00326 }
00327
00337 int At45dbInit(u_int spibas, u_int spipcs)
00338 {
00339 int dd = -1;
00340 u_char sr;
00341 int i;
00342
00343 for (i = 0; i < dcbnum; i++) {
00344 if (dcbtab[i].dcb_spibas == spibas && dcbtab[i].dcb_spipcs == spipcs) {
00345 return i;
00346 }
00347 }
00348
00349 if (dcbnum >= MAX_AT45_DEVICES) {
00350 return -1;
00351 }
00352
00353 #if defined(MCU_AT91SAM7X256) || defined(MCU_AT91SAM9260)
00354 At91SpiInit(spibas);
00355 At91SpiReset(spibas);
00356 At91SpiInitChipSelects(spibas, _BV(spipcs));
00357 At91SpiSetRate(spibas, spipcs, 1000000);
00358 At91SpiSetModeFlags(spibas, spipcs, SPIMF_MASTER | SPIMF_SCKIAHI | SPIMF_CAPRISE);
00359 #elif defined(MCU_AT91R40008)
00360 #endif
00361
00362 dcbtab[dcbnum].dcb_spibas = spibas;
00363 dcbtab[dcbnum].dcb_spipcs = spipcs;
00364 sr = At45dbGetStatus(dcbnum);
00365
00366 for (i = 0; at45_devt[i].devt_pages; i++) {
00367 if ((sr & at45_devt[i].devt_srmsk) == at45_devt[i].devt_srval) {
00368 dcbtab[dcbnum].dcb_devt = &at45_devt[i];
00369 dd = dcbnum++;
00370 break;
00371 }
00372 }
00373 return dd;
00374 }
00375
00379 int At45dbPageErase(int dd, u_int pgn)
00380 {
00381 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00382 return At45dbSendCmd(dd, DFCMD_PAGE_ERASE, pgn, 4, NULL, NULL, 0);
00383 }
00384
00388 int At45dbChipErase(void)
00389 {
00390 return -1;
00391 }
00392
00403 int At45dbPageRead(int dd, u_long pgn, void *data, u_int len)
00404 {
00405 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00406 return At45dbSendCmd(dd, DFCMD_CONT_READ, pgn, 8, data, data, len);
00407 }
00408
00421 int At45dbPageWrite(int dd, u_int pgn, CONST void *data, u_int len)
00422 {
00423 int rc = -1;
00424 void *rp;
00425
00426 if ((rp = malloc(len)) != NULL) {
00427
00428 if (At45dbSendCmd(dd, DFCMD_BUF1_WRITE, 0, 4, data, rp, len) == 0) {
00429
00430 pgn <<= dcbtab[dd].dcb_devt->devt_offs;
00431 if (At45dbSendCmd(dd, DFCMD_BUF1_FLASH, pgn, 4, NULL, NULL, 0) == 0) {
00432 rc = At45dbWaitReady(dd, AT45_WRITE_POLLS, 1);
00433 }
00434 }
00435 free(rp);
00436 }
00437 return rc;
00438 }
00439
00440 u_long At45dbParamPage(void)
00441 {
00442 #ifdef AT45_CONF_PAGE
00443 return AT45_CONF_PAGE;
00444 #else
00445 return dcbtab[dd_param].dcb_devt->devt_pages - 1;
00446 #endif
00447 }
00448
00460 int At45dbParamSize(void)
00461 {
00462 int rc;
00463
00464 if (dd_param == -1 && (dd_param = At45dbInit(AT45_CONF_DFSPI, AT45_CONF_DFPCS)) == -1) {
00465 return -1;
00466 }
00467 #ifdef AT45_CONF_SIZE
00468 rc = AT45_CONF_SIZE;
00469 #else
00470 rc = dcbtab[dd_param].dcb_devt->devt_pagsiz;
00471 #endif
00472 return rc;
00473 }
00474
00484 int At45dbParamRead(u_int pos, void *data, u_int len)
00485 {
00486 int rc = -1;
00487 u_char *buff;
00488 int csize = At45dbParamSize();
00489 u_long cpage = At45dbParamPage();
00490
00491
00492 if (csize > len && (buff = malloc(csize)) != NULL) {
00493 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00494
00495 memcpy(data, buff + pos, len);
00496 free(buff);
00497 }
00498 return rc;
00499 }
00500
00510 int At45dbParamWrite(u_int pos, CONST void *data, u_int len)
00511 {
00512 int rc = -1;
00513 u_char *buff;
00514 int csize = At45dbParamSize();
00515 u_long cpage = At45dbParamPage();
00516
00517
00518 if (csize > len && (buff = malloc(csize)) != NULL) {
00519 rc = At45dbPageRead(dd_param, cpage, buff, csize);
00520
00521 if (memcmp(buff + pos, data, len)) {
00522
00523 memcpy(buff + pos, data, len);
00524
00525 rc = At45dbPageWrite(dd_param, cpage, buff, csize);
00526 }
00527 free(buff);
00528 }
00529 return rc;
00530 }