00001
00038 #include <stdbool.h>
00039 #include <stdint.h>
00040 #include <spi.h>
00041 #include <flash/at45_device.h>
00042
00043 static bool at45_wait_poll_status(struct at45_device *at45d);
00044
00045 static bool at45_wait_poll_done(struct at45_device *at45d)
00046 {
00047 at45_deselect(at45d);
00048 if (at45_rsp_status_is_ready(at45d)) {
00049 at45d->next = NULL;
00050 return true;
00051 } else
00052 return at45_wait_poll_status(at45d);
00053 }
00054
00055 static bool at45_wait_poll_cmd_done(struct at45_device *at45d)
00056 {
00057 at45d->next = at45_wait_poll_done;
00058 at45_read_rsp(at45d, 1);
00059 return false;
00060 }
00061
00062 static bool at45_wait_poll_status(struct at45_device *at45d)
00063 {
00064 at45d->next = at45_wait_poll_cmd_done;
00065 at45_select(at45d);
00066 at45_cmd_read_status_reg(at45d);
00067 return false;
00068 }
00069
00082 bool at45_wait_ready(struct at45_device *at45d)
00083 {
00084 if (at45d->next)
00085 return at45d->next(at45d);
00086 else
00087 return at45_wait_poll_status(at45d);
00088 }
00089
00118 static bool at45_identify_got_id(struct at45_device *at45d)
00119 {
00120 at45_deselect(at45d);
00121 spi_release_bus(at45d->spim);
00122 dbg_info("at45_device: DataFlash information:\n"
00123 " Manufacturer ID : 0x%02x\n"
00124 " Device ID (part 1): 0x%02x\n"
00125 " Device ID (part 2): 0x%02x\n"
00126 " Extended info : 0x%02x\n",
00127 at45d->cmdrsp[0], at45d->cmdrsp[1],
00128 at45d->cmdrsp[2], at45d->cmdrsp[3]);
00129 if (at45_is_valid_id(at45d->cmdrsp[0], at45d->cmdrsp[1])) {
00130 set_bit(AT45_FLAG_VALID, &at45d->flags);
00131 at45d->size = at45_get_size(at45d->cmdrsp[1]);
00132 if (at45d->size >= (1024L * 1024)) {
00133 dbg_info(" Flash size : %ld MiB\n",
00134 at45d->size / (1024L * 1024));
00135 } else {
00136 dbg_info(" Flash size : %ld KiB\n",
00137 at45d->size / 1024);
00138 }
00139 at45d->page_size = at45_get_page_size(at45d->cmdrsp[1]);
00140 dbg_info(" Page size : %d\n", at45d->page_size);
00141 } else {
00142 dbg_warning("at45_device: No valid dataflash detected!\n");
00143 }
00144 at45d->next = NULL;
00145 return true;
00146 }
00147
00148 static bool at45_identify_fetch_id(struct at45_device *at45d)
00149 {
00150 at45d->next = at45_identify_got_id;
00151 at45_read_rsp(at45d, 4);
00152 return false;
00153 }
00154
00155 static bool at45_identify_fetch_status(struct at45_device *at45d);
00156
00157 static bool at45_identify_got_status(struct at45_device *at45d)
00158 {
00159 if (!at45_rsp_status_is_ready(at45d))
00160 return at45_identify_fetch_status(at45d);
00161
00162 at45d->next = at45_identify_fetch_id;
00163 at45_deselect(at45d);
00164 dbg_info("at45_device: Status register: 0x%02x\n", at45d->cmdrsp[0]);
00165 if (at45_rsp_status_is_protected(at45d))
00166 set_bit(AT45_FLAG_PROTECTED, &at45d->flags);
00167 at45_select(at45d);
00168 at45_cmd_read_id(at45d);
00169 return false;
00170 }
00171
00172 static bool at45_identify_fetch_status(struct at45_device *at45d)
00173 {
00174 at45d->next = at45_identify_got_status;
00175 at45_read_rsp(at45d, 1);
00176 return false;
00177 }
00178
00179 static bool at45_identify_start(struct at45_device *at45d)
00180 {
00181 at45d->next = at45_identify_fetch_status;
00182 at45_select(at45d);
00183 at45_cmd_read_status_reg(at45d);
00184 return false;
00185 }
00186
00199 bool at45_identify(struct at45_device *at45d)
00200 {
00201 if (at45d->next)
00202 return at45d->next(at45d);
00203 else
00204 return at45_identify_start(at45d);
00205 }
00206
00216 void at45_device_init(struct at45_device *at45d, spi_id_t spi_id,
00217 struct spi_master *spim, struct spi_device *spid)
00218 {
00219 at45d->spi_id = spi_id;
00220 at45d->spim = spim;
00221 at45d->spid = spid;
00222 at45d->next = NULL;
00223 at45d->flags = 0;
00224 }
00225