12d47cac1SBoris Brezillon // SPDX-License-Identifier: GPL-2.0
22d47cac1SBoris Brezillon /*
32d47cac1SBoris Brezillon * Copyright (C) 2005, Intec Automation Inc.
42d47cac1SBoris Brezillon * Copyright (C) 2014, Freescale Semiconductor, Inc.
52d47cac1SBoris Brezillon */
62d47cac1SBoris Brezillon
72d47cac1SBoris Brezillon #include <linux/mtd/spi-nor.h>
82d47cac1SBoris Brezillon
92d47cac1SBoris Brezillon #include "core.h"
102d47cac1SBoris Brezillon
118b7a2e00SMichael Walle #define XILINX_OP_SE 0x50 /* Sector erase */
128b7a2e00SMichael Walle #define XILINX_OP_PP 0x82 /* Page program */
138b7a2e00SMichael Walle #define XILINX_OP_RDSR 0xd7 /* Read status register */
148b4195cdSMichael Walle
158b4195cdSMichael Walle #define XSR_PAGESIZE BIT(0) /* Page size in Po2 or Linear */
168b4195cdSMichael Walle #define XSR_RDY BIT(7) /* Ready */
178b4195cdSMichael Walle
18c0abb861STudor Ambarus #define XILINX_RDSR_OP(buf) \
19c0abb861STudor Ambarus SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0), \
20c0abb861STudor Ambarus SPI_MEM_OP_NO_ADDR, \
21c0abb861STudor Ambarus SPI_MEM_OP_NO_DUMMY, \
22c0abb861STudor Ambarus SPI_MEM_OP_DATA_IN(1, buf, 0))
23c0abb861STudor Ambarus
248b4195cdSMichael Walle #define S3AN_INFO(_jedec_id, _n_sectors, _page_size) \
258b4195cdSMichael Walle .id = { \
268b4195cdSMichael Walle ((_jedec_id) >> 16) & 0xff, \
278b4195cdSMichael Walle ((_jedec_id) >> 8) & 0xff, \
288b4195cdSMichael Walle (_jedec_id) & 0xff \
298b4195cdSMichael Walle }, \
308b4195cdSMichael Walle .id_len = 3, \
318b4195cdSMichael Walle .sector_size = (8 * (_page_size)), \
328b4195cdSMichael Walle .n_sectors = (_n_sectors), \
338b4195cdSMichael Walle .page_size = (_page_size), \
349d6c5d64SMiquel Raynal .n_banks = 1, \
35c452d498STudor Ambarus .addr_nbytes = 3, \
368b4195cdSMichael Walle .flags = SPI_NOR_NO_FR
378b4195cdSMichael Walle
388b4195cdSMichael Walle /* Xilinx S3AN share MFR with Atmel SPI NOR */
3945acce20SMichael Walle static const struct flash_info xilinx_nor_parts[] = {
402d47cac1SBoris Brezillon /* Xilinx S3AN Internal Flash */
412d47cac1SBoris Brezillon { "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
422d47cac1SBoris Brezillon { "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
432d47cac1SBoris Brezillon { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
442d47cac1SBoris Brezillon { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
452d47cac1SBoris Brezillon { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
462d47cac1SBoris Brezillon };
472d47cac1SBoris Brezillon
482d47cac1SBoris Brezillon /*
492d47cac1SBoris Brezillon * This code converts an address to the Default Address Mode, that has non
502d47cac1SBoris Brezillon * power of two page sizes. We must support this mode because it is the default
512d47cac1SBoris Brezillon * mode supported by Xilinx tools, it can access the whole flash area and
522d47cac1SBoris Brezillon * changing over to the Power-of-two mode is irreversible and corrupts the
532d47cac1SBoris Brezillon * original data.
542d47cac1SBoris Brezillon * Addr can safely be unsigned int, the biggest S3AN device is smaller than
552d47cac1SBoris Brezillon * 4 MiB.
562d47cac1SBoris Brezillon */
s3an_nor_convert_addr(struct spi_nor * nor,u32 addr)5745acce20SMichael Walle static u32 s3an_nor_convert_addr(struct spi_nor *nor, u32 addr)
582d47cac1SBoris Brezillon {
595854d4a6STudor Ambarus u32 page_size = nor->params->page_size;
602d47cac1SBoris Brezillon u32 offset, page;
612d47cac1SBoris Brezillon
625854d4a6STudor Ambarus offset = addr % page_size;
635854d4a6STudor Ambarus page = addr / page_size;
645854d4a6STudor Ambarus page <<= (page_size > 512) ? 10 : 9;
652d47cac1SBoris Brezillon
662d47cac1SBoris Brezillon return page | offset;
672d47cac1SBoris Brezillon }
682d47cac1SBoris Brezillon
698b4195cdSMichael Walle /**
708b7a2e00SMichael Walle * xilinx_nor_read_sr() - Read the Status Register on S3AN flashes.
718b4195cdSMichael Walle * @nor: pointer to 'struct spi_nor'.
728b4195cdSMichael Walle * @sr: pointer to a DMA-able buffer where the value of the
738b4195cdSMichael Walle * Status Register will be written.
748b4195cdSMichael Walle *
758b4195cdSMichael Walle * Return: 0 on success, -errno otherwise.
768b4195cdSMichael Walle */
xilinx_nor_read_sr(struct spi_nor * nor,u8 * sr)778b7a2e00SMichael Walle static int xilinx_nor_read_sr(struct spi_nor *nor, u8 *sr)
788b4195cdSMichael Walle {
798b4195cdSMichael Walle int ret;
808b4195cdSMichael Walle
818b4195cdSMichael Walle if (nor->spimem) {
82c0abb861STudor Ambarus struct spi_mem_op op = XILINX_RDSR_OP(sr);
838b4195cdSMichael Walle
848b4195cdSMichael Walle spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
858b4195cdSMichael Walle
868b4195cdSMichael Walle ret = spi_mem_exec_op(nor->spimem, &op);
878b4195cdSMichael Walle } else {
888b7a2e00SMichael Walle ret = spi_nor_controller_ops_read_reg(nor, XILINX_OP_RDSR, sr,
898b4195cdSMichael Walle 1);
908b4195cdSMichael Walle }
918b4195cdSMichael Walle
928b4195cdSMichael Walle if (ret)
9356b852e8SMichael Walle dev_dbg(nor->dev, "error %d reading SR\n", ret);
948b4195cdSMichael Walle
958b4195cdSMichael Walle return ret;
968b4195cdSMichael Walle }
978b4195cdSMichael Walle
988b4195cdSMichael Walle /**
998b7a2e00SMichael Walle * xilinx_nor_sr_ready() - Query the Status Register of the S3AN flash to see
1008b7a2e00SMichael Walle * if the flash is ready for new commands.
1018b4195cdSMichael Walle * @nor: pointer to 'struct spi_nor'.
1028b4195cdSMichael Walle *
1038b4195cdSMichael Walle * Return: 1 if ready, 0 if not ready, -errno on errors.
1048b4195cdSMichael Walle */
xilinx_nor_sr_ready(struct spi_nor * nor)1058b7a2e00SMichael Walle static int xilinx_nor_sr_ready(struct spi_nor *nor)
1068b4195cdSMichael Walle {
1078b4195cdSMichael Walle int ret;
1088b4195cdSMichael Walle
1098b7a2e00SMichael Walle ret = xilinx_nor_read_sr(nor, nor->bouncebuf);
1108b4195cdSMichael Walle if (ret)
1118b4195cdSMichael Walle return ret;
1128b4195cdSMichael Walle
1138b4195cdSMichael Walle return !!(nor->bouncebuf[0] & XSR_RDY);
1148b4195cdSMichael Walle }
1158b4195cdSMichael Walle
xilinx_nor_setup(struct spi_nor * nor,const struct spi_nor_hwcaps * hwcaps)1162d47cac1SBoris Brezillon static int xilinx_nor_setup(struct spi_nor *nor,
1172d47cac1SBoris Brezillon const struct spi_nor_hwcaps *hwcaps)
1182d47cac1SBoris Brezillon {
1195854d4a6STudor Ambarus u32 page_size;
1202d47cac1SBoris Brezillon int ret;
1212d47cac1SBoris Brezillon
1228b7a2e00SMichael Walle ret = xilinx_nor_read_sr(nor, nor->bouncebuf);
1232d47cac1SBoris Brezillon if (ret)
1242d47cac1SBoris Brezillon return ret;
1252d47cac1SBoris Brezillon
1268b7a2e00SMichael Walle nor->erase_opcode = XILINX_OP_SE;
1278b7a2e00SMichael Walle nor->program_opcode = XILINX_OP_PP;
1282d47cac1SBoris Brezillon nor->read_opcode = SPINOR_OP_READ;
1292d47cac1SBoris Brezillon nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
1302d47cac1SBoris Brezillon
1312d47cac1SBoris Brezillon /*
1322d47cac1SBoris Brezillon * This flashes have a page size of 264 or 528 bytes (known as
1332d47cac1SBoris Brezillon * Default addressing mode). It can be changed to a more standard
1342d47cac1SBoris Brezillon * Power of two mode where the page size is 256/512. This comes
1352d47cac1SBoris Brezillon * with a price: there is 3% less of space, the data is corrupted
1362d47cac1SBoris Brezillon * and the page size cannot be changed back to default addressing
1372d47cac1SBoris Brezillon * mode.
1382d47cac1SBoris Brezillon *
1392d47cac1SBoris Brezillon * The current addressing mode can be read from the XRDSR register
1402d47cac1SBoris Brezillon * and should not be changed, because is a destructive operation.
1412d47cac1SBoris Brezillon */
1422d47cac1SBoris Brezillon if (nor->bouncebuf[0] & XSR_PAGESIZE) {
1432d47cac1SBoris Brezillon /* Flash in Power of 2 mode */
1445854d4a6STudor Ambarus page_size = (nor->params->page_size == 264) ? 256 : 512;
1455854d4a6STudor Ambarus nor->params->page_size = page_size;
1465854d4a6STudor Ambarus nor->mtd.writebufsize = page_size;
147f656b419STudor Ambarus nor->params->size = 8 * page_size * nor->info->n_sectors;
1485854d4a6STudor Ambarus nor->mtd.erasesize = 8 * page_size;
1492d47cac1SBoris Brezillon } else {
1502d47cac1SBoris Brezillon /* Flash in Default addressing mode */
15145acce20SMichael Walle nor->params->convert_addr = s3an_nor_convert_addr;
1522d47cac1SBoris Brezillon nor->mtd.erasesize = nor->info->sector_size;
1532d47cac1SBoris Brezillon }
1542d47cac1SBoris Brezillon
1552d47cac1SBoris Brezillon return 0;
1562d47cac1SBoris Brezillon }
1572d47cac1SBoris Brezillon
xilinx_nor_late_init(struct spi_nor * nor)158*d534fd97STakahiro Kuwano static int xilinx_nor_late_init(struct spi_nor *nor)
1592d47cac1SBoris Brezillon {
160829ec640STudor Ambarus nor->params->setup = xilinx_nor_setup;
1618b7a2e00SMichael Walle nor->params->ready = xilinx_nor_sr_ready;
162*d534fd97STakahiro Kuwano
163*d534fd97STakahiro Kuwano return 0;
1642d47cac1SBoris Brezillon }
1652d47cac1SBoris Brezillon
16645acce20SMichael Walle static const struct spi_nor_fixups xilinx_nor_fixups = {
16745acce20SMichael Walle .late_init = xilinx_nor_late_init,
1682d47cac1SBoris Brezillon };
1692d47cac1SBoris Brezillon
1702d47cac1SBoris Brezillon const struct spi_nor_manufacturer spi_nor_xilinx = {
1712d47cac1SBoris Brezillon .name = "xilinx",
17245acce20SMichael Walle .parts = xilinx_nor_parts,
17345acce20SMichael Walle .nparts = ARRAY_SIZE(xilinx_nor_parts),
17445acce20SMichael Walle .fixups = &xilinx_nor_fixups,
1752d47cac1SBoris Brezillon };
176