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