blob: b207ad2fc07a077f61764a334e994f7a582a4171 [file] [log] [blame]
Sylvain Munautf5d7bf22020-09-14 10:23:50 +02001/*
2 * fw_app.c
3 *
4 * Copyright (C) 2019-2020 Sylvain Munaut <tnt@246tNt.com>
5 * SPDX-License-Identifier: GPL-3.0-or-later
6 */
7
8#include <stdint.h>
9#include <stdbool.h>
10#include <string.h>
11
12#include <no2usb/usb.h>
13#include <no2usb/usb_dfu_rt.h>
14
15#include "console.h"
16#include "e1.h"
17#include "led.h"
18#include "misc.h"
19#include "mini-printf.h"
20#include "spi.h"
21#include "utils.h"
22
23
24extern const struct usb_stack_descriptors app_stack_desc;
25
26void usb_e1_init(void);
27void usb_e1_run(void);
28
29
30static void
31serial_no_init()
32{
33 uint8_t buf[8];
34 char *id, *desc;
35 int i;
36
37 flash_manuf_id(buf);
38 printf("Flash Manufacturer : %s\n", hexstr(buf, 3, true));
39
40 flash_unique_id(buf);
41 printf("Flash Unique ID : %s\n", hexstr(buf, 8, true));
42
43 /* Overwrite descriptor string */
44 /* In theory in rodata ... but nothing is ro here */
45 id = hexstr(buf, 8, false);
46 desc = (char*)app_stack_desc.str[1];
47 for (i=0; i<16; i++)
48 desc[2 + (i << 1)] = id[i];
49}
50
51static void
52boot_dfu(void)
53{
54 /* Force re-enumeration */
55 usb_disconnect();
56
57 /* Boot firmware */
Sylvain Munaut035e2472020-09-15 22:09:53 +020058 volatile uint32_t *boot = (void*)MISC_BASE;
Sylvain Munautf5d7bf22020-09-14 10:23:50 +020059 *boot = (1 << 2) | (1 << 0);
60}
61
62void
63usb_dfu_rt_cb_reboot(void)
64{
65 boot_dfu();
66}
67
68
69
70static uint8_t
71liu_read_reg(unsigned chan, uint8_t reg)
72{
73 uint8_t cmd = reg | 0x20;
74 uint8_t rv;
75 struct spi_xfer_chunk xfer[2] = {
76 { .data = (void*)&cmd, .len = 1, .read = false, .write = true, },
77 { .data = (void*)&rv, .len = 1, .read = true, .write = false, },
78 };
79 spi_xfer(SPI_CS_LIU(chan), xfer, 2);
80 return rv;
81}
82
83static void
84liu_write_reg(unsigned chan, uint8_t reg, uint8_t val)
85{
86 uint8_t cmd[2] = { reg, val };
87 struct spi_xfer_chunk xfer[2] = {
88 { .data = (void*)cmd, .len = 2, .read = false, .write = true, },
89 };
90 spi_xfer(SPI_CS_LIU(chan), xfer, 1);
91}
92
93
94
95#define USB_RT_LIU_REG_WRITE ((1 << 8) | 0x42)
96#define USB_RT_LIU_REG_READ ((2 << 8) | 0xc2)
97
98
99static bool
100_liu_reg_write_done_cb(struct usb_xfer *xfer)
101{
102 struct usb_ctrl_req *req = xfer->cb_ctx;
103 unsigned chan = req->wIndex - 0x81;
104
105 liu_write_reg(chan, req->wValue, xfer->data[0]);
106
107 return true;
108}
109
110static enum usb_fnd_resp
111_liu_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
112{
113 unsigned chan;
114
115 /* If this a vendor request for the E1 endpoints */
116 if (USB_REQ_RCPT(req) != USB_REQ_RCPT_EP)
117 return USB_FND_CONTINUE;
118
119 if (req->wIndex < 0x81 || req->wIndex > 0x82)
120 return USB_FND_CONTINUE;
121
122 if (USB_REQ_TYPE(req) != USB_REQ_TYPE_VENDOR)
123 return USB_FND_CONTINUE;
124
125 chan = req->wIndex - 0x81;
126
127 /* */
128 switch (req->wRequestAndType)
129 {
130 case USB_RT_LIU_REG_WRITE:
131 xfer->len = 1;
132 xfer->cb_done = _liu_reg_write_done_cb;
133 xfer->cb_ctx = req;
134 break;
135
136 case USB_RT_LIU_REG_READ:
137 xfer->len = 1;
138 xfer->data[0] = liu_read_reg(chan, req->wValue);
139 break;
140
141 default:
142 goto error;
143 }
144
145 return USB_FND_SUCCESS;
146
147error:
148 return USB_FND_ERROR;
149}
150
151static struct usb_fn_drv _liu_drv = {
152 .ctrl_req = _liu_ctrl_req,
153};
154
155
156
157void main()
158{
159 int cmd = 0;
160
161 /* Init console IO */
162 console_init();
163 puts("Booting App image..\n");
164
165 /* LED */
166 led_init();
167 led_state(true);
168
169 /* SPI */
170 spi_init();
171
172 puts("XXX\n");
173
174 /* Enable USB directly */
175 serial_no_init();
176 usb_init(&app_stack_desc);
177 usb_dfu_rt_init();
178 usb_register_function_driver(&_liu_drv);
179 usb_e1_init();
180
181 usb_connect();
182 e1_init();
183
184 /* Main loop */
185 while (1)
186 {
187 /* Prompt ? */
188 if (cmd >= 0)
189 printf("Command> ");
190
191 /* Poll for command */
192 cmd = getchar_nowait();
193
194 if (cmd >= 0) {
195 if (cmd > 32 && cmd < 127) {
196 putchar(cmd);
197 putchar('\r');
198 putchar('\n');
199 }
200
201 switch (cmd)
202 {
203 case 'u':
204 usb_debug_print();
205 break;
206 case 'e':
207 e1_debug_print(false);
208 break;
209 case 'E':
210 e1_debug_print(true);
211 break;
212 default:
213 break;
214 }
215 }
216
217 /* USB poll */
218 usb_poll();
219
220 /* E1 poll */
221 e1_poll();
222 usb_e1_run();
223 }
224}