18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2005, Intec Automation Inc. 48c2ecf20Sopenharmony_ci * Copyright (C) 2014, Freescale Semiconductor, Inc. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/mtd/spi-nor.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include "core.h" 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/* 128c2ecf20Sopenharmony_ci * The Atmel AT25FS010/AT25FS040 parts have some weird configuration for the 138c2ecf20Sopenharmony_ci * block protection bits. We don't support them. But legacy behavior in linux 148c2ecf20Sopenharmony_ci * is to unlock the whole flash array on startup. Therefore, we have to support 158c2ecf20Sopenharmony_ci * exactly this operation. 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_cistatic int atmel_at25fs_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 208c2ecf20Sopenharmony_ci} 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic int atmel_at25fs_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) 238c2ecf20Sopenharmony_ci{ 248c2ecf20Sopenharmony_ci int ret; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci /* We only support unlocking the whole flash array */ 278c2ecf20Sopenharmony_ci if (ofs || len != nor->params->size) 288c2ecf20Sopenharmony_ci return -EINVAL; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci /* Write 0x00 to the status register to disable write protection */ 318c2ecf20Sopenharmony_ci ret = spi_nor_write_sr_and_check(nor, 0); 328c2ecf20Sopenharmony_ci if (ret) 338c2ecf20Sopenharmony_ci dev_dbg(nor->dev, "unable to clear BP bits, WP# asserted?\n"); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci return ret; 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic int atmel_at25fs_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic const struct spi_nor_locking_ops atmel_at25fs_locking_ops = { 448c2ecf20Sopenharmony_ci .lock = atmel_at25fs_lock, 458c2ecf20Sopenharmony_ci .unlock = atmel_at25fs_unlock, 468c2ecf20Sopenharmony_ci .is_locked = atmel_at25fs_is_locked, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic void atmel_at25fs_default_init(struct spi_nor *nor) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci nor->params->locking_ops = &atmel_at25fs_locking_ops; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic const struct spi_nor_fixups atmel_at25fs_fixups = { 558c2ecf20Sopenharmony_ci .default_init = atmel_at25fs_default_init, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic const struct flash_info atmel_parts[] = { 598c2ecf20Sopenharmony_ci /* Atmel -- some are (confusingly) marketed as "DataFlash" */ 608c2ecf20Sopenharmony_ci { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K | SPI_NOR_HAS_LOCK) 618c2ecf20Sopenharmony_ci .fixups = &atmel_at25fs_fixups }, 628c2ecf20Sopenharmony_ci { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_HAS_LOCK) 638c2ecf20Sopenharmony_ci .fixups = &atmel_at25fs_fixups }, 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_HAS_LOCK) }, 668c2ecf20Sopenharmony_ci { "at25df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, 678c2ecf20Sopenharmony_ci { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, 688c2ecf20Sopenharmony_ci { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_LOCK) }, 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci { "at25sl321", INFO(0x1f4216, 0, 64 * 1024, 64, 718c2ecf20Sopenharmony_ci SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, 748c2ecf20Sopenharmony_ci { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_HAS_LOCK) }, 758c2ecf20Sopenharmony_ci { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_HAS_LOCK) }, 768c2ecf20Sopenharmony_ci { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ciconst struct spi_nor_manufacturer spi_nor_atmel = { 828c2ecf20Sopenharmony_ci .name = "atmel", 838c2ecf20Sopenharmony_ci .parts = atmel_parts, 848c2ecf20Sopenharmony_ci .nparts = ARRAY_SIZE(atmel_parts), 858c2ecf20Sopenharmony_ci}; 86