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