mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-02 19:06:44 +07:00
3dd8012a8e
Some flash support a bit in the status register that inverts protection so that it applies to the bottom of the flash, not the top. This yields additions to the protection range table, as noted in the comments. Because this feature is not universal to all flash that support lock/unlock, control it via a new flag. Signed-off-by: Brian Norris <computersforpeace@gmail.com> Tested-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
216 lines
7.6 KiB
C
216 lines
7.6 KiB
C
/*
|
|
* Copyright (C) 2014 Freescale Semiconductor, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*/
|
|
|
|
#ifndef __LINUX_MTD_SPI_NOR_H
|
|
#define __LINUX_MTD_SPI_NOR_H
|
|
|
|
#include <linux/bitops.h>
|
|
#include <linux/mtd/cfi.h>
|
|
#include <linux/mtd/mtd.h>
|
|
|
|
/*
|
|
* Manufacturer IDs
|
|
*
|
|
* The first byte returned from the flash after sending opcode SPINOR_OP_RDID.
|
|
* Sometimes these are the same as CFI IDs, but sometimes they aren't.
|
|
*/
|
|
#define SNOR_MFR_ATMEL CFI_MFR_ATMEL
|
|
#define SNOR_MFR_INTEL CFI_MFR_INTEL
|
|
#define SNOR_MFR_MICRON CFI_MFR_ST /* ST Micro <--> Micron */
|
|
#define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX
|
|
#define SNOR_MFR_SPANSION CFI_MFR_AMD
|
|
#define SNOR_MFR_SST CFI_MFR_SST
|
|
#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */
|
|
|
|
/*
|
|
* Note on opcode nomenclature: some opcodes have a format like
|
|
* SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
|
|
* of I/O lines used for the opcode, address, and data (respectively). The
|
|
* FUNCTION has an optional suffix of '4', to represent an opcode which
|
|
* requires a 4-byte (32-bit) address.
|
|
*/
|
|
|
|
/* Flash opcodes. */
|
|
#define SPINOR_OP_WREN 0x06 /* Write enable */
|
|
#define SPINOR_OP_RDSR 0x05 /* Read status register */
|
|
#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
|
|
#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
|
|
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
|
|
#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
|
|
#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
|
|
#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
|
|
#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
|
|
#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
|
|
#define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */
|
|
#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */
|
|
#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */
|
|
#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */
|
|
#define SPINOR_OP_RDCR 0x35 /* Read configuration register */
|
|
#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
|
|
|
|
/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
|
|
#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
|
|
#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
|
|
#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
|
|
#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
|
|
#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
|
|
#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
|
|
|
|
/* Used for SST flashes only. */
|
|
#define SPINOR_OP_BP 0x02 /* Byte program */
|
|
#define SPINOR_OP_WRDI 0x04 /* Write disable */
|
|
#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
|
|
|
|
/* Used for Macronix and Winbond flashes. */
|
|
#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
|
|
#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
|
|
|
|
/* Used for Spansion flashes only. */
|
|
#define SPINOR_OP_BRWR 0x17 /* Bank register write */
|
|
|
|
/* Used for Micron flashes only. */
|
|
#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */
|
|
#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */
|
|
|
|
/* Status Register bits. */
|
|
#define SR_WIP BIT(0) /* Write in progress */
|
|
#define SR_WEL BIT(1) /* Write enable latch */
|
|
/* meaning of other SR_* bits may differ between vendors */
|
|
#define SR_BP0 BIT(2) /* Block protect 0 */
|
|
#define SR_BP1 BIT(3) /* Block protect 1 */
|
|
#define SR_BP2 BIT(4) /* Block protect 2 */
|
|
#define SR_TB BIT(5) /* Top/Bottom protect */
|
|
#define SR_SRWD BIT(7) /* SR write protect */
|
|
|
|
#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */
|
|
|
|
/* Enhanced Volatile Configuration Register bits */
|
|
#define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */
|
|
|
|
/* Flag Status Register bits */
|
|
#define FSR_READY BIT(7)
|
|
|
|
/* Configuration Register bits. */
|
|
#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */
|
|
|
|
enum read_mode {
|
|
SPI_NOR_NORMAL = 0,
|
|
SPI_NOR_FAST,
|
|
SPI_NOR_DUAL,
|
|
SPI_NOR_QUAD,
|
|
};
|
|
|
|
#define SPI_NOR_MAX_CMD_SIZE 8
|
|
enum spi_nor_ops {
|
|
SPI_NOR_OPS_READ = 0,
|
|
SPI_NOR_OPS_WRITE,
|
|
SPI_NOR_OPS_ERASE,
|
|
SPI_NOR_OPS_LOCK,
|
|
SPI_NOR_OPS_UNLOCK,
|
|
};
|
|
|
|
enum spi_nor_option_flags {
|
|
SNOR_F_USE_FSR = BIT(0),
|
|
SNOR_F_HAS_SR_TB = BIT(1),
|
|
};
|
|
|
|
/**
|
|
* struct spi_nor - Structure for defining a the SPI NOR layer
|
|
* @mtd: point to a mtd_info structure
|
|
* @lock: the lock for the read/write/erase/lock/unlock operations
|
|
* @dev: point to a spi device, or a spi nor controller device.
|
|
* @page_size: the page size of the SPI NOR
|
|
* @addr_width: number of address bytes
|
|
* @erase_opcode: the opcode for erasing a sector
|
|
* @read_opcode: the read opcode
|
|
* @read_dummy: the dummy needed by the read operation
|
|
* @program_opcode: the program opcode
|
|
* @flash_read: the mode of the read
|
|
* @sst_write_second: used by the SST write operation
|
|
* @flags: flag options for the current SPI-NOR (SNOR_F_*)
|
|
* @cmd_buf: used by the write_reg
|
|
* @prepare: [OPTIONAL] do some preparations for the
|
|
* read/write/erase/lock/unlock operations
|
|
* @unprepare: [OPTIONAL] do some post work after the
|
|
* read/write/erase/lock/unlock operations
|
|
* @read_reg: [DRIVER-SPECIFIC] read out the register
|
|
* @write_reg: [DRIVER-SPECIFIC] write data to the register
|
|
* @read: [DRIVER-SPECIFIC] read data from the SPI NOR
|
|
* @write: [DRIVER-SPECIFIC] write data to the SPI NOR
|
|
* @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR
|
|
* at the offset @offs; if not provided by the driver,
|
|
* spi-nor will send the erase opcode via write_reg()
|
|
* @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR
|
|
* @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR
|
|
* @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is
|
|
* completely locked
|
|
* @priv: the private data
|
|
*/
|
|
struct spi_nor {
|
|
struct mtd_info mtd;
|
|
struct mutex lock;
|
|
struct device *dev;
|
|
u32 page_size;
|
|
u8 addr_width;
|
|
u8 erase_opcode;
|
|
u8 read_opcode;
|
|
u8 read_dummy;
|
|
u8 program_opcode;
|
|
enum read_mode flash_read;
|
|
bool sst_write_second;
|
|
u32 flags;
|
|
u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
|
|
|
|
int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|
|
void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
|
|
int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
|
|
int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
|
|
|
|
int (*read)(struct spi_nor *nor, loff_t from,
|
|
size_t len, size_t *retlen, u_char *read_buf);
|
|
void (*write)(struct spi_nor *nor, loff_t to,
|
|
size_t len, size_t *retlen, const u_char *write_buf);
|
|
int (*erase)(struct spi_nor *nor, loff_t offs);
|
|
|
|
int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
|
|
int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
|
|
int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
|
|
|
|
void *priv;
|
|
};
|
|
|
|
static inline void spi_nor_set_flash_node(struct spi_nor *nor,
|
|
struct device_node *np)
|
|
{
|
|
mtd_set_of_node(&nor->mtd, np);
|
|
}
|
|
|
|
static inline struct device_node *spi_nor_get_flash_node(struct spi_nor *nor)
|
|
{
|
|
return mtd_get_of_node(&nor->mtd);
|
|
}
|
|
|
|
/**
|
|
* spi_nor_scan() - scan the SPI NOR
|
|
* @nor: the spi_nor structure
|
|
* @name: the chip type name
|
|
* @mode: the read mode supported by the driver
|
|
*
|
|
* The drivers can use this fuction to scan the SPI NOR.
|
|
* In the scanning, it will try to get all the necessary information to
|
|
* fill the mtd_info{} and the spi_nor{}.
|
|
*
|
|
* The chip type name can be provided through the @name parameter.
|
|
*
|
|
* Return: 0 for success, others for failure.
|
|
*/
|
|
int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode);
|
|
|
|
#endif
|