blob: c088a11888e88eaa7db09e5909656b1982ffdf29 [file] [log] [blame]
Stefan Reinauerc566d202015-08-25 09:52:42 -07001/*
2 * Copyright 2012-2015 Google Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Stefan Reinauerc566d202015-08-25 09:52:42 -070012 */
13
14#include <stdio.h>
15#include <string.h>
16#include <unistd.h>
17#include "em100.h"
18
19/* SPI flash related operations */
20
Stefan Reinauerf70ff252019-11-13 18:58:16 -080021uint32_t get_spi_flash_id(struct em100 *em100)
Stefan Reinauerc566d202015-08-25 09:52:42 -070022{
23 unsigned char cmd[16];
24 unsigned char data[512];
25 memset(cmd, 0, 16);
26 cmd[0] = 0x30; /* Get SPI flash ID */
27 if (!send_cmd(em100->dev, cmd)) {
28 return 0;
29 }
30 int len = get_response(em100->dev, data, 512);
31 if (len == 3) {
32 int id = (data[0] << 16) | (data[1] << 8) | data[2];
33 return id;
34 }
35 return 0;
36}
37
38int erase_spi_flash(struct em100 *em100)
39{
40 unsigned char cmd[16];
41 memset(cmd, 0, 16);
42 cmd[0] = 0x31; /* Erase SPI flash */
43 if (!send_cmd(em100->dev, cmd)) {
44 return 0;
45 }
46 /* Specification says to wait 5s before
47 * issuing another USB command
48 */
49 sleep(5);
50 return 1;
51}
52
53int poll_spi_flash_status(struct em100 *em100)
54{
55 unsigned char cmd[16];
56 unsigned char data[1];
57 memset(cmd, 0, 16);
58 cmd[0] = 0x32; /* Poll SPI flash status */
59 if (!send_cmd(em100->dev, cmd)) {
60 return 0;
61 }
62 int len = get_response(em100->dev, data, 1);
63 if ((len == 1) && (data[0] == 1)) {
64 /* ready */
65 return 1;
66 }
67 /* busy (or read unsuccessful) */
68 return 0;
69}
70
71/**
72 * read_spi_flash_page: fetch SPI flash page
73 * @param em100: initialized em100 device structure
74 *
Stefan Reinauer79533882019-11-22 00:57:29 -080075 * out(16 bytes): 0x33 address address address .. 0
Stefan Reinauerc566d202015-08-25 09:52:42 -070076 * in(len + 255 bytes): 0xff ?? serno_lo serno_hi ?? ?? .. ??
77 */
Stefan Reinauer79533882019-11-22 00:57:29 -080078int read_spi_flash_page(struct em100 *em100, int address, unsigned char *blk)
Stefan Reinauerc566d202015-08-25 09:52:42 -070079{
80 unsigned char cmd[16];
81 unsigned char data[256];
82 memset(cmd, 0, 16);
Stefan Reinauerae4dcd02015-08-28 16:26:03 -070083 cmd[0] = 0x33; /* read SPI flash page */
Stefan Reinauer79533882019-11-22 00:57:29 -080084 cmd[1] = (address >> 16) & 0xff;
85 cmd[2] = (address >> 8) & 0xff;
86 cmd[3] = address & 0xff;
Stefan Reinauerc566d202015-08-25 09:52:42 -070087 if (!send_cmd(em100->dev, cmd)) {
88 return 0;
89 }
90 int len = get_response(em100->dev, data, 256);
91
92 if (len == 256) {
93 memcpy(blk, data, 256);
94 return 1;
95 }
96 return 0;
97}
98
Stefan Reinauer65559f12015-08-28 16:28:51 -070099int write_spi_flash_page(struct em100 *em100, int address, unsigned char *data)
Stefan Reinauerc566d202015-08-25 09:52:42 -0700100{
101 int length = 256;
102 int actual;
Stefan Reinauer79533882019-11-22 00:57:29 -0800103 int bytes_sent = 0;
Stefan Reinauerc566d202015-08-25 09:52:42 -0700104 int bytes_left;
105 unsigned char cmd[16];
106 memset(cmd, 0, 16);
107 cmd[0] = 0x34; /* host-to-em100 eeprom data */
Stefan Reinauer738812e2015-08-28 20:00:41 -0700108 cmd[1] = (address >> 16) & 0xff;
109 cmd[2] = (address >> 8) & 0xff;
110 cmd[3] = address & 0xff;
Stefan Reinauerc566d202015-08-25 09:52:42 -0700111
112 if (!send_cmd(em100->dev, cmd)) {
Stefan Reinauer54474a62015-08-28 16:27:30 -0700113 printf("Error: Could not initiate host-to-EM100 transfer.\n");
Stefan Reinauerc566d202015-08-25 09:52:42 -0700114 return 0;
115 }
116
117 while ( bytes_sent < length) {
118 actual = 0;
119
120 bytes_left = length - bytes_sent;
121
122 libusb_bulk_transfer(em100->dev, 1 | LIBUSB_ENDPOINT_OUT,
Martin Rothb54d6ba2015-09-29 14:49:37 -0600123 data + bytes_sent, bytes_left, &actual,
124 BULK_SEND_TIMEOUT);
Stefan Reinauerc566d202015-08-25 09:52:42 -0700125 bytes_sent += actual;
126 if (actual < bytes_left) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600127 printf("Tried sending %d bytes, sent %d\n", bytes_left,
128 actual);
Stefan Reinauerc566d202015-08-25 09:52:42 -0700129 break;
130 }
Stefan Reinauerc566d202015-08-25 09:52:42 -0700131 }
132
Stefan Reinauer8421b712015-08-28 20:01:34 -0700133 if (bytes_sent != length)
134 printf ("SPI transfer failed\n");
135
Stefan Reinauerc566d202015-08-25 09:52:42 -0700136 return (bytes_sent == length);
137}
138
Stefan Reinauer40cba332015-08-28 20:03:05 -0700139int unlock_spi_flash(struct em100 *em100)
140{
141 unsigned char cmd[16];
142 memset(cmd, 0, 16);
143 cmd[0] = 0x36; /* Unlock SPI flash */
144 if (!send_cmd(em100->dev, cmd)) {
145 return 0;
146 }
147 /* Specification says to wait 5s before
148 * issuing another USB command
149 */
150 return 1;
151}
152
153/* Erase SPI flash sector
154 * There are 32 sectors 64kB each
155 *
156 */
157int erase_spi_flash_sector(struct em100 *em100, unsigned int sector)
158{
159 unsigned char cmd[16];
160
161 if (sector > 31) {
162 printf("Can't erase sector at address %x\n", sector << 16);
163 return 0;
164 }
165
166 memset(cmd, 0, 16);
167 cmd[0] = 0x37; /* Erase SPI flash sector */
168 cmd[1] = sector;
169 if (!send_cmd(em100->dev, cmd)) {
170 return 0;
171 }
172 /* Specification says to wait 5s before
173 * issuing another USB command
174 */
175 return 1;
176
177}
178
179
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700180/* SPI Hyper Terminal related operations */
181
182/* SPI Hyper Terminal resources:
183 *
184 * FIFOs:
185 * dFIFO 64 bytes Transfer information from host to application (EM100Pro)
186 * uFIFO 512 bytes Transfer information from application to host
187 *
188 * Registers:
189 * 0 1 byte RW FIFO overflow, pause/start emulation, FIFO valid data
190 * 1 1 byte RO length of valid data in dFIFO
191 * 2 1 byte RO length of valid data in uFIFO (?? in 1 byte ??)
192 * 3 1 byte RO EM100 identification on SPI bus to differentiate from
193 * real SPI flash
194 * 4 1 byte RW uFIFO data format to indicate to the software how to
195 * read the data
196 */
Stefan Reinauerc566d202015-08-25 09:52:42 -0700197
198/**
199 * read_ht_register: Read HT registers
200 * @param em100: initialized em100 device structure
201 *
202 * out(2 bytes): 0x50 RegAddr .. 0
203 * in(len + 1 byte): 0x02 val
204 */
205int read_ht_register(struct em100 *em100, int reg, uint8_t *val)
206{
207 unsigned char cmd[16];
208 unsigned char data[2];
209
210 memset(cmd, 0, 16);
211 cmd[0] = 0x50; /* read fpga register */
212 cmd[1] = reg;
213 if (!send_cmd(em100->dev, cmd)) {
214 return 0;
215 }
216 int len = get_response(em100->dev, data, 2);
217 if ((len == 2) && (data[0] == 1)) {
218 *val = data[1];
219 return 1;
220 }
221 return 0;
222}
223
224/**
225 * write_ht_register: Write HT registers
226 * @param em100: initialized em100 device structure
227 *
228 * out(3 bytes): 0x51 RegAddr Val .. 0
229 */
230int write_ht_register(struct em100 *em100, int reg, uint8_t val)
231{
232 unsigned char cmd[16];
233 memset(cmd, 0, 16);
234 cmd[0] = 0x51; /* write fpga registers */
235 cmd[1] = reg;
236 cmd[2] = val;
237 if (!send_cmd(em100->dev, cmd)) {
238 return 0;
239 }
240 return 1;
241}
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700242
Stefan Reinauer79533882019-11-22 00:57:29 -0800243int write_dfifo(struct em100 *em100, size_t length, unsigned int timeout,
Martin Rothb54d6ba2015-09-29 14:49:37 -0600244 unsigned char *blk)
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700245{
246 int actual;
Stefan Reinauer79533882019-11-22 00:57:29 -0800247 size_t bytes_sent = 0;
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700248 int bytes_left;
249 unsigned char cmd[16];
250 unsigned char data[512];
251
252 if (length > 512) { /* Really? Should be 64? */
Martin Rothb54d6ba2015-09-29 14:49:37 -0600253 printf("Error: Length of data to be written to dFIFO can't"
254 " be > 512\n");
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700255 return 0;
256 }
Stefan Reinauer1326af22019-11-21 10:53:30 -0800257 memcpy(data, blk, length);
258
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700259 memset(cmd, 0, 16);
260 cmd[0] = 0x52; /* write dFIFO */
261 cmd[1] = (length >> 8) & 0xff;
262 cmd[2] = length & 0xff;
263 cmd[3] = (timeout >> 8) & 0xff;
264 cmd[4] = timeout & 0xff;
265
266 if (!send_cmd(em100->dev, cmd)) {
267 printf("Error: Could not initiate host-to-EM100 transfer.\n");
268 return 0;
269 }
270
271 while ( bytes_sent < length) {
272 actual = 0;
273
274 bytes_left = length - bytes_sent;
275
276 libusb_bulk_transfer(em100->dev, 1 | LIBUSB_ENDPOINT_OUT,
Martin Rothb54d6ba2015-09-29 14:49:37 -0600277 data + bytes_sent, bytes_left, &actual,
278 BULK_SEND_TIMEOUT);
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700279 bytes_sent += actual;
280 if (actual < bytes_left) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600281 printf("Tried sending %d bytes, sent %d\n", bytes_left,
282 actual);
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700283 break;
284 }
285
Stefan Reinauer79533882019-11-22 00:57:29 -0800286 printf("Sent %zd bytes of %zd\n", bytes_sent, length);
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700287 }
288
289 printf ("Transfer %s\n",bytes_sent == length ? "Succeeded" : "Failed");
Alexander Eichner3cf88282020-04-16 21:44:28 +0200290 if (bytes_sent != length)
Stefan Reinauer79533882019-11-22 00:57:29 -0800291 printf("Warning: Sent %zd bytes, expected %zd\n",
Stefan Reinauerd2518982015-10-10 10:09:24 +0000292 bytes_sent, length);
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700293
294 int len = get_response(em100->dev, data, 512);
295
Alexander Eichner3cf88282020-04-16 21:44:28 +0200296 if (len == 2 && (((size_t)data[0] << 8) | data[1]) == length) {
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700297 return 1;
298 }
299 return 0;
300}
301
Stefan Reinauer79533882019-11-22 00:57:29 -0800302int read_ufifo(struct em100 *em100, size_t length, unsigned int timeout,
Martin Rothb54d6ba2015-09-29 14:49:37 -0600303 unsigned char *blk)
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700304{
305 unsigned char cmd[16];
306 unsigned char data[512];
Martin Rothdfdff3e2015-09-18 09:42:03 -0600307 unsigned char data2[2];
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700308
309 if (length > 512) {
Martin Rothb54d6ba2015-09-29 14:49:37 -0600310 printf("Error: Length of data to be read from uFIFO can't be"
311 " > 512\n");
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700312 return 0;
313 }
314 memset(cmd, 0, 16);
315 cmd[0] = 0x53; /* read uFIFO */
316 cmd[1] = (length >> 8) & 0xff;
317 cmd[2] = length & 0xff;
318 cmd[3] = (timeout >> 8) & 0xff;
319 cmd[4] = timeout & 0xff;
320 if (!send_cmd(em100->dev, cmd)) {
321 return 0;
322 }
Stefan Reinauer79533882019-11-22 00:57:29 -0800323 size_t len = get_response(em100->dev, data, 512);
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700324
Martin Rothdfdff3e2015-09-18 09:42:03 -0600325 /* get second response from read ufifo command */
326 get_response(em100->dev, data2, 2);
327
Stefan Reinauer42dfb822015-08-28 16:59:42 -0700328 if (len == length) {
329 memcpy(blk, data, length);
330 return 1;
331 }
332 return 0;
333}