Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (C) 2005, Intec Automation Inc.
0004  * Copyright (C) 2014, Freescale Semiconductor, Inc.
0005  */
0006 
0007 #include <linux/mtd/spi-nor.h>
0008 
0009 #include "core.h"
0010 
0011 #define XILINX_OP_SE        0x50    /* Sector erase */
0012 #define XILINX_OP_PP        0x82    /* Page program */
0013 #define XILINX_OP_RDSR      0xd7    /* Read status register */
0014 
0015 #define XSR_PAGESIZE        BIT(0)  /* Page size in Po2 or Linear */
0016 #define XSR_RDY         BIT(7)  /* Ready */
0017 
0018 #define XILINX_RDSR_OP(buf)                     \
0019     SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),           \
0020            SPI_MEM_OP_NO_ADDR,                  \
0021            SPI_MEM_OP_NO_DUMMY,                 \
0022            SPI_MEM_OP_DATA_IN(1, buf, 0))
0023 
0024 #define S3AN_INFO(_jedec_id, _n_sectors, _page_size)            \
0025         .id = {                         \
0026             ((_jedec_id) >> 16) & 0xff,         \
0027             ((_jedec_id) >> 8) & 0xff,          \
0028             (_jedec_id) & 0xff              \
0029             },                      \
0030         .id_len = 3,                        \
0031         .sector_size = (8 * (_page_size)),          \
0032         .n_sectors = (_n_sectors),              \
0033         .page_size = (_page_size),              \
0034         .addr_nbytes = 3,                   \
0035         .flags = SPI_NOR_NO_FR
0036 
0037 /* Xilinx S3AN share MFR with Atmel SPI NOR */
0038 static const struct flash_info xilinx_nor_parts[] = {
0039     /* Xilinx S3AN Internal Flash */
0040     { "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
0041     { "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
0042     { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
0043     { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
0044     { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
0045 };
0046 
0047 /*
0048  * This code converts an address to the Default Address Mode, that has non
0049  * power of two page sizes. We must support this mode because it is the default
0050  * mode supported by Xilinx tools, it can access the whole flash area and
0051  * changing over to the Power-of-two mode is irreversible and corrupts the
0052  * original data.
0053  * Addr can safely be unsigned int, the biggest S3AN device is smaller than
0054  * 4 MiB.
0055  */
0056 static u32 s3an_nor_convert_addr(struct spi_nor *nor, u32 addr)
0057 {
0058     u32 page_size = nor->params->page_size;
0059     u32 offset, page;
0060 
0061     offset = addr % page_size;
0062     page = addr / page_size;
0063     page <<= (page_size > 512) ? 10 : 9;
0064 
0065     return page | offset;
0066 }
0067 
0068 /**
0069  * xilinx_nor_read_sr() - Read the Status Register on S3AN flashes.
0070  * @nor:    pointer to 'struct spi_nor'.
0071  * @sr:     pointer to a DMA-able buffer where the value of the
0072  *              Status Register will be written.
0073  *
0074  * Return: 0 on success, -errno otherwise.
0075  */
0076 static int xilinx_nor_read_sr(struct spi_nor *nor, u8 *sr)
0077 {
0078     int ret;
0079 
0080     if (nor->spimem) {
0081         struct spi_mem_op op = XILINX_RDSR_OP(sr);
0082 
0083         spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
0084 
0085         ret = spi_mem_exec_op(nor->spimem, &op);
0086     } else {
0087         ret = spi_nor_controller_ops_read_reg(nor, XILINX_OP_RDSR, sr,
0088                               1);
0089     }
0090 
0091     if (ret)
0092         dev_dbg(nor->dev, "error %d reading SR\n", ret);
0093 
0094     return ret;
0095 }
0096 
0097 /**
0098  * xilinx_nor_sr_ready() - Query the Status Register of the S3AN flash to see
0099  * if the flash is ready for new commands.
0100  * @nor:    pointer to 'struct spi_nor'.
0101  *
0102  * Return: 1 if ready, 0 if not ready, -errno on errors.
0103  */
0104 static int xilinx_nor_sr_ready(struct spi_nor *nor)
0105 {
0106     int ret;
0107 
0108     ret = xilinx_nor_read_sr(nor, nor->bouncebuf);
0109     if (ret)
0110         return ret;
0111 
0112     return !!(nor->bouncebuf[0] & XSR_RDY);
0113 }
0114 
0115 static int xilinx_nor_setup(struct spi_nor *nor,
0116                 const struct spi_nor_hwcaps *hwcaps)
0117 {
0118     u32 page_size;
0119     int ret;
0120 
0121     ret = xilinx_nor_read_sr(nor, nor->bouncebuf);
0122     if (ret)
0123         return ret;
0124 
0125     nor->erase_opcode = XILINX_OP_SE;
0126     nor->program_opcode = XILINX_OP_PP;
0127     nor->read_opcode = SPINOR_OP_READ;
0128     nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
0129 
0130     /*
0131      * This flashes have a page size of 264 or 528 bytes (known as
0132      * Default addressing mode). It can be changed to a more standard
0133      * Power of two mode where the page size is 256/512. This comes
0134      * with a price: there is 3% less of space, the data is corrupted
0135      * and the page size cannot be changed back to default addressing
0136      * mode.
0137      *
0138      * The current addressing mode can be read from the XRDSR register
0139      * and should not be changed, because is a destructive operation.
0140      */
0141     if (nor->bouncebuf[0] & XSR_PAGESIZE) {
0142         /* Flash in Power of 2 mode */
0143         page_size = (nor->params->page_size == 264) ? 256 : 512;
0144         nor->params->page_size = page_size;
0145         nor->mtd.writebufsize = page_size;
0146         nor->params->size = 8 * page_size * nor->info->n_sectors;
0147         nor->mtd.erasesize = 8 * page_size;
0148     } else {
0149         /* Flash in Default addressing mode */
0150         nor->params->convert_addr = s3an_nor_convert_addr;
0151         nor->mtd.erasesize = nor->info->sector_size;
0152     }
0153 
0154     return 0;
0155 }
0156 
0157 static void xilinx_nor_late_init(struct spi_nor *nor)
0158 {
0159     nor->params->setup = xilinx_nor_setup;
0160     nor->params->ready = xilinx_nor_sr_ready;
0161 }
0162 
0163 static const struct spi_nor_fixups xilinx_nor_fixups = {
0164     .late_init = xilinx_nor_late_init,
0165 };
0166 
0167 const struct spi_nor_manufacturer spi_nor_xilinx = {
0168     .name = "xilinx",
0169     .parts = xilinx_nor_parts,
0170     .nparts = ARRAY_SIZE(xilinx_nor_parts),
0171     .fixups = &xilinx_nor_fixups,
0172 };