embox

Форк
0
189 строк · 5.7 Кб
1
/**
2
 * @file
3
 *
4
 * @brief Flash driver for NIIET mflash (inchip)
5
 *
6
 * @author  Anton Bondarev
7
 * @date    26.04.2024
8
 */
9

10
#include <util/log.h>
11

12
#include <assert.h>
13
#include <errno.h>
14
#include <stdbool.h>
15
#include <string.h>
16

17
#include <hal/reg.h>
18

19
#include <drivers/block_dev/flash/in_chip_flash.h>
20
#include <drivers/flash/flash.h>
21
#include <drivers/flash/flash_cache.h>
22

23
#include <util/macro.h>
24
#include <util/math.h>
25

26
#define FLASH_NAME          inchip_flash
27
#define FLASH_WORD_SIZE     (4*4) /* 4 32bit words*/
28
#define FLASH_ADDR_SECTOR_0 (0x80000000UL)
29

30
IN_CHIP_FLASH_DECL();
31

32
FLASH_CACHE_DEF(FLASH_NAME, FLASH_WORD_SIZE, IN_CHIP_FLASH_SECTOR_SIZE);
33

34
#define FLASH_START_SECTOR \
35
	((IN_CHIP_FLASH_START - FLASH_ADDR_SECTOR_0) / IN_CHIP_FLASH_SECTOR_SIZE)
36

37
static uint32_t niiet_mflash_fld_aligned_word[4];
38
static const struct flash_dev_drv niiet_mflash_drv;
39

40
static int niiet_mflash_init(struct flash_dev *dev, void *arg) {
41
	struct flash_dev *flash;
42

43
	assert((IN_CHIP_FLASH_SIZE % IN_CHIP_FLASH_SECTOR_SIZE) == 0);
44

45
	flash = flash_create(MACRO_STRING(FLASH_NAME), IN_CHIP_FLASH_SIZE);
46
	if (flash == NULL) {
47
		log_error("Failed to create flash device!");
48
		return -1;
49
	}
50
	flash->drv = &niiet_mflash_drv;
51
	flash->size = IN_CHIP_FLASH_END - IN_CHIP_FLASH_START;
52
	flash->num_block_infos = 1;
53
	flash->block_info[0] = (struct flash_block_info){
54
	    .fbi_start_id = IN_CHIP_FLASH_START,
55
	    .block_size = IN_CHIP_FLASH_SECTOR_SIZE,
56
	    .blocks = IN_CHIP_FLASH_SIZE / IN_CHIP_FLASH_SECTOR_SIZE,
57
	};
58
	flash->fld_aligned_word = &niiet_mflash_fld_aligned_word[0];
59
	flash->fld_word_size = FLASH_WORD_SIZE;
60

61
	flash->fld_cache = FLASH_CACHE_GET(flash, FLASH_NAME);
62

63
	log_debug("");
64
	log_debug("Flash info:");
65
	log_debug("  Flash start address = 0x%08x", IN_CHIP_FLASH_START);
66
	log_debug("  Flash start sector  = %d", FLASH_START_SECTOR);
67
	log_debug("  Flash size   = 0x%x", flash->size);
68
	log_debug("  Block size   = 0x%x", flash->block_info[0].block_size);
69
	log_debug("  Blocks count = 0x%x", flash->block_info[0].blocks);
70
	log_debug("");
71

72
	return 0;
73
}
74

75
#define MAIN_REGION             0
76
#define NVR_REGION              1
77
/*-- MFLASH ------------------------------------------------------------------*/
78
#define MFLASH_PAGE_SIZE        4096
79
#define MFLASH_PAGE_TOTAL       256
80
#define MFLASH_WORD_WIDTH       4
81
#define MFLASH_BASE             ((void*)0x3000D000)
82
#define MFLASH_BANK_ADDR        0x80000000
83

84
#if 0
85
#define MFLASH_ADDR             (*(volatile uint32_t*)(0x3000D000u))
86
#define MFLASH_DATA0            (*(volatile uint32_t*)(0x3000D004u))
87
#define MFLASH_DATA1            (*(volatile uint32_t*)(0x3000D008u))
88
#define MFLASH_DATA2            (*(volatile uint32_t*)(0x3000D00Cu))
89
#define MFLASH_DATA3            (*(volatile uint32_t*)(0x3000D010u))
90
#define MFLASH_CMD              (*(volatile uint32_t*)(0x3000D044u))
91
#define MFLASH_STAT             (*(volatile uint32_t*)(0x3000D048u))
92
#endif
93

94
#define MFLASH_ADDR             ((0x3000D000u))
95
#define MFLASH_DATA0            ((0x3000D004u))
96
#define MFLASH_DATA1            ((0x3000D008u))
97
#define MFLASH_DATA2            ((0x3000D00Cu))
98
#define MFLASH_DATA3            ((0x3000D010u))
99
#define MFLASH_CMD              ((0x3000D044u))
100
#define MFLASH_STAT             ((0x3000D048u))
101

102
/*---- MFLASH->CMD: Command register */
103
#define MFLASH_CMD_RD           (1<<0)              /* Read data in region */
104
#define MFLASH_CMD_WR           (1<<1)              /* Write data in region */
105
#define MFLASH_CMD_ERSEC        (1<<2)              /* Sector erase in region */
106
#define MFLASH_CMD_ERALL        (1<<3)              /* Erase all sectors in region */
107
#define MFLASH_CMD_NVRON        (1<<8)              /* Select NVR region for command operation */
108
#define MFLASH_CMD_KEY          (0xC0DE<<16)        /* Command enable key */
109
/*---- MFLASH->STAT: Status register */
110
#define MFLASH_STAT_BUSY        (1<<0)              /* Flag operation busy */
111

112
static inline int niiet_mflash_get_start_sector(struct flash_dev *dev) {
113
	return ((dev->block_info[0].fbi_start_id - MFLASH_BANK_ADDR)
114
	        / dev->block_info[0].block_size);
115
}
116

117
/**
118
 * Wait while operation with flash being performed
119
 */
120
static int niiet_mflash_waitdone(struct flash_dev *dev) {
121
	uint32_t flash_status;
122

123
	do {
124
		flash_status = REG32_LOAD(MFLASH_STAT);
125
	} while(flash_status & MFLASH_STAT_BUSY);
126

127
	return 0;
128
}
129

130
static int niiet_mflash_erase_block(struct flash_dev *dev, uint32_t block) {
131
	uint32_t addr;
132

133
	addr = dev->block_info[0].fbi_start_id + block * MFLASH_PAGE_SIZE;
134

135
	niiet_mflash_waitdone(dev);
136
	REG32_STORE(MFLASH_ADDR, addr);
137
	REG32_STORE(MFLASH_CMD, MFLASH_CMD_KEY | MFLASH_CMD_ERSEC);
138
	niiet_mflash_waitdone(dev);
139

140
	return 0;
141
}
142

143
static int niiet_mflash_read(struct flash_dev *dev, uint32_t base, void *data,
144
    size_t len) {
145
	
146
	if (base + len > dev->size) {
147
		log_error("Address is out of range. Base=0x%x,len=0x%x", base, len);
148
		return -1;
149
	}
150
	/* read can be unaligned */
151
	memcpy(data, (void *)(dev->block_info[0].fbi_start_id) + base, len);
152
	
153
	return len;
154
}
155

156
static int niiet_mflash_program(struct flash_dev *dev, uint32_t base,
157
    const void *data, size_t len) {
158
	uint32_t addr;
159
	uint32_t *d = (void *)data;
160
	int cnt;
161

162
	for(cnt = 0; cnt < len; cnt += 16) {
163
		addr = dev->block_info[0].fbi_start_id + base + cnt;
164

165
		niiet_mflash_waitdone(dev);
166
		REG32_STORE(MFLASH_ADDR, addr);
167

168
		REG32_STORE(MFLASH_DATA0, d[0]);
169
		REG32_STORE(MFLASH_DATA1, d[1]);
170
		REG32_STORE(MFLASH_DATA2, d[2]);
171
		REG32_STORE(MFLASH_DATA3, d[3]);
172

173
		REG32_STORE(MFLASH_CMD, MFLASH_CMD_KEY | MFLASH_CMD_WR);
174
		niiet_mflash_waitdone(dev);
175

176
		d += 4;
177
	}
178

179
	return len;
180
}
181

182
static const struct flash_dev_drv niiet_mflash_drv = {
183
    .flash_init = niiet_mflash_init,
184
    .flash_read = niiet_mflash_read,
185
    .flash_erase_block = niiet_mflash_erase_block,
186
    .flash_program = niiet_mflash_program,
187
};
188

189
FLASH_DEV_DEF(MACRO_STRING(FLASH_NAME), &niiet_mflash_drv);
190

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.