blob: 60f3da128e83ed5d096e72778685dddc4b27adb2 [file] [log] [blame]
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Carl-Daniel Hailfinger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
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.
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000015 */
16
Carl-Daniel Hailfinger1c6d2ff2012-08-27 00:44:42 +000017#include <strings.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000018#include <string.h>
19#include <stdlib.h>
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000020#include "flash.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000021#include "programmer.h"
Patrick Georgi32508eb2012-07-20 20:35:14 +000022#include "hwaccess.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000023
Uwe Hermann24c35e42011-07-13 11:22:03 +000024struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000025{
26 struct pci_dev *temp;
27 struct pci_filter filter;
28 uint16_t tmp2;
29
30 pci_filter_init(NULL, &filter);
31 filter.vendor = vendor;
32
33 for (temp = pacc->devices; temp; temp = temp->next)
34 if (pci_filter_match(&filter, temp)) {
35 /* Read PCI class */
36 tmp2 = pci_read_word(temp, 0x0a);
Nico Huber380090f2022-05-23 01:45:11 +020037 if (tmp2 == devclass) {
38 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000039 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020040 }
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000041 }
42
43 return NULL;
44}
45
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000046struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
47{
48 struct pci_dev *temp;
49 struct pci_filter filter;
50
51 pci_filter_init(NULL, &filter);
52 filter.vendor = vendor;
53 filter.device = device;
54
Nico Huber380090f2022-05-23 01:45:11 +020055 for (temp = pacc->devices; temp; temp = temp->next) {
56 if (pci_filter_match(&filter, temp)) {
57 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000058 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020059 }
60 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000061
62 return NULL;
63}
64
65struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
66 uint16_t card_vendor, uint16_t card_device)
67{
68 struct pci_dev *temp;
69 struct pci_filter filter;
70
71 pci_filter_init(NULL, &filter);
72 filter.vendor = vendor;
73 filter.device = device;
74
75 for (temp = pacc->devices; temp; temp = temp->next)
76 if (pci_filter_match(&filter, temp)) {
77 if ((card_vendor ==
78 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
79 && (card_device ==
Nico Huber380090f2022-05-23 01:45:11 +020080 pci_read_word(temp, PCI_SUBSYSTEM_ID))) {
81 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000082 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020083 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000084 }
85
86 return NULL;
87}
88
Michael Karcher0bdc0922010-02-28 01:33:48 +000089int force_boardenable = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000090int force_boardmismatch = 0;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000091
Nico Huberc8801732017-12-01 18:19:43 +000092#if IS_X86
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000093void probe_superio(void)
94{
Carl-Daniel Hailfingerf5e62cb2012-05-06 22:48:01 +000095 probe_superio_winbond();
96 /* ITE probe causes SMSC LPC47N217 to power off the serial UART.
97 * Always probe for SMSC first, and if a SMSC Super I/O is detected
98 * at a given I/O port, do _not_ probe that port with the ITE probe.
99 * This means SMSC probing must be done before ITE probing.
100 */
101 //probe_superio_smsc();
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000102 probe_superio_ite();
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000103}
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000104
105int superio_count = 0;
106#define SUPERIO_MAX_COUNT 3
107
108struct superio superios[SUPERIO_MAX_COUNT];
109
110int register_superio(struct superio s)
111{
112 if (superio_count == SUPERIO_MAX_COUNT)
113 return 1;
114 superios[superio_count++] = s;
115 return 0;
116}
117
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000118#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000119
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000120int is_laptop = 0;
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000121int laptop_ok = 0;
Michael Karcher8c1df282010-02-26 09:51:20 +0000122
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000123static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
124 chipaddr addr);
125static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
126 chipaddr addr);
127static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
128 chipaddr addr);
129static uint8_t internal_chip_readb(const struct flashctx *flash,
130 const chipaddr addr);
131static uint16_t internal_chip_readw(const struct flashctx *flash,
132 const chipaddr addr);
133static uint32_t internal_chip_readl(const struct flashctx *flash,
134 const chipaddr addr);
135static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
136 const chipaddr addr, size_t len);
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000137static const struct par_master par_master_internal = {
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000138 .chip_readb = internal_chip_readb,
139 .chip_readw = internal_chip_readw,
140 .chip_readl = internal_chip_readl,
141 .chip_readn = internal_chip_readn,
142 .chip_writeb = internal_chip_writeb,
143 .chip_writew = internal_chip_writew,
144 .chip_writel = internal_chip_writel,
145 .chip_writen = fallback_chip_writen,
146};
147
148enum chipbustype internal_buses_supported = BUS_NONE;
149
Uwe Hermanna0869322009-05-14 20:41:57 +0000150int internal_init(void)
151{
152 int ret = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000153 int force_laptop = 0;
Stefan Taunera28087f2011-09-13 23:14:25 +0000154 int not_a_laptop = 0;
Jacob Garber1c091d12019-08-12 11:14:14 -0600155 char *board_vendor = NULL;
156 char *board_model = NULL;
Nico Huberc8801732017-12-01 18:19:43 +0000157#if IS_X86
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000158 const char *cb_vendor = NULL;
159 const char *cb_model = NULL;
Carl-Daniel Hailfinger11990da2013-07-13 23:21:05 +0000160#endif
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000161 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +0000162
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000163 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000164 if (arg && !strcmp(arg,"force")) {
165 force_boardenable = 1;
166 } else if (arg && !strlen(arg)) {
167 msg_perr("Missing argument for boardenable.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000168 free(arg);
169 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000170 } else if (arg) {
171 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000172 free(arg);
173 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000174 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000175 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000176
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000177 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000178 if (arg && !strcmp(arg,"force")) {
179 force_boardmismatch = 1;
180 } else if (arg && !strlen(arg)) {
181 msg_perr("Missing argument for boardmismatch.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000182 free(arg);
183 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000184 } else if (arg) {
185 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000186 free(arg);
187 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000188 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000189 free(arg);
190
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000191 arg = extract_programmer_param("laptop");
Stefan Taunera28087f2011-09-13 23:14:25 +0000192 if (arg && !strcmp(arg, "force_I_want_a_brick"))
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000193 force_laptop = 1;
Stefan Taunera28087f2011-09-13 23:14:25 +0000194 else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
195 not_a_laptop = 1;
196 else if (arg && !strlen(arg)) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000197 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000198 free(arg);
199 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000200 } else if (arg) {
201 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000202 free(arg);
203 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000204 }
205 free(arg);
206
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000207 arg = extract_programmer_param("mainboard");
208 if (arg && strlen(arg)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000209 if (board_parse_parameter(arg, &board_vendor, &board_model)) {
210 free(arg);
211 return 1;
212 }
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000213 } else if (arg && !strlen(arg)) {
214 msg_perr("Missing argument for mainboard.\n");
215 free(arg);
216 return 1;
217 }
218 free(arg);
219
Jacob Garber1c091d12019-08-12 11:14:14 -0600220 if (rget_io_perms()) {
221 ret = 1;
222 goto internal_init_exit;
223 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000224
Michael Karcherb9dbe482011-05-11 17:07:07 +0000225 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000226 * is found, the host controller init routine sets the
227 * internal_buses_supported bitfield.
Michael Karcherb9dbe482011-05-11 17:07:07 +0000228 */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000229 internal_buses_supported = BUS_NONSPI;
Michael Karcherb9dbe482011-05-11 17:07:07 +0000230
Jacob Garber1c091d12019-08-12 11:14:14 -0600231 if (try_mtd() == 0) {
232 ret = 0;
233 goto internal_init_exit;
234 }
David Hendricksf9a30552015-05-23 20:30:30 -0700235
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000236 /* Initialize PCI access for flash enables */
Jacob Garber1c091d12019-08-12 11:14:14 -0600237 if (pci_init_common() != 0) {
238 ret = 1;
239 goto internal_init_exit;
240 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000241
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000242 if (processor_flash_enable()) {
243 msg_perr("Processor detection/init failed.\n"
244 "Aborting.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600245 ret = 1;
246 goto internal_init_exit;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000247 }
248
Nico Huberc8801732017-12-01 18:19:43 +0000249#if IS_X86
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000250 if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
251 if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000252 msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000253 " match the current coreboot IDs of the mainboard (%s:%s).\n",
254 board_vendor, board_model, cb_vendor, cb_model);
Jacob Garber1c091d12019-08-12 11:14:14 -0600255 if (!force_boardmismatch) {
256 ret = 1;
257 goto internal_init_exit;
258 }
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000259 msg_pinfo("Continuing anyway.\n");
260 }
261 }
Carl-Daniel Hailfinger11990da2013-07-13 23:21:05 +0000262#endif
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000263
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000264#if IS_X86
Nico Huber2e50cdc2018-09-23 20:20:26 +0200265 is_laptop = 2; /* Assume that we don't know by default. */
266
Michael Karcher6701ee82010-01-20 14:14:11 +0000267 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000268
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000269 /* In case Super I/O probing would cause pretty explosions. */
270 board_handle_before_superio();
271
Uwe Hermann43959702010-03-13 17:28:29 +0000272 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000273 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000274#else
275 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
276 * by coreboot.
277 * FIXME: Find a replacement for DMI on non-x86.
278 * FIXME: Enable Super I/O probing once port I/O is possible.
279 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000280#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000281
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000282 /* Check laptop whitelist. */
283 board_handle_before_laptop();
284
Nico Huber2e50cdc2018-09-23 20:20:26 +0200285 /*
286 * Disable all internal buses by default if we are not sure
287 * this isn't a laptop. Board-enables may override this,
288 * non-legacy buses (SPI and opaque atm) are probed anyway.
289 */
290 if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2)))
291 internal_buses_supported = BUS_NONE;
Michael Karcher8c1df282010-02-26 09:51:20 +0000292
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000293 /* try to enable it. Failure IS an option, since not all motherboards
294 * really need this to be done, etc., etc.
295 */
296 ret = chipset_flash_enable();
297 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000298 msg_perr("WARNING: No chipset found. Flash detection "
299 "will most likely fail.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600300 } else if (ret == ERROR_FATAL) {
301 goto internal_init_exit;
302 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000303
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000304#if IS_X86
Vadim Girlin4dd0f902013-08-24 12:18:17 +0000305 /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
306 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
Carl-Daniel Hailfinger76d4b372010-07-10 16:56:32 +0000307 init_superio_ite();
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000308
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000309 if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000310 msg_perr("Aborting to be safe.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600311 ret = 1;
312 goto internal_init_exit;
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000313 }
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000314#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000315
Nico Huber2e50cdc2018-09-23 20:20:26 +0200316 if (internal_buses_supported & BUS_NONSPI)
317 register_par_master(&par_master_internal, internal_buses_supported);
318
319 /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
320 if (is_laptop && !laptop_ok) {
321 msg_pinfo("========================================================================\n");
322 if (is_laptop == 1) {
323 msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n"
324 "internal buses have been disabled for safety reasons.\n\n");
325 } else {
326 msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n"
327 "detect this for sure because your vendor has not set up the SMBIOS\n"
328 "tables correctly. Some internal buses have been disabled for\n"
329 "safety reasons. You can enforce using all buses by adding\n"
330 " -p internal:laptop=this_is_not_a_laptop\n"
331 "to the command line, but please read the following warning if you\n"
332 "are not sure.\n\n");
333 }
334 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
335 "recommend to use the vendor flashing utility. The embedded controller\n"
336 "(EC) in these machines often interacts badly with flashing.\n"
337 "See the manpage and https://flashrom.org/Laptops for details.\n\n"
338 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
339 "and write may brick your laptop.\n"
340 "Read and probe may irritate your EC and cause fan failure, backlight\n"
341 "failure and sudden poweroff.\n"
342 "You have been warned.\n"
343 "========================================================================\n");
344 }
345
Jacob Garber1c091d12019-08-12 11:14:14 -0600346 ret = 0;
347
348internal_init_exit:
349 free(board_vendor);
350 free(board_model);
351
352 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000353}
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000354
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000355static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
356 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000357{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000358 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000359}
360
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000361static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
362 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000363{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000364 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000365}
366
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000367static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
368 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000369{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000370 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000371}
372
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000373static uint8_t internal_chip_readb(const struct flashctx *flash,
374 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000375{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000376 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000377}
378
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000379static uint16_t internal_chip_readw(const struct flashctx *flash,
380 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000381{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000382 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000383}
384
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000385static uint32_t internal_chip_readl(const struct flashctx *flash,
386 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000387{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000388 return mmio_readl((void *) addr);
389}
390
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000391static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
392 const chipaddr addr, size_t len)
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000393{
Carl-Daniel Hailfingerccd71c22012-03-01 22:38:27 +0000394 mmio_readn((void *)addr, buf, len);
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000395 return;
396}