2 * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw>
4 * SPDX-License-Identifier: GPL-2.0+
11 #include <fdt_support.h>
16 DECLARE_GLOBAL_DATA_PTR
;
18 /* The STATUS register */
19 #define QUADSPI_SR_BP0 BIT(2)
20 #define QUADSPI_SR_BP1 BIT(3)
21 #define QUADSPI_SR_BP2 BIT(4)
22 #define QUADSPI_SR_BP2_0 GENMASK(4, 2)
23 #define QUADSPI_SR_BP3 BIT(6)
24 #define QUADSPI_SR_TB BIT(5)
27 * The QUADSPI_MEM_OP register is used to do memory protect and erase operations
29 #define QUADSPI_MEM_OP_BULK_ERASE 0x00000001
30 #define QUADSPI_MEM_OP_SECTOR_ERASE 0x00000002
31 #define QUADSPI_MEM_OP_SECTOR_PROTECT 0x00000003
34 * The QUADSPI_ISR register is used to determine whether an invalid write or
35 * erase operation trigerred an interrupt
37 #define QUADSPI_ISR_ILLEGAL_ERASE BIT(0)
38 #define QUADSPI_ISR_ILLEGAL_WRITE BIT(1)
40 struct altera_qspi_regs
{
50 struct altera_qspi_platdata
{
51 struct altera_qspi_regs
*regs
;
56 static uint flash_verbose
;
57 flash_info_t flash_info
[CONFIG_SYS_MAX_FLASH_BANKS
]; /* FLASH chips info */
59 static void altera_qspi_get_locked_range(struct mtd_info
*mtd
, loff_t
*ofs
,
62 void flash_print_info(flash_info_t
*info
)
64 struct mtd_info
*mtd
= info
->mtd
;
68 printf("Altera QSPI flash Size: %ld MB in %d Sectors\n",
69 info
->size
>> 20, info
->sector_count
);
70 altera_qspi_get_locked_range(mtd
, &ofs
, &len
);
71 printf(" %08lX +%lX", info
->start
[0], info
->size
);
73 printf(", protected %08llX +%llX",
74 info
->start
[0] + ofs
, len
);
79 void flash_set_verbose(uint v
)
84 int flash_erase(flash_info_t
*info
, int s_first
, int s_last
)
86 struct mtd_info
*mtd
= info
->mtd
;
87 struct erase_info instr
;
90 memset(&instr
, 0, sizeof(instr
));
92 instr
.addr
= mtd
->erasesize
* s_first
;
93 instr
.len
= mtd
->erasesize
* (s_last
+ 1 - s_first
);
95 ret
= mtd_erase(mtd
, &instr
);
104 int write_buff(flash_info_t
*info
, uchar
*src
, ulong addr
, ulong cnt
)
106 struct mtd_info
*mtd
= info
->mtd
;
107 struct udevice
*dev
= mtd
->dev
;
108 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
109 ulong base
= (ulong
)pdata
->base
;
110 loff_t to
= addr
- base
;
114 ret
= mtd_write(mtd
, to
, cnt
, &retlen
, src
);
116 return ERR_PROTECTED
;
121 unsigned long flash_init(void)
125 /* probe every MTD device */
126 for (uclass_first_device(UCLASS_MTD
, &dev
);
128 uclass_next_device(&dev
)) {
131 return flash_info
[0].size
;
134 static int altera_qspi_erase(struct mtd_info
*mtd
, struct erase_info
*instr
)
136 struct udevice
*dev
= mtd
->dev
;
137 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
138 struct altera_qspi_regs
*regs
= pdata
->regs
;
139 size_t addr
= instr
->addr
;
140 size_t len
= instr
->len
;
141 size_t end
= addr
+ len
;
146 instr
->state
= MTD_ERASING
;
147 addr
&= ~(mtd
->erasesize
- 1); /* get lower aligned address */
152 instr
->fail_addr
= MTD_FAIL_ADDR_UNKNOWN
;
153 instr
->state
= MTD_ERASE_FAILED
;
154 mtd_erase_callback(instr
);
157 flash
= pdata
->base
+ addr
;
158 last
= pdata
->base
+ addr
+ mtd
->erasesize
;
159 /* skip erase if sector is blank */
160 while (flash
< last
) {
161 if (readl(flash
) != 0xffffffff)
166 sect
= addr
/ mtd
->erasesize
;
168 sect
|= QUADSPI_MEM_OP_SECTOR_ERASE
;
169 debug("erase %08x\n", sect
);
170 writel(sect
, ®s
->mem_op
);
171 stat
= readl(®s
->isr
);
172 if (stat
& QUADSPI_ISR_ILLEGAL_ERASE
) {
173 /* erase failed, sector might be protected */
174 debug("erase %08x fail %x\n", sect
, stat
);
175 writel(stat
, ®s
->isr
); /* clear isr */
176 instr
->fail_addr
= addr
;
177 instr
->state
= MTD_ERASE_FAILED
;
178 mtd_erase_callback(instr
);
187 addr
+= mtd
->erasesize
;
189 instr
->state
= MTD_ERASE_DONE
;
190 mtd_erase_callback(instr
);
195 static int altera_qspi_read(struct mtd_info
*mtd
, loff_t from
, size_t len
,
196 size_t *retlen
, u_char
*buf
)
198 struct udevice
*dev
= mtd
->dev
;
199 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
201 memcpy_fromio(buf
, pdata
->base
+ from
, len
);
207 static int altera_qspi_write(struct mtd_info
*mtd
, loff_t to
, size_t len
,
208 size_t *retlen
, const u_char
*buf
)
210 struct udevice
*dev
= mtd
->dev
;
211 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
212 struct altera_qspi_regs
*regs
= pdata
->regs
;
215 memcpy_toio(pdata
->base
+ to
, buf
, len
);
216 /* check whether write triggered a illegal write interrupt */
217 stat
= readl(®s
->isr
);
218 if (stat
& QUADSPI_ISR_ILLEGAL_WRITE
) {
219 /* write failed, sector might be protected */
220 debug("write fail %x\n", stat
);
221 writel(stat
, ®s
->isr
); /* clear isr */
229 static void altera_qspi_sync(struct mtd_info
*mtd
)
233 static void altera_qspi_get_locked_range(struct mtd_info
*mtd
, loff_t
*ofs
,
236 struct udevice
*dev
= mtd
->dev
;
237 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
238 struct altera_qspi_regs
*regs
= pdata
->regs
;
239 int shift0
= ffs(QUADSPI_SR_BP2_0
) - 1;
240 int shift3
= ffs(QUADSPI_SR_BP3
) - 1 - 3;
241 u32 stat
= readl(®s
->rd_status
);
242 unsigned pow
= ((stat
& QUADSPI_SR_BP2_0
) >> shift0
) |
243 ((stat
& QUADSPI_SR_BP3
) >> shift3
);
248 *len
= mtd
->erasesize
<< (pow
- 1);
249 if (*len
> mtd
->size
)
251 if (!(stat
& QUADSPI_SR_TB
))
252 *ofs
= mtd
->size
- *len
;
256 static int altera_qspi_lock(struct mtd_info
*mtd
, loff_t ofs
, uint64_t len
)
258 struct udevice
*dev
= mtd
->dev
;
259 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
260 struct altera_qspi_regs
*regs
= pdata
->regs
;
261 u32 sector_start
, sector_end
;
267 num_sectors
= mtd
->size
/ mtd
->erasesize
;
268 sector_start
= ofs
/ mtd
->erasesize
;
269 sector_end
= (ofs
+ len
) / mtd
->erasesize
;
271 if (sector_start
>= num_sectors
/ 2) {
272 sr_bp
= fls(num_sectors
- 1 - sector_start
) + 1;
274 } else if (sector_end
< num_sectors
/ 2) {
275 sr_bp
= fls(sector_end
) + 1;
282 mem_op
= (sr_tb
<< 12) | (sr_bp
<< 8);
283 mem_op
|= QUADSPI_MEM_OP_SECTOR_PROTECT
;
284 debug("lock %08x\n", mem_op
);
285 writel(mem_op
, ®s
->mem_op
);
290 static int altera_qspi_unlock(struct mtd_info
*mtd
, loff_t ofs
, uint64_t len
)
292 struct udevice
*dev
= mtd
->dev
;
293 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
294 struct altera_qspi_regs
*regs
= pdata
->regs
;
297 mem_op
= QUADSPI_MEM_OP_SECTOR_PROTECT
;
298 debug("unlock %08x\n", mem_op
);
299 writel(mem_op
, ®s
->mem_op
);
304 static int altera_qspi_probe(struct udevice
*dev
)
306 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
307 struct altera_qspi_regs
*regs
= pdata
->regs
;
308 unsigned long base
= (unsigned long)pdata
->base
;
309 struct mtd_info
*mtd
;
310 flash_info_t
*flash
= &flash_info
[0];
314 rdid
= readl(®s
->rd_rdid
);
315 debug("rdid %x\n", rdid
);
317 mtd
= dev_get_uclass_priv(dev
);
320 mtd
->type
= MTD_NORFLASH
;
321 mtd
->flags
= MTD_CAP_NORFLASH
;
322 mtd
->size
= 1 << ((rdid
& 0xff) - 6);
324 mtd
->writebufsize
= mtd
->writesize
;
325 mtd
->_erase
= altera_qspi_erase
;
326 mtd
->_read
= altera_qspi_read
;
327 mtd
->_write
= altera_qspi_write
;
328 mtd
->_sync
= altera_qspi_sync
;
329 mtd
->_lock
= altera_qspi_lock
;
330 mtd
->_unlock
= altera_qspi_unlock
;
331 mtd
->numeraseregions
= 0;
332 mtd
->erasesize
= 0x10000;
333 if (add_mtd_device(mtd
))
337 flash
->size
= mtd
->size
;
338 flash
->sector_count
= mtd
->size
/ mtd
->erasesize
;
339 flash
->flash_id
= rdid
;
340 flash
->start
[0] = base
;
341 for (i
= 1; i
< flash
->sector_count
; i
++)
342 flash
->start
[i
] = flash
->start
[i
- 1] + mtd
->erasesize
;
343 gd
->bd
->bi_flashstart
= base
;
348 static int altera_qspi_ofdata_to_platdata(struct udevice
*dev
)
350 struct altera_qspi_platdata
*pdata
= dev_get_platdata(dev
);
351 void *blob
= (void *)gd
->fdt_blob
;
352 int node
= dev_of_offset(dev
);
353 const char *list
, *end
;
356 unsigned long addr
, size
;
357 int parent
, addrc
, sizec
;
361 * decode regs. there are multiple reg tuples, and they need to
362 * match with reg-names.
364 parent
= fdt_parent_offset(blob
, node
);
365 fdt_support_default_count_cells(blob
, parent
, &addrc
, &sizec
);
366 list
= fdt_getprop(blob
, node
, "reg-names", &len
);
370 cell
= fdt_getprop(blob
, node
, "reg", &len
);
375 addr
= fdt_translate_address((void *)blob
,
377 size
= fdt_addr_to_cpu(cell
[idx
+ addrc
]);
378 base
= map_physmem(addr
, size
, MAP_NOCACHE
);
380 if (strcmp(list
, "avl_csr") == 0) {
382 } else if (strcmp(list
, "avl_mem") == 0) {
386 idx
+= addrc
+ sizec
;
393 static const struct udevice_id altera_qspi_ids
[] = {
394 { .compatible
= "altr,quadspi-1.0" },
398 U_BOOT_DRIVER(altera_qspi
) = {
399 .name
= "altera_qspi",
401 .of_match
= altera_qspi_ids
,
402 .ofdata_to_platdata
= altera_qspi_ofdata_to_platdata
,
403 .platdata_auto_alloc_size
= sizeof(struct altera_qspi_platdata
),
404 .probe
= altera_qspi_probe
,