(no commit message)
[libreriscv.git] / shakti / m_class / pinouts.py
1 #!/usr/bin/env python
2
3 from copy import deepcopy
4
5 def pins(pingroup, bankspec, suffix, offs, bank, mux, spec=None, limit=None):
6 res = {}
7 names = {}
8 idx = 0
9 for name in pingroup[:limit]:
10 if suffix:
11 name_ = "%s_%s" % (name, suffix)
12 else:
13 name_ = name
14 if spec and spec.has_key(name):
15 continue
16 pin = {mux: (name_, bank)}
17 offs_bank, offs_ = offs
18 idx_ = offs_ + idx
19 idx += 1
20 idx_ += bankspec[bank]
21 res[idx_] = pin
22 names[name] = idx_
23 for name in pingroup:
24 if suffix:
25 name_ = "%s_%s" % (name, suffix)
26 else:
27 name_ = name
28 if not spec:
29 continue
30 if not spec.has_key(name):
31 continue
32 idx_, mux_, bank_ = spec[name]
33 idx_ = names[idx_]
34 #idx_ += bankspec[bank_]
35 pin = {mux_: (name_, bank_)}
36 if res.has_key(idx_):
37 res[idx_].update(pin)
38 else:
39 res[idx_] = pin
40 return res
41
42 def i2s(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
43 i2spins = ['IISMCK', 'IISBCK', 'IISLRCK', 'IISDI']
44 for i in range(4):
45 i2spins.append("IISDO%d" % i)
46 return pins(i2spins, bankspec, suffix, offs, bank, mux, spec, limit)
47
48 def emmc(bankspec, suffix, offs, bank, mux=1, spec=None):
49 emmcpins = ['MMCCMD', 'MMCCLK']
50 for i in range(8):
51 emmcpins.append("MMCD%d" % i)
52 return pins(emmcpins, bankspec, suffix, offs, bank, mux, spec)
53
54 def sdmmc(bankspec, suffix, offs, bank, mux=1, spec=None,
55 start=None, limit=None):
56 sdmmcpins = ['CMD', 'CLK']
57 for i in range(4):
58 sdmmcpins.append("D%d" % i)
59 sdmmcpins = sdmmcpins[start:limit]
60 sdmmcpins = namesuffix('SD', suffix, sdmmcpins)
61 return pins(sdmmcpins, bankspec, '', offs, bank, mux, spec)
62
63 def spi(bankspec, suffix, offs, bank, mux=1, spec=None):
64 spipins = namesuffix('SPI', suffix,
65 ['CLK', 'NSS', 'MOSI', 'MISO', 'NSS'])
66 return pins(spipins, bankspec, '', offs, bank, mux, spec)
67
68 def quadspi(bankspec, suffix, offs, bank, mux=1, spec=None, limit=None):
69 spipins = namesuffix('SPI', suffix,
70 ['CK', 'NSS', 'IO0', 'IO1', 'IO2', 'IO3'])
71 return pins(spipins, bankspec, '', offs, bank, mux, spec, limit)
72
73 def i2c(bankspec, suffix, offs, bank, mux=1, spec=None):
74 spipins = namesuffix('TWI', suffix,
75 ['SDA', 'SCL'])
76 return pins(spipins, bankspec, '', offs, bank, mux, spec)
77
78 def jtag(bankspec, suffix, offs, bank, mux=1, spec=None):
79 uartpins = namesuffix('JTAG', suffix, ['MS', 'DI', 'DO', 'CK'])
80 return pins(uartpins, bankspec, '', offs, bank, mux, spec)
81
82 def uart(bankspec, suffix, offs, bank, mux=1, spec=None):
83 uartpins = namesuffix('UART', suffix, ['TX', 'RX'])
84 return pins(uartpins, bankspec, '', offs, bank, mux, spec)
85
86 def namesuffix(name, suffix, namelist):
87 names = []
88 for n in namelist:
89 names.append("%s%s_%s" % (name, suffix, n))
90 return names
91
92 def ulpi(bankspec, suffix, offs, bank, mux=1, spec=None):
93 ulpipins = namesuffix('ULPI', suffix, ['CK', 'DIR', 'STP', 'NXT'])
94 for i in range(8):
95 ulpipins.append('ULPI%s_D%d' % (suffix, i))
96 return pins(ulpipins, bankspec, "", offs, bank, mux, spec)
97
98 def uartfull(bankspec, suffix, offs, bank, mux=1, spec=None):
99 uartpins = namesuffix('UART', suffix, ['TX', 'RX', 'CTS', 'RTS'])
100 return pins(uartpins, bankspec, '', offs, bank, mux, spec)
101
102 def rgbttl(bankspec, suffix, offs, bank, mux=1, spec=None):
103 ttlpins = ['LCDCK', 'LCDDE', 'LCDHS', 'LCDVS']
104 for i in range(24):
105 ttlpins.append("LCD%d" % i)
106 return pins(ttlpins, bankspec, suffix, offs, bank, mux, spec)
107
108 def rgmii(bankspec, suffix, offs, bank, mux=1, spec=None):
109 buspins = []
110 for i in range(4):
111 buspins.append("RG_ERXD%d" % i)
112 for i in range(4):
113 buspins.append("RG_ETXD%d" % i)
114 for i in range(2):
115 buspins.append("RG_FB_CS%d" % i)
116 buspins += ['RG_ERXCK', 'RG_ERXERR', 'RG_ERXDV',
117 'RG_EMDC', 'RG_EMDIO',
118 'RG_ETXEN', 'RG_ETXCK', 'RG_ECRS',
119 'RG_ECOL', 'RG_ETXERR']
120 return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
121
122 def flexbus1(bankspec, suffix, offs, bank, mux=1, spec=None):
123 buspins = []
124 for i in range(8):
125 buspins.append("FB_AD%d" % i)
126 for i in range(2):
127 buspins.append("FB_CS%d" % i)
128 buspins += ['FB_ALE', 'FB_OE', 'FB_RW', 'FB_TA', 'FB_CLK',
129 'FB_A0', 'FB_A1', 'FB_TS', 'FB_TBST',
130 'FB_TSIZ0', 'FB_TSIZ1']
131 for i in range(4):
132 buspins.append("FB_BWE%d" % i)
133 for i in range(2,6):
134 buspins.append("FB_CS%d" % i)
135 return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
136
137 def flexbus2(bankspec, suffix, offs, bank, mux=1, spec=None):
138 buspins = []
139 for i in range(8,32):
140 buspins.append("FB_AD%d" % i)
141 return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
142
143 def mcu8080(bankspec, suffix, offs, bank, mux=1, spec=None):
144 buspins = []
145 for i in range(8):
146 buspins.append("MCUD%d" % i)
147 for i in range(8):
148 buspins.append("MCUAD%d" % (i+8))
149 for i in range(6):
150 buspins.append("MCUCS%d" % i)
151 for i in range(2):
152 buspins.append("MCUNRB%d" % i)
153 buspins += ['MCUCD', 'MCURD', 'MCUWR', 'MCUCLE', 'MCUALE',
154 'MCURST']
155 return pins(buspins, bankspec, suffix, offs, bank, mux, spec)
156
157 def _pinbank(bankspec, prefix, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
158 gpiopins = []
159 for i in range(gpiooffs, gpiooffs+gpionum):
160 gpiopins.append("%s%s%d" % (prefix, bank, i))
161 return pins(gpiopins, bankspec, suffix, offs, bank, mux, spec)
162
163 def eint(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
164 gpiopins = []
165 for i in range(gpiooffs, gpiooffs+gpionum):
166 gpiopins.append("EINT%d" % (i))
167 return pins(gpiopins, bankspec, suffix, offs, bank, mux, spec)
168
169 def pwm(bankspec, suffix, offs, bank, mux=1, spec=None):
170 return pins(['PWM', ], bankspec, suffix, offs, bank, mux, spec)
171
172 def gpio(bankspec, suffix, offs, bank, gpiooffs, gpionum=1, mux=1, spec=None):
173 return _pinbank(bankspec, "GPIO", suffix, offs, bank, gpiooffs,
174 gpionum, mux=0, spec=None)
175
176 def display(pins):
177 print "| Pin | Mux0 | Mux1 | Mux2 | Mux3 |"
178 print "| --- | ----------- | ----------- | ----------- | ----------- |"
179 pinidx = pins.keys()
180 pinidx.sort()
181 for pin in pinidx:
182 pdata = pins[pin]
183 res = '| %3d |' % pin
184 for mux in range(4):
185 if not pdata.has_key(mux):
186 res += " |"
187 continue
188 name, bank = pdata[mux]
189 res += " %s %-9s |" % (bank, name)
190 print res
191
192 def fnsplit(f):
193 a = ''
194 n = 0
195 if not f.startswith('FB_'):
196 f2 = f.split('_')
197 if len(f2) == 2:
198 if f2[1].isdigit():
199 return f2[0], int(f2[1])
200 return f2[0], f2[1]
201 #print f
202 while f and not f[0].isdigit():
203 a += f[0]
204 f = f[1:]
205 return a, int(f) if f else None
206
207 def fnsort(f1, f2):
208 a1, n1 = fnsplit(f1)
209 a2, n2 = fnsplit(f2)
210 x = cmp(a1, a2)
211 if x != 0:
212 return x
213 return cmp(n1, n2)
214
215 def find_fn(fname, names):
216 for n in names:
217 if fname.startswith(n):
218 return n
219
220 def display_fns(bankspec, pins, function_names):
221 fn_names = function_names.keys()
222 fns = {}
223 for (pin, pdata) in pins.items():
224 for mux in range(1,4): # skip GPIO for now
225 if not pdata.has_key(mux):
226 continue
227 name, bank = pdata[mux]
228 if not fns.has_key(name):
229 fns[name] = []
230 fns[name].append((pin-bankspec[bank], mux, bank))
231
232 fnidx = fns.keys()
233 fnidx.sort(fnsort)
234 current_fn = None
235 for fname in fnidx:
236 fnbase = find_fn(fname, fn_names)
237 if fnbase != current_fn:
238 if current_fn is not None:
239 print
240 print "## %s" % fnbase
241 print
242 print function_names[fnbase]
243 print
244 current_fn = fnbase
245 print "* %-9s :" % fname,
246 for (pin, mux, bank) in fns[fname]:
247 print "%s%d/%d" % (bank, pin, mux),
248 print
249
250 return fns
251
252 def check_functions(title, bankspec, fns, pins, required, eint, pwm,
253 descriptions=None):
254 fns = deepcopy(fns)
255 pins = deepcopy(pins)
256 if descriptions is None:
257 descriptions = {}
258
259 print "# Pinmap for %s" % title
260 print
261
262
263 for name in required:
264 print "## %s" % name
265 print
266 if descriptions and descriptions.has_key(name):
267 print descriptions[name]
268 print
269
270 name = name.split(':')
271 if len(name) == 2:
272 findbank = name[0][0]
273 findmux = int(name[0][1:])
274 name = name[1]
275 else:
276 name = name[0]
277 findbank = None
278 findmux = None
279 name = name.split('/')
280 if len(name) == 2:
281 count = int(name[1])
282 else:
283 count = 100000
284 name = name[0]
285 found = set()
286 fnidx = fns.keys()
287 #fnidx.sort(fnsort)
288 pinfound = {}
289 for fname in fnidx:
290 if not fname.startswith(name):
291 continue
292 for pin, mux, bank in fns[fname]:
293 if findbank is not None:
294 if findbank != bank:
295 continue
296 if findmux != mux:
297 continue
298 pin_ = pin + bankspec[bank]
299 if pins.has_key(pin_):
300 pinfound[pin_] = (fname, pin_, bank, pin, mux)
301
302 pinidx = pinfound.keys()
303 pinidx.sort()
304
305 for pin_ in pinidx:
306 fname, pin_, bank, pin, mux = pinfound[pin_]
307 if fname in found:
308 continue
309 found.add(fname)
310 if len(found) > count:
311 continue
312 del pins[pin_]
313 print "* %s %d %s%d/%d" % (fname, pin_, bank, pin, mux)
314
315 print
316
317 # gpios
318 gpios = []
319 for name in descriptions.keys():
320 if not name.startswith('GPIO'):
321 continue
322 if name == 'GPIO':
323 continue
324 gpios.append(name)
325 gpios.sort()
326
327 if gpios:
328 print "## GPIO"
329 print
330
331 for fname in gpios:
332 if fname in found:
333 continue
334 desc = ''
335 if descriptions and descriptions.has_key(fname):
336 desc = ': %s' % descriptions[fname]
337 bank = fname[4]
338 pin = int(fname[5:])
339 pin_ = pin + bankspec[bank]
340 if not pins.has_key(pin_):
341 continue
342 del pins[pin_]
343 found.add(fname)
344 print "* %-8s %d %s%-2d %s" % (fname, pin_, bank, pin, desc)
345 print
346
347 if eint:
348 display_group("EINT", eint, fns, pins, descriptions)
349 if pwm:
350 display_group("PWM", pwm, fns, pins, descriptions)
351
352 print "## Unused Pinouts (spare as GPIO) for '%s'" % title
353 print
354 if descriptions and descriptions.has_key('GPIO'):
355 print descriptions['GPIO']
356 print
357 display(pins)
358 print
359
360 return pins # unused
361
362 def display_group(title, todisplay, fns, pins, descriptions):
363 print "## %s" % title
364 print
365
366 found = set()
367 for fname in todisplay:
368 desc = ''
369 if descriptions and descriptions.has_key(fname):
370 desc = ': %s' % descriptions[fname]
371 fname = fname.split(':')
372 if len(fname) == 2:
373 findbank = fname[0][0]
374 findmux = int(fname[0][1:])
375 fname = fname[1]
376 else:
377 fname = fname[0]
378 findbank = None
379 findmux = None
380 for (pin, mux, bank) in fns[fname]:
381 if findbank is not None:
382 if findbank != bank:
383 continue
384 if findmux != mux:
385 continue
386 if fname in found:
387 continue
388 pin_ = pin + bankspec[bank]
389 if not pins.has_key(pin_):
390 continue
391 del pins[pin_]
392 found.add(fname)
393 print "* %s %d %s%d/%d %s" % (fname, pin_, bank, pin, mux, desc)
394 print
395
396 def pinmerge(pins, fn):
397 for (pinidx, v) in fn.items():
398 if not pins.has_key(pinidx):
399 pins[pinidx] = v
400 continue
401 pins[pinidx].update(v)
402
403 def display_fixed(fixed, offs):
404
405 fkeys = fixed.keys()
406 fkeys.sort()
407 pin_ = offs
408 for pin, k in enumerate(fkeys):
409 print "## %s" % k
410 print
411 prevname = ''
412 linecount = 0
413 for name in fixed[k]:
414 if linecount == 4:
415 linecount = 0
416 print
417 if prevname[:2] == name[:2] and linecount != 0:
418 print name,
419 linecount += 1
420 else:
421 if linecount != 0:
422 print
423 print "* %d: %d %s" % (pin_, pin, name),
424 linecount = 1
425 prevname = name
426 pin_ += 1
427 if linecount != 0:
428 print
429 print
430
431 if __name__ == '__main__':
432 pinouts = {}
433
434 pinbanks = {'A': 16,
435 'B': 28,
436 'C': 24,
437 'D': 24,
438 'E': 24,
439 'F': 10,
440 'G': 32,
441 }
442 bankspec = {}
443 pkeys = pinbanks.keys()
444 pkeys.sort()
445 offs = 0
446 for kn in pkeys:
447 bankspec[kn] = offs
448 offs += pinbanks[kn]
449
450 # Bank A, 0-15
451 pinmerge(pinouts, gpio(bankspec, "", ('A', 0), "A", 0, 16, 0))
452 pinmerge(pinouts, spi(bankspec, "1", ('A', 0), "A", 3))
453 pinmerge(pinouts, uartfull(bankspec, "1", ('A', 0), "A", 2))
454 pinmerge(pinouts, i2c(bankspec, "1", ('A', 4), "A", 2))
455 pinmerge(pinouts, emmc(bankspec, "", ('A', 0), "A", 1))
456 #pinmerge(pinouts, uart(bankspec, "2", ('A', 14), "A", 1))
457 pinmerge(pinouts, spi(bankspec, "2", ('A', 6), "A", 2))
458 pinmerge(pinouts, eint(bankspec, "", ('A', 10), "A", 0, 6))
459 pinmerge(pinouts, eint(bankspec, "", ('A', 4), "A", 0, 6, mux=3))
460 pinmerge(pinouts, sdmmc(bankspec, "1", ('A', 10), "A", 2))
461 pinmerge(pinouts, jtag(bankspec, "1", ('A', 10), "A", 3))
462 pinmerge(pinouts, uart(bankspec, "2", ('A', 14), "A", 3))
463
464 # Bank B, 16-47
465 pinmerge(pinouts, gpio(bankspec, "", ('B', 0), "B", 0, 28, 0))
466 pinmerge(pinouts, rgbttl(bankspec, "0", ('B', 0), "B", 1))
467 pinmerge(pinouts, spi(bankspec, "1", ('B', 12), "B", 2))
468 pinmerge(pinouts, quadspi(bankspec, "3", ('B', 4), "B", 2, limit=4))
469 pinmerge(pinouts, uart(bankspec, "3", ('B', 16), "B", 2))
470 pinmerge(pinouts, i2c(bankspec, "3", ('B', 18), "B", 2))
471 pinmerge(pinouts, pwm(bankspec, "0", ('B', 9), "B", mux=2))
472 pinmerge(pinouts, pwm(bankspec, "1", ('B', 20), "B", mux=2))
473 pinmerge(pinouts, pwm(bankspec, "2", ('B', 21), "B", mux=2))
474 pinmerge(pinouts, sdmmc(bankspec, "1", ('B', 22), "B", 2))
475 pinmerge(pinouts, eint(bankspec, "", ('B', 0), "B", 6, 4, mux=3))
476 pinmerge(pinouts, flexbus2(bankspec, "", ('B', 4), "B", 3))
477 pinmerge(pinouts, i2c(bankspec, "1", ('B', 0), "B", 2))
478 pinmerge(pinouts, uart(bankspec, "2", ('B', 2), "B", 2))
479 pinmerge(pinouts, uart(bankspec, "4", ('B', 10), "B", 2))
480
481 # Bank C, 48-71
482 pinmerge(pinouts, gpio(bankspec, "", ("C", 0), "C", 0, 24, 0))
483 pinmerge(pinouts, ulpi(bankspec, "1", ('C', 0), "C", 1))
484 pinmerge(pinouts, ulpi(bankspec, "2", ('C', 12), "C", 1))
485 pinmerge(pinouts, spi(bankspec, "2", ('C', 8), "C", 2))
486 #pinmerge(pinouts, spi(bankspec, "2", ('C', 28), "C", 2))
487 pinmerge(pinouts, uartfull(bankspec, "0", ('C', 20), "C", 3))
488 pinmerge(pinouts, eint(bankspec, "", ('C', 0), "C", 10, 8, mux=3))
489 pinmerge(pinouts, jtag(bankspec, "2", ('C', 8), "C", 3))
490 pinmerge(pinouts, eint(bankspec, "", ('C', 12), "C", 22, 8, mux=3))
491 pinmerge(pinouts, uart(bankspec, "2", ('C', 22), "C", 2))
492 pinmerge(pinouts, i2s(bankspec, "", ('C', 13), "C", 2))
493 pinmerge(pinouts, pwm(bankspec, "2", ('C', 21), "C", mux=2))
494
495 # Bank D, 72-96
496 flexspec = {
497 'FB_TS': ('FB_ALE', 2, "D"),
498 'FB_CS2': ('FB_BWE2', 2, "D"),
499 'FB_A0': ('FB_BWE2', 3, "D"),
500 'FB_CS3': ('FB_BWE3', 2, "D"),
501 'FB_A1': ('FB_BWE3', 3, "D"),
502 'FB_TBST': ('FB_OE', 2, "D"),
503 'FB_TSIZ0': ('FB_BWE0', 2, "D"),
504 'FB_TSIZ1': ('FB_BWE1', 2, "D"),
505 }
506 #pinmerge(pinouts, mcu8080("", 72, "D", 1))
507 pinmerge(pinouts, gpio(bankspec, "", ('D', 0), "D", 0, 24, 0))
508 pinmerge(pinouts, flexbus1(bankspec, "", ('D', 0), "D", 1, spec=flexspec))
509 pinmerge(pinouts, i2c(bankspec, "2", ('D', 17), "D", 2))
510 pinmerge(pinouts, pwm(bankspec, "0", ('D', 21), "D", mux=1))
511 pinmerge(pinouts, pwm(bankspec, "1", ('D', 22), "D", mux=1))
512 pinmerge(pinouts, pwm(bankspec, "2", ('D', 23), "D", mux=1))
513 pinmerge(pinouts, i2c(bankspec, "1", ('D', 10), "D", 3))
514 pinmerge(pinouts, i2c(bankspec, "3", ('D', 19), "D", 2))
515 pinmerge(pinouts, uartfull(bankspec, "0", ('D', 0), "D", 2))
516 pinmerge(pinouts, uart(bankspec, "3", ('D', 21), "D", 2))
517 pinmerge(pinouts, uart(bankspec, "4", ('D', 13), "D", 2))
518 pinmerge(pinouts, eint(bankspec, "", ('D', 19), "D", 18, 4, mux=3))
519 pinmerge(pinouts, eint(bankspec, "", ('D', 23), "D", 9, 1, mux=3))
520 pinmerge(pinouts, eint(bankspec, "", ('D', 13), "D", 5, 4, mux=3))
521 pinmerge(pinouts, eint(bankspec, "", ('D', 0), "D", 30, 2, mux=3))
522 pinmerge(pinouts, i2c(bankspec, "2", ('D', 2), "D", 3))
523 pinmerge(pinouts, sdmmc(bankspec, "2", ('D', 4), "D", 2))
524
525 # Bank E
526 pinmerge(pinouts, gpio(bankspec, "", ('E', 0), "E", 0, 24, 0))
527 pinmerge(pinouts, flexbus2(bankspec, "", ('E', 0), "E", 1))
528 pinmerge(pinouts, sdmmc(bankspec, "2", ('E', 0), "E", 2))
529 pinmerge(pinouts, sdmmc(bankspec, "3", ('E', 8), "E", 2))
530 pinmerge(pinouts, quadspi(bankspec, "3", ('E', 18), "E", 2))
531 pinmerge(pinouts, uartfull(bankspec, "1", ('E', 14), "E", 2))
532 pinmerge(pinouts, i2c(bankspec, "2", ('E', 6), "E", 2))
533 pinmerge(pinouts, eint(bankspec, "", ('E', 0), "E", 10, 8, mux=3))
534 pinmerge(pinouts, eint(bankspec, "", ('E', 8), "E", 22, 6, mux=3))
535 pinmerge(pinouts, emmc(bankspec, "", ('E', 14), "E", 3))
536
537 # Bank F
538 pinmerge(pinouts, gpio(bankspec, "", ('F', 0), "F", 0, 10, 0))
539 pinmerge(pinouts, i2s(bankspec, "", ('F', 0), "F", 1))
540 pinmerge(pinouts, i2c(bankspec, "1", ('F', 6), "F", 2))
541 pinmerge(pinouts, pwm(bankspec, "0", ('F', 8), "F", mux=2))
542 pinmerge(pinouts, pwm(bankspec, "1", ('F', 9), "F", mux=2))
543 pinmerge(pinouts, uart(bankspec, "4", ('F', 8), "F", 1))
544 pinmerge(pinouts, sdmmc(bankspec, "3", ('F', 0), "F", 2))
545 pinmerge(pinouts, eint(bankspec, "", ('F', 0), "F", 18, 4, mux=3))
546 pinmerge(pinouts, pwm(bankspec, "2", ('F', 4), "F", mux=3))
547 pinmerge(pinouts, eint(bankspec, "", ('F', 5), "F", 7, 1, mux=3))
548 pinmerge(pinouts, eint(bankspec, "", ('F', 6), "F", 28, 4, mux=3))
549
550 # Bank G
551 pinmerge(pinouts, gpio(bankspec, "", ('G', 0), "G", 0, 32, 0))
552 pinmerge(pinouts, rgmii(bankspec, "", ('G', 0), "G", 1))
553 pinmerge(pinouts, ulpi(bankspec, "3", ('G', 20), "G", 1))
554 pinmerge(pinouts, rgbttl(bankspec, "1", ('G', 0), "G", 2))
555 pinmerge(pinouts, quadspi(bankspec, "3", ('G', 26), "G", 3))
556 pinmerge(pinouts, flexbus2(bankspec, "", ('G', 0), "G", 3))
557 mmc2 = sdmmc(bankspec, "2", ('G', 24), "G", 3, limit=2)
558 pinmerge(pinouts, mmc2)
559 mmc2 = sdmmc(bankspec, "2", ('G', 28), "G", 2, start=2)
560 pinmerge(pinouts, mmc2)
561
562 print "# Pinouts (PinMux)"
563 print
564 print "auto-generated by [[pinouts.py]]"
565 print
566 print "[[!toc ]]"
567 print
568 display(pinouts)
569 print
570
571 print "# Pinouts (Fixed function)"
572 print
573
574 fixedpins = {
575 'DDR3':
576 ['SDQ0', 'SDQ1', 'SDQ2', 'SDQ3', 'SDQ4', 'SDQ5', 'SDQ6', 'SDQ7',
577 'SDQ8', 'SDQ9', 'SDQ10', 'SDQ11', 'SDQ12', 'SDQ13', 'SDQ14', 'SDQ15',
578 'SDQ16', 'SDQ17', 'SDQ18', 'SDQ19', 'SDQ20', 'SDQ21', 'SDQ22', 'SDQ23',
579 'SDQ24', 'SDQ25', 'SDQ26', 'SDQ27', 'SDQ28', 'SDQ29', 'SDQ30', 'SDQ31',
580 'SVREF0', 'SVREF1', 'SVREF2', 'SVREF3',
581 'SDQS0', 'SDQS0#', 'SDQS1', 'SDQS1#',
582 'SDQS2', 'SDQS2#', 'SDQS3', 'SDQS3#',
583 'SDQM0', 'SDQM1', 'SDQM2', 'SDQM3',
584 'SCK#', 'SCK', 'SCKE0', 'SCKE1',
585 'SA0', 'SA1', 'SA2', 'SA3', 'SA4', 'SA5', 'SA6', 'SA7',
586 'SA8', 'SA9', 'SA10', 'SA11', 'SA12', 'SA13', 'SA14',
587 'SBA0', 'SBA1', 'SBA2',
588 'SWE', 'SCAS', 'SRAS',
589 'SCS0', 'SCS1',
590 'SZQ', 'SRST',
591 'SDBG0', 'SDBG1', 'ADBG',
592 'ODT0', 'ODT1'
593 ],
594
595 'CTRL_SYS':
596 [
597 'TEST', 'JTAG_SEL', 'UBOOT_SEL',
598 'NMI#', 'RESET#',
599 'CLK24M_IN', 'CLK24M_OUT',
600 'PLLTEST', 'PLLREGIO', 'PLLVP25',
601 'PLLDV', 'PLLVREG', 'PLLGND',
602 ],
603
604 'POWER_DRAM':
605 ['VCC0_DRAM', 'VCC1_DRAM', 'VCC2_DRAM', 'VCC3_DRAM', 'VCC4_DRAM',
606 'VCC5_DRAM', 'VCC6_DRAM', 'VCC7_DRAM', 'VCC8_DRAM', 'VCC9_DRAM',
607 'GND0_DRAM', 'GND1_DRAM', 'GND2_DRAM', 'GND3_DRAM', 'GND4_DRAM',
608 'GND5_DRAM', 'GND6_DRAM', 'GND7_DRAM', 'GND8_DRAM', 'GND9_DRAM',
609 ],
610
611 'POWER_CPU':
612 ['VDD0_CPU', 'VDD1_CPU', 'VDD2_CPU', 'VDD3_CPU', 'VDD4_CPU', 'VDD5_CPU',
613 'GND0_CPU', 'GND1_CPU', 'GND2_CPU', 'GND3_CPU', 'GND4_CPU', 'GND5_CPU',
614 ],
615
616 'POWER_DLL':
617 ['VDD0_DLL', 'VDD1_DLL', 'VDD2_DLL',
618 'GND0_DLL', 'GND1_DLL', 'GND2_DLL',
619 ],
620
621 'POWER_INT':
622 ['VDD0_INT', 'VDD1_INT', 'VDD2_INT', 'VDD3_INT', 'VDD4_INT',
623 'VDD5_INT', 'VDD6_INT', 'VDD7_INT', 'VDD8_INT', 'VDD9_INT',
624 'GND0_INT', 'GND1_INT', 'GND2_INT', 'GND3_INT', 'GND4_INT',
625 'GND5_INT', 'GND6_INT', 'GND7_INT', 'GND8_INT', 'GND9_INT',
626 ],
627
628 'POWER_GPIO':
629 ['VDD_GPIOA', 'VDD_GPIOB', 'VDD_GPIOC',
630 'VDD_GPIOD', 'VDD_GPIOE', 'VDD_GPIOF',
631 'VDD_GPIOG',
632 'GND_GPIOA', 'GND_GPIOB', 'GND_GPIOC',
633 'GND_GPIOD', 'GND_GPIOE', 'GND_GPIOF',
634 'GND_GPIOG',
635 ]
636
637 }
638
639 display_fixed(fixedpins, len(pinouts))
640
641 print "# Functions (PinMux)"
642 print
643 print "auto-generated by [[pinouts.py]]"
644 print
645
646 function_names = {'EINT': 'External Interrupt',
647 'FB': 'MC68k FlexBus',
648 'IIS': 'I2S Audio',
649 'JTAG1': 'JTAG (same as JTAG2, JTAG_SEL=LOW)',
650 'JTAG2': 'JTAG (same as JTAG1, JTAG_SEL=HIGH)',
651 'LCD': '24-pin RGB/TTL LCD',
652 'RG': 'RGMII Ethernet',
653 'MMC': 'eMMC 1/2/4/8 pin',
654 'PWM': 'PWM (pulse-width modulation)',
655 'SD1': 'SD/MMC 1',
656 'SD2': 'SD/MMC 2',
657 'SD3': 'SD/MMC 3',
658 'SPI1': 'SPI (Serial Peripheral Interface) 1',
659 'SPI2': 'SPI (Serial Peripheral Interface) 2',
660 'SPI3': 'Quad SPI (Serial Peripheral Interface) 3',
661 'TWI1': 'I2C 1',
662 'TWI2': 'I2C 2',
663 'TWI3': 'I2C 3',
664 'UART0': 'UART (TX/RX/CTS/RTS) 0',
665 'UART1': 'UART (TX/RX/CTS/RTS) 1',
666 'UART2': 'UART (TX/RX) 2',
667 'UART3': 'UART (TX/RX) 3',
668 'UART4': 'UART (TX/RX) 4',
669 'ULPI1': 'ULPI (USB Low Pin-count) 1',
670 'ULPI2': 'ULPI (USB Low Pin-count) 2',
671 'ULPI3': 'ULPI (USB Low Pin-count) 3',
672 }
673
674 fns = display_fns(bankspec, pinouts, function_names)
675 print
676
677 # Scenarios below can be spec'd out as either "find first interface"
678 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
679 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
680 # EINT and PWM are grouped together, specially, but may still be spec'd
681 # using "BM:Name". Pins are removed in-order as listed from
682 # lists (interfaces, EINTs, PWMs) from available pins.
683
684 # EOMA68 scenario. not totally complete (some GPIO needed for PMIC)
685 # One interface to be connected to the MCU to give RTC and boot/dbg
686 # VBUS_EN, OTG_ID etc. are all not included below, there is plenty
687 # of spare GPIO.
688
689 eoma68 = ['B1:LCD/22', 'ULPI1/8', 'ULPI2', 'MMC', 'SD1', 'UART3',
690 'TWI3', 'SPI2', 'E2:SD2',]
691 eoma68_eint = ['EINT16', 'EINT17', 'EINT18', 'EINT19']
692 eoma68_pwm = ['D1:PWM_2']
693 descriptions = {
694 'MMC': 'internal (on Card)',
695 'SD1': 'user-facing: internal (on Card), multiplexed with JTAG1\n'
696 'and UART2, for debug purposes',
697 'TWI3': 'EOMA68-compliance: must be entirely free of devices.\n'
698 'Address 0x51 used (externally) for EOMA68 EEPROM Id',
699 'E2:SD2': 'EOMA68-compliance',
700 'SPI2': 'EOMA68-compliance',
701 'UART3': 'EOMA68-compliance',
702 'B1:LCD/22': 'EOMA68-compliance, 18-bit RGB/TTL LCD',
703 'ULPI1/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
704 'ULPI2': 'EOMA68-compliance: dual USB2 Host ULPI PHY'
705 }
706
707 unused_pins = check_functions("EOMA68", bankspec, fns, pinouts,
708 eoma68, eoma68_eint, eoma68_pwm,
709 descriptions)
710
711 # Industrial scenario. not totally complete (some GPIO needed for PMIC)
712 # One interface to be connected to the MCU to give RTC, boot/dbg,
713 # option of CAN Bus, ADC, DAC, OWB, more GPIO, more PWM etc. etc.
714 # Focus is on getting as many UARTs, SPIs and TWIs as possible.
715 # OTG_ID (if to be used) would require dropping some functions in order
716 # to free up GPIO. LCD could be reduced to 15-bit (freeing 3).
717 # MMC could be reduced to 4-bit-wide, used as SD/MMC (freeing 4).
718 # SPI3 could be used in 1-bit (MOSI/MISO) mode (freeing up 2 more).
719
720 industrial = ['D1:FB/17', 'E1:FB/8', 'B1:LCD/22', 'ULPI1/8', 'ULPI2/8',
721 'MMC', 'B2:SD1',
722 'JTAG1', 'A3:UART2', 'E2:UART1', 'C3:UART0',
723 'F2:TWI1', 'D2:TWI2', 'D2:TWI3', 'SPI2', 'SPI3', 'F2:SD3']
724 industrial_pwm = ['F2:PWM_0', 'F2:PWM_1', 'D1:PWM_2']
725 industrial_eint = ['EINT24', 'EINT25', 'EINT26', 'EINT27',
726 'EINT20', 'EINT21', 'EINT22', 'EINT23']
727
728 unused_pins = check_functions("Industrial", bankspec, fns, pinouts,
729 industrial, industrial_eint, industrial_pwm)
730
731 # Industrial scenario, using an SPI-based LCD instead of RGB/TTL
732 # not totally complete (some GPIO needed for PMIC)
733 # One interface to be connected to the MCU to give RTC, boot/dbg,
734 # option of CAN Bus, ADC, DAC, OWB, more GPIO, more PWM etc. etc.
735 # Focus is on getting as many UARTs, SPIs and TWIs as possible,
736 # leaving some GPIO spare from the RGB/TTL bank (SPI CS#)
737 # also possibility of freeing up FlexBus CS# with a little reorg.
738
739 industrial = ['D1:FB/17', 'E1:FB/8', 'B2:SPI1', 'ULPI1/8', 'ULPI2/8',
740 'MMC', 'B2:SD1',
741 'JTAG1',
742 'A3:UART2', 'E2:UART1', 'C3:UART0', 'B2:UART4', 'B2:UART3',
743 'F2:TWI1', 'D2:TWI2', 'D2:TWI3', 'SPI2', 'SPI3', 'F2:SD3']
744 industrial_pwm = ['F2:PWM_0', 'F2:PWM_1', 'D1:PWM_2']
745 industrial_eint = ['EINT24', 'EINT25', 'EINT26', 'EINT27',
746 'EINT20', 'EINT21', 'EINT22', 'EINT23']
747 ind_descriptions = {
748 'B2:SPI1': 'Used for 320x240 or 640x480 etc. SPI-based LCD.\n'
749 'Frees up large numbers of GPIO from RGB/TTL bank'
750 }
751 unused_pins = check_functions("Industrial with SPI-LCD",
752 bankspec, fns, pinouts,
753 industrial, industrial_eint, industrial_pwm,
754 ind_descriptions)
755
756 # Smartphone / Tablet - basically the same thing
757
758 tablet = ['B1:LCD/22', 'ULPI1/8', 'ULPI2/8',
759 'MMC', 'SD1',
760 'F1:IIS', # I2C Audio
761 'TWI2', # I2C Audio
762 'E2:UART1', # WIFI/BT
763 'E2:SD2', # WIFI
764 'C3:UART0', # GPS
765 'D2:UART3',
766 'D2:UART4',
767 'D3:TWI1', 'D2:TWI3', 'SPI2', 'SPI3']
768 tablet_pwm = ['F2:PWM_0', # LCD_BACKLIGHT
769 'F2:PWM_1', 'D1:PWM_2']
770 tablet_eint = ['EINT24', # BT_HOST_WAKE
771 'EINT25', # WIFI_HOST_WAKE
772 'EINT26', # CTP_INT
773 'EINT27', # GSENSOR_INT
774 'EINT8', # GPS_INT
775 'EINT7', # TILT_SENSOR_INT
776 'EINT22', # COMPASS_INT
777 'EINT23', # MCU_INT
778 'EINT16', # PMIC_INT
779 'EINT17', # PWR_BUTTON_INT
780 'EINT30', # OTG_ID
781 'EINT31',
782 ]
783 descriptions = {
784 'B1:LCD/22':
785 'RGB/TTL LCD, 800x480 or use SN75LVDS83b for up to 1440x900',
786 'MMC': 'eMMC: main internal storage',
787 'ULPI1/8': 'USB-OTG, connect to ULPI OTG PHY (for charging)\n'
788 'as well as USB Host or USB Device',
789 'ULPI2/8': 'USB2 Host, connect to ULPI PHY w/and 4-port USB2 Hub\n'
790 'for example GL850G or FE1.1. '
791 'Connects to 2/3/4G/LTE Modem, 2x USB-Camera (VC0345)',
792 'SD1': 'internal, multiplexed with JTAG1\n'
793 'and UART2, for debug purposes',
794 'F1:IIS': 'I2C Audio, connect to AC97 Audio IC',
795 'TWI2': 'Connect to AC97 Audio IC',
796 'E2:UART1': 'Connect to BT on AP6234/AP6335',
797 'E2:SD2': 'Connect to WIFI on AP6234/AP6335',
798 'SPI3': 'Boot Storage (connection to companion / debug / boot MCU)\n'
799 'Only actually needs MISO/MOSI, bootstrap loader v. small\n'
800 'Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.',
801 'SPI2': 'Spare? SPI, connect to higher-speed sensor?',
802 'D2:UART3': 'Spare? UART (or 2 extra GPIO / EINT)',
803 'D2:UART4': 'Spare? UART (or 2 extra GPIO)',
804 'D3:TWI1': 'Connect to PMIC',
805 'D2:TWI3': 'Connect to sensors (Trackpad? CTP GSENSOR TILT COMPASS)',
806 'GPIO': '9 spare GPIO pins for miscellaneous functions:\n'
807 'wake-up of BT, WIFI, LCD power, sensor power etc.\n'
808 '4 GPIO may be needed for PWM Audio from Modem.\n'
809 'LED lights for camera will be needed.\n'
810 'Some phones may have clam-shell or lid switch.\n'
811 'Some Modems have spare GPIO (over AT commandset).\n'
812 'AXP209 PMIC has 4x GPIO, accessible over I2C.\n'
813 'SPI2, UART3-4, PWM1-2 may also be spare (10 extra GPIO).\n'
814 'If more needed, companion MCU may be used (48+ pin variant)\n'
815 'which also includes ADC, DAC, more PWM etc.',
816 'F2:PWM_0': 'LCD Backlight',
817 'F2:PWM_1': 'Spare? PWM (or extra GPIO / EINT)',
818 'D1:PWM_2': 'Spare? PWM (or extra GPIO / EINT)',
819 'EINT24': 'BT_HOST_WAKE',
820 'EINT25': 'WIFI_HOST_WAKE',
821 'EINT26': 'CTP_INT',
822 'EINT27': 'GSENSOR_INT',
823 'EINT8': 'GPS_INT',
824 'EINT7': 'TILT_SENSOR_INT',
825 'EINT22': 'COMPASS_INT',
826 'EINT23': 'MCU_INT',
827 'EINT16': 'PMIC_INT',
828 'EINT17': 'PWR_BUTTON_INT',
829 'EINT30': 'OTG_ID',
830 'EINT31': 'Spare?',
831 }
832 unused_pins = check_functions("Smartphone / Tablet",
833 bankspec, fns, pinouts,
834 tablet, tablet_eint, tablet_pwm,
835 descriptions)
836
837 # Laptop
838
839 laptop = ['D1:FB/17', 'E1:FB/8', 'B1:LCD/22', 'ULPI1/8', 'ULPI2/8',
840 'MMC', 'SD1',
841 'F1:IIS', # I2C Audio
842 'TWI2', # I2C Audio
843 'E2:UART1', # WIFI/BT
844 'E2:SD3', # WIFI
845 'D2:TWI3', 'SPI3']
846 laptop_pwm = ['F2:PWM_0', # LCD_BACKLIGHT
847 ]
848 laptop_eint = ['EINT20', # BT_HOST_WAKE
849 'EINT21', # WIFI_HOST_WAKE
850 'EINT9', # MCU_INT
851 'EINT31', # PMIC_INT
852 ]
853 descriptions = {
854 'D1:FB/17': 'FlexBus. Connect to DM9000 or AX99896A MCU-style Bus\n'
855 '10/100 Ethernet PHY.',
856 'E1:FB/8': 'FlexBus bus bits 8-15, needed to make a 16-bit bus width',
857 'B1:LCD/22':
858 'RGB/TTL LCD, use SN75LVDS83b for LVDS or SSD2828 for MIPI,\n'
859 'or a Chrontel CH7039, CH7038, CH7034 or CH7018 for dual\n'
860 'display output (eDP/LVDS and HDMI/VGA) '
861 'conversion.',
862 'MMC': 'eMMC: main internal storage',
863 'ULPI1/8': 'USB-OTG, connect to ULPI OTG PHY (for charging)\n'
864 'as well as USB Host or USB Device',
865 'ULPI2/8': 'USB2 Host, connect to ULPI PHY w/and 4-port USB2 Hub\n'
866 'for example GL850G or FE1.1. '
867 'Connects to USB-Camera (VC0345 and 3x external USB Ports)',
868 'SD1': 'internal, multiplexed with JTAG1\n'
869 'and UART2, for debug purposes',
870 'F1:IIS': 'I2C Audio, connect to AC97 Audio IC',
871 'TWI2': 'Connect to AC97 Audio IC',
872 'E2:UART1': 'Connect to BT on AP6234/AP6335',
873 'E2:SD3': 'Connect to WIFI on AP6234/AP6335',
874 'SPI3': 'Boot Storage (connection to companion / debug / boot MCU)\n'
875 'Only actually needs MISO/MOSI, bootstrap loader v. small\n'
876 'Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.\n'
877 'MCU implements keyboard-matrix for keyboard (also trackpad?)',
878 'D2:TWI3': 'Connect to PMIC',
879 'GPIO': 'Plenty of spare GPIO pins for miscellaneous functions\n'
880 'MCU EINT-capable GPIO may be used to generate extra EINTs\n'
881 'on the single MCU_INT line, if really needed',
882 'F2:PWM_0': 'LCD Backlight',
883 'EINT20': 'BT_HOST_WAKE',
884 'EINT21': 'WIFI_HOST_WAKE',
885 'EINT9': 'MCU_INT',
886 'EINT31': 'PMIC_INT',
887 }
888 unused_pins = check_functions("Laptop / Netbook",
889 bankspec, fns, pinouts,
890 laptop, laptop_eint, laptop_pwm,
891 descriptions)
892
893 # IoT
894
895 iot = ['B1:LCD', 'ULPI2/8', 'ULPI1/8',
896 'MMC', 'SD1',
897 'F1:IIS', # I2C Audio
898 #'TWI2', # I2C Audio
899 'C3:UART0', # HSPA UART
900 'E2:UART1', # BT UART
901 'C2:SPI2', # HSPI SPI
902 'E2:SD3', # WIFI
903 'D3:TWI1', # sensors CTP,
904 'D2:TWI3', 'SPI3']
905 iot_pwm = ['F2:PWM_0', # LCD_BACKLIGHT
906 ]
907 iot_eint = [ 'EINT5', # 'HSPA_MST_RDY',
908 'EINT6', # 'HSPA_SL_RDY',
909 'EINT7', # 'HSPA_RING',
910 'EINT8', # 'WL_PMU_EN',
911 'EINT9', # HSPA_GPIO1
912 'EINT10', # IR_DT
913 'EINT11', # 'BT_PCM_CLK',
914 'EINT12', # 'BT_PCM_DIN',
915 'EINT13', # 'BT_PCM_SYNC',
916 'EINT14', # 'BT_PCM_DOUT',
917 'EINT16', # 'USB_DRVVBUS',
918 'EINT17', # 'USB_VBUSDET',
919 'EINT21', # 'USB_ID',
920 'EINT30', # 'CTP_INT',
921 'EINT31', # 'SD_DET#',
922 ]
923 descriptions = {
924 'B1:LCD':
925 'RGB/TTL LCD, use SN75LVDS83b for LVDS or SSD2828 for MIPI,\n'
926 'or a Chrontel CH7039, CH7038, CH7034 or CH7018 for dual\n'
927 'display output (eDP/LVDS and HDMI/VGA) '
928 'conversion.',
929 'MMC': 'eMMC: main internal storage',
930 'F1:IIS': 'I2C Audio, connect to AC97 Audio IC',
931 'ULPI2/8': 'USB-OTG, connect to ULPI OTG PHY (for charging)\n'
932 'as well as USB Host or USB Device',
933 'ULPI1/8': 'USB2 Host, connect to ULPI PHY',
934 'SD1': 'internal, multiplexed with JTAG1\n'
935 'and UART2, for debug purposes',
936 'C3:UART0': 'Connect to HSPA UART',
937 'E2:UART1': 'Connect to BT UART',
938 'E2:SD3': 'Connect to WIFI',
939 'C2:SPI2': 'HSPA SPI',
940 'SPI3': 'Boot Storage (connection to companion / debug / boot MCU)\n'
941 'Only actually needs MISO/MOSI, bootstrap loader v. small\n'
942 'Bootstrap loader checks eMMC, USB-OTG, SD/MMC, SPI, etc.\n'
943 'MCU implements keyboard-matrix for keyboard (also trackpad?)',
944 'D2:TWI3': 'Connect to PMIC',
945 'D3:TWI1': 'Connect to sensors CTP',
946 'GPIO': 'Plenty of spare GPIO pins for miscellaneous functions\n'
947 'MCU EINT-capable GPIO may be used to generate extra EINTs\n'
948 'on the single MCU_INT line, if really needed',
949 'F2:PWM_0': 'LCD Backlight',
950 'GPIOD4': 'WL_WAKE_AP',
951 'GPIOD5': 'BT_WAKE_AP',
952 'GPIOD6': 'AP_WAKE_BT',
953 'GPIOD7': 'AP_CK32KO',
954 'GPIOD8': 'HSPA_PWRON',
955 'GPIOD9': 'BT_RST_N',
956 'GPIOE5': 'HSPA_ON_OFF',
957 'GPIOD2': 'HSPA_SHUTDOWN',
958 'GPIOD3': 'CTP_RST',
959 'GPIOD12': 'LCD_RDN',
960 'GPIOD17': 'LCD_WRN',
961 'GPIOD18': 'LCD_RS',
962 'GPIOD21': 'LCD_CSN',
963
964 'EINT5': 'HSPA_MST_RDY',
965 'EINT6': 'HSPA_SL_RDY',
966 'EINT7': 'HSPA_RING',
967 'EINT8': 'WL_PMU_EN',
968 'EINT9': 'HSPA_GPIO1',
969 'EINT10': 'IR_DT',
970 'EINT11': 'BT_PCM_CLK',
971 'EINT12': 'BT_PCM_DIN',
972 'EINT13': 'BT_PCM_SYNC',
973 'EINT14': 'BT_PCM_DOUT',
974
975 'EINT16': 'USB_DRVVBUS',
976 'EINT17': 'USB_VBUSDET',
977 'EINT21': 'USB_ID',
978 'EINT30': 'CTP_INT',
979 'EINT31': 'SD_DETN',
980 }
981 unused_pins = check_functions("IoT",
982 bankspec, fns, pinouts,
983 iot, iot_eint, iot_pwm,
984 descriptions)
985
986 print "# Reference Datasheets"
987 print
988 print "datasheets and pinout links"
989 print
990 print "* <http://datasheets.chipdb.org/AMD/8018x/80186/amd-80186.pdf>"
991 print "* <http://hands.com/~lkcl/eoma/shenzen/frida/FRD144A2701.pdf>"
992 print "* <http://pinouts.ru/Memory/sdcard_pinout.shtml>"
993 print "* p8 <http://www.onfi.org/~/media/onfi/specs/onfi_2_0_gold.pdf?la=en>"
994 print "* <https://www.heyrick.co.uk/blog/files/datasheets/dm9000aep.pdf>"
995 print "* <http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4393.pdf>"
996 print "* <https://www.nxp.com/docs/en/data-sheet/MCF54418.pdf>"
997 print "* ULPI OTG PHY, ST <http://www.st.com/en/interfaces-and-transceivers/stulpi01a.html>"
998 print "* ULPI OTG PHY, TI TUSB1210 <http://ti.com/product/TUSB1210/>"
999