1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
/*
* (C) Copyright 2015
* Kamil Lulko, <kamil.lulko@gmail.com>
*
* Copyright 2015 ATS Advanced Telematics Systems GmbH
* Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/stm32.h>
#define STM32_FLASH_KEY1 0x45670123
#define STM32_FLASH_KEY2 0xcdef89ab
#define STM32_NUM_BANKS 2
#define STM32_MAX_BANK 0x200
flash_info_t flash_info[STM32_NUM_BANKS];
static struct stm32_flash_bank_regs *flash_bank[STM32_NUM_BANKS];
static void stm32f1_flash_lock(u8 bank, u8 lock)
{
if (lock) {
setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_LOCK);
} else {
writel(STM32_FLASH_KEY1, &flash_bank[bank]->keyr);
writel(STM32_FLASH_KEY2, &flash_bank[bank]->keyr);
}
}
/* Only XL devices are supported (2 KiB sector size) */
unsigned long flash_init(void)
{
u8 i, banks;
u16 j, size;
/* Set up accessors for XL devices with wonky register layout */
flash_bank[0] = (struct stm32_flash_bank_regs *)&STM32_FLASH->keyr;
flash_bank[1] = (struct stm32_flash_bank_regs *)&STM32_FLASH->keyr2;
/*
* Get total flash size (in KiB) and configure number of banks
* present and sector count per bank.
*/
size = readw(&STM32_DES->flash_size);
if (size <= STM32_MAX_BANK) {
banks = 1;
flash_info[0].sector_count = size >> 1;
} else if (size > STM32_MAX_BANK) {
banks = 2;
flash_info[0].sector_count = STM32_MAX_BANK >> 1;
flash_info[1].sector_count = (size - STM32_MAX_BANK) >> 1;
}
/* Configure start/size for all sectors */
for (i = 0; i < banks; i++) {
flash_info[i].flash_id = FLASH_STM32F1;
flash_info[i].start[0] = CONFIG_SYS_FLASH_BASE + (i << 19);
flash_info[i].size = 2048;
for (j = 1; (j < flash_info[i].sector_count); j++) {
flash_info[i].start[j] = flash_info[i].start[j - 1]
+ 2048;
flash_info[i].size += 2048;
}
}
return size << 10;
}
void flash_print_info(flash_info_t *info)
{
int i;
if (info->flash_id == FLASH_UNKNOWN) {
printf("Missing or unknown FLASH type\n");
return;
} else if (info->flash_id == FLASH_STM32F1) {
printf("STM32F1 Embedded Flash\n");
}
printf(" Size: %ld MB in %d Sectors\n",
info->size >> 10, info->sector_count);
printf(" Sector Start Addresses:");
for (i = 0; i < info->sector_count; ++i) {
if ((i % 5) == 0)
printf("\n ");
printf(" %08lX%s",
info->start[i],
info->protect[i] ? " (RO)" : " ");
}
printf("\n");
return;
}
int flash_erase(flash_info_t *info, int first, int last)
{
u8 bank = 0xff;
int i;
for (i = 0; i < STM32_NUM_BANKS; i++) {
if (info == &flash_info[i]) {
bank = i;
break;
}
}
if (bank == 0xff)
return -1;
stm32f1_flash_lock(bank, 0);
for (i = first; i <= last; i++) {
while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
;
setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PER);
writel(info->start[i], &flash_bank[bank]->ar);
setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_STRT);
while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
;
}
clrbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PER);
stm32f1_flash_lock(bank, 1);
return 0;
}
int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
{
ulong i;
u8 bank = 0xff;
if (addr & 1) {
printf("Flash address must be half word aligned\n");
return -1;
}
if (cnt & 1) {
printf("Flash length must be half word aligned\n");
return -1;
}
for (i = 0; i < 2; i++) {
if (info == &flash_info[i]) {
bank = i;
break;
}
}
if (bank == 0xff)
return -1;
while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
;
stm32f1_flash_lock(bank, 0);
setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PG);
/* STM32F1 requires half word writes */
for (i = 0; i < cnt >> 1; i++) {
*(u16 *)(addr + i * 2) = ((u16 *)src)[i];
while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY)
;
}
clrbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PG);
stm32f1_flash_lock(bank, 1);
return 0;
}
|