Commit d66d3519 authored by Brian Norris's avatar Brian Norris

Merge branch 'spinor'

Addition of the spi-nor framework, plus updates to the ST SPI FSM
driver.
parents 6189cccb dc002f99
* 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 {
....
};
};
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" ...@@ -321,6 +321,8 @@ source "drivers/mtd/onenand/Kconfig"
source "drivers/mtd/lpddr/Kconfig" source "drivers/mtd/lpddr/Kconfig"
source "drivers/mtd/spi-nor/Kconfig"
source "drivers/mtd/ubi/Kconfig" source "drivers/mtd/ubi/Kconfig"
endif # MTD endif # MTD
...@@ -32,4 +32,5 @@ inftl-objs := inftlcore.o inftlmount.o ...@@ -32,4 +32,5 @@ inftl-objs := inftlcore.o inftlmount.o
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-$(CONFIG_MTD_UBI) += ubi/ obj-$(CONFIG_MTD_UBI) += ubi/
...@@ -80,7 +80,7 @@ config MTD_DATAFLASH_OTP ...@@ -80,7 +80,7 @@ config MTD_DATAFLASH_OTP
config MTD_M25P80 config MTD_M25P80
tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)" tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
depends on SPI_MASTER depends on SPI_MASTER && MTD_SPI_NOR
help help
This enables access to most modern SPI flash chips, used for This enables access to most modern SPI flash chips, used for
program and data storage. Series supported include Atmel AT26DF, program and data storage. Series supported include Atmel AT26DF,
...@@ -212,7 +212,7 @@ config MTD_DOCG3 ...@@ -212,7 +212,7 @@ config MTD_DOCG3
config MTD_ST_SPI_FSM config MTD_ST_SPI_FSM
tristate "ST Microelectronics SPI FSM Serial Flash Controller" tristate "ST Microelectronics SPI FSM Serial Flash Controller"
depends on ARM || SH depends on ARCH_STI
help help
This provides an MTD device driver for the ST Microelectronics This provides an MTD device driver for the ST Microelectronics
SPI Fast Sequence Mode (FSM) Serial Flash Controller and support SPI Fast Sequence Mode (FSM) Serial Flash Controller and support
......
This diff is collapsed.
...@@ -13,43 +13,23 @@ ...@@ -13,43 +13,23 @@
#define _MTD_SERIAL_FLASH_CMDS_H #define _MTD_SERIAL_FLASH_CMDS_H
/* Generic Flash Commands/OPCODEs */ /* Generic Flash Commands/OPCODEs */
#define FLASH_CMD_WREN 0x06 #define SPINOR_OP_RDSR2 0x35
#define FLASH_CMD_WRDI 0x04 #define SPINOR_OP_WRVCR 0x81
#define FLASH_CMD_RDID 0x9f #define SPINOR_OP_RDVCR 0x85
#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
/* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */ /* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */
#define FLASH_CMD_READ 0x03 /* READ */ #define SPINOR_OP_READ_1_2_2 0xbb /* DUAL I/O READ */
#define FLASH_CMD_READ_FAST 0x0b /* FAST READ */ #define SPINOR_OP_READ_1_4_4 0xeb /* QUAD I/O 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 FLASH_CMD_WRITE 0x02 /* PAGE PROGRAM */ #define SPINOR_OP_WRITE 0x02 /* PAGE PROGRAM */
#define FLASH_CMD_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */ #define SPINOR_OP_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
#define FLASH_CMD_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */ #define SPINOR_OP_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
#define FLASH_CMD_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */ #define SPINOR_OP_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
#define FLASH_CMD_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */ #define SPINOR_OP_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 */
/* READ commands with 32-bit addressing */ /* READ commands with 32-bit addressing */
#define FLASH_CMD_READ4 0x13 #define SPINOR_OP_READ4_1_2_2 0xbc
#define FLASH_CMD_READ4_FAST 0x0c #define SPINOR_OP_READ4_1_4_4 0xec
#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
/* Configuration flags */ /* Configuration flags */
#define FLASH_FLAG_SINGLE 0x000000ff #define FLASH_FLAG_SINGLE 0x000000ff
......
This diff is collapsed.
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
obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o
This diff is collapsed.
This diff is collapsed.
/*
* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment