^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2005, Intec Automation Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2014, Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/mtd/spi-nor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) static const struct flash_info xilinx_parts[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /* Xilinx S3AN Internal Flash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) { "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) { "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * This code converts an address to the Default Address Mode, that has non
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * power of two page sizes. We must support this mode because it is the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * mode supported by Xilinx tools, it can access the whole flash area and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * changing over to the Power-of-two mode is irreversible and corrupts the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * original data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Addr can safely be unsigned int, the biggest S3AN device is smaller than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 4 MiB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) u32 offset, page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) offset = addr % nor->page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) page = addr / nor->page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) page <<= (nor->page_size > 512) ? 10 : 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return page | offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int xilinx_nor_setup(struct spi_nor *nor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const struct spi_nor_hwcaps *hwcaps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = spi_nor_xread_sr(nor, nor->bouncebuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) nor->erase_opcode = SPINOR_OP_XSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) nor->program_opcode = SPINOR_OP_XPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) nor->read_opcode = SPINOR_OP_READ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * This flashes have a page size of 264 or 528 bytes (known as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * Default addressing mode). It can be changed to a more standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Power of two mode where the page size is 256/512. This comes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * with a price: there is 3% less of space, the data is corrupted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * and the page size cannot be changed back to default addressing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * The current addressing mode can be read from the XRDSR register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * and should not be changed, because is a destructive operation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (nor->bouncebuf[0] & XSR_PAGESIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* Flash in Power of 2 mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) nor->page_size = (nor->page_size == 264) ? 256 : 512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) nor->mtd.writebufsize = nor->page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) nor->mtd.erasesize = 8 * nor->page_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* Flash in Default addressing mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) nor->params->convert_addr = s3an_convert_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) nor->mtd.erasesize = nor->info->sector_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) nor->params->setup = xilinx_nor_setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static const struct spi_nor_fixups xilinx_fixups = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) .post_sfdp = xilinx_post_sfdp_fixups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) const struct spi_nor_manufacturer spi_nor_xilinx = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .name = "xilinx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .parts = xilinx_parts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .nparts = ARRAY_SIZE(xilinx_parts),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .fixups = &xilinx_fixups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };