summaryrefslogtreecommitdiff
path: root/chip/g/usb_endpoints.c
diff options
context:
space:
mode:
authorPatrick Georgi <pgeorgi@google.com>2018-08-16 15:35:43 +0200
committerchrome-bot <chrome-bot@chromium.org>2018-10-16 10:30:37 -0700
commitf3ee6eab984aa6855dea035b7771540280371b34 (patch)
tree2281612c4f94f00ac59d98bbb2e9d72f254f9cc1 /chip/g/usb_endpoints.c
parent69bc0deb614cc131cd669b5ac8935e68d10ac6e5 (diff)
downloadchrome-ec-f3ee6eab984aa6855dea035b7771540280371b34.tar.gz
chip/g: Convert usb_endpoints to C so gcc's LTO knows about it
If we keep it assembly-only, the link time optimizer gets confused and eliminates seemingly unused functions, to then replace references to them with the "no handler" defaults in a later step. Similar approach as with vecttable: Implement the table in C so LTO knows the entire story. BUG=b:65441143 BRANCH=none TEST=usb_ep_{rx,tx,reset} and usb_iface_request look more reasonable in disassembly on cr50. Change-Id: I72103af742164c29aac38e9929d1a83d8c154b53 Signed-off-by: Patrick Georgi <pgeorgi@google.com> Reviewed-on: https://chromium-review.googlesource.com/1177711 Commit-Ready: Patrick Georgi <pgeorgi@chromium.org> Tested-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Reviewed-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org> Reviewed-by: Stefan Reinauer <reinauer@chromium.org>
Diffstat (limited to 'chip/g/usb_endpoints.c')
-rw-r--r--chip/g/usb_endpoints.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/chip/g/usb_endpoints.c b/chip/g/usb_endpoints.c
new file mode 100644
index 0000000000..0cf73e2b13
--- /dev/null
+++ b/chip/g/usb_endpoints.c
@@ -0,0 +1,158 @@
+/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * USB endpoints/interfaces callbacks declaration
+ */
+
+#include "config.h"
+#include "common.h"
+#include "usb_hw.h"
+
+typedef void (*xfer_func)(void);
+typedef void (*rst_func) (void);
+typedef int (*iface_func)(struct usb_setup_packet *req);
+#ifndef PASS
+#define PASS 1
+#endif
+
+#if PASS == 1
+void ep_undefined(void)
+{
+ return;
+}
+
+void ep_rst_undefined(void)
+{
+ return;
+}
+
+/* Undefined interface callbacks fail by returning non-zero*/
+int iface_undefined(struct usb_setup_packet *req)
+{
+ return 1;
+}
+
+#define table(type, name, x) x
+
+#define endpoint_tx(number) \
+ extern void __attribute__((used, weak, alias("ep_undefined"))) \
+ ep_ ## number ## _tx(void);
+#define endpoint_rx(number) \
+ extern void __attribute__((used, weak, alias("ep_undefined"))) \
+ ep_ ## number ## _rx(void);
+#define endpoint_rst(number) \
+ extern void __attribute__((used, weak, alias("ep_rst_undefined"))) \
+ ep_ ## number ## _rst(void);
+#define interface(number) \
+ extern int __attribute__((used, weak, alias("iface_undefined"))) \
+ iface_ ## number ## _request(struct usb_setup_packet *req);
+
+#define null
+
+#endif /* PASS 1 */
+
+#if PASS == 2
+#undef table
+#undef endpoint_tx
+#undef endpoint_rx
+#undef endpoint_rst
+#undef interface
+#undef null
+
+/* align function pointers on a 32-bit boundary */
+#define table(type, name, x) type name[] __attribute__((aligned(4),section(".rodata.usb_ep." #name ",\"a\" @"))) = { x };
+#define null (void *)0
+
+#define ep_(num, suf) CONCAT3(ep_, num, suf)
+#define ep(num, suf) ep_(num, suf)
+
+#define endpoint_tx(number) \
+ [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _tx,
+#define endpoint_rx(number) \
+ [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _rx,
+#define endpoint_rst(number) \
+ [number < USB_EP_COUNT ? number : USB_EP_COUNT - 1] = ep_ ## number ## _rst,
+#define interface(number) \
+ [number < USB_IFACE_COUNT ? number : USB_IFACE_COUNT - 1] = iface_ ## number ## _request,
+#endif /* PASS 2 */
+
+/*
+ * The initializers are listed backwards, but that's so that the items beyond
+ * the chip's limit are first assigned to the last field, then overwritten by
+ * its actual value due to the designated initializers in the macros above.
+ * It all sorts out nicely
+ */
+table(xfer_func, usb_ep_tx,
+ endpoint_tx(15)
+ endpoint_tx(14)
+ endpoint_tx(13)
+ endpoint_tx(12)
+ endpoint_tx(11)
+ endpoint_tx(10)
+ endpoint_tx(9)
+ endpoint_tx(8)
+ endpoint_tx(7)
+ endpoint_tx(6)
+ endpoint_tx(5)
+ endpoint_tx(4)
+ endpoint_tx(3)
+ endpoint_tx(2)
+ endpoint_tx(1)
+ endpoint_tx(0)
+)
+
+table(xfer_func, usb_ep_rx,
+ endpoint_rx(15)
+ endpoint_rx(14)
+ endpoint_rx(13)
+ endpoint_rx(12)
+ endpoint_rx(11)
+ endpoint_rx(10)
+ endpoint_rx(9)
+ endpoint_rx(8)
+ endpoint_rx(7)
+ endpoint_rx(6)
+ endpoint_rx(5)
+ endpoint_rx(4)
+ endpoint_rx(3)
+ endpoint_rx(2)
+ endpoint_rx(1)
+ endpoint_rx(0)
+)
+
+table(rst_func, usb_ep_reset,
+ endpoint_rst(15)
+ endpoint_rst(14)
+ endpoint_rst(13)
+ endpoint_rst(12)
+ endpoint_rst(11)
+ endpoint_rst(10)
+ endpoint_rst(9)
+ endpoint_rst(8)
+ endpoint_rst(7)
+ endpoint_rst(6)
+ endpoint_rst(5)
+ endpoint_rst(4)
+ endpoint_rst(3)
+ endpoint_rst(2)
+ endpoint_rst(1)
+ endpoint_rst(0)
+)
+
+table(iface_func, usb_iface_request,
+ interface(7)
+ interface(6)
+ interface(5)
+ interface(4)
+ interface(3)
+ interface(2)
+ interface(1)
+ interface(0)
+)
+
+#if PASS == 1
+#undef PASS
+#define PASS 2
+#include "usb_endpoints.c"
+#endif