00001
00038 #include <assert.h>
00039 #include <bitops.h>
00040 #include <debug.h>
00041 #include <interrupt.h>
00042 #include <malloc.h>
00043 #include <status_codes.h>
00044 #include <string.h>
00045 #include <util.h>
00046 #include <string.h>
00047 #include <spi.h>
00048 #include <block/device.h>
00049 #include <block/dataflash.h>
00050 #include <workqueue.h>
00051 #include <mempool.h>
00052 #include <flash/at45_device.h>
00053
00106
00107 #define DATAFLASH_BLOCK_SIZE 512
00108
00110 struct dataflash_breq {
00112 struct block_request breq;
00114 struct workqueue_task task;
00116 block_addr_t lba;
00118 block_len_t remaining_blocks;
00120 enum block_operation operation;
00122 bool sleeping;
00123 };
00124
00126 struct dataflash_bdev {
00128 struct block_device bdev;
00130 struct at45_device at45d;
00132 struct workqueue_task *event_task;
00134 struct mem_pool req_pool;
00136 struct workqueue_task task;
00143 int8_t page_block_shift;
00145 struct slist current_buf_list;
00147 int transfer_pos;
00148 };
00149
00150 static inline struct dataflash_breq *dataflash_breq_of(
00151 struct block_request *req)
00152 {
00153 return container_of(req, struct dataflash_breq, breq);
00154 }
00155
00156 static inline struct dataflash_bdev *dataflash_bdev_of(
00157 struct block_device *dev)
00158 {
00159 return container_of(dev, struct dataflash_bdev, bdev);
00160 }
00161
00162 static inline struct dataflash_breq *dataflash_breq_of_task(
00163 struct workqueue_task *task)
00164 {
00165 return container_of(task, struct dataflash_breq, task);
00166 }
00167
00180 static int8_t dataflash_get_page_block_shift(struct dataflash_breq *df_breq)
00181 {
00182 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00183
00184 return df_bdev->page_block_shift;
00185 }
00186
00197 static bool dataflash_is_page_aligned(struct dataflash_breq *df_breq)
00198 {
00199 int8_t shift;
00200
00201 shift = dataflash_get_page_block_shift(df_breq);
00202 if (shift == 0)
00203 return true;
00204 else if (shift == 1) {
00205
00206
00207
00208
00209
00210 if (!(df_breq->lba & 1) && (df_breq->remaining_blocks >= 2))
00211 return true;
00212 else
00213 return false;
00214 } else
00215 return true;
00216 }
00217
00226 static bool dataflash_store_page_size(struct dataflash_bdev *df_bdev,
00227 uint16_t page_size)
00228 {
00229 switch (page_size) {
00230 case 256:
00231 df_bdev->page_block_shift = -1;
00232 return true;
00233 case 512:
00234 df_bdev->page_block_shift = 0;
00235 return true;
00236 case 1024:
00237 df_bdev->page_block_shift = 1;
00238 return true;
00239 default:
00240 return false;
00241 }
00242 }
00243
00251 static uint16_t dataflash_get_remaining_page_size(
00252 struct dataflash_breq *df_breq)
00253 {
00254 int8_t shift;
00255
00256 shift = dataflash_get_page_block_shift(df_breq);
00257
00258
00259 assert((shift >= -1) && (shift <= 1));
00260
00261 if (shift == 0)
00262 return 512;
00263 else if (shift == 1) {
00264
00265
00266
00267
00268 if (!(df_breq->lba & 1) && (df_breq->remaining_blocks >= 2))
00269 return 1024;
00270 else
00271 return 512;
00272 } else {
00273
00274 return 256;
00275 }
00276 }
00277
00278 static void dataflash_read_setup(struct workqueue_task *task);
00279 static void dataflash_write_setup(struct workqueue_task *task);
00280
00281 static void dataflash_page_done(struct workqueue_task *task)
00282 {
00283 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00284 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00285
00286 df_breq->breq.buf_list_done(&df_bdev->bdev, &df_breq->breq,
00287 &df_bdev->current_buf_list);
00288 df_breq->breq.bytes_xfered += df_bdev->transfer_pos;
00289 df_breq->remaining_blocks -=
00290 df_bdev->transfer_pos / DATAFLASH_BLOCK_SIZE;
00291 df_breq->lba += df_bdev->transfer_pos / DATAFLASH_BLOCK_SIZE;
00292 if (df_breq->remaining_blocks) {
00293 if (df_breq->operation == BLK_OP_READ)
00294 dataflash_read_setup(task);
00295 else
00296 dataflash_write_setup(task);
00297 } else {
00298 dbg_verbose("DataFlash: req done\n");
00299 at45_release(&df_bdev->at45d);
00300 df_breq->breq.status = STATUS_OK;
00301 df_breq->breq.req_done(df_breq->breq.bdev, &df_breq->breq);
00302 }
00303 }
00304
00305 static void dataflash_read_done(struct workqueue_task *task);
00306 static void dataflash_write_done(struct workqueue_task *task);
00307
00308 static void dataflash_transfer(struct workqueue_task *task)
00309 {
00310 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00311 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00312 struct buffer *buf;
00313 int next_pos;
00314 int end_pos;
00315 irqflags_t flags;
00316
00317 if (!slist_is_empty(&df_bdev->current_buf_list)) {
00318 df_breq->breq.buf_list_done(&df_bdev->bdev, &df_breq->breq,
00319 &df_bdev->current_buf_list);
00320 slist_init(&df_bdev->current_buf_list);
00321 }
00322
00323 flags = cpu_irq_save();
00324 if (slist_is_empty(&df_breq->breq.buf_list)) {
00325 dbg_verbose("DataFlash: sleep\n");
00326 df_breq->sleeping = true;
00327 cpu_irq_restore(flags);
00328 return;
00329 }
00330 cpu_irq_restore(flags);
00331
00332 next_pos = df_bdev->transfer_pos;
00333 end_pos = dataflash_get_remaining_page_size(df_breq);
00334 while (next_pos < end_pos) {
00335 flags = cpu_irq_save();
00336 if (slist_is_empty(&df_breq->breq.buf_list)) {
00337 cpu_irq_restore(flags);
00338 break;
00339 } else
00340 buf = buf_list_pop_head(&df_breq->breq.buf_list);
00341 cpu_irq_restore(flags);
00342 assert((next_pos + buf->len) <= end_pos);
00343 slist_insert_tail(&df_bdev->current_buf_list, &buf->node);
00344 next_pos += buf->len;
00345 }
00346
00347 df_bdev->transfer_pos = next_pos;
00348
00349 if (df_breq->operation == BLK_OP_READ) {
00350 if (next_pos == end_pos) {
00351 workqueue_task_set_work_func(&df_breq->task,
00352 dataflash_read_done);
00353 }
00354 at45_read_buf_list(&df_bdev->at45d, &df_bdev->current_buf_list);
00355 } else {
00356 if (next_pos == end_pos) {
00357 workqueue_task_set_work_func(&df_breq->task,
00358 dataflash_write_done);
00359 }
00360 at45_write_buf_list(&df_bdev->at45d, &df_bdev->current_buf_list);
00361 }
00362 }
00363
00364 static void dataflash_read_done(struct workqueue_task *task)
00365 {
00366 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00367 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00368
00369 at45_deselect(&df_bdev->at45d);
00370 dataflash_page_done(task);
00371 }
00372
00373 static void dataflash_read_setup(struct workqueue_task *task)
00374 {
00375 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00376 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00377
00378 workqueue_task_set_work_func(&df_breq->task, dataflash_transfer);
00379
00380 df_bdev->transfer_pos = 0;
00381
00382 at45_select(&df_bdev->at45d);
00383 at45_cmd_cont_array_read(&df_bdev->at45d, df_breq->lba >> 1,
00384 (df_breq->lba & 1) << 9);
00385 }
00386
00387 static void dataflash_write_wait(struct workqueue_task *task)
00388 {
00389 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00390 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00391 bool done;
00392
00393 done = at45_wait_ready(&df_bdev->at45d);
00394 if (!done) {
00395
00396 return;
00397 }
00398 dataflash_page_done(task);
00399 }
00400
00401 static void dataflash_write_wait_begin(struct workqueue_task *task)
00402 {
00403 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00404 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00405
00406 at45_deselect(&df_bdev->at45d);
00407 workqueue_task_set_work_func(&df_breq->task,
00408 dataflash_write_wait);
00409 dataflash_write_wait(task);
00410 }
00411
00412 static void dataflash_write_done(struct workqueue_task *task)
00413 {
00414 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00415 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00416
00417 workqueue_task_set_work_func(&df_breq->task,
00418 dataflash_write_wait_begin);
00419
00420 at45_deselect(&df_bdev->at45d);
00421 at45_select(&df_bdev->at45d);
00422 at45_cmd_buffer_1_main_memory_program_with_erase(&df_bdev->at45d,
00423 df_breq->lba >> 1);
00424 }
00425
00426 static void dataflash_write_ready(struct workqueue_task *task)
00427 {
00428 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00429 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00430
00431 workqueue_task_set_work_func(&df_breq->task, dataflash_transfer);
00432
00433 at45_select(&df_bdev->at45d);
00434 at45_cmd_buffer_1_write(&df_bdev->at45d, (df_breq->lba & 1) << 9);
00435 }
00436
00437 static void dataflash_write_buffered_wait(struct workqueue_task *task)
00438 {
00439 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00440 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00441 bool done;
00442
00443 done = at45_wait_ready(&df_bdev->at45d);
00444 if (!done) {
00445
00446 return;
00447 }
00448 dataflash_write_ready(task);
00449 }
00450
00451 static void dataflash_write_buffered(struct workqueue_task *task)
00452 {
00453 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00454 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00455
00456 at45_deselect(&df_bdev->at45d);
00457 workqueue_task_set_work_func(&df_breq->task,
00458 dataflash_write_buffered_wait);
00459 dataflash_write_buffered_wait(task);
00460 }
00461
00462 static void dataflash_write_setup(struct workqueue_task *task)
00463 {
00464 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00465 struct dataflash_bdev *df_bdev = dataflash_bdev_of(df_breq->breq.bdev);
00466
00467 workqueue_task_set_work_func(&df_breq->task, dataflash_write_buffered);
00468
00469 df_bdev->transfer_pos = 0;
00470
00471 if (dataflash_is_page_aligned(df_breq))
00472 dataflash_write_ready(task);
00473 else {
00474
00475
00476
00477 at45_select(&df_bdev->at45d);
00478 at45_cmd_main_memory_to_buffer_1_transfer(&df_bdev->at45d,
00479 df_breq->lba >> 1);
00480 }
00481 }
00482
00483 static void dataflash_start(struct workqueue_task *task)
00484 {
00485 struct dataflash_breq *df_breq = dataflash_breq_of_task(task);
00486
00487 switch (df_breq->operation) {
00488 case BLK_OP_READ:
00489 dbg_verbose("DataFlash: reading %ld blocks @ 0x%04lx ...\n",
00490 df_breq->remaining_blocks, df_breq->lba);
00491 dataflash_read_setup(task);
00492 break;
00493 case BLK_OP_WRITE:
00494 dbg_verbose("DataFlash: writing %ld blocks @ 0x%04lx ...\n",
00495 df_breq->remaining_blocks, df_breq->lba);
00496 dataflash_write_setup(task);
00497 break;
00498 default:
00499 unhandled_case(df_breq->operation);
00500 }
00501 }
00502
00504 static void dataflash_submit(struct block_device *bdev,
00505 struct block_request *breq)
00506 {
00507 struct dataflash_bdev *df_bdev = dataflash_bdev_of(bdev);
00508 struct dataflash_breq *df_breq = dataflash_breq_of(breq);
00509
00510 at45_request(&df_bdev->at45d, &df_breq->task);
00511 }
00512
00514 static int dataflash_submit_buf_list(struct block_device *bdev,
00515 struct block_request *breq, struct slist *buf_list)
00516 {
00517 struct dataflash_breq *df_breq = dataflash_breq_of(breq);
00518
00519 dbg_verbose("DataFlash: submit_buf_list\n");
00520 slist_move_to_tail(&breq->buf_list, buf_list);
00521 if (df_breq->sleeping) {
00522 dbg_verbose("DataFlash: wakeup\n");
00523 df_breq->sleeping = false;
00524 workqueue_add_task(&main_workqueue, &df_breq->task);
00525 }
00526
00527 return STATUS_OK;
00528 }
00529
00531 static void dataflash_prepare_req(struct block_device *bdev,
00532 struct block_request *breq,
00533 block_addr_t lba, block_len_t nr_blocks,
00534 enum block_operation operation)
00535 {
00536 struct dataflash_breq *df_breq = dataflash_breq_of(breq);
00537
00538 breq->status = OPERATION_IN_PROGRESS;
00539 breq->bytes_xfered = 0;
00540 workqueue_task_init(&df_breq->task, dataflash_start);
00541 df_breq->lba = lba;
00542 df_breq->remaining_blocks = nr_blocks;
00543 df_breq->operation = operation;
00544 df_breq->sleeping = false;
00545 }
00546
00548 static struct block_request *dataflash_alloc_req(struct block_device *bdev)
00549 {
00550 struct dataflash_bdev *df_bdev = dataflash_bdev_of(bdev);
00551 struct dataflash_breq *df_breq;
00552
00553 df_breq = mem_pool_alloc(&df_bdev->req_pool);
00554 if (!df_breq)
00555 return NULL;
00556
00557 slist_init(&df_breq->breq.buf_list);
00558 df_breq->breq.bdev = bdev;
00559 df_breq->breq.req_submit = dataflash_submit;
00560 df_breq->breq.req_submit_buf_list = dataflash_submit_buf_list;
00561
00562 return &df_breq->breq;
00563 }
00564
00566 static void dataflash_free_req(struct block_device *bdev,
00567 struct block_request *breq)
00568 {
00569 struct dataflash_bdev *df_bdev = dataflash_bdev_of(bdev);
00570 struct dataflash_breq *df_breq = dataflash_breq_of(breq);
00571
00572 mem_pool_free(&df_bdev->req_pool, df_breq);
00573 }
00574
00575 static inline struct dataflash_bdev *dataflash_bdev_of_task(
00576 struct workqueue_task *task)
00577 {
00578 return container_of(task, struct dataflash_bdev, task);
00579 }
00580
00586 static void dataflash_detect(struct workqueue_task *task)
00587 {
00588 struct dataflash_bdev *df_bdev = dataflash_bdev_of_task(task);
00589 bool done;
00590
00591 done = at45_identify(&df_bdev->at45d);
00592 if (!done) {
00593
00594
00595
00596 return;
00597 }
00598
00599 if (test_bit(AT45_FLAG_VALID, &df_bdev->at45d.flags)) {
00600 if (!test_bit(AT45_FLAG_PROTECTED, &df_bdev->at45d.flags))
00601 set_bit(BDEV_WRITEABLE, &df_bdev->bdev.flags);
00602
00603 blkdev_set_block_size(&df_bdev->bdev, DATAFLASH_BLOCK_SIZE);
00604 df_bdev->bdev.nr_blocks =
00605 df_bdev->at45d.size / DATAFLASH_BLOCK_SIZE;
00606 if (!dataflash_store_page_size(df_bdev,
00607 df_bdev->at45d.page_size))
00608 dbg_warning("DataFlash: Unsupported page size!\n");
00609 else
00610 set_bit(BDEV_PRESENT, &df_bdev->bdev.flags);
00611 }
00612
00613 workqueue_add_task(&main_workqueue, df_bdev->event_task);
00614 }
00615
00617
00634 struct block_device *dataflash_blkdev_init(spi_id_t spi_id,
00635 struct spi_master *master, struct spi_device *device,
00636 struct workqueue_task *event_task)
00637 {
00638 struct dataflash_bdev *df_bdev;
00639
00640 df_bdev = zalloc(sizeof(struct dataflash_bdev));
00641 if (!df_bdev)
00642 return NULL;
00643
00644 at45_device_init(&df_bdev->at45d, spi_id, master, device);
00645 df_bdev->bdev.prepare_req = dataflash_prepare_req;
00646 df_bdev->bdev.alloc_req = dataflash_alloc_req;
00647 df_bdev->bdev.free_req = dataflash_free_req;
00648 df_bdev->event_task = event_task;
00649 slist_init(&df_bdev->current_buf_list);
00650
00651 mem_pool_init_physmem(&df_bdev->req_pool, &cpu_sram_pool,
00652 4, sizeof(struct dataflash_breq), 2);
00653
00654
00655 workqueue_task_init(&df_bdev->task, dataflash_detect);
00656 at45_request(&df_bdev->at45d, &df_bdev->task);
00657
00658 return &df_bdev->bdev;
00659 }
00660