mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.7 KiB
94 lines
2.7 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
/* |
|
* Copyright (C) 2005, Intec Automation Inc. |
|
* Copyright (C) 2014, Freescale Semiconductor, Inc. |
|
*/ |
|
|
|
#include <linux/mtd/spi-nor.h> |
|
|
|
#include "core.h" |
|
|
|
static const struct flash_info xilinx_parts[] = { |
|
/* Xilinx S3AN Internal Flash */ |
|
{ "3S50AN", S3AN_INFO(0x1f2200, 64, 264) }, |
|
{ "3S200AN", S3AN_INFO(0x1f2400, 256, 264) }, |
|
{ "3S400AN", S3AN_INFO(0x1f2400, 256, 264) }, |
|
{ "3S700AN", S3AN_INFO(0x1f2500, 512, 264) }, |
|
{ "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) }, |
|
}; |
|
|
|
/* |
|
* This code converts an address to the Default Address Mode, that has non |
|
* power of two page sizes. We must support this mode because it is the default |
|
* mode supported by Xilinx tools, it can access the whole flash area and |
|
* changing over to the Power-of-two mode is irreversible and corrupts the |
|
* original data. |
|
* Addr can safely be unsigned int, the biggest S3AN device is smaller than |
|
* 4 MiB. |
|
*/ |
|
static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr) |
|
{ |
|
u32 offset, page; |
|
|
|
offset = addr % nor->page_size; |
|
page = addr / nor->page_size; |
|
page <<= (nor->page_size > 512) ? 10 : 9; |
|
|
|
return page | offset; |
|
} |
|
|
|
static int xilinx_nor_setup(struct spi_nor *nor, |
|
const struct spi_nor_hwcaps *hwcaps) |
|
{ |
|
int ret; |
|
|
|
ret = spi_nor_xread_sr(nor, nor->bouncebuf); |
|
if (ret) |
|
return ret; |
|
|
|
nor->erase_opcode = SPINOR_OP_XSE; |
|
nor->program_opcode = SPINOR_OP_XPP; |
|
nor->read_opcode = SPINOR_OP_READ; |
|
nor->flags |= SNOR_F_NO_OP_CHIP_ERASE; |
|
|
|
/* |
|
* This flashes have a page size of 264 or 528 bytes (known as |
|
* Default addressing mode). It can be changed to a more standard |
|
* Power of two mode where the page size is 256/512. This comes |
|
* with a price: there is 3% less of space, the data is corrupted |
|
* and the page size cannot be changed back to default addressing |
|
* mode. |
|
* |
|
* The current addressing mode can be read from the XRDSR register |
|
* and should not be changed, because is a destructive operation. |
|
*/ |
|
if (nor->bouncebuf[0] & XSR_PAGESIZE) { |
|
/* Flash in Power of 2 mode */ |
|
nor->page_size = (nor->page_size == 264) ? 256 : 512; |
|
nor->mtd.writebufsize = nor->page_size; |
|
nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors; |
|
nor->mtd.erasesize = 8 * nor->page_size; |
|
} else { |
|
/* Flash in Default addressing mode */ |
|
nor->params->convert_addr = s3an_convert_addr; |
|
nor->mtd.erasesize = nor->info->sector_size; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static void xilinx_post_sfdp_fixups(struct spi_nor *nor) |
|
{ |
|
nor->params->setup = xilinx_nor_setup; |
|
} |
|
|
|
static const struct spi_nor_fixups xilinx_fixups = { |
|
.post_sfdp = xilinx_post_sfdp_fixups, |
|
}; |
|
|
|
const struct spi_nor_manufacturer spi_nor_xilinx = { |
|
.name = "xilinx", |
|
.parts = xilinx_parts, |
|
.nparts = ARRAY_SIZE(xilinx_parts), |
|
.fixups = &xilinx_fixups, |
|
};
|
|
|