blob: 2a94630bd854ab76100240fb9d056d7918b8451e [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
Nico Huber10337f72026-03-04 19:57:27 +010023#include "chipdrivers/memory_bus.h"
Nico Huber0e76d992023-01-12 20:22:55 +010024
Nico Huber3d6bd5a2026-02-21 15:47:21 +010025static void *programmer_map_flash_region(const struct par_master *par, const char *descr,
26 uintptr_t phys_addr, chipsize_t len)
Nico Huber0e76d992023-01-12 20:22:55 +010027{
28 void *ret;
Nico Huber3d6bd5a2026-02-21 15:47:21 +010029 if (par->map_flash)
30 ret = par->map_flash(descr, phys_addr, len);
Nico Huber0e76d992023-01-12 20:22:55 +010031 else
32 ret = fallback_map(descr, phys_addr, len);
Nico Huber3d6bd5a2026-02-21 15:47:21 +010033 msg_gspew("%s: mapping%s%s from 0x%0*" PRIxPTR " to 0x%0*" PRIxPTR "\n",
34 __func__, *descr ? " " : "", descr,
35 PRIxPTR_WIDTH, phys_addr, PRIxPTR_WIDTH, (uintptr_t)ret);
Nico Huber0e76d992023-01-12 20:22:55 +010036 return ret;
37}
38
Nico Huber3d6bd5a2026-02-21 15:47:21 +010039void programmer_unmap_flash_region(const struct par_master *par, void *virt_addr, chipsize_t len)
Nico Huber0e76d992023-01-12 20:22:55 +010040{
Nico Huber3d6bd5a2026-02-21 15:47:21 +010041 if (par->unmap_flash)
42 par->unmap_flash(virt_addr, len);
Nico Huber0e76d992023-01-12 20:22:55 +010043 else
44 fallback_unmap(virt_addr, len);
45 msg_gspew("%s: unmapped 0x%0*" PRIxPTR "\n", __func__, PRIxPTR_WIDTH, (uintptr_t)virt_addr);
46}
47
Nico Huber3d6bd5a2026-02-21 15:47:21 +010048static uintptr_t calculate_flash_data_base(const struct par_master *par, chipsize_t size)
49{
50 return par->rom_base ? par->rom_base : (0xffffffff - size + 1);
51}
52
53void *programmer_map_flash_data(const struct par_master *par, chipsize_t size, const char *descr)
54{
55 uintptr_t base = calculate_flash_data_base(par, size);
56 void *const addr = programmer_map_flash_region(par, descr, base, size);
57 if (addr == ERROR_PTR) {
58 msg_perr("Could not map flash chip%s%s at 0x%0*" PRIxPTR ".\n",
59 *descr ? " " : "", descr, PRIxPTR_WIDTH, base);
60 }
61 return addr;
62}
63
Nico Huber0e76d992023-01-12 20:22:55 +010064int prepare_memory_access(struct flashctx *flash, enum preparation_steps prep)
65{
Nico Huber47aa85c2026-02-21 14:57:20 +010066 const struct par_master *const par = flash->mst.par;
67
Nico Huberb89c4522024-12-04 23:30:13 +010068 if (prep == PREPARE_POST_PROBE)
69 return 0;
70
Nico Huber0e76d992023-01-12 20:22:55 +010071 /* Init pointers to the fail-safe state to distinguish them later from legit values. */
72 flash->virtual_memory = (chipaddr)ERROR_PTR;
73 flash->virtual_registers = (chipaddr)ERROR_PTR;
74
Nico Huber0e76d992023-01-12 20:22:55 +010075 const chipsize_t size = flash->chip->total_size * 1024;
Nico Huber3d6bd5a2026-02-21 15:47:21 +010076 void *const addr = programmer_map_flash_data(par, size, flash->chip->name);
77 if (addr == ERROR_PTR)
Nico Huber0e76d992023-01-12 20:22:55 +010078 return 1;
Nico Huber3d6bd5a2026-02-21 15:47:21 +010079
80 flash->physical_memory = calculate_flash_data_base(par, size);
Nico Huber0e76d992023-01-12 20:22:55 +010081 flash->virtual_memory = (chipaddr)addr;
82
Nico Huberb1974022023-01-12 13:13:12 +010083 return 0;
84}
85
86int prepare_memory_register_access(struct flashctx *flash, enum preparation_steps prep)
87{
Nico Huber3d6bd5a2026-02-21 15:47:21 +010088 const struct par_master *const par = flash->mst.par;
89
Nico Huberb89c4522024-12-04 23:30:13 +010090 if (prep == PREPARE_POST_PROBE)
91 return 0;
92
Nico Huberb1974022023-01-12 13:13:12 +010093 if (prepare_memory_access(flash, prep))
94 return 1;
95
Nico Huber0e76d992023-01-12 20:22:55 +010096 /*
97 * FIXME: Special function registers normally live 4 MByte below flash space,
98 * but it might be somewhere completely different on some chips and programmers,
99 * or not mappable at all. Ignore these problems for now and always report success.
100 */
Nico Huberb1974022023-01-12 13:13:12 +0100101 const chipsize_t size = flash->chip->total_size * 1024;
102 const uintptr_t base = 0xffffffff - size - 0x400000 + 1;
Nico Huber3d6bd5a2026-02-21 15:47:21 +0100103 void *const addr = programmer_map_flash_region(par, "flash chip registers", base, size);
Nico Huberb1974022023-01-12 13:13:12 +0100104 if (addr == ERROR_PTR) {
105 msg_pdbg2("Could not map flash chip registers %s at 0x%0*" PRIxPTR ".\n",
106 flash->chip->name, PRIxPTR_WIDTH, base);
107 return 0;
Nico Huber0e76d992023-01-12 20:22:55 +0100108 }
Nico Huberb1974022023-01-12 13:13:12 +0100109 flash->physical_registers = base;
110 flash->virtual_registers = (chipaddr)addr;
111
Nico Huber0e76d992023-01-12 20:22:55 +0100112 return 0;
113}
114
115void finish_memory_access(struct flashctx *flash)
116{
117 const size_t size = flashprog_flash_getsize(flash);
118
119 if (flash->virtual_registers != (chipaddr)ERROR_PTR) {
Nico Huber3d6bd5a2026-02-21 15:47:21 +0100120 programmer_unmap_flash_region(flash->mst.par, (void *)flash->virtual_registers, size);
Nico Huber0e76d992023-01-12 20:22:55 +0100121 flash->physical_registers = 0;
122 flash->virtual_registers = (chipaddr)ERROR_PTR;
123 }
124
125 if (flash->virtual_memory != (chipaddr)ERROR_PTR) {
Nico Huber3d6bd5a2026-02-21 15:47:21 +0100126 programmer_unmap_flash_region(flash->mst.par, (void *)flash->virtual_memory, size);
Nico Huber0e76d992023-01-12 20:22:55 +0100127 flash->physical_memory = 0;
128 flash->virtual_memory = (chipaddr)ERROR_PTR;
129 }
130}