-
Notifications
You must be signed in to change notification settings - Fork 8
/
omap_USB.c
executable file
·150 lines (120 loc) · 3.17 KB
/
omap_USB.c
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
143
144
145
146
147
148
149
150
//(c) uARM project https://github.com/uARM-Palm/uARM [email protected]
#include "omap_USB.h"
#include "omap_IC.h"
#include <string.h>
#include <stdlib.h>
#include "util.h"
#include "mem.h"
#define OMAP_USB_BASE 0xFFFB4000UL
#define OMAP_USB_SIZE 256
struct OmapUsb {
struct ArmMem *mem;
struct SocDma *dma;
struct SocIc *ic;
uint16_t syscon1, irqSrc, ep0Cfg;
uint16_t rxEpCfg[15];
uint16_t txEpCfg[15];
uint8_t epNum, irqEn, devStat;
};
static bool omapUsbPrvMemAccessF(void* userData, uint32_t pa, uint_fast8_t size, bool write, void* buf)
{
struct OmapUsb *usb = (struct OmapUsb*)userData;
uint32_t val = 0;
if ((size != 4 && size != 2) || (pa & 3)) {
fprintf(stderr, "%s: Unexpected %s of %u bytes to 0x%08lx\n", __func__, write ? "write" : "read", size, (unsigned long)pa);
return false;
}
pa = (pa - OMAP_USB_BASE) >> 2;
if (write)
val = (size == 2) ? *(uint16_t*)buf : *(uint32_t*)buf;
switch (pa) {
case 0x04 / 4:
if (write)
usb->epNum = val & 0x7f; //i am approximately 100% sure that this is not how this is uspposed to work.
else
val = usb->epNum;
break;
case 0x0c / 4:
if (write) {
if (val & 0x01)
fprintf(stderr, "USB: %s ep %u\n", "reset", usb->epNum & 15);
if (val & 0x02)
fprintf(stderr, "USB: %s ep %u\n", "clear", usb->epNum & 15);
if (val & 0x04)
fprintf(stderr, "USB: %s ep %u\n", "FIFO ON", usb->epNum & 15);
if (val & 0x40)
fprintf(stderr, "USB: %s ep %u\n", "HALT", usb->epNum & 15);
if (val & 0x80)
fprintf(stderr, "USB: %s ep %u\n", "UNHALT", usb->epNum & 15);
}
else
val = 0; //read returns zero
break;
case 0x18 / 4:
if (write)
usb->syscon1 = val & 0x0117;
else
val = usb->syscon1;
break;
case 0x20 / 4:
if (write)
return false;
else
val = usb->devStat;
break;
case 0x28 / 4:
if (write)
usb->irqEn = val & 0x00b9;
else
val = usb->irqEn;
break;
case 0x30 / 4:
if (write)
; //write ignored //might be wrong
else {
val = usb->irqSrc;
usb->irqSrc = 0; //might be wrong
}
break;
case 0x80 / 4:
if (write)
usb->ep0Cfg = val & 0x37ff;
else
val = usb->ep0Cfg;
break;
case 0x84 / 4 ... 0xbc / 4:
if (write)
usb->rxEpCfg[pa - 0x84 / 4] = val;
else
val = usb->rxEpCfg[pa - 0x84 / 4];
break;
case 0xc4 / 4 ... 0xfc / 4:
if (write)
usb->txEpCfg[pa - 0xc4 / 4] = val;
else
val = usb->txEpCfg[pa - 0xc4 / 4];
break;
default:
return false;
}
if (!write) {
if (size == 2)
*(uint16_t*)buf = val;
else
*(uint32_t*)buf = val;
}
return true;
}
struct OmapUsb* omapUsbInit(struct ArmMem *physMem, struct SocIc *ic, struct SocDma *dma)
{
struct OmapUsb *usb = (struct OmapUsb*)malloc(sizeof(*usb));
if (!usb)
ERR("cannot alloc USB");
memset(usb, 0, sizeof (*usb));
usb->mem = physMem;
usb->dma = dma;
usb->ic = ic;
if (!memRegionAdd(physMem, OMAP_USB_BASE, OMAP_USB_SIZE, omapUsbPrvMemAccessF, usb))
ERR("cannot add USB to MEM\n");
return usb;
}