xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/block/spi/spi.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #define __SIMPLE_DEVICE__
4 
5 #include <assert.h>
6 #include <commonlib/bsd/helpers.h>
7 #include <device/device.h>
8 #include <device/mmio.h>
9 #include <device/pci.h>
10 #include <device/pci_ids.h>
11 #include <device/pci_ops.h>
12 #include <device/spi.h>
13 #include <intelblocks/fast_spi.h>
14 #include <intelblocks/gspi.h>
15 #include <intelblocks/spi.h>
16 #include <soc/pci_devs.h>
17 #include <spi-generic.h>
18 #include <types.h>
19 
20 const struct spi_ctrlr_buses spi_ctrlr_bus_map[] = {
21 	{ .ctrlr = &fast_spi_flash_ctrlr, .bus_start = 0, .bus_end = 0 },
22 #if !ENV_SMM && CONFIG(SOC_INTEL_COMMON_BLOCK_GSPI)
23 	{ .ctrlr = &gspi_ctrlr, .bus_start = 1,
24 	  .bus_end =  1 + (CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX - 1)},
25 #endif
26 };
27 
28 const size_t spi_ctrlr_bus_map_count = ARRAY_SIZE(spi_ctrlr_bus_map);
29 
30 #define MMIO_BIOS_GPR0	0x98
31 
32 union spi_bios_gpr0 {
33 	struct {
34 		/* Specified write protection is enabled */
35 		/*
36 		 * This field corresponds to flash address bits 26:12
37 		 * and specifies the lower limit of protected range.
38 		 */
39 		uint32_t protect_range_base:15;
40 
41 		/* Specifies read protection is enabled */
42 		uint32_t read_protect_en:1;
43 
44 		/*
45 		 * This field corresponds to flash address bits 26:12
46 		 * and specifies the upper limit of the protected range
47 		 */
48 		uint32_t protect_range_limit:15;
49 
50 		uint32_t write_protect_en:1;
51 	} __packed fields;
52 
53 	uint32_t data;
54 };
55 
56 /* Read SPI BAR 0 from PCI configuration space */
get_spi_bar(pci_devfn_t dev)57 static uintptr_t get_spi_bar(pci_devfn_t dev)
58 {
59 	uintptr_t bar;
60 
61 	bar = pci_read_config32(dev, PCI_BASE_ADDRESS_0);
62 	assert(bar != 0);
63 	/*
64 	 * Bits 31-12 are the base address as per EDS for SPI,
65 	 * Don't care about 0-11 bit
66 	 */
67 	return bar & ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
68 }
69 
spi_read_bar(pci_devfn_t dev,uint32_t offset)70 static uint32_t spi_read_bar(pci_devfn_t dev, uint32_t offset)
71 {
72 	return read32p(get_spi_bar(dev) + offset);
73 }
74 
spi_read_bios_gpr0(void)75 static uint32_t spi_read_bios_gpr0(void)
76 {
77 	return spi_read_bar(PCH_DEV_SPI, MMIO_BIOS_GPR0);
78 }
79 
spi_get_wp_cse_ro_start_offset(union spi_bios_gpr0 bios_gpr0)80 static uint32_t spi_get_wp_cse_ro_start_offset(union spi_bios_gpr0 bios_gpr0)
81 {
82 	return bios_gpr0.fields.protect_range_base << 12;
83 }
84 
spi_get_wp_cse_ro_limit(union spi_bios_gpr0 bios_gpr0)85 static uint32_t spi_get_wp_cse_ro_limit(union spi_bios_gpr0 bios_gpr0)
86 {
87 	return bios_gpr0.fields.protect_range_limit << 12 | 0xfff;
88 }
89 
is_spi_wp_cse_ro_en(void)90 bool is_spi_wp_cse_ro_en(void)
91 {
92 	union spi_bios_gpr0 bios_gpr0;
93 
94 	bios_gpr0.data = spi_read_bios_gpr0();
95 	return !!bios_gpr0.fields.write_protect_en;
96 }
97 
spi_get_wp_cse_ro_range(uint32_t * base,uint32_t * limit)98 void spi_get_wp_cse_ro_range(uint32_t *base, uint32_t *limit)
99 {
100 	union spi_bios_gpr0 bios_gpr0;
101 
102 	bios_gpr0.data = spi_read_bios_gpr0();
103 	*base = spi_get_wp_cse_ro_start_offset(bios_gpr0);
104 	*limit = spi_get_wp_cse_ro_limit(bios_gpr0);
105 }
106 
spi_dev_to_bus(struct device * dev)107 static int spi_dev_to_bus(struct device *dev)
108 {
109 	return spi_soc_devfn_to_bus(dev->path.pci.devfn);
110 }
111 
112 static struct spi_bus_operations spi_bus_ops = {
113 	.dev_to_bus			= &spi_dev_to_bus,
114 };
115 
116 struct device_operations spi_dev_ops = {
117 	.read_resources			= pci_dev_read_resources,
118 	.set_resources			= pci_dev_set_resources,
119 	.enable_resources		= pci_dev_enable_resources,
120 	.scan_bus			= scan_generic_bus,
121 	.ops_spi_bus			= &spi_bus_ops,
122 	.ops_pci			= &pci_dev_ops_pci,
123 };
124 
125 static const unsigned short pci_device_ids[] = {
126 	PCI_DID_INTEL_PTL_HWSEQ_SPI,
127 	PCI_DID_INTEL_PTL_SPI0,
128 	PCI_DID_INTEL_PTL_SPI1,
129 	PCI_DID_INTEL_PTL_SPI2,
130 	PCI_DID_INTEL_LNL_GSPI0,
131 	PCI_DID_INTEL_LNL_GSPI1,
132 	PCI_DID_INTEL_LNL_GSPI2,
133 	PCI_DID_INTEL_MTL_GSPI0,
134 	PCI_DID_INTEL_MTL_GSPI1,
135 	PCI_DID_INTEL_MTL_GSPI2,
136 	PCI_DID_INTEL_APL_SPI0,
137 	PCI_DID_INTEL_APL_SPI1,
138 	PCI_DID_INTEL_APL_SPI2,
139 	PCI_DID_INTEL_GLK_SPI0,
140 	PCI_DID_INTEL_GLK_SPI1,
141 	PCI_DID_INTEL_GLK_SPI2,
142 	PCI_DID_INTEL_CNL_SPI0,
143 	PCI_DID_INTEL_CNL_SPI1,
144 	PCI_DID_INTEL_CNL_SPI2,
145 	PCI_DID_INTEL_CNP_H_SPI0,
146 	PCI_DID_INTEL_CNP_H_SPI1,
147 	PCI_DID_INTEL_CNP_H_SPI2,
148 	PCI_DID_INTEL_ICP_SPI0,
149 	PCI_DID_INTEL_ICP_SPI1,
150 	PCI_DID_INTEL_ICP_SPI2,
151 	PCI_DID_INTEL_CMP_SPI0,
152 	PCI_DID_INTEL_CMP_SPI1,
153 	PCI_DID_INTEL_CMP_SPI2,
154 	PCI_DID_INTEL_CMP_H_SPI0,
155 	PCI_DID_INTEL_CMP_H_SPI1,
156 	PCI_DID_INTEL_CMP_H_SPI2,
157 	PCI_DID_INTEL_TGP_GSPI0,
158 	PCI_DID_INTEL_TGP_GSPI1,
159 	PCI_DID_INTEL_TGP_GSPI2,
160 	PCI_DID_INTEL_TGP_GSPI3,
161 	PCI_DID_INTEL_TGP_GSPI4,
162 	PCI_DID_INTEL_TGP_GSPI5,
163 	PCI_DID_INTEL_TGP_GSPI6,
164 	PCI_DID_INTEL_TGP_H_SPI0,
165 	PCI_DID_INTEL_TGP_H_GSPI0,
166 	PCI_DID_INTEL_TGP_H_GSPI1,
167 	PCI_DID_INTEL_TGP_H_GSPI2,
168 	PCI_DID_INTEL_TGP_H_GSPI3,
169 	PCI_DID_INTEL_MCC_GSPI0,
170 	PCI_DID_INTEL_MCC_GSPI1,
171 	PCI_DID_INTEL_MCC_GSPI2,
172 	PCI_DID_INTEL_JSP_SPI0,
173 	PCI_DID_INTEL_JSP_SPI1,
174 	PCI_DID_INTEL_JSP_SPI2,
175 	PCI_DID_INTEL_ADP_P_SPI0,
176 	PCI_DID_INTEL_ADP_P_SPI1,
177 	PCI_DID_INTEL_ADP_P_SPI2,
178 	PCI_DID_INTEL_ADP_P_SPI3,
179 	PCI_DID_INTEL_ADP_P_SPI4,
180 	PCI_DID_INTEL_ADP_P_SPI5,
181 	PCI_DID_INTEL_ADP_P_SPI6,
182 	PCI_DID_INTEL_ADP_S_SPI0,
183 	PCI_DID_INTEL_ADP_S_SPI1,
184 	PCI_DID_INTEL_ADP_S_SPI2,
185 	PCI_DID_INTEL_ADP_S_SPI3,
186 	PCI_DID_INTEL_ADP_S_SPI4,
187 	PCI_DID_INTEL_ADP_S_SPI5,
188 	PCI_DID_INTEL_ADP_S_SPI6,
189 	PCI_DID_INTEL_ADP_M_N_SPI0,
190 	PCI_DID_INTEL_ADP_M_N_SPI1,
191 	PCI_DID_INTEL_ADP_M_SPI2,
192 	PCI_DID_INTEL_RPP_S_SPI0,
193 	PCI_DID_INTEL_RPP_S_SPI1,
194 	PCI_DID_INTEL_RPP_S_SPI2,
195 	PCI_DID_INTEL_RPP_S_SPI3,
196 	PCI_DID_INTEL_DNV_SPI,
197 	0
198 };
199 
200 static const struct pci_driver pch_spi __pci_driver = {
201 	.ops				= &spi_dev_ops,
202 	.vendor				= PCI_VID_INTEL,
203 	.devices			= pci_device_ids,
204 };
205