blob: b4d8839dc3f8674cebfcf65a1e28e230acfb01de [file] [log] [blame]
Sylvain Munautbc9f5c42020-09-14 10:22:29 +02001/*
2 * usb_e1.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_hw.h>
13#include <no2usb/usb_priv.h>
14
15#include "console.h"
16#include "misc.h"
Harald Welte2df1f802020-12-14 17:46:53 +010017#include "e1.h"
Harald Welte9469e042020-12-15 23:09:40 +010018#include "e1_hw.h"
19
20#include "ice1usb_proto.h"
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020021
22struct {
Harald Welte30fc5602020-12-14 15:56:28 +010023 bool running; /* are we running (transceiving USB data)? */
24 int out_bdi; /* buffer descriptor index for OUT EP */
25 int in_bdi; /* buffer descriptor index for IN EP */
Harald Welte9469e042020-12-15 23:09:40 +010026 struct ice1usb_tx_config tx_cfg;
27 struct ice1usb_rx_config rx_cfg;
Harald Welte805f2cf2020-12-14 17:31:03 +010028 struct e1_error_count last_err;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020029} g_usb_e1;
30
Harald Welte9469e042020-12-15 23:09:40 +010031/* default configuration at power-up */
32static const struct ice1usb_tx_config tx_cfg_default = {
33 .mode = ICE1USB_TX_MODE_TS0_CRC4_E,
34 .timing = ICE1USB_TX_TIME_SRC_LOCAL,
35 .ext_loopback = ICE1USB_TX_EXT_LOOPBACK_OFF,
36 .alarm = 0,
37};
38
39static const struct ice1usb_rx_config rx_cfg_default = {
40 .mode = ICE1USB_RX_MODE_MULTIFRAME,
41};
42
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020043
44/* Hack */
Harald Weltedaff4f62020-12-14 17:39:23 +010045unsigned int e1_rx_need_data(unsigned int usb_addr, unsigned int max_len, unsigned int *pos);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020046unsigned int e1_tx_feed_data(unsigned int usb_addr, unsigned int len);
47unsigned int e1_tx_level(void);
48unsigned int e1_rx_level(void);
49/* ---- */
50
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020051static void
52_usb_fill_feedback_ep(void)
53{
54 static uint16_t ticks_prev = 0;
55 uint16_t ticks;
56 uint32_t val = 8192;
57 unsigned int level;
58
Harald Welte2b7dadf2020-12-14 15:56:15 +010059 /* Compute real E1 tick count (with safety against bad values) */
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020060 ticks = e1_tick_read();
61 val = (ticks - ticks_prev) & 0xffff;
62 ticks_prev = ticks;
63 if ((val < 7168) | (val > 9216))
64 val = 8192;
65
66 /* Bias depending on TX fifo level */
67 level = e1_tx_level();
68 if (level < (3 * 16))
69 val += 256;
70 else if (level > (8 * 16))
71 val -= 256;
72
73 /* Prepare buffer */
Sylvain Munaut96744362022-01-03 17:03:26 +010074 usb_data_write(usb_ep_regs[1].in.bd[0].ptr, &val, 4);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +020075 usb_ep_regs[1].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(3);
76}
77
78
79void
80usb_e1_run(void)
81{
82 int bdi;
83
84 if (!g_usb_e1.running)
85 return;
86
Harald Welte805f2cf2020-12-14 17:31:03 +010087 /* EP3 IRQ */
88 if ((usb_ep_regs[3].in.bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA) {
89 const struct e1_error_count *cur_err = e1_get_error_count();
90 if (memcmp(cur_err, &g_usb_e1.last_err, sizeof(*cur_err))) {
91 struct ice1usb_irq errmsg = {
92 .type = ICE1USB_IRQ_T_ERRCNT,
93 .u = {
94 .errors = {
95 .crc = cur_err->crc,
96 .align = cur_err->align,
97 .ovfl = cur_err->ovfl,
98 .unfl = cur_err->unfl,
99 .flags = cur_err->flags,
100 }
101 }
102 };
103 printf("E");
104 usb_data_write(usb_ep_regs[3].in.bd[0].ptr, &errmsg, sizeof(errmsg));
105 usb_ep_regs[3].in.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(sizeof(errmsg));
106 g_usb_e1.last_err = *cur_err;
107 }
108 }
109
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200110 /* EP2 IN */
111 bdi = g_usb_e1.in_bdi;
112
113 while ((usb_ep_regs[2].in.bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
114 {
115 uint32_t ptr = usb_ep_regs[2].in.bd[bdi].ptr;
116 uint32_t hdr;
Harald Welte2df1f802020-12-14 17:46:53 +0100117 unsigned int pos;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200118
119 /* Error check */
120 if ((usb_ep_regs[2].in.bd[bdi].csr & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR)
121 puts("Err EP2 IN\n");
122
123 /* Get some data from E1 */
124 int n = e1_rx_level();
125
126 if (n > 64)
127 n = 12;
128 else if (n > 32)
129 n = 10;
130 else if (n > 8)
131 n = 8;
132 else if (!n)
133 break;
134
Harald Welte2df1f802020-12-14 17:46:53 +0100135 n = e1_rx_need_data((ptr >> 2) + 1, n, &pos);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200136
Harald Welte2df1f802020-12-14 17:46:53 +0100137 /* Write header: currently version and pos (mfr/fr number) */
138 hdr = (0 << 28) | (pos & 0xff);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200139 usb_data_write(ptr, &hdr, 4);
140
141 /* Resubmit */
142 usb_ep_regs[2].in.bd[bdi].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN((n * 32) + 4);
143
144 /* Next BDI */
145 bdi ^= 1;
146 g_usb_e1.in_bdi = bdi;
147 }
148
149 /* EP1 OUT */
150 bdi = g_usb_e1.out_bdi;
151
152 while ((usb_ep_regs[1].out.bd[bdi].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
153 {
154 uint32_t ptr = usb_ep_regs[1].out.bd[bdi].ptr;
155 uint32_t csr = usb_ep_regs[1].out.bd[bdi].csr;
156 uint32_t hdr;
157
158 /* Error check */
159 if ((csr & USB_BD_STATE_MSK) == USB_BD_STATE_DONE_ERR) {
160 puts("Err EP1 OUT\n");
161 goto refill;
162 }
163
164 /* Grab header */
165 usb_data_read(&hdr, ptr, 4);
166
167 /* Empty data into the FIFO */
168 int n = ((csr & USB_BD_LEN_MSK) - 4) / 32;
169 n = e1_tx_feed_data((ptr >> 2) + 1, n);
170
171refill:
172 /* Refill it */
173 usb_ep_regs[1].out.bd[bdi].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(388);
174
175 /* Next BDI */
176 bdi ^= 1;
177 g_usb_e1.out_bdi = bdi;
178
179 static int x = 0;
180 if ((x++ & 0xff) == 0xff)
181 puts(".");
182 }
183
184 /* EP1 IN */
185 if ((usb_ep_regs[1].in.bd[0].csr & USB_BD_STATE_MSK) != USB_BD_STATE_RDY_DATA)
186 {
187 _usb_fill_feedback_ep();
188 }
189}
190
Harald Weltec8271852020-12-14 13:48:09 +0100191static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200192_e1_set_conf(const struct usb_conf_desc *conf)
193{
194 const struct usb_intf_desc *intf;
195
196 printf("e1 set_conf %08x\n", conf);
197 if (!conf)
198 return USB_FND_SUCCESS;
199
Sylvain Munaut96744362022-01-03 17:03:26 +0100200 intf = usb_desc_find_intf(conf, 0, 0, NULL);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200201 if (!intf)
202 return USB_FND_ERROR;
203
204 printf("e1 set_conf %08x\n", intf);
205
206 usb_ep_boot(intf, 0x01, true);
Sylvain Munaut96744362022-01-03 17:03:26 +0100207 usb_ep_boot(intf, 0x81, false);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200208 usb_ep_boot(intf, 0x82, true);
Sylvain Munaut96744362022-01-03 17:03:26 +0100209 usb_ep_boot(intf, 0x83, false);
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200210
211 return USB_FND_SUCCESS;
212}
213
Harald Welte9469e042020-12-15 23:09:40 +0100214static void _perform_tx_config(void)
215{
216 const struct ice1usb_tx_config *cfg = &g_usb_e1.tx_cfg;
217 e1_tx_config( ((cfg->mode & 3) << 1) |
218 ((cfg->timing & 1) << 3) |
219 ((cfg->alarm & 1) << 4) |
220 ((cfg->ext_loopback & 3) << 5) );
221}
222
223static void _perform_rx_config(void)
224{
225 const struct ice1usb_rx_config *cfg = &g_usb_e1.rx_cfg;
226 e1_rx_config((cfg->mode << 1));
227}
228
Harald Weltec8271852020-12-14 13:48:09 +0100229static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200230_e1_set_intf(const struct usb_intf_desc *base, const struct usb_intf_desc *sel)
231{
Sylvain Munaut96744362022-01-03 17:03:26 +0100232 /* Validity checks */
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200233 if (base->bInterfaceNumber != 0)
234 return USB_FND_CONTINUE;
235
Sylvain Munaut96744362022-01-03 17:03:26 +0100236 if (sel->bAlternateSetting > 1)
237 return USB_FND_ERROR;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200238
Sylvain Munaut96744362022-01-03 17:03:26 +0100239 /* Don't do anything if no change */
240 if (g_usb_e1.running == (sel->bAlternateSetting != 0))
241 return USB_FND_SUCCESS;
242
243 g_usb_e1.running = (sel->bAlternateSetting != 0);
244
245 /* Reconfigure the endpoints */
246 usb_ep_reconf(sel, 0x01);
247 usb_ep_reconf(sel, 0x81);
248 usb_ep_reconf(sel, 0x82);
249 usb_ep_reconf(sel, 0x83);
250
251 /* Update E1 and USB state */
252 switch (g_usb_e1.running) {
253 case false:
254 /* Disable E1 rx/tx */
Harald Weltee6b0fe82020-12-17 22:22:05 +0100255 e1_init(0, 0);
Harald Weltee6b0fe82020-12-17 22:22:05 +0100256 break;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200257
Sylvain Munaut96744362022-01-03 17:03:26 +0100258 case true:
259 /* Reset and Re-Enable E1 */
260 e1_init(0, 0);
Harald Weltee6b0fe82020-12-17 22:22:05 +0100261 _perform_rx_config();
262 _perform_tx_config();
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200263
Sylvain Munaut96744362022-01-03 17:03:26 +0100264 /* Reset BDI */
Harald Weltee6b0fe82020-12-17 22:22:05 +0100265 g_usb_e1.in_bdi = 0;
Sylvain Munaut96744362022-01-03 17:03:26 +0100266 g_usb_e1.out_bdi = 0;
Harald Weltee6b0fe82020-12-17 22:22:05 +0100267
268 /* EP1 OUT: Queue two buffers */
Harald Weltee6b0fe82020-12-17 22:22:05 +0100269 usb_ep_regs[1].out.bd[0].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(388);
Harald Weltee6b0fe82020-12-17 22:22:05 +0100270 usb_ep_regs[1].out.bd[1].csr = USB_BD_STATE_RDY_DATA | USB_BD_LEN(388);
271
272 /* EP1 IN: Queue buffer */
273 _usb_fill_feedback_ep();
274
Harald Weltee6b0fe82020-12-17 22:22:05 +0100275 break;
Harald Weltee6b0fe82020-12-17 22:22:05 +0100276 }
Harald Welte805f2cf2020-12-14 17:31:03 +0100277
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200278 return USB_FND_SUCCESS;
279}
280
Harald Weltec8271852020-12-14 13:48:09 +0100281static enum usb_fnd_resp
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200282_e1_get_intf(const struct usb_intf_desc *base, uint8_t *alt)
283{
284 if (base->bInterfaceNumber != 0)
285 return USB_FND_CONTINUE;
286
287 *alt = g_usb_e1.running ? 1 : 0;
288
289 return USB_FND_SUCCESS;
290}
291
Harald Welte9469e042020-12-15 23:09:40 +0100292static bool
293_set_tx_mode_done(struct usb_xfer *xfer)
294{
295 const struct ice1usb_tx_config *cfg = (const struct ice1usb_tx_config *) xfer->data;
296 printf("set_tx_mode %02x%02x%02x%02x\r\n",
297 xfer->data[0], xfer->data[1], xfer->data[2], xfer->data[3]);
298 g_usb_e1.tx_cfg = *cfg;
299 _perform_tx_config();
300 return true;
301}
302
303static bool
304_set_rx_mode_done(struct usb_xfer *xfer)
305{
306 const struct ice1usb_rx_config *cfg = (const struct ice1usb_rx_config *) xfer->data;
307 printf("set_rx_mode %02x\r\n", xfer->data[0]);
308 g_usb_e1.rx_cfg = *cfg;
309 _perform_rx_config();
310 return true;
311}
312
313/* per-interface requests */
314static enum usb_fnd_resp
315_e1_ctrl_req_intf(struct usb_ctrl_req *req, struct usb_xfer *xfer)
316{
317 unsigned int i;
318
319 switch (req->bRequest) {
320 case ICE1USB_INTF_GET_CAPABILITIES:
321 /* no optional capabilities yet */
322 xfer->len = 0;
323 break;
324 case ICE1USB_INTF_SET_TX_CFG:
325 if (req->wLength < sizeof(struct ice1usb_tx_config))
326 return USB_FND_ERROR;
327 xfer->cb_done = _set_tx_mode_done;
328 xfer->cb_ctx = req;
329 xfer->len = sizeof(struct ice1usb_tx_config);
330 break;
331 case ICE1USB_INTF_GET_TX_CFG:
332 if (req->wLength < sizeof(struct ice1usb_tx_config))
333 return USB_FND_ERROR;
334 memcpy(xfer->data, &g_usb_e1.tx_cfg, sizeof(struct ice1usb_tx_config));
335 xfer->len = sizeof(struct ice1usb_tx_config);
336 break;
337 case ICE1USB_INTF_SET_RX_CFG:
338 if (req->wLength < sizeof(struct ice1usb_rx_config))
339 return USB_FND_ERROR;
340 xfer->cb_done = _set_rx_mode_done;
341 xfer->cb_ctx = req;
342 xfer->len = sizeof(struct ice1usb_rx_config);
343 break;
344 case ICE1USB_INTF_GET_RX_CFG:
345 if (req->wLength < sizeof(struct ice1usb_rx_config))
346 return USB_FND_ERROR;
347 memcpy(xfer->data, &g_usb_e1.rx_cfg, sizeof(struct ice1usb_rx_config));
348 xfer->len = sizeof(struct ice1usb_rx_config);
349 break;
350 default:
351 return USB_FND_ERROR;
352 }
353
354 return USB_FND_SUCCESS;
355}
356
357/* device-global requests */
358static enum usb_fnd_resp
359_e1_ctrl_req_dev(struct usb_ctrl_req *req, struct usb_xfer *xfer)
360{
361 switch (req->bRequest) {
362 case ICE1USB_DEV_GET_CAPABILITIES:
363 xfer->data[0] = (1 << ICE1USB_DEV_CAP_GPSDO);
364 xfer->len = 1;
365 break;
366 default:
367 return USB_FND_ERROR;
368 }
369
370 return USB_FND_SUCCESS;
371}
372
373
374/* USB host issues a control request to us */
375static enum usb_fnd_resp
376_e1_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
377{
378 if (USB_REQ_TYPE(req) != USB_REQ_TYPE_VENDOR)
379 return USB_FND_CONTINUE;
380
381 switch (USB_REQ_RCPT(req)) {
382 case USB_REQ_RCPT_DEV:
383 return _e1_ctrl_req_dev(req, xfer);
384 case USB_REQ_RCPT_INTF:
385 if (req->wIndex != 0)
386 return USB_FND_ERROR;
387 return _e1_ctrl_req_intf(req, xfer);
388 case USB_REQ_RCPT_EP:
389 case USB_REQ_RCPT_OTHER:
390 default:
391 return USB_FND_ERROR;
392 }
393}
394
395
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200396static struct usb_fn_drv _e1_drv = {
397 .set_conf = _e1_set_conf,
398 .set_intf = _e1_set_intf,
399 .get_intf = _e1_get_intf,
Harald Welte9469e042020-12-15 23:09:40 +0100400 .ctrl_req = _e1_ctrl_req,
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200401};
402
403void
404usb_e1_init(void)
405{
406 memset(&g_usb_e1, 0x00, sizeof(g_usb_e1));
Harald Welte9469e042020-12-15 23:09:40 +0100407 g_usb_e1.tx_cfg = tx_cfg_default;
408 g_usb_e1.rx_cfg = rx_cfg_default;
Sylvain Munautbc9f5c42020-09-14 10:22:29 +0200409 usb_register_function_driver(&_e1_drv);
410}