27#define MODNAME "flash"
28#define M_PRINTF(format, args...) \
29 printf(MODNAME ": " format, ## args)
33#define FLASH_ID_64MBIT 0xe6
34#define FLASH_ID_128MBIT 0x73
35#define FLASH_ID_256MBIT 0x75
36#define FLASH_ID_512MBIT 0x76
37#define FLASH_ID_1024MBIT 0x79
40#define SM_CMD_READ1 0x00
41#define SM_CMD_READ2 0x01
42#define SM_CMD_READ3 0x50
43#define SM_CMD_RESET 0xff
44#define SM_CMD_WRITEDATA 0x80
45#define SM_CMD_PROGRAMPAGE 0x10
46#define SM_CMD_ERASEBLOCK 0x60
47#define SM_CMD_ERASECONFIRM 0xd0
48#define SM_CMD_GETSTATUS 0x70
49#define SM_CMD_READID 0x90
52 { FLASH_ID_64MBIT, 64, 528, 16, 1024 },
53 { FLASH_ID_128MBIT, 128, 528, 32, 1024 },
54 { FLASH_ID_256MBIT, 256, 528, 32, 2048 },
55 { FLASH_ID_512MBIT, 512, 528, 32, 4096 },
56 { FLASH_ID_1024MBIT, 1024, 528, 32, 8192 }
58#define NUM_DEVICES (sizeof(devices)/sizeof(flash_info_t))
61static u32 timeout_cb(
void *);
65int _start(
int argc,
char *argv[])
70 if (flash_detect() < 0)
71 return MODULE_NO_RESIDENT_END;
73 return (RegisterLibraryEntries(&_exp_fls) != 0) ? MODULE_NO_RESIDENT_END : MODULE_RESIDENT_END;
83 if ((DEV9_REG(DEV9_R_REV) & 0xf0) != DEV9_DEV9C_9611) {
84 M_PRINTF(
"CXD9611 required for flash interface.\n");
89 if ((rev = SPD_REG16(SPD_R_REV_3)) & SPD_CAPS_FLASH) {
90 M_PRINTF(
"Detected flash (rev3 0x%02x).\n", rev);
94 M_PRINTF(
"No flash detected (rev3 0x%02x).\n", rev);
99int flash_device_reset(
void)
102 u32 has_timedout = 0;
104 SPD_REG16(0x480c) = 0x100;
105 SPD_REG16(0x4804) = SM_CMD_RESET;
106 (void)(SPD_REG16(0x480c));
107 (void)(SPD_REG16(0x480c));
109 SetAlarm(&timeout, (
void *)timeout_cb, &has_timedout);
111 while ((SPD_REG16(0x480c) & 0x01) == 0) {
113 if (SPD_REG16(0x480c) & 0x01)
116 M_PRINTF(
"Device erase: timed out.\n");
121 CancelAlarm((
void *)timeout_cb, &has_timedout);
123 SPD_REG16(0x4804) = SM_CMD_GETSTATUS;
124 if (SPD_REG16(0x4814) & 0x01) {
125 M_PRINTF(
"Device erase: status error.\n");
129 SPD_REG16(0x480c) = 0;
140 SPD_REG16(0x480c) = 0x100;
141 SPD_REG16(0x4804) = SM_CMD_READID;
142 SPD_REG16(0x4808) = 0;
143 (void)(SPD_REG16(0x480c));
144 (void)(SPD_REG16(0x4814));
145 id = SPD_REG16(0x4814);
146 SPD_REG16(0x480c) = 0;
150 for (i = 0; (u32)i < NUM_DEVICES; i++) {
151 if (
id != devices[i].
id)
155 M_PRINTF(
"Device: ID 0x%02x, %ld Mbit, %ld bytes/page, %ld pages/block, %ld blocks total.\n",
164static void flash_set_page(u32
id, u32 pageofs)
169 case FLASH_ID_64MBIT:
170 SPD_REG16(0x4808) = ((pageofs >> 9) & 0xff) | 0x100;
171 SPD_REG16(0x4808) = ((pageofs >> 17) & 0x3f);
173 case FLASH_ID_128MBIT:
174 SPD_REG16(0x4808) = ((pageofs >> 9) & 0xff) | 0x100;
175 SPD_REG16(0x4808) = ((pageofs >> 17) & 0x7f);
177 case FLASH_ID_256MBIT:
178 SPD_REG16(0x4808) = ((pageofs >> 9) & 0xff) | 0x100;
179 SPD_REG16(0x4808) = ((pageofs >> 17) & 0xff);
181 case FLASH_ID_512MBIT:
182 SPD_REG16(0x4808) = ((pageofs >> 17) & 0xff) | 0x100;
183 SPD_REG16(0x4808) = ((pageofs >> 25) & 0x01);
185 case FLASH_ID_1024MBIT:
186 SPD_REG16(0x4808) = ((pageofs >> 17) & 0xff) | 0x100;
187 SPD_REG16(0x4808) = ((pageofs >> 25) & 0x02);
196 u32 pageofs = page * 512;
197 u32 has_timedout = 0;
199 SPD_REG16(0x480c) = 0x180;
200 SPD_REG16(0x4804) = SM_CMD_ERASEBLOCK;
202 flash_set_page(
info->id, pageofs);
204 SPD_REG16(0x4804) = SM_CMD_ERASECONFIRM;
205 (void)(SPD_REG16(0x480c));
206 (void)(SPD_REG16(0x480c));
208 SetAlarm(&timeout, (
void *)timeout_cb, &has_timedout);
210 while ((SPD_REG16(0x480c) & 0x01) == 0) {
212 if (SPD_REG16(0x480c) & 0x01)
215 M_PRINTF(
"Page erase: timed out.\n");
220 CancelAlarm((
void *)timeout_cb, &has_timedout);
222 SPD_REG16(0x4804) = SM_CMD_GETSTATUS;
223 if (SPD_REG16(0x4814) & 0x01) {
224 M_PRINTF(
"Page erase: status error.\n");
228 SPD_REG16(0x480c) = 0;
245 u32 byteofs, pageofs = page * 512;
249 if (
info->page_bytes == 512)
252 SPD_REG16(0x480c) = func;
254 if (
info->page_bytes == 16) {
255 SPD_REG16(0x4804) = SM_CMD_READ3;
256 byteofs = pageofs & 0x0f;
258 SPD_REG16(0x4804) = SM_CMD_READ1;
259 byteofs = pageofs & 0x1ff;
262 SPD_REG16(0x4808) = (byteofs & 0xff) | 0x100;
264 flash_set_page(
info->id, pageofs);
269 for (i = 0; (u32)i <
count; i++) {
270 (void)(SPD_REG16(0x480c));
271 (void)(SPD_REG16(0x480c));
274 SetAlarm(&timeout, (
void *)timeout_cb, &has_timedout);
276 while ((SPD_REG16(0x480c) & 0x01) == 0) {
278 if (SPD_REG16(0x480c) & 0x01)
281 M_PRINTF(
"Page read: timed out.\n");
286 CancelAlarm((
void *)timeout_cb, &has_timedout);
288 SPD_REG16(0x480c) = func | 0x800;
292 for (j = 0; (u32)j < (
info->page_bytes / 4); j++)
293 *buf_w++ = SPD_REG32(0x4800);
296 for (j = (byteofs + (byteofs >> 31)) / 2; (u32)j < (
info->page_bytes / 2); j++)
297 *buf_h++ = SPD_REG16(0x4800);
301 SPD_REG16(0x480c) = func;
304 SPD_REG16(0x480c) = 0;
316 u32 pageofs = page * 512;
317 u32 has_timedout = 0;
319 SPD_REG16(0x480c) = 0x180;
320 SPD_REG16(0x4804) = SM_CMD_WRITEDATA;
322 SPD_REG16(0x4808) = 0x100;
323 flash_set_page(
info->id, pageofs);
325 for (i = 0; (u32)i < (
info->page_bytes / 2); i++)
326 SPD_REG16(0x4800) = *buf_h++;
328 SPD_REG16(0x4804) = SM_CMD_PROGRAMPAGE;
329 (void)(SPD_REG16(0x480c));
330 (void)(SPD_REG16(0x480c));
332 SetAlarm(&timeout, (
void *)timeout_cb, &has_timedout);
334 while ((SPD_REG16(0x480c) & 0x01) == 0) {
336 if (SPD_REG16(0x480c) & 0x01)
339 M_PRINTF(
"Page write: timed out.\n");
344 CancelAlarm((
void *)timeout_cb, &has_timedout);
346 SPD_REG16(0x4804) = SM_CMD_GETSTATUS;
347 if (SPD_REG16(0x4814) & 0x01) {
348 M_PRINTF(
"Page write: status error.\n");
352 SPD_REG16(0x480c) = 0;
356static u32 timeout_cb(
void *arg)
358 u32 *has_timedout = (u32 *)arg;
u32 count
start sector of fragmented bd/file