xref: /aosp_15_r20/external/flashrom/nicintel_spi.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1*0d6140beSAndroid Build Coastguard Worker /*
2*0d6140beSAndroid Build Coastguard Worker  * This file is part of the flashrom project.
3*0d6140beSAndroid Build Coastguard Worker  *
4*0d6140beSAndroid Build Coastguard Worker  * Copyright (C) 2010 Carl-Daniel Hailfinger
5*0d6140beSAndroid Build Coastguard Worker  * Copyright (C) 2010 Idwer Vollering
6*0d6140beSAndroid Build Coastguard Worker  *
7*0d6140beSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
8*0d6140beSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
9*0d6140beSAndroid Build Coastguard Worker  * the Free Software Foundation; version 2 of the License.
10*0d6140beSAndroid Build Coastguard Worker  *
11*0d6140beSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
12*0d6140beSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*0d6140beSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*0d6140beSAndroid Build Coastguard Worker  * GNU General Public License for more details.
15*0d6140beSAndroid Build Coastguard Worker  */
16*0d6140beSAndroid Build Coastguard Worker 
17*0d6140beSAndroid Build Coastguard Worker /*
18*0d6140beSAndroid Build Coastguard Worker  * Datasheets:
19*0d6140beSAndroid Build Coastguard Worker  * PCI/PCI-X Family of Gigabit Ethernet Controllers Software Developer's Manual
20*0d6140beSAndroid Build Coastguard Worker  * 82540EP/EM, 82541xx, 82544GC/EI, 82545GM/EM, 82546GB/EB, and 82547xx
21*0d6140beSAndroid Build Coastguard Worker  * http://www.intel.com/content/www/us/en/ethernet-controllers/pci-pci-x-family-gbe-controllers-software-dev-manual.html
22*0d6140beSAndroid Build Coastguard Worker  *
23*0d6140beSAndroid Build Coastguard Worker  * PCIe GbE Controllers Open Source Software Developer's Manual
24*0d6140beSAndroid Build Coastguard Worker  * http://www.intel.com/content/www/us/en/ethernet-controllers/pcie-gbe-controllers-open-source-manual.html
25*0d6140beSAndroid Build Coastguard Worker  *
26*0d6140beSAndroid Build Coastguard Worker  * Intel 82574 Gigabit Ethernet Controller Family Datasheet
27*0d6140beSAndroid Build Coastguard Worker  * http://www.intel.com/content/www/us/en/ethernet-controllers/82574l-gbe-controller-datasheet.html
28*0d6140beSAndroid Build Coastguard Worker  *
29*0d6140beSAndroid Build Coastguard Worker  * Intel 82599 10 GbE Controller Datasheet (331520)
30*0d6140beSAndroid Build Coastguard Worker  * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/82599-10-gbe-controller-datasheet.pdf
31*0d6140beSAndroid Build Coastguard Worker  */
32*0d6140beSAndroid Build Coastguard Worker 
33*0d6140beSAndroid Build Coastguard Worker #include <stdlib.h>
34*0d6140beSAndroid Build Coastguard Worker #include <unistd.h>
35*0d6140beSAndroid Build Coastguard Worker #include "flash.h"
36*0d6140beSAndroid Build Coastguard Worker #include "programmer.h"
37*0d6140beSAndroid Build Coastguard Worker #include "hwaccess_physmap.h"
38*0d6140beSAndroid Build Coastguard Worker #include "platform/pci.h"
39*0d6140beSAndroid Build Coastguard Worker 
40*0d6140beSAndroid Build Coastguard Worker #define PCI_VENDOR_ID_INTEL 0x8086
41*0d6140beSAndroid Build Coastguard Worker #define MEMMAP_SIZE getpagesize()
42*0d6140beSAndroid Build Coastguard Worker 
43*0d6140beSAndroid Build Coastguard Worker /* EEPROM/Flash Control & Data Register */
44*0d6140beSAndroid Build Coastguard Worker #define EECD	0x10
45*0d6140beSAndroid Build Coastguard Worker /* Flash Access Register */
46*0d6140beSAndroid Build Coastguard Worker #define FLA	0x1c
47*0d6140beSAndroid Build Coastguard Worker 
48*0d6140beSAndroid Build Coastguard Worker /*
49*0d6140beSAndroid Build Coastguard Worker  * Register bits of EECD.
50*0d6140beSAndroid Build Coastguard Worker  * Table 13-6
51*0d6140beSAndroid Build Coastguard Worker  *
52*0d6140beSAndroid Build Coastguard Worker  * Bit 04, 05: FWE (Flash Write Enable Control)
53*0d6140beSAndroid Build Coastguard Worker  * 00b = not allowed (on some cards this sends an erase command if bit 31 (FL_ER) of FLA is set)
54*0d6140beSAndroid Build Coastguard Worker  * 01b = flash writes disabled
55*0d6140beSAndroid Build Coastguard Worker  * 10b = flash writes enabled
56*0d6140beSAndroid Build Coastguard Worker  * 11b = not allowed
57*0d6140beSAndroid Build Coastguard Worker  */
58*0d6140beSAndroid Build Coastguard Worker #define FLASH_WRITES_DISABLED	0x10 /* FWE: 10000b */
59*0d6140beSAndroid Build Coastguard Worker #define FLASH_WRITES_ENABLED	0x20 /* FWE: 100000b */
60*0d6140beSAndroid Build Coastguard Worker 
61*0d6140beSAndroid Build Coastguard Worker /* Flash Access register bits
62*0d6140beSAndroid Build Coastguard Worker  * Table 13-9
63*0d6140beSAndroid Build Coastguard Worker  */
64*0d6140beSAndroid Build Coastguard Worker #define FL_SCK	0
65*0d6140beSAndroid Build Coastguard Worker #define FL_CS	1
66*0d6140beSAndroid Build Coastguard Worker #define FL_SI	2
67*0d6140beSAndroid Build Coastguard Worker #define FL_SO	3
68*0d6140beSAndroid Build Coastguard Worker #define FL_REQ	4
69*0d6140beSAndroid Build Coastguard Worker #define FL_GNT	5
70*0d6140beSAndroid Build Coastguard Worker #define FL_LOCKED  6
71*0d6140beSAndroid Build Coastguard Worker #define FL_ABORT   7
72*0d6140beSAndroid Build Coastguard Worker #define FL_CLR_ERR 8
73*0d6140beSAndroid Build Coastguard Worker /* Currently unused */
74*0d6140beSAndroid Build Coastguard Worker // #define FL_BUSY	30
75*0d6140beSAndroid Build Coastguard Worker // #define FL_ER	31
76*0d6140beSAndroid Build Coastguard Worker 
77*0d6140beSAndroid Build Coastguard Worker struct nicintel_spi_data {
78*0d6140beSAndroid Build Coastguard Worker 	uint8_t *spibar;
79*0d6140beSAndroid Build Coastguard Worker };
80*0d6140beSAndroid Build Coastguard Worker 
81*0d6140beSAndroid Build Coastguard Worker static const struct dev_entry nics_intel_spi[] = {
82*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x105e, OK, "Intel", "82571EB Gigabit Ethernet Controller"},
83*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1076, OK, "Intel", "82541GI Gigabit Ethernet Controller"},
84*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x107c, OK, "Intel", "82541PI Gigabit Ethernet Controller"},
85*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10b9, OK, "Intel", "82572EI Gigabit Ethernet Controller"},
86*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10d3, OK, "Intel", "82574L Gigabit Ethernet Controller"},
87*0d6140beSAndroid Build Coastguard Worker 
88*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10d8, NT, "Intel", "82599 10 Gigabit Unprogrammed Network Controller"},
89*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10f7, NT, "Intel", "82599 10 Gigabit KX4 Dual Port Network Controller"},
90*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10f8, NT, "Intel", "82599 10 Gigabit Dual Port Backplane Controller"},
91*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10f9, NT, "Intel", "82599 10 Gigabit CX4 Dual Port Network Controller"},
92*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10fb, NT, "Intel", "82599 10-Gigabit SFI/SFP+ Network Controller"},
93*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x10fc, OK, "Intel", "82599 10 Gigabit XAUI/BX4 Dual Port Network Controller"},
94*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1517, NT, "Intel", "82599 10 Gigabit KR Network Controller"},
95*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x151c, NT, "Intel", "82599 10 Gigabit TN Network Controller"},
96*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1529, NT, "Intel", "82599 10 Gigabit Dual Port Network Controller with FCoE"},
97*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x152a, NT, "Intel", "82599 10 Gigabit Dual Port Backplane Controller with FCoE"},
98*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1557, NT, "Intel", "82599 10 Gigabit SFI Network Controller"},
99*0d6140beSAndroid Build Coastguard Worker 
100*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1531, OK, "Intel", "I210 Gigabit Network Connection Unprogrammed"},
101*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1532, NT, "Intel", "I211 Gigabit Network Connection Unprogrammed"},
102*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1533, NT, "Intel", "I210 Gigabit Network Connection"},
103*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1536, NT, "Intel", "I210 Gigabit Network Connection SERDES Fiber"},
104*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1537, NT, "Intel", "I210 Gigabit Network Connection SERDES Backplane"},
105*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1538, NT, "Intel", "I210 Gigabit Network Connection SGMII"},
106*0d6140beSAndroid Build Coastguard Worker 	{PCI_VENDOR_ID_INTEL, 0x1539, NT, "Intel", "I211 Gigabit Network Connection"},
107*0d6140beSAndroid Build Coastguard Worker 
108*0d6140beSAndroid Build Coastguard Worker 	{0},
109*0d6140beSAndroid Build Coastguard Worker };
110*0d6140beSAndroid Build Coastguard Worker 
nicintel_request_spibus(void * spi_data)111*0d6140beSAndroid Build Coastguard Worker static void nicintel_request_spibus(void *spi_data)
112*0d6140beSAndroid Build Coastguard Worker {
113*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
114*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
115*0d6140beSAndroid Build Coastguard Worker 
116*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
117*0d6140beSAndroid Build Coastguard Worker 	tmp |= BIT(FL_REQ);
118*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + FLA);
119*0d6140beSAndroid Build Coastguard Worker 
120*0d6140beSAndroid Build Coastguard Worker 	/* Wait until we are allowed to use the SPI bus. */
121*0d6140beSAndroid Build Coastguard Worker 	while (!(pci_mmio_readl(data->spibar + FLA) & BIT(FL_GNT))) ;
122*0d6140beSAndroid Build Coastguard Worker }
123*0d6140beSAndroid Build Coastguard Worker 
nicintel_release_spibus(void * spi_data)124*0d6140beSAndroid Build Coastguard Worker static void nicintel_release_spibus(void *spi_data)
125*0d6140beSAndroid Build Coastguard Worker {
126*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
127*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
128*0d6140beSAndroid Build Coastguard Worker 
129*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
130*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~BIT(FL_REQ);
131*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + FLA);
132*0d6140beSAndroid Build Coastguard Worker }
133*0d6140beSAndroid Build Coastguard Worker 
nicintel_bitbang_set_cs(int val,void * spi_data)134*0d6140beSAndroid Build Coastguard Worker static void nicintel_bitbang_set_cs(int val, void *spi_data)
135*0d6140beSAndroid Build Coastguard Worker {
136*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
137*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
138*0d6140beSAndroid Build Coastguard Worker 
139*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
140*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~BIT(FL_CS);
141*0d6140beSAndroid Build Coastguard Worker 	tmp |= (val << FL_CS);
142*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + FLA);
143*0d6140beSAndroid Build Coastguard Worker }
144*0d6140beSAndroid Build Coastguard Worker 
nicintel_bitbang_set_sck(int val,void * spi_data)145*0d6140beSAndroid Build Coastguard Worker static void nicintel_bitbang_set_sck(int val, void *spi_data)
146*0d6140beSAndroid Build Coastguard Worker {
147*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
148*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
149*0d6140beSAndroid Build Coastguard Worker 
150*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
151*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~BIT(FL_SCK);
152*0d6140beSAndroid Build Coastguard Worker 	tmp |= (val << FL_SCK);
153*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + FLA);
154*0d6140beSAndroid Build Coastguard Worker }
155*0d6140beSAndroid Build Coastguard Worker 
nicintel_bitbang_set_mosi(int val,void * spi_data)156*0d6140beSAndroid Build Coastguard Worker static void nicintel_bitbang_set_mosi(int val, void *spi_data)
157*0d6140beSAndroid Build Coastguard Worker {
158*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
159*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
160*0d6140beSAndroid Build Coastguard Worker 
161*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
162*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~BIT(FL_SI);
163*0d6140beSAndroid Build Coastguard Worker 	tmp |= (val << FL_SI);
164*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + FLA);
165*0d6140beSAndroid Build Coastguard Worker }
166*0d6140beSAndroid Build Coastguard Worker 
nicintel_bitbang_set_sck_set_mosi(int sck,int mosi,void * spi_data)167*0d6140beSAndroid Build Coastguard Worker static void nicintel_bitbang_set_sck_set_mosi(int sck, int mosi, void *spi_data)
168*0d6140beSAndroid Build Coastguard Worker {
169*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
170*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
171*0d6140beSAndroid Build Coastguard Worker 
172*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
173*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~BIT(FL_SCK);
174*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~BIT(FL_SI);
175*0d6140beSAndroid Build Coastguard Worker 	tmp |= (sck << FL_SCK);
176*0d6140beSAndroid Build Coastguard Worker 	tmp |= (mosi << FL_SI);
177*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + FLA);
178*0d6140beSAndroid Build Coastguard Worker }
179*0d6140beSAndroid Build Coastguard Worker 
nicintel_bitbang_get_miso(void * spi_data)180*0d6140beSAndroid Build Coastguard Worker static int nicintel_bitbang_get_miso(void *spi_data)
181*0d6140beSAndroid Build Coastguard Worker {
182*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
183*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
184*0d6140beSAndroid Build Coastguard Worker 
185*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
186*0d6140beSAndroid Build Coastguard Worker 	tmp = (tmp >> FL_SO) & 0x1;
187*0d6140beSAndroid Build Coastguard Worker 	return tmp;
188*0d6140beSAndroid Build Coastguard Worker }
189*0d6140beSAndroid Build Coastguard Worker 
nicintel_bitbang_set_sck_get_miso(int sck,void * spi_data)190*0d6140beSAndroid Build Coastguard Worker static int nicintel_bitbang_set_sck_get_miso(int sck, void *spi_data)
191*0d6140beSAndroid Build Coastguard Worker {
192*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
193*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
194*0d6140beSAndroid Build Coastguard Worker 
195*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
196*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~BIT(FL_SCK);
197*0d6140beSAndroid Build Coastguard Worker 	tmp |= (sck << FL_SCK);
198*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + FLA);
199*0d6140beSAndroid Build Coastguard Worker 	return (tmp >> FL_SO) & 0x1;
200*0d6140beSAndroid Build Coastguard Worker }
201*0d6140beSAndroid Build Coastguard Worker 
202*0d6140beSAndroid Build Coastguard Worker static const struct bitbang_spi_master bitbang_spi_master_nicintel = {
203*0d6140beSAndroid Build Coastguard Worker 	.set_cs			= nicintel_bitbang_set_cs,
204*0d6140beSAndroid Build Coastguard Worker 	.set_sck		= nicintel_bitbang_set_sck,
205*0d6140beSAndroid Build Coastguard Worker 	.set_mosi		= nicintel_bitbang_set_mosi,
206*0d6140beSAndroid Build Coastguard Worker 	.set_sck_set_mosi	= nicintel_bitbang_set_sck_set_mosi,
207*0d6140beSAndroid Build Coastguard Worker 	.set_sck_get_miso	= nicintel_bitbang_set_sck_get_miso,
208*0d6140beSAndroid Build Coastguard Worker 	.get_miso		= nicintel_bitbang_get_miso,
209*0d6140beSAndroid Build Coastguard Worker 	.request_bus		= nicintel_request_spibus,
210*0d6140beSAndroid Build Coastguard Worker 	.release_bus		= nicintel_release_spibus,
211*0d6140beSAndroid Build Coastguard Worker 	.half_period		= 1,
212*0d6140beSAndroid Build Coastguard Worker };
213*0d6140beSAndroid Build Coastguard Worker 
nicintel_spi_shutdown(void * spi_data)214*0d6140beSAndroid Build Coastguard Worker static int nicintel_spi_shutdown(void *spi_data)
215*0d6140beSAndroid Build Coastguard Worker {
216*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = spi_data;
217*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
218*0d6140beSAndroid Build Coastguard Worker 
219*0d6140beSAndroid Build Coastguard Worker 	/* Disable writes manually. See the comment about EECD in nicintel_spi_init() for details. */
220*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + EECD);
221*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~FLASH_WRITES_ENABLED;
222*0d6140beSAndroid Build Coastguard Worker 	tmp |= FLASH_WRITES_DISABLED;
223*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + EECD);
224*0d6140beSAndroid Build Coastguard Worker 
225*0d6140beSAndroid Build Coastguard Worker 	free(data);
226*0d6140beSAndroid Build Coastguard Worker 	return 0;
227*0d6140beSAndroid Build Coastguard Worker }
228*0d6140beSAndroid Build Coastguard Worker 
nicintel_spi_82599_enable_flash(struct nicintel_spi_data * data)229*0d6140beSAndroid Build Coastguard Worker static int nicintel_spi_82599_enable_flash(struct nicintel_spi_data *data)
230*0d6140beSAndroid Build Coastguard Worker {
231*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
232*0d6140beSAndroid Build Coastguard Worker 
233*0d6140beSAndroid Build Coastguard Worker 	/* Automatic restore of EECD on shutdown is not possible because EECD
234*0d6140beSAndroid Build Coastguard Worker 	 * does not only contain FLASH_WRITES_DISABLED|FLASH_WRITES_ENABLED,
235*0d6140beSAndroid Build Coastguard Worker 	 * but other bits with side effects as well. Those other bits must be
236*0d6140beSAndroid Build Coastguard Worker 	 * left untouched.
237*0d6140beSAndroid Build Coastguard Worker 	 */
238*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + EECD);
239*0d6140beSAndroid Build Coastguard Worker 	tmp &= ~FLASH_WRITES_DISABLED;
240*0d6140beSAndroid Build Coastguard Worker 	tmp |= FLASH_WRITES_ENABLED;
241*0d6140beSAndroid Build Coastguard Worker 	pci_mmio_writel(tmp, data->spibar + EECD);
242*0d6140beSAndroid Build Coastguard Worker 
243*0d6140beSAndroid Build Coastguard Worker 	/* test if FWE is really set to allow writes */
244*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + EECD);
245*0d6140beSAndroid Build Coastguard Worker 	if ( (tmp & FLASH_WRITES_DISABLED) || !(tmp & FLASH_WRITES_ENABLED) ) {
246*0d6140beSAndroid Build Coastguard Worker 		msg_perr("Enabling flash write access failed.\n");
247*0d6140beSAndroid Build Coastguard Worker 		return 1;
248*0d6140beSAndroid Build Coastguard Worker 	}
249*0d6140beSAndroid Build Coastguard Worker 
250*0d6140beSAndroid Build Coastguard Worker 	if (register_shutdown(nicintel_spi_shutdown, data))
251*0d6140beSAndroid Build Coastguard Worker 		return 1;
252*0d6140beSAndroid Build Coastguard Worker 
253*0d6140beSAndroid Build Coastguard Worker 	return 0;
254*0d6140beSAndroid Build Coastguard Worker }
255*0d6140beSAndroid Build Coastguard Worker 
nicintel_spi_i210_shutdown(void * data)256*0d6140beSAndroid Build Coastguard Worker static int nicintel_spi_i210_shutdown(void *data)
257*0d6140beSAndroid Build Coastguard Worker {
258*0d6140beSAndroid Build Coastguard Worker 	free(data);
259*0d6140beSAndroid Build Coastguard Worker 	return 0;
260*0d6140beSAndroid Build Coastguard Worker }
261*0d6140beSAndroid Build Coastguard Worker 
nicintel_spi_i210_enable_flash(struct nicintel_spi_data * data)262*0d6140beSAndroid Build Coastguard Worker static int nicintel_spi_i210_enable_flash(struct nicintel_spi_data *data)
263*0d6140beSAndroid Build Coastguard Worker {
264*0d6140beSAndroid Build Coastguard Worker 	uint32_t tmp;
265*0d6140beSAndroid Build Coastguard Worker 
266*0d6140beSAndroid Build Coastguard Worker 	tmp = pci_mmio_readl(data->spibar + FLA);
267*0d6140beSAndroid Build Coastguard Worker 	if (tmp & BIT(FL_LOCKED)) {
268*0d6140beSAndroid Build Coastguard Worker 		msg_perr("Flash is in Secure Mode. Abort.\n");
269*0d6140beSAndroid Build Coastguard Worker 		return 1;
270*0d6140beSAndroid Build Coastguard Worker 	}
271*0d6140beSAndroid Build Coastguard Worker 
272*0d6140beSAndroid Build Coastguard Worker 	if (tmp & BIT(FL_ABORT)) {
273*0d6140beSAndroid Build Coastguard Worker 		tmp |= BIT(FL_CLR_ERR);
274*0d6140beSAndroid Build Coastguard Worker 		pci_mmio_writel(tmp, data->spibar + FLA);
275*0d6140beSAndroid Build Coastguard Worker 		tmp = pci_mmio_readl(data->spibar + FLA);
276*0d6140beSAndroid Build Coastguard Worker 		if (!(tmp & BIT(FL_ABORT))) {
277*0d6140beSAndroid Build Coastguard Worker 			msg_perr("Unable to clear Flash Access Error. Abort\n");
278*0d6140beSAndroid Build Coastguard Worker 			return 1;
279*0d6140beSAndroid Build Coastguard Worker 		}
280*0d6140beSAndroid Build Coastguard Worker 	}
281*0d6140beSAndroid Build Coastguard Worker 
282*0d6140beSAndroid Build Coastguard Worker 	if (register_shutdown(nicintel_spi_i210_shutdown, data))
283*0d6140beSAndroid Build Coastguard Worker 		return 1;
284*0d6140beSAndroid Build Coastguard Worker 
285*0d6140beSAndroid Build Coastguard Worker 	return 0;
286*0d6140beSAndroid Build Coastguard Worker }
287*0d6140beSAndroid Build Coastguard Worker 
nicintel_spi_init(const struct programmer_cfg * cfg)288*0d6140beSAndroid Build Coastguard Worker static int nicintel_spi_init(const struct programmer_cfg *cfg)
289*0d6140beSAndroid Build Coastguard Worker {
290*0d6140beSAndroid Build Coastguard Worker 	struct pci_dev *dev = NULL;
291*0d6140beSAndroid Build Coastguard Worker 
292*0d6140beSAndroid Build Coastguard Worker 	dev = pcidev_init(cfg, nics_intel_spi, PCI_BASE_ADDRESS_0);
293*0d6140beSAndroid Build Coastguard Worker 	if (!dev)
294*0d6140beSAndroid Build Coastguard Worker 		return 1;
295*0d6140beSAndroid Build Coastguard Worker 
296*0d6140beSAndroid Build Coastguard Worker 	uint32_t io_base_addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_0);
297*0d6140beSAndroid Build Coastguard Worker 	if (!io_base_addr)
298*0d6140beSAndroid Build Coastguard Worker 		return 1;
299*0d6140beSAndroid Build Coastguard Worker 
300*0d6140beSAndroid Build Coastguard Worker 	struct nicintel_spi_data *data = calloc(1, sizeof(*data));
301*0d6140beSAndroid Build Coastguard Worker 	if (!data) {
302*0d6140beSAndroid Build Coastguard Worker 		msg_perr("Unable to allocate space for SPI master data\n");
303*0d6140beSAndroid Build Coastguard Worker 		return 1;
304*0d6140beSAndroid Build Coastguard Worker 	}
305*0d6140beSAndroid Build Coastguard Worker 
306*0d6140beSAndroid Build Coastguard Worker 	if ((dev->device_id & 0xfff0) == 0x1530) {
307*0d6140beSAndroid Build Coastguard Worker 		data->spibar = rphysmap("Intel I210 Gigabit w/ SPI flash", io_base_addr + 0x12000,
308*0d6140beSAndroid Build Coastguard Worker 					   MEMMAP_SIZE);
309*0d6140beSAndroid Build Coastguard Worker 		if (!data->spibar || nicintel_spi_i210_enable_flash(data)) {
310*0d6140beSAndroid Build Coastguard Worker 				free(data);
311*0d6140beSAndroid Build Coastguard Worker 				return 1;
312*0d6140beSAndroid Build Coastguard Worker 		}
313*0d6140beSAndroid Build Coastguard Worker 	} else if (dev->device_id < 0x10d8) {
314*0d6140beSAndroid Build Coastguard Worker 		data->spibar = rphysmap("Intel Gigabit NIC w/ SPI flash", io_base_addr,
315*0d6140beSAndroid Build Coastguard Worker 					   MEMMAP_SIZE);
316*0d6140beSAndroid Build Coastguard Worker 		if (!data->spibar || nicintel_spi_82599_enable_flash(data)) {
317*0d6140beSAndroid Build Coastguard Worker 				free(data);
318*0d6140beSAndroid Build Coastguard Worker 				return 1;
319*0d6140beSAndroid Build Coastguard Worker 		}
320*0d6140beSAndroid Build Coastguard Worker 	} else {
321*0d6140beSAndroid Build Coastguard Worker 		data->spibar = rphysmap("Intel 10 Gigabit NIC w/ SPI flash", io_base_addr + 0x10000,
322*0d6140beSAndroid Build Coastguard Worker 					   MEMMAP_SIZE);
323*0d6140beSAndroid Build Coastguard Worker 		if (!data->spibar || nicintel_spi_82599_enable_flash(data)) {
324*0d6140beSAndroid Build Coastguard Worker 				free(data);
325*0d6140beSAndroid Build Coastguard Worker 				return 1;
326*0d6140beSAndroid Build Coastguard Worker 		}
327*0d6140beSAndroid Build Coastguard Worker 	}
328*0d6140beSAndroid Build Coastguard Worker 
329*0d6140beSAndroid Build Coastguard Worker 	if (register_spi_bitbang_master(&bitbang_spi_master_nicintel, data))
330*0d6140beSAndroid Build Coastguard Worker 		return 1; /* shutdown function does cleanup */
331*0d6140beSAndroid Build Coastguard Worker 
332*0d6140beSAndroid Build Coastguard Worker 	return 0;
333*0d6140beSAndroid Build Coastguard Worker }
334*0d6140beSAndroid Build Coastguard Worker 
335*0d6140beSAndroid Build Coastguard Worker const struct programmer_entry programmer_nicintel_spi = {
336*0d6140beSAndroid Build Coastguard Worker 	.name			= "nicintel_spi",
337*0d6140beSAndroid Build Coastguard Worker 	.type			= PCI,
338*0d6140beSAndroid Build Coastguard Worker 	.devs.dev		= nics_intel_spi,
339*0d6140beSAndroid Build Coastguard Worker 	.init			= nicintel_spi_init,
340*0d6140beSAndroid Build Coastguard Worker };
341