22#include "target.h"
33#include "target_internal.h"
44#include "cortexar.h"
5+ #include "buffer_utils.h"
56
6- #define TMS570_SYS_BASE 0xffffff00U
7- #define TMS570_SYS_DEVID (TMS570_SYS_BASE + 0xf0U )
8- #define TMS570_SCM_DEVID_ID_MASK 0x0700fe7fU /* Note: value is swapped since target is BE */
7+ #define TMS570_SYS_BASE 0xFFFFFF00U
8+ #define TMS570_SYS_DEVID (TMS570_SYS_BASE + 0xF0U )
9+ #define TMS570_SCM_DEVID_ID_MASK 0x0700FE7FU /* Note: value is swapped since target is BE */
910#define TMS570_SCM_REVID_ID_TMS570 0x05004400U /* Note: value is swapped since target is BE */
1011
12+ #define TMS570_OTP_BANK0_MEMORY_INFORMATION 0xF008015CU
13+ #define TMS570_OTP_BANK0_MEMORY_SIZE_MASK 0xFFFFU
14+
1115/* Base address for the OCRAM regions, including their mirrors (including RETRAM) */
1216#define TMS570_SRAM_BASE 0x08000000U
1317#define TMS570_SRAM_ECC_BASE 0x08400000U
1418#define TMS570_SRAM_SIZE 0x80000U
1519
20+ #define TMS570_FLASH_BASE_ADDR 0x00000000U
21+ #define TMS570_FLASH_SECTOR_ADDR (TMS570_L2FMC_BASE_ADDR + 0x408U)
22+ #define TMS570_FLASH_SECTOR_SIZE
23+
24+ #define TMS570_L2FMC_BASE_ADDR 0xFFF87000U
25+ #define TMS570_L2FMC_FSPRD_ADDR (TMS570_FLASH_BASE_ADDR + 0x4U)
26+ #define TMS570_L2FMC_FMAC_ADDR (TMS570_FLASH_BASE_ADDR + 0x50U)
27+ #define TMS570_L2FMC_FLOCK_ADDR (TMS570_FLASH_BASE_ADDR + 0x64U) /* Undocumented */
28+ #define TMS570_L2FMC_FVREADCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x80U) /* Undocumented */
29+ #define TMS570_L2FMC_FVNVCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x8CU) /* Undocumented */
30+ #define TMS570_L2FMC_FVPPCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x90U) /* Undocumented */
31+ #define TMS570_L2FMC_FVWLCT_ADDR (TMS570_FLASH_BASE_ADDR + 0x94U) /* Undocumented */
32+ #define TMS570_L2FMC_FEFUSE_ADDR (TMS570_FLASH_BASE_ADDR + 0x98U) /* Undocumented */
33+ #define TMS570_L2FMC_FBSTROBES_ADDR (TMS570_FLASH_BASE_ADDR + 0x100U) /* Undocumented */
34+ #define TMS570_L2FMC_FPSTROBES_ADDR (TMS570_FLASH_BASE_ADDR + 0x104U) /* Undocumented */
35+ #define TMS570_L2FMC_FBMODE_ADDR (TMS570_FLASH_BASE_ADDR + 0x108U) /* Undocumented */
36+ #define TMS570_L2FMC_FTCR_ADDR (TMS570_FLASH_BASE_ADDR + 0x10CU) /* Undocumented */
37+ #define TMS570_L2FMC_FSM_WR_ENA_ADDR (TMS570_FLASH_BASE_ADDR + 0x288U)
38+
1639#define TMS570_OTP_PACKAGE_AND_FLASH_MEMORY_SIZE 0xf008015cU
1740
41+ #define TMS570_OTP_BANK0_BASE 0xF0080000U
42+ #define TMS570_FLASH_OTP_BASE (TMS570_OTP_BANK0_BASE + 0x170)
43+
44+ /*
45+ * Flash functions
46+ */
47+ static bool tms570_flash_erase (target_flash_s * flash , target_addr_t addr , size_t len );
48+ static bool tms570_flash_write (target_flash_s * flash , target_addr_t dest , const void * src , size_t len );
49+ static bool tms570_flash_prepare (target_flash_s * flash );
50+ static bool tms570_flash_done (target_flash_s * flash );
51+ static bool tms570_flash_initialize (target_s * const target );
52+
1853bool ti_tms570_probe (target_s * const target )
1954{
2055 const uint32_t part_id = target_mem32_read32 (target , TMS570_SYS_DEVID );
@@ -27,5 +62,175 @@ bool ti_tms570_probe(target_s *const target)
2762 target_add_ram32 (target , TMS570_SRAM_BASE , TMS570_SRAM_SIZE );
2863 target_add_ram32 (target , TMS570_SRAM_ECC_BASE , TMS570_SRAM_SIZE );
2964
65+ // target_flash_s *flash = calloc(1, sizeof(*flash));
66+ // if (!flash) { /* calloc failed: heap exhaustion */
67+ // DEBUG_ERROR("calloc: failed in %s\n", __func__);
68+ // return false;
69+ // }
70+
71+ tms570_flash_initialize (target );
72+
73+ // flash->start = TMS570_FLASH_BASE_ADDR;
74+ // flash->length = flash_size;
75+ // flash->blocksize = TMS570_FLASH_SECTOR_SIZE;
76+ // flash->writesize = CH579_FLASH_WRITE_SIZE;
77+ // flash->erase = tms570_flash_erase;
78+ // flash->write = tms570_flash_write;
79+ // flash->prepare = tms570_flash_prepare;
80+ // flash->done = tms570_flash_done;
81+ // flash->erased = 0xffU;
82+ // target_add_flash(target, flash);
83+
84+ return true;
85+ }
86+
87+ static uint32_t accumulate (uint32_t arg , const uint32_t val )
88+ {
89+ arg += (val & 0xffffU );
90+ return (arg & 0xffffU ) + (arg >> 16 );
91+ }
92+
93+ /// The flash configuration data is burned into a special OTP block on the target.
94+ /// This data is hashed with a Fletcher checksum, which has the nice property that
95+ /// it can tell us if the endianness is backwards or if we're not talking to the
96+ /// correct device. The checksum value is stored in the last word of the OTP area.
97+ static bool fletcher_checksum (const uint32_t * const otp_data , const size_t otp_data_count , const uint32_t comparison )
98+ {
99+ uint32_t check_low = 0xffffU ;
100+ uint32_t check_high = 0xffffU ;
101+
102+ for (size_t i = 0 ; i < otp_data_count ; i ++ ) {
103+ uint32_t word = otp_data [i ];
104+ // Accumulate low word
105+ check_low = accumulate (check_low , word );
106+ check_high = accumulate (check_high , check_low );
107+ // Accumulate high word
108+ check_low = accumulate (check_low , word >> 16 );
109+ check_high = accumulate (check_high , check_low );
110+ }
111+
112+ uint32_t result = (check_high << 16 ) | check_low ;
113+ DEBUG_TARGET ("Comparing result %08" PRIx32 " to check value %08" PRIx32 "\n" , result , comparison );
114+ return comparison == result ;
115+ }
116+
117+ static bool tms570_flash_initialize (target_s * const target )
118+ {
119+ if (target -> tms570_flash_initialized )
120+ return true;
121+
122+ // Read the OTP data out of flash. This is protected with a Fletcher checksum
123+ uint32_t otp_data [12 ];
124+ for (int i = 0 ; i < 12 ; i ++ ) {
125+ const uint32_t value = target_mem32_read32 (target , TMS570_FLASH_OTP_BASE + (i * 4 ));
126+ otp_data [i ] = read_be4 ((const uint8_t * )& value , 0 );
127+ DEBUG_TARGET ("Flash OTP[0x%08" PRIx32 "]: 0x%08" PRIx32 "\n" , TMS570_FLASH_OTP_BASE + (i * 4 ), otp_data [i ]);
128+ }
129+ if (!fletcher_checksum (otp_data , 11 , otp_data [11 ])) {
130+ return false;
131+ }
132+
133+ // Enable all three banks
134+ uint32_t fmac = target_mem32_read32 (target , TMS570_L2FMC_FMAC_ADDR );
135+ target_mem32_write32 (target , TMS570_L2FMC_FMAC_ADDR , fmac | 7 );
136+
137+ // Disable read margin control.
138+ // (Note: previously this set RMBSEL first and then RM0/1, but do both in one write now)
139+ target_mem32_write32 (target , TMS570_L2FMC_FSPRD_ADDR , 0 );
140+
141+ // Disable the FSM
142+ target_mem32_write32 (target , TMS570_L2FMC_FSM_WR_ENA_ADDR , 0 );
143+
144+ // Copy some timing values from OTP
145+ uint32_t unk_210 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x210 );
146+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x210 , (unk_210 & 0xffff0000 ) | (otp_data [0 ] >> 16 ));
147+ uint32_t unk_218 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x218 );
148+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x218 , (unk_218 & 0xffff0000 ) | (otp_data [0 ] & 0xffff ));
149+
150+ // Set the 2nd nibble after the first write is completed
151+ uint32_t unk_21c = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x21c );
152+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x21c , (unk_21c & 0xffff00f0 ) | (otp_data [1 ] & 0xff0f ));
153+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x21c , (unk_21c & 0xffff0000 ) | (otp_data [1 ] & 0xffff ));
154+
155+ // ???
156+ uint8_t unk_214 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x214 );
157+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x214 , (unk_214 & 0xffff0fff ) | (otp_data [3 ] & 0xf000 ));
158+
159+ // ???
160+ uint8_t unk_220 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x220 );
161+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x220 , (unk_220 & 0xffffff00 ) | ((otp_data [1 ] >> 24 ) & 0xff ));
162+
163+ // ???
164+ uint32_t unk_224 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x224 );
165+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x224 , (unk_224 & 0xffffff00 ) | ((otp_data [2 ] >> 16 ) & 0xff ));
166+
167+ // ???
168+ uint16_t unk_268 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x268 );
169+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x268 , (unk_268 & 0xfffff000 ) | (otp_data [5 ] & 0xfff ));
170+
171+ // ???
172+ uint16_t unk_26c = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x26c );
173+ target_mem32_write16 (
174+ target , TMS570_L2FMC_BASE_ADDR + 0x26c , (unk_26c & 0xfe00ffff ) | ((otp_data [8 ] & 0x1ff ) << 16 ));
175+
176+ // NOTE: This used to be a 16-bit access -- ensure that it's properly swapped
177+ uint16_t unk_270 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x270 );
178+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x270 , unk_270 & 0xfe00ffff );
179+
180+ uint32_t unk_278 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x278 );
181+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x278 , (unk_278 & 0xffffff80 ) | ((otp_data [4 ] - 1 ) & 0x7f ));
182+
183+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x27c , 0x4500 );
184+
185+ // Unlock L2FMC
186+ target_mem32_write32 (target , TMS570_L2FMC_FLOCK_ADDR , 0x55aa );
187+
188+ uint32_t fvreadct = target_mem32_read32 (target , TMS570_L2FMC_FVREADCT_ADDR );
189+ target_mem32_write32 (target , TMS570_L2FMC_FVREADCT_ADDR , (fvreadct & 0xfffffff0 ) | ((otp_data [10 ] >> 8 ) & 0xf ));
190+
191+ target_mem32_write32 (target , TMS570_L2FMC_FVNVCT_ADDR , 0 );
192+
193+ target_mem32_write32 (target , TMS570_L2FMC_FBSTROBES_ADDR , 0x00010104 );
194+ target_mem32_write32 (target , TMS570_L2FMC_FPSTROBES_ADDR , 0x103 );
195+ target_mem32_write32 (target , TMS570_L2FMC_FBMODE_ADDR , 0 );
196+
197+ uint32_t ftcr = target_mem32_read32 (target , TMS570_L2FMC_FTCR_ADDR );
198+ target_mem32_write32 (target , TMS570_L2FMC_FTCR_ADDR , ftcr & 0xffffff80 );
199+
200+ uint32_t fvppct = target_mem32_read32 (target , TMS570_L2FMC_FVPPCT_ADDR );
201+ target_mem32_write32 (target , TMS570_L2FMC_FVPPCT_ADDR ,
202+ (fvppct & 0xffffe0e0 ) | (((otp_data [9 ] >> 8 ) & 0x1f ) << 8 ) | (otp_data [9 ] & 0x1f ));
203+
204+ uint8_t fvwlct = target_mem32_read32 (target , TMS570_L2FMC_FVWLCT_ADDR );
205+ target_mem32_write32 (target , TMS570_L2FMC_FVWLCT_ADDR , (fvwlct & ~0xf000 ) | ((otp_data [10 ] >> 24 ) & 0xf ) << 12 );
206+
207+ uint32_t fefuse = target_mem32_read32 (target , TMS570_L2FMC_FEFUSE_ADDR );
208+ target_mem32_write32 (target , TMS570_L2FMC_FEFUSE_ADDR , (fefuse & 0xffffffe0 ) | ((otp_data [10 ] >> 16 ) & 0x1f ));
209+
210+ uint32_t unk_a8 = target_mem32_read32 (target , TMS570_L2FMC_BASE_ADDR + 0x0a8 );
211+ target_mem32_write32 (target , TMS570_L2FMC_BASE_ADDR + 0x0a8 , (unk_a8 & 0xffffff00 ) | ((otp_data [3 ] >> 16 ) & 0xff ));
212+
213+ target_mem32_write32 (target , TMS570_L2FMC_FPSTROBES_ADDR , 0x103 );
214+
215+ target_mem32_write32 (target , TMS570_L2FMC_FBSTROBES_ADDR , 0x10104 );
216+
217+ // Reads as 0x55aa
218+ target_mem32_write32 (target , TMS570_L2FMC_FLOCK_ADDR , 0 );
219+
220+ // Re-enable the FSM
221+ uint32_t fsm = target_mem32_read32 (target , TMS570_L2FMC_FSM_WR_ENA_ADDR );
222+ target_mem32_write32 (target , TMS570_L2FMC_FSM_WR_ENA_ADDR , (fsm & 0xfffffff8 ) | 2 );
223+
224+ target -> tms570_flash_initialized = true;
30225 return true;
31226}
227+
228+ static bool tms570_flash_prepare (target_flash_s * flash )
229+ {
230+ target_s * const target = flash -> t ;
231+
232+ if (!tms570_flash_initialize (target )) {
233+ DEBUG_ERROR ("Checksum for OTP values doesn't match!" );
234+ return false;
235+ }
236+ }
0 commit comments