blob: 8445455f7f6bbb3f4151b7334c668a16de193cc5 [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 Heijligend96c97c2021-11-02 21:03:00 +010024#include "platform/pci.h"
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000025
Uwe Hermann24c35e42011-07-13 11:22:03 +000026struct pci_dev *pci_dev_find_vendorclass(uint16_t vendor, uint16_t devclass)
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000027{
28 struct pci_dev *temp;
29 struct pci_filter filter;
30 uint16_t tmp2;
31
32 pci_filter_init(NULL, &filter);
33 filter.vendor = vendor;
34
35 for (temp = pacc->devices; temp; temp = temp->next)
36 if (pci_filter_match(&filter, temp)) {
37 /* Read PCI class */
38 tmp2 = pci_read_word(temp, 0x0a);
Nico Huber380090f2022-05-23 01:45:11 +020039 if (tmp2 == devclass) {
40 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000041 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020042 }
Carl-Daniel Hailfinger9f46cfc2009-11-15 17:13:29 +000043 }
44
45 return NULL;
46}
47
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000048struct pci_dev *pci_dev_find(uint16_t vendor, uint16_t device)
49{
50 struct pci_dev *temp;
51 struct pci_filter filter;
52
53 pci_filter_init(NULL, &filter);
54 filter.vendor = vendor;
55 filter.device = device;
56
Nico Huber380090f2022-05-23 01:45:11 +020057 for (temp = pacc->devices; temp; temp = temp->next) {
58 if (pci_filter_match(&filter, temp)) {
59 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000060 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020061 }
62 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000063
64 return NULL;
65}
66
67struct pci_dev *pci_card_find(uint16_t vendor, uint16_t device,
68 uint16_t card_vendor, uint16_t card_device)
69{
70 struct pci_dev *temp;
71 struct pci_filter filter;
72
73 pci_filter_init(NULL, &filter);
74 filter.vendor = vendor;
75 filter.device = device;
76
77 for (temp = pacc->devices; temp; temp = temp->next)
78 if (pci_filter_match(&filter, temp)) {
79 if ((card_vendor ==
80 pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID))
81 && (card_device ==
Nico Huber380090f2022-05-23 01:45:11 +020082 pci_read_word(temp, PCI_SUBSYSTEM_ID))) {
83 pci_fill_info(temp, PCI_FILL_IDENT);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000084 return temp;
Nico Huber380090f2022-05-23 01:45:11 +020085 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +000086 }
87
88 return NULL;
89}
90
Michael Karcher0bdc0922010-02-28 01:33:48 +000091int force_boardenable = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +000092int force_boardmismatch = 0;
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000093
Thomas Heijligen4b918a12021-09-26 13:42:39 +020094#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +000095void probe_superio(void)
96{
Carl-Daniel Hailfingerf5e62cb2012-05-06 22:48:01 +000097 probe_superio_winbond();
98 /* ITE probe causes SMSC LPC47N217 to power off the serial UART.
99 * Always probe for SMSC first, and if a SMSC Super I/O is detected
100 * at a given I/O port, do _not_ probe that port with the ITE probe.
101 * This means SMSC probing must be done before ITE probing.
102 */
103 //probe_superio_smsc();
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000104 probe_superio_ite();
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000105}
Carl-Daniel Hailfingerbfecef62011-04-27 14:34:08 +0000106
107int superio_count = 0;
108#define SUPERIO_MAX_COUNT 3
109
110struct superio superios[SUPERIO_MAX_COUNT];
111
112int register_superio(struct superio s)
113{
114 if (superio_count == SUPERIO_MAX_COUNT)
115 return 1;
116 superios[superio_count++] = s;
117 return 0;
118}
119
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000120#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000121
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000122int is_laptop = 0;
Felix Singerd1ab7d22022-08-19 03:03:47 +0200123bool laptop_ok = false;
Michael Karcher8c1df282010-02-26 09:51:20 +0000124
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000125static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
126 chipaddr addr);
127static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
128 chipaddr addr);
129static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
130 chipaddr addr);
131static uint8_t internal_chip_readb(const struct flashctx *flash,
132 const chipaddr addr);
133static uint16_t internal_chip_readw(const struct flashctx *flash,
134 const chipaddr addr);
135static uint32_t internal_chip_readl(const struct flashctx *flash,
136 const chipaddr addr);
137static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
138 const chipaddr addr, size_t len);
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000139static const struct par_master par_master_internal = {
Thomas Heijligen43040f22022-06-23 14:38:35 +0200140 .chip_readb = internal_chip_readb,
141 .chip_readw = internal_chip_readw,
142 .chip_readl = internal_chip_readl,
143 .chip_readn = internal_chip_readn,
144 .chip_writeb = internal_chip_writeb,
145 .chip_writew = internal_chip_writew,
146 .chip_writel = internal_chip_writel,
147 .chip_writen = fallback_chip_writen,
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000148};
149
150enum chipbustype internal_buses_supported = BUS_NONE;
151
Thomas Heijligencc853d82021-05-04 15:32:17 +0200152static int internal_init(void)
Uwe Hermanna0869322009-05-14 20:41:57 +0000153{
154 int ret = 0;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000155 int force_laptop = 0;
Stefan Taunera28087f2011-09-13 23:14:25 +0000156 int not_a_laptop = 0;
Jacob Garber1c091d12019-08-12 11:14:14 -0600157 char *board_vendor = NULL;
158 char *board_model = NULL;
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200159#if defined(__i386__) || defined(__x86_64__)
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000160 const char *cb_vendor = NULL;
161 const char *cb_model = NULL;
Carl-Daniel Hailfinger11990da2013-07-13 23:21:05 +0000162#endif
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000163 char *arg;
Uwe Hermanna0869322009-05-14 20:41:57 +0000164
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000165 arg = extract_programmer_param("boardenable");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000166 if (arg && !strcmp(arg,"force")) {
167 force_boardenable = 1;
168 } else if (arg && !strlen(arg)) {
169 msg_perr("Missing argument for boardenable.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000170 free(arg);
171 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000172 } else if (arg) {
173 msg_perr("Unknown argument for boardenable: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000174 free(arg);
175 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000176 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000177 free(arg);
Michael Karcher0bdc0922010-02-28 01:33:48 +0000178
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000179 arg = extract_programmer_param("boardmismatch");
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000180 if (arg && !strcmp(arg,"force")) {
181 force_boardmismatch = 1;
182 } else if (arg && !strlen(arg)) {
183 msg_perr("Missing argument for boardmismatch.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000184 free(arg);
185 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000186 } else if (arg) {
187 msg_perr("Unknown argument for boardmismatch: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000188 free(arg);
189 return 1;
Michael Karcher0bdc0922010-02-28 01:33:48 +0000190 }
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000191 free(arg);
192
Carl-Daniel Hailfinger2b6dcb32010-07-08 10:13:37 +0000193 arg = extract_programmer_param("laptop");
Stefan Taunera28087f2011-09-13 23:14:25 +0000194 if (arg && !strcmp(arg, "force_I_want_a_brick"))
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000195 force_laptop = 1;
Stefan Taunera28087f2011-09-13 23:14:25 +0000196 else if (arg && !strcmp(arg, "this_is_not_a_laptop"))
197 not_a_laptop = 1;
198 else if (arg && !strlen(arg)) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000199 msg_perr("Missing argument for laptop.\n");
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000200 free(arg);
201 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000202 } else if (arg) {
203 msg_perr("Unknown argument for laptop: %s\n", arg);
Carl-Daniel Hailfinger744132a2010-07-06 09:55:48 +0000204 free(arg);
205 return 1;
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000206 }
207 free(arg);
208
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000209 arg = extract_programmer_param("mainboard");
210 if (arg && strlen(arg)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000211 if (board_parse_parameter(arg, &board_vendor, &board_model)) {
212 free(arg);
213 return 1;
214 }
Carl-Daniel Hailfinger2d927fb2012-01-04 00:48:27 +0000215 } else if (arg && !strlen(arg)) {
216 msg_perr("Missing argument for mainboard.\n");
217 free(arg);
218 return 1;
219 }
220 free(arg);
221
Jacob Garber1c091d12019-08-12 11:14:14 -0600222 if (rget_io_perms()) {
223 ret = 1;
224 goto internal_init_exit;
225 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000226
Edward O'Callaghanbd275812022-11-28 11:20:44 +1100227 /* Unconditionally reset global state from previous operation. */
228 laptop_ok = false;
229
Michael Karcherb9dbe482011-05-11 17:07:07 +0000230 /* Default to Parallel/LPC/FWH flash devices. If a known host controller
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000231 * is found, the host controller init routine sets the
232 * internal_buses_supported bitfield.
Michael Karcherb9dbe482011-05-11 17:07:07 +0000233 */
Carl-Daniel Hailfingereaacd2d2011-11-09 23:40:00 +0000234 internal_buses_supported = BUS_NONSPI;
Michael Karcherb9dbe482011-05-11 17:07:07 +0000235
Jacob Garber1c091d12019-08-12 11:14:14 -0600236 if (try_mtd() == 0) {
237 ret = 0;
238 goto internal_init_exit;
239 }
David Hendricksf9a30552015-05-23 20:30:30 -0700240
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000241 /* Initialize PCI access for flash enables */
Jacob Garber1c091d12019-08-12 11:14:14 -0600242 if (pci_init_common() != 0) {
243 ret = 1;
244 goto internal_init_exit;
245 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000246
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000247 if (processor_flash_enable()) {
248 msg_perr("Processor detection/init failed.\n"
249 "Aborting.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600250 ret = 1;
251 goto internal_init_exit;
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000252 }
253
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200254#if defined(__i386__) || defined(__x86_64__)
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000255 if ((cb_parse_table(&cb_vendor, &cb_model) == 0) && (board_vendor != NULL) && (board_model != NULL)) {
256 if (strcasecmp(board_vendor, cb_vendor) || strcasecmp(board_model, cb_model)) {
Stefan Taunerc6fa32d2013-01-04 22:54:07 +0000257 msg_pwarn("Warning: The mainboard IDs set by -p internal:mainboard (%s:%s) do not\n"
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000258 " match the current coreboot IDs of the mainboard (%s:%s).\n",
259 board_vendor, board_model, cb_vendor, cb_model);
Jacob Garber1c091d12019-08-12 11:14:14 -0600260 if (!force_boardmismatch) {
261 ret = 1;
262 goto internal_init_exit;
263 }
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000264 msg_pinfo("Continuing anyway.\n");
265 }
266 }
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000267
Nico Huber2e50cdc2018-09-23 20:20:26 +0200268 is_laptop = 2; /* Assume that we don't know by default. */
269
Michael Karcher6701ee82010-01-20 14:14:11 +0000270 dmi_init();
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000271
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000272 /* In case Super I/O probing would cause pretty explosions. */
273 board_handle_before_superio();
274
Uwe Hermann43959702010-03-13 17:28:29 +0000275 /* Probe for the Super I/O chip and fill global struct superio. */
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000276 probe_superio();
Carl-Daniel Hailfingerb5b161b2010-06-04 19:05:39 +0000277#else
278 /* FIXME: Enable cbtable searching on all non-x86 platforms supported
279 * by coreboot.
280 * FIXME: Find a replacement for DMI on non-x86.
281 * FIXME: Enable Super I/O probing once port I/O is possible.
282 */
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000283#endif
Carl-Daniel Hailfinger14e100c2009-12-22 23:42:04 +0000284
Carl-Daniel Hailfinger580d29a2011-05-05 07:12:40 +0000285 /* Check laptop whitelist. */
286 board_handle_before_laptop();
287
Nico Huber2e50cdc2018-09-23 20:20:26 +0200288 /*
289 * Disable all internal buses by default if we are not sure
290 * this isn't a laptop. Board-enables may override this,
291 * non-legacy buses (SPI and opaque atm) are probed anyway.
292 */
293 if (is_laptop && !(laptop_ok || force_laptop || (not_a_laptop && is_laptop == 2)))
294 internal_buses_supported = BUS_NONE;
Michael Karcher8c1df282010-02-26 09:51:20 +0000295
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000296 /* try to enable it. Failure IS an option, since not all motherboards
297 * really need this to be done, etc., etc.
298 */
299 ret = chipset_flash_enable();
300 if (ret == -2) {
Carl-Daniel Hailfinger27023762010-04-28 15:22:14 +0000301 msg_perr("WARNING: No chipset found. Flash detection "
302 "will most likely fail.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600303 } else if (ret == ERROR_FATAL) {
304 goto internal_init_exit;
305 }
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000306
Thomas Heijligen4b918a12021-09-26 13:42:39 +0200307#if defined(__i386__) || defined(__x86_64__)
Vadim Girlin4dd0f902013-08-24 12:18:17 +0000308 /* Probe unconditionally for ITE Super I/O chips. This enables LPC->SPI translation on IT87* and
309 * parallel writes on IT8705F. Also, this handles the manual chip select for Gigabyte's DualBIOS. */
Carl-Daniel Hailfinger76d4b372010-07-10 16:56:32 +0000310 init_superio_ite();
Carl-Daniel Hailfinger01f3ef42010-03-25 02:50:40 +0000311
Stefan Taunerfa9fa712012-09-24 21:29:29 +0000312 if (board_flash_enable(board_vendor, board_model, cb_vendor, cb_model)) {
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000313 msg_perr("Aborting to be safe.\n");
Jacob Garber1c091d12019-08-12 11:14:14 -0600314 ret = 1;
315 goto internal_init_exit;
Stefan Taunerb4e06bd2012-08-20 00:24:22 +0000316 }
Stefan Taunerb0eee9b2015-01-10 09:32:50 +0000317#endif
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000318
Nico Huber2e50cdc2018-09-23 20:20:26 +0200319 if (internal_buses_supported & BUS_NONSPI)
Anastasia Klimchukb91a2032021-05-21 09:40:58 +1000320 register_par_master(&par_master_internal, internal_buses_supported, NULL);
Nico Huber2e50cdc2018-09-23 20:20:26 +0200321
322 /* Report if a non-whitelisted laptop is detected that likely uses a legacy bus. */
323 if (is_laptop && !laptop_ok) {
324 msg_pinfo("========================================================================\n");
325 if (is_laptop == 1) {
326 msg_pinfo("You seem to be running flashrom on an unknown laptop. Some\n"
327 "internal buses have been disabled for safety reasons.\n\n");
328 } else {
329 msg_pinfo("You may be running flashrom on an unknown laptop. We could not\n"
330 "detect this for sure because your vendor has not set up the SMBIOS\n"
331 "tables correctly. Some internal buses have been disabled for\n"
332 "safety reasons. You can enforce using all buses by adding\n"
333 " -p internal:laptop=this_is_not_a_laptop\n"
334 "to the command line, but please read the following warning if you\n"
335 "are not sure.\n\n");
336 }
337 msg_perr("Laptops, notebooks and netbooks are difficult to support and we\n"
338 "recommend to use the vendor flashing utility. The embedded controller\n"
339 "(EC) in these machines often interacts badly with flashing.\n"
340 "See the manpage and https://flashrom.org/Laptops for details.\n\n"
341 "If flash is shared with the EC, erase is guaranteed to brick your laptop\n"
342 "and write may brick your laptop.\n"
343 "Read and probe may irritate your EC and cause fan failure, backlight\n"
344 "failure and sudden poweroff.\n"
345 "You have been warned.\n"
346 "========================================================================\n");
347 }
348
Jacob Garber1c091d12019-08-12 11:14:14 -0600349 ret = 0;
350
351internal_init_exit:
352 free(board_vendor);
353 free(board_model);
354
355 return ret;
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000356}
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000357
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000358static void internal_chip_writeb(const struct flashctx *flash, uint8_t val,
359 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000360{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000361 mmio_writeb(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000362}
363
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000364static void internal_chip_writew(const struct flashctx *flash, uint16_t val,
365 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000366{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000367 mmio_writew(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000368}
369
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000370static void internal_chip_writel(const struct flashctx *flash, uint32_t val,
371 chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000372{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000373 mmio_writel(val, (void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000374}
375
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000376static uint8_t internal_chip_readb(const struct flashctx *flash,
377 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000378{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000379 return mmio_readb((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000380}
381
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000382static uint16_t internal_chip_readw(const struct flashctx *flash,
383 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000384{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000385 return mmio_readw((void *) addr);
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000386}
387
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000388static uint32_t internal_chip_readl(const struct flashctx *flash,
389 const chipaddr addr)
Carl-Daniel Hailfinger702218d2009-05-08 17:43:22 +0000390{
Carl-Daniel Hailfinger78185dc2009-05-17 15:49:24 +0000391 return mmio_readl((void *) addr);
392}
393
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000394static void internal_chip_readn(const struct flashctx *flash, uint8_t *buf,
395 const chipaddr addr, size_t len)
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000396{
Carl-Daniel Hailfingerccd71c22012-03-01 22:38:27 +0000397 mmio_readn((void *)addr, buf, len);
Carl-Daniel Hailfinger0bd2a2b2009-06-05 18:32:07 +0000398 return;
399}
Thomas Heijligencc853d82021-05-04 15:32:17 +0200400
401const struct programmer_entry programmer_internal = {
402 .name = "internal",
403 .type = OTHER,
404 .devs.note = NULL,
405 .init = internal_init,
406 .map_flash_region = physmap,
407 .unmap_flash_region = physunmap,
408 .delay = internal_delay,
409};