blob: b9cd68ce9d669b61468054e2bb6e99f079e6afba [file] [log] [blame]
Nico Huber0e76d992023-01-12 20:22:55 +01001/*
2 * This file is part of the flashprog project.
3 *
Nico Huber404529d2025-01-30 23:14:14 +01004 * Copyright (C) 2014 Stefan Tauner
5 *
Nico Huber0e76d992023-01-12 20:22:55 +01006 * 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 <stddef.h>
18#include <stdint.h>
19
20#include "flash.h"
21#include "programmer.h"
22
23#include "chipdrivers.h"
24
25static void *programmer_map_flash_region(const struct flashctx *flash, const char *descr,
26 uintptr_t phys_addr, size_t len)
27{
28 void *ret;
Nico Huber9a11cbf2023-01-13 01:19:07 +010029 if (flash->mst.par->map_flash)
30 ret = flash->mst.par->map_flash(descr, phys_addr, len);
Nico Huber0e76d992023-01-12 20:22:55 +010031 else
32 ret = fallback_map(descr, phys_addr, len);
33 msg_gspew("%s: mapping %s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n",
34 __func__, descr, PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t) ret);
35 return ret;
36}
37
38static void programmer_unmap_flash_region(const struct flashctx *flash, void *virt_addr, size_t len)
39{
Nico Huber9a11cbf2023-01-13 01:19:07 +010040 if (flash->mst.par->unmap_flash)
41 flash->mst.par->unmap_flash(virt_addr, len);
Nico Huber0e76d992023-01-12 20:22:55 +010042 else
43 fallback_unmap(virt_addr, len);
44 msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr);
45}
46
47int prepare_memory_access(struct flashctx *flash, enum preparation_steps prep)
48{
Nico Huberb89c4522024-12-04 23:30:13 +010049 if (prep == PREPARE_POST_PROBE)
50 return 0;
51
Nico Huber0e76d992023-01-12 20:22:55 +010052 /* Init pointers to the fail-safe state to distinguish them later from legit values. */
53 flash->virtual_memory = (chipaddr)ERROR_PTR;
54 flash->virtual_registers = (chipaddr)ERROR_PTR;
55
Nico Huber0e76d992023-01-12 20:22:55 +010056 const chipsize_t size = flash->chip->total_size * 1024;
Nico Huberb1974022023-01-12 13:13:12 +010057 const uintptr_t base = flashbase ? flashbase : (0xffffffff - size + 1);
58 void *const addr = programmer_map_flash_region(flash, flash->chip->name, base, size);
Nico Huber0e76d992023-01-12 20:22:55 +010059 if (addr == ERROR_PTR) {
60 msg_perr("Could not map flash chip %s at 0x%0*" PRIxPTR ".\n",
61 flash->chip->name, PRIxPTR_WIDTH, base);
62 return 1;
63 }
64 flash->physical_memory = base;
65 flash->virtual_memory = (chipaddr)addr;
66
Nico Huberb1974022023-01-12 13:13:12 +010067 return 0;
68}
69
70int prepare_memory_register_access(struct flashctx *flash, enum preparation_steps prep)
71{
Nico Huberb89c4522024-12-04 23:30:13 +010072 if (prep == PREPARE_POST_PROBE)
73 return 0;
74
Nico Huberb1974022023-01-12 13:13:12 +010075 if (prepare_memory_access(flash, prep))
76 return 1;
77
Nico Huber0e76d992023-01-12 20:22:55 +010078 /*
79 * FIXME: Special function registers normally live 4 MByte below flash space,
80 * but it might be somewhere completely different on some chips and programmers,
81 * or not mappable at all. Ignore these problems for now and always report success.
82 */
Nico Huberb1974022023-01-12 13:13:12 +010083 const chipsize_t size = flash->chip->total_size * 1024;
84 const uintptr_t base = 0xffffffff - size - 0x400000 + 1;
85 void *const addr = programmer_map_flash_region(flash, "flash chip registers", base, size);
86 if (addr == ERROR_PTR) {
87 msg_pdbg2("Could not map flash chip registers %s at 0x%0*" PRIxPTR ".\n",
88 flash->chip->name, PRIxPTR_WIDTH, base);
89 return 0;
Nico Huber0e76d992023-01-12 20:22:55 +010090 }
Nico Huberb1974022023-01-12 13:13:12 +010091 flash->physical_registers = base;
92 flash->virtual_registers = (chipaddr)addr;
93
Nico Huber0e76d992023-01-12 20:22:55 +010094 return 0;
95}
96
97void finish_memory_access(struct flashctx *flash)
98{
99 const size_t size = flashprog_flash_getsize(flash);
100
101 if (flash->virtual_registers != (chipaddr)ERROR_PTR) {
102 programmer_unmap_flash_region(flash, (void *)flash->virtual_registers, size);
103 flash->physical_registers = 0;
104 flash->virtual_registers = (chipaddr)ERROR_PTR;
105 }
106
107 if (flash->virtual_memory != (chipaddr)ERROR_PTR) {
108 programmer_unmap_flash_region(flash, (void *)flash->virtual_memory, size);
109 flash->physical_memory = 0;
110 flash->virtual_memory = (chipaddr)ERROR_PTR;
111 }
112}