blob: 5b86b53e16369e17d26fd012476cc7414cc4bc19 [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
61#define GOOGLE_RAIDEN_ENDPOINT 2
62
63#define PACKET_HEADER_SIZE 2
64#define MAX_PACKET_SIZE 64
65
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;
87
88static int send_command(unsigned int write_count,
89 unsigned int read_count,
90 const unsigned char *write_buffer,
91 unsigned char *read_buffer)
92{
93 uint8_t buffer[MAX_PACKET_SIZE];
94 int transferred;
95
96 if (write_count > MAX_PACKET_SIZE - PACKET_HEADER_SIZE) {
97 msg_perr("Raiden: invalid write_count of %d\n", write_count);
98 return SPI_INVALID_LENGTH;
99 }
100
101 if (read_count > MAX_PACKET_SIZE - PACKET_HEADER_SIZE) {
102 msg_perr("Raiden: invalid read_count of %d\n", read_count);
103 return SPI_INVALID_LENGTH;
104 }
105
106 buffer[0] = write_count;
107 buffer[1] = read_count;
108
109 memcpy(buffer + PACKET_HEADER_SIZE, write_buffer, write_count);
110
111 CHECK(libusb_bulk_transfer(device,
112 LIBUSB_ENDPOINT_OUT |
113 GOOGLE_RAIDEN_ENDPOINT,
114 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,
131 LIBUSB_ENDPOINT_IN |
132 GOOGLE_RAIDEN_ENDPOINT,
133 buffer,
134 read_count + PACKET_HEADER_SIZE,
135 &transferred,
136 TRANSFER_TIMEOUT_MS),
137 "Raiden: IN transfer failed\n"
138 " write_count = %d\n"
139 " read_count = %d\n",
140 write_count,
141 read_count);
142
143 if (transferred != read_count + PACKET_HEADER_SIZE) {
144 msg_perr("Raiden: Read failure (read %d, expected %d)\n",
145 transferred, read_count + PACKET_HEADER_SIZE);
146 return 0x10002;
147 }
148
149 memcpy(read_buffer, buffer + PACKET_HEADER_SIZE, read_count);
150
151 return buffer[0] | (buffer[1] << 8);
152}
153
154/*
155 * Unfortunately there doesn't seem to be a way to specify the maximum number
156 * of bytes that your SPI device can read/write, these values are the maximum
157 * data chunk size that flashrom will package up with an additional four bytes
158 * of command for the flash device, resulting in a 62 byte packet, that we then
159 * add two bytes to in either direction, making our way up to the 64 byte
160 * maximum USB packet size for the device.
161 *
162 * The largest command that flashrom generates is the byte program command, so
163 * we use that command header maximum size here. The definition of
164 * JEDEC_BYTE_PROGRAM_OUTSIZE includes enough space for a single byte of data
165 * to write, so we add one byte of space back.
166 */
167#define MAX_DATA_SIZE (MAX_PACKET_SIZE - \
168 PACKET_HEADER_SIZE - \
169 JEDEC_BYTE_PROGRAM_OUTSIZE + \
170 1)
171
172static const struct spi_programmer spi_programmer_raiden_debug = {
173 .type = SPI_CONTROLLER_RAIDEN_DEBUG,
174 .max_data_read = MAX_DATA_SIZE,
175 .max_data_write = MAX_DATA_SIZE,
176 .command = send_command,
177 .multicommand = default_spi_send_multicommand,
178 .read = default_spi_read,
179 .write_256 = default_spi_write_256,
180};
181
182int raiden_debug_spi_init(void)
183{
184 CHECK(libusb_init(&context), "Raiden: libusb_init failed\n");
185
186 device = libusb_open_device_with_vid_pid(context,
187 GOOGLE_VID,
188 GOOGLE_RAIDEN_PID);
189
190 if (device == NULL) {
191 msg_perr("Unable to find device 0x%04x:0x%04x\n",
192 GOOGLE_VID,
193 GOOGLE_RAIDEN_PID);
194 return 1;
195 }
196
197 CHECK(libusb_set_auto_detach_kernel_driver(device, 1), "");
198 CHECK(libusb_claim_interface(device, 1), "");
199
200 register_spi_programmer(&spi_programmer_raiden_debug);
201
202 return 0;
203}