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 }