blob: 44dcb25d2e5f374beb6408eb4d461c0965c1d797 [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"
Thomas Heijligena0655202021-12-14 16:36:05 +010023#include "hwaccess_x86_io.h"
Thomas Heijligen74b4aa02021-12-14 17:52:30 +010024#include "hwaccess_physmap.h"
Thomas Heijligend96c97c2021-11-02 21:03:00 +010025#include "platform/pci.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000026
Uwe Hermann24c35e42011-07-13 11:22:03 +000027struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000028{
29 struct pci_dev *temp;
30 struct pci_filter filter;
31 uint16_t tmp2;
32
33 pci_filter_init(NULL, &filter);
34 filter.vendor = vendor;
35
36 for (temp = pacc->devices; temp; temp = temp->next)
37 if (pci_filter_match(&filter, temp)) {
38 /* Read PCI class */
39 tmp2 = pci_read_word(temp, 0x0a);
Nico Huber380090f2022-05-23 01:45:11 +020040 if (tmp2 == devclass) {
41 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000042 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020043 }
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000044 }
45
46 return NULL;
47}
48
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000049struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
50{
51 struct pci_dev *temp;
52 struct pci_filter filter;
53
54 pci_filter_init(NULL, &filter);
55 filter.vendor = vendor;
56 filter.device = device;
57
Nico Huber380090f2022-05-23 01:45:11 +020058 for (temp = pacc->devices; temp; temp = temp->next) {
59 if (pci_filter_match(&filter, temp)) {
60 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000061 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020062 }
63 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000064
65 return NULL;
66}
67
68struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
69 uint16_t card_vendor, uint16_t card_device)
70{
71 struct pci_dev *temp;
72 struct pci_filter filter;
73
74 pci_filter_init(NULL, &filter);
75 filter.vendor = vendor;
76 filter.device = device;
77
78 for (temp = pacc->devices; temp; temp = temp->next)
79 if (pci_filter_match(&filter, temp)) {
80 if ((card_vendor ==
81 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
82 && (card_device ==
Nico Huber380090f2022-05-23 01:45:11 +020083 pci_read_word(temp, PCI_SUBSYSTEM_ID))) {
84 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000085 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020086 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000087 }
88
89 return NULL;
90}
91
Michael Karcher0bdc0922010-02-28 01:33:48 +000092int force_boardenable = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000093int force_boardmismatch = 0;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000094
Thomas Heijligen4b918a12021-09-26 13:42:39 +020095#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000096void probe_superio(void)
97{
Carl-Daniel Hailfingerf5e62cb2012-05-06 22:48:01 +000098 probe_superio_winbond();
99 /* ITE probe causes SMSC LPC47N217 to power off the serial UART.
100 * Always probe for SMSC first, and if a SMSC Super I/O is detected
101 * at a given I/O port, do _not_ probe that port with the ITE probe.
102 * This means SMSC probing must be done before ITE probing.
103 */
104 //probe_superio_smsc();
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000105 probe_superio_ite();
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000106}
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000107
108int superio_count = 0;
109#define SUPERIO_MAX_COUNT 3
110
111struct superio superios[SUPERIO_MAX_COUNT];
112
113int register_superio(struct superio s)
114{
115 if (superio_count == SUPERIO_MAX_COUNT)
116 return 1;
117 superios[superio_count++] = s;
118 return 0;
119}
120
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000121#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000122
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000123int is_laptop = 0;
Felix Singerd1ab7d22022-08-19 03:03:47 +0200124bool laptop_ok = false;
Michael Karcher8c1df282010-02-26 09:51:20 +0000125
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000126static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
127 chipaddr addr);
128static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
129 chipaddr addr);
130static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
131 chipaddr addr);
132static uint8_t internal_chip_readb(const struct flashctx *flash,
133 const chipaddr addr);
134static uint16_t internal_chip_readw(const struct flashctx *flash,
135 const chipaddr addr);
136static uint32_t internal_chip_readl(const struct flashctx *flash,
137 const chipaddr addr);
138static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
139 const chipaddr addr, size_t len);
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000140static const struct par_master par_master_internal = {
Thomas Heijligen43040f22022-06-23 14:38:35 +0200141 .chip_readb = internal_chip_readb,
142 .chip_readw = internal_chip_readw,
143 .chip_readl = internal_chip_readl,
144 .chip_readn = internal_chip_readn,
145 .chip_writeb = internal_chip_writeb,
146 .chip_writew = internal_chip_writew,
147 .chip_writel = internal_chip_writel,
148 .chip_writen = fallback_chip_writen,
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000149};
150
151enum chipbustype internal_buses_supported = BUS_NONE;
152
Thomas Heijligencc853d82021-05-04 15:32:17 +0200153static int internal_init(void)
Uwe Hermanna0869322009-05-14 20:41:57 +0000154{
155 int ret = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000156 int force_laptop = 0;
Stefan Taunera28087f2011-09-13 23:14:25 +0000157 int not_a_laptop = 0;
Jacob Garber1c091d12019-08-12 11:14:14 -0600158 char *board_vendor = NULL;
159 char *board_model = NULL;
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200160#if defined(__i386__) || defined(__x86_64__)
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000161 const char *cb_vendor = NULL;
162 const char *cb_model = NULL;
Carl-Daniel Hailfinger11990da2013-07-13 23:21:05 +0000163#endif
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000164 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +0000165
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000166 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000167 if (arg && !strcmp(arg,"force")) {
168 force_boardenable = 1;
169 } else if (arg && !strlen(arg)) {
170 msg_perr("Missing argument for boardenable.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000171 free(arg);
172 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000173 } else if (arg) {
174 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000175 free(arg);
176 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000177 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000178 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000179
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000180 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000181 if (arg && !strcmp(arg,"force")) {
182 force_boardmismatch = 1;
183 } else if (arg && !strlen(arg)) {
184 msg_perr("Missing argument for boardmismatch.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000185 free(arg);
186 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000187 } else if (arg) {
188 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000189 free(arg);
190 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000191 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000192 free(arg);
193
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000194 arg = extract_programmer_param("laptop");
Stefan Taunera28087f2011-09-13 23:14:25 +0000195 if (arg && !strcmp(arg, "force_I_want_a_brick"))
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000196 force_laptop = 1;
Stefan Taunera28087f2011-09-13 23:14:25 +0000197 else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
198 not_a_laptop = 1;
199 else if (arg && !strlen(arg)) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000200 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000201 free(arg);
202 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000203 } else if (arg) {
204 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000205 free(arg);
206 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000207 }
208 free(arg);
209
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000210 arg = extract_programmer_param("mainboard");
211 if (arg && strlen(arg)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000212 if (board_parse_parameter(arg, &board_vendor, &board_model)) {
213 free(arg);
214 return 1;
215 }
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000216 } else if (arg && !strlen(arg)) {
217 msg_perr("Missing argument for mainboard.\n");
218 free(arg);
219 return 1;
220 }
221 free(arg);
222
Jacob Garber1c091d12019-08-12 11:14:14 -0600223 if (rget_io_perms()) {
224 ret = 1;
225 goto internal_init_exit;
226 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000227
Edward O'Callaghanbd275812022-11-28 11:20:44 +1100228 /* Unconditionally reset global state from previous operation. */
229 laptop_ok = false;
230
Michael Karcherb9dbe482011-05-11 17:07:07 +0000231 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000232 * is found, the host controller init routine sets the
233 * internal_buses_supported bitfield.
Michael Karcherb9dbe482011-05-11 17:07:07 +0000234 */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000235 internal_buses_supported = BUS_NONSPI;
Michael Karcherb9dbe482011-05-11 17:07:07 +0000236
Jacob Garber1c091d12019-08-12 11:14:14 -0600237 if (try_mtd() == 0) {
238 ret = 0;
239 goto internal_init_exit;
240 }
David Hendricksf9a30552015-05-23 20:30:30 -0700241
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000242 /* Initialize PCI access for flash enables */
Jacob Garber1c091d12019-08-12 11:14:14 -0600243 if (pci_init_common() != 0) {
244 ret = 1;
245 goto internal_init_exit;
246 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000247
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000248 if (processor_flash_enable()) {
249 msg_perr("Processor detection/init failed.\n"
250 "Aborting.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600251 ret = 1;
252 goto internal_init_exit;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000253 }
254
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200255#if defined(__i386__) || defined(__x86_64__)
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000256 if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
257 if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000258 msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000259 " match the current coreboot IDs of the mainboard (%s:%s).\n",
260 board_vendor, board_model, cb_vendor, cb_model);
Jacob Garber1c091d12019-08-12 11:14:14 -0600261 if (!force_boardmismatch) {
262 ret = 1;
263 goto internal_init_exit;
264 }
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000265 msg_pinfo("Continuing anyway.\n");
266 }
267 }
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000268
Nico Huber2e50cdc2018-09-23 20:20:26 +0200269 is_laptop = 2; /* Assume that we don't know by default. */
270
Michael Karcher6701ee82010-01-20 14:14:11 +0000271 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000272
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000273 /* In case Super I/O probing would cause pretty explosions. */
274 board_handle_before_superio();
275
Uwe Hermann43959702010-03-13 17:28:29 +0000276 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000277 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000278#else
279 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
280 * by coreboot.
281 * FIXME: Find a replacement for DMI on non-x86.
282 * FIXME: Enable Super I/O probing once port I/O is possible.
283 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000284#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000285
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000286 /* Check laptop whitelist. */
287 board_handle_before_laptop();
288
Nico Huber2e50cdc2018-09-23 20:20:26 +0200289 /*
290 * Disable all internal buses by default if we are not sure
291 * this isn't a laptop. Board-enables may override this,
292 * non-legacy buses (SPI and opaque atm) are probed anyway.
293 */
294 if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2)))
295 internal_buses_supported = BUS_NONE;
Michael Karcher8c1df282010-02-26 09:51:20 +0000296
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000297 /* try to enable it. Failure IS an option, since not all motherboards
298 * really need this to be done, etc., etc.
299 */
300 ret = chipset_flash_enable();
301 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000302 msg_perr("WARNING: No chipset found. Flash detection "
303 "will most likely fail.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600304 } else if (ret == ERROR_FATAL) {
305 goto internal_init_exit;
306 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000307
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200308#if defined(__i386__) || defined(__x86_64__)
Vadim Girlin4dd0f902013-08-24 12:18:17 +0000309 /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
310 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
Carl-Daniel Hailfinger76d4b372010-07-10 16:56:32 +0000311 init_superio_ite();
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000312
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000313 if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000314 msg_perr("Aborting to be safe.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600315 ret = 1;
316 goto internal_init_exit;
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000317 }
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000318#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000319
Nico Huber2e50cdc2018-09-23 20:20:26 +0200320 if (internal_buses_supported & BUS_NONSPI)
Anastasia Klimchukb91a2032021-05-21 09:40:58 +1000321 register_par_master(&par_master_internal, internal_buses_supported, NULL);
Nico Huber2e50cdc2018-09-23 20:20:26 +0200322
323 /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
324 if (is_laptop && !laptop_ok) {
325 msg_pinfo("========================================================================\n");
326 if (is_laptop == 1) {
327 msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n"
328 "internal buses have been disabled for safety reasons.\n\n");
329 } else {
330 msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n"
331 "detect this for sure because your vendor has not set up the SMBIOS\n"
332 "tables correctly. Some internal buses have been disabled for\n"
333 "safety reasons. You can enforce using all buses by adding\n"
334 " -p internal:laptop=this_is_not_a_laptop\n"
335 "to the command line, but please read the following warning if you\n"
336 "are not sure.\n\n");
337 }
338 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
339 "recommend to use the vendor flashing utility. The embedded controller\n"
340 "(EC) in these machines often interacts badly with flashing.\n"
341 "See the manpage and https://flashrom.org/Laptops for details.\n\n"
342 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
343 "and write may brick your laptop.\n"
344 "Read and probe may irritate your EC and cause fan failure, backlight\n"
345 "failure and sudden poweroff.\n"
346 "You have been warned.\n"
347 "========================================================================\n");
348 }
349
Jacob Garber1c091d12019-08-12 11:14:14 -0600350 ret = 0;
351
352internal_init_exit:
353 free(board_vendor);
354 free(board_model);
355
356 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000357}
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000358
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000359static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
360 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000361{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000362 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000363}
364
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000365static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
366 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000367{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000368 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000369}
370
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000371static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
372 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000373{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000374 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000375}
376
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000377static uint8_t internal_chip_readb(const struct flashctx *flash,
378 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000379{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000380 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000381}
382
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000383static uint16_t internal_chip_readw(const struct flashctx *flash,
384 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000385{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000386 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000387}
388
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000389static uint32_t internal_chip_readl(const struct flashctx *flash,
390 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000391{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000392 return mmio_readl((void *) addr);
393}
394
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000395static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
396 const chipaddr addr, size_t len)
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000397{
Carl-Daniel Hailfingerccd71c22012-03-01 22:38:27 +0000398 mmio_readn((void *)addr, buf, len);
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000399 return;
400}
Thomas Heijligencc853d82021-05-04 15:32:17 +0200401
402const struct programmer_entry programmer_internal = {
403 .name = "internal",
404 .type = OTHER,
405 .devs.note = NULL,
406 .init = internal_init,
407 .map_flash_region = physmap,
408 .unmap_flash_region = physunmap,
409 .delay = internal_delay,
410};