1/*
2 * Copyright (c) 2012, ETH Zurich. All rights reserved.
3 *
4 * This file is distributed under the terms in the attached LICENSE file.
5 * If you do not find this file, copies can be found by writing to:
6 * ETH Zurich D-INFK, Universitaestr. 6, CH-8092 Zurich. Attn: Systems Group.
7 */
8
9/*
10 * ohci.dev
11 *
12 * DESCRIPTION: Open Host Controller Interface (OHCI) description
13 * 
14 * Archaic USB interface, but still found on e.g. ATI and NVidia
15 * chipsets. 
16 * 
17 * Numbers in comments refer to the OpenHCI Open Host Controller
18 * Interface Specification for USB, by Compaq, Microsoft, and National
19 * Semiconductor, 09/14/99 2:33 PM, Release: 1.0a 
20 */
21
22
23device ohci lsbfirst ( io base ) "OHCI USB controller" {
24
25/*
26    //
27    // Data structures
28    //
29
30    // 4.2.1
31    constants direction width(2) "Data flow direction" {
32	dir_td	= 0b00	"Get direction from TD";
33	dir_out = 0b01	"Out";
34	dir_in  = 0b10  "In";
35	dir_td1 = 0b11  "Get direction from TD (alt)";
36    };
37
38    datatype epdesc lsbfirst(32) "Endpoint descriptor" {
39	fa	7	"Function address";
40	en	4	"Endpoint number";
41	d	2 type(direction) "Direction";
42	s	1	"Speed (1=low, 0=full)";
43	k	1	"Skip";
44	f	1	"Format (1=isochronous, 0=general)";
45	mps	11	"Maximum packet size";
46	_	5;
47	_	4;
48	tailp	28	"TD queue tail pointer";
49	h	1	"Halted";
50	c	1	"Toggle carry";
51	_	2 mbz;
52	headp	28	"TD queue head pointer";
53	_	4;
54	nexted	28	"Next endpoint descriptor";
55    };
56
57    // 4.3.1 
58    constants pid width(2) "Direction / PID for token" {
59	pid_setup	= 0b00	"Setup (to endpoint)";
60	pid_out		= 0b01	"To endpoint";
61	pid_in		= 0b10  "From endpoint";
62    };	
63    datatype gentd lsbfirst(32) "General transfer descriptor" { 
64	_	18;
65	r	1 	"Buffer rounding";
66	dp	2 type(pid) "Direction or PID";
67	di	3	"Delay interrupt frames";
68	t	2	"Data toggle";
69	ec	2	"Error count";
70	cc	4 type(ccode) "Condition code for last attempted transaction";
71	cbp	32	"Current buffer pointer";
72	_	4 mbz;
73	nexttd	28	"Next transfer descriptor";
74	be	32	"Buffer end";
75    };
76
77
78    // 4.3.2
79    datatype isotd lsbfirst(32) "Isochronous transfer descriptor" {
80	sf	16	"Starting frame";
81	_	5;
82	di	3	"Delay interrupt frames";
83	fc	3	"Frame count";
84	_	1;
85	cc	4 type(ccode) "Condition code for last attempted transaction";
86	_	12;
87	bp0	20	"Buffer page 0";
88	_	5 mbz;
89	nexttd	27	"Next transfer descriptor";
90	be	32	"Buffer end";
91	ofpsw0	16	"Offset / packet status word 0";
92	ofpsw1	16	"Offset / packet status word 1";
93	ofpsw2	16	"Offset / packet status word 2";
94	ofpsw3	16	"Offset / packet status word 4";
95	ofpsw4	16	"Offset / packet status word 3";
96	ofpsw5	16	"Offset / packet status word 5";
97	ofpsw6	16	"Offset / packet status word 6";
98	ofpsw7	16	"Offset / packet status word 7";
99    };
100    datatype psw lsbfirst(16) "Packet status word" {
101	size	11	"Size of packet";
102	_	1 mbz;
103	cc	4 type(ccode) "Condition code";
104    };
105
106    /// 4.3.3
107    constants ccode width(4) "Completion codes" {
108	cc_ne	= 0b0000	"No error";
109	cc_crc	= 0b0001	"CRC error";
110	cc_bs	= 0b0010	"Bitstuffing violation";
111	cc_dtm	= 0b0011	"Data toggle PID mismatch";
112	cc_stl	= 0b0100	"EP returned stall PID";
113	cc_dnr	= 0b0101	"Device not responding";
114	cc_pcf	= 0b0110	"PID check failure";
115	cc_uxp	= 0b0111	"Unexpected PID";
116	cc_dor	= 0b1000	"Data overrun";
117	cc_dur	= 0b1001	"Data underrun";
118	cc_bor	= 0b1100	"Buffer overrun";
119	cc_bur	= 0b1101	"Buffer underrun";
120	cc_nac	= 0b1110	"Not accessed";
121	cc_nac_	= 0b1111	"Not accessed (alternate)";
122    };
123*/
124    //
125    // Registers
126    //
127    // 7.1 Control and status partition
128    //
129
130    // 7.1.1 Interface revision 
131    /// Initially 0x10.
132    register revision ro io(base, 0x00) "Revision" {
133	rev	8	"BCD rep. of interface version";
134	_	24;
135    };
136
137    // 7.1.2 Control register
138    constants state "Functional state" {
139	st_reset       = 0b00	"Reset (after h/w reset)";
140	st_resume      = 0b01	"Resume from downstream port";
141	st_operational = 0b10  "Operational (running)";
142	st_suspend     = 0b11  "Suspend (after s/w reset)";
143    };
144    // Initially 0x00
145    register control rw io(base, 0x04) "Control" {
146	cbsr	2	"Control/bulk service ratio";
147	pe	1	"Periodic list enable";
148	ie	1	"Isochronous enable";
149	cle	1	"Control list enable";
150	ble	1	"Bulk list enable";
151	hcfs	2 type(state) "Host controller functional state";
152	ir	1	"Interrupt routing";
153	rwc	1	"Remote wakeup connected";
154	rwe	1	"Remote wakeup enabled";
155	_	21;
156    };
157
158
159    // 7.1.3 Command and Status 
160    // Initially 0x00
161    register cmdstatus rw io(base, 0x08) "08 CommandStatus" {
162	hcr	1	"Host controller reset";
163	clf	1	"Control list filled";
164	blf	1	"Bulk list filled";
165	ocr	1	"Ownership change request";
166	_	12;
167	soc	2 ro	"Scheduling overrun count";
168	_	14;
169    };
170
171    // 7.1.4-6: Interrupt registers
172    regtype interrupt "Interrupts" {
173	so	1	"Scheduling overrun";
174	wdh	1	"Writeback done head";
175	sf	1	"Start of frame";
176	rd	1	"Resume detected";
177	ue	1	"Unrecoverable error";
178	fno	1	"Frame number overflow";
179	rhsc	1	"Root hub status change";
180	_	23;
181	oc	1	"Ownership change";
182	mie	1	"Master interrupt enable";
183    };
184    register intstatus rw io(base, 0x0C) "Interrupt status"
185	type(interrupt);
186    register intenable rw io(base, 0x10) "Interrupt enable" 
187	type(interrupt);
188    register intdisable rw io(base, 0x14) "Interrupt disable" 
189	type(interrupt);
190
191    //
192    // 7.2 Memory pointer partition
193    //
194
195    // 7.2.1
196    register hcca rw io(base, 0x18) "Host controller communication area" {
197	_	8 mbz;
198	hcca	24	"Physical address";
199    };
200
201    regtype physptr "Physical address pointer" {
202	_	4 mbz;
203	addr	28	"Address";
204    };
205
206    // 7.2.2.
207    register period_cur ro io(base, 0x1C) "Cur. isochronous or int. ED"
208	type(physptr);
209
210    // 7.2.3
211    register ctrl_head rw io(base, 0x20) "First ED of control list"
212	type(physptr);
213
214
215    // 7.2.4
216    register ctrl_cur rw io(base, 0x24) "Current ED of control list" 
217	type(physptr);
218
219    // 7.2.5
220    register bulk_head rw io(base, 0x28) "First ED of bulk list" 
221	type(physptr);
222
223    // 7.2.6
224    register bulk_cur rw io(base, 0x2C) "Current ED of bulk list" 
225	type(physptr);
226
227
228    // 7.2.7
229    register done_head ro io(base, 0x30) "Done head pointer"
230	type(physptr);
231
232    //
233    // 7.3 Frame counter partition
234    //
235
236    // 7.3.1
237    register fm_interval rw io(base, 0x34) "Frame interval" {
238	fi	14	"Frame interval (dflt 0x2edf)";
239	_	2;
240	fsmps	15	"FS largest data packet";
241	fit	1	"Frame interval toggle";
242    };
243
244    // 7.3.2
245    register fm_remain ro io(base, 0x38) "Frame remaining" {
246	fr	14	"Bit time remaining in current frame";
247	_	17;
248	frt	1	"Frame remaining toggle";
249    };
250
251    // 7.3.3
252    register fm_num ro io(base, 0x3C) "Frame number" {
253	fn	16 	"Frame number (16-bit counter)";
254	_	16;
255    };
256
257    // 7.3.4
258    register period_start rw io(base, 0x40) "Period start" {
259	ps	14	"Start time for processing periodic list";
260	_	18;
261    };
262
263    // 7.3.5
264    register hclsthreshold rw io(base, 0x44) "LS threshold" {
265	lst	11	"Low-speed threshold (should be 0x0628)";
266	_	21;
267    };
268
269    //
270    // 7.4 Root Hub partition
271    //
272
273    // 7.4.1
274    register rh_descra rw io(base, 0x48) "Root hub descriptor a" {
275	ndp	8 ro	"Number of downstream ports";
276	psm	1	"Power switching mode";
277	nps	1	"No power switching";
278	dt	1 ro	"Device type";
279	ocpm	1	"Overcurrent protection mode";
280	nocp	1	"No overcurrent protection";
281	_	11;
282	potpgt	8	"Power-on to power-good time (* 2ms)";
283    };
284
285    // 7.4.2
286    register rh_descrb rw io(base, 0x4C) "Root hub descriptor b" {
287	dr	16	"Device removal";
288	ppcm	16	"Port power control mask";
289    };
290
291    // 7.4.3
292    register rh_status rw io(base, 0x50) "Root hub status" {
293	lps	1 wo	"Clear global power";
294	oci	1 ro	"Overcurrent indicator";
295	_	13;
296	drwe	1 rw1c	"Device remote wakeup enable";
297	lpsc	1 wo	"Set globl power";
298	ocic	1 rw1c	"Overcurrent indicator change";
299	_	13;
300	crwe	1 wo	"Clear remote wakeup enable";
301    };
302
303    // 7.4.4
304    // Assume 256 ports at this stage; it's actually given by
305    // rh_descra->ndp. 
306    regarray rh_portstat ro io(base, 0x54)[256] "Root hub port status" {
307	ccs	1 	"Current connection status";
308	pes	1 	"Port enable status";
309	pss	1	"Port suspend status";
310	poci	1 	"Port overcurrent indicator";
311	prs	1	"Port reset status";
312	_	3;
313	pps	1	"Port power status";
314	lsda	1	"Low-speed device attached";
315	_	6;
316	csc	1	"Connect status change";
317	pesc	1	"Port enable status change";
318	pssc	1	"Port suspend status change";
319	ocic	1	"Port overcurrent indicator change";
320	prsc	1	"Port reset status change";
321	_	11;
322    };
323    regarray rh_portctrl wo also io(base, 0x54)[256] "Root hub port control" {
324	cpe	1 	"Clear port enable";
325	spe	1 	"Set port enable";
326	sps	1	"Set port suspend";
327	css	1 	"Clear suspend status";
328	spr	1	"Set port reset";
329	_	3;
330	spp	1	"Set port power";
331	cpp	1	"Clear port power";
332	_	6;
333	csc	1	"Clear connect status change";
334	pesc	1	"Clear port enable status change";
335	pssc	1	"Clear port suspend status change";
336	ocic	1	"Clear port overcurrent indicator change";
337	prsc	1	"Clear port reset status change";
338	_	11;
339    };
340};
341