680fecee7e399038ef146bfbf2512bb3af5441f4
[pinmux.git] / src / spec / ls180.py
1 #!/usr/bin/env python
2 # see https://bugs.libre-soc.org/show_bug.cgi?id=304
3
4 from spec.base import PinSpec
5 from parse import Parse
6 import json
7
8 from pprint import pprint
9 from spec.ifaceprint import display, display_fns, check_functions
10 from spec.ifaceprint import display_fixed
11 from collections import OrderedDict
12
13 def pinspec():
14 pinbanks = OrderedDict((
15 ('N', (32, 2)),
16 ('E', (32, 2)),
17 ('S', (32, 2)),
18 ('W', (32, 2)),
19 ))
20 fixedpins = {
21 'CTRL_SYS': [
22 'TEST',
23 'JTAG_SEL',
24 'UBOOT_SEL',
25 'NMI#',
26 'RESET#',
27 'CLK24M_IN',
28 'CLK24M_OUT',
29 'PLLTEST',
30 'PLLREGIO',
31 'PLLVP25',
32 'PLLDV',
33 'PLLVREG',
34 'PLLGND',
35 ],
36 'POWER_GPIO': [
37 'VDD_GPIOB',
38 'GND_GPIOB',
39 ]}
40 fixedpins = {}
41 function_names = {
42 'PWM': 'PWM (pulse-width modulation)',
43 'MSPI0': 'SPI Master 1 (general)',
44 'MSPI1': 'SPI Master 2 (SDCard)',
45 'UART0': 'UART (TX/RX) 1',
46 'SYS': 'System Control',
47 'GPIO': 'GPIO',
48 'EINT': 'External Interrupt',
49 'PWM': 'PWM',
50 'JTAG': 'JTAG',
51 'MTWI': 'I2C Master 1',
52 'SD0': 'SD/MMC 1',
53 'SDR': 'SDRAM',
54 'VDD': 'Power',
55 'VSS': 'GND',
56 #'LPC1': 'Low Pincount Interface 1',
57 #'LPC2': 'Low Pincount Interface 2',
58 }
59
60 ps = PinSpec(pinbanks, fixedpins, function_names)
61
62 ps.vdd("E", ('S', 0), 0, 0, 1)
63 ps.vss("E", ('S', 1), 0, 0, 1)
64 ps.vdd("I", ('S', 2), 0, 0, 1)
65 ps.vss("I", ('S', 3), 0, 0, 1)
66 ps.mi2c("", ('S', 4), 0, 0, 2)
67 ps.sdram1("", ('S', 6), 0, 0, 15) # SDRAM DAM0, D0-7, AD0-3
68 ps.vss("I", ('S', 22), 0, 1, 1)
69 ps.vdd("I", ('S', 23), 0, 1, 1)
70 ps.vss("E", ('S', 24), 0, 1, 1)
71 ps.vdd("E", ('S', 25), 0, 1, 1)
72 ps.sdram1("", ('S', 26), 0, 15, 6) # AD4-9
73
74 ps.sdram2("", ('W', 0), 0, 0, 4) # 1st 4, AD10-12,DQM1
75 ps.vdd("E", ('W', 4), 0, 2, 1)
76 ps.vss("E", ('W', 5), 0, 2, 1)
77 ps.vdd("I", ('W', 6), 0, 2, 1)
78 ps.vss("I", ('W', 7), 0, 2, 1)
79 ps.sdram2("", ('W', 8), 0, 4, 8) # D8-15
80 ps.sdram1("", ('W', 16), 0, 21, 9) # clk etc.
81 ps.vss("I", ('W', 22), 0, 3, 1)
82 ps.vdd("I", ('W', 23), 0, 3, 1)
83 ps.vss("E", ('W', 24), 0, 3, 1)
84 ps.vdd("E", ('W', 25), 0, 3, 1)
85 ps.uart("0", ('W', 26), 0)
86 ps.mspi("0", ('W', 28), 0)
87
88 ps.sys("", ('E', 0), 0, 5, 1) # analog VCO out in right top
89 ps.gpio("", ('E', 1), 0, 0, 5) # GPIO 0-4
90 ps.vss("E", ('E', 6), 0, 4, 1)
91 ps.vdd("E", ('E', 7), 0, 4, 1)
92 ps.vdd("I", ('E', 8), 0, 4, 1)
93 ps.vss("I", ('E', 9), 0, 4, 1)
94 ps.gpio("", ('E', 10), 0, 5, 3) # GPIO 5-7
95 ps.jtag("", ('E', 13), 0, 0, 4)
96 ps.gpio("", ('E', 17), 0, 8, 5) # GPIO 8-12
97 ps.vss("I", ('E', 22), 0, 5, 1)
98 ps.vdd("I", ('E', 23), 0, 5, 1)
99 ps.vss("E", ('E', 24), 0, 5, 1)
100 ps.vdd("E", ('E', 25), 0, 5, 1)
101 ps.gpio("", ('E', 26), 0, 13, 3) # GPIO 13-15
102 ps.eint("", ('E', 29), 0, 0, 3)
103
104 ps.vss("E", ('N', 6), 0, 6, 1)
105 ps.vdd("E", ('N', 7), 0, 6, 1)
106 ps.vdd("I", ('N', 8), 0, 6, 1)
107 ps.vss("I", ('N', 9), 0, 6, 1)
108 #ps.pwm("", ('N', 2), 0, 0, 2) comment out (litex problem 25mar2021)
109 #ps.mspi("1", ('N', 7), 0) comment out (litex problem 25mar2021)
110 #ps.sdmmc("0", ('N', 11), 0) # comment out (litex problem 25mar2021)
111 ps.sys("", ('N', 27), 0, 0, 5) # all but analog out in top right
112 ps.vss("I", ('N', 22), 0, 7, 1)
113 ps.vdd("I", ('N', 23), 0, 7, 1)
114 ps.vss("E", ('N', 24), 0, 7, 1)
115 ps.vdd("E", ('N', 25), 0, 7, 1)
116
117 #ps.mquadspi("1", ('S', 0), 0)
118
119 print "ps clocks", ps.clocks
120
121 # Scenarios below can be spec'd out as either "find first interface"
122 # by name/number e.g. SPI1, or as "find in bank/mux" which must be
123 # spec'd as "BM:Name" where B is bank (A-F), M is Mux (0-3)
124 # EINT and PWM are grouped together, specially, but may still be spec'd
125 # using "BM:Name". Pins are removed in-order as listed from
126 # lists (interfaces, EINTs, PWMs) from available pins.
127
128 ls180 = [
129 # 'SD0', litex problem 25mar2021
130 'UART0', 'GPIOS', 'GPIOE', 'JTAG', 'PWM', 'EINT',
131 'VDD', 'VSS', 'SYS',
132 'MTWI', 'MSPI0',
133 # 'MSPI1', litex problem 25mar2021
134 'SDR']
135 ls180_eint = []
136 ls180_pwm = []#['B0:PWM_0']
137 descriptions = {
138 'SD0': 'user-facing: internal (on Card), multiplexed with JTAG\n'
139 'and UART2, for debug purposes',
140 'MTWI': 'I2C.\n',
141 'E2:SD1': '',
142 'MSPI1': '',
143 'UART0': '',
144 'LPC1': '',
145 'SYS': '',
146 'LPC2': '',
147 'SDR': '',
148 'B1:LCD/22': '18-bit RGB/TTL LCD',
149 'ULPI0/8': 'user-facing: internal (on Card), USB-OTG ULPI PHY',
150 'ULPI1': 'dual USB2 Host ULPI PHY'
151 }
152
153 ps.add_scenario("Libre-SOC 180nm", ls180, ls180_eint, ls180_pwm,
154 descriptions)
155
156 return ps
157
158
159 # map pins to litex name conventions, primarily for use in coriolis2
160 # yes this is a mess. it'll do the job though. improvements later
161 def pinparse(psp, pinspec):
162 p = Parse(pinspec, verify=False)
163 pinmap = {}
164 litexmap = {}
165
166 print p.muxed_cells
167 print p.muxed_cells_bank
168
169 ps = [''] * 32
170 pn = [''] * 32
171 pe = [''] * 32
172 pw = [''] * 32
173 pads = {'N': pn, 'S': ps, 'E': pe, 'W': pw}
174
175 iopads = []
176 domains = {}
177 clocks = {}
178
179 n_intpower = 0
180 n_extpower = 0
181 for (padnum, name, x), bank in zip(p.muxed_cells, p.muxed_cells_bank):
182 orig_name = name
183 litex_name = None
184 domain = None # TODO, get this from the PinSpec. sigh
185 padnum = int(padnum)
186 start = p.bankstart[bank]
187 banknum = padnum - start
188 print "bank", bank, banknum, "padname", name, padnum, x
189 padbank = pads[bank]
190 pad = None
191 # VSS
192 if name.startswith('vss'):
193 name = 'p_%s_' % name[:-2] + name[-1]
194 if 'i' in name:
195 name = 'ground_' + name[-1]
196 name2 = 'vss'
197 else:
198 name = 'ioground_' + name[-1]
199 name2 = 'iovss'
200 pad = [name, name2]
201 # VDD
202 elif name.startswith('vdd'):
203 if 'i' in name:
204 n_intpower += 1
205 name = 'power_' + name[-1]
206 name2 = 'vdd'
207 else:
208 n_extpower += 1
209 name = 'iopower_' + name[-1]
210 name2 = 'iovdd'
211 pad = [name, name2]
212 # SYS
213 elif name.startswith('sys'):
214 domain = 'SYS'
215 if name == 'sys_pllclk':
216 pad = ["p_"+name, name, name]
217 elif name == 'sys_rst':
218 #name = 'p_sys_rst_1'
219 pad = [name, name, name]
220 padbank[banknum] = name
221 print "sys_rst add", bank, banknum, name
222 name = None
223 elif name == 'sys_pllclk':
224 name = None # ignore
225 elif name == 'sys_pllvcout':
226 name = 'sys_pll_vco_o'
227 pad = ['p_' + name, name, name, "A"] # A for Analog
228 elif name == 'sys_plltestout':
229 name = 'sys_pll_testout_o'
230 pad = ['p_' + name, name, name]
231 elif name.startswith('sys_pllsel'):
232 i = name[-1]
233 name2 = 'sys_clksel_i(%s)' % i
234 name = 'p_sys_clksel_' + i
235 pad = [name, name2, name2]
236 #if name:
237 # iopads.append([pname, name, name])
238 print "sys pad", name
239 # SPI Card
240 elif name.startswith('mspi0') or name.startswith('mspi1'):
241 domain = 'MSPI'
242 suffix = name[6:]
243 if suffix == 'ck':
244 suffix = 'clk'
245 elif suffix == 'nss':
246 suffix = 'cs_n'
247 if name.startswith('mspi0'):
248 prefix = 'spimaster_'
249 else:
250 prefix = 'spisdcard_'
251 litex_name = name[:6] + suffix
252 name = prefix + suffix
253 pad = ['p_' + name, name, name]
254 # SD/MMC
255 elif name.startswith('sd0'):
256 domain = 'SD'
257 if name.startswith('sd0_d'):
258 i = name[5:]
259 name = 'sdcard_data' + i
260 name2 = 'sdcard_data_%%s(%s)' % i
261 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
262 elif name.startswith('sd0_cmd'):
263 name = 'sdcard_cmd'
264 name2 = 'sdcard_cmd_%s'
265 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
266 else:
267 name = 'sdcard_' + name[4:]
268 pad = ['p_' + name, name, name]
269 litex_name = orig_name[:4] + "_".join(name.split("_")[1:])
270 # SDRAM
271 elif name.startswith('sdr'):
272 domain = 'SDR'
273 if name == 'sdr_clk':
274 name = 'sdram_clock'
275 pad = ['p_' + name, name, name]
276 elif name.startswith('sdr_ad'):
277 i = name[6:]
278 name = 'sdram_a_' + i
279 name2 = 'sdram_a(%s)' % i
280 pad = ['p_' + name, name2, name2]
281 elif name.startswith('sdr_ba'):
282 i = name[-1]
283 name = 'sdram_ba_' + i
284 name2 = 'sdram_ba(%s)' % i
285 pad = ['p_' + name, name2, name2]
286 elif name.startswith('sdr_dqm'):
287 i = name[-1]
288 name = 'sdram_dm_' + i
289 name2 = 'sdram_dm(%s)' % i
290 pad = ['p_' + name, name2, name2]
291 elif name.startswith('sdr_d'):
292 i = name[5:]
293 name = 'sdram_dq_' + i
294 name2 = 'sdram_dq_%%s(%s)' % i
295 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
296 elif name == 'sdr_csn0':
297 name = 'sdram_cs_n'
298 pad = ['p_' + name, name, name]
299 elif name[-1] == 'n':
300 name = 'sdram_' + name[4:-1] + '_n'
301 pad = ['p_' + name, name, name]
302 else:
303 name = 'sdram_' + name[4:]
304 pad = ['p_' + name, name, name]
305 litex_name = orig_name[:4] + "_".join(name.split("_")[1:])
306 # UART
307 elif name.startswith('uart'):
308 domain = 'UART'
309 name = 'uart_' + name[6:]
310 pad = ['p_' + name, name, name]
311 # GPIO
312 elif name.startswith('gpio'):
313 gbank = name[4]
314 domain = 'GPIO'
315 i = name[7:]
316 name = 'gpio_' + i
317 name2 = 'gpio_%%s(%s)' % i
318 pad = ['p_' + name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
319 print ("GPIO pad", name, pad)
320 litex_name = "gpio_%s" % gbank + "_".join(name.split("_")[1:])
321 # I2C master-only
322 elif name.startswith('mtwi'):
323 domain = 'MTWI'
324 suffix = name[4:]
325 litex_name = 'mtwi' + suffix
326 name = 'i2c' + suffix
327 if name.startswith('i2c_sda'):
328 name2 = 'i2c_sda_%s'
329 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
330 print ("I2C pad", name, pad)
331 else:
332 pad = ['p_' + name, name, name]
333 # I2C bi-directional
334 elif name.startswith('twi'):
335 domain = 'TWI'
336 name = 'i2c' + name[3:]
337 name2 = name + '_%s'
338 pad = ['p_'+name, name, name2 % 'o', name2 % 'i', name2 % 'oe']
339 print ("I2C pad", name, pad)
340 # EINT
341 elif name.startswith('eint'):
342 domain = 'EINT'
343 i = name[-1]
344 name = 'eint_%s' % i
345 name2 = 'eint_%s' % i
346 pad = ['p_' + name, name2, name2]
347 # PWM
348 elif name.startswith('pwm'):
349 domain = 'PWM'
350 name = name[:-4]
351 i = name[3:]
352 name2 = 'pwm(%s)' % i
353 pad = ['p_' + name, name2, name2]
354 else:
355 pad = ['p_' + name, name, name]
356 print ("GPIO pad", name, pad)
357
358 if litex_name is None:
359 litex_name = name
360
361 # JTAG domain
362 if name and name.startswith('jtag'):
363 domain = 'JTAG'
364
365 if name and not name.startswith('p_'):
366 if 'power' not in name and 'ground' not in name:
367 name = 'p_' + name
368 if name is not None:
369 padbank[banknum] = name
370 # create domains
371 if domain is not None:
372 if domain not in domains:
373 domains[domain] = []
374 domains[domain].append(name)
375 dl = domain.lower()
376 if domain in psp.clocks and orig_name.startswith(dl):
377 clk = psp.clocks[domain]
378 if clk.lower() in orig_name: # TODO, might over-match
379 clocks[domain] = name
380 # record remap
381 pinmap[orig_name] = name
382 litexmap[litex_name] = name
383
384 # add pad to iopads
385 if domain and pad is not None:
386 # append direction from spec/domain. damn awkward processing
387 # to find it.
388 fn, name = orig_name.split("_")
389 if domain == 'PWM':
390 name = fn[3:]
391 print psp.byspec
392 spec = None
393 for k in psp.byspec.keys():
394 if k.startswith(domain):
395 spec = psp.byspec[k]
396 print "spec found", domain, spec
397 assert spec is not None
398 found = None
399 for pname in spec:
400 if pname.lower().startswith(name):
401 found = pname
402 print "found spec", found
403 assert found is not None
404 # whewwww. add the direction onto the pad spec list
405 dirn = found[-1]
406 if pad[-1] == 'A':
407 pad[-1] += dirn
408 else:
409 pad.append(dirn)
410 iopads.append(pad)
411 elif pad is not None:
412 iopads.append(pad)
413
414 # not connected
415 nc_idx = 0
416 for pl in [pe, pw, pn, ps]:
417 for i in range(len(pl)):
418 if pl[i] == '':
419 name = 'nc_%d' % nc_idx
420 name2 = 'nc(%d)' % nc_idx
421 pl[i] = name
422 pinmap[name] = name
423 iopads.append([name, name2, name2, "-"])
424 nc_idx += 1
425
426 print p.bankstart
427 pprint(psp.clocks)
428
429 print
430 print "N pads", pn
431 print "S pads", ps
432 print "E pads", pe
433 print "W pads", pw
434
435 # do not want these
436 del clocks['SYS']
437 del domains['SYS']
438
439 print "chip domains (excluding sys-default)"
440 pprint(domains)
441 print "chip clocks (excluding sys-default)"
442 pprint(clocks)
443 print "pin spec"
444 pprint(psp.byspec)
445
446 chip = {
447 'pads.south' : ps,
448 'pads.east' : pe,
449 'pads.north' : pn,
450 'pads.west' : pw,
451 'pads.instances' : iopads,
452 'pins.specs' : psp.byspec,
453 'pins.map' : pinmap,
454 'litex.map' : litexmap,
455 'chip.domains' : domains,
456 'chip.clocks' : clocks,
457 'chip.n_intpower': n_intpower,
458 'chip.n_extpower': n_extpower,
459 }
460
461 return pinmap, chip