You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'spinor'
Addition of the spi-nor framework, plus updates to the ST SPI FSM driver.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
* Freescale Quad Serial Peripheral Interface(QuadSPI)
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,vf610-qspi"
|
||||
- reg : the first contains the register location and length,
|
||||
the second contains the memory mapping address and length
|
||||
- reg-names: Should contain the reg names "QuadSPI" and "QuadSPI-memory"
|
||||
- interrupts : Should contain the interrupt for the device
|
||||
- clocks : The clocks needed by the QuadSPI controller
|
||||
- clock-names : the name of the clocks
|
||||
|
||||
Optional properties:
|
||||
- fsl,qspi-has-second-chip: The controller has two buses, bus A and bus B.
|
||||
Each bus can be connected with two NOR flashes.
|
||||
Most of the time, each bus only has one NOR flash
|
||||
connected, this is the default case.
|
||||
But if there are two NOR flashes connected to the
|
||||
bus, you should enable this property.
|
||||
(Please check the board's schematic.)
|
||||
|
||||
Example:
|
||||
|
||||
qspi0: quadspi@40044000 {
|
||||
compatible = "fsl,vf610-qspi";
|
||||
reg = <0x40044000 0x1000>, <0x20000000 0x10000000>;
|
||||
reg-names = "QuadSPI", "QuadSPI-memory";
|
||||
interrupts = <0 24 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&clks VF610_CLK_QSPI0_EN>,
|
||||
<&clks VF610_CLK_QSPI0>;
|
||||
clock-names = "qspi_en", "qspi";
|
||||
|
||||
flash0: s25fl128s@0 {
|
||||
....
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
SPI NOR framework
|
||||
============================================
|
||||
|
||||
Part I - Why do we need this framework?
|
||||
---------------------------------------
|
||||
|
||||
SPI bus controllers (drivers/spi/) only deal with streams of bytes; the bus
|
||||
controller operates agnostic of the specific device attached. However, some
|
||||
controllers (such as Freescale's QuadSPI controller) cannot easily handle
|
||||
arbitrary streams of bytes, but rather are designed specifically for SPI NOR.
|
||||
|
||||
In particular, Freescale's QuadSPI controller must know the NOR commands to
|
||||
find the right LUT sequence. Unfortunately, the SPI subsystem has no notion of
|
||||
opcodes, addresses, or data payloads; a SPI controller simply knows to send or
|
||||
receive bytes (Tx and Rx). Therefore, we must define a new layering scheme under
|
||||
which the controller driver is aware of the opcodes, addressing, and other
|
||||
details of the SPI NOR protocol.
|
||||
|
||||
Part II - How does the framework work?
|
||||
--------------------------------------
|
||||
|
||||
This framework just adds a new layer between the MTD and the SPI bus driver.
|
||||
With this new layer, the SPI NOR controller driver does not depend on the
|
||||
m25p80 code anymore.
|
||||
|
||||
Before this framework, the layer is like:
|
||||
|
||||
MTD
|
||||
------------------------
|
||||
m25p80
|
||||
------------------------
|
||||
SPI bus driver
|
||||
------------------------
|
||||
SPI NOR chip
|
||||
|
||||
After this framework, the layer is like:
|
||||
MTD
|
||||
------------------------
|
||||
SPI NOR framework
|
||||
------------------------
|
||||
m25p80
|
||||
------------------------
|
||||
SPI bus driver
|
||||
------------------------
|
||||
SPI NOR chip
|
||||
|
||||
With the SPI NOR controller driver (Freescale QuadSPI), it looks like:
|
||||
MTD
|
||||
------------------------
|
||||
SPI NOR framework
|
||||
------------------------
|
||||
fsl-quadSPI
|
||||
------------------------
|
||||
SPI NOR chip
|
||||
|
||||
Part III - How can drivers use the framework?
|
||||
---------------------------------------------
|
||||
|
||||
The main API is spi_nor_scan(). Before you call the hook, a driver should
|
||||
initialize the necessary fields for spi_nor{}. Please see
|
||||
drivers/mtd/spi-nor/spi-nor.c for detail. Please also refer to fsl-quadspi.c
|
||||
when you want to write a new driver for a SPI NOR controller.
|
||||
@@ -321,6 +321,8 @@ source "drivers/mtd/onenand/Kconfig"
|
||||
|
||||
source "drivers/mtd/lpddr/Kconfig"
|
||||
|
||||
source "drivers/mtd/spi-nor/Kconfig"
|
||||
|
||||
source "drivers/mtd/ubi/Kconfig"
|
||||
|
||||
endif # MTD
|
||||
|
||||
@@ -32,4 +32,5 @@ inftl-objs := inftlcore.o inftlmount.o
|
||||
|
||||
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
|
||||
|
||||
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
|
||||
obj-$(CONFIG_MTD_UBI) += ubi/
|
||||
|
||||
@@ -80,7 +80,7 @@ config MTD_DATAFLASH_OTP
|
||||
|
||||
config MTD_M25P80
|
||||
tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
|
||||
depends on SPI_MASTER
|
||||
depends on SPI_MASTER && MTD_SPI_NOR
|
||||
help
|
||||
This enables access to most modern SPI flash chips, used for
|
||||
program and data storage. Series supported include Atmel AT26DF,
|
||||
@@ -212,7 +212,7 @@ config MTD_DOCG3
|
||||
|
||||
config MTD_ST_SPI_FSM
|
||||
tristate "ST Microelectronics SPI FSM Serial Flash Controller"
|
||||
depends on ARM || SH
|
||||
depends on ARCH_STI
|
||||
help
|
||||
This provides an MTD device driver for the ST Microelectronics
|
||||
SPI Fast Sequence Mode (FSM) Serial Flash Controller and support
|
||||
|
||||
+107
-1200
File diff suppressed because it is too large
Load Diff
@@ -13,43 +13,23 @@
|
||||
#define _MTD_SERIAL_FLASH_CMDS_H
|
||||
|
||||
/* Generic Flash Commands/OPCODEs */
|
||||
#define FLASH_CMD_WREN 0x06
|
||||
#define FLASH_CMD_WRDI 0x04
|
||||
#define FLASH_CMD_RDID 0x9f
|
||||
#define FLASH_CMD_RDSR 0x05
|
||||
#define FLASH_CMD_RDSR2 0x35
|
||||
#define FLASH_CMD_WRSR 0x01
|
||||
#define FLASH_CMD_SE_4K 0x20
|
||||
#define FLASH_CMD_SE_32K 0x52
|
||||
#define FLASH_CMD_SE 0xd8
|
||||
#define FLASH_CMD_CHIPERASE 0xc7
|
||||
#define FLASH_CMD_WRVCR 0x81
|
||||
#define FLASH_CMD_RDVCR 0x85
|
||||
#define SPINOR_OP_RDSR2 0x35
|
||||
#define SPINOR_OP_WRVCR 0x81
|
||||
#define SPINOR_OP_RDVCR 0x85
|
||||
|
||||
/* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */
|
||||
#define FLASH_CMD_READ 0x03 /* READ */
|
||||
#define FLASH_CMD_READ_FAST 0x0b /* FAST READ */
|
||||
#define FLASH_CMD_READ_1_1_2 0x3b /* DUAL OUTPUT READ */
|
||||
#define FLASH_CMD_READ_1_2_2 0xbb /* DUAL I/O READ */
|
||||
#define FLASH_CMD_READ_1_1_4 0x6b /* QUAD OUTPUT READ */
|
||||
#define FLASH_CMD_READ_1_4_4 0xeb /* QUAD I/O READ */
|
||||
#define SPINOR_OP_READ_1_2_2 0xbb /* DUAL I/O READ */
|
||||
#define SPINOR_OP_READ_1_4_4 0xeb /* QUAD I/O READ */
|
||||
|
||||
#define FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */
|
||||
#define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
|
||||
#define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
|
||||
#define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
|
||||
#define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */
|
||||
|
||||
#define FLASH_CMD_EN4B_ADDR 0xb7 /* Enter 4-byte address mode */
|
||||
#define FLASH_CMD_EX4B_ADDR 0xe9 /* Exit 4-byte address mode */
|
||||
#define SPINOR_OP_WRITE 0x02 /* PAGE PROGRAM */
|
||||
#define SPINOR_OP_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
|
||||
#define SPINOR_OP_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
|
||||
#define SPINOR_OP_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
|
||||
#define SPINOR_OP_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */
|
||||
|
||||
/* READ commands with 32-bit addressing */
|
||||
#define FLASH_CMD_READ4 0x13
|
||||
#define FLASH_CMD_READ4_FAST 0x0c
|
||||
#define FLASH_CMD_READ4_1_1_2 0x3c
|
||||
#define FLASH_CMD_READ4_1_2_2 0xbc
|
||||
#define FLASH_CMD_READ4_1_1_4 0x6c
|
||||
#define FLASH_CMD_READ4_1_4_4 0xec
|
||||
#define SPINOR_OP_READ4_1_2_2 0xbc
|
||||
#define SPINOR_OP_READ4_1_4_4 0xec
|
||||
|
||||
/* Configuration flags */
|
||||
#define FLASH_FLAG_SINGLE 0x000000ff
|
||||
|
||||
+156
-184
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
menuconfig MTD_SPI_NOR
|
||||
tristate "SPI-NOR device support"
|
||||
depends on MTD
|
||||
help
|
||||
This is the framework for the SPI NOR which can be used by the SPI
|
||||
device drivers and the SPI-NOR device driver.
|
||||
|
||||
if MTD_SPI_NOR
|
||||
|
||||
config SPI_FSL_QUADSPI
|
||||
tristate "Freescale Quad SPI controller"
|
||||
depends on ARCH_MXC
|
||||
help
|
||||
This enables support for the Quad SPI controller in master mode.
|
||||
We only connect the NOR to this controller now.
|
||||
|
||||
endif # MTD_SPI_NOR
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
|
||||
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Status Register bits. */
|
||||
#define SR_WIP 1 /* Write in progress */
|
||||
#define SR_WEL 2 /* Write enable latch */
|
||||
/* meaning of other SR_* bits may differ between vendors */
|
||||
#define SR_BP0 4 /* Block protect 0 */
|
||||
#define SR_BP1 8 /* Block protect 1 */
|
||||
#define SR_BP2 0x10 /* Block protect 2 */
|
||||
#define SR_SRWD 0x80 /* SR write protect */
|
||||
|
||||
#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */
|
||||
|
||||
/* Configuration Register bits. */
|
||||
#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */
|
||||
|
||||
enum read_mode {
|
||||
SPI_NOR_NORMAL = 0,
|
||||
SPI_NOR_FAST,
|
||||
SPI_NOR_DUAL,
|
||||
SPI_NOR_QUAD,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
|
||||
* @wren: command for "Write Enable", or 0x00 for not required
|
||||
* @cmd: command for operation
|
||||
* @cmd_pins: number of pins to send @cmd (1, 2, 4)
|
||||
* @addr: address for operation
|
||||
* @addr_pins: number of pins to send @addr (1, 2, 4)
|
||||
* @addr_width: number of address bytes
|
||||
* (3,4, or 0 for address not required)
|
||||
* @mode: mode data
|
||||
* @mode_pins: number of pins to send @mode (1, 2, 4)
|
||||
* @mode_cycles: number of mode cycles (0 for mode not required)
|
||||
* @dummy_cycles: number of dummy cycles (0 for dummy not required)
|
||||
*/
|
||||
struct spi_nor_xfer_cfg {
|
||||
u8 wren;
|
||||
u8 cmd;
|
||||
u8 cmd_pins;
|
||||
u32 addr;
|
||||
u8 addr_pins;
|
||||
u8 addr_width;
|
||||
u8 mode;
|
||||
u8 mode_pins;
|
||||
u8 mode_cycles;
|
||||
u8 dummy_cycles;
|
||||
};
|
||||
|
||||
#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,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @cfg: used by the read_xfer/write_xfer
|
||||
* @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_xfer: [OPTIONAL] the read fundamental primitive
|
||||
* @write_xfer: [OPTIONAL] the writefundamental primitive
|
||||
* @read_reg: [DRIVER-SPECIFIC] read out the register
|
||||
* @write_reg: [DRIVER-SPECIFIC] write data to the register
|
||||
* @read_id: [REPLACEABLE] read out the ID data, and find
|
||||
* the proper spi_device_id
|
||||
* @wait_till_ready: [REPLACEABLE] wait till the NOR becomes ready
|
||||
* @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
|
||||
* @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;
|
||||
struct spi_nor_xfer_cfg cfg;
|
||||
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_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
|
||||
u8 *buf, size_t len);
|
||||
int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
|
||||
u8 *buf, size_t len);
|
||||
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 write_enable);
|
||||
const struct spi_device_id *(*read_id)(struct spi_nor *nor);
|
||||
int (*wait_till_ready)(struct spi_nor *nor);
|
||||
|
||||
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);
|
||||
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* spi_nor_scan() - scan the SPI NOR
|
||||
* @nor: the spi_nor structure
|
||||
* @id: the spi_device_id provided by the driver
|
||||
* @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 board may assigns a spi_device_id with @id which be used to compared with
|
||||
* the spi_device_id detected by the scanning.
|
||||
*
|
||||
* Return: 0 for success, others for failure.
|
||||
*/
|
||||
int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
|
||||
enum read_mode mode);
|
||||
extern const struct spi_device_id spi_nor_ids[];
|
||||
|
||||
/**
|
||||
* spi_nor_match_id() - find the spi_device_id by the name
|
||||
* @name: the name of the spi_device_id
|
||||
*
|
||||
* The drivers use this function to find the spi_device_id
|
||||
* specified by the @name.
|
||||
*
|
||||
* Return: returns the right spi_device_id pointer on success,
|
||||
* and returns NULL on failure.
|
||||
*/
|
||||
const struct spi_device_id *spi_nor_match_id(char *name);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user