1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Intel PCH/PCU SPI flash PCI driver. |
4 | * |
5 | * Copyright (C) 2016 - 2022, Intel Corporation |
6 | * Author: Mika Westerberg <mika.westerberg@linux.intel.com> |
7 | */ |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/pci.h> |
11 | |
12 | #include "spi-intel.h" |
13 | |
14 | #define BCR 0xdc |
15 | #define BCR_WPD BIT(0) |
16 | |
17 | static bool intel_spi_pci_set_writeable(void __iomem *base, void *data) |
18 | { |
19 | struct pci_dev *pdev = data; |
20 | u32 bcr; |
21 | |
22 | /* Try to make the chip read/write */ |
23 | pci_read_config_dword(dev: pdev, BCR, val: &bcr); |
24 | if (!(bcr & BCR_WPD)) { |
25 | bcr |= BCR_WPD; |
26 | pci_write_config_dword(dev: pdev, BCR, val: bcr); |
27 | pci_read_config_dword(dev: pdev, BCR, val: &bcr); |
28 | } |
29 | |
30 | return bcr & BCR_WPD; |
31 | } |
32 | |
33 | static const struct intel_spi_boardinfo bxt_info = { |
34 | .type = INTEL_SPI_BXT, |
35 | .set_writeable = intel_spi_pci_set_writeable, |
36 | }; |
37 | |
38 | static const struct intel_spi_boardinfo cnl_info = { |
39 | .type = INTEL_SPI_CNL, |
40 | .set_writeable = intel_spi_pci_set_writeable, |
41 | }; |
42 | |
43 | static int intel_spi_pci_probe(struct pci_dev *pdev, |
44 | const struct pci_device_id *id) |
45 | { |
46 | struct intel_spi_boardinfo *info; |
47 | int ret; |
48 | |
49 | ret = pcim_enable_device(pdev); |
50 | if (ret) |
51 | return ret; |
52 | |
53 | info = devm_kmemdup(dev: &pdev->dev, src: (void *)id->driver_data, len: sizeof(*info), |
54 | GFP_KERNEL); |
55 | if (!info) |
56 | return -ENOMEM; |
57 | |
58 | info->data = pdev; |
59 | return intel_spi_probe(dev: &pdev->dev, mem: &pdev->resource[0], info); |
60 | } |
61 | |
62 | static const struct pci_device_id intel_spi_pci_ids[] = { |
63 | { PCI_VDEVICE(INTEL, 0x02a4), (unsigned long)&cnl_info }, |
64 | { PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&cnl_info }, |
65 | { PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info }, |
66 | { PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info }, |
67 | { PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info }, |
68 | { PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&cnl_info }, |
69 | { PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info }, |
70 | { PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info }, |
71 | { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, |
72 | { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, |
73 | { PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info }, |
74 | { PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info }, |
75 | { PCI_VDEVICE(INTEL, 0x5794), (unsigned long)&cnl_info }, |
76 | { PCI_VDEVICE(INTEL, 0x7a24), (unsigned long)&cnl_info }, |
77 | { PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info }, |
78 | { PCI_VDEVICE(INTEL, 0x7e23), (unsigned long)&cnl_info }, |
79 | { PCI_VDEVICE(INTEL, 0x7f24), (unsigned long)&cnl_info }, |
80 | { PCI_VDEVICE(INTEL, 0x9d24), (unsigned long)&cnl_info }, |
81 | { PCI_VDEVICE(INTEL, 0x9da4), (unsigned long)&cnl_info }, |
82 | { PCI_VDEVICE(INTEL, 0xa0a4), (unsigned long)&cnl_info }, |
83 | { PCI_VDEVICE(INTEL, 0xa1a4), (unsigned long)&bxt_info }, |
84 | { PCI_VDEVICE(INTEL, 0xa224), (unsigned long)&bxt_info }, |
85 | { PCI_VDEVICE(INTEL, 0xa2a4), (unsigned long)&cnl_info }, |
86 | { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info }, |
87 | { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&cnl_info }, |
88 | { PCI_VDEVICE(INTEL, 0xa823), (unsigned long)&cnl_info }, |
89 | { }, |
90 | }; |
91 | MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids); |
92 | |
93 | static struct pci_driver intel_spi_pci_driver = { |
94 | .name = "intel-spi" , |
95 | .id_table = intel_spi_pci_ids, |
96 | .probe = intel_spi_pci_probe, |
97 | }; |
98 | |
99 | module_pci_driver(intel_spi_pci_driver); |
100 | |
101 | MODULE_DESCRIPTION("Intel PCH/PCU SPI flash PCI driver" ); |
102 | MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>" ); |
103 | MODULE_LICENSE("GPL v2" ); |
104 | |