Merge branch 'master' of git://www.denx.de/git/u-boot-socfpga
[oweals/u-boot.git] / arch / arm / cpu / armv7m / stm32f4 / flash.c
1 /*
2  * (C) Copyright 2015
3  * Kamil Lulko, <rev13@wp.pl>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <asm/io.h>
10 #include <asm/arch/stm32.h>
11
12 #define STM32_FLASH_KEY1        0x45670123
13 #define STM32_FLASH_KEY2        0xCDEF89AB
14
15 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
16
17 const u32 sect_sz_kb[CONFIG_SYS_MAX_FLASH_SECT] = {
18         [0 ... 3] =     16 * 1024,
19         [4] =           64 * 1024,
20         [5 ... 11] =    128 * 1024
21 };
22
23 static void stm32f4_flash_lock(u8 lock)
24 {
25         if (lock) {
26                 setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_LOCK);
27         } else {
28                 writel(STM32_FLASH_KEY1, &STM32_FLASH->key);
29                 writel(STM32_FLASH_KEY2, &STM32_FLASH->key);
30         }
31 }
32
33 unsigned long flash_init(void)
34 {
35         unsigned long total_size = 0;
36         u8 i, j;
37
38         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
39                 flash_info[i].flash_id = FLASH_STM32F4;
40                 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
41                 flash_info[i].start[0] = CONFIG_SYS_FLASH_BASE + (i << 20);
42                 flash_info[i].size = sect_sz_kb[0];
43                 for (j = 1; j < CONFIG_SYS_MAX_FLASH_SECT; j++) {
44                         flash_info[i].start[j] = flash_info[i].start[j - 1]
45                                 + (sect_sz_kb[j - 1]);
46                         flash_info[i].size += sect_sz_kb[j];
47                 }
48                 total_size += flash_info[i].size;
49         }
50
51         return total_size;
52 }
53
54 void flash_print_info(flash_info_t *info)
55 {
56         int i;
57
58         if (info->flash_id == FLASH_UNKNOWN) {
59                 printf("missing or unknown FLASH type\n");
60                 return;
61         } else if (info->flash_id == FLASH_STM32F4) {
62                 printf("STM32F4 Embedded Flash\n");
63         }
64
65         printf("  Size: %ld MB in %d Sectors\n",
66                info->size >> 20, info->sector_count);
67
68         printf("  Sector Start Addresses:");
69         for (i = 0; i < info->sector_count; ++i) {
70                 if ((i % 5) == 0)
71                         printf("\n   ");
72                 printf(" %08lX%s",
73                        info->start[i],
74                         info->protect[i] ? " (RO)" : "     ");
75         }
76         printf("\n");
77         return;
78 }
79
80 int flash_erase(flash_info_t *info, int first, int last)
81 {
82         u8 bank = 0xFF;
83         int i;
84
85         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
86                 if (info == &flash_info[i]) {
87                         bank = i;
88                         break;
89                 }
90         }
91         if (bank == 0xFF)
92                 return -1;
93
94         stm32f4_flash_lock(0);
95
96         for (i = first; i <= last; i++) {
97                 while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY)
98                         ;
99
100                 if (bank == 0) {
101                         setbits_le32(&STM32_FLASH->cr,
102                                      (i << STM32_FLASH_CR_SNB_OFFSET));
103                 } else if (bank == 1) {
104                         setbits_le32(&STM32_FLASH->cr,
105                                      ((0x10 | i) << STM32_FLASH_CR_SNB_OFFSET));
106                 } else {
107                         stm32f4_flash_lock(1);
108                         return -1;
109                 }
110                 setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_SER);
111                 setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_STRT);
112
113                 while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY)
114                         ;
115
116                 clrbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_SER);
117                 stm32f4_flash_lock(1);
118         }
119
120         return 0;
121 }
122
123 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
124 {
125         ulong i;
126
127         while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY)
128                 ;
129
130         stm32f4_flash_lock(0);
131
132         setbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_PG);
133         /* To make things simple use byte writes only */
134         for (i = 0; i < cnt; i++) {
135                 *(uchar *)(addr + i) = src[i];
136                 while (readl(&STM32_FLASH->sr) & STM32_FLASH_SR_BSY)
137                         ;
138         }
139         clrbits_le32(&STM32_FLASH->cr, STM32_FLASH_CR_PG);
140         stm32f4_flash_lock(1);
141
142         return 0;
143 }