1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2005, Intec Automation Inc. 4 * Copyright (C) 2014, Freescale Semiconductor, Inc. 5 */ 6 7#include <linux/mtd/spi-nor.h> 8 9#include "core.h" 10 11/* 12 * The Atmel AT25FS010/AT25FS040 parts have some weird configuration for the 13 * block protection bits. We don't support them. But legacy behavior in linux 14 * is to unlock the whole flash array on startup. Therefore, we have to support 15 * exactly this operation. 16 */ 17static int atmel_at25fs_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) 18{ 19 return -EOPNOTSUPP; 20} 21 22static int atmel_at25fs_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) 23{ 24 int ret; 25 26 /* We only support unlocking the whole flash array */ 27 if (ofs || len != nor->params->size) 28 return -EINVAL; 29 30 /* Write 0x00 to the status register to disable write protection */ 31 ret = spi_nor_write_sr_and_check(nor, 0); 32 if (ret) 33 dev_dbg(nor->dev, "unable to clear BP bits, WP# asserted?\n"); 34 35 return ret; 36} 37 38static int atmel_at25fs_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) 39{ 40 return -EOPNOTSUPP; 41} 42 43static const struct spi_nor_locking_ops atmel_at25fs_locking_ops = { 44 .lock = atmel_at25fs_lock, 45 .unlock = atmel_at25fs_unlock, 46 .is_locked = atmel_at25fs_is_locked, 47}; 48 49static void atmel_at25fs_default_init(struct spi_nor *nor) 50{ 51 nor->params->locking_ops = &atmel_at25fs_locking_ops; 52} 53 54static const struct spi_nor_fixups atmel_at25fs_fixups = { 55 .default_init = atmel_at25fs_default_init, 56}; 57 58static const struct flash_info atmel_parts[] = { 59 /* Atmel -- some are (confusingly) marketed as "DataFlash" */ 60 { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K | SPI_NOR_HAS_LOCK) 61 .fixups = &atmel_at25fs_fixups }, 62 { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_HAS_LOCK) 63 .fixups = &atmel_at25fs_fixups }, 64 65 { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_HAS_LOCK) }, 66 { "at25df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, 67 { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, 68 { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_LOCK) }, 69 70 { "at25sl321", INFO(0x1f4216, 0, 64 * 1024, 64, 71 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, 72 73 { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, 74 { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_HAS_LOCK) }, 75 { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_HAS_LOCK) }, 76 { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) }, 77 78 { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, 79}; 80 81const struct spi_nor_manufacturer spi_nor_atmel = { 82 .name = "atmel", 83 .parts = atmel_parts, 84 .nparts = ARRAY_SIZE(atmel_parts), 85}; 86