comparison src/cs/drivers/drv_app/ffs/board/intelsbdrv.c @ 0:945cf7f506b2

src/cs: chipsetsw import from tcs211-fcmodem binary blobs and LCD demo files have been excluded, all line endings are LF only
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 25 Sep 2016 22:50:11 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:945cf7f506b2
1 /******************************************************************************
2 * Flash File System (ffs)
3 * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
4 *
5 * FFS AMD single bank low level flash driver RAM code
6 *
7 * $Id: intelsbdrv.c 1.13 Thu, 08 Jan 2004 15:05:23 +0100 tsj $
8 *
9 ******************************************************************************/
10
11 #include "ffs.cfg"
12
13 #include "ffs/ffs.h"
14 #include "ffs/board/drv.h"
15 #include "ffs/board/ffstrace.h"
16
17
18 #define INTEL_UNLOCK_SLOW 1
19
20
21 #undef tlw
22 #define tlw(contents)
23 #undef ttw
24 #define ttw(contents)
25
26 // Status bits for Intel flash memory devices
27 #define INTEL_STATE_MACHINE_DONE (1<<7)
28 #define FLASH_READ(addr) (*(volatile uint16 *) (addr))
29 #define FLASH_WRITE(addr, data) (*(volatile uint16 *) (addr)) = data
30
31 asm(" .label _ffsdrv_ram_intel_begin");
32 asm(" .def _ffsdrv_ram_intel_begin");
33
34 uint32 intel_int_disable(void);
35 void intel_int_enable(uint32 tmp);
36
37 /******************************************************************************
38 * INTEL Single Bank Driver Functions
39 ******************************************************************************/
40 // Actually we should have disabled and enable the interrupts in this
41 // function, but when the interrupt functions are used Target don't run!
42 // Anyway, currently the interrupts are already disabled at this point thus
43 // it does not cause any problems.
44 int ffsdrv_ram_intel_sb_init(void)
45 {
46 uint32 cpsr, i;
47 volatile char *addr;
48 uint16 status;
49
50 for (i = 0; i < dev.numblocks; i++)
51 {
52 addr = block2addr(i);
53
54 *addr = 0x50; // Intel Clear Status Register
55 *addr = 0xFF; // Intel read array
56
57 *addr = 0x60; // Intel Config Setup
58 *addr = 0xD0; // Intel Unlock Block
59
60 // Wait for unlock to finish
61 do {
62 status = FLASH_READ(addr);
63 } while (!(status & INTEL_STATE_MACHINE_DONE));
64
65 *addr = 0x70; // Intel Read Status Register
66 status = FLASH_READ(addr);
67
68 // Is there an erase suspended?
69 if ((status & 0x40) != 0) {
70 *addr = 0xD0; // Intel erase resume
71
72 *addr = 0x70; // Intel Read Status Register
73 // wait for erase to finish
74 do {
75 status = FLASH_READ(addr);
76 } while (!(status & INTEL_STATE_MACHINE_DONE));
77 }
78
79 *addr = 0xFF; // Intel Read Array
80 }
81
82 return 0;
83 }
84
85 void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value)
86 {
87 uint32 cpsr;
88
89 ttw(ttr(TTrDrv, "wh(%x,%x)" NL, addr, value));
90
91 if (~*addr & value) {
92 ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
93 return;
94 }
95
96 cpsr = intel_int_disable();
97 tlw(led_on(LED_WRITE));
98
99 #if (INTEL_UNLOCK_SLOW == 1)
100 *addr = 0x60; // Intel Config Setup
101 *addr = 0xD0; // Intel Unlock Block
102 #endif
103
104 *addr = 0x50; // Intel Clear Status Register
105 *addr = 0x40; // Intel program byte/word
106 *addr = value;
107 while ((*addr & 0x80) == 0)
108 ;
109 *addr = 0xFF; // Intel read array
110 tlw(led_off(LED_WRITE));
111 intel_int_enable(cpsr);
112 }
113
114 void ffsdrv_ram_intel_sb_erase(uint8 block)
115 {
116 volatile char *addr;
117 uint32 cpsr;
118 uint16 poll;
119
120 ttw(ttr(TTrDrvEra, "e(%d)" NL, block));
121
122 addr = block2addr(block);
123
124 cpsr = intel_int_disable();
125 tlw(led_on(LED_ERASE));
126
127 #if (INTEL_UNLOCK_SLOW == 1)
128 *addr = 0x60; // Intel Config Setup
129 *addr = 0xD0; // Intel Unlock Block
130 #endif
131
132 *addr = 0x50; // Intel Clear Status Register
133 *addr = 0x20; // Intel Erase Setup
134 *addr = 0xD0; // Intel Erase Confirm
135 *addr = 0x70; // Intel Read Status Register
136
137 // Wait for erase to finish.
138 while ((*addr & 0x80) == 0) {
139 tlw(led_toggle(LED_ERASE));
140 // Poll interrupts, taking interrupt mask into account.
141 if (INT_REQUESTED)
142 {
143 // 1. suspend erase
144 // 2. enable interrupts
145 // .. now the interrupt code executes
146 // 3. disable interrupts
147 // 4. resume erase
148
149 tlw(led_on(LED_ERASE_SUSPEND));
150
151 *addr = 0xB0; // Intel Erase Suspend
152 *addr = 0x70; // Intel Read Status Register
153 while (((poll = *addr) & 0x80) == 0)
154 ;
155
156 // If erase is complete, exit immediately
157 if ((poll & 0x40) == 0)
158 break;
159
160 *addr = 0xFF; // Intel read array
161
162 tlw(led_off(LED_ERASE_SUSPEND));
163 intel_int_enable(cpsr);
164
165 // Other interrupts and tasks run now...
166
167 cpsr = intel_int_disable();
168 tlw(led_on(LED_ERASE_SUSPEND));
169
170 *addr = 0xD0; // Intel erase resume
171 // The following "extra" Read Status command is required because Intel has
172 // changed the specification of the W30 flash! (See "1.8 Volt Intel®
173 // Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30, 28F320W30
174 // Specification Update")
175 *addr = 0x70; // Intel Read Status Register
176
177 tlw(led_off(LED_ERASE_SUSPEND));
178 }
179 }
180 *addr = 0xFF; // Intel read array
181
182 tlw(led_on(LED_ERASE));
183 tlw(led_off(LED_ERASE));
184 intel_int_enable(cpsr);
185 }
186
187 // TODO: remove below function, not in use anymore.
188 void ffsdrv_ram_intel_erase(uint8 block)
189 {
190 uint32 cpsr;
191 uint16 status;
192
193 ttw(ttr(TTrDrvErase, "e(%d)" NL, block));
194 tlw(led_on(LED_ERASE));
195
196 dev.addr = (uint16 *) block2addr(block);
197
198 cpsr = intel_int_disable();
199 dev.state = DEV_ERASE;
200
201 *dev.addr = 0x60; // Intel Config setup
202 *dev.addr = 0xD0; // Intel Unlock block
203
204 *dev.addr = 0x50; // Intel clear status register (not really necessary)
205 *dev.addr = 0x20; // Intel erase setup
206 *dev.addr = 0xD0; // Intel erase confirm
207
208 intel_int_enable(cpsr);
209
210 while ((*dev.addr & 0x80) == 0)
211 ;
212
213 *dev.addr = 0xFF; // Intel read array
214 dev.state = DEV_READ;
215 tlw(led_off(LED_WRITE));
216 }
217
218
219 /******************************************************************************
220 * Interrupt Enable/Disable
221 ******************************************************************************/
222
223 uint32 intel_int_disable(void)
224 {
225 asm(" .state16");
226 asm(" mov A1, #0xC0");
227 asm(" ldr A2, tct_intel_disable");
228 asm(" bx A2 ");
229
230 asm("tct_intel_disable .field _TCT_Control_Interrupts+0,32");
231 asm(" .global _TCT_Control_Interrupts");
232 }
233
234 void intel_int_enable(uint32 cpsr)
235 {
236 asm(" .state16");
237 asm(" ldr A2, tct_intel_enable");
238 asm(" bx A2 ");
239
240 asm("tct_intel_enable .field _TCT_Control_Interrupts+0,32");
241 asm(" .global _TCT_Control_Interrupts");
242 }
243
244 // Even though we have this end label, we cannot determine the number of
245 // constant/PC-relative data following the code!
246 asm(" .state32");
247 asm(" .label _ffsdrv_ram_intel_end");
248 asm(" .def _ffsdrv_ram_intel_end");