usbboot/src/cmd.c |
31 | 31 | #include "ingenic_usb.h" |
32 | 32 | #include "usb_boot_defines.h" |
33 | 33 | |
34 | | struct hand hand; |
35 | 34 | struct sdram_in sdram_in; |
36 | 35 | |
37 | 36 | unsigned int total_size; |
38 | 37 | static char code_buf[4 * 512 * 1024]; |
39 | 38 | static char ret[8]; |
40 | 39 | |
41 | | |
42 | | static int load_file(struct ingenic_dev *ingenic_dev, const char *file_path) |
| 40 | static int load_file(struct ingenic_dev *dev, const char *file_path, char *buf) |
43 | 41 | { |
44 | 42 | struct stat fstat; |
45 | | int fd, status, res = -1; |
| 43 | int fd, status; |
46 | 44 | |
47 | 45 | status = stat(file_path, &fstat); |
48 | 46 | |
49 | 47 | if (status < 0) { |
50 | 48 | fprintf(stderr, "Error - can't get file size from '%s': %s\n", |
51 | 49 | file_path, strerror(errno)); |
52 | | goto out; |
| 50 | return errno; |
53 | 51 | } |
54 | 52 | |
55 | | ingenic_dev->file_len = fstat.st_size; |
56 | | ingenic_dev->file_buff = code_buf; |
57 | | |
58 | 53 | fd = open(file_path, O_RDONLY); |
59 | 54 | |
60 | 55 | if (fd < 0) { |
61 | | fprintf(stderr, "Error - can't open file '%s': %s\n", |
| 56 | fprintf(stderr, "Error - can't open file '%s': %s\n", |
62 | 57 | file_path, strerror(errno)); |
63 | | goto out; |
| 58 | return errno; |
64 | 59 | } |
65 | 60 | |
66 | | status = read(fd, ingenic_dev->file_buff, ingenic_dev->file_len); |
| 61 | status = read(fd, buf, fstat.st_size); |
67 | 62 | |
68 | | if (status < (int)ingenic_dev->file_len) { |
69 | | fprintf(stderr, "Error - can't read file '%s': %s\n", |
| 63 | if (status < (int)fstat.st_size) { |
| 64 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
70 | 65 | file_path, strerror(errno)); |
71 | 66 | goto close; |
72 | 67 | } |
73 | 68 | |
74 | 69 | /* write args to code */ |
75 | | memcpy(ingenic_dev->file_buff + 8, &hand.fw_args, |
76 | | sizeof(struct fw_args)); |
77 | | |
78 | | res = 1; |
| 70 | memcpy(buf + 8, &dev->config.fw_args, sizeof(struct fw_args)); |
79 | 71 | |
80 | 72 | close: |
81 | 73 | close(fd); |
82 | | out: |
83 | | return res; |
| 74 | |
| 75 | return fstat.st_size; |
84 | 76 | } |
85 | 77 | |
86 | 78 | /* after upload stage2. must init device */ |
87 | 79 | void init_cfg(struct ingenic_dev *dev) |
88 | 80 | { |
89 | 81 | if (usb_get_ingenic_cpu(dev) < 3) { |
90 | | printf(" XBurst CPU not booted yet, boot it first!\n"); |
| 82 | printf("XBurst CPU not booted yet, boot it first!\n"); |
91 | 83 | return; |
92 | 84 | } |
93 | 85 | |
94 | | if (usb_send_data_to_ingenic(dev, (char*)&hand, sizeof(hand)) != 1) |
| 86 | if (usb_send_data_to_ingenic(dev, (char*)&dev->config, sizeof(dev->config)) |
| 87 | < 0) |
95 | 88 | goto xout; |
96 | 89 | |
97 | | if (usb_ingenic_configration(dev, DS_hand) != 1) |
| 90 | if (usb_ingenic_configration(dev, DS_hand) < 0) |
98 | 91 | goto xout; |
99 | 92 | |
100 | | if (usb_read_data_from_ingenic(dev, ret, 8) != 1) |
| 93 | if (usb_read_data_from_ingenic(dev, ret, 8) < 0) |
101 | 94 | goto xout; |
102 | 95 | |
103 | | printf(" Configuring XBurst CPU succeeded.\n"); |
| 96 | printf("Configuring XBurst CPU succeeded.\n"); |
104 | 97 | return; |
105 | 98 | xout: |
106 | 99 | printf("Configuring XBurst CPU failed.\n"); |
... | ... | |
109 | 102 | int boot(struct ingenic_dev *dev, const char *stage1_path, const char *stage2_path) |
110 | 103 | { |
111 | 104 | int status; |
| 105 | int size; |
112 | 106 | |
113 | 107 | status = usb_get_ingenic_cpu(dev); |
114 | 108 | switch (status) { |
115 | | case 1: /* Jz4740v1 */ |
| 109 | case INGENIC_CPU_JZ4740V1: |
116 | 110 | status = 0; |
117 | | hand.fw_args.cpu_id = 0x4740; |
| 111 | dev->config.fw_args.cpu_id = 0x4740; |
118 | 112 | break; |
119 | | case 2: /* Jz4750v1 */ |
| 113 | case INGENIC_CPU_JZ4750V1: |
120 | 114 | status = 0; |
121 | | hand.fw_args.cpu_id = 0x4750; |
| 115 | dev->config.fw_args.cpu_id = 0x4750; |
122 | 116 | break; |
123 | | case 3: /* Boot4740 */ |
| 117 | case INGENIC_CPU_JZ4740: |
124 | 118 | status = 1; |
125 | | hand.fw_args.cpu_id = 0x4740; |
| 119 | dev->config.fw_args.cpu_id = 0x4740; |
126 | 120 | break; |
127 | | case 4: /* Boot4750 */ |
| 121 | case INGENIC_CPU_JZ4750: |
128 | 122 | status = 1; |
129 | | hand.fw_args.cpu_id = 0x4750; |
| 123 | dev->config.fw_args.cpu_id = 0x4750; |
130 | 124 | break; |
131 | 125 | default: |
132 | | return 1; |
| 126 | return (status < 0) ? status : -1; |
133 | 127 | } |
134 | 128 | |
135 | 129 | if (status) { |
136 | | printf(" Already booted.\n"); |
137 | | return 1; |
| 130 | printf("Already booted.\n"); |
| 131 | return 0; |
138 | 132 | } else { |
139 | | printf(" CPU not yet booted, now booting...\n"); |
| 133 | printf("CPU not yet booted, now booting...\n"); |
140 | 134 | |
141 | 135 | /* now we upload the boot stage1 */ |
142 | | printf(" Loading stage1 from '%s'\n", stage1_path); |
143 | | if (load_file(dev, stage1_path) < 1) |
144 | | return -1; |
| 136 | printf("Loading stage1 from '%s'\n", stage1_path); |
| 137 | size = load_file(dev, stage1_path, code_buf); |
| 138 | if (size < 0) |
| 139 | return size; |
145 | 140 | |
146 | | if (usb_ingenic_upload(dev, 1) < 1) |
| 141 | if (usb_ingenic_upload(dev, 1, code_buf, size) < 0) |
147 | 142 | return -1; |
148 | 143 | |
149 | 144 | /* now we upload the boot stage2 */ |
150 | 145 | usleep(100); |
151 | | printf(" Loading stage2 from '%s'\n", stage2_path); |
152 | | if (load_file(dev, stage2_path) < 1) |
153 | | return -1; |
| 146 | printf("Loading stage2 from '%s'\n", stage2_path); |
| 147 | size = load_file(dev, stage2_path, code_buf); |
| 148 | if (size < 0) { |
| 149 | printf("FOOBAR"); |
| 150 | return size; |
| 151 | } |
154 | 152 | |
155 | | if (usb_ingenic_upload(dev, 2) < 1) |
| 153 | if (usb_ingenic_upload(dev, 2, code_buf, size) < 0) |
156 | 154 | return -1; |
157 | 155 | |
158 | | printf(" Booted successfully!\n"); |
| 156 | printf("Booted successfully!\n"); |
159 | 157 | } |
160 | 158 | usleep(100); |
161 | 159 | init_cfg(dev); |
162 | | return 1; |
| 160 | return 0; |
163 | 161 | } |
164 | 162 | |
165 | 163 | |
... | ... | |
171 | 169 | |
172 | 170 | tmp = usb_get_ingenic_cpu(dev); |
173 | 171 | if (tmp > 2) { |
174 | | printf(" This command only run under UNBOOT state!\n"); |
| 172 | printf("This command only run under UNBOOT state!\n"); |
175 | 173 | return -1; |
176 | 174 | } |
177 | 175 | |
178 | 176 | switch (tmp) { |
179 | 177 | case 1: |
180 | | tmp = 0; |
181 | | hand.fw_args.cpu_id = 0x4740; |
| 178 | dev->config.fw_args.cpu_id = 0x4740; |
182 | 179 | break; |
183 | 180 | case 2: |
184 | | tmp = 0; |
185 | | hand.fw_args.cpu_id = 0x4750; |
| 181 | dev->config.fw_args.cpu_id = 0x4750; |
186 | 182 | break; |
187 | 183 | } |
188 | 184 | |
189 | | hand.fw_args.debug_ops = 1;/* tell device it's memory debug */ |
190 | | hand.fw_args.start = start; |
| 185 | dev->config.fw_args.debug_ops = 1;/* tell device it's memory debug */ |
| 186 | dev->config.fw_args.start = start; |
191 | 187 | |
192 | 188 | if (size == 0) |
193 | | hand.fw_args.size = total_size; |
| 189 | dev->config.fw_args.size = total_size; |
194 | 190 | else |
195 | | hand.fw_args.size = size; |
| 191 | dev->config.fw_args.size = size; |
196 | 192 | |
197 | | printf(" Now test memory from 0x%x to 0x%x: \n", |
198 | | start, start + hand.fw_args.size); |
| 193 | printf("Now test memory from 0x%x to 0x%x: \n", |
| 194 | start, start + dev->config.fw_args.size); |
199 | 195 | |
200 | | if (load_file(dev, STAGE1_FILE_PATH) < 1) |
201 | | return -1; |
202 | | if (usb_ingenic_upload(dev, 1) < 1) |
| 196 | size = load_file(dev, STAGE1_FILE_PATH, code_buf); |
| 197 | if (size < 0) |
| 198 | return size; |
| 199 | if (usb_ingenic_upload(dev, 1, code_buf, size) < 1) |
203 | 200 | return -1; |
204 | 201 | |
205 | 202 | usleep(100); |
206 | 203 | usb_read_data_from_ingenic(dev, buffer, 8); |
207 | 204 | if (buffer[0] != 0) |
208 | | printf(" Test memory fail! Last error address is 0x%x !\n", |
| 205 | printf("Test memory fail! Last error address is 0x%x !\n", |
209 | 206 | buffer[0]); |
210 | 207 | else |
211 | | printf(" Test memory pass!\n"); |
| 208 | printf("Test memory pass!\n"); |
212 | 209 | |
213 | 210 | return 1; |
214 | 211 | } |
215 | 212 | |
216 | 213 | int debug_go(struct ingenic_dev *dev, size_t argc, char *argv[]) |
217 | 214 | { |
218 | | unsigned int addr,obj; |
| 215 | unsigned int addr, obj; |
219 | 216 | if (argc < 3) { |
220 | 217 | printf(" Usage: go (1) (2) \n" |
221 | 218 | " 1:start SDRAM address\n" |
... | ... | |
226 | 223 | addr = strtoul(argv[1], NULL, 0); |
227 | 224 | obj = atoi(argv[2]); |
228 | 225 | |
229 | | printf(" Executing No.%d device at address 0x%x\n", obj, addr); |
| 226 | printf("Executing No.%d device at address 0x%x\n", obj, addr); |
230 | 227 | |
231 | 228 | if (usb_ingenic_start(dev, VR_PROGRAM_START2, addr) < 1) |
232 | 229 | return -1; |
... | ... | |
237 | 234 | int sdram_load(struct ingenic_dev *dev, struct sdram_in *sdram_in) |
238 | 235 | { |
239 | 236 | if (usb_get_ingenic_cpu(dev) < 3) { |
240 | | printf(" Device unboot! Boot it first!\n"); |
| 237 | printf("Device unboot! Boot it first!\n"); |
241 | 238 | return -1; |
242 | 239 | } |
243 | 240 | |
244 | 241 | if (sdram_in->length > (unsigned int) MAX_LOAD_SIZE) { |
245 | | printf(" Image length too long!\n"); |
| 242 | printf("Image length too long!\n"); |
246 | 243 | return -1; |
247 | 244 | } |
248 | 245 | |
... | ... | |
252 | 249 | /* usb_ingenic_sdram_ops(dev, sdram_in);*/ |
253 | 250 | |
254 | 251 | usb_read_data_from_ingenic(dev, ret, 8); |
255 | | printf(" Load last address at 0x%x\n", |
| 252 | printf("Load last address at 0x%x\n", |
256 | 253 | ((ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0))); |
257 | 254 | |
258 | 255 | return 1; |
... | ... | |
283 | 280 | j = flen % MAX_LOAD_SIZE; |
284 | 281 | offset = 0; |
285 | 282 | |
286 | | printf(" Total size to send in byte is :%d\n", flen); |
287 | | printf(" Loading data to SDRAM :\n"); |
| 283 | printf("Total size to send in byte is :%d\n", flen); |
| 284 | printf("Loading data to SDRAM :\n"); |
288 | 285 | |
289 | 286 | for (k = 0; k < m; k++) { |
290 | 287 | status = read(fd, sdram_in->buf, MAX_LOAD_SIZE); |
usbboot/src/ingenic_usb.c |
41 | 41 | (usb_dev->descriptor.idProduct == PRODUCT_ID)) { |
42 | 42 | ingenic_dev->usb_dev = usb_dev; |
43 | 43 | count++; |
44 | | break; |
| 44 | break; |
45 | 45 | } |
46 | 46 | |
47 | 47 | } |
... | ... | |
63 | 63 | usb_config_desc = &ingenic_dev->usb_dev->config[config_index]; |
64 | 64 | |
65 | 65 | if (!usb_config_desc) |
66 | | return 0; |
| 66 | return -1; |
67 | 67 | |
68 | 68 | for (if_index = 0; if_index < usb_config_desc->bNumInterfaces; |
69 | 69 | if_index++) { |
70 | 70 | usb_if = &usb_config_desc->interface[if_index]; |
71 | 71 | |
72 | 72 | if (!usb_if) |
73 | | return 0; |
| 73 | return -1; |
74 | 74 | |
75 | 75 | for (alt_index = 0; alt_index < usb_if->num_altsetting; |
76 | 76 | alt_index++) { |
77 | 77 | usb_if_desc = &usb_if->altsetting[alt_index]; |
78 | 78 | |
79 | 79 | if (!usb_if_desc) |
80 | | return 0; |
| 80 | return -1; |
81 | 81 | |
82 | 82 | if ((usb_if_desc->bInterfaceClass == 0xff) && |
83 | 83 | (usb_if_desc->bInterfaceSubClass == 0)) { |
84 | 84 | ingenic_dev->interface = |
85 | 85 | usb_if_desc->bInterfaceNumber; |
86 | | return 1; |
| 86 | return 0; |
87 | 87 | } |
88 | 88 | } |
89 | 89 | } |
... | ... | |
94 | 94 | |
95 | 95 | int usb_ingenic_init(struct ingenic_dev *ingenic_dev) |
96 | 96 | { |
97 | | int num_ingenic, status = -1; |
| 97 | int num_ingenic; |
| 98 | int ret = -1; |
98 | 99 | |
99 | 100 | memset(ingenic_dev, 0, sizeof(struct ingenic_dev)); |
100 | 101 | |
... | ... | |
107 | 108 | |
108 | 109 | if (num_ingenic == 0) { |
109 | 110 | fprintf(stderr, "Error - no XBurst device found\n"); |
110 | | goto out; |
| 111 | goto err; |
111 | 112 | } |
112 | 113 | |
113 | 114 | if (num_ingenic > 1) { |
114 | | fprintf(stderr, "Error - too many XBurst devices found: %i\n", |
| 115 | fprintf(stderr, "Error - too many XBurst devices found: %d\n", |
115 | 116 | num_ingenic); |
116 | | goto out; |
| 117 | goto err; |
117 | 118 | } |
118 | 119 | |
119 | 120 | ingenic_dev->usb_handle = usb_open(ingenic_dev->usb_dev); |
120 | 121 | if (!ingenic_dev->usb_handle) { |
121 | 122 | fprintf(stderr, "Error - can't open XBurst device: %s\n", |
122 | 123 | usb_strerror()); |
123 | | goto out; |
| 124 | goto err; |
124 | 125 | } |
125 | 126 | |
126 | | if (get_ingenic_interface(ingenic_dev) < 1) { |
| 127 | ret = get_ingenic_interface(ingenic_dev); |
| 128 | if (ret < 0) { |
127 | 129 | fprintf(stderr, "Error - can't find XBurst interface\n"); |
128 | | goto out; |
| 130 | goto err; |
129 | 131 | } |
130 | 132 | |
131 | | if (usb_claim_interface(ingenic_dev->usb_handle, ingenic_dev->interface) |
132 | | < 0) { |
| 133 | ret = usb_claim_interface(ingenic_dev->usb_handle, ingenic_dev->interface); |
| 134 | if (ret < 0) { |
133 | 135 | fprintf(stderr, "Error - can't claim XBurst interface: %s\n", |
134 | 136 | usb_strerror()); |
135 | | goto out; |
| 137 | goto err; |
136 | 138 | } |
137 | 139 | |
138 | | status = 1; |
139 | | |
140 | | out: |
141 | | return status; |
| 140 | return 0; |
| 141 | err: |
| 142 | return ret; |
142 | 143 | } |
143 | 144 | |
144 | 145 | int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev) |
145 | 146 | { |
146 | | int status; |
147 | | |
148 | | memset(&ingenic_dev->cpu_info_buff, 0, |
149 | | ARRAY_SIZE(ingenic_dev->cpu_info_buff)); |
| 147 | int ret; |
| 148 | char buf[9]; |
150 | 149 | |
151 | 150 | sleep(1); |
152 | | status = usb_control_msg(ingenic_dev->usb_handle, |
153 | | /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR |USB_RECIP_DEVICE, |
154 | | /* bRequest */ VR_GET_CPU_INFO, |
155 | | /* wValue */ 0, |
156 | | /* wIndex */ 0, |
157 | | /* Data */ ingenic_dev->cpu_info_buff, |
158 | | /* wLength */ 8, |
159 | | USB_TIMEOUT); |
160 | | |
161 | | if (status != sizeof(ingenic_dev->cpu_info_buff) - 1 ) { |
| 151 | ret = usb_control_msg(ingenic_dev->usb_handle, |
| 152 | /* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR |USB_RECIP_DEVICE, |
| 153 | /* bRequest */ VR_GET_CPU_INFO, |
| 154 | /* wValue */ 0, |
| 155 | /* wIndex */ 0, |
| 156 | /* Data */ buf, |
| 157 | /* wLength */ 8, |
| 158 | USB_TIMEOUT); |
| 159 | |
| 160 | if (ret != 8) { |
162 | 161 | fprintf(stderr, "Error - " |
163 | | "can't retrieve XBurst CPU information: %i\n", status); |
164 | | return status; |
| 162 | "can't retrieve XBurst CPU information: %d\n", ret); |
| 163 | return ret; |
165 | 164 | } |
166 | 165 | |
167 | | ingenic_dev->cpu_info_buff[8] = '\0'; |
168 | | printf(" CPU data: %s\n", ingenic_dev->cpu_info_buff); |
| 166 | buf[8] = '\0'; |
| 167 | printf(" CPU data: %s\n", buf); |
169 | 168 | |
170 | | if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4740V1")) return 1; |
171 | | if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4750V1")) return 2; |
172 | | if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4740")) return 3; |
173 | | if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4750")) return 4; |
| 169 | if (!strcmp(buf, "JZ4740V1")) |
| 170 | return INGENIC_CPU_JZ4740V1; |
| 171 | if (!strcmp(buf, "JZ4750V1")) |
| 172 | return INGENIC_CPU_JZ4750V1; |
| 173 | if (!strcmp(buf, "Boot4740")) |
| 174 | return INGENIC_CPU_JZ4740; |
| 175 | if (!strcmp(buf, "Boot4750")) |
| 176 | return INGENIC_CPU_JZ4750; |
174 | 177 | |
175 | | return 0; |
| 178 | return INGENIC_CPU_UNKOWN; |
176 | 179 | } |
177 | 180 | |
178 | | int usb_ingenic_flush_cache(struct ingenic_dev *ingenic_dev) |
| 181 | int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev, const char *data, |
| 182 | int size) |
179 | 183 | { |
180 | | int status; |
181 | | |
182 | | status = usb_control_msg(ingenic_dev->usb_handle, |
183 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
184 | | /* bRequest */ VR_FLUSH_CACHES, |
185 | | /* wValue */ 0, |
186 | | /* wIndex */ 0, |
187 | | /* Data */ 0, |
188 | | /* wLength */ 0, |
189 | | USB_TIMEOUT); |
190 | | |
191 | | if (status != 0) { |
192 | | fprintf(stderr, "Error - can't flush cache: %i\n", status); |
193 | | return status; |
| 184 | int ret; |
| 185 | ret = usb_bulk_write(ingenic_dev->usb_handle, |
| 186 | /* endpoint */ INGENIC_OUT_ENDPOINT, |
| 187 | /* bulk data */ data, |
| 188 | /* bulk data length */ size, |
| 189 | USB_TIMEOUT); |
| 190 | |
| 191 | if (ret < 0) { |
| 192 | fprintf(stderr, "Error - " |
| 193 | "Can't send bulk data to Ingenic CPU: %d\n", ret); |
| 194 | return ret; |
194 | 195 | } |
195 | 196 | |
196 | | return 1; |
| 197 | return size; |
197 | 198 | } |
198 | 199 | |
199 | | int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, unsigned int len) |
| 200 | int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev, |
| 201 | char *data, int size) |
200 | 202 | { |
201 | | int status; |
| 203 | int ret; |
| 204 | ret = usb_bulk_read(ingenic_dev->usb_handle, |
| 205 | /* endpoint */ INGENIC_IN_ENDPOINT, |
| 206 | /* bulk data */ data, |
| 207 | /* bulk data length */ size, |
| 208 | USB_TIMEOUT); |
202 | 209 | |
203 | | /* tell the device the length of the file to be uploaded */ |
204 | | status = usb_control_msg(ingenic_dev->usb_handle, |
205 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
206 | | /* bRequest */ VR_SET_DATA_LENGTH, |
207 | | /* wValue */ STAGE_ADDR_MSB(len), |
208 | | /* wIndex */ STAGE_ADDR_LSB(len), |
209 | | /* Data */ 0, |
210 | | /* wLength */ 0, |
211 | | USB_TIMEOUT); |
212 | | |
213 | | if (status != 0) { |
| 210 | if (ret < 0) { |
214 | 211 | fprintf(stderr, "Error - " |
215 | | "can't set data length on Ingenic device: %i\n", status); |
216 | | return -1; |
| 212 | "Can't read bulk data from Ingenic device: %d\n", ret); |
| 213 | return ret; |
217 | 214 | } |
218 | 215 | |
219 | | return 1; |
| 216 | return size; |
220 | 217 | } |
221 | 218 | |
222 | | int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev, uint32_t addr) |
| 219 | int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr) |
223 | 220 | { |
224 | | int status; |
225 | | /* tell the device the RAM address to store the file */ |
226 | | status = usb_control_msg(ingenic_dev->usb_handle, |
227 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
228 | | /* bRequest */ VR_SET_DATA_ADDRESS, |
229 | | /* wValue */ STAGE_ADDR_MSB(addr), |
230 | | /* wIndex */ STAGE_ADDR_LSB(addr), |
231 | | /* Data */ 0, |
232 | | /* wLength */ 0, |
233 | | USB_TIMEOUT); |
234 | | |
235 | | if (status != 0) { |
236 | | fprintf(stderr, "Error - " |
237 | | "can't set the address on Ingenic device: %i\n", status); |
238 | | return -1; |
239 | | } |
| 221 | int ret; |
240 | 222 | |
241 | | return 1; |
242 | | } |
| 223 | /* tell the device to start the uploaded device */ |
| 224 | ret = usb_control_msg(ingenic_dev->usb_handle, |
| 225 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 226 | /* bRequest */ rqst, |
| 227 | /* wValue */ STAGE_ADDR_MSB(stage_addr), |
| 228 | /* wIndex */ STAGE_ADDR_LSB(stage_addr), |
| 229 | /* Data */ 0, |
| 230 | /* wLength */ 0, |
| 231 | USB_TIMEOUT); |
243 | 232 | |
244 | | int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev, const char *data, |
245 | | int size) |
246 | | { |
247 | | int status; |
248 | | status = usb_bulk_write(ingenic_dev->usb_handle, |
249 | | /* endpoint */ INGENIC_OUT_ENDPOINT, |
250 | | /* bulk data */ data, |
251 | | /* bulk data length */ size, |
252 | | USB_TIMEOUT); |
253 | | if (status < size) { |
254 | | fprintf(stderr, "Error - " |
255 | | "can't send bulk data to Ingenic CPU: %i\n", status); |
256 | | return -1; |
| 233 | if (ret != 0) { |
| 234 | fprintf(stderr, "Error - can't start the uploaded binary " |
| 235 | "on the Ingenic device: %d\n", ret); |
257 | 236 | } |
258 | | |
259 | | return 1; |
| 237 | return ret; |
260 | 238 | } |
261 | 239 | |
262 | | int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev, |
263 | | char *data, int size) |
| 240 | int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, unsigned int len) |
264 | 241 | { |
265 | | int status; |
266 | | status = usb_bulk_read(ingenic_dev->usb_handle, |
267 | | /* endpoint */ INGENIC_IN_ENDPOINT, |
268 | | /* bulk data */ data, |
269 | | /* bulk data length */ size, |
270 | | USB_TIMEOUT); |
271 | | if (status < size) { |
| 242 | int ret; |
| 243 | |
| 244 | /* tell the device the length of the file to be uploaded */ |
| 245 | ret = usb_control_msg(ingenic_dev->usb_handle, |
| 246 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 247 | /* bRequest */ VR_SET_DATA_LENGTH, |
| 248 | /* wValue */ STAGE_ADDR_MSB(len), |
| 249 | /* wIndex */ STAGE_ADDR_LSB(len), |
| 250 | /* Data */ 0, |
| 251 | /* wLength */ 0, |
| 252 | USB_TIMEOUT); |
| 253 | |
| 254 | if (ret != 0) { |
272 | 255 | fprintf(stderr, "Error - " |
273 | | "can't read bulk data from Ingenic device:%i\n", status); |
274 | | return -1; |
| 256 | "can't set data length on Ingenic device: %d\n", ret); |
275 | 257 | } |
276 | 258 | |
277 | | return 1; |
| 259 | return ret; |
278 | 260 | } |
279 | 261 | |
280 | | int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr) |
| 262 | int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev, uint32_t addr) |
281 | 263 | { |
282 | | int status; |
| 264 | int ret; |
283 | 265 | |
284 | | /* tell the device to start the uploaded device */ |
285 | | status = usb_control_msg(ingenic_dev->usb_handle, |
286 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
287 | | /* bRequest */ rqst, |
288 | | /* wValue */ STAGE_ADDR_MSB(stage_addr), |
289 | | /* wIndex */ STAGE_ADDR_LSB(stage_addr), |
290 | | /* Data */ 0, |
291 | | /* wLength */ 0, |
292 | | USB_TIMEOUT); |
293 | | |
294 | | if (status != 0) { |
295 | | fprintf(stderr, "Error - can't start the uploaded binary " |
296 | | "on the Ingenic device: %i\n", status); |
297 | | return status; |
| 266 | /* tell the device the RAM address to store the file */ |
| 267 | ret = usb_control_msg(ingenic_dev->usb_handle, |
| 268 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 269 | /* bRequest */ VR_SET_DATA_ADDRESS, |
| 270 | /* wValue */ STAGE_ADDR_MSB(addr), |
| 271 | /* wIndex */ STAGE_ADDR_LSB(addr), |
| 272 | /* Data */ 0, |
| 273 | /* wLength */ 0, |
| 274 | USB_TIMEOUT); |
| 275 | |
| 276 | if (ret != 0) { |
| 277 | fprintf(stderr, "Error - " |
| 278 | "Can't set the address on Ingenic device: %d\n", ret); |
298 | 279 | } |
299 | | return 1; |
| 280 | |
| 281 | return ret; |
300 | 282 | } |
301 | 283 | |
302 | | int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage) |
| 284 | |
| 285 | int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage, |
| 286 | const char *buf, int size) |
303 | 287 | { |
304 | | unsigned int stage2_addr; |
305 | | stage2_addr = total_size + 0x80000000; |
306 | | stage2_addr -= CODE_SIZE; |
| 288 | uint32_t stage_addr; |
| 289 | int request; |
| 290 | int ret; |
| 291 | |
| 292 | if (stage == 1) { |
| 293 | stage_addr = 0x80002000; |
| 294 | request = VR_PROGRAM_START1; |
| 295 | } else { |
| 296 | stage_addr = 0x80000000 + total_size - CODE_SIZE; |
| 297 | request = VR_PROGRAM_START2; |
| 298 | } |
307 | 299 | |
308 | | int stage_addr = (stage == 1 ? 0x80002000 : stage2_addr); |
309 | | int rqst = VR_PROGRAM_START1; |
310 | 300 | |
311 | 301 | usb_send_data_address_to_ingenic(ingenic_dev, stage_addr); |
312 | | printf(" Download stage %d program and execute at 0x%08x\n", |
313 | | stage, (stage_addr)); |
314 | | usb_send_data_to_ingenic(ingenic_dev, ingenic_dev->file_buff, |
315 | | ingenic_dev->file_len); |
| 302 | printf("Download stage %d program and execute at 0x%08x\n", |
| 303 | stage, stage_addr); |
| 304 | usb_send_data_to_ingenic(ingenic_dev, buf, size); |
316 | 305 | |
317 | 306 | if (stage == 2) { |
318 | | if (usb_get_ingenic_cpu(ingenic_dev) < 1) |
319 | | return -1; |
| 307 | ret = usb_get_ingenic_cpu(ingenic_dev); |
| 308 | if (ret < 0) |
| 309 | return ret; |
320 | 310 | usb_ingenic_flush_cache(ingenic_dev); |
321 | | rqst = VR_PROGRAM_START2; |
322 | 311 | } |
323 | 312 | |
324 | | if (usb_ingenic_start(ingenic_dev, rqst, stage_addr) < 1) |
325 | | return -1; |
326 | | if (usb_get_ingenic_cpu(ingenic_dev) < 1) |
327 | | return -1; |
| 313 | ret = usb_ingenic_start(ingenic_dev, request, stage_addr); |
| 314 | if (ret) |
| 315 | return ret; |
| 316 | ret = usb_get_ingenic_cpu(ingenic_dev); |
| 317 | if (ret) |
| 318 | return ret; |
328 | 319 | |
329 | | return 1; |
| 320 | return 0; |
330 | 321 | } |
331 | 322 | |
332 | 323 | void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev) |
333 | 324 | { |
334 | | if ((ingenic_dev->usb_handle) && (ingenic_dev->interface)) |
335 | | usb_release_interface(ingenic_dev->usb_handle, |
336 | | ingenic_dev->interface); |
| 325 | if (ingenic_dev->usb_handle) { |
| 326 | if (ingenic_dev->interface) { |
| 327 | usb_release_interface(ingenic_dev->usb_handle, |
| 328 | ingenic_dev->interface); |
| 329 | } |
337 | 330 | |
338 | | if (ingenic_dev->usb_handle) |
339 | 331 | usb_close(ingenic_dev->usb_handle); |
| 332 | } |
| 333 | |
340 | 334 | } |
341 | 335 | |
| 336 | static int usb_ingenic_ops(struct ingenic_dev *ingenic_dev, uint32_t type, |
| 337 | uint32_t ops) |
| 338 | { |
| 339 | int ret; |
| 340 | ret = usb_control_msg(ingenic_dev->usb_handle, |
| 341 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 342 | /* bRequest */ type, |
| 343 | /* wValue */ ops, |
| 344 | /* wIndex */ 0, |
| 345 | /* Data */ 0, |
| 346 | /* wLength */ 0, |
| 347 | USB_TIMEOUT); |
| 348 | |
| 349 | return ret; |
| 350 | } |
| 351 | |
| 352 | int usb_ingenic_flush_cache(struct ingenic_dev *ingenic_dev) |
| 353 | { |
| 354 | int ret; |
| 355 | ret = usb_ingenic_ops(ingenic_dev, VR_FLUSH_CACHES, 0); |
| 356 | |
| 357 | if (ret != 0) { |
| 358 | fprintf(stderr, "Error - can't flush cache: %d\n", ret); |
| 359 | } |
| 360 | |
| 361 | return ret; |
| 362 | } |
| 363 | |
| 364 | |
342 | 365 | int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops) |
343 | 366 | { |
344 | | int status; |
345 | | status = usb_control_msg(ingenic_dev->usb_handle, |
346 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
347 | | /* bRequest */ VR_NAND_OPS, |
348 | | /* wValue */ ops & 0xffff, |
349 | | /* wIndex */ 0, |
350 | | /* Data */ 0, |
351 | | /* wLength */ 0, |
352 | | USB_TIMEOUT); |
353 | | |
354 | | if (status != 0) { |
| 367 | int ret; |
| 368 | ret = usb_ingenic_ops(ingenic_dev, VR_NAND_OPS, ops); |
| 369 | |
| 370 | if (ret != 0) { |
355 | 371 | fprintf(stderr, "Error - " |
356 | | "can't set Ingenic device nand ops: %i\n", status); |
357 | | return -1; |
| 372 | "can't set Ingenic device nand ops: %d\n", ret); |
358 | 373 | } |
359 | 374 | |
360 | | return 1; |
| 375 | return ret; |
361 | 376 | } |
362 | 377 | |
363 | 378 | int usb_ingenic_mem_ops(struct ingenic_dev *ingenic_dev, int ops) |
364 | 379 | { |
365 | | int status; |
366 | | status = usb_control_msg(ingenic_dev->usb_handle, |
367 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
368 | | /* bRequest */ VR_MEM_OPS, |
369 | | /* wValue */ ops & 0xffff, |
370 | | /* wIndex */ 0, |
371 | | /* Data */ 0, |
372 | | /* wLength */ 0, |
373 | | USB_TIMEOUT); |
374 | | |
375 | | if (status != 0) { |
| 380 | int ret; |
| 381 | ret = usb_ingenic_ops(ingenic_dev, VR_MEM_OPS, ops); |
| 382 | |
| 383 | if (ret != 0) { |
376 | 384 | fprintf(stderr, "Error - " |
377 | | "can't set Ingenic device nand ops: %i\n", status); |
378 | | return -1; |
| 385 | "can't set Ingenic device nand ops: %d\n", ret); |
379 | 386 | } |
380 | 387 | |
381 | | return 1; |
| 388 | return ret; |
382 | 389 | } |
383 | 390 | |
384 | 391 | |
385 | 392 | int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops) |
386 | 393 | { |
387 | | int status; |
388 | | status = usb_control_msg(ingenic_dev->usb_handle, |
389 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
390 | | /* bRequest */ VR_CONFIGRATION, |
391 | | /* wValue */ ops, |
392 | | /* wIndex */ 0, |
393 | | /* Data */ 0, |
394 | | /* wLength */ 0, |
395 | | USB_TIMEOUT); |
396 | | |
397 | | if (status != 0) { |
| 394 | int ret; |
| 395 | ret = usb_ingenic_ops(ingenic_dev, VR_CONFIGURATION, ops); |
| 396 | |
| 397 | if (ret != 0) { |
398 | 398 | fprintf(stderr, "Error - " |
399 | | "can't init Ingenic configration: %i\n", status); |
400 | | return -1; |
| 399 | "can't init Ingenic configration: %d\n", ret); |
401 | 400 | } |
402 | 401 | |
403 | | return 1; |
| 402 | return ret; |
404 | 403 | } |
405 | 404 | |
406 | 405 | int usb_ingenic_sdram_ops(struct ingenic_dev *ingenic_dev, int ops) |
407 | 406 | { |
408 | | int status; |
409 | | status = usb_control_msg(ingenic_dev->usb_handle, |
410 | | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
411 | | /* bRequest */ VR_SDRAM_OPS, |
412 | | /* wValue */ ops, |
413 | | /* wIndex */ 0, |
414 | | /* Data */ 0, |
415 | | /* wLength */ 0, |
416 | | USB_TIMEOUT); |
417 | | |
418 | | if (status != 0) { |
| 407 | int ret; |
| 408 | |
| 409 | ret = usb_ingenic_ops(ingenic_dev, VR_SDRAM_OPS, ops); |
| 410 | |
| 411 | if (ret != 0) { |
419 | 412 | fprintf(stderr, "Error - " |
420 | | "Device can't load file to sdram: %i\n", status); |
421 | | return -1; |
| 413 | "Device can't load file to sdram: %d\n", ret); |
422 | 414 | } |
423 | 415 | |
424 | | return 1; |
| 416 | return ret; |
425 | 417 | } |
usbboot/src/nand.c |
10 | 10 | #include "ingenic_usb.h" |
11 | 11 | #include "usb_boot_defines.h" |
12 | 12 | |
13 | | extern struct hand hand; |
14 | | |
15 | 13 | #define NAND_OP(idx, op, mode) (((mode << 12) & 0xf000) | ((idx << 4) & 0xff0) | op) |
16 | 14 | |
17 | 15 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) |
... | ... | |
22 | 20 | "without oob", |
23 | 21 | }; |
24 | 22 | |
25 | | static int error_check(const char *org, const char *obj, unsigned int size) |
| 23 | static int error_check(const char *a, const char *b, unsigned int size) |
26 | 24 | { |
27 | 25 | unsigned int i; |
| 26 | const unsigned char *org = (const unsigned char *)a; |
| 27 | const unsigned char *obj= (const unsigned char *)b; |
| 28 | |
| 29 | |
28 | 30 | printf("Comparing %d bytes - ", size); |
29 | 31 | for (i = 0; i < size; i++) { |
30 | 32 | if (org[i] != obj[i]) { |
... | ... | |
65 | 67 | (void)nand_idx; |
66 | 68 | |
67 | 69 | if (usb_get_ingenic_cpu(dev) < 3) { |
68 | | printf("Device unboot! Boot it first!\n"); |
69 | | return -1; |
| 70 | fprintf(stderr, "Device unboot! Boot it first!\n"); |
| 71 | return -ENODEV; |
70 | 72 | } |
71 | 73 | printf("Mark bad block : %d\n", block); |
72 | 74 | usb_send_data_address_to_ingenic(dev, block); |
... | ... | |
75 | 77 | printf("Mark bad block at %d\n",((ret[3] << 24) | |
76 | 78 | (ret[2] << 16) | |
77 | 79 | (ret[1] << 8) | |
78 | | (ret[0] << 0)) / hand.nand_ppb); |
| 80 | (ret[0] << 0)) / dev->config.nand_ppb); |
79 | 81 | |
80 | 82 | return 0; |
81 | 83 | } |
... | ... | |
91 | 93 | |
92 | 94 | printf("Writing NAND page %u len %u...\n", start_page, length); |
93 | 95 | if (length > (unsigned int)MAX_TRANSFER_SIZE) { |
94 | | printf("Buffer size too long!\n"); |
95 | | return -ENOMEM; |
| 96 | fprintf(stderr, "Buffer size too long!\n"); |
| 97 | return -EINVAL; |
96 | 98 | } |
97 | 99 | |
98 | 100 | if (usb_get_ingenic_cpu(dev) < 3) { |
99 | | printf("Device unboot! Boot it first!\n"); |
| 101 | fprintf(stderr, "Device unboot! Boot it first!\n"); |
100 | 102 | return -ENODEV; |
101 | 103 | } |
102 | 104 | usb_send_data_to_ingenic(dev, data, length); |
103 | 105 | |
104 | 106 | if (mode == NO_OOB) |
105 | | page_num = DIV_ROUND_UP(length, hand.nand_ps); |
| 107 | page_num = DIV_ROUND_UP(length, dev->config.nand_ps); |
106 | 108 | else |
107 | | page_num = DIV_ROUND_UP(length, hand.nand_ps + hand.nand_os); |
| 109 | page_num = DIV_ROUND_UP(length, dev->config.nand_ps + dev->config.nand_os); |
108 | 110 | |
109 | 111 | op = NAND_OP(nand_idx, NAND_PROGRAM, mode); |
110 | 112 | |
... | ... | |
117 | 119 | length, start_page, page_num); |
118 | 120 | |
119 | 121 | switch(mode) { |
120 | | case NAND_READ: |
| 122 | case NO_OOB: |
121 | 123 | op = NAND_OP(nand_idx, NAND_READ, NO_OOB); |
122 | 124 | break; |
123 | | case NAND_READ_OOB: |
124 | | op = NAND_OP(nand_idx, NAND_READ_OOB, 0); |
125 | | break; |
126 | | case NAND_READ_RAW: |
127 | | op = NAND_OP(nand_idx, NAND_READ_RAW, NO_OOB); |
| 125 | default: |
| 126 | op = NAND_OP(nand_idx, NAND_READ_RAW, OOB_ECC); |
128 | 127 | break; |
129 | 128 | } |
130 | 129 | |
... | ... | |
135 | 134 | (ret[0] << 0); |
136 | 135 | |
137 | 136 | if (start_page < 1 && |
138 | | hand.nand_ps == 4096 && |
139 | | hand.fw_args.cpu_id == 0x4740) { |
| 137 | dev->config.nand_ps == 4096 && |
| 138 | dev->config.fw_args.cpu_id == 0x4740) { |
140 | 139 | printf("no check! End at Page: %d\n", cur_page); |
141 | 140 | } |
142 | 141 | |
143 | 142 | if (!error_check(data, read_back_buf, length)) { |
144 | 143 | // tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page? |
145 | 144 | // tbd: why do we only mark a block as bad if the last page in the block was written? |
146 | | if (cur_page % hand.nand_ppb == 0) |
147 | | nand_markbad(dev, nand_idx, (cur_page - 1) / hand.nand_ppb); |
| 145 | if (cur_page % dev->config.nand_ppb == 0) |
| 146 | nand_markbad(dev, nand_idx, (cur_page - 1) / dev->config.nand_ppb); |
148 | 147 | } |
149 | 148 | |
150 | 149 | printf("End at Page: %d\n", cur_page); |
... | ... | |
161 | 160 | static char ret[8]; |
162 | 161 | |
163 | 162 | if (start_block > (unsigned int)NAND_MAX_BLK_NUM) { |
164 | | printf("Start block number overflow!\n"); |
165 | | return -1; |
| 163 | fprintf(stderr, "Start block number overflow!\n"); |
| 164 | return -EINVAL; |
166 | 165 | } |
167 | 166 | if (num_blocks > (unsigned int)NAND_MAX_BLK_NUM) { |
168 | | printf("Length block number overflow!\n"); |
169 | | return -1; |
| 167 | fprintf(stderr, "Length block number overflow!\n"); |
| 168 | return -EINVAL; |
170 | 169 | } |
171 | 170 | |
172 | 171 | if (usb_get_ingenic_cpu(dev) < 3) { |
173 | | printf("Device unboot! Boot it first!\n"); |
174 | | return -1; |
| 172 | fprintf(stderr, "Device unboot! Boot it first!\n"); |
| 173 | return -ENODEV; |
175 | 174 | } |
176 | 175 | |
177 | 176 | printf("Erasing No.%d device No.%d flash (start_blk %u blk_num %u)......\n", |
... | ... | |
187 | 186 | printf("Finish!"); |
188 | 187 | |
189 | 188 | end_block = ((ret[3] << 24) | (ret[2] << 16) | |
190 | | (ret[1] << 8) | (ret[0] << 0)) / hand.nand_ppb; |
| 189 | (ret[1] << 8) | (ret[0] << 0)) / dev->config.nand_ppb; |
191 | 190 | printf("Return: %02x %02x %02x %02x %02x %02x %02x %02x (position %d)\n", |
192 | 191 | ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7], end_block); |
193 | | if (!hand.nand_force_erase) { |
| 192 | if (!dev->config.nand_force_erase) { |
194 | 193 | /* not force erase, show bad block infomation */ |
195 | 194 | printf("There are marked bad blocks: %d\n", |
196 | 195 | end_block - start_block - num_blocks ); |
... | ... | |
217 | 216 | if (status < 0) { |
218 | 217 | fprintf(stderr, "Error - can't get file size from '%s': %s\n", |
219 | 218 | filename, strerror(errno)); |
220 | | return -1; |
| 219 | return -EEXIST; |
221 | 220 | } |
222 | 221 | flen = fstat.st_size; |
223 | 222 | |
... | ... | |
225 | 224 | if (fd < 0) { |
226 | 225 | fprintf(stderr, "Error - can't open file '%s': %s\n", |
227 | 226 | filename, strerror(errno)); |
228 | | return -1; |
| 227 | return errno; |
229 | 228 | } |
230 | 229 | |
231 | 230 | printf("Programing No.%d device, flen %d, start page %d...\n", 0, |
... | ... | |
233 | 232 | |
234 | 233 | /* printf("length %d flen %d\n", n_in.length, flen); */ |
235 | 234 | if (mode == NO_OOB) |
236 | | transfer_size = (hand.nand_ppb * hand.nand_ps); |
| 235 | transfer_size = (dev->config.nand_ppb * dev->config.nand_ps); |
237 | 236 | else |
238 | | transfer_size = (hand.nand_ppb * (hand.nand_ps + hand.nand_os)); |
| 237 | transfer_size = (dev->config.nand_ppb * (dev->config.nand_ps + |
| 238 | dev->config.nand_os)); |
239 | 239 | |
240 | | start_block = start_page / hand.nand_ppb; |
| 240 | start_block = start_page / dev->config.nand_ppb; |
241 | 241 | num_blocks = flen / (transfer_size - 1) + 1; |
242 | 242 | |
243 | 243 | if (nand_erase(dev, nand_idx, start_block, num_blocks)) |
... | ... | |
247 | 247 | j = flen % transfer_size; |
248 | 248 | |
249 | 249 | printf("Size to send %d, transfer_size %d\n", flen, transfer_size); |
250 | | printf("Image type : %s\n", IMAGE_TYPE[mode]); |
| 250 | /* printf("Image type : %s\n", IMAGE_TYPE[mode]);*/ |
251 | 251 | printf("It will cause %d times buffer transfer.\n", j == 0 ? m : m + 1); |
252 | 252 | |
253 | 253 | if (mode == NO_OOB) |
254 | | page_num = transfer_size / hand.nand_ps; |
| 254 | page_num = transfer_size / dev->config.nand_ps; |
255 | 255 | else |
256 | | page_num = transfer_size / (hand.nand_ps + hand.nand_os); |
| 256 | page_num = transfer_size / (dev->config.nand_ps + dev->config.nand_os); |
257 | 257 | |
258 | 258 | |
259 | 259 | offset = 0; |
... | ... | |
269 | 269 | if (nand_program_check(dev, nand_idx, start_page, code_buf, code_len, mode) == -1) |
270 | 270 | goto close; |
271 | 271 | |
272 | | /* if (start_page - nand_in->start > hand.nand_ppb) |
| 272 | /* if (start_page - nand_in->start > dev->config.nand_ppb) |
273 | 273 | printf("Skip a old bad block !\n");*/ |
274 | 274 | |
275 | 275 | offset += code_len ; |
... | ... | |
277 | 277 | |
278 | 278 | if (j) { |
279 | 279 | code_len = j; |
280 | | if (j % hand.nand_ps) |
281 | | j += hand.nand_ps - (j % hand.nand_ps); |
| 280 | if (j % dev->config.nand_ps) |
| 281 | j += dev->config.nand_ps - (j % dev->config.nand_ps); |
282 | 282 | memset(code_buf, 0, j); /* set all to null */ |
283 | 283 | |
284 | 284 | status = read(fd, code_buf, code_len); |
... | ... | |
293 | 293 | goto close; |
294 | 294 | |
295 | 295 | /* |
296 | | if (start_page - nand_in->start > hand.nand_ppb) |
| 296 | if (start_page - nand_in->start > dev->config.nand_ppb) |
297 | 297 | printf("Skip a old bad block !"); |
298 | 298 | */ |
299 | 299 | } |
... | ... | |
305 | 305 | int nand_prog(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_page, |
306 | 306 | const char *filename, int mode) |
307 | 307 | { |
308 | | if (hand.nand_plane > 1) |
| 308 | if (dev->config.nand_plane > 1) |
309 | 309 | printf("ERROR"); |
310 | 310 | else |
311 | 311 | nand_program_file(dev, nand_idx, start_page, filename, mode); |
... | ... | |
316 | 316 | int nand_query(struct ingenic_dev *dev, uint8_t nand_idx) |
317 | 317 | { |
318 | 318 | uint16_t op; |
319 | | char ret[8]; |
| 319 | char ret[8] = {0,0,0,0,0,0,0,0}; |
| 320 | int ret2; |
320 | 321 | |
321 | 322 | if (usb_get_ingenic_cpu(dev) < 3) { |
322 | | printf("Device unboot! Boot it first!\n"); |
323 | | return -1; |
| 323 | fprintf(stderr, "Device unboot! Boot it first!\n"); |
| 324 | return -ENODEV; |
324 | 325 | } |
325 | 326 | |
326 | 327 | printf("ID of No.%u device No.%u flash: \n", 0, nand_idx); |
... | ... | |
328 | 329 | op = NAND_OP(nand_idx, NAND_QUERY, 0); |
329 | 330 | |
330 | 331 | usb_ingenic_nand_ops(dev, op); |
331 | | usb_read_data_from_ingenic(dev, ret, ARRAY_SIZE(ret)); |
| 332 | ret2 = usb_read_data_from_ingenic(dev, ret, ARRAY_SIZE(ret)); |
| 333 | |
| 334 | if (ret2 < 0) |
| 335 | return ret2; |
| 336 | |
332 | 337 | printf("Vendor ID :0x%x \n", (unsigned char)ret[0]); |
333 | 338 | printf("Product ID :0x%x \n", (unsigned char)ret[1]); |
334 | 339 | printf("Chip ID :0x%x \n", (unsigned char)ret[2]); |
... | ... | |
342 | 347 | } |
343 | 348 | |
344 | 349 | int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode, |
345 | | uint32_t start_page, uint32_t length, uint32_t ram_addr) |
| 350 | uint32_t start_page, uint32_t length, uint32_t ram_addr, |
| 351 | nand_read_cb_t callback, void *userdata) |
346 | 352 | { |
347 | 353 | uint16_t op; |
348 | 354 | uint32_t page; |
... | ... | |
350 | 356 | uint32_t pages_per_request; |
351 | 357 | char ret[8]; |
352 | 358 | char *buf; |
353 | | int fd; |
| 359 | int ret2; |
354 | 360 | |
355 | 361 | if (start_page > NAND_MAX_PAGE_NUM) { |
356 | | printf("Page number overflow!\n"); |
357 | | return -1; |
| 362 | fprintf(stderr, "Page number overflow!\n"); |
| 363 | return -EINVAL; |
358 | 364 | } |
359 | 365 | if (usb_get_ingenic_cpu(dev) < 3) { |
360 | | printf("Device unboot! Boot it first!\n"); |
361 | | return -1; |
| 366 | fprintf(stderr, "Device unboot! Boot it first!\n"); |
| 367 | return -EINVAL; |
362 | 368 | } |
363 | 369 | if (nand_idx >= 16) |
364 | | return -1; |
| 370 | return -EINVAL; |
365 | 371 | |
366 | 372 | printf("Reading from No.%u device No.%u flash....\n", 0, nand_idx); |
367 | 373 | |
... | ... | |
374 | 380 | op = NAND_OP(nand_idx, NAND_READ_OOB, 0); |
375 | 381 | break; |
376 | 382 | case NAND_READ_RAW: |
377 | | op = NAND_OP(nand_idx, NAND_READ_RAW, NO_OOB); |
| 383 | op = NAND_OP(nand_idx, NAND_READ_RAW, OOB_ECC); |
378 | 384 | break; |
379 | 385 | case NAND_READ_TO_RAM: |
380 | 386 | op = NAND_OP(nand_idx, NAND_READ_TO_RAM, NO_OOB); |
381 | | printf("Reading nand to RAM: 0x%x\n", ram_addr); |
382 | 387 | usb_ingenic_start(dev, VR_PROGRAM_START1, ram_addr); |
383 | 388 | break; |
384 | 389 | default: |
385 | | printf("unknow mode!\n"); |
386 | | return -1; |
| 390 | return -EINVAL; |
387 | 391 | } |
388 | 392 | |
389 | 393 | pages_per_request = 1; |
390 | | request_length = hand.nand_ps * pages_per_request; |
| 394 | if (mode == NAND_READ_OOB || mode == NAND_READ_RAW) |
| 395 | request_length = (dev->config.nand_ps + dev->config.nand_os) * pages_per_request; |
| 396 | else |
| 397 | request_length = dev->config.nand_ps * pages_per_request; |
391 | 398 | |
392 | 399 | page = start_page; |
393 | 400 | |
394 | 401 | buf = malloc(request_length); |
395 | 402 | |
396 | | fd = open("/tmp/dump.bin", O_WRONLY | O_TRUNC | O_CREAT); |
397 | | if (fd < 0) { |
398 | | printf("Failed to open file\n"); |
399 | | return errno; |
400 | | } |
401 | | |
402 | 403 | while (length > 0) { |
403 | 404 | if (request_length > length) |
404 | 405 | request_length = length; |
405 | 406 | |
406 | 407 | nand_read_pages(dev, page, pages_per_request, buf, request_length, op, ret); |
407 | 408 | |
408 | | write(fd, buf, request_length); |
| 409 | ret2 = callback(userdata, buf, request_length); |
| 410 | if (ret2) |
| 411 | return ret2; |
409 | 412 | |
410 | 413 | length -= request_length; |
411 | 414 | page += pages_per_request; |
412 | 415 | } |
413 | | close(fd); |
| 416 | |
414 | 417 | printf("Operation end position : %u \n", |
415 | 418 | (ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0)); |
416 | 419 | free(buf); |
417 | 420 | |
418 | | return 1; |
| 421 | return 0; |
419 | 422 | } |