summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorJames Buren <braewoods+rb@braewoods.net>2020-10-29 02:11:29 +0000
committerWilliam Wilgus <me.theuser@yahoo.com>2020-10-29 05:30:28 +0000
commitf65e4104970b17cd9a69618da1997c5e523bef82 (patch)
tree6695bc8e4adb96b2580fca662017d144df87d5b2 /apps
parentc5c17fa7995c62267a1695e58841bd17b9fb2099 (diff)
downloadrockbox-f65e4104970b17cd9a69618da1997c5e523bef82.tar.gz
rockbox-f65e4104970b17cd9a69618da1997c5e523bef82.zip
iriver_flash: rewrite how the flash commands wait for the ROM
This uses the toggle bit method referenced in the datasheets for the supported ROM chips and moves the code to a reusable subroutine. It also introduces a short delay to give the bus a chance to recover. The older ROM datasheet doesn't mention this delay as necessary but the newer one does so it now does this for both. Change-Id: Ie9dc8833bbd3ee545072b0c724ab220d13208d3d
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/iriver_flash.c54
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 */
70bool cfi_read_id(uint8_t* pManufacturerID, uint8_t* pDeviceID) 70static 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 */
103static 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 */
104bool cfi_erase_sector(volatile uint16_t* pAddr) 128static 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 */
124static inline bool cfi_program_word(volatile uint16_t* pAddr, uint16_t data) 141static 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 */
146bool cfi_get_flash_info(struct flash_info* pInfo) 152bool cfi_get_flash_info(struct flash_info* pInfo)
147{ 153{