History

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.

Mika Westerberg committed 4 years ago

Commit cd149ef1 parent e7833624 files · +96 −39Browse files

Unified · Split

4 files
  1. drivers/mfd/lpc_ich.c +54 −5
  2. drivers/mtd/spi-nor/controllers/intel-spi-pci.c +19 −10
  3. drivers/mtd/spi-nor/controllers/intel-spi.c +19 −22
  4. include/linux/platform_data/x86/intel-spi.h +4 −2
drivers/mfd/lpc_ich.c+54−5
@@ -63,6 +63,8 @@ · 62 unmodified lines
6363 #define SPIBASE_BYT 0x54
6464 #define SPIBASE_BYT_SZ 512
6565 #define SPIBASE_BYT_EN BIT(1)
66+#define BYT_BCR 0xfc
67+#define BYT_BCR_WPD BIT(0)
6668
6769 #define SPIBASE_LPT 0x3800
6870 #define SPIBASE_LPT_SZ 512
@@ -1084,12 +1086,57 @@ wdt_done: · 1015 unmodified lines
10841086 return ret;
10851087 }
10861088
1089+static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
1090+{
1091+ u32 val;
1092+
1093+ val = readl(base + BYT_BCR);
1094+ if (!(val & BYT_BCR_WPD)) {
1095+ val |= BYT_BCR_WPD;
1096+ writel(val, base + BYT_BCR);
1097+ val = readl(base + BYT_BCR);
1098+ }
1099+
1100+ return val & BYT_BCR_WPD;
1101+}
1102+
1103+static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)
1104+{
1105+ struct pci_dev *pdev = data;
1106+ u32 bcr;
1107+
1108+ pci_read_config_dword(pdev, BCR, &bcr);
1109+ if (!(bcr & BCR_WPD)) {
1110+ bcr |= BCR_WPD;
1111+ pci_write_config_dword(pdev, BCR, bcr);
1112+ pci_read_config_dword(pdev, BCR, &bcr);
1113+ }
1114+
1115+ return bcr & BCR_WPD;
1116+}
1117+
1118+static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data)
1119+{
1120+ unsigned int spi = PCI_DEVFN(13, 2);
1121+ struct pci_bus *bus = data;
1122+ u32 bcr;
1123+
1124+ pci_bus_read_config_dword(bus, spi, BCR, &bcr);
1125+ if (!(bcr & BCR_WPD)) {
1126+ bcr |= BCR_WPD;
1127+ pci_bus_write_config_dword(bus, spi, BCR, bcr);
1128+ pci_bus_read_config_dword(bus, spi, BCR, &bcr);
1129+ }
1130+
1131+ return bcr & BCR_WPD;
1132+}
1133+
10871134 static int lpc_ich_init_spi(struct pci_dev *dev)
10881135 {
10891136 struct lpc_ich_priv *priv = pci_get_drvdata(dev);
10901137 struct resource *res = &intel_spi_res[0];
10911138 struct intel_spi_boardinfo *info;
1092− u32 spi_base, rcba, bcr;
1139+ u32 spi_base, rcba;
10931140
10941141 info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
10951142 if (!info)
@@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev) · 7 unmodified lines
11031150 if (spi_base & SPIBASE_BYT_EN) {
11041151 res->start = spi_base & ~(SPIBASE_BYT_SZ - 1);
11051152 res->end = res->start + SPIBASE_BYT_SZ - 1;
1153+
1154+ info->set_writeable = lpc_ich_byt_set_writeable;
11061155 }
11071156 break;
11081157
@@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev) · 4 unmodified lines
11131162 res->start = spi_base + SPIBASE_LPT;
11141163 res->end = res->start + SPIBASE_LPT_SZ - 1;
11151164
1116− pci_read_config_dword(dev, BCR, &bcr);
1117− info->writeable = !!(bcr & BCR_WPD);
1165+ info->set_writeable = lpc_ich_lpt_set_writeable;
1166+ info->data = dev;
11181167 }
11191168 break;
11201169
@@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev) · 14 unmodified lines
11351184 res->start = spi_base & 0xfffffff0;
11361185 res->end = res->start + SPIBASE_APL_SZ - 1;
11371186
1138− pci_bus_read_config_dword(bus, spi, BCR, &bcr);
1139− info->writeable = !!(bcr & BCR_WPD);
1187+ info->set_writeable = lpc_ich_bxt_set_writeable;
1188+ info->data = bus;
11401189 }
11411190
11421191 pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);
drivers/mtd/spi-nor/controllers/intel-spi-pci.c+19−10
@@ -16,12 +16,30 @@ · 15 unmodified lines
1616 #define BCR 0xdc
1717 #define BCR_WPD BIT(0)
1818
19+static bool intel_spi_pci_set_writeable(void __iomem *base, void *data)
20+{
21+ struct pci_dev *pdev = data;
22+ u32 bcr;
23+
24+ /* Try to make the chip read/write */
25+ pci_read_config_dword(pdev, BCR, &bcr);
26+ if (!(bcr & BCR_WPD)) {
27+ bcr |= BCR_WPD;
28+ pci_write_config_dword(pdev, BCR, bcr);
29+ pci_read_config_dword(pdev, BCR, &bcr);
30+ }
31+
32+ return bcr & BCR_WPD;
33+}
34+
1935 static const struct intel_spi_boardinfo bxt_info = {
2036 .type = INTEL_SPI_BXT,
37+ .set_writeable = intel_spi_pci_set_writeable,
2138 };
2239
2340 static const struct intel_spi_boardinfo cnl_info = {
2441 .type = INTEL_SPI_CNL,
42+ .set_writeable = intel_spi_pci_set_writeable,
2543 };
2644
2745 static int intel_spi_pci_probe(struct pci_dev *pdev,
@@ -29,7 +47,6 @@ static int intel_spi_pci_probe(struct pci_dev *pdev, · 1 unmodified line
2947 {
3048 struct intel_spi_boardinfo *info;
3149 struct intel_spi *ispi;
32− u32 bcr;
3350 int ret;
3451
3552 ret = pcim_enable_device(pdev);
@@ -41,15 +58,7 @@ static int intel_spi_pci_probe(struct pci_dev *pdev, · 5 unmodified lines
4158 if (!info)
4259 return -ENOMEM;
4360
44− /* Try to make the chip read/write */
45− pci_read_config_dword(pdev, BCR, &bcr);
46− if (!(bcr & BCR_WPD)) {
47− bcr |= BCR_WPD;
48− pci_write_config_dword(pdev, BCR, bcr);
49− pci_read_config_dword(pdev, BCR, &bcr);
50− }
51− info->writeable = !!(bcr & BCR_WPD);
52−
61+ info->data = pdev;
5362 ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
5463 if (IS_ERR(ispi))
5564 return PTR_ERR(ispi);
drivers/mtd/spi-nor/controllers/intel-spi.c+19−22
@@ -131,7 +131,6 @@ · 130 unmodified lines
131131 * @sregs: Start of software sequencer registers
132132 * @nregions: Maximum number of regions
133133 * @pr_num: Maximum number of protected range registers
134− * @writeable: Is the chip writeable
135134 * @locked: Is SPI setting locked
136135 * @swseq_reg: Use SW sequencer in register reads/writes
137136 * @swseq_erase: Use SW sequencer in erase operation
@@ -149,7 +148,6 @@ struct intel_spi { · 11 unmodified lines
149148 void __iomem *sregs;
150149 size_t nregions;
151150 size_t pr_num;
152− bool writeable;
153151 bool locked;
154152 bool swseq_reg;
155153 bool swseq_erase;
@@ -304,6 +302,14 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi) · 148 unmodified lines
304302 INTEL_SPI_TIMEOUT * 1000);
305303 }
306304
305+static bool intel_spi_set_writeable(struct intel_spi *ispi)
306+{
307+ if (!ispi->info->set_writeable)
308+ return false;
309+
310+ return ispi->info->set_writeable(ispi->base, ispi->info->data);
311+}
312+
307313 static int intel_spi_init(struct intel_spi *ispi)
308314 {
309315 u32 opmenu0, opmenu1, lvscc, uvscc, val;
@@ -316,19 +322,6 @@ static int intel_spi_init(struct intel_spi *ispi) · 6 unmodified lines
316322 ispi->nregions = BYT_FREG_NUM;
317323 ispi->pr_num = BYT_PR_NUM;
318324 ispi->swseq_reg = true;
319−
320− if (writeable) {
321− /* Disable write protection */
322− val = readl(ispi->base + BYT_BCR);
323− if (!(val & BYT_BCR_WPD)) {
324− val |= BYT_BCR_WPD;
325− writel(val, ispi->base + BYT_BCR);
326− val = readl(ispi->base + BYT_BCR);
327− }
328−
329− ispi->writeable = !!(val & BYT_BCR_WPD);
330− }
331−
332325 break;
333326
334327 case INTEL_SPI_LPT:
@@ -358,6 +351,12 @@ static int intel_spi_init(struct intel_spi *ispi) · 23 unmodified lines
358351 return -EINVAL;
359352 }
360353
354+ /* Try to disable write protection if user asked to do so */
355+ if (writeable && !intel_spi_set_writeable(ispi)) {
356+ dev_warn(ispi->dev, "can't disable chip write protection\n");
357+ writeable = false;
358+ }
359+
361360 /* Disable #SMI generation from HW sequencer */
362361 val = readl(ispi->base + HSFSTS_CTL);
363362 val &= ~HSFSTS_CTL_FSMIE;
@@ -884,9 +883,12 @@ static void intel_spi_fill_partition(struct intel_spi *ispi, · 520 unmodified lines
884883 /*
885884 * If any of the regions have protection bits set, make the
886885 * whole partition read-only to be on the safe side.
886+ *
887+ * Also if the user did not ask the chip to be writeable
888+ * mask the bit too.
887889 */
888− if (intel_spi_is_protected(ispi, base, limit))
889− ispi->writeable = false;
890+ if (!writeable || intel_spi_is_protected(ispi, base, limit))
891+ part->mask_flags |= MTD_WRITEABLE;
890892
891893 end = (limit << 12) + 4096;
892894 if (end > part->size)
@@ -927,7 +929,6 @@ struct intel_spi *intel_spi_probe(struct device *dev, · 34 unmodified lines
927929
928930 ispi->dev = dev;
929931 ispi->info = info;
930− ispi->writeable = info->writeable;
931932
932933 ret = intel_spi_init(ispi);
933934 if (ret)
@@ -945,10 +946,6 @@ struct intel_spi *intel_spi_probe(struct device *dev, · 11 unmodified lines
945946
946947 intel_spi_fill_partition(ispi, &part);
947948
948− /* Prevent writes if not explicitly enabled */
949− if (!ispi->writeable || !writeable)
950− ispi->nor.mtd.flags &= ~MTD_WRITEABLE;
951−
952949 ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
953950 if (ret)
954951 return ERR_PTR(ret);
include/linux/platform_data/x86/intel-spi.h+4−2
@@ -19,11 +19,13 @@ enum intel_spi_type { · 18 unmodified lines
1919 /**
2020 * struct intel_spi_boardinfo - Board specific data for Intel SPI driver
2121 * @type: Type which this controller is compatible with
22− * @writeable: The chip is writeable
22+ * @set_writeable: Try to make the chip writeable (optional)
23+ * @data: Data to be passed to @set_writeable can be %NULL
2324 */
2425 struct intel_spi_boardinfo {
2526 enum intel_spi_type type;
26− bool writeable;
27+ bool (*set_writeable)(void __iomem *base, void *data);
28+ void *data;
2729 };
2830
2931 #endif /* INTEL_SPI_PDATA_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t