2 * Copyright © 2009 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 #include "at45db161d.h"
22 #define FLASH_CS_INDEX 1
24 __xdata uint8_t ao_flash_mutex;
26 #define ao_flash_delay() do { \
32 void ao_flash_cs_low(void)
39 void ao_flash_cs_high(void)
46 struct ao_flash_instruction {
49 } __xdata ao_flash_instruction;
52 ao_flash_set_pagesize_512(void)
55 ao_flash_instruction.instruction = FLASH_SET_CONFIG;
56 ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0;
57 ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1;
58 ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2;
59 ao_spi_send(&ao_flash_instruction, 4);
65 ao_flash_read_status(void)
68 ao_flash_instruction.instruction = FLASH_READ_STATUS;
69 ao_spi_send(&ao_flash_instruction, 1);
70 ao_spi_recv(&ao_flash_instruction, 1);
72 return ao_flash_instruction.instruction;
75 #define FLASH_BLOCK_NONE 0xffff
77 static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX];
78 static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE;
79 static __pdata uint8_t ao_flash_block_dirty;
80 static __pdata uint8_t ao_flash_write_pending;
81 static __pdata uint8_t ao_flash_setup_done;
82 static __data uint32_t ao_flash_device_size;
83 static __data uint8_t ao_flash_block_shift;
84 static __data uint16_t ao_flash_block_size;
91 if (ao_flash_setup_done)
94 ao_mutex_get(&ao_flash_mutex);
95 if (ao_flash_setup_done) {
96 ao_mutex_put(&ao_flash_mutex);
100 /* On first use, check to see if the flash chip has
101 * been programmed to use 512 byte pages. If not, do so.
102 * And then, because the flash part must be power cycled
103 * for that change to take effect, panic.
105 status = ao_flash_read_status();
107 if (!(status & FLASH_STATUS_PAGESIZE_512)) {
108 ao_flash_set_pagesize_512();
109 ao_panic(AO_PANIC_FLASH);
112 switch (status & 0x3c) {
116 ao_flash_block_shift = 9;
117 ao_flash_device_size = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024);
122 ao_flash_block_shift = 9;
123 ao_flash_device_size = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024);
128 ao_flash_block_shift = 8;
129 ao_flash_device_size = ((uint32_t) 1024 * (uint32_t) 1024);
134 ao_flash_block_shift = 8;
135 ao_flash_device_size = ((uint32_t) 512 * (uint32_t) 1024);
140 ao_flash_block_shift = 8;
141 ao_flash_device_size = ((uint32_t) 256 * (uint32_t) 1024);
146 ao_flash_block_shift = 8;
147 ao_flash_device_size = ((uint32_t) 128 * (uint32_t) 1024);
151 ao_panic(AO_PANIC_FLASH);
153 ao_flash_block_size = 1 << ao_flash_block_shift;
154 ao_flash_setup_done = 1;
155 ao_mutex_put(&ao_flash_mutex);
159 ao_flash_wait_write(void)
161 if (ao_flash_write_pending) {
163 uint8_t status = ao_flash_read_status();
164 if ((status & FLASH_STATUS_RDY))
167 ao_flash_write_pending = 0;
171 /* Write the current block to the FLASHPROM */
173 ao_flash_write_block(void)
175 ao_flash_wait_write();
177 ao_flash_instruction.instruction = FLASH_WRITE;
179 /* 13/14 block bits + 9/8 byte bits (always 0) */
180 ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
181 ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
182 ao_flash_instruction.address[2] = 0;
183 ao_spi_send(&ao_flash_instruction, 4);
184 ao_spi_send(ao_flash_data, FLASH_BLOCK_SIZE);
186 ao_flash_write_pending = 1;
189 /* Read the current block from the FLASHPROM */
191 ao_flash_read_block(void)
193 ao_flash_wait_write();
195 ao_flash_instruction.instruction = FLASH_READ;
197 /* 13/14 block bits + 9/8 byte bits (always 0) */
198 ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift);
199 ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8);
200 ao_flash_instruction.address[2] = 0;
201 ao_spi_send(&ao_flash_instruction, 4);
202 ao_spi_recv(ao_flash_data, FLASH_BLOCK_SIZE);
207 ao_flash_flush_internal(void)
209 if (ao_flash_block_dirty) {
210 ao_flash_write_block();
211 ao_flash_block_dirty = 0;
216 ao_flash_fill(uint16_t block)
218 if (block != ao_flash_block) {
219 ao_flash_flush_internal();
220 ao_flash_block = block;
221 ao_flash_read_block();
226 ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant
233 if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE)
237 /* Compute portion of transfer within
240 this_off = (uint16_t) pos & FLASH_BLOCK_MASK;
241 this_len = FLASH_BLOCK_SIZE - this_off;
242 block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT);
246 /* Transfer the data */
247 ao_mutex_get(&ao_flash_mutex); {
248 if (this_len != FLASH_BLOCK_SIZE)
249 ao_flash_fill(block);
251 ao_flash_flush_internal();
252 ao_flash_block = block;
254 memcpy(ao_flash_data + this_off, buf, this_len);
255 ao_flash_block_dirty = 1;
256 } ao_mutex_put(&ao_flash_mutex);
258 /* See how much is left */
267 ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant
274 if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE)
279 /* Compute portion of transfer within
282 this_off = (uint16_t) pos & FLASH_BLOCK_MASK;
283 this_len = FLASH_BLOCK_SIZE - this_off;
284 block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT);
288 /* Transfer the data */
289 ao_mutex_get(&ao_flash_mutex); {
290 ao_flash_fill(block);
291 memcpy(buf, ao_flash_data + this_off, this_len);
292 } ao_mutex_put(&ao_flash_mutex);
294 /* See how much is left */
303 ao_ee_flush(void) __reentrant
305 ao_mutex_get(&ao_flash_mutex); {
306 ao_flash_flush_internal();
307 } ao_mutex_put(&ao_flash_mutex);
311 * Read/write the config block, which is in
312 * the last block of the flash
316 ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant
319 if (len > FLASH_BLOCK_SIZE)
321 ao_mutex_get(&ao_flash_mutex); {
322 ao_flash_fill(FLASH_CONFIG_BLOCK);
323 memcpy(ao_flash_data, buf, len);
324 ao_flash_block_dirty = 1;
325 ao_flash_flush_internal();
326 } ao_mutex_put(&ao_flash_mutex);
331 ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
334 if (len > FLASH_BLOCK_SIZE)
336 ao_mutex_get(&ao_flash_mutex); {
337 ao_flash_fill(FLASH_CONFIG_BLOCK);
338 memcpy(buf, ao_flash_data, len);
339 } ao_mutex_put(&ao_flash_mutex);
344 flash_dump(void) __reentrant
351 block = ao_cmd_lex_i;
352 if (ao_cmd_status != ao_cmd_success)
359 ao_cmd_put16((uint16_t) i);
362 ao_ee_read(((uint32_t) block << 8) | i, &b, 1);
370 flash_store(void) __reentrant
379 block = ao_cmd_lex_i;
382 addr = ((uint32_t) block << 8) | i;
385 if (ao_cmd_status != ao_cmd_success)
389 if (ao_cmd_status != ao_cmd_success)
392 ao_ee_write(addr, &b, 1);
399 ao_ee_dump_config(void) __reentrant
402 printf("Configuration block %d\n", FLASH_CONFIG_BLOCK);
403 ao_mutex_get(&ao_flash_mutex); {
404 ao_flash_flush_internal();
405 ao_flash_block = FLASH_BLOCK_NONE;
406 ao_flash_fill(FLASH_CONFIG_BLOCK);
412 ao_cmd_put16((uint16_t) i);
415 ao_cmd_put8(ao_flash_data[i]);
417 } while (i < sizeof (ao_config));
418 } ao_mutex_put(&ao_flash_mutex);
422 flash_status(void) __reentrant
427 ao_mutex_get(&ao_flash_mutex); {
428 status = ao_flash_read_status();
429 printf ("Flash status: 0x%02x\n", status);
430 printf ("Flash block shift: %d\n", FLASH_BLOCK_SHIFT);
431 printf ("Flash block size: %d\n", FLASH_BLOCK_SIZE);
432 printf ("Flash block mask: %d\n", FLASH_BLOCK_MASK);
433 printf ("Flash device size: %ld\n", FLASH_DEVICE_SIZE);
434 printf ("Flash data size: %ld\n", FLASH_DATA_SIZE);
435 printf ("Flash config block: %d\n", FLASH_CONFIG_BLOCK);
436 } ao_mutex_put(&ao_flash_mutex);
440 __code struct ao_cmds ao_flash_cmds[] = {
441 { 'e', flash_dump, "e <block> Dump a block of flash data" },
442 { 'w', flash_store, "w <block> <start> <len> <data> ... Write data to flash" },
443 { 'f', flash_status, "f Show flash status register" },
444 { 0, flash_store, NULL },
448 * To initialize the chip, set up the CS line and
456 P1DIR |= (1 << FLASH_CS_INDEX);
457 P1SEL &= ~(1 << FLASH_CS_INDEX);
458 ao_cmd_register(&ao_flash_cmds[0]);