aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mediatek/files-5.10/drivers/mtd/mtk-snand/mtk-snand-def.h
blob: 1a93d93dcd7be3ef5297600cd1b20d0c0015fd35 (plain)
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
 * Copyright (C) 2020 MediaTek Inc. All Rights Reserved.
 *
 * Author: Weijie Gao <weijie.gao@mediatek.com>
 */

#ifndef _MTK_SNAND_DEF_H_
#define _MTK_SNAND_DEF_H_

#include "mtk-snand-os.h"

#ifdef PRIVATE_MTK_SNAND_HEADER
#include "mtk-snand.h"
#else
#include <mtk-snand.h>
#endif

struct mtk_snand_plat_dev;

enum snand_flash_io {
	SNAND_IO_1_1_1,
	SNAND_IO_1_1_2,
	SNAND_IO_1_2_2,
	SNAND_IO_1_1_4,
	SNAND_IO_1_4_4,

	__SNAND_IO_MAX
};

#define SPI_IO_1_1_1			BIT(SNAND_IO_1_1_1)
#define SPI_IO_1_1_2			BIT(SNAND_IO_1_1_2)
#define SPI_IO_1_2_2			BIT(SNAND_IO_1_2_2)
#define SPI_IO_1_1_4			BIT(SNAND_IO_1_1_4)
#define SPI_IO_1_4_4			BIT(SNAND_IO_1_4_4)

struct snand_opcode {
	uint8_t opcode;
	uint8_t dummy;
};

struct snand_io_cap {
	uint8_t caps;
	struct snand_opcode opcodes[__SNAND_IO_MAX];
};

#define SNAND_OP(_io, _opcode, _dummy) [_io] = { .opcode = (_opcode), \
						 .dummy = (_dummy) }

#define SNAND_IO_CAP(_name, _caps, ...) \
	struct snand_io_cap _name = { .caps = (_caps), \
				      .opcodes = { __VA_ARGS__ } }

#define SNAND_MAX_ID_LEN		4

enum snand_id_type {
	SNAND_ID_DYMMY,
	SNAND_ID_ADDR = SNAND_ID_DYMMY,
	SNAND_ID_DIRECT,

	__SNAND_ID_TYPE_MAX
};

struct snand_id {
	uint8_t type;	/* enum snand_id_type */
	uint8_t len;
	uint8_t id[SNAND_MAX_ID_LEN];
};

#define SNAND_ID(_type, ...) \
	{ .type = (_type), .id = { __VA_ARGS__ }, \
	  .len = sizeof((uint8_t[]) { __VA_ARGS__ }) }

struct snand_mem_org {
	uint16_t pagesize;
	uint16_t sparesize;
	uint16_t pages_per_block;
	uint16_t blocks_per_die;
	uint16_t planes_per_die;
	uint16_t ndies;
};

#define SNAND_MEMORG(_ps, _ss, _ppb, _bpd, _ppd, _nd) \
	{ .pagesize = (_ps), .sparesize = (_ss), .pages_per_block = (_ppb), \
	  .blocks_per_die = (_bpd), .planes_per_die = (_ppd), .ndies = (_nd) }

typedef int (*snand_select_die_t)(struct mtk_snand *snf, uint32_t dieidx);

struct snand_flash_info {
	const char *model;
	struct snand_id id;
	const struct snand_mem_org memorg;
	const struct snand_io_cap *cap_rd;
	const struct snand_io_cap *cap_pl;
	snand_select_die_t select_die;
};

#define SNAND_INFO(_model, _id, _memorg, _cap_rd, _cap_pl, ...) \
	{ .model = (_model), .id = _id, .memorg = _memorg, \
	  .cap_rd = (_cap_rd), .cap_pl = (_cap_pl), __VA_ARGS__ }

const struct snand_flash_info *snand_flash_id_lookup(enum snand_id_type type,
						     const uint8_t *id);

struct mtk_snand_soc_data {
	uint16_t sector_size;
	uint16_t max_sectors;
	uint16_t fdm_size;
	uint16_t fdm_ecc_size;
	uint16_t fifo_size;

	bool bbm_swap;
	bool empty_page_check;
	uint32_t mastersta_mask;

	const uint8_t *spare_sizes;
	uint32_t num_spare_size;
};

enum mtk_ecc_regs {
	ECC_DECDONE,
};

struct mtk_ecc_soc_data {
	const uint8_t *ecc_caps;
	uint32_t num_ecc_cap;
	const uint32_t *regs;
	uint16_t mode_shift;
	uint8_t errnum_bits;
	uint8_t errnum_shift;
};

struct mtk_snand {
	struct mtk_snand_plat_dev *pdev;

	void __iomem *nfi_base;
	void __iomem *ecc_base;

	enum mtk_snand_soc soc;
	const struct mtk_snand_soc_data *nfi_soc;
	const struct mtk_ecc_soc_data *ecc_soc;
	bool snfi_quad_spi;
	bool quad_spi_op;

	const char *model;
	uint64_t size;
	uint64_t die_size;
	uint32_t erasesize;
	uint32_t writesize;
	uint32_t oobsize;

	uint32_t num_dies;
	snand_select_die_t select_die;

	uint8_t opcode_rfc;
	uint8_t opcode_pl;
	uint8_t dummy_rfc;
	uint8_t mode_rfc;
	uint8_t mode_pl;

	uint32_t writesize_mask;
	uint32_t writesize_shift;
	uint32_t erasesize_mask;
	uint32_t erasesize_shift;
	uint64_t die_mask;
	uint32_t die_shift;

	uint32_t spare_per_sector;
	uint32_t raw_sector_size;
	uint32_t ecc_strength;
	uint32_t ecc_steps;
	uint32_t ecc_bytes;
	uint32_t ecc_parity_bits;

	uint8_t *page_cache;	/* Used by read/write page */
	uint8_t *buf_cache;	/* Used by block bad/markbad & auto_oob */
	int *sect_bf;		/* Used by ECC correction */
};

enum mtk_snand_log_category {
	SNAND_LOG_NFI,
	SNAND_LOG_SNFI,
	SNAND_LOG_ECC,
	SNAND_LOG_CHIP,

	__SNAND_LOG_CAT_MAX
};

int mtk_ecc_setup(struct mtk_snand *snf, void *fmdaddr, uint32_t max_ecc_bytes,
		  uint32_t msg_size);
int mtk_snand_ecc_encoder_start(struct mtk_snand *snf);
void mtk_snand_ecc_encoder_stop(struct mtk_snand *snf);
int mtk_snand_ecc_decoder_start(struct mtk_snand *snf);
void mtk_snand_ecc_decoder_stop(struct mtk_snand *snf);
int mtk_ecc_wait_decoder_done(struct mtk_snand *snf);
int mtk_ecc_check_decode_error(struct mtk_snand *snf);
int mtk_ecc_fixup_empty_sector(struct mtk_snand *snf, uint32_t sect);

int mtk_snand_mac_io(struct mtk_snand *snf, const uint8_t *out, uint32_t outlen,
		     uint8_t *in, uint32_t inlen);
int mtk_snand_set_feature(struct mtk_snand *snf, uint32_t addr, uint32_t val);

int mtk_snand_log(struct mtk_snand_plat_dev *pdev,
		  enum mtk_snand_log_category cat, const char *fmt, ...);

#define snand_log_nfi(pdev, fmt, ...) \
	mtk_snand_log(pdev, SNAND_LOG_NFI, fmt, ##__VA_ARGS__)

#define snand_log_snfi(pdev, fmt, ...) \
	mtk_snand_log(pdev, SNAND_LOG_SNFI, fmt, ##__VA_ARGS__)

#define snand_log_ecc(pdev, fmt, ...) \
	mtk_snand_log(pdev, SNAND_LOG_ECC, fmt, ##__VA_ARGS__)

#define snand_log_chip(pdev, fmt, ...) \
	mtk_snand_log(pdev, SNAND_LOG_CHIP, fmt, ##__VA_ARGS__)

/* ffs64 */
static inline int mtk_snand_ffs64(uint64_t x)
{
	if (!x)
		return 0;

	if (!(x & 0xffffffff))
		return ffs((uint32_t)(x >> 32)) + 32;

	return ffs((uint32_t)(x & 0xffffffff));
}

/* NFI dummy commands */
#define NFI_CMD_DUMMY_READ		0x00
#define NFI_CMD_DUMMY_WRITE		0x80

/* SPI-NAND opcodes */
#define SNAND_CMD_RESET			0xff
#define SNAND_CMD_BLOCK_ERASE		0xd8
#define SNAND_CMD_READ_FROM_CACHE_QUAD	0xeb
#define SNAND_CMD_WINBOND_SELECT_DIE	0xc2
#define SNAND_CMD_READ_FROM_CACHE_DUAL	0xbb
#define SNAND_CMD_READID		0x9f
#define SNAND_CMD_READ_FROM_CACHE_X4	0x6b
#define SNAND_CMD_READ_FROM_CACHE_X2	0x3b
#define SNAND_CMD_PROGRAM_LOAD_X4	0x32
#define SNAND_CMD_SET_FEATURE		0x1f
#define SNAND_CMD_READ_TO_CACHE		0x13
#define SNAND_CMD_PROGRAM_EXECUTE	0x10
#define SNAND_CMD_GET_FEATURE		0x0f
#define SNAND_CMD_READ_FROM_CACHE	0x0b
#define SNAND_CMD_WRITE_ENABLE		0x06
#define SNAND_CMD_PROGRAM_LOAD		0x02

/* SPI-NAND feature addresses */
#define SNAND_FEATURE_MICRON_DIE_ADDR	0xd0
#define SNAND_MICRON_DIE_SEL_1		BIT(6)

#define SNAND_FEATURE_STATUS_ADDR	0xc0
#define SNAND_STATUS_OIP		BIT(0)
#define SNAND_STATUS_WEL		BIT(1)
#define SNAND_STATUS_ERASE_FAIL		BIT(2)
#define SNAND_STATUS_PROGRAM_FAIL	BIT(3)

#define SNAND_FEATURE_CONFIG_ADDR	0xb0
#define SNAND_FEATURE_QUAD_ENABLE	BIT(0)
#define SNAND_FEATURE_ECC_EN		BIT(4)

#define SNAND_FEATURE_PROTECT_ADDR	0xa0

#endif /* _MTK_SNAND_DEF_H_ */