blob: 97224edef3bec289bd28b5b40b23048ae58c1511 [file] [log] [blame]
Nico Hubere7598392026-06-23 22:29:15 +02001/*
2 * This file is part of the flashprog project.
3 *
4 * Copyright (C) 2026 Nico Huber <nico.h@gmx.de>
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.
15 */
16
17#include <stdint.h>
18
19#include "flash.h"
20#include "chipdrivers/memory_bus.h"
21
22static int write_m28f_1(struct flashctx *flash, unsigned int pos, uint8_t val)
23{
24 const chipaddr base = flash->virtual_memory;
25 unsigned int tries;
26
27 for (tries = 25; tries > 0; --tries) {
28 chip_writeb(flash, 0x40, base);
29 chip_writeb(flash, val, base + pos);
30 programmer_delay(10);
31
32 chip_writeb(flash, 0xc0, base);
33 programmer_delay(6);
34
35 if (chip_readb(flash, base) == val)
36 return 0;
37 }
38
39 msg_cerr("Write failed at 0x%06x.\n", pos);
40 return 1;
41}
42
43int write_m28f(struct flashctx *flash, const uint8_t *src, unsigned int pos, unsigned int len)
44{
45 const chipaddr base = flash->virtual_memory;
46 const unsigned int limit = pos + len;
47 int ret;
48
49 for (; pos < limit; ++pos, ++src) {
50 if (*src == 0xff) /* skip no-op writes */
51 continue;
52
53 ret = write_m28f_1(flash, pos, *src);
54 if (ret)
55 goto return_to_read_mode;
56 }
57
58return_to_read_mode:
59 chip_writeb(flash, 0x00, base);
60 return ret;
61}
62
63int erase_m28f(struct flashctx *flash, unsigned int addr, unsigned int blocksize)
64{
65 const chipaddr base = flash->virtual_memory;
66 unsigned int tries, pos;
67 int ret;
68
69 /* Programming everything to 0 is required. */
70 for (pos = 0; pos < blocksize; ++pos) {
71 ret = write_m28f_1(flash, pos, 0x00);
72 if (ret)
73 goto return_to_read_mode;
74 }
75
76 for (pos = 0, tries = 1000; tries > 0; --tries) {
77 chip_writeb(flash, 0x20, base);
78 chip_writeb(flash, 0x20, base);
79 programmer_delay(10*1000);
80
81 for (; pos < blocksize; ++pos) {
82 chip_writeb(flash, 0xa0, base + pos);
83 programmer_delay(6);
84
85 if (chip_readb(flash, base) != 0xff)
86 break;
87 }
88 if (pos == blocksize)
89 goto return_to_read_mode;
90 }
91
92 msg_cerr("Erase failed at 0x%06x.\n", pos);
93 ret = 1;
94
95return_to_read_mode:
96 chip_writeb(flash, 0x00, base);
97 return ret;
98}