diff options
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/iriver_flash.c | 104 |
1 files changed, 38 insertions, 66 deletions
diff --git a/apps/plugins/iriver_flash.c b/apps/plugins/iriver_flash.c index 37bb3b3847..e33e422d01 100644 --- a/apps/plugins/iriver_flash.c +++ b/apps/plugins/iriver_flash.c | |||
@@ -49,9 +49,9 @@ ssize_t audiobuf_size; | |||
49 | 49 | ||
50 | struct flash_info | 50 | struct flash_info |
51 | { | 51 | { |
52 | uint8_t manufacturer; | 52 | uint16_t manufacturer; |
53 | uint8_t id; | 53 | uint16_t id; |
54 | int size; | 54 | uint32_t size; |
55 | char name[32]; | 55 | char name[32]; |
56 | }; | 56 | }; |
57 | 57 | ||
@@ -67,36 +67,20 @@ static volatile uint16_t* FB = (uint16_t*)0x00000000; /* Flash base address */ | |||
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | /* read the manufacturer and device ID */ | 69 | /* read the manufacturer and device ID */ |
70 | static bool cfi_read_id(uint8_t* pManufacturerID, uint8_t* pDeviceID) | 70 | static void cfi_read_id(struct flash_info* pInfo) |
71 | { | 71 | { |
72 | uint8_t not_manu, not_id; /* read values before switching to ID mode */ | ||
73 | uint8_t manu, id; /* read values when in ID mode */ | ||
74 | |||
75 | /* read the normal content */ | ||
76 | not_manu = FB[0]; /* should be 'A' (0x41) and 'R' (0x52) */ | ||
77 | not_id = FB[1]; /* from the "ARCH" marker */ | ||
78 | |||
79 | FB[0x5555] = 0xAA; /* enter command mode */ | 72 | FB[0x5555] = 0xAA; /* enter command mode */ |
80 | FB[0x2AAA] = 0x55; | 73 | FB[0x2AAA] = 0x55; |
81 | FB[0x5555] = 0x90; /* ID command */ | 74 | FB[0x5555] = 0x90; /* enter ID mode */ |
82 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ | 75 | rb->sleep(HZ/100); /* we only need to sleep 150ns but 10ms is the minimum */ |
83 | 76 | ||
84 | manu = FB[0]; | 77 | pInfo->manufacturer = FB[0]; |
85 | id = FB[1]; | 78 | pInfo->id = FB[1]; |
86 | 79 | ||
87 | FB[0] = 0xF0; /* reset flash (back to normal read mode) */ | 80 | FB[0x5555] = 0xAA; /* enter command mode */ |
88 | rb->sleep(HZ/50); /* Atmel wants 20ms pause here */ | 81 | FB[0x2AAA] = 0x55; |
89 | 82 | FB[0x5555] = 0xF0; /* exit ID mode */ | |
90 | /* I assume success if the obtained values are different from | 83 | rb->sleep(HZ/100); /* we only need to sleep 150ns but 10ms is the minimum */ |
91 | the normal flash content. This is not perfectly bulletproof, they | ||
92 | could theoretically be the same by chance, causing us to fail. */ | ||
93 | if (not_manu != manu || not_id != id) /* a value has changed */ | ||
94 | { | ||
95 | *pManufacturerID = manu; /* return the results */ | ||
96 | *pDeviceID = id; | ||
97 | return true; /* success */ | ||
98 | } | ||
99 | return false; /* fail */ | ||
100 | } | 84 | } |
101 | 85 | ||
102 | /* wait until the rom signals completion of an operation */ | 86 | /* wait until the rom signals completion of an operation */ |
@@ -148,44 +132,34 @@ static bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) | |||
148 | return cfi_wait_for_rom(pAddr); | 132 | return cfi_wait_for_rom(pAddr); |
149 | } | 133 | } |
150 | 134 | ||
151 | /* this returns true if supported and fills the info struct */ | 135 | /* fills in the struct with data about the flash rom */ |
152 | bool cfi_get_flash_info(struct flash_info* pInfo) | 136 | static void cfi_get_flash_info(struct flash_info* pInfo) |
153 | { | 137 | { |
154 | rb->memset(pInfo, 0, sizeof(struct flash_info)); | 138 | uint32_t size = 0; |
139 | const char* name = ""; | ||
155 | 140 | ||
156 | if (!cfi_read_id(&pInfo->manufacturer, &pInfo->id)) | 141 | cfi_read_id(pInfo); |
157 | return false; | ||
158 | 142 | ||
159 | if (pInfo->manufacturer == 0xBF) /* SST */ | 143 | switch (pInfo->manufacturer) |
160 | { | 144 | { |
161 | if (pInfo->id == 0xD6) | 145 | /* SST */ |
162 | { | 146 | case 0x00BF: |
163 | pInfo->size = 256* 1024; /* 256k */ | 147 | switch (pInfo->id) |
164 | rb->strcpy(pInfo->name, "SST39VF020"); | 148 | { |
165 | return true; | 149 | case 0x2782: |
166 | } | 150 | size = 2048 * 1024; /* 2 MiB */ |
167 | else if (pInfo->id == 0xD7) | 151 | name = "SST39VF160"; |
168 | { | 152 | break; |
169 | pInfo->size = 512* 1024; /* 512k */ | 153 | case 0x235B: |
170 | rb->strcpy(pInfo->name, "SST39VF040"); | 154 | size = 4096 * 1024; /* 4 MiB */ |
171 | return true; | 155 | name = "SST39VF3201"; |
172 | } | 156 | break; |
173 | else if (pInfo->id == 0x82) | 157 | } |
174 | { | 158 | break; |
175 | pInfo->size = 2048* 1024; /* 2 MiB */ | ||
176 | rb->strcpy(pInfo->name, "SST39VF160"); | ||
177 | return true; | ||
178 | } | ||
179 | else if (pInfo->id == 0x5B) | ||
180 | { | ||
181 | pInfo->size = 4096* 1024; /* 4 MiB */ | ||
182 | rb->strcpy(pInfo->name, "SST39VF3201"); | ||
183 | return true; | ||
184 | } | ||
185 | else | ||
186 | return false; | ||
187 | } | 159 | } |
188 | return false; | 160 | |
161 | pInfo->size = size; | ||
162 | rb->strcpy(pInfo->name, name); | ||
189 | } | 163 | } |
190 | 164 | ||
191 | /***************** User Interface Functions *****************/ | 165 | /***************** User Interface Functions *****************/ |
@@ -206,25 +180,23 @@ void ShowFlashInfo(struct flash_info* pInfo) | |||
206 | { | 180 | { |
207 | if (!pInfo->manufacturer) | 181 | if (!pInfo->manufacturer) |
208 | { | 182 | { |
209 | rb->lcd_puts(0, 0, "Flash: M=?? D=??"); | 183 | rb->lcd_puts(0, 0, "Flash: M=???? D=????"); |
210 | rb->lcd_puts(0, 1, "Impossible to program"); | 184 | rb->lcd_puts(0, 1, "Impossible to program"); |
211 | } | 185 | } |
212 | else | 186 | else |
213 | { | 187 | { |
214 | rb->lcd_putsf(0, 0, "Flash: M=%02x D=%02x", | 188 | rb->lcd_putsf(0, 0, "Flash: M=%04x D=%04x", |
215 | pInfo->manufacturer, pInfo->id); | 189 | pInfo->manufacturer, pInfo->id); |
216 | 190 | ||
217 | |||
218 | if (pInfo->size) | 191 | if (pInfo->size) |
219 | { | 192 | { |
220 | rb->lcd_puts(0, 1, pInfo->name); | 193 | rb->lcd_puts(0, 1, pInfo->name); |
221 | rb->lcd_putsf(0, 2, "Size: %d KB", pInfo->size / 1024); | 194 | rb->lcd_putsf(0, 2, "Size: %u KB", pInfo->size / 1024); |
222 | } | 195 | } |
223 | else | 196 | else |
224 | { | 197 | { |
225 | rb->lcd_puts(0, 1, "Unsupported chip"); | 198 | rb->lcd_puts(0, 1, "Unsupported chip"); |
226 | } | 199 | } |
227 | |||
228 | } | 200 | } |
229 | 201 | ||
230 | rb->lcd_update(); | 202 | rb->lcd_update(); |