xref: /openbmc/linux/drivers/mtd/spi-nor/issi.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
10a371981SBoris Brezillon // SPDX-License-Identifier: GPL-2.0
20a371981SBoris Brezillon /*
30a371981SBoris Brezillon  * Copyright (C) 2005, Intec Automation Inc.
40a371981SBoris Brezillon  * Copyright (C) 2014, Freescale Semiconductor, Inc.
50a371981SBoris Brezillon  */
60a371981SBoris Brezillon 
70a371981SBoris Brezillon #include <linux/mtd/spi-nor.h>
80a371981SBoris Brezillon 
90a371981SBoris Brezillon #include "core.h"
100a371981SBoris Brezillon 
110a371981SBoris Brezillon static int
is25lp256_post_bfpt_fixups(struct spi_nor * nor,const struct sfdp_parameter_header * bfpt_header,const struct sfdp_bfpt * bfpt)120a371981SBoris Brezillon is25lp256_post_bfpt_fixups(struct spi_nor *nor,
130a371981SBoris Brezillon 			   const struct sfdp_parameter_header *bfpt_header,
14a580293aSTudor Ambarus 			   const struct sfdp_bfpt *bfpt)
150a371981SBoris Brezillon {
160a371981SBoris Brezillon 	/*
17c452d498STudor Ambarus 	 * IS25LP256 supports 4B opcodes, but the BFPT advertises
18c452d498STudor Ambarus 	 * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY.
19c452d498STudor Ambarus 	 * Overwrite the number of address bytes advertised by the BFPT.
200a371981SBoris Brezillon 	 */
2186d4cdf8STakahiro Kuwano 	if ((bfpt->dwords[SFDP_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
220a371981SBoris Brezillon 		BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
2347c6f8a6STudor Ambarus 		nor->params->addr_nbytes = 4;
240a371981SBoris Brezillon 
250a371981SBoris Brezillon 	return 0;
260a371981SBoris Brezillon }
270a371981SBoris Brezillon 
2865b54ff6STudor Ambarus static const struct spi_nor_fixups is25lp256_fixups = {
290a371981SBoris Brezillon 	.post_bfpt = is25lp256_post_bfpt_fixups,
300a371981SBoris Brezillon };
310a371981SBoris Brezillon 
pm25lv_nor_late_init(struct spi_nor * nor)32*d534fd97STakahiro Kuwano static int pm25lv_nor_late_init(struct spi_nor *nor)
3377d4ac6dSMichael Walle {
3477d4ac6dSMichael Walle 	struct spi_nor_erase_map *map = &nor->params->erase_map;
3577d4ac6dSMichael Walle 	int i;
3677d4ac6dSMichael Walle 
3777d4ac6dSMichael Walle 	/* The PM25LV series has a different 4k sector erase opcode */
3877d4ac6dSMichael Walle 	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
3977d4ac6dSMichael Walle 		if (map->erase_type[i].size == 4096)
4077d4ac6dSMichael Walle 			map->erase_type[i].opcode = SPINOR_OP_BE_4K_PMC;
41*d534fd97STakahiro Kuwano 
42*d534fd97STakahiro Kuwano 	return 0;
4377d4ac6dSMichael Walle }
4477d4ac6dSMichael Walle 
4577d4ac6dSMichael Walle static const struct spi_nor_fixups pm25lv_nor_fixups = {
4677d4ac6dSMichael Walle 	.late_init = pm25lv_nor_late_init,
4777d4ac6dSMichael Walle };
4877d4ac6dSMichael Walle 
49cc5af02fSMichael Walle static const struct flash_info issi_nor_parts[] = {
500a371981SBoris Brezillon 	/* ISSI */
51ec1c0e99STudor Ambarus 	{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2)
52ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K) },
53ec1c0e99STudor Ambarus 	{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8)
54ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
55ec1c0e99STudor Ambarus 	{ "is25lp016d", INFO(0x9d6015, 0, 64 * 1024,  32)
56ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
57ec1c0e99STudor Ambarus 	{ "is25lp080d", INFO(0x9d6014, 0, 64 * 1024,  16)
58ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
59ec1c0e99STudor Ambarus 	{ "is25lp032",  INFO(0x9d6016, 0, 64 * 1024,  64)
60ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
61ec1c0e99STudor Ambarus 	{ "is25lp064",  INFO(0x9d6017, 0, 64 * 1024, 128)
62ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
63ec1c0e99STudor Ambarus 	{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256)
64ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
65ec1c0e99STudor Ambarus 	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512)
6622bfe945STudor Ambarus 		PARSE_SFDP
67ec1c0e99STudor Ambarus 		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
680a371981SBoris Brezillon 		.fixups = &is25lp256_fixups },
69ec1c0e99STudor Ambarus 	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64)
70ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
71ec1c0e99STudor Ambarus 	{ "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128)
72ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
73ec1c0e99STudor Ambarus 	{ "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256)
74ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
75a30f53d8SSudip Mukherjee 	{ "is25wp256", INFO(0x9d7019, 0, 0, 0)
76a30f53d8SSudip Mukherjee 		PARSE_SFDP
77ec1c0e99STudor Ambarus 		FIXUP_FLAGS(SPI_NOR_4B_OPCODES)
781799cd85SSudip Mukherjee 		FLAGS(SPI_NOR_QUAD_PP)
790a371981SBoris Brezillon 		.fixups = &is25lp256_fixups },
800a371981SBoris Brezillon 
810a371981SBoris Brezillon 	/* PMC */
82ec1c0e99STudor Ambarus 	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2)
8377d4ac6dSMichael Walle 		NO_SFDP_FLAGS(SECT_4K)
8477d4ac6dSMichael Walle 		.fixups = &pm25lv_nor_fixups
8577d4ac6dSMichael Walle 	},
86ec1c0e99STudor Ambarus 	{ "pm25lv010",   INFO(0,        0, 32 * 1024,    4)
8777d4ac6dSMichael Walle 		NO_SFDP_FLAGS(SECT_4K)
8877d4ac6dSMichael Walle 		.fixups = &pm25lv_nor_fixups
8977d4ac6dSMichael Walle 	},
90ec1c0e99STudor Ambarus 	{ "pm25lq032",   INFO(0x7f9d46, 0, 64 * 1024,   64)
91ec1c0e99STudor Ambarus 		NO_SFDP_FLAGS(SECT_4K) },
920a371981SBoris Brezillon };
930a371981SBoris Brezillon 
issi_nor_default_init(struct spi_nor * nor)94cc5af02fSMichael Walle static void issi_nor_default_init(struct spi_nor *nor)
950a371981SBoris Brezillon {
96829ec640STudor Ambarus 	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
970a371981SBoris Brezillon }
980a371981SBoris Brezillon 
990a371981SBoris Brezillon static const struct spi_nor_fixups issi_fixups = {
100cc5af02fSMichael Walle 	.default_init = issi_nor_default_init,
1010a371981SBoris Brezillon };
1020a371981SBoris Brezillon 
1030a371981SBoris Brezillon const struct spi_nor_manufacturer spi_nor_issi = {
1040a371981SBoris Brezillon 	.name = "issi",
105cc5af02fSMichael Walle 	.parts = issi_nor_parts,
106cc5af02fSMichael Walle 	.nparts = ARRAY_SIZE(issi_nor_parts),
1070a371981SBoris Brezillon 	.fixups = &issi_fixups,
1080a371981SBoris Brezillon };
109