diff options
-rw-r--r-- | apps/plugins/iriver_flash.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/apps/plugins/iriver_flash.c b/apps/plugins/iriver_flash.c index 2921ca0501..37bb3b3847 100644 --- a/apps/plugins/iriver_flash.c +++ b/apps/plugins/iriver_flash.c | |||
@@ -67,7 +67,7 @@ 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 | bool cfi_read_id(uint8_t* pManufacturerID, uint8_t* pDeviceID) | 70 | static bool cfi_read_id(uint8_t* pManufacturerID, uint8_t* pDeviceID) |
71 | { | 71 | { |
72 | uint8_t not_manu, not_id; /* read values before switching to ID mode */ | 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 */ | 73 | uint8_t manu, id; /* read values when in ID mode */ |
@@ -99,12 +99,34 @@ bool cfi_read_id(uint8_t* pManufacturerID, uint8_t* pDeviceID) | |||
99 | return false; /* fail */ | 99 | return false; /* fail */ |
100 | } | 100 | } |
101 | 101 | ||
102 | /* wait until the rom signals completion of an operation */ | ||
103 | static bool cfi_wait_for_rom(volatile uint16_t* pAddr) | ||
104 | { | ||
105 | const unsigned MAX_TIMEOUT = 0xffffff; /* should be sufficient for most targets */ | ||
106 | const unsigned RECOVERY_TIME = 64; /* based on 140MHz MCF 5249 */ | ||
107 | uint16_t old_data = *pAddr & 0x0040; /* we only want DQ6 */ | ||
108 | volatile unsigned i; /* disables certain optimizations */ | ||
109 | |||
110 | /* repeat up to MAX_TIMEOUT times or until DQ6 stops flipping */ | ||
111 | for (i = 0; i < MAX_TIMEOUT; i++) | ||
112 | { | ||
113 | uint16_t new_data = *pAddr & 0x0040; /* we only want DQ6 */ | ||
114 | if(old_data == new_data) | ||
115 | break; | ||
116 | old_data = new_data; | ||
117 | } | ||
118 | |||
119 | bool result = i != MAX_TIMEOUT; | ||
120 | |||
121 | /* delay at least 1us to give the bus time to recover */ | ||
122 | for (i = 0; i < RECOVERY_TIME; i++); | ||
123 | |||
124 | return result; | ||
125 | } | ||
102 | 126 | ||
103 | /* erase the sector which contains the given address */ | 127 | /* erase the sector which contains the given address */ |
104 | bool cfi_erase_sector(volatile uint16_t* pAddr) | 128 | static bool cfi_erase_sector(volatile uint16_t* pAddr) |
105 | { | 129 | { |
106 | unsigned timeout = 430000; /* the timeout loop should be no less than 25ms */ | ||
107 | |||
108 | FB[0x5555] = 0xAA; /* enter command mode */ | 130 | FB[0x5555] = 0xAA; /* enter command mode */ |
109 | FB[0x2AAA] = 0x55; | 131 | FB[0x2AAA] = 0x55; |
110 | FB[0x5555] = 0x80; /* erase command */ | 132 | FB[0x5555] = 0x80; /* erase command */ |
@@ -112,36 +134,20 @@ bool cfi_erase_sector(volatile uint16_t* pAddr) | |||
112 | FB[0x2AAA] = 0x55; | 134 | FB[0x2AAA] = 0x55; |
113 | *pAddr = 0x30; /* erase the sector */ | 135 | *pAddr = 0x30; /* erase the sector */ |
114 | 136 | ||
115 | /* I counted 7 instructions for this loop -> min. 0.58 us per round */ | 137 | return cfi_wait_for_rom(pAddr); |
116 | /* Plus memory waitstates it will be much more, gives margin */ | ||
117 | while (*pAddr != 0xFFFF && --timeout); /* poll for erased */ | ||
118 | |||
119 | return (timeout != 0); | ||
120 | } | 138 | } |
121 | 139 | ||
122 | |||
123 | /* address must be in an erased location */ | 140 | /* address must be in an erased location */ |
124 | static inline bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) | 141 | static bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) |
125 | { | 142 | { |
126 | unsigned timeout = 85; /* the timeout loop should be no less than 20us */ | ||
127 | |||
128 | if (~*pAddr & data) /* just a safety feature, not really necessary */ | ||
129 | return false; /* can't set any bit from 0 to 1 */ | ||
130 | |||
131 | FB[0x5555] = 0xAA; /* enter command mode */ | 143 | FB[0x5555] = 0xAA; /* enter command mode */ |
132 | FB[0x2AAA] = 0x55; | 144 | FB[0x2AAA] = 0x55; |
133 | FB[0x5555] = 0xA0; /* byte program command */ | 145 | FB[0x5555] = 0xA0; /* byte program command */ |
146 | *pAddr = data; /* write the word data */ | ||
134 | 147 | ||
135 | *pAddr = data; | 148 | return cfi_wait_for_rom(pAddr); |
136 | |||
137 | /* I counted 7 instructions for this loop -> min. 0.58 us per round */ | ||
138 | /* Plus memory waitstates it will be much more, gives margin */ | ||
139 | while (*pAddr != data && --timeout); /* poll for programmed */ | ||
140 | |||
141 | return (timeout != 0); | ||
142 | } | 149 | } |
143 | 150 | ||
144 | |||
145 | /* this returns true if supported and fills the info struct */ | 151 | /* this returns true if supported and fills the info struct */ |
146 | bool cfi_get_flash_info(struct flash_info* pInfo) | 152 | bool cfi_get_flash_info(struct flash_info* pInfo) |
147 | { | 153 | { |