summaryrefslogtreecommitdiff
path: root/chip/stm32/usb_hw.h
blob: 0c75322a7d71e555fdf38928e8d801e52e6f22fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* Copyright 2015 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.
 */

#ifndef __CROS_EC_USB_HW_H
#define __CROS_EC_USB_HW_H

#include <stddef.h>
#include <stdint.h>

/* Event types for the endpoint event handler. */
enum usb_ep_event {
	USB_EVENT_RESET,
	USB_EVENT_DEVICE_RESUME, /* Device-initiated wake completed. */
};

#if defined(CHIP_FAMILY_STM32F4)
#include "usb_dwc_hw.h"
#else


/*
 * The STM32 has dedicated USB RAM visible on the APB1 bus (so all reads &
 * writes are 16-bits wide). The endpoint tables and the data buffers live in
 * this RAM.
*/

/* Primitive to access the words in USB RAM */
typedef CONFIG_USB_RAM_ACCESS_TYPE usb_uint;
/* Linker symbol for start of USB RAM */
extern usb_uint __usb_ram_start[];

/* Attribute to define a buffer variable in USB RAM */
#define __usb_ram __attribute__((section(".usb_ram.99_data")))

/* Mask for the rx_count to identify the number of bytes in the buffer. */
#define RX_COUNT_MASK (0x3ff)

struct stm32_endpoint {
	volatile usb_uint tx_addr;
	volatile usb_uint tx_count;
	volatile usb_uint rx_addr;
	volatile usb_uint rx_count;
};

extern struct stm32_endpoint btable_ep[];

/* Attribute to put the endpoint table in USB RAM */
#define __usb_btable __attribute__((section(".usb_ram.00_btable")))

/* Read from USB RAM into a usb_setup_packet struct */
struct usb_setup_packet;
void usb_read_setup_packet(usb_uint *buffer, struct usb_setup_packet *packet);

/*
 * Copy data to and from the USB dedicated RAM and take care of the weird
 * addressing.  These functions correctly handle unaligned accesses to the USB
 * memory.  They have the same prototype as memcpy, allowing them to be used
 * in places that expect memcpy.  The void pointer used to represent a location
 * in the USB dedicated RAM should be the offset in that address space, not the
 * AHB address space.
 *
 * The USB packet RAM is attached to the processor via the AHB2APB bridge.  This
 * bridge performs manipulations of read and write accesses as per the note in
 * section 2.1 of RM0091.  The upshot is that custom memcpy-like routines need
 * to be employed.
 */
void *memcpy_to_usbram(void *dest, const void *src, size_t n);
void *memcpy_from_usbram(void *dest, const void *src, size_t n);

/*
 * Descriptor patching support, useful to change a few values in the descriptor
 * (typically, length or bitfields) without having to move descriptors to RAM.
 */

enum usb_desc_patch_type {
#ifdef CONFIG_USB_HID_KEYBOARD_BACKLIGHT
	USB_DESC_KEYBOARD_BACKLIGHT,
#endif
	USB_DESC_PATCH_COUNT,
};

/*
 * Set patch in table: replace uint16_t at address (STM32 flash) with data.
 *
 * The patches need to be setup before _before_ usb_init is executed (or, at
 * least, before the first call to memcpy_to_usbram_ep0_patch).
 */
void set_descriptor_patch(enum usb_desc_patch_type type,
			  const void *address, uint16_t data);

/* Copy to USB ram, applying patches to src as required. */
void *memcpy_to_usbram_ep0_patch(const void *src, size_t n);

/* Compute the address inside dedicate SRAM for the USB controller */
#define usb_sram_addr(x) ((x - __usb_ram_start) * sizeof(uint16_t))

/* Helpers for endpoint declaration */
#define _EP_HANDLER2(num, suffix) CONCAT3(ep_, num, suffix)
#define _EP_TX_HANDLER(num) _EP_HANDLER2(num, _tx)
#define _EP_RX_HANDLER(num) _EP_HANDLER2(num, _rx)
#define _EP_EVENT_HANDLER(num) _EP_HANDLER2(num, _evt)
/* Used to check function types are correct (attribute alias does not do it) */
#define _EP_TX_HANDLER_TYPECHECK(num) _EP_HANDLER2(num, _tx_typecheck)
#define _EP_RX_HANDLER_TYPECHECK(num) _EP_HANDLER2(num, _rx_typecheck)
#define _EP_EVENT_HANDLER_TYPECHECK(num) _EP_HANDLER2(num, _evt_typecheck)

#define USB_DECLARE_EP(num, tx_handler, rx_handler, evt_handler)  \
	void _EP_TX_HANDLER(num)(void)				  \
		__attribute__ ((alias(STRINGIFY(tx_handler))));	  \
	void _EP_RX_HANDLER(num)(void)                            \
		__attribute__ ((alias(STRINGIFY(rx_handler))));	  \
	void _EP_EVENT_HANDLER(num)(enum usb_ep_event evt)        \
		__attribute__ ((alias(STRINGIFY(evt_handler))));  \
	static __unused void					  \
	(*_EP_TX_HANDLER_TYPECHECK(num))(void) = tx_handler;	  \
	static __unused void					  \
	(*_EP_RX_HANDLER_TYPECHECK(num))(void) = rx_handler;	  \
	static __unused void					  \
	(*_EP_EVENT_HANDLER_TYPECHECK(num))(enum usb_ep_event evt)\
			= evt_handler

/* arrays with all endpoint callbacks */
extern void (*usb_ep_tx[]) (void);
extern void (*usb_ep_rx[]) (void);
extern void (*usb_ep_event[]) (enum usb_ep_event evt);
/* array with interface-specific control request callbacks */
extern int (*usb_iface_request[]) (usb_uint *ep0_buf_rx, usb_uint *ep0_buf_tx);

/*
 * Interface handler returns -1 on error, 0 if it wrote the last chunk of data,
 * or 1 if more data needs to be transferred on the next control request.
 */
#define _IFACE_HANDLER(num) CONCAT3(iface_, num, _request)
#define USB_DECLARE_IFACE(num, handler)					\
	int _IFACE_HANDLER(num)(usb_uint *ep0_buf_rx,			\
			       usb_uint *epo_buf_tx)			\
	__attribute__ ((alias(STRINGIFY(handler))));

#endif
#endif	/* __CROS_EC_USB_HW_H */