-
Notifications
You must be signed in to change notification settings - Fork 14
/
nand.c
135 lines (123 loc) · 3.89 KB
/
nand.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
* @file nand.c
* @author Andrew Loebs
* @brief "Glue" layer between dhara and spi_nand module
*
*/
#include "nand.h"
#include <stdbool.h>
#include "../modules/spi_nand.h"
// public function definitions
int dhara_nand_is_bad(const struct dhara_nand *n, dhara_block_t b)
{
// construct row address
row_address_t row = {.block = b, .page = 0};
// call spi_nand layer for block status
bool is_bad;
int ret = spi_nand_block_is_bad(row, &is_bad);
if (SPI_NAND_RET_OK != ret) {
// if we get a bad return, we'll just call this block bad
is_bad = true;
}
return (int)is_bad;
}
void dhara_nand_mark_bad(const struct dhara_nand *n, dhara_block_t b)
{
// construct row address
row_address_t row = {.block = b, .page = 0};
// call spi_nand layer
spi_nand_block_mark_bad(row); // ignore ret
}
int dhara_nand_erase(const struct dhara_nand *n, dhara_block_t b, dhara_error_t *err)
{
// construct row address
row_address_t row = {.block = b, .page = 0};
// call spi_nand layer
int ret = spi_nand_block_erase(row);
if (SPI_NAND_RET_OK == ret) { // success
return 0;
}
else if (SPI_NAND_RET_E_FAIL == ret) { // failed internally on nand
*err = DHARA_E_BAD_BLOCK;
return -1;
}
else { // failed for some other reason
return -1;
}
}
int dhara_nand_prog(const struct dhara_nand *n, dhara_page_t p, const uint8_t *data,
dhara_error_t *err)
{
// construct row address -- dhara's page address is identical to an MT29F row address
row_address_t row = {.whole = p};
// call spi_nand layer
int ret = spi_nand_page_program(row, 0, data, SPI_NAND_PAGE_SIZE);
if (SPI_NAND_RET_OK == ret) { // success
return 0;
}
else if (SPI_NAND_RET_P_FAIL == ret) { // failed internally on nand
*err = DHARA_E_BAD_BLOCK;
return -1;
}
else { // failed for some other reason
return -1;
}
}
int dhara_nand_is_free(const struct dhara_nand *n, dhara_page_t p)
{
// construct row address -- dhara's page address is identical to an MT29F row address
row_address_t row = {.whole = p};
// call spi_nand layer
bool is_free;
int ret = spi_nand_page_is_free(row, &is_free);
if (SPI_NAND_RET_OK != ret) {
// if we get a bad return, we'll report the page as "not free"
is_free = true;
}
return (int)is_free;
}
int dhara_nand_read(const struct dhara_nand *n, dhara_page_t p, size_t offset, size_t length,
uint8_t *data, dhara_error_t *err)
{
// construct row address -- dhara's page address is identical to an MT29F row address
row_address_t row = {.whole = p};
// call spi_nand layer
int ret = spi_nand_page_read(row, offset, data, length);
if (SPI_NAND_RET_OK == ret) { // success
return 0;
}
else if (SPI_NAND_RET_ECC_ERR == ret) { // ECC failure
*err = DHARA_E_ECC;
return -1;
}
else { // failed for some other reason
return -1;
}
}
/* Read a page from one location and reprogram it in another location.
* This might be done using the chip's internal buffers, but it must use
* ECC.
*/
int dhara_nand_copy(const struct dhara_nand *n, dhara_page_t src, dhara_page_t dst,
dhara_error_t *err)
{
// construct row addresses -- dhara's page address is identical to an MT29F row address
row_address_t source = {.whole = src};
row_address_t dest = {.whole = dst};
// call spi_nand layer
int ret = spi_nand_page_copy(source, dest);
if (SPI_NAND_RET_OK == ret) { // success
return 0;
}
else if (SPI_NAND_RET_ECC_ERR == ret) { // ECC failure on read
*err = DHARA_E_ECC;
return -1;
}
else if (SPI_NAND_RET_P_FAIL == ret) { // program failure
*err = DHARA_E_BAD_BLOCK;
return -1;
}
else { // failed for some other reason
return -1;
}
}