Unverified Commit 0177212e authored by Mark Brown's avatar Mark Brown
Browse files

mtd: spi-nor / spi / MFD: Convert intel-spi to SPI MEM

Merge series from Mika Westerberg <mika.westerberg@linux.intel.com>:

Based on discussion on the patch I sent some time ago here:

  http://lists.infradead.org/pipermail/linux-mtd/2021-June/086867.html

it turns out that the preferred way to deal with the SPI flash controller
drivers is through SPI MEM which is part of Linux SPI subsystem.

This series does that for the intel-spi driver. This also renames the
driver to follow the convention used in the SPI subsystem. The first patch
improves the write protection handling to be slightly more safer. The
following two patches do the conversion itself. Note the Intel SPI flash
controller only allows commands such as read, write and so on and it
internally uses whatever addressing etc. it figured from the SFDP on the
flash device.

base-commit: e783362e
parents f48dc6b9 4ab13489
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -7,6 +7,6 @@ Memory Technology Device (MTD)
.. toctree::
   :maxdepth: 1

   intel-spi
   spi-intel
   nand_ecc
   spi-nor
+4 −4
Original line number Diff line number Diff line
==============================
Upgrading BIOS using intel-spi
Upgrading BIOS using spi-intel
==============================

Many Intel CPUs like Baytrail and Braswell include SPI serial flash host
@@ -11,12 +11,12 @@ avoid accidental (or on purpose) overwrite of the content.
Not all manufacturers protect the SPI serial flash, mainly because it
allows upgrading the BIOS image directly from an OS.

The intel-spi driver makes it possible to read and write the SPI serial
The spi-intel driver makes it possible to read and write the SPI serial
flash, if certain protection bits are not set and locked. If it finds
any of them set, the whole MTD device is made read-only to prevent
partial overwrites. By default the driver exposes SPI serial flash
contents as read-only but it can be changed from kernel command line,
passing "intel-spi.writeable=1".
passing "spi_intel.writeable=1".

Please keep in mind that overwriting the BIOS image on SPI serial flash
might render the machine unbootable and requires special equipment like
@@ -32,7 +32,7 @@ Linux.
    serial flash. Distros like Debian and Fedora have this prepackaged with
    name "mtd-utils".

 3) Add "intel-spi.writeable=1" to the kernel command line and reboot
 3) Add "spi_intel.writeable=1" to the kernel command line and reboot
    the board (you can also reload the driver passing "writeable=1" as
    module parameter to modprobe).

+54 −5
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@
#define SPIBASE_BYT		0x54
#define SPIBASE_BYT_SZ		512
#define SPIBASE_BYT_EN		BIT(1)
#define BYT_BCR			0xfc
#define BYT_BCR_WPD		BIT(0)

#define SPIBASE_LPT		0x3800
#define SPIBASE_LPT_SZ		512
@@ -1084,12 +1086,57 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
	return ret;
}

static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
{
	u32 val;

	val = readl(base + BYT_BCR);
	if (!(val & BYT_BCR_WPD)) {
		val |= BYT_BCR_WPD;
		writel(val, base + BYT_BCR);
		val = readl(base + BYT_BCR);
	}

	return val & BYT_BCR_WPD;
}

static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)
{
	struct pci_dev *pdev = data;
	u32 bcr;

	pci_read_config_dword(pdev, BCR, &bcr);
	if (!(bcr & BCR_WPD)) {
		bcr |= BCR_WPD;
		pci_write_config_dword(pdev, BCR, bcr);
		pci_read_config_dword(pdev, BCR, &bcr);
	}

	return bcr & BCR_WPD;
}

static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data)
{
	unsigned int spi = PCI_DEVFN(13, 2);
	struct pci_bus *bus = data;
	u32 bcr;

	pci_bus_read_config_dword(bus, spi, BCR, &bcr);
	if (!(bcr & BCR_WPD)) {
		bcr |= BCR_WPD;
		pci_bus_write_config_dword(bus, spi, BCR, bcr);
		pci_bus_read_config_dword(bus, spi, BCR, &bcr);
	}

	return bcr & BCR_WPD;
}

static int lpc_ich_init_spi(struct pci_dev *dev)
{
	struct lpc_ich_priv *priv = pci_get_drvdata(dev);
	struct resource *res = &intel_spi_res[0];
	struct intel_spi_boardinfo *info;
	u32 spi_base, rcba, bcr;
	u32 spi_base, rcba;

	info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
	if (!info)
@@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
		if (spi_base & SPIBASE_BYT_EN) {
			res->start = spi_base & ~(SPIBASE_BYT_SZ - 1);
			res->end = res->start + SPIBASE_BYT_SZ - 1;

			info->set_writeable = lpc_ich_byt_set_writeable;
		}
		break;

@@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
			res->start = spi_base + SPIBASE_LPT;
			res->end = res->start + SPIBASE_LPT_SZ - 1;

			pci_read_config_dword(dev, BCR, &bcr);
			info->writeable = !!(bcr & BCR_WPD);
			info->set_writeable = lpc_ich_lpt_set_writeable;
			info->data = dev;
		}
		break;

@@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
			res->start = spi_base & 0xfffffff0;
			res->end = res->start + SPIBASE_APL_SZ - 1;

			pci_bus_read_config_dword(bus, spi, BCR, &bcr);
			info->writeable = !!(bcr & BCR_WPD);
			info->set_writeable = lpc_ich_bxt_set_writeable;
			info->data = bus;
		}

		pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);
+0 −36
Original line number Diff line number Diff line
@@ -26,39 +26,3 @@ config SPI_NXP_SPIFI
	  SPIFI is a specialized controller for connecting serial SPI
	  Flash. Enable this option if you have a device with a SPIFI
	  controller and want to access the Flash as a mtd device.

config SPI_INTEL_SPI
	tristate

config SPI_INTEL_SPI_PCI
	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
	depends on X86 && PCI
	select SPI_INTEL_SPI
	help
	  This enables PCI support for the Intel PCH/PCU SPI controller in
	  master mode. This controller is present in modern Intel hardware
	  and is used to hold BIOS and other persistent settings. Using
	  this driver it is possible to upgrade BIOS directly from Linux.

	  Say N here unless you know what you are doing. Overwriting the
	  SPI flash may render the system unbootable.

	  To compile this driver as a module, choose M here: the module
	  will be called intel-spi-pci.

config SPI_INTEL_SPI_PLATFORM
	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
	depends on X86
	select SPI_INTEL_SPI
	help
	  This enables platform support for the Intel PCH/PCU SPI
	  controller in master mode. This controller is present in modern
	  Intel hardware and is used to hold BIOS and other persistent
	  settings. Using this driver it is possible to upgrade BIOS
	  directly from Linux.

	  Say N here unless you know what you are doing. Overwriting the
	  SPI flash may render the system unbootable.

	  To compile this driver as a module, choose M here: the module
	  will be called intel-spi-platform.
+0 −3
Original line number Diff line number Diff line
@@ -2,6 +2,3 @@
obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o
obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o
obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o
obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o
Loading