source: trunk/nicintel_spi.c @ 1510

Revision 1510, 5.1 KB checked in by stefanct, 3 months ago (diff)

nicintel_spi.c: check if write enable is really set (and minor comment changes).

Signed-off-by: Stefan Tauner <stefan.tauner@…>
Acked-by: Idwer Vollering <vidwer@…>

Line 
1/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2010 Carl-Daniel Hailfinger
5 * Copyright (C) 2010 Idwer Vollering
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19 */
20
21/*
22 * Datasheet:
23 * PCI/PCI-X Family of Gigabit Ethernet Controllers Software Developer's Manual
24 * 82540EP/EM, 82541xx, 82544GC/EI, 82545GM/EM, 82546GB/EB, and 82547xx
25 * http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf
26 */
27
28#include <stdlib.h>
29#include "flash.h"
30#include "programmer.h"
31
32#define PCI_VENDOR_ID_INTEL 0x8086
33
34/* EEPROM/Flash Control & Data Register */
35#define EECD    0x10
36/* Flash Access Register */
37#define FLA     0x1c
38
39/*
40 * Register bits of EECD.
41 * Table 13-6
42 *
43 * Bit 04, 05: FWE (Flash Write Enable Control)
44 * 00b = not allowed
45 * 01b = flash writes disabled
46 * 10b = flash writes enabled
47 * 11b = not allowed
48 */
49#define FLASH_WRITES_DISABLED   0x10 /* FWE: 10000b */
50#define FLASH_WRITES_ENABLED    0x20 /* FWE: 100000b */
51
52/* Flash Access register bits
53 * Table 13-9
54 */
55#define FL_SCK  0
56#define FL_CS   1
57#define FL_SI   2
58#define FL_SO   3
59#define FL_REQ  4
60#define FL_GNT  5
61/* Currently unused */
62// #define FL_BUSY      30
63// #define FL_ER        31
64
65uint8_t *nicintel_spibar;
66
67const struct pcidev_status nics_intel_spi[] = {
68        {PCI_VENDOR_ID_INTEL, 0x105e, OK, "Intel", "82571EB Gigabit Ethernet Controller"},
69        {PCI_VENDOR_ID_INTEL, 0x1076, OK, "Intel", "82541GI Gigabit Ethernet Controller"},
70        {PCI_VENDOR_ID_INTEL, 0x107c, OK, "Intel", "82541PI Gigabit Ethernet Controller"},
71        {PCI_VENDOR_ID_INTEL, 0x10b9, OK, "Intel", "82572EI Gigabit Ethernet Controller"},
72
73        {},
74};
75
76static void nicintel_request_spibus(void)
77{
78        uint32_t tmp;
79
80        tmp = pci_mmio_readl(nicintel_spibar + FLA);
81        tmp |= 1 << FL_REQ;
82        pci_mmio_writel(tmp, nicintel_spibar + FLA);
83
84        /* Wait until we are allowed to use the SPI bus. */
85        while (!(pci_mmio_readl(nicintel_spibar + FLA) & (1 << FL_GNT))) ;
86}
87
88static void nicintel_release_spibus(void)
89{
90        uint32_t tmp;
91
92        tmp = pci_mmio_readl(nicintel_spibar + FLA);
93        tmp &= ~(1 << FL_REQ);
94        pci_mmio_writel(tmp, nicintel_spibar + FLA);
95}
96
97static void nicintel_bitbang_set_cs(int val)
98{
99        uint32_t tmp;
100
101        tmp = pci_mmio_readl(nicintel_spibar + FLA);
102        tmp &= ~(1 << FL_CS);
103        tmp |= (val << FL_CS);
104        pci_mmio_writel(tmp,  nicintel_spibar + FLA);
105}
106
107static void nicintel_bitbang_set_sck(int val)
108{
109        uint32_t tmp;
110
111        tmp = pci_mmio_readl(nicintel_spibar + FLA);
112        tmp &= ~(1 << FL_SCK);
113        tmp |= (val << FL_SCK);
114        pci_mmio_writel(tmp, nicintel_spibar + FLA);
115}
116
117static void nicintel_bitbang_set_mosi(int val)
118{
119        uint32_t tmp;
120
121        tmp = pci_mmio_readl(nicintel_spibar + FLA);
122        tmp &= ~(1 << FL_SI);
123        tmp |= (val << FL_SI);
124        pci_mmio_writel(tmp, nicintel_spibar + FLA);
125}
126
127static int nicintel_bitbang_get_miso(void)
128{
129        uint32_t tmp;
130
131        tmp = pci_mmio_readl(nicintel_spibar + FLA);
132        tmp = (tmp >> FL_SO) & 0x1;
133        return tmp;
134}
135
136static const struct bitbang_spi_master bitbang_spi_master_nicintel = {
137        .type = BITBANG_SPI_MASTER_NICINTEL,
138        .set_cs = nicintel_bitbang_set_cs,
139        .set_sck = nicintel_bitbang_set_sck,
140        .set_mosi = nicintel_bitbang_set_mosi,
141        .get_miso = nicintel_bitbang_get_miso,
142        .request_bus = nicintel_request_spibus,
143        .release_bus = nicintel_release_spibus,
144        .half_period = 1,
145};
146
147static int nicintel_spi_shutdown(void *data)
148{
149        uint32_t tmp;
150
151        /* Disable writes manually. See the comment about EECD in
152         * nicintel_spi_init() for details.
153         */
154        tmp = pci_mmio_readl(nicintel_spibar + EECD);
155        tmp &= ~FLASH_WRITES_ENABLED;
156        tmp |= FLASH_WRITES_DISABLED;
157        pci_mmio_writel(tmp, nicintel_spibar + EECD);
158
159        physunmap(nicintel_spibar, 4096);
160        pci_cleanup(pacc);
161        release_io_perms();
162
163        return 0;
164}
165
166int nicintel_spi_init(void)
167{
168        uint32_t tmp;
169
170        get_io_perms();
171
172        io_base_addr = pcidev_init(PCI_BASE_ADDRESS_0, nics_intel_spi);
173
174        nicintel_spibar = physmap("Intel Gigabit NIC w/ SPI flash",
175                                  io_base_addr, 4096);
176        /* Automatic restore of EECD on shutdown is not possible because EECD
177         * does not only contain FLASH_WRITES_DISABLED|FLASH_WRITES_ENABLED,
178         * but other bits with side effects as well. Those other bits must be
179         * left untouched.
180         */
181        tmp = pci_mmio_readl(nicintel_spibar + EECD);
182        tmp &= ~FLASH_WRITES_DISABLED;
183        tmp |= FLASH_WRITES_ENABLED;
184        pci_mmio_writel(tmp, nicintel_spibar + EECD);
185
186        /* test if FWE is really set to allow writes */
187        tmp = pci_mmio_readl(nicintel_spibar + EECD);
188        if ( (tmp & FLASH_WRITES_DISABLED) || !(tmp & FLASH_WRITES_ENABLED) ) {
189                msg_perr("Enabling flash write access failed.\n");
190                return 1;
191        }
192
193        if (register_shutdown(nicintel_spi_shutdown, NULL))
194                return 1;
195
196        if (bitbang_spi_init(&bitbang_spi_master_nicintel))
197                return 1;
198
199        return 0;
200}
Note: See TracBrowser for help on using the repository browser.