summaryrefslogtreecommitdiff
path: root/chip
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
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')
-rw-r--r--chip/g/usb_endpoints.S107
-rw-r--r--chip/g/usb_endpoints.c158
2 files changed, 158 insertions, 107 deletions
diff --git a/chip/g/usb_endpoints.S b/chip/g/usb_endpoints.S
deleted file mode 100644
index cc13cadeb3..0000000000
--- a/chip/g/usb_endpoints.S
+++ /dev/null
@@ -1,107 +0,0 @@
-/* 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"
-
-.section .rodata.usb_ep
-
-.macro endpoint number suffix
-.if \number < USB_EP_COUNT
-.long ep_\number\()_\()\suffix
-.weak ep_\number\()_\()\suffix
-.set ep_\number\()_\()\suffix, ep_undefined
-.endif
-.endm
-
-.macro interface number
-.if \number < USB_IFACE_COUNT
-.long iface_\number\()_request
-.weak iface_\number\()_request
-.set iface_\number\()_request, iface_undefined
-.endif
-.endm
-
-/* align function pointers on a 32-bit boundary */
-.align 2
-/* Endpoint callbacks */
-.global usb_ep_tx
-usb_ep_tx:
-endpoint 0 tx
-endpoint 1 tx
-endpoint 2 tx
-endpoint 3 tx
-endpoint 4 tx
-endpoint 5 tx
-endpoint 6 tx
-endpoint 7 tx
-endpoint 8 tx
-endpoint 9 tx
-endpoint 10 tx
-endpoint 11 tx
-endpoint 12 tx
-endpoint 13 tx
-endpoint 14 tx
-endpoint 15 tx
-
-.global usb_ep_rx
-usb_ep_rx:
-endpoint 0 rx
-endpoint 1 rx
-endpoint 2 rx
-endpoint 3 rx
-endpoint 4 rx
-endpoint 5 rx
-endpoint 6 rx
-endpoint 7 rx
-endpoint 8 rx
-endpoint 9 rx
-endpoint 10 rx
-endpoint 11 rx
-endpoint 12 rx
-endpoint 13 rx
-endpoint 14 rx
-endpoint 15 rx
-
-.global usb_ep_reset
-usb_ep_reset:
-endpoint 0 rst
-endpoint 1 rst
-endpoint 2 rst
-endpoint 3 rst
-endpoint 4 rst
-endpoint 5 rst
-endpoint 6 rst
-endpoint 7 rst
-endpoint 8 rst
-endpoint 9 rst
-endpoint 10 rst
-endpoint 11 rst
-endpoint 12 rst
-endpoint 13 rst
-endpoint 14 rst
-endpoint 15 rst
-
-.global usb_iface_request
-usb_iface_request:
-interface 0
-interface 1
-interface 2
-interface 3
-interface 4
-interface 5
-interface 6
-interface 7
-
-.text
-.code 16
-
-.thumb_func
-/* Undefined interface callbacks fail by returning non-zero*/
-iface_undefined:
- mov r0, #1
-ep_undefined:
- bx lr
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