blob: fe0f891ee6fb2b620b022fb1e4b4a94d80a913b4 [file] [log] [blame]
Anton Staafb2647882014-09-17 15:13:43 -07001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright 2014, Google Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following disclaimer
15 * in the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Google Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Alternatively, this software may be distributed under the terms of the
34 * GNU General Public License ("GPL") version 2 as published by the Free
35 * Software Foundation.
36 */
37
38/*
39 * This SPI flash programming interface is designed to talk to a Chromium OS
40 * device over a Raiden USB connection. The USB connection is routed to a
41 * microcontroller running an image compiled from:
42 *
43 * https://chromium.googlesource.com/chromiumos/platform/ec
44 *
45 * The protocol for the USB-SPI bridge is documented in the following file in
46 * that respository:
47 *
48 * chip/stm32/usb_spi.c
49 */
50
51#include <stdio.h>
52#include <string.h>
53#include "programmer.h"
54#include "spi.h"
55
56#include <libusb.h>
57#include <stdlib.h>
58
59#define GOOGLE_VID 0x18D1
60#define GOOGLE_RAIDEN_PID 0x500f
Anton Staafb049ae32014-10-21 10:30:37 -070061#define GOOGLE_RAIDEN_ENDPOINT 3
Anton Staafb2647882014-09-17 15:13:43 -070062
Anton Staafd27536d2014-09-30 08:10:17 -070063#define PACKET_HEADER_SIZE 2
64#define MAX_PACKET_SIZE 64
Anton Staafb2647882014-09-17 15:13:43 -070065
66/*
67 * This timeout is so large because the Raiden SPI timeout is 800ms.
68 */
69#define TRANSFER_TIMEOUT_MS 1000
70
71#define CHECK(expression, string...) \
72 ({ \
73 int error__ = (expression); \
74 \
75 if (error__ != 0) { \
76 msg_perr("Raiden: libusb error: %s:%d %s\n", \
77 __FILE__, \
78 __LINE__, \
79 libusb_error_name(error__)); \
80 msg_perr(string); \
81 return 0x20000 | -error__; \
82 } \
83 })
84
85static libusb_context *context = NULL;
86static libusb_device_handle *device = NULL;
Anton Staafd27536d2014-09-30 08:10:17 -070087static uint8_t endpoint = GOOGLE_RAIDEN_ENDPOINT;
Anton Staafb2647882014-09-17 15:13:43 -070088
89static int send_command(unsigned int write_count,
90 unsigned int read_count,
91 const unsigned char *write_buffer,
92 unsigned char *read_buffer)
93{
94 uint8_t buffer[MAX_PACKET_SIZE];
95 int transferred;
96
97 if (write_count > MAX_PACKET_SIZE - PACKET_HEADER_SIZE) {
98 msg_perr("Raiden: invalid write_count of %d\n", write_count);
99 return SPI_INVALID_LENGTH;
100 }
101
102 if (read_count > MAX_PACKET_SIZE - PACKET_HEADER_SIZE) {
103 msg_perr("Raiden: invalid read_count of %d\n", read_count);
104 return SPI_INVALID_LENGTH;
105 }
106
107 buffer[0] = write_count;
108 buffer[1] = read_count;
109
110 memcpy(buffer + PACKET_HEADER_SIZE, write_buffer, write_count);
111
112 CHECK(libusb_bulk_transfer(device,
Anton Staafb049ae32014-10-21 10:30:37 -0700113 LIBUSB_ENDPOINT_OUT | endpoint,
Anton Staafb2647882014-09-17 15:13:43 -0700114 buffer,
115 write_count + PACKET_HEADER_SIZE,
116 &transferred,
117 TRANSFER_TIMEOUT_MS),
118 "Raiden: OUT transfer failed\n"
119 " write_count = %d\n"
120 " read_count = %d\n",
121 write_count,
122 read_count);
123
124 if (transferred != write_count + PACKET_HEADER_SIZE) {
125 msg_perr("Raiden: Write failure (wrote %d, expected %d)\n",
126 transferred, write_count + PACKET_HEADER_SIZE);
127 return 0x10001;
128 }
129
130 CHECK(libusb_bulk_transfer(device,
Anton Staafb049ae32014-10-21 10:30:37 -0700131 LIBUSB_ENDPOINT_IN | endpoint,
Anton Staafb2647882014-09-17 15:13:43 -0700132 buffer,
133 read_count + PACKET_HEADER_SIZE,
134 &transferred,
135 TRANSFER_TIMEOUT_MS),
136 "Raiden: IN transfer failed\n"
137 " write_count = %d\n"
138 " read_count = %d\n",
139 write_count,
140 read_count);
141
142 if (transferred != read_count + PACKET_HEADER_SIZE) {
143 msg_perr("Raiden: Read failure (read %d, expected %d)\n",
144 transferred, read_count + PACKET_HEADER_SIZE);
145 return 0x10002;
146 }
147
148 memcpy(read_buffer, buffer + PACKET_HEADER_SIZE, read_count);
149
150 return buffer[0] | (buffer[1] << 8);
151}
152
153/*
154 * Unfortunately there doesn't seem to be a way to specify the maximum number
155 * of bytes that your SPI device can read/write, these values are the maximum
156 * data chunk size that flashrom will package up with an additional four bytes
157 * of command for the flash device, resulting in a 62 byte packet, that we then
158 * add two bytes to in either direction, making our way up to the 64 byte
159 * maximum USB packet size for the device.
160 *
161 * The largest command that flashrom generates is the byte program command, so
162 * we use that command header maximum size here. The definition of
163 * JEDEC_BYTE_PROGRAM_OUTSIZE includes enough space for a single byte of data
164 * to write, so we add one byte of space back.
165 */
166#define MAX_DATA_SIZE (MAX_PACKET_SIZE - \
167 PACKET_HEADER_SIZE - \
168 JEDEC_BYTE_PROGRAM_OUTSIZE + \
169 1)
170
171static const struct spi_programmer spi_programmer_raiden_debug = {
172 .type = SPI_CONTROLLER_RAIDEN_DEBUG,
173 .max_data_read = MAX_DATA_SIZE,
174 .max_data_write = MAX_DATA_SIZE,
175 .command = send_command,
176 .multicommand = default_spi_send_multicommand,
177 .read = default_spi_read,
178 .write_256 = default_spi_write_256,
179};
180
Anton Staafd27536d2014-09-30 08:10:17 -0700181static long int get_parameter(char const * name, long int default_value)
182{
183 char * string = extract_programmer_param(name);
184 long int value = default_value;
185
186 if (string)
187 value = strtol(string, NULL, 0);
188
189 free(string);
190
191 return value;
192}
193
Anton Staafb2647882014-09-17 15:13:43 -0700194int raiden_debug_spi_init(void)
195{
Anton Staafd27536d2014-09-30 08:10:17 -0700196 uint16_t vid = get_parameter("vid", GOOGLE_VID);
197 uint16_t pid = get_parameter("pid", GOOGLE_RAIDEN_PID);
198
Anton Staafb2647882014-09-17 15:13:43 -0700199 CHECK(libusb_init(&context), "Raiden: libusb_init failed\n");
200
Anton Staafd27536d2014-09-30 08:10:17 -0700201 endpoint = get_parameter("endpoint", GOOGLE_RAIDEN_ENDPOINT);
202 device = libusb_open_device_with_vid_pid(context, vid, pid);
Anton Staafb2647882014-09-17 15:13:43 -0700203
204 if (device == NULL) {
Anton Staafd27536d2014-09-30 08:10:17 -0700205 msg_perr("Unable to find device 0x%04x:0x%04x\n", vid, pid);
Anton Staafb2647882014-09-17 15:13:43 -0700206 return 1;
207 }
208
209 CHECK(libusb_set_auto_detach_kernel_driver(device, 1), "");
210 CHECK(libusb_claim_interface(device, 1), "");
211
212 register_spi_programmer(&spi_programmer_raiden_debug);
213
214 return 0;
215}