blob: 365c53ccfad92002b073bc1b0f6953459b80d7e9 [file] [log] [blame]
Nico Huber0e76d992023-01-12 20:22:55 +01001/*
2 * This file is part of the flashprog project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <stddef.h>
16#include <stdint.h>
17
18#include "flash.h"
19#include "programmer.h"
20
21#include "chipdrivers.h"
22
23static void *programmer_map_flash_region(const struct flashctx *flash, const char *descr,
24 uintptr_t phys_addr, size_t len)
25{
26 void *ret;
Nico Huber9a11cbf2023-01-13 01:19:07 +010027 if (flash->mst.par->map_flash)
28 ret = flash->mst.par->map_flash(descr, phys_addr, len);
Nico Huber0e76d992023-01-12 20:22:55 +010029 else
30 ret = fallback_map(descr, phys_addr, len);
31 msg_gspew("%s: mapping %s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n",
32 __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret);
33 return ret;
34}
35
36static void programmer_unmap_flash_region(const struct flashctx *flash, void *virt_addr, size_t len)
37{
Nico Huber9a11cbf2023-01-13 01:19:07 +010038 if (flash->mst.par->unmap_flash)
39 flash->mst.par->unmap_flash(virt_addr, len);
Nico Huber0e76d992023-01-12 20:22:55 +010040 else
41 fallback_unmap(virt_addr, len);
42 msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr);
43}
44
45int prepare_memory_access(struct flashctx *flash, enum preparation_steps prep)
46{
47 /* Init pointers to the fail-safe state to distinguish them later from legit values. */
48 flash->virtual_memory = (chipaddr)ERROR_PTR;
49 flash->virtual_registers = (chipaddr)ERROR_PTR;
50
Nico Huber0e76d992023-01-12 20:22:55 +010051 const chipsize_t size = flash->chip->total_size * 1024;
Nico Huberb1974022023-01-12 13:13:12 +010052 const uintptr_t base = flashbase ? flashbase : (0xffffffff - size + 1);
53 void *const addr = programmer_map_flash_region(flash, flash->chip->name, base, size);
Nico Huber0e76d992023-01-12 20:22:55 +010054 if (addr == ERROR_PTR) {
55 msg_perr("Could not map flash chip %s at 0x%0*" PRIxPTR ".\n",
56 flash->chip->name, PRIxPTR_WIDTH, base);
57 return 1;
58 }
59 flash->physical_memory = base;
60 flash->virtual_memory = (chipaddr)addr;
61
Nico Huberb1974022023-01-12 13:13:12 +010062 return 0;
63}
64
65int prepare_memory_register_access(struct flashctx *flash, enum preparation_steps prep)
66{
67 if (prepare_memory_access(flash, prep))
68 return 1;
69
Nico Huber0e76d992023-01-12 20:22:55 +010070 /*
71 * FIXME: Special function registers normally live 4 MByte below flash space,
72 * but it might be somewhere completely different on some chips and programmers,
73 * or not mappable at all. Ignore these problems for now and always report success.
74 */
Nico Huberb1974022023-01-12 13:13:12 +010075 const chipsize_t size = flash->chip->total_size * 1024;
76 const uintptr_t base = 0xffffffff - size - 0x400000 + 1;
77 void *const addr = programmer_map_flash_region(flash, "flash chip registers", base, size);
78 if (addr == ERROR_PTR) {
79 msg_pdbg2("Could not map flash chip registers %s at 0x%0*" PRIxPTR ".\n",
80 flash->chip->name, PRIxPTR_WIDTH, base);
81 return 0;
Nico Huber0e76d992023-01-12 20:22:55 +010082 }
Nico Huberb1974022023-01-12 13:13:12 +010083 flash->physical_registers = base;
84 flash->virtual_registers = (chipaddr)addr;
85
Nico Huber0e76d992023-01-12 20:22:55 +010086 return 0;
87}
88
89void finish_memory_access(struct flashctx *flash)
90{
91 const size_t size = flashprog_flash_getsize(flash);
92
93 if (flash->virtual_registers != (chipaddr)ERROR_PTR) {
94 programmer_unmap_flash_region(flash, (void *)flash->virtual_registers, size);
95 flash->physical_registers = 0;
96 flash->virtual_registers = (chipaddr)ERROR_PTR;
97 }
98
99 if (flash->virtual_memory != (chipaddr)ERROR_PTR) {
100 programmer_unmap_flash_region(flash, (void *)flash->virtual_memory, size);
101 flash->physical_memory = 0;
102 flash->virtual_memory = (chipaddr)ERROR_PTR;
103 }
104}