source: trunk/spi.c @ 1475

Revision 1475, 5.4 KB checked in by hailfinger, 5 months ago (diff)

Have all programmer init functions register bus masters/programmers

All programmer types (Parallel, SPI, Opaque) now register themselves
into a generic programmer list and probing is now programmer-centric
instead of chip-centric.
Registering multiple SPI/... masters at the same time is now possible
without any problems. Handling multiple flash chips is still unchanged,
but now we have the infrastructure to deal with "dual BIOS" and "one
flash behind southbridge and one flash behind EC" sanely.

A nice side effect is that this patch kills quite a few global variables
and improves the situation for libflashrom.

Hint for developers:
struct {spi,par,opaque}_programmer now have a void *data pointer to
store any additional programmer-specific data, e.g. hardware
configuration info.

Note:
flashrom -f -c FOO -r forced_read.bin
does not work anymore. We have to find an architecturally clean way to
solve this.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@…>
Acked-by: Michael Karcher <flashrom@…>

Line 
1/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2007, 2008, 2009, 2010, 2011 Carl-Daniel Hailfinger
5 * Copyright (C) 2008 coresystems GmbH
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 * Contains the generic SPI framework
23 */
24
25#include <strings.h>
26#include <string.h>
27#include "flash.h"
28#include "flashchips.h"
29#include "chipdrivers.h"
30#include "programmer.h"
31#include "spi.h"
32
33int spi_send_command(struct flashctx *flash, unsigned int writecnt,
34                     unsigned int readcnt, const unsigned char *writearr,
35                     unsigned char *readarr)
36{
37        return flash->pgm->spi.command(flash, writecnt, readcnt, writearr,
38                                       readarr);
39}
40
41int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds)
42{
43        return flash->pgm->spi.multicommand(flash, cmds);
44}
45
46int default_spi_send_command(struct flashctx *flash, unsigned int writecnt,
47                             unsigned int readcnt,
48                             const unsigned char *writearr,
49                             unsigned char *readarr)
50{
51        struct spi_command cmd[] = {
52        {
53                .writecnt = writecnt,
54                .readcnt = readcnt,
55                .writearr = writearr,
56                .readarr = readarr,
57        }, {
58                .writecnt = 0,
59                .writearr = NULL,
60                .readcnt = 0,
61                .readarr = NULL,
62        }};
63
64        return spi_send_multicommand(flash, cmd);
65}
66
67int default_spi_send_multicommand(struct flashctx *flash,
68                                  struct spi_command *cmds)
69{
70        int result = 0;
71        for (; (cmds->writecnt || cmds->readcnt) && !result; cmds++) {
72                result = spi_send_command(flash, cmds->writecnt, cmds->readcnt,
73                                          cmds->writearr, cmds->readarr);
74        }
75        return result;
76}
77
78int default_spi_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
79                     unsigned int len)
80{
81        unsigned int max_data = flash->pgm->spi.max_data_read;
82        if (max_data == MAX_DATA_UNSPECIFIED) {
83                msg_perr("%s called, but SPI read chunk size not defined "
84                         "on this hardware. Please report a bug at "
85                         "flashrom@flashrom.org\n", __func__);
86                return 1;
87        }
88        return spi_read_chunked(flash, buf, start, len, max_data);
89}
90
91int default_spi_write_256(struct flashctx *flash, uint8_t *buf,
92                          unsigned int start, unsigned int len)
93{
94        unsigned int max_data = flash->pgm->spi.max_data_write;
95        if (max_data == MAX_DATA_UNSPECIFIED) {
96                msg_perr("%s called, but SPI write chunk size not defined "
97                         "on this hardware. Please report a bug at "
98                         "flashrom@flashrom.org\n", __func__);
99                return 1;
100        }
101        return spi_write_chunked(flash, buf, start, len, max_data);
102}
103
104int spi_chip_read(struct flashctx *flash, uint8_t *buf, unsigned int start,
105                  unsigned int len)
106{
107        unsigned int addrbase = 0;
108
109        /* Check if the chip fits between lowest valid and highest possible
110         * address. Highest possible address with the current SPI implementation
111         * means 0xffffff, the highest unsigned 24bit number.
112         */
113        addrbase = spi_get_valid_read_addr(flash);
114        if (addrbase + flash->total_size * 1024 > (1 << 24)) {
115                msg_perr("Flash chip size exceeds the allowed access window. ");
116                msg_perr("Read will probably fail.\n");
117                /* Try to get the best alignment subject to constraints. */
118                addrbase = (1 << 24) - flash->total_size * 1024;
119        }
120        /* Check if alignment is native (at least the largest power of two which
121         * is a factor of the mapped size of the chip).
122         */
123        if (ffs(flash->total_size * 1024) > (ffs(addrbase) ? : 33)) {
124                msg_perr("Flash chip is not aligned natively in the allowed "
125                         "access window.\n");
126                msg_perr("Read will probably return garbage.\n");
127        }
128        return flash->pgm->spi.read(flash, buf, addrbase + start, len);
129}
130
131/*
132 * Program chip using page (256 bytes) programming.
133 * Some SPI masters can't do this, they use single byte programming instead.
134 * The redirect to single byte programming is achieved by setting
135 * .write_256 = spi_chip_write_1
136 */
137/* real chunksize is up to 256, logical chunksize is 256 */
138int spi_chip_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start,
139                       unsigned int len)
140{
141        return flash->pgm->spi.write_256(flash, buf, start, len);
142}
143
144/*
145 * Get the lowest allowed address for read accesses. This often happens to
146 * be the lowest allowed address for all commands which take an address.
147 * This is a programmer limitation.
148 */
149uint32_t spi_get_valid_read_addr(struct flashctx *flash)
150{
151        switch (flash->pgm->spi.type) {
152#if CONFIG_INTERNAL == 1
153#if defined(__i386__) || defined(__x86_64__)
154        case SPI_CONTROLLER_ICH7:
155                /* Return BBAR for ICH chipsets. */
156                return ichspi_bbar;
157#endif
158#endif
159        default:
160                return 0;
161        }
162}
163
164int register_spi_programmer(const struct spi_programmer *pgm)
165{
166        struct registered_programmer rpgm;
167
168        if (!pgm->write_256 || !pgm->read || !pgm->command ||
169            !pgm->multicommand ||
170            ((pgm->command == default_spi_send_command) &&
171             (pgm->multicommand == default_spi_send_multicommand))) {
172                msg_perr("%s called with incomplete programmer definition. "
173                         "Please report a bug at flashrom@flashrom.org\n",
174                         __func__);
175                return ERROR_FLASHROM_BUG;
176        }
177
178
179        rpgm.buses_supported = BUS_SPI;
180        rpgm.spi = *pgm;
181        return register_programmer(&rpgm);
182}
Note: See TracBrowser for help on using the repository browser.