2 * Copyright © 2012 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; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 #include <ao_eeprom.h>
22 /* Total bytes of available storage */
23 const ao_pos_t ao_eeprom_total = 4096;
25 /* Location of eeprom in address space */
26 #define stm_eeprom ((uint8_t *) 0x08080000)
29 * The internal flash chip is arranged in 8 byte sectors; the
30 * chip cannot erase in units smaller than that.
32 * Writing happens in units of 2 bytes and
33 * can only change bits from 1 to 0. So, you can rewrite
34 * the same contents, or append to an existing page easily enough
38 ao_intflash_unlock(void)
40 /* Disable backup write protection */
41 stm_pwr.cr |= (1 << STM_PWR_CR_DBP);
43 /* Unlock Data EEPROM and FLASH_PECR register */
44 stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1;
45 stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2;
47 if (stm_flash.pecr & (1 << STM_FLASH_PECR_PELOCK))
48 printf ("eeprom unlock failed\n");
50 /* Configure the FTDW bit (FLASH_PECR[8]) to execute
51 * word write, whatever the previous value of the word
54 stm_flash.pecr = ((0 << STM_FLASH_PECR_OBL_LAUNCH) |
55 (0 << STM_FLASH_PECR_ERRIE) |
56 (0 << STM_FLASH_PECR_EOPIE) |
57 (0 << STM_FLASH_PECR_FPRG) |
58 (0 << STM_FLASH_PECR_ERASE) |
59 (1 << STM_FLASH_PECR_FTDW) |
60 (0 << STM_FLASH_PECR_DATA) |
61 (0 << STM_FLASH_PECR_PROG) |
62 (0 << STM_FLASH_PECR_OPTLOCK) |
63 (0 << STM_FLASH_PECR_PRGLOCK) |
64 (0 << STM_FLASH_PECR_PELOCK));
68 ao_intflash_lock(void)
70 stm_flash.pecr |= (1 << STM_FLASH_PECR_PELOCK);
74 ao_intflash_wait(void)
76 /* Wait for the flash unit to go idle */
77 while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
82 ao_intflash_write32(uint16_t pos, uint32_t w)
84 volatile uint32_t *addr;
86 addr = (uint32_t *) (void *) (stm_eeprom + pos);
88 /* Write a word to a valid address in the data EEPROM */
94 ao_intflash_write8(uint16_t pos, uint8_t d)
96 uint32_t w, *addr, mask;
99 addr = (uint32_t *) (void *) (stm_eeprom + (pos & ~3));
101 /* Compute word to be written */
102 shift = (pos & 3) << 3;
103 mask = 0xff << shift;
104 w = (*addr & ~mask) | (d << shift);
106 ao_intflash_write32(pos & ~3, w);
110 ao_intflash_read(uint16_t pos)
112 return stm_eeprom[pos];
120 ao_eeprom_write(ao_pos_t pos32, void *v, uint16_t len)
122 uint16_t pos = pos32;
125 if (pos >= ao_eeprom_total || pos + len > ao_eeprom_total)
128 ao_intflash_unlock();
130 if ((pos & 3) == 0 && len >= 4) {
133 w = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24);
134 ao_intflash_write32(pos, w);
139 ao_intflash_write8(pos, *d);
154 ao_eeprom_read(ao_pos_t pos, void *v, uint16_t len)
158 if (pos >= ao_eeprom_total || pos + len > ao_eeprom_total)
161 *d++ = ao_intflash_read(pos++);
172 /* Nothing to do here */