1 /*
2 * Copyright (c) 2015 Brian Swetland
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9 #include <app.h>
10 #include <lk/err.h>
11 #include <lk/debug.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <printf.h>
15 #include <dev/udc.h>
16
17 #include <platform.h>
18 #include <arch/arm.h>
19 #include <kernel/thread.h>
20 #include <kernel/event.h>
21 #include <kernel/timer.h>
22
23 #include <platform/lpc43xx-gpio.h>
24
25 #define PIN_LED PIN(1,1)
26 #define GPIO_LED GPIO(0,8)
27
28 void spifi_init(void);
29 void spifi_page_program(u32 addr, u32 *ptr, u32 count);
30 void spifi_sector_erase(u32 addr);
31 int spifi_verify_erased(u32 addr, u32 count);
32 int spifi_verify_page(u32 addr, u32 *ptr);
33
34 static event_t txevt = EVENT_INITIAL_VALUE(txevt, 0, 0);
35 static event_t rxevt = EVENT_INITIAL_VALUE(rxevt, 0, 0);
36
37 static udc_request_t *txreq;
38 static udc_request_t *rxreq;
39 static udc_endpoint_t *txept;
40 static udc_endpoint_t *rxept;
41
42 static volatile int online;
43 static volatile int txstatus;
44 static volatile int rxstatus;
45 static volatile unsigned rxactual;
46
lpcboot_notify(udc_gadget_t * gadget,unsigned event)47 static void lpcboot_notify(udc_gadget_t *gadget, unsigned event) {
48 if (event == UDC_EVENT_ONLINE) {
49 online = 1;
50 } else {
51 online = 0;
52 }
53 }
54
rx_complete(udc_request_t * req,unsigned actual,int status)55 static void rx_complete(udc_request_t *req, unsigned actual, int status) {
56 rxactual = actual;
57 rxstatus = status;
58 event_signal(&rxevt, 0);
59 }
60
tx_complete(udc_request_t * req,unsigned actual,int status)61 static void tx_complete(udc_request_t *req, unsigned actual, int status) {
62 txstatus = status;
63 event_signal(&txevt, 0);
64 }
65
usb_xmit(void * data,unsigned len)66 void usb_xmit(void *data, unsigned len) {
67 event_unsignal(&txevt);
68 txreq->buffer = data;
69 txreq->length = len;
70 txstatus = 1;
71 udc_request_queue(txept, txreq);
72 event_wait(&txevt);
73 }
74
usb_recv(void * data,unsigned len,lk_time_t timeout)75 int usb_recv(void *data, unsigned len, lk_time_t timeout) {
76 event_unsignal(&rxevt);
77 rxreq->buffer = data;
78 rxreq->length = len;
79 rxstatus = 1;
80 udc_request_queue(rxept, rxreq);
81 if (event_wait_timeout(&rxevt, timeout)) {
82 return ERR_TIMED_OUT;
83 }
84 return rxactual;
85 }
86
87 static udc_device_t lpcboot_device = {
88 .vendor_id = 0x1209,
89 .product_id = 0x5039,
90 .version_id = 0x0100,
91 };
92
93 static udc_endpoint_t *lpcboot_endpoints[2];
94
95 static udc_gadget_t lpcboot_gadget = {
96 .notify = lpcboot_notify,
97 .ifc_class = 0xFF,
98 .ifc_subclass = 0xFF,
99 .ifc_protocol = 0xFF,
100 .ifc_endpoints = 2,
101 .ept = lpcboot_endpoints,
102 };
103
lpcboot_init(const struct app_descriptor * app)104 static void lpcboot_init(const struct app_descriptor *app) {
105 udc_init(&lpcboot_device);
106 lpcboot_endpoints[0] = txept = udc_endpoint_alloc(UDC_BULK_IN, 512);
107 lpcboot_endpoints[1] = rxept = udc_endpoint_alloc(UDC_BULK_OUT, 512);
108 txreq = udc_request_alloc();
109 rxreq = udc_request_alloc();
110 rxreq->complete = rx_complete;
111 txreq->complete = tx_complete;
112 udc_register_gadget(&lpcboot_gadget);
113 }
114
115 #define RAM_BASE 0x10000000
116 #define RAM_SIZE (128 * 1024)
117
118 #define BOOT_BASE 0
119 #define BOOT_SIZE (32 * 1024)
120
121 #define ROM_BASE (32 * 1024)
122 #define ROM_SIZE (128 * 1024)
123
124 struct device_info {
125 u8 part[16];
126 u8 board[16];
127 u32 version;
128 u32 ram_base;
129 u32 ram_size;
130 u32 rom_base;
131 u32 rom_size;
132 u32 unused0;
133 u32 unused1;
134 u32 unused2;
135 };
136
137 struct device_info DEVICE = {
138 .part = "LPC43xx",
139 .board = TARGET,
140 .version = 0x0001000,
141 .ram_base = RAM_BASE,
142 .ram_size = RAM_SIZE,
143 .rom_base = ROM_BASE,
144 .rom_size = ROM_SIZE,
145 };
146
147
148 #define MAGIC1 0xAA113377
149 #define MAGIC2 0xAA773311
150 #define MAGIC1_ADDR 0x20003FF8
151 #define MAGIC2_ADDR 0x20003FFC
152
boot_app(void)153 void boot_app(void) {
154 writel(MAGIC1, MAGIC1_ADDR);
155 writel(MAGIC2, MAGIC2_ADDR);
156 }
157
erase_page(u32 addr)158 int erase_page(u32 addr) {
159 spifi_sector_erase(addr);
160 return spifi_verify_erased(addr, 0x1000/4);
161 }
162
write_page(u32 addr,void * ptr)163 int write_page(u32 addr, void *ptr) {
164 unsigned n;
165 u32 *x = ptr;
166 for (n = 0; n < 16; n++) {
167 spifi_page_program(addr, x, 256 / 4);
168 if (spifi_verify_page(addr, x)) return -1;
169 addr += 256;
170 x += (256 / 4);
171 }
172 return 0;
173 }
174
175 static uint32_t ram[4096/4];
176
handle(u32 magic,u32 cmd,u32 arg)177 void handle(u32 magic, u32 cmd, u32 arg) {
178 u32 reply[2];
179 u32 addr, xfer;
180 int err = 0;
181
182 if (magic != 0xDB00A5A5)
183 return;
184
185 reply[0] = magic;
186 reply[1] = -1;
187
188 switch (cmd) {
189 case 'E':
190 reply[1] = erase_page(ROM_BASE);
191 break;
192 case 'W':
193 case 'w':
194 if (cmd == 'W') {
195 if (arg > ROM_SIZE)
196 break;
197 addr = ROM_BASE;
198 } else {
199 if (arg > BOOT_SIZE)
200 break;
201 addr = BOOT_BASE;
202 }
203 reply[1] = 0;
204 usb_xmit(reply, 8);
205 while (arg > 0) {
206 xfer = (arg > 4096) ? 4096 : arg;
207 usb_recv(ram, xfer, INFINITE_TIME);
208 if (!err) err = erase_page(addr);
209 if (!err) err = write_page(addr, ram);
210 addr += 4096;
211 arg -= xfer;
212 }
213 printf("flash %s\n", err ? "ERROR" : "OK");
214 reply[1] = err;
215 break;
216 #if WITH_BOOT_TO_RAM
217 case 'X':
218 if (arg > RAM_SIZE)
219 break;
220 reply[1] = 0;
221 usb_xmit(reply, 8);
222 usb_recv(ram, arg);
223 usb_xmit(reply, 8);
224
225 /* let last txn clear */
226 usb_recv_timeout(buf, 64, 10);
227
228 boot_image(ram);
229 break;
230 #endif
231 case 'Q':
232 reply[1] = 0;
233 usb_xmit(reply, 8);
234 usb_xmit(&DEVICE, sizeof(DEVICE));
235 return;
236 case 'A':
237 boot_app();
238 /* fallthrough */
239 case 'R':
240 /* reboot "normally" */
241 reply[1] = 0;
242 usb_xmit(reply, 8);
243 udc_stop();
244 platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
245 default:
246 break;
247 }
248 usb_xmit(reply, 8);
249 }
250
251 static short led_idx = 0;
252 static short led_delay[] = { 500, 100, 100, 100, };
253 static short led_state[] = { 1, 0, 1, 0, };
254 static timer_t led_timer = TIMER_INITIAL_VALUE(led_timer);
255
led_timer_cb(timer_t * timer,lk_time_t now,void * arg)256 static enum handler_return led_timer_cb(timer_t *timer, lk_time_t now, void *arg) {
257 gpio_set(GPIO_LED, led_state[led_idx]);
258 timer_set_oneshot(timer, led_delay[led_idx], led_timer_cb, NULL);
259 led_idx++;
260 if (led_idx == (sizeof(led_state)/sizeof(led_state[0]))) {
261 led_idx = 0;
262 }
263 return 0;
264 }
265
lpcboot_entry(const struct app_descriptor * app,void * args)266 static void lpcboot_entry(const struct app_descriptor *app, void *args) {
267 lk_time_t timeout;
268 int r;
269 u32 buf[64/4];
270
271 #if 0
272 timeout = INFINITE_TIME;
273 #else
274 if (readl(32768) != 0) {
275 timeout = 3000;
276 } else {
277 timeout = INFINITE_TIME;
278 }
279 #endif
280
281 pin_config(PIN_LED, PIN_MODE(0) | PIN_PLAIN);
282 gpio_config(GPIO_LED, GPIO_OUTPUT);
283 led_timer_cb(&led_timer, 0, NULL);
284
285 udc_start();
286 spifi_init();
287 for (;;) {
288 if (!online) {
289 thread_yield();
290 continue;
291 }
292 r = usb_recv(buf, 64, timeout);
293 if (r == ERR_TIMED_OUT) {
294 boot_app();
295 platform_halt(HALT_ACTION_REBOOT, HALT_REASON_SW_RESET);
296 }
297 if (r == 12) {
298 handle(buf[0], buf[1], buf[2]);
299 timeout = INFINITE_TIME;
300 }
301 }
302 }
303
304 APP_START(usbtest)
305 .init = lpcboot_init,
306 .entry = lpcboot_entry,
307 APP_END
308
309
310