FreeCalypso > hg > freecalypso-tools
comparison loadtools/flashid.c @ 506:0dd2c87c1b63
fc-loadtool flash support overhaul
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 28 May 2019 05:12:47 +0000 |
parents | |
children | c942be3c7997 |
comparison
equal
deleted
inserted
replaced
505:7bf0d909c87e | 506:0dd2c87c1b63 |
---|---|
1 /* | |
2 * Flash device detection code lives here | |
3 */ | |
4 | |
5 #include <sys/types.h> | |
6 #include <stdio.h> | |
7 #include <stdint.h> | |
8 #include <stdlib.h> | |
9 #include "flash.h" | |
10 | |
11 extern struct flash_device flashdev_28F160C3T; | |
12 extern struct flash_device flashdev_28F320C3T; | |
13 extern struct flash_device flashdev_28F640C3T; | |
14 extern struct flash_device flashdev_28F640C3B; | |
15 extern struct flash_device flashdev_28F640W30T; | |
16 extern struct flash_device flashdev_28F640W30B; | |
17 extern struct flash_device flashdev_PL129J; | |
18 extern struct flash_device flashdev_PL129N; | |
19 extern struct flash_device flashdev_K5A32xx_T; | |
20 | |
21 extern int flash_global_config; | |
22 extern struct flash_bank_info flash_bank_info[2]; | |
23 | |
24 static | |
25 run_cfi_check(bi, table) | |
26 struct flash_bank_info *bi; | |
27 struct cfi_check *table; | |
28 { | |
29 struct cfi_check *tp; | |
30 uint16_t rdword; | |
31 | |
32 for (tp = table; tp->offset >= 0; tp++) { | |
33 if (do_r16(bi->base_addr + (tp->offset << 1), &rdword) < 0) | |
34 return(-1); | |
35 if (rdword != tp->expect_val) | |
36 return(0); | |
37 } | |
38 return(1); | |
39 } | |
40 | |
41 static | |
42 try_device(bi, dev) | |
43 struct flash_bank_info *bi; | |
44 struct flash_device *dev; | |
45 { | |
46 int rc; | |
47 | |
48 printf("Appears to be %s or compatible, checking CFI\n", dev->name); | |
49 if (do_w16(bi->base_addr + 0xAA, 0x98)) { | |
50 fprintf(stderr, "unexpected response to w16 - aborting\n"); | |
51 return(-1); | |
52 } | |
53 rc = run_cfi_check(bi, dev->cfi_table); | |
54 if (rc < 0) | |
55 return(rc); | |
56 if (!rc) { | |
57 fprintf(stderr, "Error: CFI mismatch, unsafe to continue\n"); | |
58 return(-1); | |
59 } | |
60 printf("Confirmed %s or compatible\n", dev->name); | |
61 bi->device = dev; | |
62 return(0); | |
63 } | |
64 | |
65 static | |
66 spansion_pl129j_or_n(bi) | |
67 struct flash_bank_info *bi; | |
68 { | |
69 int rc; | |
70 | |
71 printf("Spansion PL129J or PL129N, looking at CFI\n"); | |
72 if (do_w16(bi->base_addr + 0xAA, 0x98)) { | |
73 fprintf(stderr, "unexpected response to w16 - aborting\n"); | |
74 return(-1); | |
75 } | |
76 rc = run_cfi_check(bi, flashdev_PL129N.cfi_table); | |
77 if (rc < 0) | |
78 return(rc); | |
79 if (rc) { | |
80 printf("Found PL129N\n"); | |
81 bi->device = &flashdev_PL129N; | |
82 return(0); | |
83 } | |
84 rc = run_cfi_check(bi, flashdev_PL129J.cfi_table); | |
85 if (rc < 0) | |
86 return(rc); | |
87 if (rc) { | |
88 printf("Found PL129J\n"); | |
89 bi->device = &flashdev_PL129J; | |
90 return(0); | |
91 } | |
92 fprintf(stderr, "Error: no matching CFI found\n"); | |
93 return(-1); | |
94 } | |
95 | |
96 static | |
97 amd_extended_id(bi) | |
98 struct flash_bank_info *bi; | |
99 { | |
100 uint16_t ext1, ext2; | |
101 | |
102 printf("AMD-style extended ID device, reading\n"); | |
103 if (do_r16(bi->base_addr + 0x1C, &ext1) < 0) | |
104 return(-1); | |
105 if (do_r16(bi->base_addr + 0x1E, &ext2) < 0) | |
106 return(-1); | |
107 printf("Extended ID: %04X %04X\n", ext1, ext2); | |
108 if (ext1 == 0x2221 && ext2 == 0x2200) | |
109 return spansion_pl129j_or_n(bi); | |
110 fprintf(stderr, "Error: unknown device ID\n"); | |
111 return(-1); | |
112 } | |
113 | |
114 static struct idmap { | |
115 uint16_t manuf_id; | |
116 uint16_t dev_id; | |
117 int (*handler)(); | |
118 void *extra_arg; | |
119 } device_id_table[] = { | |
120 /* AMD/Spansion devices */ | |
121 {0x0001, 0x227E, amd_extended_id, 0}, | |
122 /* 28F160C3T equivalent found in a C11x phone in the wild */ | |
123 {0x0020, 0x88CE, try_device, &flashdev_28F160C3T}, | |
124 /* Intel flash chips */ | |
125 {0x0089, 0x8854, try_device, &flashdev_28F640W30T}, | |
126 {0x0089, 0x8855, try_device, &flashdev_28F640W30B}, | |
127 {0x0089, 0x8864, try_device, &flashdev_28F640W30T}, | |
128 {0x0089, 0x88C2, try_device, &flashdev_28F160C3T}, | |
129 {0x0089, 0x88C4, try_device, &flashdev_28F320C3T}, | |
130 {0x0089, 0x88CC, try_device, &flashdev_28F640C3T}, | |
131 {0x0089, 0x88CD, try_device, &flashdev_28F640C3B}, | |
132 /* Samsung flash */ | |
133 {0x00EC, 0x22A0, try_device, &flashdev_K5A32xx_T}, | |
134 /* table search terminator */ | |
135 {0, 0, 0, 0} | |
136 }; | |
137 | |
138 flash_detect(bank, repeat) | |
139 { | |
140 struct flash_bank_info *bi; | |
141 uint16_t manuf_id, dev_id; | |
142 struct idmap *tp; | |
143 int rc; | |
144 | |
145 bi = flash_bank_info + bank; | |
146 if (bi->detect_done && !repeat) | |
147 return(0); | |
148 printf("Autodetecting flash chip type\n"); | |
149 if (do_w16(bi->base_addr + 0xAAA, 0xAA)) { | |
150 bad_w16: fprintf(stderr, | |
151 "unexpected response to w16 in read ID cmd sequence - aborting\n"); | |
152 return(-1); | |
153 } | |
154 if (do_w16(bi->base_addr + 0x554, 0x55)) | |
155 goto bad_w16; | |
156 if (do_w16(bi->base_addr + 0xAAA, 0x90)) | |
157 goto bad_w16; | |
158 if (do_r16(bi->base_addr, &manuf_id) < 0) | |
159 return(-1); | |
160 if (do_r16(bi->base_addr + 2, &dev_id) < 0) | |
161 return(-1); | |
162 printf("Basic device ID: %04X %04X\n", manuf_id, dev_id); | |
163 for (tp = device_id_table; tp->handler; tp++) | |
164 if (tp->manuf_id == manuf_id && tp->dev_id == dev_id) | |
165 break; | |
166 if (!tp->handler) { | |
167 fprintf(stderr, "Error: unknown device ID\n"); | |
168 return(-1); | |
169 } | |
170 rc = tp->handler(bi, tp->extra_arg); | |
171 if (rc < 0) | |
172 return(rc); | |
173 /* got the device, see if it is compatible with global config */ | |
174 if (bi->device->required_global_config > flash_global_config) { | |
175 fprintf(stderr, | |
176 "Error: detected flash device is not compatible with the configured mapping\n"); | |
177 return(-1); | |
178 } | |
179 /* good to go */ | |
180 if (bi->device->bank_geom[1] && bank) | |
181 bi->geom = bi->device->bank_geom[1]; | |
182 else | |
183 bi->geom = bi->device->bank_geom[0]; | |
184 bi->ops = bi->device->cmdset; | |
185 bi->detect_done = 1; | |
186 /* return device to read array mode */ | |
187 return bi->ops->reset_cmd(bi); | |
188 } |