1 /* 2 * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <console.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <fdt_support.h> 12 #include <flash.h> 13 #include <mtd.h> 14 #include <asm/io.h> 15 16 DECLARE_GLOBAL_DATA_PTR; 17 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) 25 26 /* 27 * The QUADSPI_MEM_OP register is used to do memory protect and erase operations 28 */ 29 #define QUADSPI_MEM_OP_BULK_ERASE 0x00000001 30 #define QUADSPI_MEM_OP_SECTOR_ERASE 0x00000002 31 #define QUADSPI_MEM_OP_SECTOR_PROTECT 0x00000003 32 33 /* 34 * The QUADSPI_ISR register is used to determine whether an invalid write or 35 * erase operation trigerred an interrupt 36 */ 37 #define QUADSPI_ISR_ILLEGAL_ERASE BIT(0) 38 #define QUADSPI_ISR_ILLEGAL_WRITE BIT(1) 39 40 struct altera_qspi_regs { 41 u32 rd_status; 42 u32 rd_sid; 43 u32 rd_rdid; 44 u32 mem_op; 45 u32 isr; 46 u32 imr; 47 u32 chip_select; 48 }; 49 50 struct altera_qspi_platdata { 51 struct altera_qspi_regs *regs; 52 void *base; 53 unsigned long size; 54 }; 55 56 static uint flash_verbose; 57 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* FLASH chips info */ 58 59 static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t *ofs, 60 uint64_t *len); 61 62 void flash_print_info(flash_info_t *info) 63 { 64 struct mtd_info *mtd = info->mtd; 65 loff_t ofs; 66 u64 len; 67 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); 72 if (len) { 73 printf(", protected %08llX +%llX", 74 info->start[0] + ofs, len); 75 } 76 putc('\n'); 77 } 78 79 void flash_set_verbose(uint v) 80 { 81 flash_verbose = v; 82 } 83 84 int flash_erase(flash_info_t *info, int s_first, int s_last) 85 { 86 struct mtd_info *mtd = info->mtd; 87 struct erase_info instr; 88 int ret; 89 90 memset(&instr, 0, sizeof(instr)); 91 instr.mtd = mtd; 92 instr.addr = mtd->erasesize * s_first; 93 instr.len = mtd->erasesize * (s_last + 1 - s_first); 94 flash_set_verbose(1); 95 ret = mtd_erase(mtd, &instr); 96 flash_set_verbose(0); 97 if (ret) 98 return ERR_PROTECTED; 99 100 puts(" done\n"); 101 return 0; 102 } 103 104 int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) 105 { 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; 111 size_t retlen; 112 int ret; 113 114 ret = mtd_write(mtd, to, cnt, &retlen, src); 115 if (ret) 116 return ERR_PROTECTED; 117 118 return 0; 119 } 120 121 unsigned long flash_init(void) 122 { 123 struct udevice *dev; 124 125 /* probe every MTD device */ 126 for (uclass_first_device(UCLASS_MTD, &dev); 127 dev; 128 uclass_next_device(&dev)) { 129 } 130 131 return flash_info[0].size; 132 } 133 134 static int altera_qspi_erase(struct mtd_info *mtd, struct erase_info *instr) 135 { 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; 142 u32 sect; 143 u32 stat; 144 u32 *flash, *last; 145 146 instr->state = MTD_ERASING; 147 addr &= ~(mtd->erasesize - 1); /* get lower aligned address */ 148 while (addr < end) { 149 if (ctrlc()) { 150 if (flash_verbose) 151 putc('\n'); 152 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; 153 instr->state = MTD_ERASE_FAILED; 154 mtd_erase_callback(instr); 155 return -EIO; 156 } 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) 162 break; 163 flash++; 164 } 165 if (flash < last) { 166 sect = addr / mtd->erasesize; 167 sect <<= 8; 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); 179 return -EIO; 180 } 181 if (flash_verbose) 182 putc('.'); 183 } else { 184 if (flash_verbose) 185 putc(','); 186 } 187 addr += mtd->erasesize; 188 } 189 instr->state = MTD_ERASE_DONE; 190 mtd_erase_callback(instr); 191 192 return 0; 193 } 194 195 static int altera_qspi_read(struct mtd_info *mtd, loff_t from, size_t len, 196 size_t *retlen, u_char *buf) 197 { 198 struct udevice *dev = mtd->dev; 199 struct altera_qspi_platdata *pdata = dev_get_platdata(dev); 200 201 memcpy_fromio(buf, pdata->base + from, len); 202 *retlen = len; 203 204 return 0; 205 } 206 207 static int altera_qspi_write(struct mtd_info *mtd, loff_t to, size_t len, 208 size_t *retlen, const u_char *buf) 209 { 210 struct udevice *dev = mtd->dev; 211 struct altera_qspi_platdata *pdata = dev_get_platdata(dev); 212 struct altera_qspi_regs *regs = pdata->regs; 213 u32 stat; 214 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 */ 222 return -EIO; 223 } 224 *retlen = len; 225 226 return 0; 227 } 228 229 static void altera_qspi_sync(struct mtd_info *mtd) 230 { 231 } 232 233 static void altera_qspi_get_locked_range(struct mtd_info *mtd, loff_t *ofs, 234 uint64_t *len) 235 { 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); 244 245 *ofs = 0; 246 *len = 0; 247 if (pow) { 248 *len = mtd->erasesize << (pow - 1); 249 if (*len > mtd->size) 250 *len = mtd->size; 251 if (!(stat & QUADSPI_SR_TB)) 252 *ofs = mtd->size - *len; 253 } 254 } 255 256 static int altera_qspi_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 257 { 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; 262 u32 num_sectors; 263 u32 mem_op; 264 u32 sr_bp; 265 u32 sr_tb; 266 267 num_sectors = mtd->size / mtd->erasesize; 268 sector_start = ofs / mtd->erasesize; 269 sector_end = (ofs + len) / mtd->erasesize; 270 271 if (sector_start >= num_sectors / 2) { 272 sr_bp = fls(num_sectors - 1 - sector_start) + 1; 273 sr_tb = 0; 274 } else if (sector_end < num_sectors / 2) { 275 sr_bp = fls(sector_end) + 1; 276 sr_tb = 1; 277 } else { 278 sr_bp = 15; 279 sr_tb = 0; 280 } 281 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); 286 287 return 0; 288 } 289 290 static int altera_qspi_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 291 { 292 struct udevice *dev = mtd->dev; 293 struct altera_qspi_platdata *pdata = dev_get_platdata(dev); 294 struct altera_qspi_regs *regs = pdata->regs; 295 u32 mem_op; 296 297 mem_op = QUADSPI_MEM_OP_SECTOR_PROTECT; 298 debug("unlock %08x\n", mem_op); 299 writel(mem_op, ®s->mem_op); 300 301 return 0; 302 } 303 304 static int altera_qspi_probe(struct udevice *dev) 305 { 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]; 311 u32 rdid; 312 int i; 313 314 rdid = readl(®s->rd_rdid); 315 debug("rdid %x\n", rdid); 316 317 mtd = dev_get_uclass_priv(dev); 318 mtd->dev = dev; 319 mtd->name = "nor0"; 320 mtd->type = MTD_NORFLASH; 321 mtd->flags = MTD_CAP_NORFLASH; 322 mtd->size = 1 << ((rdid & 0xff) - 6); 323 mtd->writesize = 1; 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)) 334 return -ENOMEM; 335 336 flash->mtd = 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; 344 345 return 0; 346 } 347 348 static int altera_qspi_ofdata_to_platdata(struct udevice *dev) 349 { 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; 354 const fdt32_t *cell; 355 void *base; 356 unsigned long addr, size; 357 int parent, addrc, sizec; 358 int len, idx; 359 360 /* 361 * decode regs. there are multiple reg tuples, and they need to 362 * match with reg-names. 363 */ 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); 367 if (!list) 368 return -ENOENT; 369 end = list + len; 370 cell = fdt_getprop(blob, node, "reg", &len); 371 if (!cell) 372 return -ENOENT; 373 idx = 0; 374 while (list < end) { 375 addr = fdt_translate_address((void *)blob, 376 node, cell + idx); 377 size = fdt_addr_to_cpu(cell[idx + addrc]); 378 base = map_physmem(addr, size, MAP_NOCACHE); 379 len = strlen(list); 380 if (strcmp(list, "avl_csr") == 0) { 381 pdata->regs = base; 382 } else if (strcmp(list, "avl_mem") == 0) { 383 pdata->base = base; 384 pdata->size = size; 385 } 386 idx += addrc + sizec; 387 list += (len + 1); 388 } 389 390 return 0; 391 } 392 393 static const struct udevice_id altera_qspi_ids[] = { 394 { .compatible = "altr,quadspi-1.0" }, 395 {} 396 }; 397 398 U_BOOT_DRIVER(altera_qspi) = { 399 .name = "altera_qspi", 400 .id = UCLASS_MTD, 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, 405 }; 406