blob: 699ce1ae57b8e5b8d0f238ada83190216f5da19f [file] [log] [blame]
Edward O'Callaghan63f6a372022-08-12 12:56:43 +10001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2000 Silicon Integrated System Corporation
5 * Copyright (C) 2004 Tyan Corp <yhlu@tyan.com>
6 * Copyright (C) 2005-2008 coresystems GmbH
7 * Copyright (C) 2008,2009 Carl-Daniel Hailfinger
8 * Copyright (C) 2016 secunet Security Networks AG
9 * (Written by Nico Huber <nico.huber@secunet.com> for secunet)
10 * Copyright (C) 2009,2010,2011 Carl-Daniel Hailfinger
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; version 2 of the License.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 */
21
Nico Huber2ae63012026-03-04 21:06:45 +010022#include <stdlib.h>
23#include <string.h>
24
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100025#include "flash.h"
26#include "programmer.h"
Nico Huber2ae63012026-03-04 21:06:45 +010027#include "chipdrivers/probing.h"
28#include "chipdrivers/memory_bus.h"
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100029
30void chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
31{
Nico Huberdd6e07a2026-02-21 17:55:26 +010032 flash->mst.par->chip_writeb(flash->mst.par, val, addr);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100033}
34
35void chip_writew(const struct flashctx *flash, uint16_t val, chipaddr addr)
36{
Nico Huberdd6e07a2026-02-21 17:55:26 +010037 flash->mst.par->chip_writew(flash->mst.par, val, addr);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100038}
39
40void chip_writel(const struct flashctx *flash, uint32_t val, chipaddr addr)
41{
Nico Huberdd6e07a2026-02-21 17:55:26 +010042 flash->mst.par->chip_writel(flash->mst.par, val, addr);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100043}
44
45void chip_writen(const struct flashctx *flash, const uint8_t *buf, chipaddr addr, size_t len)
46{
Nico Huberdd6e07a2026-02-21 17:55:26 +010047 flash->mst.par->chip_writen(flash->mst.par, buf, addr, len);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100048}
49
50uint8_t chip_readb(const struct flashctx *flash, const chipaddr addr)
51{
Nico Huberdd6e07a2026-02-21 17:55:26 +010052 return flash->mst.par->chip_readb(flash->mst.par, addr);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100053}
54
55uint16_t chip_readw(const struct flashctx *flash, const chipaddr addr)
56{
Nico Huberdd6e07a2026-02-21 17:55:26 +010057 return flash->mst.par->chip_readw(flash->mst.par, addr);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100058}
59
60uint32_t chip_readl(const struct flashctx *flash, const chipaddr addr)
61{
Nico Huberdd6e07a2026-02-21 17:55:26 +010062 return flash->mst.par->chip_readl(flash->mst.par, addr);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100063}
64
65void chip_readn(const struct flashctx *flash, uint8_t *buf, chipaddr addr,
66 size_t len)
67{
Nico Huberdd6e07a2026-02-21 17:55:26 +010068 flash->mst.par->chip_readn(flash->mst.par, buf, addr, len);
Edward O'Callaghan63f6a372022-08-12 12:56:43 +100069}
70
Nico Huber2ae63012026-03-04 21:06:45 +010071struct memory_found_id *alloc_memory_found_id(void)
72{
73 struct memory_found_id *const found = calloc(1, sizeof(*found));
74 if (found)
75 found->generic.info.ext = &found->memory_info;
76 return found;
77}
78
79static const struct bus_probe memory_probes[] = {
80 /* prio. type function function argument */
Nico Huber2e947462026-03-07 17:04:59 +010081 { 0, ID_JEDEC, probe_jedec, NULL },
82 { 0, ID_JEDEC_29GL, probe_jedec_29gl, NULL },
Nico Huber3a2a4d52026-03-01 12:15:23 +010083 { 0, ID_82802AB, probe_82802ab, NULL },
Nico Huber2cadbe32026-03-05 18:34:57 +010084 /* Old Winbond W29* probe method w/ low priority because the
85 probing sequence puts the AMIC A49LF040A in a funky state. */
86 { 1, ID_W29EE011, probe_w29ee011, NULL },
Nico Huber2ae63012026-03-04 21:06:45 +010087};
88
Nico Huberdae90222026-03-09 20:36:56 +010089static bool memory_probe_match(const struct flashchip *chip, const struct id_info_ext *found)
Nico Huber2ae63012026-03-04 21:06:45 +010090{
91 const struct memory_chip_info *const probe_info = found->ext;
92
93 return (memcmp(&found->id, &chip->id, sizeof(chip->id)) == 0) &&
94 (probe_info->chip_size == chip->total_size * KiB) &&
Nico Huber2e947462026-03-07 17:04:59 +010095 (!probe_info->probe_timing || probe_info->probe_timing == chip->probe_timing) &&
Nico Huber2ae63012026-03-04 21:06:45 +010096 (probe_info->chip_features == (probe_info->chip_features & chip->feature_bits));
97}
98
Nico Huber89569d62023-01-12 23:31:40 +010099int register_par_master(const struct par_master *mst, const enum chipbustype buses,
Nico Huber47aa85c2026-02-21 14:57:20 +0100100 const uintptr_t rom_base, const size_t max_rom_decode, void *data)
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000101{
Nico Huberaf9d7382023-05-01 13:33:26 +0200102 struct registered_master rmst = { 0 };
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000103
104 if (mst->shutdown) {
105 if (register_shutdown(mst->shutdown, data)) {
106 mst->shutdown(data); /* cleanup */
107 return 1;
108 }
109 }
110
111 if (!mst->chip_writeb || !mst->chip_writew || !mst->chip_writel ||
112 !mst->chip_writen || !mst->chip_readb || !mst->chip_readw ||
113 !mst->chip_readl || !mst->chip_readn) {
114 msg_perr("%s called with incomplete master definition.\n"
Nico Huberc3b02dc2023-08-12 01:13:45 +0200115 "Please report a bug at flashprog@flashprog.org\n",
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000116 __func__);
Nico Huberc3b02dc2023-08-12 01:13:45 +0200117 return ERROR_FLASHPROG_BUG;
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000118 }
119
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000120 rmst.buses_supported = buses;
Nico Huber2ae63012026-03-04 21:06:45 +0100121 rmst.probing.probe_count = ARRAY_SIZE(memory_probes);
122 rmst.probing.probes = memory_probes;
123 rmst.probing.match = memory_probe_match;
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000124 rmst.par = *mst;
Nico Huber47aa85c2026-02-21 14:57:20 +0100125
126 rmst.par.rom_base = rom_base;
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000127 if (data)
128 rmst.par.data = data;
Nico Huber006d08d2026-03-10 22:33:22 +0100129
130 if (max_rom_decode)
131 rmst.common.max_rom_decode = max_rom_decode;
132 else
133 rmst.common.max_rom_decode = DEFAULT_MAX_DECODE_PARALLEL;
134
Edward O'Callaghan63f6a372022-08-12 12:56:43 +1000135 return register_master(&rmst);
136}