usb4604 0.2.0

Hardware abstraction layer for USB4604 hub (GPIO control and I2C master)
Documentation
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
use bitfield_struct::bitfield;
use super::SmscReg;

macro_rules! impl_smsc_reg {
    ($reg_name:ident, $reg_addr:literal) => {
        impl SmscReg for $reg_name {
            const ADDR: u16 = $reg_addr;

            fn from_value(bits: u8) -> Self {
                Self(bits)
            }

            fn value(&self) -> u8 {
                self.0
            }
        }
    };
}

impl_smsc_reg!(Gpio0_7PullDown, 0x082F);
impl_smsc_reg!(Gpio8_10PullDown, 0x082E);
impl_smsc_reg!(Gpio17_20PullDown, 0x082D);
impl_smsc_reg!(Gpio41_45PullDown, 0x092E);

impl_smsc_reg!(Gpio0_7Dir, 0x0833);
impl_smsc_reg!(Gpio8_10Dir, 0x0832);
impl_smsc_reg!(Gpio17_20Dir, 0x0831);
impl_smsc_reg!(Gpio41_45Dir, 0x0932);

impl_smsc_reg!(Gpio0_7Output, 0x0837);
impl_smsc_reg!(Gpio8_10Output, 0x0836);
impl_smsc_reg!(Gpio17_20Output, 0x0835);
impl_smsc_reg!(Gpio41_45Output, 0x0936);

impl_smsc_reg!(Gpio0_7Input, 0x083B);
impl_smsc_reg!(Gpio8_10Input, 0x083A);
impl_smsc_reg!(Gpio17_20Input, 0x0839);
impl_smsc_reg!(Gpio41_45Input, 0x093A);

impl_smsc_reg!(Gpio0_7PullUp, 0x083F);
impl_smsc_reg!(Gpio8_10PullUp, 0x083E);
impl_smsc_reg!(Gpio17_20PullUp, 0x083D);
impl_smsc_reg!(Gpio41_45PullUp, 0x093E);

#[bitfield(u8, order = Msb)]
pub struct Gpio0_7Dir {
    #[bits(1)]
    _gpio7_out_en: bool,
    #[bits(1)]
    _gpio6_out_en: bool,
    #[bits(1)]
    pub gpio5_out_en: bool,
    #[bits(1)]
    _gpio4_out_en: bool,
    #[bits(1)]
    pub gpio3_out_en: bool,

    /// Disable I2C interface before using
    #[bits(1)]
    pub gpio2_out_en: bool,
    #[bits(1)]
    pub gpio1_out_en: bool,
    #[bits(1)]
    pub gpio0_out_en: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio0_7Output {
    #[bits(1)]
    _gpio7_out: bool,
    #[bits(1)]
    _gpio6_out: bool,
    #[bits(1)]
    pub gpio5_out: bool,
    #[bits(1)]
    _gpio4_out: bool,
    #[bits(1)]
    pub gpio3_out: bool,
    #[bits(1)]
    pub gpio2_out: bool,
    #[bits(1)]
    pub gpio1_out: bool,
    #[bits(1)]
    pub gpio0_out: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio0_7Input {
    #[bits(1)]
    _gpio7_in: bool,
    #[bits(1)]
    _gpio6_in: bool,
    #[bits(1)]
    pub gpio5_in: bool,
    #[bits(1)]
    _gpio4_in: bool,
    #[bits(1)]
    pub gpio3_in: bool,
    #[bits(1)]
    pub gpio2_in: bool,
    #[bits(1)]
    pub gpio1_in: bool,
    #[bits(1)]
    pub gpio0_in: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio0_7PullUp {
    #[bits(1)]
    _gpio7_pu: bool,
    #[bits(1)]
    _gpio6_pu: bool,
    #[bits(1)]
    pub gpio5_pu: bool,
    #[bits(1)]
    _gpio4_pu: bool,
    #[bits(1)]
    pub gpio3_pu: bool,
    #[bits(1)]
    pub gpio2_pu: bool,
    #[bits(1)]
    pub gpio1_pu: bool,
    #[bits(1)]
    pub gpio0_pu: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio0_7PullDown {
    #[bits(1)]
    _gpio7_pd: bool,
    #[bits(1)]
    _gpio6_pd: bool,
    #[bits(1)]
    pub gpio5_pd: bool,
    #[bits(1)]
    _gpio4_pd: bool,
    #[bits(1)]
    pub gpio3_pd: bool,
    #[bits(1)]
    pub gpio2_pd: bool,
    #[bits(1)]
    pub gpio1_pd: bool,
    #[bits(1)]
    pub gpio0_pd: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio8_10Dir {
    #[bits(5)]
    _reserved: u8,
    #[bits(1)]
    pub gpio10_out_en: bool,
    #[bits(1)]
    pub gpio9_out_en: bool,
    #[bits(1)]
    pub gpio8_out_en: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio8_10Output {
    #[bits(5)]
    _reserved: u8,
    #[bits(1)]
    pub gpio10_out: bool,
    #[bits(1)]
    pub gpio9_out: bool,
    #[bits(1)]
    pub gpio8_out: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio8_10Input {
    #[bits(5)]
    _reserved: u8,
    #[bits(1)]
    pub gpio10_in: bool,
    #[bits(1)]
    pub gpio9_in: bool,
    #[bits(1)]
    pub gpio8_in: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio8_10PullUp {
    #[bits(5)]
    _reserved: u8,
    #[bits(1)]
    pub gpio10_pu: bool,
    #[bits(1)]
    pub gpio9_pu: bool,
    #[bits(1)]
    pub gpio8_pu: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio8_10PullDown {
    #[bits(5)]
    _reserved: u8,
    #[bits(1)]
    pub gpio10_pd: bool,
    #[bits(1)]
    pub gpio9_pd: bool,
    #[bits(1)]
    pub gpio8_pd: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio17_20Dir {
    #[bits(3)]
    _reserved: u8,

    /// Set hub into OCS Ganged Mode and Disable OCS Input
    /// or Disable Port 4 and Disable OCS Input
    #[bits(1)]
    pub gpio20_out_en: bool,

    /// Set hub into OCS Ganged Mode and Disable OCS Input
    /// or Disable Port 3 and Disable OCS Input
    #[bits(1)]
    pub gpio19_out_en: bool,

    /// Set hub into OCS Ganged Mode and Disable OCS Input
    /// or Disable Port 2 and Disable OCS Input
    #[bits(1)]
    pub gpio18_out_en: bool,

    /// Disable Port 1 and Disable OCS Input
    #[bits(1)]
    pub gpio17_out_en: bool,

    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio17_20Output {
    #[bits(3)]
    _reserved: u8,
    #[bits(1)]
    pub gpio20_out: bool,
    #[bits(1)]
    pub gpio19_out: bool,
    #[bits(1)]
    pub gpio18_out: bool,
    #[bits(1)]
    pub gpio17_out: bool,
    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio17_20Input {
    #[bits(3)]
    _reserved: u8,
    #[bits(1)]
    pub gpio20_in: bool,
    #[bits(1)]
    pub gpio19_in: bool,
    #[bits(1)]
    pub gpio18_in: bool,
    #[bits(1)]
    pub gpio17_in: bool,
    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio17_20PullUp {
    #[bits(3)]
    _reserved: u8,
    #[bits(1)]
    pub gpio20_pu: bool,
    #[bits(1)]
    pub gpio19_pu: bool,
    #[bits(1)]
    pub gpio18_pu: bool,
    #[bits(1)]
    pub gpio17_pu: bool,
    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio17_20PullDown {
    #[bits(3)]
    _reserved: u8,
    #[bits(1)]
    pub gpio20_pd: bool,
    #[bits(1)]
    pub gpio19_pd: bool,
    #[bits(1)]
    pub gpio18_pd: bool,
    #[bits(1)]
    pub gpio17_pd: bool,
    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio41_45Dir {
    #[bits(2)]
    _reserved: u8,

    /// Disable I2C interface
    #[bits(1)]
    pub gpio45_out_en: bool,

    /// Set hub into Port Power Ganged Mode and Disable Port Power Output
    /// or Disable Port 4 and Disable Port Power Output
    #[bits(1)]
    pub gpio44_out_en: bool,

    /// Set hub into Port Power Ganged Mode and Disable Port Power Output
    /// or Disable Port 3 and Disable Port Power Output
    #[bits(1)]
    pub gpio43_out_en: bool,

    /// Set hub into Port Power Ganged Mode and Disable Port Power Output
    /// or Disable Port 2 and Disable Port Power Output
    #[bits(1)]
    pub gpio42_out_en: bool,

    /// Disable Port 1 and Disable Port Power Output
    #[bits(1)]
    pub gpio41_out_en: bool,

    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio41_45Output {
    #[bits(2)]
    _reserved: u8,
    #[bits(1)]
    pub gpio45_out: bool,
    #[bits(1)]
    pub gpio44_out: bool,
    #[bits(1)]
    pub gpio43_out: bool,
    #[bits(1)]
    pub gpio42_out: bool,
    #[bits(1)]
    pub gpio41_out: bool,
    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio41_45Input {
    #[bits(2)]
    _reserved: u8,
    #[bits(1)]
    pub gpio45_in: bool,
    #[bits(1)]
    pub gpio44_in: bool,
    #[bits(1)]
    pub gpio43_in: bool,
    #[bits(1)]
    pub gpio42_in: bool,
    #[bits(1)]
    pub gpio41_in: bool,
    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio41_45PullUp {
    #[bits(2)]
    _reserved: u8,
    #[bits(1)]
    pub gpio45_pu: bool,
    #[bits(1)]
    pub gpio44_pu: bool,
    #[bits(1)]
    pub gpio43_pu: bool,
    #[bits(1)]
    pub gpio42_pu: bool,
    #[bits(1)]
    pub gpio41_pu: bool,
    #[bits(1)]
    _reserved: bool,
}

#[bitfield(u8, order = Msb)]
pub struct Gpio41_45PullDown {
    #[bits(2)]
    _reserved: u8,
    #[bits(1)]
    pub gpio45_pd: bool,
    #[bits(1)]
    pub gpio44_pd: bool,
    #[bits(1)]
    pub gpio43_pd: bool,
    #[bits(1)]
    pub gpio42_pd: bool,
    #[bits(1)]
    pub gpio41_pd: bool,
    #[bits(1)]
    _reserved: bool,
}

// Does not seem to work through USB, these (and many other) registers are probably only accessible from I2C interface
// #[bitfield(u8, order = Msb)]
// pub struct Port3PowerSelect {
//     #[bits(1)]
//     pub combined_power_select: bool,
//     #[bits(1)]
//     _reserved: bool,
//     #[bits(1)]
//     pub disabled: bool,
//     #[bits(1)]
//     pub permanent: bool,
//     #[bits(4)]
//     pub prt_sel: u8,
// }
// impl_smsc_reg!(Port3PowerSelect, 0x3C08);
//
// #[bitfield(u8, order = Msb)]
// pub struct HubConfigurationDB0 {
//     #[bits(1, access = RO)]
//     pub self_bus_pwr: bool,
//     #[bits(1, access = RO)]
//     pub vsm_disable: bool,
//     #[bits(1, access = RO)]
//     pub hs_disable: bool,
//     #[bits(1, access = RO)]
//     pub mtt_enable: bool,
//     #[bits(1, access = RO)]
//     pub eop_disable: bool,
//     #[bits(2, access = RO)]
//     pub current_sns: u8,
//     #[bits(1, access = RO)]
//     pub port_pwr: bool,
// }
// impl_smsc_reg!(HubConfigurationDB0, 0x3006);