blob: 4b6200fa9717c1429baff6ca952996471486453f [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
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,
113 LIBUSB_ENDPOINT_OUT |
114 GOOGLE_RAIDEN_ENDPOINT,
115 buffer,
116 write_count + PACKET_HEADER_SIZE,
117 &transferred,
118 TRANSFER_TIMEOUT_MS),
119 "Raiden: OUT transfer failed\n"
120 " write_count = %d\n"
121 " read_count = %d\n",
122 write_count,
123 read_count);
124
125 if (transferred != write_count + PACKET_HEADER_SIZE) {
126 msg_perr("Raiden: Write failure (wrote %d, expected %d)\n",
127 transferred, write_count + PACKET_HEADER_SIZE);
128 return 0x10001;
129 }
130
131 CHECK(libusb_bulk_transfer(device,
132 LIBUSB_ENDPOINT_IN |
133 GOOGLE_RAIDEN_ENDPOINT,
134 buffer,
135 read_count + PACKET_HEADER_SIZE,
136 &transferred,
137 TRANSFER_TIMEOUT_MS),
138 "Raiden: IN transfer failed\n"
139 " write_count = %d\n"
140 " read_count = %d\n",
141 write_count,
142 read_count);
143
144 if (transferred != read_count + PACKET_HEADER_SIZE) {
145 msg_perr("Raiden: Read failure (read %d, expected %d)\n",
146 transferred, read_count + PACKET_HEADER_SIZE);
147 return 0x10002;
148 }
149
150 memcpy(read_buffer, buffer + PACKET_HEADER_SIZE, read_count);
151
152 return buffer[0] | (buffer[1] << 8);
153}
154
155/*
156 * Unfortunately there doesn't seem to be a way to specify the maximum number
157 * of bytes that your SPI device can read/write, these values are the maximum
158 * data chunk size that flashrom will package up with an additional four bytes
159 * of command for the flash device, resulting in a 62 byte packet, that we then
160 * add two bytes to in either direction, making our way up to the 64 byte
161 * maximum USB packet size for the device.
162 *
163 * The largest command that flashrom generates is the byte program command, so
164 * we use that command header maximum size here. The definition of
165 * JEDEC_BYTE_PROGRAM_OUTSIZE includes enough space for a single byte of data
166 * to write, so we add one byte of space back.
167 */
168#define MAX_DATA_SIZE (MAX_PACKET_SIZE - \
169 PACKET_HEADER_SIZE - \
170 JEDEC_BYTE_PROGRAM_OUTSIZE + \
171 1)
172
173static const struct spi_programmer spi_programmer_raiden_debug = {
174 .type = SPI_CONTROLLER_RAIDEN_DEBUG,
175 .max_data_read = MAX_DATA_SIZE,
176 .max_data_write = MAX_DATA_SIZE,
177 .command = send_command,
178 .multicommand = default_spi_send_multicommand,
179 .read = default_spi_read,
180 .write_256 = default_spi_write_256,
181};
182
Anton Staafd27536d2014-09-30 08:10:17 -0700183static long int get_parameter(char const * name, long int default_value)
184{
185 char * string = extract_programmer_param(name);
186 long int value = default_value;
187
188 if (string)
189 value = strtol(string, NULL, 0);
190
191 free(string);
192
193 return value;
194}
195
Anton Staafb2647882014-09-17 15:13:43 -0700196int raiden_debug_spi_init(void)
197{
Anton Staafd27536d2014-09-30 08:10:17 -0700198 uint16_t vid = get_parameter("vid", GOOGLE_VID);
199 uint16_t pid = get_parameter("pid", GOOGLE_RAIDEN_PID);
200
Anton Staafb2647882014-09-17 15:13:43 -0700201 CHECK(libusb_init(&context), "Raiden: libusb_init failed\n");
202
Anton Staafd27536d2014-09-30 08:10:17 -0700203 endpoint = get_parameter("endpoint", GOOGLE_RAIDEN_ENDPOINT);
204 device = libusb_open_device_with_vid_pid(context, vid, pid);
Anton Staafb2647882014-09-17 15:13:43 -0700205
206 if (device == NULL) {
Anton Staafd27536d2014-09-30 08:10:17 -0700207 msg_perr("Unable to find device 0x%04x:0x%04x\n", vid, pid);
Anton Staafb2647882014-09-17 15:13:43 -0700208 return 1;
209 }
210
211 CHECK(libusb_set_auto_detach_kernel_driver(device, 1), "");
212 CHECK(libusb_claim_interface(device, 1), "");
213
214 register_spi_programmer(&spi_programmer_raiden_debug);
215
216 return 0;
217}