summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2022-02-09 15:27:04 +0300
committerMark Brown <broonie@kernel.org>2022-02-14 12:53:08 +0000
commitcd149eff8d2201a63c074a6d9d03e52926aa535d (patch)
tree43b13c86a761ded91c8bc8b34c93dff9aec420ca /drivers/mfd
parente783362eb54cd99b2cac8b3a9aeac942e6f6ac07 (diff)
mtd: spi-nor: intel-spi: Disable write protection only if asked
Currently the driver tries to disable the BIOS write protection automatically even if this is not what the user wants. For this reason modify the driver so that by default it does not touch the write protection. Only if specifically asked by the user (setting writeable=1 command line parameter) the driver tries to disable the BIOS write protection. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Mauro Lima <mauro.lima@eclypsium.com> Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com> Acked-by: Lee Jones <lee.jones@linaro.org> Link: https://lore.kernel.org/r/20220209122706.42439-2-mika.westerberg@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/lpc_ich.c59
1 files changed, 54 insertions, 5 deletions
diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index f10e53187f67..9ffab9aafd81 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -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 @@ wdt_done:
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);