Commit Graph

18 Commits

Author SHA1 Message Date
Rafał Miłecki 11edc1133e mtd: spi-nor: intel-spi: use mtd_device_register()
This driver doesn't specify parsers so it can use that little helper.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
2018-08-01 09:18:55 +02:00
Nicholas Mc Guire aba3a882a1 mtd: spi-nor: intel: provide a range for poll_timout
The overall poll time here is INTEL_SPI_TIMEOUT * 1000 which is
5000 * 1000 - so 5seconds and it is coded as a tight loop here delay_us
to readl_poll_timeout() is set to 0. As this is never called in an atomic
context sleeping should be no issue and there is no reasons for the
tight-loop here.

Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
2018-05-18 12:53:33 +02:00
Mika Westerberg c7d6a82d90 mtd: spi-nor: intel-spi: Fix atomic sequence handling
On many older systems using SW sequencer the PREOP_OPTYPE register
contains two preopcodes as following:

  PREOP_OPTYPE=0xf2785006

The last two bytes are the opcodes decoded to:

  0x50 - Write enable for volatile status register
  0x06 - Write enable

The former is used to modify volatile bits in the status register. For
non-volatile bits the latter is needed. Preopcodes are used in SW
sequencer to send one command "atomically" without anything else
interfering the transfer. The sequence that gets executed is:

  - Send preopcode (write enable) from PREOP_OPTYPE register
  - Send the actual SPI command
  - Poll busy bit in the status register (0x05, RDSR)

Commit 8c473dd61b ("spi-nor: intel-spi: Don't assume OPMENU0/1 to be
programmed by BIOS") enabled atomic sequence handling but because both
preopcodes are programmed, the following happens:

  if (preop >> 8)
  	val |= SSFSTS_CTL_SPOP;

Since on these systems preop >> 8 == 0x50 we end up picking volatile
write enable instead. Because of this the actual write command is pretty
much NOP unless there is a WREN latched in the chip already.

Furthermore we should not really just assume that WREN was issued in
previous call to intel_spi_write_reg() because that might not be the
case.

This updates driver to first check that the opcode is actually available
in PREOP_OPTYPE register and if not return error back to the spi-nor
core (if the controller is not locked we program it now). In addition we
save the opcode to ispi->atomic_preopcode field which is checked in next
call to intel_spi_sw_cycle() to actually enable atomic sequence using
the requested preopcode.

Fixes: 8c473dd61b ("spi-nor: intel-spi: Don't assume OPMENU0/1 to be programmed by BIOS")
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: stable@vger.kernel.org
Reviewed-by: Marek Vasut <marek.vasut@gmail.com>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
2018-05-18 12:53:05 +02:00
Mika Westerberg a6e4836d69 spi-nor: intel-spi: Remove unused preopcodes field
This field is not used in the driver anymore so remove it.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2018-01-07 21:22:32 +01:00
Bin Meng 3163d125b7 spi-nor: intel-spi: Fall back to use SW sequencer to erase
According to the datasheet, the HW sequencer has a predefined list
of opcodes, with only the erase opcode being programmable in LVSCC
and UVSCC registers. If these registers don't contain a valid erase
opcode (eg: BIOS does not program it), erase cannot be done using
the HW sequencer, even though the erase operation does not report
any error, the flash remains not erased.

If such register setting is detected, let's fall back to use the SW
sequencer to erase instead.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:57:50 +02:00
Bin Meng 2421f1ccbd spi-nor: intel-spi: Rename swseq to swseq_reg in 'struct intel_spi'
The ispi->swseq is used for register access. Let's rename it to
swseq_reg to better describe its usage.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:56:31 +02:00
Bin Meng 6e995b84ce spi-nor: intel-spi: Remove the unnecessary HSFSTS register RW
There is no code that alters the HSFSTS register content in between
in intel_spi_write(). Remove the unnecessary RW to save some cycles.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:52:01 +02:00
Bin Meng 8c473dd61b spi-nor: intel-spi: Don't assume OPMENU0/1 to be programmed by BIOS
At present the driver relies on valid OPMENU0/OPMENU1 register values
that are programmed by BIOS to function correctly. However in a real
world it's absolutely legitimate for a bootloader to leave these two
registers untouched. Intel FSP for Baytrail exactly does like this.
When we are booting from any Intel FSP based bootloaders like U-Boot,
the driver refuses to work.

We can of course program various flash opcodes in the OPMENU0/OPMENU1
registers, and such workaround can be added in either the bootloader
codes, or the kernel driver itself.

But a graceful solution would be to update the kernel driver to remove
such limitation of OPMENU0/1 register dependency. The SPI controller
settings are not locked under such configuration. So we can first check
the controller locking status, and if it is not locked that means the
driver job can be fulfilled by using a chosen OPMENU index to set up
the flash opcode every time.

While we are here, the missing 'Atomic Cycle Sequence' handling in the
SW sequencer codes is also added.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:47:04 +02:00
Bin Meng aecf59e90a spi-nor: intel-spi: Remove 'Atomic Cycle Sequence' in intel_spi_write()
So far intel_spi_write() uses the HW sequencer to do the write. But
the HW sequencer register HSFSTS_CTL does not have such a field for
'Atomic Cycle Sequence', remove it.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:46:04 +02:00
Bin Meng fc2b347261 spi-nor: intel-spi: Use SW sequencer for BYT/LPT
Baytrail/Lynx Point SPI controller's HW sequencer only supports basic
operations. This is determined by the chipset design, however current
codes try to use register values in OPMENU0/OPMENU1 to see whether SW
sequencer should be used, which is wrong. In fact OPMENU0/OPMENU1 can
remain unprogrammed by some bootloaders.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:44:39 +02:00
Bin Meng db2ce7f3c7 spi-nor: intel-spi: Check transfer length in the HW/SW cycle
Intel SPI controller only has a 64 bytes FIFO. This adds a sanity
check before triggering any HW/SW sequencer work.

Additionally for the SW sequencer, if given data length is zero,
we should not mark the 'Data Cycle' bit.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:43:13 +02:00
Bin Meng 9d63f17661 spi-nor: intel-spi: Fix broken software sequencing codes
There are two bugs in current intel_spi_sw_cycle():

- The 'data byte count' field should be the number of bytes
  transferred minus 1
- SSFSTS_CTL is the offset from ispi->sregs, not ispi->base

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Cc: <stable@vger.kernel.org> # v4.11+
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:41:48 +02:00
Bin Meng e58348b0e4 spi-nor: intel-spi: Remove useless 'buf' parameter in the HW/SW cycle
intel_spi_hw_cycle() and intel_spi_sw_cycle() don't use the parameter
'buf' at all. Remove it.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:40:54 +02:00
Bin Meng 9cbb035cc1 spi-nor: intel-spi: Fix number of protected range registers for BYT/LPT
The number of protected range registers is not the same on BYT/LPT/
BXT. GPR0 only exists on Apollo Lake and its offset is reserved on
other platforms.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
2017-10-11 09:40:06 +02:00
Cyrille Pitchen cfc5604c48 mtd: spi-nor: introduce SPI 1-2-2 and SPI 1-4-4 protocols
This patch changes the prototype of spi_nor_scan(): its 3rd parameter
is replaced by a 'struct spi_nor_hwcaps' pointer, which tells the spi-nor
framework about the actual hardware capabilities supported by the SPI
controller and its driver.

Besides, this patch also introduces a new 'struct spi_nor_flash_parameter'
telling the spi-nor framework about the hardware capabilities supported by
the SPI flash memory and the associated settings required to use those
hardware caps.

Then, to improve the readability of spi_nor_scan(), the discovery of the
memory settings and the memory initialization are now split into two
dedicated functions.

1 - spi_nor_init_params()

The spi_nor_init_params() function is responsible for initializing the
'struct spi_nor_flash_parameter'. Currently this structure is filled with
legacy values but further patches will allow to override some parameter
values dynamically, for instance by reading the JESD216 Serial Flash
Discoverable Parameter (SFDP) tables from the SPI memory.
The spi_nor_init_params() function only deals with the hardware
capabilities of the SPI flash memory: especially it doesn't care about
the hardware capabilities supported by the SPI controller.

2 - spi_nor_setup()

The second function is called once the 'struct spi_nor_flash_parameter'
has been initialized by spi_nor_init_params().
With both 'struct spi_nor_flash_parameter' and 'struct spi_nor_hwcaps',
the new argument of spi_nor_scan(), spi_nor_setup() computes the best
match between hardware caps supported by both the (Q)SPI memory and
controller hence selecting the relevant settings for (Fast) Read and Page
Program operations.

Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Reviewed-by: Marek Vasut <marek.vasut@gmail.com>
2017-05-15 21:56:17 +02:00
Nicholas Mc Guire 011de1b1db mtd: spi-nor: intel: use ERR_CAST in return statement
This fixes a sparse warning about incorrect type in return expression.

Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
Acked-by: Marek Vasut <marek.vasut@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
2017-03-07 22:09:56 +01:00
Nicholas Mc Guire 22d6187856 mtd: spi-nor: intel: use true/false for boolean
writeable in struct intel_spi is a boolean and assignment should be to
true/false not 1/0 as recommended by boolinit.cocci.

Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
Acked-by: Marek Vasut <marek.vasut@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
2017-03-07 22:01:45 +01:00
Mika Westerberg 8afda8b26d spi-nor: Add support for Intel SPI serial flash controller
Add support for the SPI serial flash host controller found on many Intel
CPUs including Baytrail and Braswell. The SPI serial flash controller is
used to access BIOS and other platform specific information. By default the
driver exposes a single read-only MTD device but with a module parameter
"writeable=1" the MTD device can be made read-write which makes it possible
to upgrade BIOS directly from Linux.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
2017-01-03 17:33:36 +00:00