1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io> *
5 * Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net> *
6 ***************************************************************************/
13 #include <target/image.h>
15 #define SWM050_DELAY 100
17 #define SWM050_FLASH_PAGE_SIZE 0x200
18 #define SWM050_FLASH_PAGES 16
20 #define SWM050_CPU_ID 0xE000ED00
21 #define SWM050_CPU_ID_VAL 0x410CC200
23 #define SWM050_FLASH_REG1 0x1F000000
24 #define SWM050_FLASH_REG2 0x1F000038
25 #define SWM050_FLASH_KEY 0xAAAAAAAA
27 #define SWM050_SYSCTL_CFG_0 0x400F0000
28 #define SWM050_SYSCTL_DBLF 0x400F0008
30 static int swm050_erase(struct flash_bank *bank, unsigned int first,
33 struct target *target = bank->target;
36 if (target->state != TARGET_HALTED) {
37 LOG_ERROR("Target not halted");
38 return ERROR_TARGET_NOT_HALTED;
42 retval = target_write_u32(target, SWM050_FLASH_REG1, 0x4);
43 if (retval != ERROR_OK)
46 for (unsigned int curr_page = first; curr_page <= last; curr_page++) {
47 uint32_t curr_addr = bank->base + (SWM050_FLASH_PAGE_SIZE * curr_page);
49 retval = target_write_u32(target, curr_addr, SWM050_FLASH_KEY);
50 if (retval != ERROR_OK)
52 alive_sleep(SWM050_DELAY);
55 /* Close flash interface */
56 retval = target_write_u32(target, SWM050_FLASH_REG1, 0x0);
57 if (retval != ERROR_OK)
63 static int swm050_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
65 struct target *target = bank->target;
68 if (target->state != TARGET_HALTED) {
69 LOG_ERROR("Target not halted");
70 retval = ERROR_TARGET_NOT_HALTED;
75 retval = target_write_u32(target, SWM050_FLASH_REG1, 0x1);
76 if (retval != ERROR_OK)
79 retval = target_write_memory(target, bank->base + offset, 4, count/4, buffer);
80 if (retval != ERROR_OK)
83 /* Close flash interface */
84 retval = target_write_u32(target, SWM050_FLASH_REG1, 0x0);
85 if (retval != ERROR_OK)
91 static int swm050_probe(struct flash_bank *bank)
96 static int swm050_mass_erase(struct flash_bank *bank)
98 struct target *target = bank->target;
101 if (target->state != TARGET_HALTED) {
102 LOG_ERROR("Target not halted");
103 return ERROR_TARGET_NOT_HALTED;
106 /* Perform mass erase */
107 retval = target_write_u32(target, SWM050_FLASH_REG1, 0x6);
108 if (retval != ERROR_OK)
110 retval = target_write_u32(target, SWM050_FLASH_REG2, 0x1);
111 if (retval != ERROR_OK)
113 retval = target_write_u32(target, 0x0, SWM050_FLASH_KEY);
114 if (retval != ERROR_OK)
117 alive_sleep(SWM050_DELAY);
119 /* Close flash interface */
120 retval = target_write_u32(target, SWM050_FLASH_REG1, 0x0);
121 if (retval != ERROR_OK)
127 COMMAND_HANDLER(swm050_handle_mass_erase_command)
130 return ERROR_COMMAND_SYNTAX_ERROR;
132 struct flash_bank *bank;
133 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
134 if (retval != ERROR_OK)
137 retval = swm050_mass_erase(bank);
138 if (retval == ERROR_OK)
139 command_print(CMD, "swm050 mass erase complete");
141 command_print(CMD, "swm050 mass erase failed");
146 FLASH_BANK_COMMAND_HANDLER(swm050_flash_bank_command)
149 bank->write_start_alignment = 4;
150 bank->write_end_alignment = 4;
151 bank->size = SWM050_FLASH_PAGE_SIZE * SWM050_FLASH_PAGES;
153 bank->num_sectors = SWM050_FLASH_PAGES;
154 bank->sectors = alloc_block_array(0, SWM050_FLASH_PAGE_SIZE, SWM050_FLASH_PAGES);
158 for (unsigned int i = 0; i < bank->num_sectors; i++)
159 bank->sectors[i].is_protected = 0;
164 static const struct command_registration swm050_exec_command_handlers[] = {
166 .name = "mass_erase",
167 .handler = swm050_handle_mass_erase_command,
168 .mode = COMMAND_EXEC,
170 .help = "Erase entire flash device.",
172 COMMAND_REGISTRATION_DONE
175 static const struct command_registration swm050_command_handlers[] = {
179 .help = "swm050 flash command group",
181 .chain = swm050_exec_command_handlers,
183 COMMAND_REGISTRATION_DONE
186 struct flash_driver swm050_flash = {
188 .commands = swm050_command_handlers,
189 .flash_bank_command = swm050_flash_bank_command,
190 .erase = swm050_erase,
191 .write = swm050_write,
192 .read = default_flash_read,
193 .probe = swm050_probe,
194 .auto_probe = swm050_probe,
195 .erase_check = default_flash_blank_check,
196 .free_driver_priv = default_flash_free_driver_priv,